From a851b91c4c1db76dd1e26a7d1a99124ad456b020 Mon Sep 17 00:00:00 2001 From: Marc Schink Date: Wed, 6 Feb 2019 12:07:10 +0100 Subject: [PATCH 01/70] target/riscv-011: Fix memory leak in handle_halt_routine() Tested with SiFive HiFive1 development board. Change-Id: Ie0d9fa0899804d17ccdd84b03ba4028e97b632b8 Signed-off-by: Marc Schink Reviewed-on: http://openocd.zylin.com/4884 Tested-by: jenkins Reviewed-by: Tim Newsome Reviewed-by: Tomas Vanek --- src/target/riscv/riscv-011.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/target/riscv/riscv-011.c b/src/target/riscv/riscv-011.c index 3820d8fc0..bd3f159fb 100644 --- a/src/target/riscv/riscv-011.c +++ b/src/target/riscv/riscv-011.c @@ -1806,6 +1806,8 @@ static riscv_error_t handle_halt_routine(struct target *target) } } + scans_delete(scans); + if (dbus_busy) { increase_dbus_busy_delay(target); return RE_AGAIN; @@ -1819,8 +1821,6 @@ static riscv_error_t handle_halt_routine(struct target *target) info->dpc = reg_cache_get(target, CSR_DPC); info->dcsr = reg_cache_get(target, CSR_DCSR); - scans_delete(scans); - cache_invalidate(target); return RE_OK; From dd9b7296bdbc236e0eeab35e00fc77f5ba9e565c Mon Sep 17 00:00:00 2001 From: Tomas Vanek Date: Sat, 9 Feb 2019 16:06:22 +0100 Subject: [PATCH 02/70] doc/openocd.texi: fix xref warning Xref without trailing '.' or ',' was introduced in deaf3d264123391d8fe5c4cccbf8fb8852e1be23 Change-Id: I99afd40e1ffeddd1298b7b07e4deba3dcc41799f Signed-off-by: Tomas Vanek Reviewed-on: http://openocd.zylin.com/4905 Tested-by: jenkins --- doc/openocd.texi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/openocd.texi b/doc/openocd.texi index 7f3a7ade1..3c1e33d6d 100644 --- a/doc/openocd.texi +++ b/doc/openocd.texi @@ -5453,7 +5453,7 @@ the flash. All members of the ATSAM D2x, D1x, D0x, ATSAMR, ATSAML and ATSAMC microcontroller families from Atmel include internal flash and use ARM's Cortex-M0+ core. -Do not use for ATSAM D51 and E5x: use @xref{atsame5} instead. +Do not use for ATSAM D51 and E5x: use @xref{atsame5}. The devices have one flash bank: From 1c22f5b7dee61e6eb85159970c43240703a1a616 Mon Sep 17 00:00:00 2001 From: Oleksij Rempel Date: Mon, 11 Feb 2019 07:14:06 +0100 Subject: [PATCH 03/70] doc: fix typo in "adapter usb location" command Change-Id: If959c5461904cdf4bcdf1887a9afaa9c2c94282b Signed-off-by: Oleksij Rempel Reviewed-on: http://openocd.zylin.com/4907 Tested-by: jenkins Reviewed-by: Matthias Welwarsky --- doc/openocd.texi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/openocd.texi b/doc/openocd.texi index 3c1e33d6d..f9a9297b0 100644 --- a/doc/openocd.texi +++ b/doc/openocd.texi @@ -2368,7 +2368,7 @@ the hardware can support. Returns the name of the debug adapter driver being used. @end deffn -@deffn Command {adapter usb location} :[.]... +@deffn Command {adapter usb location} -[.]... Specifies the physical USB port of the adapter to use. The path roots at @var{bus} and walks down the physical ports, with each @var{port} option specifying a deeper level in the bus topology, the last From fd8a3c9516d6580ab749e4127f6dab0077a8b078 Mon Sep 17 00:00:00 2001 From: Tomas Vanek Date: Thu, 24 Jan 2019 14:33:16 +0100 Subject: [PATCH 04/70] target, breakpoints: improve error handling handle_bp_command_set() showed the error message "Failure setting breakpoint, the same address(IVA) is already used" on any error returned from (xxx_)breakpoint_add(). Paradoxically breakpoint_add() returned ERROR_OK if it detected duplicated bp address. context_breakpoint_add() and hybrid_breakpoint_add() returned -1 instead of OpenOCD compatible error if they detected duplicity. Introduce ERROR_TARGET_DUPLICATE_BREAKPOINT Unify error handling to LOG_ERROR() any error in (xxx_)breakpoint_add() Remove misleading error messages from handle_bp_command_set() handle_bp_command_set() returns error if the target does not implement add_context_breakpoint or add_hybrid_breakpoint. Change-Id: If17dfad1756d82a77028ebdc4b305f9c8e1365ba Signed-off-by: Tomas Vanek Reviewed-on: http://openocd.zylin.com/4871 Tested-by: jenkins Reviewed-by: Matthias Welwarsky --- src/target/breakpoints.c | 16 ++++++++-------- src/target/target.c | 27 ++++++++++----------------- src/target/target.h | 1 + 3 files changed, 19 insertions(+), 25 deletions(-) diff --git a/src/target/breakpoints.c b/src/target/breakpoints.c index 58bcc8615..94e8a823d 100644 --- a/src/target/breakpoints.c +++ b/src/target/breakpoints.c @@ -60,9 +60,9 @@ int breakpoint_add_internal(struct target *target, * breakpoint" ... check all the parameters before * succeeding. */ - LOG_DEBUG("Duplicate Breakpoint address: " TARGET_ADDR_FMT " (BP %" PRIu32 ")", + LOG_ERROR("Duplicate Breakpoint address: " TARGET_ADDR_FMT " (BP %" PRIu32 ")", address, breakpoint->unique_id); - return ERROR_OK; + return ERROR_TARGET_DUPLICATE_BREAKPOINT; } breakpoint_p = &breakpoint->next; breakpoint = breakpoint->next; @@ -124,9 +124,9 @@ int context_breakpoint_add_internal(struct target *target, * breakpoint" ... check all the parameters before * succeeding. */ - LOG_DEBUG("Duplicate Breakpoint asid: 0x%08" PRIx32 " (BP %" PRIu32 ")", + LOG_ERROR("Duplicate Breakpoint asid: 0x%08" PRIx32 " (BP %" PRIu32 ")", asid, breakpoint->unique_id); - return -1; + return ERROR_TARGET_DUPLICATE_BREAKPOINT; } breakpoint_p = &breakpoint->next; breakpoint = breakpoint->next; @@ -176,13 +176,13 @@ int hybrid_breakpoint_add_internal(struct target *target, * breakpoint" ... check all the parameters before * succeeding. */ - LOG_DEBUG("Duplicate Hybrid Breakpoint asid: 0x%08" PRIx32 " (BP %" PRIu32 ")", + LOG_ERROR("Duplicate Hybrid Breakpoint asid: 0x%08" PRIx32 " (BP %" PRIu32 ")", asid, breakpoint->unique_id); - return -1; + return ERROR_TARGET_DUPLICATE_BREAKPOINT; } else if ((breakpoint->address == address) && (breakpoint->asid == 0)) { - LOG_DEBUG("Duplicate Breakpoint IVA: " TARGET_ADDR_FMT " (BP %" PRIu32 ")", + LOG_ERROR("Duplicate Breakpoint IVA: " TARGET_ADDR_FMT " (BP %" PRIu32 ")", address, breakpoint->unique_id); - return -1; + return ERROR_TARGET_DUPLICATE_BREAKPOINT; } breakpoint_p = &breakpoint->next; diff --git a/src/target/target.c b/src/target/target.c index 7e30d789b..693eb519e 100644 --- a/src/target/target.c +++ b/src/target/target.c @@ -3719,38 +3719,31 @@ static int handle_bp_command_set(struct command_context *cmd_ctx, if (asid == 0) { retval = breakpoint_add(target, addr, length, hw); + /* error is always logged in breakpoint_add(), do not print it again */ if (ERROR_OK == retval) command_print(cmd_ctx, "breakpoint set at " TARGET_ADDR_FMT "", addr); - else { - LOG_ERROR("Failure setting breakpoint, the same address(IVA) is already used"); - return retval; - } + } else if (addr == 0) { if (target->type->add_context_breakpoint == NULL) { - LOG_WARNING("Context breakpoint not available"); - return ERROR_OK; + LOG_ERROR("Context breakpoint not available"); + return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; } retval = context_breakpoint_add(target, asid, length, hw); + /* error is always logged in context_breakpoint_add(), do not print it again */ if (ERROR_OK == retval) command_print(cmd_ctx, "Context breakpoint set at 0x%8.8" PRIx32 "", asid); - else { - LOG_ERROR("Failure setting breakpoint, the same address(CONTEXTID) is already used"); - return retval; - } + } else { if (target->type->add_hybrid_breakpoint == NULL) { - LOG_WARNING("Hybrid breakpoint not available"); - return ERROR_OK; + LOG_ERROR("Hybrid breakpoint not available"); + return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; } retval = hybrid_breakpoint_add(target, addr, asid, length, hw); + /* error is always logged in hybrid_breakpoint_add(), do not print it again */ if (ERROR_OK == retval) command_print(cmd_ctx, "Hybrid breakpoint set at 0x%8.8" PRIx32 "", asid); - else { - LOG_ERROR("Failure setting breakpoint, the same address is already used"); - return retval; - } } - return ERROR_OK; + return retval; } COMMAND_HANDLER(handle_bp_command) diff --git a/src/target/target.h b/src/target/target.h index fb9d71465..983f450ac 100644 --- a/src/target/target.h +++ b/src/target/target.h @@ -725,6 +725,7 @@ void target_handle_event(struct target *t, enum target_event e); #define ERROR_TARGET_TRANSLATION_FAULT (-309) #define ERROR_TARGET_NOT_RUNNING (-310) #define ERROR_TARGET_NOT_EXAMINED (-311) +#define ERROR_TARGET_DUPLICATE_BREAKPOINT (-312) extern bool get_target_reset_nag(void); From b04c7c2ca587feebd6506716cd84297212350608 Mon Sep 17 00:00:00 2001 From: Oleksij Rempel Date: Fri, 16 Nov 2018 08:58:58 +0100 Subject: [PATCH 05/70] ftdi: use "adapter usb location" instead of ftdi_location command Use unified "adapter usb location" instead of driver specific command. Change-Id: I568a76b87d09cea0f40f1580cf81f7c51402f6f1 Signed-off-by: Oleksij Rempel Reviewed-on: http://openocd.zylin.com/4771 Tested-by: jenkins Reviewed-by: Matthias Welwarsky --- doc/openocd.texi | 6 +++++- src/jtag/drivers/ftdi.c | 29 ++--------------------------- src/target/startup.tcl | 6 ++++++ 3 files changed, 13 insertions(+), 28 deletions(-) diff --git a/doc/openocd.texi b/doc/openocd.texi index f9a9297b0..9918cee06 100644 --- a/doc/openocd.texi +++ b/doc/openocd.texi @@ -2368,6 +2368,7 @@ the hardware can support. Returns the name of the debug adapter driver being used. @end deffn +@anchor{adapter_usb_location} @deffn Command {adapter usb location} -[.]... Specifies the physical USB port of the adapter to use. The path roots at @var{bus} and walks down the physical ports, with each @@ -2510,7 +2511,10 @@ If not specified, serial numbers are not considered. and are not restricted to containing only decimal digits.) @end deffn -@deffn {Config Command} {ftdi_location} :[,]... +@deffn {Config Command} {ftdi_location} -[.]... +@emph{DEPRECATED -- avoid using this. +Use the @xref{adapter_usb_location, adapter usb location} command instead.} + Specifies the physical USB port of the adapter to use. The path roots at @var{bus} and walks down the physical ports, with each @var{port} option specifying a deeper level in the bus topology, the last diff --git a/src/jtag/drivers/ftdi.c b/src/jtag/drivers/ftdi.c index 1afedd1af..b709d28da 100644 --- a/src/jtag/drivers/ftdi.c +++ b/src/jtag/drivers/ftdi.c @@ -69,6 +69,7 @@ #endif /* project specific includes */ +#include #include #include #include @@ -89,7 +90,6 @@ static char *ftdi_device_desc; static char *ftdi_serial; -static char *ftdi_location; static uint8_t ftdi_channel; static uint8_t ftdi_jtag_mode = JTAG_MODE; @@ -658,7 +658,7 @@ static int ftdi_initialize(void) for (int i = 0; ftdi_vid[i] || ftdi_pid[i]; i++) { mpsse_ctx = mpsse_open(&ftdi_vid[i], &ftdi_pid[i], ftdi_device_desc, - ftdi_serial, ftdi_location, ftdi_channel); + ftdi_serial, jtag_usb_get_location(), ftdi_channel); if (mpsse_ctx) break; } @@ -704,7 +704,6 @@ static int ftdi_quit(void) free(ftdi_device_desc); free(ftdi_serial); - free(ftdi_location); free(swd_cmd_queue); @@ -737,21 +736,6 @@ COMMAND_HANDLER(ftdi_handle_serial_command) return ERROR_OK; } -#ifdef HAVE_LIBUSB_GET_PORT_NUMBERS -COMMAND_HANDLER(ftdi_handle_location_command) -{ - if (CMD_ARGC == 1) { - if (ftdi_location) - free(ftdi_location); - ftdi_location = strdup(CMD_ARGV[0]); - } else { - return ERROR_COMMAND_SYNTAX_ERROR; - } - - return ERROR_OK; -} -#endif - COMMAND_HANDLER(ftdi_handle_channel_command) { if (CMD_ARGC == 1) @@ -966,15 +950,6 @@ static const struct command_registration ftdi_command_handlers[] = { .help = "set the serial number of the FTDI device", .usage = "serial_string", }, -#ifdef HAVE_LIBUSB_GET_PORT_NUMBERS - { - .name = "ftdi_location", - .handler = &ftdi_handle_location_command, - .mode = COMMAND_CONFIG, - .help = "set the USB bus location of the FTDI device", - .usage = ":port[,port]...", - }, -#endif { .name = "ftdi_channel", .handler = &ftdi_handle_channel_command, diff --git a/src/target/startup.tcl b/src/target/startup.tcl index cf844e1f6..4d4426f98 100644 --- a/src/target/startup.tcl +++ b/src/target/startup.tcl @@ -221,3 +221,9 @@ proc cortex_a8 args { echo "DEPRECATED! use 'cortex_a' not 'cortex_a8'" eval cortex_a $args } + +# deprecated ftdi cmds +proc ftdi_location args { + echo "DEPRECATED! use 'adapter usb location' not 'ftdi_location'" + eval adapter usb location $args +} From a4d50544de07f13e3f9644d2b48e41ebdc91a7a3 Mon Sep 17 00:00:00 2001 From: Armin van der Togt Date: Thu, 14 Feb 2019 15:35:07 +0100 Subject: [PATCH 06/70] Fix support for single-bank stm32l4 processors Recent patches for STM32L4+ assumed all STM32L4 processors have a dual- bank option. This is not the case for STM32L4{3,4,5,6}xx processors and therefore, these processors (like STM32L433) failed when attempting to flash the second half of the flash memory. This patch fixed this issue. Tested on STM32L433xC, STM32L476xG and STM32L471xG. Change-Id: I8262ba4f05190802c5868d753f3e7af50e581811 Signed-off-by: Armin van der Togt Reviewed-on: http://openocd.zylin.com/4913 Tested-by: jenkins Reviewed-by: Peter Tettelaar Reviewed-by: Tomas Vanek Reviewed-by: Mark Schulte --- src/flash/nor/stm32l4x.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/src/flash/nor/stm32l4x.c b/src/flash/nor/stm32l4x.c index 7c5811ead..7d1e42984 100644 --- a/src/flash/nor/stm32l4x.c +++ b/src/flash/nor/stm32l4x.c @@ -678,8 +678,9 @@ static int stm32l4_probe(struct flash_bank *bank) /* Invalid FLASH size for this device. */ LOG_WARNING("Invalid flash size for STM32L4+ family device."); return ERROR_FAIL; - default: - /* Other L4 family devices have 2K pages. */ + case 0x461: + case 0x415: + /* These are dual-bank devices, we need to check the OPT_DBANK_LE_1M bit here */ page_size = 2048; num_pages = flash_size_in_kb / 2; /* check that calculation result makes sense */ @@ -689,6 +690,16 @@ static int stm32l4_probe(struct flash_bank *bank) else stm32l4_info->bank2_start = num_pages / 2; break; + case 0x462: + case 0x435: + default: + /* These are single-bank devices */ + page_size = 2048; + num_pages = flash_size_in_kb / 2; + /* check that calculation result makes sense */ + assert(num_pages > 0); + stm32l4_info->bank2_start = UINT16_MAX; + break; } /* Release sector table if allocated. */ From 6f66267f853b6c65f47ba686da562c95f0482714 Mon Sep 17 00:00:00 2001 From: Tomas Vanek Date: Mon, 21 Jan 2019 21:51:04 +0100 Subject: [PATCH 07/70] server: fix small mem leak of bindto_name Change-Id: Ib9c8003e164a156f1c4d3cde47e4158d867d82c6 Signed-off-by: Tomas Vanek Reviewed-on: http://openocd.zylin.com/4909 Tested-by: jenkins Reviewed-by: Antonio Borneo --- src/server/server.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/server/server.c b/src/server/server.c index f8273d42d..539bdaf82 100644 --- a/src/server/server.c +++ b/src/server/server.c @@ -703,6 +703,8 @@ void server_free(void) tcl_service_free(); telnet_service_free(); jsp_service_free(); + + free(bindto_name); } void exit_on_signal(int sig) From 3b39618eb5ab2bcceb00acaba3df303c4d9fa51e Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Fri, 15 Feb 2019 21:33:34 +0100 Subject: [PATCH 08/70] cortex_a: fix a potential memory leak in cortex_a_target_create() If the function cortex_a_target_create() or the function cortex_r4_target_create() exit for an error, the value of pointer cortex_a get lost, causing a memory leak. Move the allocation of cortex_a after the check on the parameters. While there, add checks on the value returned by calloc(). Issue highlighted by clang 7.0.0. Change-Id: Ic6eeb9c3b39922d016f6d0319eada1a97a6681f0 Signed-off-by: Antonio Borneo Reviewed-on: http://openocd.zylin.com/4925 Reviewed-by: Tomas Vanek Tested-by: jenkins Reviewed-by: Matthias Welwarsky --- src/target/cortex_a.c | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/src/target/cortex_a.c b/src/target/cortex_a.c index 648317e49..9203fb9ec 100644 --- a/src/target/cortex_a.c +++ b/src/target/cortex_a.c @@ -2840,8 +2840,7 @@ static int cortex_a_init_arch_info(struct target *target, static int cortex_a_target_create(struct target *target, Jim_Interp *interp) { - struct cortex_a_common *cortex_a = calloc(1, sizeof(struct cortex_a_common)); - cortex_a->common_magic = CORTEX_A_COMMON_MAGIC; + struct cortex_a_common *cortex_a; struct adiv5_private_config *pc; if (target->private_config == NULL) @@ -2849,8 +2848,13 @@ static int cortex_a_target_create(struct target *target, Jim_Interp *interp) pc = (struct adiv5_private_config *)target->private_config; + cortex_a = calloc(1, sizeof(struct cortex_a_common)); + if (cortex_a == NULL) { + LOG_ERROR("Out of memory"); + return ERROR_FAIL; + } + cortex_a->common_magic = CORTEX_A_COMMON_MAGIC; cortex_a->armv7a_common.is_armv7r = false; - cortex_a->armv7a_common.arm.arm_vfp_version = ARM_VFP_V3; return cortex_a_init_arch_info(target, cortex_a, pc->dap); @@ -2858,14 +2862,19 @@ static int cortex_a_target_create(struct target *target, Jim_Interp *interp) static int cortex_r4_target_create(struct target *target, Jim_Interp *interp) { - struct cortex_a_common *cortex_a = calloc(1, sizeof(struct cortex_a_common)); - cortex_a->common_magic = CORTEX_A_COMMON_MAGIC; + struct cortex_a_common *cortex_a; struct adiv5_private_config *pc; pc = (struct adiv5_private_config *)target->private_config; if (adiv5_verify_config(pc) != ERROR_OK) return ERROR_FAIL; + cortex_a = calloc(1, sizeof(struct cortex_a_common)); + if (cortex_a == NULL) { + LOG_ERROR("Out of memory"); + return ERROR_FAIL; + } + cortex_a->common_magic = CORTEX_A_COMMON_MAGIC; cortex_a->armv7a_common.is_armv7r = true; return cortex_a_init_arch_info(target, cortex_a, pc->dap); From 1c6f7075f75db1e4da3b918a8c64f2b178712942 Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Fri, 15 Feb 2019 21:26:27 +0100 Subject: [PATCH 09/70] mem_ap: fix a potential memory leak in mem_ap_target_create() If the function mem_ap_target_create() exits for an error, the value of pointer mem_ap get lost, causing a memory leak. Move the allocation of mem_ap after the check on the parameters. While there, add a check on the value returned by calloc(). Issue highlighted by clang 7.0.0. Change-Id: Ia2c11b14fde9694f28bf6efe01d278923db0f0d4 Signed-off-by: Antonio Borneo Reviewed-on: http://openocd.zylin.com/4923 Reviewed-by: Tomas Vanek Tested-by: jenkins Reviewed-by: Matthias Welwarsky --- src/target/mem_ap.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/target/mem_ap.c b/src/target/mem_ap.c index 3a2d4b7c5..584e19d4c 100644 --- a/src/target/mem_ap.c +++ b/src/target/mem_ap.c @@ -31,7 +31,7 @@ struct mem_ap { static int mem_ap_target_create(struct target *target, Jim_Interp *interp) { - struct mem_ap *mem_ap = calloc(1, sizeof(struct mem_ap)); + struct mem_ap *mem_ap; struct adiv5_private_config *pc; pc = (struct adiv5_private_config *)target->private_config; @@ -43,6 +43,12 @@ static int mem_ap_target_create(struct target *target, Jim_Interp *interp) return ERROR_FAIL; } + mem_ap = calloc(1, sizeof(struct mem_ap)); + if (mem_ap == NULL) { + LOG_ERROR("Out of memory"); + return ERROR_FAIL; + } + mem_ap->ap_num = pc->ap_num; mem_ap->arm.common_magic = ARM_COMMON_MAGIC; mem_ap->arm.dap = pc->dap; From f473f84840d0c324df684c49744e32f086595bab Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Fri, 15 Feb 2019 21:31:02 +0100 Subject: [PATCH 10/70] aarch64: fix a potential memory leak in aarch64_target_create() If the function aarch64_target_create() exits for an error, the value of pointer aarch64 get lost, causing a memory leak. Move the allocation of aarch64 after the check on the parameters. While there, add a check on the value returned by calloc(). Issue highlighted by clang 7.0.0. Change-Id: Ib9ad27f4acd940da308c01fdbf33cfe51ab0c639 Signed-off-by: Antonio Borneo Reviewed-on: http://openocd.zylin.com/4924 Reviewed-by: Tomas Vanek Tested-by: jenkins Reviewed-by: Matthias Welwarsky --- src/target/aarch64.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/target/aarch64.c b/src/target/aarch64.c index 63174c2eb..2357eb217 100644 --- a/src/target/aarch64.c +++ b/src/target/aarch64.c @@ -2396,11 +2396,17 @@ static int aarch64_init_arch_info(struct target *target, static int aarch64_target_create(struct target *target, Jim_Interp *interp) { struct aarch64_private_config *pc = target->private_config; - struct aarch64_common *aarch64 = calloc(1, sizeof(struct aarch64_common)); + struct aarch64_common *aarch64; if (adiv5_verify_config(&pc->adiv5_config) != ERROR_OK) return ERROR_FAIL; + aarch64 = calloc(1, sizeof(struct aarch64_common)); + if (aarch64 == NULL) { + LOG_ERROR("Out of memory"); + return ERROR_FAIL; + } + return aarch64_init_arch_info(target, aarch64, pc->adiv5_config.dap); } From 2c76f1ac0e27c643539b604e23435f58fa0af016 Mon Sep 17 00:00:00 2001 From: Paul Fertser Date: Fri, 4 Nov 2016 13:58:05 +0300 Subject: [PATCH 11/70] jtag: drivers: cmsis-dap: correct vendor request code While at it, change the macro name to make it obvious it's a string, not some numeric ID. This also matches ARM code that's using Change-Id: Id35ba5b95cef0ac77657c40985b24c1ae2720748 Signed-off-by: Paul Fertser Reviewed-on: http://openocd.zylin.com/3855 Tested-by: jenkins Reviewed-by: Tomas Vanek --- src/jtag/drivers/cmsis_dap_usb.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/jtag/drivers/cmsis_dap_usb.c b/src/jtag/drivers/cmsis_dap_usb.c index bd8d0bec7..14a23d442 100644 --- a/src/jtag/drivers/cmsis_dap_usb.c +++ b/src/jtag/drivers/cmsis_dap_usb.c @@ -77,8 +77,8 @@ static bool swd_mode; #define CMD_DAP_RESET_TARGET 0x0A /* CMD_INFO */ -#define INFO_ID_VID 0x00 /* string */ -#define INFO_ID_PID 0x02 /* string */ +#define INFO_ID_VENDOR 0x01 /* string */ +#define INFO_ID_PRODUCT 0x02 /* string */ #define INFO_ID_SERNUM 0x03 /* string */ #define INFO_ID_FW_VER 0x04 /* string */ #define INFO_ID_TD_VEND 0x05 /* string */ From f21c12abecb9df244f147740166378ede7ea398e Mon Sep 17 00:00:00 2001 From: Moritz Fischer Date: Mon, 21 Jan 2019 09:24:12 -0800 Subject: [PATCH 12/70] flash: stm32f2/f4/f7: Add One-Time-Porgrammable (OTP) support The OTP is part of the flash memory. It has 512 (1024 for F7) bytes and is organized in 16 sectors with 32 (64 for F7) bytes each. The OTP is exposed as separate flash bank 1 and can be used with the usual flash commands. Writing the OTP can be done as follows: > stm32f2x otp 1 enable > flash write bank 1 foo.bin 0 > mdw 0x1fff7800 4 > verify_image foo.bin 0x1fff7800 > stm32f2x otp 1 disable Note: This patch is largely a rebase/cleanup of a patch from 2012 by Laurent Charpentier and he did most of the work. No new Clang-Analyzer warnings. Change-Id: I5e6371f6a7c7a9929c1d7907d6ba4724f9d20d97 Signed-off-by: Moritz Fischer Reviewed-on: http://openocd.zylin.com/829 Tested-by: jenkins Reviewed-by: Tarek BOCHKATI Reviewed-by: Tomas Vanek --- doc/openocd.texi | 11 ++ src/flash/nor/stm32f2x.c | 221 +++++++++++++++++++++++++++++++++++++-- tcl/target/stm32f2x.cfg | 1 + tcl/target/stm32f4x.cfg | 2 + tcl/target/stm32f7x.cfg | 1 + 5 files changed, 226 insertions(+), 10 deletions(-) diff --git a/doc/openocd.texi b/doc/openocd.texi index 9918cee06..8b03b80b6 100644 --- a/doc/openocd.texi +++ b/doc/openocd.texi @@ -6645,6 +6645,17 @@ the chip identification register, and autoconfigures itself. flash bank $_FLASHNAME stm32f2x 0 0 0 0 $_TARGETNAME @end example +If you use OTP (One-Time Programmable) memory define it as a second bank +as per the following example. +@example +flash bank $_FLASHNAME stm32f2x 0x1FFF7800 0 0 0 $_TARGETNAME +@end example + +@deffn Command {stm32f2x otp } num (@option{enable}|@option{disable}|@option{show}) +Enables or disables OTP write commands for bank @var{num}. +The @var{num} parameter is a value shown by @command{flash banks}. +@end deffn + Note that some devices have been found that have a flash size register that contains an invalid value, to workaround this issue you can override the probed value used by the flash driver. diff --git a/src/flash/nor/stm32f2x.c b/src/flash/nor/stm32f2x.c index b46fb0786..63c83479d 100644 --- a/src/flash/nor/stm32f2x.c +++ b/src/flash/nor/stm32f2x.c @@ -123,6 +123,19 @@ /* Mass erase time can be as high as 32 s in x8 mode. */ #define FLASH_MASS_ERASE_TIMEOUT 33000 +#define FLASH_BANK_BASE 0x80000000 + +#define STM32F2_OTP_SIZE 512 +#define STM32F2_OTP_SECTOR_SIZE 32 +#define STM32F2_OTP_BANK_BASE 0x1fff7800 +#define STM32F2_OTP_LOCK_BASE ((STM32F2_OTP_BANK_BASE) + (STM32F2_OTP_SIZE)) + +/* see RM0410 section 3.6 "One-time programmable bytes" */ +#define STM32F7_OTP_SECTOR_SIZE 64 +#define STM32F7_OTP_SIZE 1024 +#define STM32F7_OTP_BANK_BASE 0x1ff0f000 +#define STM32F7_OTP_LOCK_BASE ((STM32F7_OTP_BANK_BASE) + (STM32F7_OTP_SIZE)) + #define STM32_FLASH_BASE 0x40023c00 #define STM32_FLASH_ACR 0x40023c00 #define STM32_FLASH_KEYR 0x40023c04 @@ -185,7 +198,8 @@ struct stm32x_options { struct stm32x_flash_bank { struct stm32x_options option_bytes; - int probed; + bool probed; + bool otp_unlocked; bool has_large_mem; /* F42x/43x/469/479/7xx in dual bank mode */ bool has_extra_options; /* F42x/43x/469/479/7xx */ bool has_boot_addr; /* F7xx */ @@ -194,6 +208,49 @@ struct stm32x_flash_bank { uint32_t user_bank_size; }; +static bool stm32x_is_otp(struct flash_bank *bank) +{ + return bank->base == STM32F2_OTP_BANK_BASE || + bank->base == STM32F7_OTP_BANK_BASE; +} + +static bool stm32x_otp_is_f7(struct flash_bank *bank) +{ + return bank->base == STM32F7_OTP_BANK_BASE; +} + +static int stm32x_is_otp_unlocked(struct flash_bank *bank) +{ + struct stm32x_flash_bank *stm32x_info = bank->driver_priv; + + return stm32x_info->otp_unlocked; +} + +static int stm32x_otp_disable(struct flash_bank *bank) +{ + struct stm32x_flash_bank *stm32x_info = bank->driver_priv; + + LOG_INFO("OTP memory bank #%d is disabled for write commands.", + bank->bank_number); + stm32x_info->otp_unlocked = false; + return ERROR_OK; +} + +static int stm32x_otp_enable(struct flash_bank *bank) +{ + struct stm32x_flash_bank *stm32x_info = bank->driver_priv; + + if (!stm32x_info->otp_unlocked) { + LOG_INFO("OTP memory bank #%d is is enabled for write commands.", + bank->bank_number); + stm32x_info->otp_unlocked = true; + } else { + LOG_WARNING("OTP memory bank #%d is is already enabled for write commands.", + bank->bank_number); + } + return ERROR_OK; +} + /* flash bank stm32x 0 0 */ FLASH_BANK_COMMAND_HANDLER(stm32x_flash_bank_command) @@ -206,7 +263,8 @@ FLASH_BANK_COMMAND_HANDLER(stm32x_flash_bank_command) stm32x_info = malloc(sizeof(struct stm32x_flash_bank)); bank->driver_priv = stm32x_info; - stm32x_info->probed = 0; + stm32x_info->probed = false; + stm32x_info->otp_unlocked = false; stm32x_info->user_bank_size = bank->size; return ERROR_OK; @@ -460,14 +518,67 @@ static int stm32x_write_options(struct flash_bank *bank) return ERROR_OK; } +static int stm32x_otp_read_protect(struct flash_bank *bank) +{ + struct target *target = bank->target; + uint32_t lock_base; + int i, retval; + uint8_t lock; + + lock_base = stm32x_otp_is_f7(bank) ? STM32F7_OTP_LOCK_BASE + : STM32F2_OTP_LOCK_BASE; + + for (i = 0; i < bank->num_sectors; i++) { + retval = target_read_u8(target, lock_base + i, &lock); + if (retval != ERROR_OK) + return retval; + bank->sectors[i].is_protected = !lock; + } + + return ERROR_OK; +} + +static int stm32x_otp_protect(struct flash_bank *bank, int first, int last) +{ + struct target *target = bank->target; + uint32_t lock_base; + int i, retval; + uint8_t lock; + + assert((0 <= first) && (first <= last) && (last < bank->num_sectors)); + + lock_base = stm32x_otp_is_f7(bank) ? STM32F7_OTP_LOCK_BASE + : STM32F2_OTP_LOCK_BASE; + + for (i = first; first <= last; i++) { + retval = target_read_u8(target, lock_base + i, &lock); + if (retval != ERROR_OK) + return retval; + if (lock) + continue; + + lock = 0xff; + retval = target_write_u8(target, lock_base + i, lock); + if (retval != ERROR_OK) + return retval; + } + + return ERROR_OK; +} + static int stm32x_protect_check(struct flash_bank *bank) { struct stm32x_flash_bank *stm32x_info = bank->driver_priv; struct flash_sector *prot_blocks; int num_prot_blocks; + int retval; + + /* if it's the OTP bank, look at the lock bits there */ + if (stm32x_is_otp(bank)) + return stm32x_otp_read_protect(bank); /* read write protection settings */ - int retval = stm32x_read_options(bank); + retval = stm32x_read_options(bank); if (retval != ERROR_OK) { LOG_DEBUG("unable to read option bytes"); return retval; @@ -494,6 +605,11 @@ static int stm32x_erase(struct flash_bank *bank, int first, int last) struct target *target = bank->target; int i; + if (stm32x_is_otp(bank)) { + LOG_ERROR("Cannot erase OTP memory"); + return ERROR_FAIL; + } + assert((0 <= first) && (first <= last) && (last < bank->num_sectors)); if (bank->target->state != TARGET_HALTED) { @@ -553,6 +669,13 @@ static int stm32x_protect(struct flash_bank *bank, int set, int first, int last) return ERROR_TARGET_NOT_HALTED; } + if (stm32x_is_otp(bank)) { + if (!set) + return ERROR_COMMAND_ARGUMENT_INVALID; + + return stm32x_otp_protect(bank, first, last); + } + /* read protection settings */ int retval = stm32x_read_options(bank); if (retval != ERROR_OK) { @@ -590,6 +713,11 @@ static int stm32x_write_block(struct flash_bank *bank, const uint8_t *buffer, #include "../../../contrib/loaders/flash/stm32/stm32f2x.inc" }; + if (stm32x_is_otp(bank) && !stm32x_is_otp_unlocked(bank)) { + LOG_ERROR("OTP memory bank is disabled for write commands."); + return ERROR_FAIL; + } + if (target_alloc_working_area(target, sizeof(stm32x_flash_write_code), &write_algorithm) != ERROR_OK) { LOG_WARNING("no working area available, can't do block memory writes"); @@ -774,7 +902,7 @@ static int setup_sector(struct flash_bank *bank, int start, int num, int size) bank->sectors[i].offset = bank->size; bank->sectors[i].size = size; bank->size += bank->sectors[i].size; - LOG_DEBUG("sector %d: %dkBytes", i, size >> 10); + LOG_DEBUG("sector %d: %d kBytes", i, size >> 10); } return start + num; @@ -828,15 +956,17 @@ static int stm32x_probe(struct flash_bank *bank) { struct target *target = bank->target; struct stm32x_flash_bank *stm32x_info = bank->driver_priv; - int i, num_prot_blocks; + int i, num_prot_blocks, num_sectors; uint16_t flash_size_in_kb; + uint16_t otp_size_in_b; + uint16_t otp_sector_size; uint32_t flash_size_reg = 0x1FFF7A22; uint16_t max_sector_size_in_kb = 128; uint16_t max_flash_size_in_kb; uint32_t device_id; uint32_t base_address = 0x08000000; - stm32x_info->probed = 0; + stm32x_info->probed = false; stm32x_info->has_large_mem = false; stm32x_info->has_boot_addr = false; stm32x_info->has_extra_options = false; @@ -856,6 +986,40 @@ static int stm32x_probe(struct flash_bank *bank) bank->prot_blocks = NULL; } + /* if explicitely called out as OTP bank, short circuit probe */ + if (stm32x_is_otp(bank)) { + if (stm32x_otp_is_f7(bank)) { + otp_size_in_b = STM32F7_OTP_SIZE; + otp_sector_size = STM32F7_OTP_SECTOR_SIZE; + } else { + otp_size_in_b = STM32F2_OTP_SIZE; + otp_sector_size = STM32F2_OTP_SECTOR_SIZE; + } + + num_sectors = otp_size_in_b / otp_sector_size; + LOG_INFO("flash size = %d bytes", otp_size_in_b); + + assert(num_sectors > 0); + + bank->num_sectors = num_sectors; + bank->sectors = calloc(sizeof(struct flash_sector), num_sectors); + + if (stm32x_otp_is_f7(bank)) + bank->size = STM32F7_OTP_SIZE; + else + bank->size = STM32F2_OTP_SIZE; + + for (i = 0; i < num_sectors; i++) { + bank->sectors[i].offset = i * otp_sector_size; + bank->sectors[i].size = otp_sector_size; + bank->sectors[i].is_erased = 1; + bank->sectors[i].is_protected = 0; + } + + stm32x_info->probed = true; + return ERROR_OK; + } + /* read stm32 device id register */ int retval = stm32x_get_device_id(bank, &device_id); if (retval != ERROR_OK) @@ -945,7 +1109,7 @@ static int stm32x_probe(struct flash_bank *bank) flash_size_in_kb = stm32x_info->user_bank_size / 1024; } - LOG_INFO("flash size = %dkbytes", flash_size_in_kb); + LOG_INFO("flash size = %d kbytes", flash_size_in_kb); /* did we assign flash size? */ assert(flash_size_in_kb != 0xffff); @@ -1040,7 +1204,7 @@ static int stm32x_probe(struct flash_bank *bank) bank->num_prot_blocks = num_prot_blocks; assert((bank->size >> 10) == flash_size_in_kb); - stm32x_info->probed = 1; + stm32x_info->probed = true; return ERROR_OK; } @@ -1483,7 +1647,7 @@ COMMAND_HANDLER(stm32f2x_handle_options_write_command) /* switching between single- and dual-bank modes requires re-probe */ /* ... and reprogramming of whole flash */ - stm32x_info->probed = 0; + stm32x_info->probed = false; command_print(CMD_CTX, "stm32f2x write options complete.\n" "INFO: a reset or power cycle is required " @@ -1533,6 +1697,37 @@ COMMAND_HANDLER(stm32f2x_handle_optcr2_write_command) return retval; } +COMMAND_HANDLER(stm32x_handle_otp_command) +{ + if (CMD_ARGC < 2) { + command_print(CMD_CTX, "stm32x otp (enable|disable|show)"); + return ERROR_COMMAND_SYNTAX_ERROR; + } + + struct flash_bank *bank; + int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank); + if (ERROR_OK != retval) + return retval; + if (stm32x_is_otp(bank)) { + if (strcmp(CMD_ARGV[1], "enable") == 0) { + stm32x_otp_enable(bank); + } else if (strcmp(CMD_ARGV[1], "disable") == 0) { + stm32x_otp_disable(bank); + } else if (strcmp(CMD_ARGV[1], "show") == 0) { + command_print(CMD_CTX, + "OTP memory bank #%d is %s for write commands.", + bank->bank_number, + stm32x_is_otp_unlocked(bank) ? "enabled" : "disabled"); + } else { + return ERROR_COMMAND_SYNTAX_ERROR; + } + } else { + command_print(CMD_CTX, "Failed: not an OTP bank."); + } + + return retval; +} + static const struct command_registration stm32x_exec_command_handlers[] = { { .name = "lock", @@ -1576,7 +1771,13 @@ static const struct command_registration stm32x_exec_command_handlers[] = { .usage = "bank_id optcr2", .help = "Write optcr2 word", }, - + { + .name = "otp", + .handler = stm32x_handle_otp_command, + .mode = COMMAND_EXEC, + .usage = "bank_id", + .help = "OTP (One Time Programmable) memory write enable/disable.", + }, COMMAND_REGISTRATION_DONE }; diff --git a/tcl/target/stm32f2x.cfg b/tcl/target/stm32f2x.cfg index 80f9274d5..1e8b94ace 100644 --- a/tcl/target/stm32f2x.cfg +++ b/tcl/target/stm32f2x.cfg @@ -62,6 +62,7 @@ $_TARGETNAME configure -work-area-phys 0x20000000 -work-area-size $_WORKAREASIZE set _FLASHNAME $_CHIPNAME.flash flash bank $_FLASHNAME stm32f2x 0 0 0 0 $_TARGETNAME +flash bank $_CHIPNAME.otp stm32f2x 0x1fff7800 0 0 0 $_TARGETNAME reset_config srst_nogate diff --git a/tcl/target/stm32f4x.cfg b/tcl/target/stm32f4x.cfg index 73b1dc8ed..09ce14a5d 100644 --- a/tcl/target/stm32f4x.cfg +++ b/tcl/target/stm32f4x.cfg @@ -50,6 +50,8 @@ $_TARGETNAME configure -work-area-phys 0x20000000 -work-area-size $_WORKAREASIZE set _FLASHNAME $_CHIPNAME.flash flash bank $_FLASHNAME stm32f2x 0 0 0 0 $_TARGETNAME +flash bank $_CHIPNAME.otp stm32f2x 0x1fff7800 0 0 0 $_TARGETNAME + # JTAG speed should be <= F_CPU/6. F_CPU after reset is 16MHz, so use F_JTAG = 2MHz # # Since we may be running of an RC oscilator, we crank down the speed a diff --git a/tcl/target/stm32f7x.cfg b/tcl/target/stm32f7x.cfg index f6a44cc29..b777c6112 100755 --- a/tcl/target/stm32f7x.cfg +++ b/tcl/target/stm32f7x.cfg @@ -49,6 +49,7 @@ $_TARGETNAME configure -work-area-phys 0x20000000 -work-area-size $_WORKAREASIZE set _FLASHNAME $_CHIPNAME.flash flash bank $_FLASHNAME stm32f2x 0 0 0 0 $_TARGETNAME +flash bank $_CHIPNAME.otp stm32f2x 0x1ff0f000 0 0 0 $_TARGETNAME # adapter speed should be <= F_CPU/6. F_CPU after reset is 16MHz, so use F_JTAG = 2MHz adapter_khz 2000 From 17a052d6fe44fc265d48e94bdd3356d6f25ca064 Mon Sep 17 00:00:00 2001 From: Marc Schink Date: Fri, 15 Feb 2019 14:31:19 +0100 Subject: [PATCH 13/70] target: Use proper data types for timer callback Change-Id: I5ca6da767f9e96180c43b179b2c682b1b7c98563 Signed-off-by: Marc Schink Reviewed-on: http://openocd.zylin.com/4920 Tested-by: jenkins Reviewed-by: Tomas Vanek --- src/target/target.c | 9 +++++---- src/target/target.h | 11 ++++++++--- 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/src/target/target.c b/src/target/target.c index 693eb519e..a3230d248 100644 --- a/src/target/target.c +++ b/src/target/target.c @@ -1460,7 +1460,8 @@ int target_register_trace_callback(int (*callback)(struct target *target, return ERROR_OK; } -int target_register_timer_callback(int (*callback)(void *priv), int time_ms, int periodic, void *priv) +int target_register_timer_callback(int (*callback)(void *priv), + unsigned int time_ms, enum target_timer_type type, void *priv) { struct target_timer_callback **callbacks_p = &target_timer_callbacks; @@ -1475,7 +1476,7 @@ int target_register_timer_callback(int (*callback)(void *priv), int time_ms, int (*callbacks_p) = malloc(sizeof(struct target_timer_callback)); (*callbacks_p)->callback = callback; - (*callbacks_p)->periodic = periodic; + (*callbacks_p)->type = type; (*callbacks_p)->time_ms = time_ms; (*callbacks_p)->removed = false; @@ -1625,7 +1626,7 @@ static int target_call_timer_callback(struct target_timer_callback *cb, { cb->callback(cb->priv); - if (cb->periodic) + if (cb->type == TARGET_TIMER_TYPE_PERIODIC) return target_timer_callback_periodic_restart(cb, now); return target_unregister_timer_callback(cb->callback, cb->priv); @@ -1659,7 +1660,7 @@ static int target_call_timer_callbacks_check_time(int checktime) } bool call_it = (*callback)->callback && - ((!checktime && (*callback)->periodic) || + ((!checktime && (*callback)->type == TARGET_TIMER_TYPE_PERIODIC) || timeval_compare(&now, &(*callback)->when) >= 0); if (call_it) diff --git a/src/target/target.h b/src/target/target.h index 983f450ac..36b131aa9 100644 --- a/src/target/target.h +++ b/src/target/target.h @@ -314,10 +314,15 @@ struct target_trace_callback { int (*callback)(struct target *target, size_t len, uint8_t *data, void *priv); }; +enum target_timer_type { + TARGET_TIMER_TYPE_ONESHOT, + TARGET_TIMER_TYPE_PERIODIC +}; + struct target_timer_callback { int (*callback)(void *priv); - int time_ms; - int periodic; + unsigned int time_ms; + enum target_timer_type type; bool removed; struct timeval when; void *priv; @@ -385,7 +390,7 @@ int target_call_trace_callbacks(struct target *target, size_t len, uint8_t *data * or much more rarely than specified */ int target_register_timer_callback(int (*callback)(void *priv), - int time_ms, int periodic, void *priv); + unsigned int time_ms, enum target_timer_type type, void *priv); int target_unregister_timer_callback(int (*callback)(void *priv), void *priv); int target_call_timer_callbacks(void); /** From 21687eb983a4d5e30cd9c4050b9ebce2f3b280c7 Mon Sep 17 00:00:00 2001 From: Marc Schink Date: Fri, 15 Feb 2019 14:36:54 +0100 Subject: [PATCH 14/70] Use enum for target_register_timer_callback() Change-Id: I268e8c5d783914aa97cbde301448b2c5bc3cb9e6 Signed-off-by: Marc Schink Reviewed-on: http://openocd.zylin.com/4921 Tested-by: jenkins Reviewed-by: Tomas Vanek --- src/target/aarch64.c | 3 ++- src/target/arm7_9_common.c | 2 +- src/target/armv7m_trace.c | 3 ++- src/target/cortex_a.c | 3 ++- src/target/cortex_m.c | 3 ++- src/target/hla_target.c | 3 ++- src/target/openrisc/jsp_server.c | 3 ++- src/target/target.c | 2 +- 8 files changed, 14 insertions(+), 8 deletions(-) diff --git a/src/target/aarch64.c b/src/target/aarch64.c index 2357eb217..c9cedea82 100644 --- a/src/target/aarch64.c +++ b/src/target/aarch64.c @@ -2388,7 +2388,8 @@ static int aarch64_init_arch_info(struct target *target, armv8->armv8_mmu.read_physical_memory = aarch64_read_phys_memory; armv8_init_arch_info(target, armv8); - target_register_timer_callback(aarch64_handle_target_request, 1, 1, target); + target_register_timer_callback(aarch64_handle_target_request, 1, + TARGET_TIMER_TYPE_PERIODIC, target); return ERROR_OK; } diff --git a/src/target/arm7_9_common.c b/src/target/arm7_9_common.c index 7fd1ed9f8..96e31b9d3 100644 --- a/src/target/arm7_9_common.c +++ b/src/target/arm7_9_common.c @@ -2859,7 +2859,7 @@ int arm7_9_init_arch_info(struct target *target, struct arm7_9_common *arm7_9) return retval; return target_register_timer_callback(arm7_9_handle_target_request, - 1, 1, target); + 1, TARGET_TIMER_TYPE_PERIODIC, target); } static const struct command_registration arm7_9_any_command_handlers[] = { diff --git a/src/target/armv7m_trace.c b/src/target/armv7m_trace.c index 62f0f8e61..6170119d9 100644 --- a/src/target/armv7m_trace.c +++ b/src/target/armv7m_trace.c @@ -116,7 +116,8 @@ int armv7m_trace_tpiu_config(struct target *target) return retval; if (trace_config->config_type == TRACE_CONFIG_TYPE_INTERNAL) - target_register_timer_callback(armv7m_poll_trace, 1, 1, target); + target_register_timer_callback(armv7m_poll_trace, 1, + TARGET_TIMER_TYPE_PERIODIC, target); target_call_event_callbacks(target, TARGET_EVENT_TRACE_CONFIG); diff --git a/src/target/cortex_a.c b/src/target/cortex_a.c index 9203fb9ec..5d5fb9621 100644 --- a/src/target/cortex_a.c +++ b/src/target/cortex_a.c @@ -2833,7 +2833,8 @@ static int cortex_a_init_arch_info(struct target *target, /* REVISIT v7a setup should be in a v7a-specific routine */ armv7a_init_arch_info(target, armv7a); - target_register_timer_callback(cortex_a_handle_target_request, 1, 1, target); + target_register_timer_callback(cortex_a_handle_target_request, 1, + TARGET_TIMER_TYPE_PERIODIC, target); return ERROR_OK; } diff --git a/src/target/cortex_m.c b/src/target/cortex_m.c index 62d376098..d751fd854 100644 --- a/src/target/cortex_m.c +++ b/src/target/cortex_m.c @@ -2269,7 +2269,8 @@ static int cortex_m_init_arch_info(struct target *target, armv7m->load_core_reg_u32 = cortex_m_load_core_reg_u32; armv7m->store_core_reg_u32 = cortex_m_store_core_reg_u32; - target_register_timer_callback(cortex_m_handle_target_request, 1, 1, target); + target_register_timer_callback(cortex_m_handle_target_request, 1, + TARGET_TIMER_TYPE_PERIODIC, target); return ERROR_OK; } diff --git a/src/target/hla_target.c b/src/target/hla_target.c index 4f97eb95c..60ed7d64d 100644 --- a/src/target/hla_target.c +++ b/src/target/hla_target.c @@ -346,7 +346,8 @@ static int adapter_init_arch_info(struct target *target, armv7m->examine_debug_reason = adapter_examine_debug_reason; armv7m->stlink = true; - target_register_timer_callback(hl_handle_target_request, 1, 1, target); + target_register_timer_callback(hl_handle_target_request, 1, + TARGET_TIMER_TYPE_PERIODIC, target); return ERROR_OK; } diff --git a/src/target/openrisc/jsp_server.c b/src/target/openrisc/jsp_server.c index 6cd53f43c..6fb764a6c 100644 --- a/src/target/openrisc/jsp_server.c +++ b/src/target/openrisc/jsp_server.c @@ -101,7 +101,8 @@ static int jsp_new_connection(struct connection *connection) jsp_service->connection = connection; - int retval = target_register_timer_callback(&jsp_poll_read, 1, 1, jsp_service); + int retval = target_register_timer_callback(&jsp_poll_read, 1, + TARGET_TIMER_TYPE_PERIODIC, jsp_service); if (ERROR_OK != retval) return retval; diff --git a/src/target/target.c b/src/target/target.c index a3230d248..9955a5655 100644 --- a/src/target/target.c +++ b/src/target/target.c @@ -1357,7 +1357,7 @@ static int target_init(struct command_context *cmd_ctx) return retval; retval = target_register_timer_callback(&handle_target, - polling_interval, 1, cmd_ctx->interp); + polling_interval, TARGET_TIMER_TYPE_PERIODIC, cmd_ctx->interp); if (ERROR_OK != retval) return retval; From db429c34d047ac40dadf0087f3b3434551c855d4 Mon Sep 17 00:00:00 2001 From: Matthias Welwarsky Date: Thu, 5 Apr 2018 13:42:21 +0200 Subject: [PATCH 15/70] armv8: allow halt on exception add command 'catch_exc' to halt a core on entering any of Secure EL1 or EL3 or Non-Secure EL1 or EL2. Change-Id: I0c68e247af68dd96616855a9bc1063c277d222e5 Signed-off-by: Matthias Welwarsky Reviewed-on: http://openocd.zylin.com/4479 Tested-by: jenkins Reviewed-by: Antonio Borneo Reviewed-by: Matthias Welwarsky --- doc/openocd.texi | 8 +++++ src/server/gdb_server.c | 2 ++ src/target/armv8.c | 73 +++++++++++++++++++++++++++++++++++++++++ src/target/armv8.h | 1 + src/target/armv8_dpm.c | 4 ++- src/target/target.c | 1 + src/target/target.h | 3 +- 7 files changed, 90 insertions(+), 2 deletions(-) diff --git a/doc/openocd.texi b/doc/openocd.texi index 8b03b80b6..2e04182b3 100644 --- a/doc/openocd.texi +++ b/doc/openocd.texi @@ -9345,6 +9345,14 @@ be copied to an in-memory buffer identified by the @option{address} and @option{size} options using DMA. @end deffn +@deffn Command {$target_name catch_exc} [@option{off}|@option{sec_el1}|@option{sec_el3}|@option{nsec_el1}|@option{nsec_el2}]+ +Cause @command{$target_name} to halt when an exception is taken. Any combination of +Secure (sec) EL1/EL3 or Non-Secure (nsec) EL1/EL2 is valid. The target +@command{$target_name} will halt before taking the exception. In order to resume +the target, the exception catch must be disabled again with @command{$target_name catch_exc off}. +Issuing the command without options prints the current configuration. +@end deffn + @section Intel Architecture Intel Quark X10xx is the first product in the Quark family of SoCs. It is an IA-32 diff --git a/src/server/gdb_server.c b/src/server/gdb_server.c index 13e5aca6a..ef2ead44f 100644 --- a/src/server/gdb_server.c +++ b/src/server/gdb_server.c @@ -153,6 +153,8 @@ static int gdb_last_signal(struct target *target) return 0x05; /* SIGTRAP */ case DBG_REASON_SINGLESTEP: return 0x05; /* SIGTRAP */ + case DBG_REASON_EXC_CATCH: + return 0x05; case DBG_REASON_NOTHALTED: return 0x0; /* no signal... shouldn't happen */ default: diff --git a/src/target/armv8.c b/src/target/armv8.c index cee837f58..76a2d98af 100644 --- a/src/target/armv8.c +++ b/src/target/armv8.c @@ -1013,6 +1013,72 @@ int armv8_mmu_translate_va_pa(struct target *target, target_addr_t va, return retval; } +COMMAND_HANDLER(armv8_handle_exception_catch_command) +{ + struct target *target = get_current_target(CMD_CTX); + struct armv8_common *armv8 = target_to_armv8(target); + uint32_t edeccr = 0; + unsigned int argp = 0; + int retval; + + static const Jim_Nvp nvp_ecatch_modes[] = { + { .name = "off", .value = 0 }, + { .name = "nsec_el1", .value = (1 << 5) }, + { .name = "nsec_el2", .value = (2 << 5) }, + { .name = "nsec_el12", .value = (3 << 5) }, + { .name = "sec_el1", .value = (1 << 1) }, + { .name = "sec_el3", .value = (4 << 1) }, + { .name = "sec_el13", .value = (5 << 1) }, + { .name = NULL, .value = -1 }, + }; + const Jim_Nvp *n; + + if (CMD_ARGC == 0) { + const char *sec = NULL, *nsec = NULL; + + retval = mem_ap_read_atomic_u32(armv8->debug_ap, + armv8->debug_base + CPUV8_DBG_ECCR, &edeccr); + if (retval != ERROR_OK) + return retval; + + n = Jim_Nvp_value2name_simple(nvp_ecatch_modes, edeccr & 0x0f); + if (n->name != NULL) + sec = n->name; + + n = Jim_Nvp_value2name_simple(nvp_ecatch_modes, edeccr & 0xf0); + if (n->name != NULL) + nsec = n->name; + + if (sec == NULL || nsec == NULL) { + LOG_WARNING("Exception Catch: unknown exception catch configuration: EDECCR = %02x", edeccr & 0xff); + return ERROR_FAIL; + } + + command_print(CMD_CTX, "Exception Catch: Secure: %s, Non-Secure: %s", sec, nsec); + return ERROR_OK; + } + + while (CMD_ARGC > argp) { + n = Jim_Nvp_name2value_simple(nvp_ecatch_modes, CMD_ARGV[argp]); + if (n->name == NULL) { + LOG_ERROR("Unknown option: %s", CMD_ARGV[argp]); + return ERROR_FAIL; + } + + LOG_DEBUG("found: %s", n->name); + + edeccr |= n->value; + argp++; + } + + retval = mem_ap_write_atomic_u32(armv8->debug_ap, + armv8->debug_base + CPUV8_DBG_ECCR, edeccr); + if (retval != ERROR_OK) + return retval; + + return ERROR_OK; +} + int armv8_handle_cache_info_command(struct command_context *cmd_ctx, struct armv8_cache_common *armv8_cache) { @@ -1675,6 +1741,13 @@ void armv8_free_reg_cache(struct target *target) } const struct command_registration armv8_command_handlers[] = { + { + .name = "catch_exc", + .handler = armv8_handle_exception_catch_command, + .mode = COMMAND_EXEC, + .help = "configure exception catch", + .usage = "[(nsec_el1,nsec_el2,sec_el1,sec_el3)+,off]", + }, COMMAND_REGISTRATION_DONE }; diff --git a/src/target/armv8.h b/src/target/armv8.h index dfd54edcb..af00e52d6 100644 --- a/src/target/armv8.h +++ b/src/target/armv8.h @@ -261,6 +261,7 @@ static inline bool is_armv8(struct armv8_common *armv8) #define CPUV8_DBG_WFAR1 0x34 #define CPUV8_DBG_DSCR 0x088 #define CPUV8_DBG_DRCR 0x090 +#define CPUV8_DBG_ECCR 0x098 #define CPUV8_DBG_PRCR 0x310 #define CPUV8_DBG_PRSR 0x314 diff --git a/src/target/armv8_dpm.c b/src/target/armv8_dpm.c index a5d7d11f8..081eed21b 100644 --- a/src/target/armv8_dpm.c +++ b/src/target/armv8_dpm.c @@ -1381,13 +1381,15 @@ void armv8_dpm_report_dscr(struct arm_dpm *dpm, uint32_t dscr) case DSCRV8_ENTRY_BKPT: /* SW BKPT (?) */ case DSCRV8_ENTRY_RESET_CATCH: /* Reset catch */ case DSCRV8_ENTRY_OS_UNLOCK: /*OS unlock catch*/ - case DSCRV8_ENTRY_EXCEPTION_CATCH: /*exception catch*/ case DSCRV8_ENTRY_SW_ACCESS_DBG: /*SW access dbg register*/ target->debug_reason = DBG_REASON_BREAKPOINT; break; case DSCRV8_ENTRY_WATCHPOINT: /* asynch watchpoint */ target->debug_reason = DBG_REASON_WATCHPOINT; break; + case DSCRV8_ENTRY_EXCEPTION_CATCH: /*exception catch*/ + target->debug_reason = DBG_REASON_EXC_CATCH; + break; default: target->debug_reason = DBG_REASON_UNDEFINED; break; diff --git a/src/target/target.c b/src/target/target.c index 9955a5655..1f8e0bfc3 100644 --- a/src/target/target.c +++ b/src/target/target.c @@ -251,6 +251,7 @@ static const Jim_Nvp nvp_target_debug_reason[] = { { .name = "single-step" , .value = DBG_REASON_SINGLESTEP }, { .name = "target-not-halted" , .value = DBG_REASON_NOTHALTED }, { .name = "program-exit" , .value = DBG_REASON_EXIT }, + { .name = "exception-catch" , .value = DBG_REASON_EXC_CATCH }, { .name = "undefined" , .value = DBG_REASON_UNDEFINED }, { .name = NULL, .value = -1 }, }; diff --git a/src/target/target.h b/src/target/target.h index 36b131aa9..794ee833e 100644 --- a/src/target/target.h +++ b/src/target/target.h @@ -84,7 +84,8 @@ enum target_debug_reason { DBG_REASON_SINGLESTEP = 4, DBG_REASON_NOTHALTED = 5, DBG_REASON_EXIT = 6, - DBG_REASON_UNDEFINED = 7, + DBG_REASON_EXC_CATCH = 7, + DBG_REASON_UNDEFINED = 8, }; enum target_endianness { From 45d90aa380b9ae19029af8759894e1fa4afa3adf Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Wed, 7 Nov 2018 17:55:43 +0100 Subject: [PATCH 16/70] gdb_server: remove warning for stepi after gdb_sync The command "gdb_sync" is used to resynchronize gdb with OpenOCD. It is supposed to be follow by the gdb command "stepi" that will be ignored by OpenOCD. Don't annoy the user with a warning message when the stepi command is ignored, but simply log a debug message. Change-Id: Ie4cffa89e761d7335e5961900b62e31f209d4b1b Signed-off-by: Antonio Borneo Reviewed-on: http://openocd.zylin.com/4764 Tested-by: jenkins Reviewed-by: Spencer Oliver --- src/server/gdb_server.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/server/gdb_server.c b/src/server/gdb_server.c index ef2ead44f..6047a4820 100644 --- a/src/server/gdb_server.c +++ b/src/server/gdb_server.c @@ -2850,7 +2850,7 @@ static bool gdb_handle_vcont_packet(struct connection *connection, const char *p if (gdb_connection->sync) { gdb_connection->sync = false; if (ct->state == TARGET_HALTED) { - LOG_WARNING("stepi ignored. GDB will now fetch the register state " \ + LOG_DEBUG("stepi ignored. GDB will now fetch the register state " \ "from the target."); gdb_sig_halted(connection); log_remove_callback(gdb_log_callback, connection); @@ -3234,7 +3234,7 @@ static int gdb_input_inner(struct connection *connection) * make only the single stepping have the sync feature... */ nostep = true; - LOG_WARNING("stepi ignored. GDB will now fetch the register state " \ + LOG_DEBUG("stepi ignored. GDB will now fetch the register state " \ "from the target."); } gdb_con->sync = false; From 4db695c66c9240232a0c7a4af494657ea0e18da5 Mon Sep 17 00:00:00 2001 From: Diego Herranz Date: Wed, 13 Feb 2019 08:33:17 +0000 Subject: [PATCH 17/70] src/jtag/drivers/ftdi: fix swd pin comment and links - TDI/DO is not pin 2 and in fact, we don't even need to mention which pin number it is. "TDI/DO pin" is descriptive enough. - FT2232D link didn't work anymore. It could have been updated to the current working FT2232D link but changed to link the FT2232H instead which is the latest generation and the most commonly used these days. - Taking advantage of the change, link to the MPSSE document updated. It still worked but through a redirection, so updated just in case the redirection stops working. Change-Id: Ia7d01bbcac2158026831edb010a6b50f58351e42 Signed-off-by: Diego Herranz Reviewed-on: http://openocd.zylin.com/4908 Tested-by: jenkins Reviewed-by: Andreas Fritiofson --- src/jtag/drivers/ftdi.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/jtag/drivers/ftdi.c b/src/jtag/drivers/ftdi.c index b709d28da..e7f3c3dce 100644 --- a/src/jtag/drivers/ftdi.c +++ b/src/jtag/drivers/ftdi.c @@ -53,11 +53,11 @@ * * This code uses information contained in the MPSSE specification which was * found here: - * http://www.ftdichip.com/Documents/AppNotes/AN2232C-01_MPSSE_Cmnd.pdf + * https://www.ftdichip.com/Support/Documents/AppNotes/AN2232C-01_MPSSE_Cmnd.pdf * Hereafter this is called the "MPSSE Spec". * - * The datasheet for the ftdichip.com's FT2232D part is here: - * http://www.ftdichip.com/Documents/DataSheets/DS_FT2232D.pdf + * The datasheet for the ftdichip.com's FT2232H part is here: + * https://www.ftdichip.com/Support/Documents/DataSheets/ICs/DS_FT2232H.pdf * * Also note the issue with code 0x4b (clock data to TMS) noted in * http://developer.intra2net.com/mailarchive/html/libftdi/2009/msg00292.html @@ -1055,7 +1055,7 @@ static void ftdi_swd_swdio_en(bool enable) if (oe->data_mask) ftdi_set_signal(oe, enable ? '1' : '0'); else { - /* Sets TDI/DO pin (pin 2) to input during rx when both pins are connected + /* Sets TDI/DO pin to input during rx when both pins are connected to SWDIO */ if (enable) direction |= jtag_direction_init & 0x0002U; From 334c5096eb4f6cb82de3a48fe678f6dff4c7e9d3 Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Sat, 16 Feb 2019 00:23:25 +0100 Subject: [PATCH 18/70] gdb_server: fix 'null' pointer passed as 'nonnull' parameter The null pointer used as second parameter to gdb_put_packet() is passed as second parameter to the memcpy() in line 408 of gdb_put_packet_inner(). In this case memcpy() does not segfault because also the parameter length is zero. Nevertheless, the prototype of memcpy() requires a nonnull pointer. Fixed by passing an empty string in place of the null pointer. Issue highlighted by clang 7.0.0 with warning message: "Null pointer passed as an argument to a 'nonnull' parameter" Change-Id: Ib3dde95d76fcc5fb245ee2d6669e5535d0e0b127 Signed-off-by: Antonio Borneo Reviewed-on: http://openocd.zylin.com/4946 Tested-by: jenkins Reviewed-by: Tomas Vanek --- src/server/gdb_server.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/server/gdb_server.c b/src/server/gdb_server.c index 6047a4820..54cf9aff8 100644 --- a/src/server/gdb_server.c +++ b/src/server/gdb_server.c @@ -1437,7 +1437,7 @@ static int gdb_read_memory_packet(struct connection *connection, if (!len) { LOG_WARNING("invalid read memory packet received (len == 0)"); - gdb_put_packet(connection, NULL, 0); + gdb_put_packet(connection, "", 0); return ERROR_OK; } @@ -3337,7 +3337,7 @@ static int gdb_input_inner(struct connection *connection) default: /* ignore unknown packets */ LOG_DEBUG("ignoring 0x%2.2x packet", packet[0]); - gdb_put_packet(connection, NULL, 0); + gdb_put_packet(connection, "", 0); break; } From 79a859413038c85f084ec1e91c90d2a85344ea2f Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Sun, 24 Feb 2019 18:19:44 +0100 Subject: [PATCH 19/70] stlink: remove unused assignment Fix a warning identified by clang 7.0.1: stlink_usb.c:1092:3: warning: Value stored to 'p' is never read p += sprintf(p, "S%d", swim); ^ ~~~~~~~~~~~~~~~~~~~~~~~ Change-Id: Ic9da57e19ceecb0e3d65d3ea3412a05e1c2c779a Signed-off-by: Antonio Borneo Reviewed-on: http://openocd.zylin.com/4945 Tested-by: jenkins Reviewed-by: Tomas Vanek --- src/jtag/drivers/stlink_usb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/jtag/drivers/stlink_usb.c b/src/jtag/drivers/stlink_usb.c index 1a3cc6154..a9ee44d92 100644 --- a/src/jtag/drivers/stlink_usb.c +++ b/src/jtag/drivers/stlink_usb.c @@ -1002,7 +1002,7 @@ static int stlink_usb_version(void *handle) if (bridge) p += sprintf(p, "B%d", bridge); if (swim || !msd) - p += sprintf(p, "S%d", swim); + sprintf(p, "S%d", swim); LOG_INFO("STLINK %s (API v%d) VID:PID %04X:%04X", v_str, From d470b84b51c89ecbc541081cc2cfa1744437dfa3 Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Tue, 26 Feb 2019 09:32:04 +0100 Subject: [PATCH 20/70] helper/command: return proper JIM error code The function command_unknown() is expected to return a value recognized as JIM error code, as it is correctly done in the other cases it returns. Fix the only case in which command_unknown() does not return a JIM error code, by s/ERROR_FAIL/JIM_ERR/ Change-Id: Ib98b75755ae36870bd68c17f8839ddbfa06c6312 Signed-off-by: Antonio Borneo Reviewed-on: http://openocd.zylin.com/4973 Tested-by: jenkins Reviewed-by: Tomas Vanek --- src/helper/command.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/helper/command.c b/src/helper/command.c index 0afbe2ccf..7a3c2d4fe 100644 --- a/src/helper/command.c +++ b/src/helper/command.c @@ -1037,7 +1037,7 @@ static int command_unknown(Jim_Interp *interp, int argc, Jim_Obj *const *argv) /* pass the command through to the intended handler */ if (c->jim_handler) { if (!command_can_run(cmd_ctx, c)) - return ERROR_FAIL; + return JIM_ERR; interp->cmdPrivData = c->jim_handler_data; return (*c->jim_handler)(interp, count, start); From f426d8dd33797a504f118933c8ff658e5c080809 Mon Sep 17 00:00:00 2001 From: Marc Schink Date: Tue, 26 Feb 2019 13:27:23 +0100 Subject: [PATCH 21/70] target: Remove unused variable 'has_percent' Change-Id: Ib080fc33e8a0305990ee334019547e7643c446ac Signed-off-by: Marc Schink Reviewed-on: http://openocd.zylin.com/4949 Tested-by: jenkins Reviewed-by: Tomas Vanek --- src/target/target.h | 1 - 1 file changed, 1 deletion(-) diff --git a/src/target/target.h b/src/target/target.h index 794ee833e..48793da6e 100644 --- a/src/target/target.h +++ b/src/target/target.h @@ -291,7 +291,6 @@ struct target_event_action { enum target_event event; struct Jim_Interp *interp; struct Jim_Obj *body; - int has_percent; struct target_event_action *next; }; From 351ef7bf3cce048ec854c8d19d8af5aa2b97c3a9 Mon Sep 17 00:00:00 2001 From: Marc Schink Date: Tue, 26 Feb 2019 13:40:23 +0100 Subject: [PATCH 22/70] target/cortex_m: Use 'bool' instead of 'int' Change-Id: I273d24997e2c844015e144a15981f8f0af522261 Signed-off-by: Marc Schink Reviewed-on: http://openocd.zylin.com/4950 Tested-by: jenkins Reviewed-by: Antonio Borneo --- src/target/cortex_m.c | 12 ++++++------ src/target/cortex_m.h | 6 +++--- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/target/cortex_m.c b/src/target/cortex_m.c index d751fd854..4bada398d 100644 --- a/src/target/cortex_m.c +++ b/src/target/cortex_m.c @@ -265,7 +265,7 @@ static int cortex_m_endreset_event(struct target *target) return retval; } - cortex_m->fpb_enabled = 1; + cortex_m->fpb_enabled = true; /* Restore FPB registers */ for (i = 0; i < cortex_m->fp_num_code + cortex_m->fp_num_lit; i++) { @@ -1180,7 +1180,7 @@ int cortex_m_set_breakpoint(struct target *target, struct breakpoint *breakpoint LOG_ERROR("Unhandled Cortex-M Flash Patch Breakpoint architecture revision"); return ERROR_FAIL; } - comparator_list[fp_num].used = 1; + comparator_list[fp_num].used = true; comparator_list[fp_num].fpcr_value = fpcr_value; target_write_u32(target, comparator_list[fp_num].fpcr_address, comparator_list[fp_num].fpcr_value); @@ -1195,7 +1195,7 @@ int cortex_m_set_breakpoint(struct target *target, struct breakpoint *breakpoint return retval; } - cortex_m->fpb_enabled = 1; + cortex_m->fpb_enabled = true; } } else if (breakpoint->type == BKPT_SOFT) { uint8_t code[4]; @@ -1254,7 +1254,7 @@ int cortex_m_unset_breakpoint(struct target *target, struct breakpoint *breakpoi LOG_DEBUG("Invalid FP Comparator number in breakpoint"); return ERROR_OK; } - comparator_list[fp_num].used = 0; + comparator_list[fp_num].used = false; comparator_list[fp_num].fpcr_value = 0; target_write_u32(target, comparator_list[fp_num].fpcr_address, comparator_list[fp_num].fpcr_value); @@ -1351,7 +1351,7 @@ int cortex_m_set_watchpoint(struct target *target, struct watchpoint *watchpoint LOG_ERROR("Can not find free DWT Comparator"); return ERROR_FAIL; } - comparator->used = 1; + comparator->used = true; watchpoint->set = dwt_num + 1; comparator->comp = watchpoint->address; @@ -1408,7 +1408,7 @@ int cortex_m_unset_watchpoint(struct target *target, struct watchpoint *watchpoi } comparator = cortex_m->dwt_comparator_list + dwt_num; - comparator->used = 0; + comparator->used = false; comparator->function = 0; target_write_u32(target, comparator->dwt_comparator_address + 8, comparator->function); diff --git a/src/target/cortex_m.h b/src/target/cortex_m.h index 22d9735e5..b375d1111 100644 --- a/src/target/cortex_m.h +++ b/src/target/cortex_m.h @@ -136,14 +136,14 @@ #define FPCR_REPLACE_BKPT_BOTH (3 << 30) struct cortex_m_fp_comparator { - int used; + bool used; int type; uint32_t fpcr_value; uint32_t fpcr_address; }; struct cortex_m_dwt_comparator { - int used; + bool used; uint32_t comp; uint32_t mask; uint32_t function; @@ -174,7 +174,7 @@ struct cortex_m_common { int fp_num_code; int fp_code_available; int fp_rev; - int fpb_enabled; + bool fpb_enabled; struct cortex_m_fp_comparator *fp_comparator_list; /* Data Watchpoint and Trace (DWT) */ From 92f51c50ae41732ba287ea8ee4a4cdeb54e313ee Mon Sep 17 00:00:00 2001 From: Marc Schink Date: Tue, 26 Feb 2019 14:00:30 +0100 Subject: [PATCH 23/70] target/register: Use 'bool' data type Change-Id: I3633ced9cb2bfe6afb0ef49aa42fd1b54f155a66 Signed-off-by: Marc Schink Reviewed-on: http://openocd.zylin.com/4951 Tested-by: jenkins Reviewed-by: Antonio Borneo --- src/target/register.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/target/register.c b/src/target/register.c index 850641448..5352d2f21 100644 --- a/src/target/register.c +++ b/src/target/register.c @@ -88,8 +88,8 @@ void register_cache_invalidate(struct reg_cache *cache) for (unsigned n = cache->num_regs; n != 0; n--, reg++) { if (reg->exist == false) continue; - reg->valid = 0; - reg->dirty = 0; + reg->valid = false; + reg->dirty = false; } } @@ -100,8 +100,8 @@ static int register_get_dummy_core_reg(struct reg *reg) static int register_set_dummy_core_reg(struct reg *reg, uint8_t *buf) { - reg->dirty = 1; - reg->valid = 1; + reg->dirty = true; + reg->valid = true; return ERROR_OK; } From de58a6d1b7407afe92a4d1b6e62b7fa886426443 Mon Sep 17 00:00:00 2001 From: Marc Schink Date: Tue, 26 Feb 2019 14:01:17 +0100 Subject: [PATCH 24/70] target/armv4_5: Use 'bool' data type Change-Id: I82e3963ea662844bb96943aee849dab35ea96bb3 Signed-off-by: Marc Schink Reviewed-on: http://openocd.zylin.com/4952 Tested-by: jenkins Reviewed-by: Antonio Borneo --- src/target/armv4_5.c | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/src/target/armv4_5.c b/src/target/armv4_5.c index 30aeb43bb..e16a9ecea 100644 --- a/src/target/armv4_5.c +++ b/src/target/armv4_5.c @@ -434,8 +434,8 @@ void arm_set_cpsr(struct arm *arm, uint32_t cpsr) */ if (arm->cpsr) { buf_set_u32(arm->cpsr->value, 0, 32, cpsr); - arm->cpsr->valid = 1; - arm->cpsr->dirty = 0; + arm->cpsr->valid = true; + arm->cpsr->dirty = false; } arm->core_mode = mode; @@ -526,7 +526,7 @@ static struct reg_feature arm_gdb_dummy_fp_features = { struct reg arm_gdb_dummy_fp_reg = { .name = "GDB dummy FPA register", .value = (uint8_t *) arm_gdb_dummy_fp_value, - .valid = 1, + .valid = true, .size = 96, .exist = false, .number = 16, @@ -543,7 +543,7 @@ static const uint8_t arm_gdb_dummy_fps_value[4]; struct reg arm_gdb_dummy_fps_reg = { .name = "GDB dummy FPA status register", .value = (uint8_t *) arm_gdb_dummy_fps_value, - .valid = 1, + .valid = true, .size = 32, .exist = false, .number = 24, @@ -573,8 +573,8 @@ static int armv4_5_get_core_reg(struct reg *reg) retval = reg_arch_info->arm->read_core_reg(target, reg, reg_arch_info->num, reg_arch_info->mode); if (retval == ERROR_OK) { - reg->valid = 1; - reg->dirty = 0; + reg->valid = true; + reg->dirty = false; } return retval; @@ -619,9 +619,9 @@ static int armv4_5_set_core_reg(struct reg *reg, uint8_t *buf) value = buf_get_u32(buf + 4, 0, 32); buf_set_u32(reg->value + 4, 0, 32, value); } - reg->valid = 1; + reg->valid = true; } - reg->dirty = 1; + reg->dirty = true; return ERROR_OK; } @@ -1399,8 +1399,8 @@ int armv4_5_run_algorithm_inner(struct target *target, arm_algorithm_info->core_mode); buf_set_u32(arm->cpsr->value, 0, 5, arm_algorithm_info->core_mode); - arm->cpsr->dirty = 1; - arm->cpsr->valid = 1; + arm->cpsr->dirty = true; + arm->cpsr->valid = true; } /* terminate using a hardware or (ARMv5+) software breakpoint */ @@ -1470,14 +1470,14 @@ int armv4_5_run_algorithm_inner(struct target *target, buf_set_u32(ARMV4_5_CORE_REG_MODE(arm->core_cache, arm_algorithm_info->core_mode, i).value, 0, 32, context[i]); ARMV4_5_CORE_REG_MODE(arm->core_cache, arm_algorithm_info->core_mode, - i).valid = 1; + i).valid = true; ARMV4_5_CORE_REG_MODE(arm->core_cache, arm_algorithm_info->core_mode, - i).dirty = 1; + i).dirty = true; } } arm_set_cpsr(arm, cpsr); - arm->cpsr->dirty = 1; + arm->cpsr->dirty = true; arm->core_state = core_state; From ae02b84cf8248623e165561f99065b850218a229 Mon Sep 17 00:00:00 2001 From: Marc Schink Date: Tue, 26 Feb 2019 14:02:33 +0100 Subject: [PATCH 25/70] target/armv7_9_common: Use 'bool' data type Change-Id: I5af27247f39cf47c925260784e21292f34665471 Signed-off-by: Marc Schink Reviewed-on: http://openocd.zylin.com/4953 Tested-by: jenkins Reviewed-by: Antonio Borneo --- src/target/arm7_9_common.c | 68 +++++++++++++++++++------------------- 1 file changed, 34 insertions(+), 34 deletions(-) diff --git a/src/target/arm7_9_common.c b/src/target/arm7_9_common.c index 96e31b9d3..c6a8a26d8 100644 --- a/src/target/arm7_9_common.c +++ b/src/target/arm7_9_common.c @@ -1141,20 +1141,20 @@ int arm7_9_soft_reset_halt(struct target *target) cpsr &= ~0xff; cpsr |= 0xd3; arm_set_cpsr(arm, cpsr); - arm->cpsr->dirty = 1; + arm->cpsr->dirty = true; /* start fetching from 0x0 */ buf_set_u32(arm->pc->value, 0, 32, 0x0); - arm->pc->dirty = 1; - arm->pc->valid = 1; + arm->pc->dirty = true; + arm->pc->valid = true; /* reset registers */ for (i = 0; i <= 14; i++) { struct reg *r = arm_reg_current(arm, i); buf_set_u32(r->value, 0, 32, 0xffffffff); - r->dirty = 1; - r->valid = 1; + r->dirty = true; + r->valid = true; } retval = target_call_event_callbacks(target, TARGET_EVENT_HALTED); @@ -1346,7 +1346,7 @@ static int arm7_9_debug_entry(struct target *target) buf_set_u32(r->value, 0, 32, context[i]); /* r0 and r15 (pc) have to be restored later */ r->dirty = (i == 0) || (i == 15); - r->valid = 1; + r->valid = true; } LOG_DEBUG("entered debug state at PC 0x%" PRIx32 "", context[15]); @@ -1359,8 +1359,8 @@ static int arm7_9_debug_entry(struct target *target) if (retval != ERROR_OK) return retval; buf_set_u32(arm->spsr->value, 0, 32, spsr); - arm->spsr->dirty = 0; - arm->spsr->valid = 1; + arm->spsr->dirty = false; + arm->spsr->valid = true; } retval = jtag_execute_queue(); @@ -1411,13 +1411,13 @@ static int arm7_9_full_context(struct target *target) uint32_t mask = 0; uint32_t *reg_p[16]; int j; - int valid = 1; + bool valid = true; /* check if there are invalid registers in the current mode */ for (j = 0; j <= 16; j++) { - if (ARMV4_5_CORE_REG_MODE(arm->core_cache, armv4_5_number_to_mode(i), j).valid == 0) - valid = 0; + if (!ARMV4_5_CORE_REG_MODE(arm->core_cache, armv4_5_number_to_mode(i), j).valid) + valid = false; } if (!valid) { @@ -1431,8 +1431,8 @@ static int arm7_9_full_context(struct target *target) arm7_9->write_xpsr_im8(target, tmp_cpsr & 0xff, 0, 0); for (j = 0; j < 15; j++) { - if (ARMV4_5_CORE_REG_MODE(arm->core_cache, - armv4_5_number_to_mode(i), j).valid == 0) { + if (!ARMV4_5_CORE_REG_MODE(arm->core_cache, + armv4_5_number_to_mode(i), j).valid) { reg_p[j] = (uint32_t *)ARMV4_5_CORE_REG_MODE( arm->core_cache, armv4_5_number_to_mode(i), @@ -1440,10 +1440,10 @@ static int arm7_9_full_context(struct target *target) mask |= 1 << j; ARMV4_5_CORE_REG_MODE(arm->core_cache, armv4_5_number_to_mode(i), - j).valid = 1; + j).valid = true; ARMV4_5_CORE_REG_MODE(arm->core_cache, armv4_5_number_to_mode(i), - j).dirty = 0; + j).dirty = false; } } @@ -1452,15 +1452,15 @@ static int arm7_9_full_context(struct target *target) arm7_9->read_core_regs(target, mask, reg_p); /* check if the PSR has to be read */ - if (ARMV4_5_CORE_REG_MODE(arm->core_cache, armv4_5_number_to_mode(i), - 16).valid == 0) { + if (!ARMV4_5_CORE_REG_MODE(arm->core_cache, armv4_5_number_to_mode(i), + 16).valid) { arm7_9->read_xpsr(target, (uint32_t *)ARMV4_5_CORE_REG_MODE(arm->core_cache, armv4_5_number_to_mode(i), 16).value, 1); ARMV4_5_CORE_REG_MODE(arm->core_cache, armv4_5_number_to_mode(i), - 16).valid = 1; + 16).valid = true; ARMV4_5_CORE_REG_MODE(arm->core_cache, armv4_5_number_to_mode(i), - 16).dirty = 0; + 16).dirty = false; } } } @@ -1494,7 +1494,7 @@ static int arm7_9_restore_context(struct target *target) struct reg *reg; enum arm_mode current_mode = arm->core_mode; int i, j; - int dirty; + bool dirty; int mode_change; LOG_DEBUG("-"); @@ -1518,15 +1518,15 @@ static int arm7_9_restore_context(struct target *target) for (i = 0; i < 6; i++) { LOG_DEBUG("examining %s mode", arm_mode_name(arm->core_mode)); - dirty = 0; + dirty = false; mode_change = 0; /* check if there are dirty registers in the current mode */ for (j = 0; j <= 16; j++) { reg = &ARMV4_5_CORE_REG_MODE(arm->core_cache, armv4_5_number_to_mode(i), j); - if (reg->dirty == 1) { - if (reg->valid == 1) { - dirty = 1; + if (reg->dirty) { + if (reg->valid) { + dirty = true; LOG_DEBUG("examining dirty reg: %s", reg->name); struct arm_reg *reg_arch_info; reg_arch_info = reg->arch_info; @@ -1567,12 +1567,12 @@ static int arm7_9_restore_context(struct target *target) armv4_5_number_to_mode(i), j); - if (reg->dirty == 1) { + if (reg->dirty) { regs[j] = buf_get_u32(reg->value, 0, 32); mask |= 1 << j; num_regs++; - reg->dirty = 0; - reg->valid = 1; + reg->dirty = false; + reg->valid = true; LOG_DEBUG("writing register %i mode %s " "with value 0x%8.8" PRIx32, j, arm_mode_name(arm->core_mode), @@ -1614,15 +1614,15 @@ static int arm7_9_restore_context(struct target *target) arm7_9->write_xpsr(target, buf_get_u32(arm->cpsr->value, 0, 32) & ~0x20, 0); - arm->cpsr->dirty = 0; - arm->cpsr->valid = 1; + arm->cpsr->dirty = false; + arm->cpsr->valid = true; } /* restore PC */ LOG_DEBUG("writing PC with value 0x%8.8" PRIx32, buf_get_u32(arm->pc->value, 0, 32)); arm7_9->write_pc(target, buf_get_u32(arm->pc->value, 0, 32)); - arm->pc->dirty = 0; + arm->pc->dirty = false; return ERROR_OK; } @@ -2024,8 +2024,8 @@ static int arm7_9_read_core_reg(struct target *target, struct reg *r, if (retval != ERROR_OK) return retval; - r->valid = 1; - r->dirty = 0; + r->valid = true; + r->dirty = false; buf_set_u32(r->value, 0, 32, value); if ((mode != ARM_MODE_ANY) && (mode != arm->core_mode) @@ -2081,8 +2081,8 @@ static int arm7_9_write_core_reg(struct target *target, struct reg *r, arm7_9->write_xpsr(target, t, spsr); } - r->valid = 1; - r->dirty = 0; + r->valid = true; + r->dirty = false; if ((mode != ARM_MODE_ANY) && (mode != arm->core_mode) && (areg->mode != ARM_MODE_ANY)) { From 31a3e353489ab8a16e2251d4f41402ce15d1bb37 Mon Sep 17 00:00:00 2001 From: Marc Schink Date: Tue, 26 Feb 2019 14:02:59 +0100 Subject: [PATCH 26/70] target/arm11: Use 'bool' data type Change-Id: Ia09adeab88eaf66c009f94be25ab82b0b8f88f61 Signed-off-by: Marc Schink Reviewed-on: http://openocd.zylin.com/4954 Tested-by: jenkins Reviewed-by: Antonio Borneo --- src/target/arm11.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/target/arm11.c b/src/target/arm11.c index 443866149..159c30a85 100644 --- a/src/target/arm11.c +++ b/src/target/arm11.c @@ -442,8 +442,8 @@ static uint32_t arm11_nextpc(struct arm11_common *arm11, int current, uint32_t a } buf_set_u32(value, 0, 32, address); - arm11->arm.pc->dirty = 1; - arm11->arm.pc->valid = 1; + arm11->arm.pc->dirty = true; + arm11->arm.pc->valid = true; return address; } From 8c8c93c185f9cce51855bf2d495fd2aaec16d6c1 Mon Sep 17 00:00:00 2001 From: Marc Schink Date: Tue, 26 Feb 2019 14:03:27 +0100 Subject: [PATCH 27/70] target/armv7m: Use 'bool' data type Change-Id: I9cfbba9d81601cc72e2b54ec410e21c7edc4f1c4 Signed-off-by: Marc Schink Reviewed-on: http://openocd.zylin.com/4955 Tested-by: jenkins Reviewed-by: Antonio Borneo --- src/target/armv7m.c | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/src/target/armv7m.c b/src/target/armv7m.c index ef00b9427..3d73b2954 100644 --- a/src/target/armv7m.c +++ b/src/target/armv7m.c @@ -205,8 +205,8 @@ static int armv7m_set_core_reg(struct reg *reg, uint8_t *buf) return ERROR_TARGET_NOT_HALTED; buf_cpy(buf, reg->value, reg->size); - reg->dirty = 1; - reg->valid = 1; + reg->dirty = true; + reg->valid = true; return ERROR_OK; } @@ -244,8 +244,8 @@ static int armv7m_read_core_reg(struct target *target, struct reg *r, buf_set_u32(armv7m->arm.core_cache->reg_list[num].value, 0, 32, reg_value); } - armv7m->arm.core_cache->reg_list[num].valid = 1; - armv7m->arm.core_cache->reg_list[num].dirty = 0; + armv7m->arm.core_cache->reg_list[num].valid = true; + armv7m->arm.core_cache->reg_list[num].dirty = false; return retval; } @@ -283,8 +283,8 @@ static int armv7m_write_core_reg(struct target *target, struct reg *r, goto out_error; } - armv7m->arm.core_cache->reg_list[num].valid = 1; - armv7m->arm.core_cache->reg_list[num].dirty = 0; + armv7m->arm.core_cache->reg_list[num].valid = true; + armv7m->arm.core_cache->reg_list[num].dirty = false; return ERROR_OK; @@ -424,8 +424,8 @@ int armv7m_start_algorithm(struct target *target, */ struct reg *reg = &armv7m->arm.core_cache->reg_list[ARMV7M_xPSR]; buf_set_u32(reg->value, 0, 32, 0x01000000); - reg->valid = 1; - reg->dirty = 1; + reg->valid = true; + reg->dirty = true; } if (armv7m_algorithm_info->core_mode != ARM_MODE_ANY && @@ -440,8 +440,8 @@ int armv7m_start_algorithm(struct target *target, LOG_DEBUG("setting core_mode: 0x%2.2x", armv7m_algorithm_info->core_mode); buf_set_u32(armv7m->arm.core_cache->reg_list[ARMV7M_CONTROL].value, 0, 1, armv7m_algorithm_info->core_mode); - armv7m->arm.core_cache->reg_list[ARMV7M_CONTROL].dirty = 1; - armv7m->arm.core_cache->reg_list[ARMV7M_CONTROL].valid = 1; + armv7m->arm.core_cache->reg_list[ARMV7M_CONTROL].dirty = true; + armv7m->arm.core_cache->reg_list[ARMV7M_CONTROL].valid = true; } /* save previous core mode */ @@ -535,8 +535,8 @@ int armv7m_wait_algorithm(struct target *target, armv7m_algorithm_info->context[i]); buf_set_u32(armv7m->arm.core_cache->reg_list[i].value, 0, 32, armv7m_algorithm_info->context[i]); - armv7m->arm.core_cache->reg_list[i].valid = 1; - armv7m->arm.core_cache->reg_list[i].dirty = 1; + armv7m->arm.core_cache->reg_list[i].valid = true; + armv7m->arm.core_cache->reg_list[i].dirty = true; } } @@ -545,8 +545,8 @@ int armv7m_wait_algorithm(struct target *target, LOG_DEBUG("restoring core_mode: 0x%2.2x", armv7m_algorithm_info->core_mode); buf_set_u32(armv7m->arm.core_cache->reg_list[ARMV7M_CONTROL].value, 0, 1, armv7m_algorithm_info->core_mode); - armv7m->arm.core_cache->reg_list[ARMV7M_CONTROL].dirty = 1; - armv7m->arm.core_cache->reg_list[ARMV7M_CONTROL].valid = 1; + armv7m->arm.core_cache->reg_list[ARMV7M_CONTROL].dirty = true; + armv7m->arm.core_cache->reg_list[ARMV7M_CONTROL].valid = true; } armv7m->arm.core_mode = armv7m_algorithm_info->core_mode; @@ -619,8 +619,8 @@ struct reg_cache *armv7m_build_reg_cache(struct target *target) if (storage_size < 4) storage_size = 4; reg_list[i].value = calloc(1, storage_size); - reg_list[i].dirty = 0; - reg_list[i].valid = 0; + reg_list[i].dirty = false; + reg_list[i].valid = false; reg_list[i].type = &armv7m_reg_type; reg_list[i].arch_info = &arch_info[i]; From 093f9d1c8538c2b31fefbb3391c40021cdeb2e47 Mon Sep 17 00:00:00 2001 From: Marc Schink Date: Tue, 26 Feb 2019 14:03:49 +0100 Subject: [PATCH 28/70] target/armv8: Use 'bool' data type Change-Id: I65def33f24187ab336db5732ce35200ca5cd8f5f Signed-off-by: Marc Schink Reviewed-on: http://openocd.zylin.com/4956 Tested-by: jenkins Reviewed-by: Antonio Borneo --- src/target/armv8.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/target/armv8.c b/src/target/armv8.c index 76a2d98af..c8cfcae20 100644 --- a/src/target/armv8.c +++ b/src/target/armv8.c @@ -678,8 +678,8 @@ void armv8_set_cpsr(struct arm *arm, uint32_t cpsr) */ if (arm->cpsr) { buf_set_u32(arm->cpsr->value, 0, 32, cpsr); - arm->cpsr->valid = 1; - arm->cpsr->dirty = 0; + arm->cpsr->valid = true; + arm->cpsr->dirty = false; } /* Older ARMs won't have the J bit */ @@ -1518,17 +1518,17 @@ static int armv8_set_core_reg(struct reg *reg, uint8_t *buf) armv8_set_cpsr(arm, (uint32_t)value); else { buf_set_u64(reg->value, 0, reg->size, value); - reg->valid = 1; + reg->valid = true; } } else if (reg->size <= 128) { uint64_t hvalue = buf_get_u64(buf + 8, 0, reg->size - 64); buf_set_u64(reg->value, 0, 64, value); buf_set_u64(reg->value + 8, 0, reg->size - 64, hvalue); - reg->valid = 1; + reg->valid = true; } - reg->dirty = 1; + reg->dirty = true; return ERROR_OK; } @@ -1585,11 +1585,11 @@ static int armv8_set_core_reg32(struct reg *reg, uint8_t *buf) uint64_t value64 = buf_get_u64(buf, 0, 64); buf_set_u64(reg->value, 0, 64, value64); } - reg->valid = 1; - reg64->valid = 1; + reg->valid = true; + reg64->valid = true; } - reg64->dirty = 1; + reg64->dirty = true; return ERROR_OK; } From 7779c8f7ac26d91f92e71b9a55bbbbb0963ec022 Mon Sep 17 00:00:00 2001 From: Marc Schink Date: Tue, 26 Feb 2019 14:04:46 +0100 Subject: [PATCH 29/70] target/aarch64: Use 'bool' data type Change-Id: Ibfe4413b88ed0759a556a8777dac40f0c2c64922 Signed-off-by: Marc Schink Reviewed-on: http://openocd.zylin.com/4957 Tested-by: jenkins Reviewed-by: Antonio Borneo --- src/target/aarch64.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/target/aarch64.c b/src/target/aarch64.c index c9cedea82..1fafcfd45 100644 --- a/src/target/aarch64.c +++ b/src/target/aarch64.c @@ -601,8 +601,8 @@ static int aarch64_restore_one(struct target *target, int current, } LOG_DEBUG("resume pc = 0x%016" PRIx64, resume_pc); buf_set_u64(arm->pc->value, 0, 64, resume_pc); - arm->pc->dirty = 1; - arm->pc->valid = 1; + arm->pc->dirty = true; + arm->pc->valid = true; /* called it now before restoring context because it uses cpu * register r0 for restoring system control register */ From 7fafb3e96110a7712bb08611c57b14d64550fa0f Mon Sep 17 00:00:00 2001 From: Marc Schink Date: Tue, 26 Feb 2019 14:05:22 +0100 Subject: [PATCH 30/70] target/arm720t: Use 'bool' data type Change-Id: I9838d0d0ba472f029169ab37597ef367a6084fbf Signed-off-by: Marc Schink Reviewed-on: http://openocd.zylin.com/4958 Tested-by: jenkins Reviewed-by: Antonio Borneo --- src/target/arm720t.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/target/arm720t.c b/src/target/arm720t.c index 3d12aba22..b592ffc47 100644 --- a/src/target/arm720t.c +++ b/src/target/arm720t.c @@ -365,12 +365,12 @@ static int arm720t_soft_reset_halt(struct target *target) cpsr &= ~0xff; cpsr |= 0xd3; arm_set_cpsr(arm, cpsr); - arm->cpsr->dirty = 1; + arm->cpsr->dirty = true; /* start fetching from 0x0 */ buf_set_u32(arm->pc->value, 0, 32, 0x0); - arm->pc->dirty = 1; - arm->pc->valid = 1; + arm->pc->dirty = true; + arm->pc->valid = true; retval = arm720t_disable_mmu_caches(target, 1, 1, 1); if (retval != ERROR_OK) From fc8885a9c30d720e17381d772df2ea5fb3729924 Mon Sep 17 00:00:00 2001 From: Marc Schink Date: Tue, 26 Feb 2019 14:05:43 +0100 Subject: [PATCH 31/70] target/arm920t: Use 'bool' data type Change-Id: I5f2c95d9a4bdb14cc31d72eb026f58710fb07db5 Signed-off-by: Marc Schink Reviewed-on: http://openocd.zylin.com/4959 Tested-by: jenkins Reviewed-by: Antonio Borneo --- src/target/arm920t.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/target/arm920t.c b/src/target/arm920t.c index 39d75902c..ed9d388a5 100644 --- a/src/target/arm920t.c +++ b/src/target/arm920t.c @@ -283,8 +283,8 @@ static int arm920t_read_cp15_interpreted(struct target *target, return ERROR_FAIL; } - r[0].dirty = 1; - r[1].dirty = 1; + r[0].dirty = true; + r[1].dirty = true; return ERROR_OK; } @@ -327,8 +327,8 @@ int arm920t_write_cp15_interpreted(struct target *target, return ERROR_FAIL; } - r[0].dirty = 1; - r[1].dirty = 1; + r[0].dirty = true; + r[1].dirty = true; return ERROR_OK; } @@ -781,12 +781,12 @@ int arm920t_soft_reset_halt(struct target *target) cpsr &= ~0xff; cpsr |= 0xd3; arm_set_cpsr(arm, cpsr); - arm->cpsr->dirty = 1; + arm->cpsr->dirty = true; /* start fetching from 0x0 */ buf_set_u32(arm->pc->value, 0, 32, 0x0); - arm->pc->dirty = 1; - arm->pc->valid = 1; + arm->pc->dirty = true; + arm->pc->valid = true; arm920t_disable_mmu_caches(target, 1, 1, 1); arm920t->armv4_5_mmu.mmu_enabled = 0; From bc1f5cabc046d36696f5e3b55319e4e1b7a385f9 Mon Sep 17 00:00:00 2001 From: Marc Schink Date: Tue, 26 Feb 2019 14:06:06 +0100 Subject: [PATCH 32/70] target/arm926ejs: Use 'bool' data type Change-Id: I3016a8ba37942d674017c09e4540d9813c832872 Signed-off-by: Marc Schink Reviewed-on: http://openocd.zylin.com/4960 Tested-by: jenkins Reviewed-by: Antonio Borneo --- src/target/arm926ejs.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/target/arm926ejs.c b/src/target/arm926ejs.c index 07c519a53..3f22a8a46 100644 --- a/src/target/arm926ejs.c +++ b/src/target/arm926ejs.c @@ -576,12 +576,12 @@ int arm926ejs_soft_reset_halt(struct target *target) cpsr &= ~0xff; cpsr |= 0xd3; arm_set_cpsr(arm, cpsr); - arm->cpsr->dirty = 1; + arm->cpsr->dirty = true; /* start fetching from 0x0 */ buf_set_u32(arm->pc->value, 0, 32, 0x0); - arm->pc->dirty = 1; - arm->pc->valid = 1; + arm->pc->dirty = true; + arm->pc->valid = true; retval = arm926ejs_disable_mmu_caches(target, 1, 1, 1); if (retval != ERROR_OK) From 5db10c0559c6ae346e93621db5cd6db98bde422d Mon Sep 17 00:00:00 2001 From: Marc Schink Date: Tue, 26 Feb 2019 14:06:44 +0100 Subject: [PATCH 33/70] target/avr32_ap7k: Use 'bool' data type Change-Id: I49f1a6c6ee6d175935eb40b49abf8ebdf56a0b6e Signed-off-by: Marc Schink Reviewed-on: http://openocd.zylin.com/4961 Tested-by: jenkins Reviewed-by: Antonio Borneo --- src/target/avr32_ap7k.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/target/avr32_ap7k.c b/src/target/avr32_ap7k.c index f8da8d5ac..cf08e3ab9 100644 --- a/src/target/avr32_ap7k.c +++ b/src/target/avr32_ap7k.c @@ -110,8 +110,8 @@ static int avr32_read_core_reg(struct target *target, int num) reg_value = ap7k->core_regs[num]; buf_set_u32(ap7k->core_cache->reg_list[num].value, 0, 32, reg_value); - ap7k->core_cache->reg_list[num].valid = 1; - ap7k->core_cache->reg_list[num].dirty = 0; + ap7k->core_cache->reg_list[num].valid = true; + ap7k->core_cache->reg_list[num].dirty = false; return ERROR_OK; } @@ -129,8 +129,8 @@ static int avr32_write_core_reg(struct target *target, int num) reg_value = buf_get_u32(ap7k->core_cache->reg_list[num].value, 0, 32); ap7k->core_regs[num] = reg_value; LOG_DEBUG("write core reg %i value 0x%" PRIx32 "", num, reg_value); - ap7k->core_cache->reg_list[num].valid = 1; - ap7k->core_cache->reg_list[num].dirty = 0; + ap7k->core_cache->reg_list[num].valid = true; + ap7k->core_cache->reg_list[num].dirty = false; return ERROR_OK; } @@ -159,8 +159,8 @@ static int avr32_set_core_reg(struct reg *reg, uint8_t *buf) return ERROR_TARGET_NOT_HALTED; buf_set_u32(reg->value, 0, 32, value); - reg->dirty = 1; - reg->valid = 1; + reg->dirty = true; + reg->valid = true; return ERROR_OK; } @@ -196,8 +196,8 @@ static struct reg_cache *avr32_build_reg_cache(struct target *target) reg_list[i].name = avr32_core_reg_list[i]; reg_list[i].size = 32; reg_list[i].value = calloc(1, 4); - reg_list[i].dirty = 0; - reg_list[i].valid = 0; + reg_list[i].dirty = false; + reg_list[i].valid = false; reg_list[i].type = &avr32_reg_type; reg_list[i].arch_info = &arch_info[i]; } From 8795090edcf7b83e65f07941b0186c63a358c31a Mon Sep 17 00:00:00 2001 From: Marc Schink Date: Tue, 26 Feb 2019 14:08:00 +0100 Subject: [PATCH 34/70] target/cortex_a: Use 'bool' data type Change-Id: I055767f1c20af539159ee59e35de8dd20b399fa4 Signed-off-by: Marc Schink Reviewed-on: http://openocd.zylin.com/4963 Tested-by: jenkins Reviewed-by: Antonio Borneo --- src/target/cortex_a.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/target/cortex_a.c b/src/target/cortex_a.c index 5d5fb9621..e460f3b70 100644 --- a/src/target/cortex_a.c +++ b/src/target/cortex_a.c @@ -806,15 +806,15 @@ static int cortex_a_internal_restore(struct target *target, int current, * C_MASKINTS in parallel with disabled interrupts can cause * local faults to not be taken. */ buf_set_u32(armv7m->core_cache->reg_list[ARMV7M_PRIMASK].value, 0, 32, 1); - armv7m->core_cache->reg_list[ARMV7M_PRIMASK].dirty = 1; - armv7m->core_cache->reg_list[ARMV7M_PRIMASK].valid = 1; + armv7m->core_cache->reg_list[ARMV7M_PRIMASK].dirty = true; + armv7m->core_cache->reg_list[ARMV7M_PRIMASK].valid = true; /* Make sure we are in Thumb mode */ buf_set_u32(armv7m->core_cache->reg_list[ARMV7M_xPSR].value, 0, 32, buf_get_u32(armv7m->core_cache->reg_list[ARMV7M_xPSR].value, 0, 32) | (1 << 24)); - armv7m->core_cache->reg_list[ARMV7M_xPSR].dirty = 1; - armv7m->core_cache->reg_list[ARMV7M_xPSR].valid = 1; + armv7m->core_cache->reg_list[ARMV7M_xPSR].dirty = true; + armv7m->core_cache->reg_list[ARMV7M_xPSR].valid = true; } #endif @@ -848,8 +848,8 @@ static int cortex_a_internal_restore(struct target *target, int current, } LOG_DEBUG("resume pc = 0x%08" PRIx32, resume_pc); buf_set_u32(arm->pc->value, 0, 32, resume_pc); - arm->pc->dirty = 1; - arm->pc->valid = 1; + arm->pc->dirty = true; + arm->pc->valid = true; /* restore dpm_mode at system halt */ arm_dpm_modeswitch(&armv7a->dpm, ARM_MODE_ANY); From 8be87420dbe00fd4d1648f8111e947c08791f22f Mon Sep 17 00:00:00 2001 From: Marc Schink Date: Tue, 26 Feb 2019 14:08:18 +0100 Subject: [PATCH 35/70] target/embeddedice: Use 'bool' data type Change-Id: I0f237e0769786aa560d1a472a71499d3856ab25c Signed-off-by: Marc Schink Reviewed-on: http://openocd.zylin.com/4964 Tested-by: jenkins Reviewed-by: Antonio Borneo --- src/target/embeddedice.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/target/embeddedice.c b/src/target/embeddedice.c index 7232ef1e4..61ee8bbd9 100644 --- a/src/target/embeddedice.c +++ b/src/target/embeddedice.c @@ -205,8 +205,8 @@ struct reg_cache *embeddedice_build_reg_cache(struct target *target, for (i = 0; i < num_regs; i++) { reg_list[i].name = eice_regs[i].name; reg_list[i].size = eice_regs[i].width; - reg_list[i].dirty = 0; - reg_list[i].valid = 0; + reg_list[i].dirty = false; + reg_list[i].valid = false; reg_list[i].value = calloc(1, 4); reg_list[i].arch_info = &arch_info[i]; reg_list[i].type = &eice_reg_type; @@ -470,8 +470,8 @@ void embeddedice_set_reg(struct reg *reg, uint32_t value) embeddedice_write_reg(reg, value); buf_set_u32(reg->value, 0, reg->size, value); - reg->valid = 1; - reg->dirty = 0; + reg->valid = true; + reg->dirty = false; } From 0118dc5e47da98cfd082d1b109ed995dcb779510 Mon Sep 17 00:00:00 2001 From: Marc Schink Date: Tue, 26 Feb 2019 14:08:42 +0100 Subject: [PATCH 36/70] target/arm_semihosting: Use 'bool' data type Change-Id: I05245b7dc9c37ea8e0e40672070fb3e87cb7683f Signed-off-by: Marc Schink Reviewed-on: http://openocd.zylin.com/4965 Tested-by: jenkins Reviewed-by: Antonio Borneo --- src/target/arm_semihosting.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/target/arm_semihosting.c b/src/target/arm_semihosting.c index 9117a7442..61f1e7801 100644 --- a/src/target/arm_semihosting.c +++ b/src/target/arm_semihosting.c @@ -94,12 +94,12 @@ static int post_result(struct target *target) /* return value in R0 */ buf_set_u32(arm->core_cache->reg_list[0].value, 0, 32, target->semihosting->result); - arm->core_cache->reg_list[0].dirty = 1; + arm->core_cache->reg_list[0].dirty = true; /* LR --> PC */ buf_set_u32(arm->core_cache->reg_list[15].value, 0, 32, buf_get_u32(arm_reg_current(arm, 14)->value, 0, 32)); - arm->core_cache->reg_list[15].dirty = 1; + arm->core_cache->reg_list[15].dirty = true; /* saved PSR --> current PSR */ spsr = buf_get_u32(arm->spsr->value, 0, 32); @@ -109,7 +109,7 @@ static int post_result(struct target *target) */ buf_set_u32(arm->cpsr->value, 0, 32, spsr); - arm->cpsr->dirty = 1; + arm->cpsr->dirty = true; arm->core_mode = spsr & 0x1f; if (spsr & 0x20) arm->core_state = ARM_STATE_THUMB; @@ -118,11 +118,11 @@ static int post_result(struct target *target) if (arm->core_state == ARM_STATE_AARCH64) { /* return value in R0 */ buf_set_u64(arm->core_cache->reg_list[0].value, 0, 64, target->semihosting->result); - arm->core_cache->reg_list[0].dirty = 1; + arm->core_cache->reg_list[0].dirty = true; uint64_t pc = buf_get_u64(arm->core_cache->reg_list[32].value, 0, 64); buf_set_u64(arm->pc->value, 0, 64, pc + 4); - arm->pc->dirty = 1; + arm->pc->dirty = true; } } else { /* resume execution, this will be pc+2 to skip over the @@ -130,7 +130,7 @@ static int post_result(struct target *target) /* return result in R0 */ buf_set_u32(arm->core_cache->reg_list[0].value, 0, 32, target->semihosting->result); - arm->core_cache->reg_list[0].dirty = 1; + arm->core_cache->reg_list[0].dirty = true; } return ERROR_OK; From 61a55f6278f73332ea55ff08194d0c41b9136ecd Mon Sep 17 00:00:00 2001 From: Marc Schink Date: Tue, 26 Feb 2019 14:09:03 +0100 Subject: [PATCH 37/70] target/etb: Use 'bool' data type Change-Id: I536036b15af10bb1879dbbec84576134fd3dce35 Signed-off-by: Marc Schink Reviewed-on: http://openocd.zylin.com/4966 Tested-by: jenkins Reviewed-by: Antonio Borneo --- src/target/etb.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/target/etb.c b/src/target/etb.c index dc25844b9..98a90a556 100644 --- a/src/target/etb.c +++ b/src/target/etb.c @@ -143,8 +143,8 @@ struct reg_cache *etb_build_reg_cache(struct etb *etb) for (i = 0; i < num_regs; i++) { reg_list[i].name = etb_reg_list[i]; reg_list[i].size = 32; - reg_list[i].dirty = 0; - reg_list[i].valid = 0; + reg_list[i].dirty = false; + reg_list[i].valid = false; reg_list[i].value = calloc(1, 4); reg_list[i].arch_info = &arch_info[i]; reg_list[i].type = &etb_reg_type; @@ -272,8 +272,8 @@ static int etb_set_reg(struct reg *reg, uint32_t value) } buf_set_u32(reg->value, 0, reg->size, value); - reg->valid = 1; - reg->dirty = 0; + reg->valid = true; + reg->dirty = false; return ERROR_OK; } From ffd8e2b630600703805c6500f92da8775aa88d10 Mon Sep 17 00:00:00 2001 From: Marc Schink Date: Tue, 26 Feb 2019 14:09:22 +0100 Subject: [PATCH 38/70] target/feroceon: Use 'bool' data type Change-Id: I30b8d07ee198e8f67cd98f83c4bec15bcfe8be08 Signed-off-by: Marc Schink Reviewed-on: http://openocd.zylin.com/4967 Tested-by: jenkins Reviewed-by: Antonio Borneo --- src/target/feroceon.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/target/feroceon.c b/src/target/feroceon.c index 21963e55e..4a6c6dcf0 100644 --- a/src/target/feroceon.c +++ b/src/target/feroceon.c @@ -532,8 +532,8 @@ static int feroceon_bulk_write_memory(struct target *target, /* set up target address in r0 */ buf_set_u32(arm->core_cache->reg_list[0].value, 0, 32, address); - arm->core_cache->reg_list[0].valid = 1; - arm->core_cache->reg_list[0].dirty = 1; + arm->core_cache->reg_list[0].valid = true; + arm->core_cache->reg_list[0].dirty = true; arm->core_state = ARM_STATE_ARM; embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_COMMS_DATA], 0); @@ -575,12 +575,12 @@ static int feroceon_bulk_write_memory(struct target *target, /* restore target state */ for (i = 0; i <= 5; i++) { buf_set_u32(arm->core_cache->reg_list[i].value, 0, 32, save[i]); - arm->core_cache->reg_list[i].valid = 1; - arm->core_cache->reg_list[i].dirty = 1; + arm->core_cache->reg_list[i].valid = true; + arm->core_cache->reg_list[i].dirty = true; } buf_set_u32(arm->pc->value, 0, 32, save[i]); - arm->pc->valid = 1; - arm->pc->dirty = 1; + arm->pc->valid = true; + arm->pc->dirty = true; arm->core_state = core_state; return retval; From c69da2eb0c118dbcfcc26090355fa23818cec61e Mon Sep 17 00:00:00 2001 From: Marc Schink Date: Tue, 26 Feb 2019 14:10:09 +0100 Subject: [PATCH 39/70] target/lakemont: Use 'bool' data type Change-Id: I9baaf617c2bfabd07ac3ca195e486893d7950398 Signed-off-by: Marc Schink Reviewed-on: http://openocd.zylin.com/4969 Tested-by: jenkins Reviewed-by: Antonio Borneo --- src/target/lakemont.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/target/lakemont.c b/src/target/lakemont.c index b81213ebd..31882b828 100644 --- a/src/target/lakemont.c +++ b/src/target/lakemont.c @@ -322,8 +322,8 @@ static int restore_context(struct target *t) } for (i = 0; i < (x86_32->cache->num_regs); i++) { - x86_32->cache->reg_list[i].dirty = 0; - x86_32->cache->reg_list[i].valid = 0; + x86_32->cache->reg_list[i].dirty = false; + x86_32->cache->reg_list[i].valid = false; } return err; } @@ -357,8 +357,8 @@ static int lakemont_set_core_reg(struct reg *reg, uint8_t *buf) if (check_not_halted(t)) return ERROR_TARGET_NOT_HALTED; buf_set_u32(reg->value, 0, 32, value); - reg->dirty = 1; - reg->valid = 1; + reg->dirty = true; + reg->valid = true; return ERROR_OK; } @@ -405,8 +405,8 @@ struct reg_cache *lakemont_build_reg_cache(struct target *t) reg_list[i].name = regs[i].name; reg_list[i].size = 32; reg_list[i].value = calloc(1, 4); - reg_list[i].dirty = 0; - reg_list[i].valid = 0; + reg_list[i].dirty = false; + reg_list[i].valid = false; reg_list[i].type = &lakemont_reg_type; reg_list[i].arch_info = &arch_info[i]; @@ -667,8 +667,8 @@ static int read_hw_reg(struct target *t, int reg, uint32_t *regval, uint8_t cach *regval = buf_get_u32(scan.out, 0, 32); if (cache) { buf_set_u32(x86_32->cache->reg_list[reg].value, 0, 32, *regval); - x86_32->cache->reg_list[reg].valid = 1; - x86_32->cache->reg_list[reg].dirty = 0; + x86_32->cache->reg_list[reg].valid = true; + x86_32->cache->reg_list[reg].dirty = false; } LOG_DEBUG("reg=%s, op=0x%016" PRIx64 ", val=0x%08" PRIx32, x86_32->cache->reg_list[reg].name, @@ -709,8 +709,8 @@ static int write_hw_reg(struct target *t, int reg, uint32_t regval, uint8_t cach /* we are writing from the cache so ensure we reset flags */ if (cache) { - x86_32->cache->reg_list[reg].dirty = 0; - x86_32->cache->reg_list[reg].valid = 0; + x86_32->cache->reg_list[reg].dirty = false; + x86_32->cache->reg_list[reg].valid = false; } return ERROR_OK; } @@ -947,8 +947,8 @@ int lakemont_poll(struct target *t) * breakpoint instruction. This needs to be corrected. */ buf_set_u32(x86_32->cache->reg_list[EIP].value, 0, 32, eip-1); - x86_32->cache->reg_list[EIP].dirty = 1; - x86_32->cache->reg_list[EIP].valid = 1; + x86_32->cache->reg_list[EIP].dirty = true; + x86_32->cache->reg_list[EIP].valid = true; LOG_USER("hit software breakpoint at 0x%08" PRIx32, eip-1); } else { /* it's not a hardware breakpoint (checked already in DR6 state) From 6431a85b0ad3a39895be780053d589a1bf1b88c2 Mon Sep 17 00:00:00 2001 From: Marc Schink Date: Tue, 26 Feb 2019 14:11:15 +0100 Subject: [PATCH 40/70] target/openrisc/or1k: Use 'bool' data type Change-Id: I6393bb8503d64947a1f2349e1d14c1552cabf927 Signed-off-by: Marc Schink Reviewed-on: http://openocd.zylin.com/4971 Tested-by: jenkins Reviewed-by: Antonio Borneo --- src/target/openrisc/or1k.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/target/openrisc/or1k.c b/src/target/openrisc/or1k.c index bcb648c27..34b1b0748 100644 --- a/src/target/openrisc/or1k.c +++ b/src/target/openrisc/or1k.c @@ -424,8 +424,8 @@ static int or1k_read_core_reg(struct target *target, int num) reg_value = or1k->core_regs[num]; buf_set_u32(or1k->core_cache->reg_list[num].value, 0, 32, reg_value); LOG_DEBUG("Read core reg %i value 0x%08" PRIx32, num , reg_value); - or1k->core_cache->reg_list[num].valid = 1; - or1k->core_cache->reg_list[num].dirty = 0; + or1k->core_cache->reg_list[num].valid = true; + or1k->core_cache->reg_list[num].dirty = false; } else { /* This is an spr, always read value from HW */ int retval = du_core->or1k_jtag_read_cpu(&or1k->jtag, @@ -453,8 +453,8 @@ static int or1k_write_core_reg(struct target *target, int num) uint32_t reg_value = buf_get_u32(or1k->core_cache->reg_list[num].value, 0, 32); or1k->core_regs[num] = reg_value; LOG_DEBUG("Write core reg %i value 0x%08" PRIx32, num , reg_value); - or1k->core_cache->reg_list[num].valid = 1; - or1k->core_cache->reg_list[num].dirty = 0; + or1k->core_cache->reg_list[num].valid = true; + or1k->core_cache->reg_list[num].dirty = false; return ERROR_OK; } @@ -487,8 +487,8 @@ static int or1k_set_core_reg(struct reg *reg, uint8_t *buf) if (or1k_reg->list_num < OR1KNUMCOREREGS) { buf_set_u32(reg->value, 0, 32, value); - reg->dirty = 1; - reg->valid = 1; + reg->dirty = true; + reg->valid = true; } else { /* This is an spr, write it to the HW */ int retval = du_core->or1k_jtag_write_cpu(&or1k->jtag, @@ -541,8 +541,8 @@ static struct reg_cache *or1k_build_reg_cache(struct target *target) reg_list[i].group = or1k_core_reg_list_arch_info[i].group; reg_list[i].size = 32; reg_list[i].value = calloc(1, 4); - reg_list[i].dirty = 0; - reg_list[i].valid = 0; + reg_list[i].dirty = false; + reg_list[i].valid = false; reg_list[i].type = &or1k_reg_type; reg_list[i].arch_info = &arch_info[i]; reg_list[i].number = i; From e243075962fc11f0b217db72d68819355c1be7dc Mon Sep 17 00:00:00 2001 From: Marc Schink Date: Tue, 26 Feb 2019 14:11:46 +0100 Subject: [PATCH 41/70] target/openrisc/x86_32_common: Use 'bool' data type Change-Id: I395a36ddd7ac7e85bc54f6bb073a93b0c6f24db0 Signed-off-by: Marc Schink Reviewed-on: http://openocd.zylin.com/4972 Tested-by: jenkins Reviewed-by: Antonio Borneo --- src/target/x86_32_common.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/target/x86_32_common.c b/src/target/x86_32_common.c index ef4f80680..011e7d843 100644 --- a/src/target/x86_32_common.c +++ b/src/target/x86_32_common.c @@ -939,14 +939,14 @@ static int set_debug_regs(struct target *t, uint32_t address, * when we exit PM */ buf_set_u32(x86_32->cache->reg_list[bp_num+DR0].value, 0, 32, address); - x86_32->cache->reg_list[bp_num+DR0].dirty = 1; - x86_32->cache->reg_list[bp_num+DR0].valid = 1; + x86_32->cache->reg_list[bp_num+DR0].dirty = true; + x86_32->cache->reg_list[bp_num+DR0].valid = true; buf_set_u32(x86_32->cache->reg_list[DR6].value, 0, 32, PM_DR6); - x86_32->cache->reg_list[DR6].dirty = 1; - x86_32->cache->reg_list[DR6].valid = 1; + x86_32->cache->reg_list[DR6].dirty = true; + x86_32->cache->reg_list[DR6].valid = true; buf_set_u32(x86_32->cache->reg_list[DR7].value, 0, 32, dr7); - x86_32->cache->reg_list[DR7].dirty = 1; - x86_32->cache->reg_list[DR7].valid = 1; + x86_32->cache->reg_list[DR7].dirty = true; + x86_32->cache->reg_list[DR7].valid = true; return ERROR_OK; } @@ -970,14 +970,14 @@ static int unset_debug_regs(struct target *t, uint8_t bp_num) * when we exit PM */ buf_set_u32(x86_32->cache->reg_list[bp_num+DR0].value, 0, 32, 0); - x86_32->cache->reg_list[bp_num+DR0].dirty = 1; - x86_32->cache->reg_list[bp_num+DR0].valid = 1; + x86_32->cache->reg_list[bp_num+DR0].dirty = true; + x86_32->cache->reg_list[bp_num+DR0].valid = true; buf_set_u32(x86_32->cache->reg_list[DR6].value, 0, 32, PM_DR6); - x86_32->cache->reg_list[DR6].dirty = 1; - x86_32->cache->reg_list[DR6].valid = 1; + x86_32->cache->reg_list[DR6].dirty = true; + x86_32->cache->reg_list[DR6].valid = true; buf_set_u32(x86_32->cache->reg_list[DR7].value, 0, 32, dr7); - x86_32->cache->reg_list[DR7].dirty = 1; - x86_32->cache->reg_list[DR7].valid = 1; + x86_32->cache->reg_list[DR7].dirty = true; + x86_32->cache->reg_list[DR7].valid = true; return ERROR_OK; } From 5c55fbb065a829beafa233e5c0c0be56d9664934 Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Sun, 3 Feb 2019 21:07:31 +0100 Subject: [PATCH 42/70] stlink: handle error bad-AP The new firmwares for ST-Link support handling multiple AP, but are (actually) limited to the AP number in range [0..8]. Any tentative to operate on AP number higher than 8 returns an error "bad AP". Add the error code and the related message. Change-Id: I78a98b2612d10e580d03fc43ed9f2b09619d39d8 Signed-off-by: Antonio Borneo Reviewed-on: http://openocd.zylin.com/4981 Reviewed-by: Tomas Vanek Tested-by: jenkins --- src/jtag/drivers/stlink_usb.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/jtag/drivers/stlink_usb.c b/src/jtag/drivers/stlink_usb.c index a9ee44d92..134cb2f42 100644 --- a/src/jtag/drivers/stlink_usb.c +++ b/src/jtag/drivers/stlink_usb.c @@ -167,6 +167,8 @@ struct stlink_usb_handle_s { #define STLINK_SWD_AP_STICKY_ERROR 0x19 #define STLINK_SWD_AP_STICKYORUN_ERROR 0x1a +#define STLINK_BAD_AP_ERROR 0x1d + #define STLINK_CORE_RUNNING 0x80 #define STLINK_CORE_HALTED 0x81 #define STLINK_CORE_STAT_UNKNOWN -1 @@ -751,6 +753,9 @@ static int stlink_usb_error_check(void *handle) case STLINK_SWD_AP_STICKYORUN_ERROR: LOG_DEBUG("STLINK_SWD_AP_STICKYORUN_ERROR"); return ERROR_FAIL; + case STLINK_BAD_AP_ERROR: + LOG_DEBUG("STLINK_BAD_AP_ERROR"); + return ERROR_FAIL; default: LOG_DEBUG("unknown/unexpected STLINK status code 0x%x", h->databuf[0]); return ERROR_FAIL; From 720380f9e372d9bab19445ff300ef1cb58e70a12 Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Tue, 5 Feb 2019 11:25:19 +0100 Subject: [PATCH 43/70] stlink: handle error GET_IDCODE When the connection with target is lost on the physical JTAG/SWD link (either wire disconnected or DAP/TAP in reset), STLINK fail to connect and returns error STLINK_JTAG_GET_IDCODE_ERROR. Add it in the list of known errors. Change-Id: Iabd6e6892111726f614345497d9286554bfe4ac0 Signed-off-by: Antonio Borneo Reviewed-on: http://openocd.zylin.com/4982 Reviewed-by: Tomas Vanek Tested-by: jenkins --- src/jtag/drivers/stlink_usb.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/jtag/drivers/stlink_usb.c b/src/jtag/drivers/stlink_usb.c index 134cb2f42..b02f9d018 100644 --- a/src/jtag/drivers/stlink_usb.c +++ b/src/jtag/drivers/stlink_usb.c @@ -156,6 +156,7 @@ struct stlink_usb_handle_s { #define STLINK_SWD_AP_FAULT 0x11 #define STLINK_SWD_AP_ERROR 0x12 #define STLINK_SWD_AP_PARITY_ERROR 0x13 +#define STLINK_JTAG_GET_IDCODE_ERROR 0x09 #define STLINK_JTAG_WRITE_ERROR 0x0c #define STLINK_JTAG_WRITE_VERIF_ERROR 0x0d #define STLINK_SWD_DP_WAIT 0x14 @@ -715,6 +716,9 @@ static int stlink_usb_error_check(void *handle) case STLINK_SWD_DP_WAIT: LOG_DEBUG("wait status SWD_DP_WAIT (0x%x)", STLINK_SWD_DP_WAIT); return ERROR_WAIT; + case STLINK_JTAG_GET_IDCODE_ERROR: + LOG_DEBUG("STLINK_JTAG_GET_IDCODE_ERROR"); + return ERROR_FAIL; case STLINK_JTAG_WRITE_ERROR: LOG_DEBUG("Write error"); return ERROR_FAIL; From d46b28983dc27369e90f4dc8a0e54b5057583b38 Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Fri, 7 Dec 2018 22:11:12 +0100 Subject: [PATCH 44/70] drivers/stlink_usb: fix stlink_usb_read_regs() for API v2 API v2 implementation for command READALLREGS returns the status in the first two bytes, followed by two bytes of padding. This makes the reply 4 bytes longer and changes the offset of the first register value to 4. Fix it for the case API v2 and clean-up the management of the return value. Change-Id: I448c82bcc0baa72d66fdfe7f0c525b94f8a4468b Signed-off-by: Antonio Borneo Reviewed-on: http://openocd.zylin.com/4824 Tested-by: jenkins Reviewed-by: Tarek BOCHKATI Reviewed-by: Tomas Vanek --- src/jtag/drivers/stlink_usb.c | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/src/jtag/drivers/stlink_usb.c b/src/jtag/drivers/stlink_usb.c index b02f9d018..9ba4f4af9 100644 --- a/src/jtag/drivers/stlink_usb.c +++ b/src/jtag/drivers/stlink_usb.c @@ -1895,20 +1895,21 @@ static int stlink_usb_read_regs(void *handle) assert(handle != NULL); - stlink_usb_init_buffer(handle, h->rx_ep, 84); + stlink_usb_init_buffer(handle, h->rx_ep, 88); h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_COMMAND; - if (h->version.jtag_api == STLINK_JTAG_API_V1) + if (h->version.jtag_api == STLINK_JTAG_API_V1) { + h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_APIV1_READALLREGS; - else + res = stlink_usb_xfer(handle, h->databuf, 84); + /* regs data from offset 0 */ + } else { h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_APIV2_READALLREGS; + res = stlink_usb_xfer(handle, h->databuf, 88); + /* status at offset 0, regs data from offset 4 */ + } - res = stlink_usb_xfer(handle, h->databuf, 84); - - if (res != ERROR_OK) - return res; - - return ERROR_OK; + return res; } /** */ From 05c6c871e3328dd38dc46ea11b3b9b546feb7850 Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Fri, 7 Dec 2018 12:37:20 +0100 Subject: [PATCH 45/70] drivers/stlink_usb: check error code returned by st-link Most of ST-Link commands return an error code, but this is almost never checked. Check for the error code for every command that returns it. Change-Id: Ifc4e32f8c73196de23700ba0989bfdfe0f5b46e3 Signed-off-by: Antonio Borneo Reviewed-on: http://openocd.zylin.com/4825 Tested-by: jenkins Reviewed-by: Tomas Vanek --- src/jtag/drivers/stlink_usb.c | 82 ++++++++++++++++++++--------------- 1 file changed, 46 insertions(+), 36 deletions(-) diff --git a/src/jtag/drivers/stlink_usb.c b/src/jtag/drivers/stlink_usb.c index 9ba4f4af9..64c44d90d 100644 --- a/src/jtag/drivers/stlink_usb.c +++ b/src/jtag/drivers/stlink_usb.c @@ -644,8 +644,9 @@ static int stlink_usb_xfer_v1_get_sense(void *handle) transfers block in cmdbuf indicates number of bytes in the following data phase. + Ignore the (eventual) error code in the received packet. */ -static int stlink_usb_xfer(void *handle, const uint8_t *buf, int size) +static int stlink_usb_xfer_noerrcheck(void *handle, const uint8_t *buf, int size) { int err, cmdsize = STLINK_CMD_SIZE_V2; struct stlink_usb_handle_s *h = handle; @@ -766,6 +767,22 @@ static int stlink_usb_error_check(void *handle) } } +/* + * Wrapper around stlink_usb_xfer_noerrcheck() + * to check the error code in the received packet + */ +static int stlink_usb_xfer_errcheck(void *handle, const uint8_t *buf, int size) +{ + int retval; + + assert(size > 0); + + retval = stlink_usb_xfer_noerrcheck(handle, buf, size); + if (retval != ERROR_OK) + return retval; + + return stlink_usb_error_check(handle); +} /** Issue an STLINK command via USB transfer, with retries on any wait status responses. @@ -782,7 +799,7 @@ static int stlink_cmd_allow_retry(void *handle, const uint8_t *buf, int size) while (1) { if ((h->transport != HL_TRANSPORT_SWIM) || !retries) { - res = stlink_usb_xfer(handle, buf, size); + res = stlink_usb_xfer_noerrcheck(handle, buf, size); if (res != ERROR_OK) return res; } @@ -886,7 +903,7 @@ static int stlink_usb_version(void *handle) h->cmdbuf[h->cmdidx++] = STLINK_GET_VERSION; - res = stlink_usb_xfer(handle, h->databuf, 6); + res = stlink_usb_xfer_noerrcheck(handle, h->databuf, 6); if (res != ERROR_OK) return res; @@ -927,7 +944,7 @@ static int stlink_usb_version(void *handle) h->cmdbuf[h->cmdidx++] = STLINK_APIV3_GET_VERSION_EX; - res = stlink_usb_xfer(handle, h->databuf, 12); + res = stlink_usb_xfer_noerrcheck(handle, h->databuf, 12); if (res != ERROR_OK) return res; @@ -1035,7 +1052,7 @@ static int stlink_usb_check_voltage(void *handle, float *target_voltage) h->cmdbuf[h->cmdidx++] = STLINK_GET_TARGET_VOLTAGE; - int result = stlink_usb_xfer(handle, h->databuf, 8); + int result = stlink_usb_xfer_noerrcheck(handle, h->databuf, 8); if (result != ERROR_OK) return result; @@ -1114,7 +1131,7 @@ static int stlink_usb_current_mode(void *handle, uint8_t *mode) h->cmdbuf[h->cmdidx++] = STLINK_GET_CURRENT_MODE; - res = stlink_usb_xfer(handle, h->databuf, 2); + res = stlink_usb_xfer_noerrcheck(handle, h->databuf, 2); if (res != ERROR_OK) return res; @@ -1202,7 +1219,7 @@ static int stlink_usb_mode_leave(void *handle, enum stlink_mode type) return ERROR_FAIL; } - res = stlink_usb_xfer(handle, 0, 0); + res = stlink_usb_xfer_noerrcheck(handle, 0, 0); if (res != ERROR_OK) return res; @@ -1348,7 +1365,8 @@ static int stlink_swim_status(void *handle) stlink_usb_init_buffer(handle, h->rx_ep, 4); h->cmdbuf[h->cmdidx++] = STLINK_SWIM_COMMAND; h->cmdbuf[h->cmdidx++] = STLINK_SWIM_READSTATUS; - res = stlink_usb_xfer(handle, h->databuf, 4); + /* error is checked by the caller */ + res = stlink_usb_xfer_noerrcheck(handle, h->databuf, 4); if (res != ERROR_OK) return res; return ERROR_OK; @@ -1368,7 +1386,7 @@ static int stlink_swim_cap(void *handle, uint8_t *cap) h->cmdbuf[h->cmdidx++] = STLINK_SWIM_COMMAND; h->cmdbuf[h->cmdidx++] = STLINK_SWIM_READ_CAP; h->cmdbuf[h->cmdidx++] = 0x01; - res = stlink_usb_xfer(handle, h->databuf, 8); + res = stlink_usb_xfer_noerrcheck(handle, h->databuf, 8); if (res != ERROR_OK) return res; memcpy(cap, h->databuf, 8); @@ -1525,7 +1543,7 @@ static int stlink_swim_readbytes(void *handle, uint32_t addr, uint32_t len, uint stlink_usb_init_buffer(handle, h->rx_ep, len); h->cmdbuf[h->cmdidx++] = STLINK_SWIM_COMMAND; h->cmdbuf[h->cmdidx++] = STLINK_SWIM_READBUF; - res = stlink_usb_xfer(handle, data, len); + res = stlink_usb_xfer_noerrcheck(handle, data, len); if (res != ERROR_OK) return res; @@ -1551,7 +1569,7 @@ static int stlink_usb_idcode(void *handle, uint32_t *idcode) h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_COMMAND; h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_READCOREID; - res = stlink_usb_xfer(handle, h->databuf, 4); + res = stlink_usb_xfer_noerrcheck(handle, h->databuf, 4); if (res != ERROR_OK) return res; @@ -1621,7 +1639,7 @@ static int stlink_usb_trace_read(void *handle, uint8_t *buf, size_t *size) h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_COMMAND; h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_APIV2_GET_TRACE_NB; - res = stlink_usb_xfer(handle, h->databuf, 2); + res = stlink_usb_xfer_noerrcheck(handle, h->databuf, 2); if (res != ERROR_OK) return res; @@ -1698,7 +1716,7 @@ static enum target_state stlink_usb_state(void *handle) h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_COMMAND; h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_GETSTATUS; - res = stlink_usb_xfer(handle, h->databuf, 2); + res = stlink_usb_xfer_noerrcheck(handle, h->databuf, 2); if (res != ERROR_OK) return TARGET_UNKNOWN; @@ -1749,7 +1767,7 @@ static void stlink_usb_trace_disable(void *handle) stlink_usb_init_buffer(handle, h->rx_ep, 2); h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_COMMAND; h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_APIV2_STOP_TRACE_RX; - res = stlink_usb_xfer(handle, h->databuf, 2); + res = stlink_usb_xfer_errcheck(handle, h->databuf, 2); if (res == ERROR_OK) h->trace.enabled = false; @@ -1774,7 +1792,7 @@ static int stlink_usb_trace_enable(void *handle) h_u32_to_le(h->cmdbuf+h->cmdidx, h->trace.source_hz); h->cmdidx += 4; - res = stlink_usb_xfer(handle, h->databuf, 2); + res = stlink_usb_xfer_errcheck(handle, h->databuf, 2); if (res == ERROR_OK) { h->trace.enabled = true; @@ -1901,11 +1919,11 @@ static int stlink_usb_read_regs(void *handle) if (h->version.jtag_api == STLINK_JTAG_API_V1) { h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_APIV1_READALLREGS; - res = stlink_usb_xfer(handle, h->databuf, 84); + res = stlink_usb_xfer_noerrcheck(handle, h->databuf, 84); /* regs data from offset 0 */ } else { h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_APIV2_READALLREGS; - res = stlink_usb_xfer(handle, h->databuf, 88); + res = stlink_usb_xfer_errcheck(handle, h->databuf, 88); /* status at offset 0, regs data from offset 4 */ } @@ -1930,7 +1948,7 @@ static int stlink_usb_read_reg(void *handle, int num, uint32_t *val) h->cmdbuf[h->cmdidx++] = num; if (h->version.jtag_api == STLINK_JTAG_API_V1) { - res = stlink_usb_xfer(handle, h->databuf, 4); + res = stlink_usb_xfer_noerrcheck(handle, h->databuf, 4); if (res != ERROR_OK) return res; *val = le_to_h_u32(h->databuf); @@ -1967,7 +1985,6 @@ static int stlink_usb_write_reg(void *handle, int num, uint32_t val) static int stlink_usb_get_rw_status(void *handle) { - int res; struct stlink_usb_handle_s *h = handle; assert(handle != NULL); @@ -1980,18 +1997,11 @@ static int stlink_usb_get_rw_status(void *handle) h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_COMMAND; if (h->version.flags & STLINK_F_HAS_GETLASTRWSTATUS2) { h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_APIV2_GETLASTRWSTATUS2; - - res = stlink_usb_xfer(handle, h->databuf, 12); + return stlink_usb_xfer_errcheck(handle, h->databuf, 12); } else { h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_APIV2_GETLASTRWSTATUS; - - res = stlink_usb_xfer(handle, h->databuf, 2); + return stlink_usb_xfer_errcheck(handle, h->databuf, 2); } - - if (res != ERROR_OK) - return res; - - return stlink_usb_error_check(h); } /** */ @@ -2023,7 +2033,7 @@ static int stlink_usb_read_mem8(void *handle, uint32_t addr, uint16_t len, if (read_len == 1) read_len++; - res = stlink_usb_xfer(handle, h->databuf, read_len); + res = stlink_usb_xfer_noerrcheck(handle, h->databuf, read_len); if (res != ERROR_OK) return res; @@ -2057,7 +2067,7 @@ static int stlink_usb_write_mem8(void *handle, uint32_t addr, uint16_t len, h_u16_to_le(h->cmdbuf+h->cmdidx, len); h->cmdidx += 2; - res = stlink_usb_xfer(handle, buffer, len); + res = stlink_usb_xfer_noerrcheck(handle, buffer, len); if (res != ERROR_OK) return res; @@ -2092,7 +2102,7 @@ static int stlink_usb_read_mem16(void *handle, uint32_t addr, uint16_t len, h_u16_to_le(h->cmdbuf+h->cmdidx, len); h->cmdidx += 2; - res = stlink_usb_xfer(handle, h->databuf, len); + res = stlink_usb_xfer_noerrcheck(handle, h->databuf, len); if (res != ERROR_OK) return res; @@ -2129,7 +2139,7 @@ static int stlink_usb_write_mem16(void *handle, uint32_t addr, uint16_t len, h_u16_to_le(h->cmdbuf+h->cmdidx, len); h->cmdidx += 2; - res = stlink_usb_xfer(handle, buffer, len); + res = stlink_usb_xfer_noerrcheck(handle, buffer, len); if (res != ERROR_OK) return res; @@ -2161,7 +2171,7 @@ static int stlink_usb_read_mem32(void *handle, uint32_t addr, uint16_t len, h_u16_to_le(h->cmdbuf+h->cmdidx, len); h->cmdidx += 2; - res = stlink_usb_xfer(handle, h->databuf, len); + res = stlink_usb_xfer_noerrcheck(handle, h->databuf, len); if (res != ERROR_OK) return res; @@ -2195,7 +2205,7 @@ static int stlink_usb_write_mem32(void *handle, uint32_t addr, uint16_t len, h_u16_to_le(h->cmdbuf+h->cmdidx, len); h->cmdidx += 2; - res = stlink_usb_xfer(handle, buffer, len); + res = stlink_usb_xfer_noerrcheck(handle, buffer, len); if (res != ERROR_OK) return res; @@ -2516,7 +2526,7 @@ static int stlink_get_com_freq(void *handle, bool is_jtag, struct speed_map *map h->cmdbuf[h->cmdidx++] = STLINK_APIV3_GET_COM_FREQ; h->cmdbuf[h->cmdidx++] = is_jtag ? 1 : 0; - int res = stlink_usb_xfer(handle, h->databuf, 52); + int res = stlink_usb_xfer_errcheck(handle, h->databuf, 52); int size = h->databuf[8]; @@ -2553,7 +2563,7 @@ static int stlink_set_com_freq(void *handle, bool is_jtag, unsigned int frequenc h_u32_to_le(&h->cmdbuf[4], frequency); - return stlink_usb_xfer(handle, h->databuf, 8); + return stlink_usb_xfer_errcheck(handle, h->databuf, 8); } static int stlink_speed_v3(void *handle, bool is_jtag, int khz, bool query) From 56568b7996323da8e9254cadcdd555323a76466f Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Thu, 20 Dec 2018 00:01:58 +0100 Subject: [PATCH 46/70] drivers/stlink_usb: use command STLINK_DEBUG_APIV2_READ_IDCODES API v2 deprecates using command STLINK_DEBUG_READCOREID to read the core ID. Switch to STLINK_DEBUG_APIV2_READ_IDCODES on new stlink firmware version. Change-Id: Iabadfc116c57f2c31f08f2e77baefea0cf90bdc3 Signed-off-by: Antonio Borneo Reviewed-on: http://openocd.zylin.com/4826 Tested-by: jenkins Reviewed-by: Tomas Vanek --- src/jtag/drivers/stlink_usb.c | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/src/jtag/drivers/stlink_usb.c b/src/jtag/drivers/stlink_usb.c index 64c44d90d..491f2e4ff 100644 --- a/src/jtag/drivers/stlink_usb.c +++ b/src/jtag/drivers/stlink_usb.c @@ -1553,7 +1553,7 @@ static int stlink_swim_readbytes(void *handle, uint32_t addr, uint32_t len, uint /** */ static int stlink_usb_idcode(void *handle, uint32_t *idcode) { - int res; + int res, offset; struct stlink_usb_handle_s *h = handle; assert(handle != NULL); @@ -1564,17 +1564,25 @@ static int stlink_usb_idcode(void *handle, uint32_t *idcode) return ERROR_OK; } - stlink_usb_init_buffer(handle, h->rx_ep, 4); + stlink_usb_init_buffer(handle, h->rx_ep, 12); h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_COMMAND; - h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_READCOREID; + if (h->version.jtag_api == STLINK_JTAG_API_V1) { + h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_READCOREID; - res = stlink_usb_xfer_noerrcheck(handle, h->databuf, 4); + res = stlink_usb_xfer_noerrcheck(handle, h->databuf, 4); + offset = 0; + } else { + h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_APIV2_READ_IDCODES; + + res = stlink_usb_xfer_errcheck(handle, h->databuf, 12); + offset = 4; + } if (res != ERROR_OK) return res; - *idcode = le_to_h_u32(h->databuf); + *idcode = le_to_h_u32(h->databuf + offset); LOG_DEBUG("IDCODE: 0x%08" PRIX32, *idcode); From 85ba2dc4c6ab4c91f4461c2853660cc2cb9e2623 Mon Sep 17 00:00:00 2001 From: Matthias Welwarsky Date: Fri, 17 Feb 2017 16:16:51 +0100 Subject: [PATCH 47/70] rtos/hwthread: add hardware-thread pseudo rtos This patch adds "hwthread", a pseudo rtos that represents cpu cores in an SMP system as threads to gdb. This allows to debug SMP system kernels in a more sensible manner and removes the current atrocities of switching gdb manually between CPU cores to update the context. Change-Id: Ib781c6c34097689d21d9e02011e4d74a4a742379 Signed-off-by: Matthias Welwarsky Reviewed-on: http://openocd.zylin.com/3999 Tested-by: jenkins Reviewed-by: Tim Newsome Reviewed-by: Matthias Welwarsky Reviewed-by: Graham Sanderson --- doc/openocd.texi | 118 ++++++++------- src/rtos/Makefile.am | 1 + src/rtos/hwthread.c | 347 +++++++++++++++++++++++++++++++++++++++++++ src/rtos/rtos.c | 2 + 4 files changed, 417 insertions(+), 51 deletions(-) create mode 100644 src/rtos/hwthread.c diff --git a/doc/openocd.texi b/doc/openocd.texi index 2e04182b3..bbb907558 100644 --- a/doc/openocd.texi +++ b/doc/openocd.texi @@ -10199,55 +10199,6 @@ and GDB would require stopping the target to get the prompt back. Do not use this mode under an IDE like Eclipse as it caches values of previously shown varibles. -@anchor{usingopenocdsmpwithgdb} -@section Using OpenOCD SMP with GDB -@cindex SMP -For SMP support following GDB serial protocol packet have been defined : -@itemize @bullet -@item j - smp status request -@item J - smp set request -@end itemize - -OpenOCD implements : -@itemize @bullet -@item @option{jc} packet for reading core id displayed by -GDB connection. Reply is @option{XXXXXXXX} (8 hex digits giving core id) or - @option{E01} for target not smp. -@item @option{JcXXXXXXXX} (8 hex digits) packet for setting core id displayed at next GDB continue -(core id -1 is reserved for returning to normal resume mode). Reply @option{E01} -for target not smp or @option{OK} on success. -@end itemize - -Handling of this packet within GDB can be done : -@itemize @bullet -@item by the creation of an internal variable (i.e @option{_core}) by mean -of function allocate_computed_value allowing following GDB command. -@example -set $_core 1 -#Jc01 packet is sent -print $_core -#jc packet is sent and result is affected in $ -@end example - -@item by the usage of GDB maintenance command as described in following example (2 cpus in SMP with -core id 0 and 1 @pxref{definecputargetsworkinginsmp,,Define CPU targets working in SMP}). - -@example -# toggle0 : force display of coreid 0 -define toggle0 -maint packet Jc0 -continue -main packet Jc-1 -end -# toggle1 : force display of coreid 1 -define toggle1 -maint packet Jc1 -continue -main packet Jc-1 -end -@end example -@end itemize - @section RTOS Support @cindex RTOS Support @anchor{gdbrtossupport} @@ -10278,12 +10229,11 @@ Currently supported rtos's include: @item @option{mqx} @item @option{uCOS-III} @item @option{nuttx} +@item @option{hwthread} (This is not an actual RTOS. @xref{usingopenocdsmpwithgdb,,Using OpenOCD SMP with GDB}.) @end itemize -@quotation Note Before an RTOS can be detected, it must export certain symbols; otherwise, it cannot be used by OpenOCD. Below is a list of the required symbols for each supported RTOS. -@end quotation @table @code @item eCos symbols @@ -10330,6 +10280,72 @@ contrib/rtos-helpers/FreeRTOS-openocd.c contrib/rtos-helpers/uCOS-III-openocd.c @end table +@anchor{usingopenocdsmpwithgdb} +@section Using OpenOCD SMP with GDB +@cindex SMP +@cindex RTOS +@cindex hwthread +OpenOCD includes a pseudo RTOS called @emph{hwthread} that presents CPU cores +("hardware threads") in an SMP system as threads to GDB. With this extension, +GDB can be used to inspect the state of an SMP system in a natural way. +After halting the system, using the GDB command @command{info threads} will +list the context of each active CPU core in the system. GDB's @command{thread} +command can be used to switch the view to a different CPU core. +The @command{step} and @command{stepi} commands can be used to step a specific core +while other cores are free-running or remain halted, depending on the +scheduler-locking mode configured in GDB. + +@section Legacy SMP core switching support +@quotation Note +This method is deprecated in favor of the @emph{hwthread} pseudo RTOS. +@end quotation + +For SMP support following GDB serial protocol packet have been defined : +@itemize @bullet +@item j - smp status request +@item J - smp set request +@end itemize + +OpenOCD implements : +@itemize @bullet +@item @option{jc} packet for reading core id displayed by +GDB connection. Reply is @option{XXXXXXXX} (8 hex digits giving core id) or + @option{E01} for target not smp. +@item @option{JcXXXXXXXX} (8 hex digits) packet for setting core id displayed at next GDB continue +(core id -1 is reserved for returning to normal resume mode). Reply @option{E01} +for target not smp or @option{OK} on success. +@end itemize + +Handling of this packet within GDB can be done : +@itemize @bullet +@item by the creation of an internal variable (i.e @option{_core}) by mean +of function allocate_computed_value allowing following GDB command. +@example +set $_core 1 +#Jc01 packet is sent +print $_core +#jc packet is sent and result is affected in $ +@end example + +@item by the usage of GDB maintenance command as described in following example (2 cpus in SMP with +core id 0 and 1 @pxref{definecputargetsworkinginsmp,,Define CPU targets working in SMP}). + +@example +# toggle0 : force display of coreid 0 +define toggle0 +maint packet Jc0 +continue +main packet Jc-1 +end +# toggle1 : force display of coreid 1 +define toggle1 +maint packet Jc1 +continue +main packet Jc-1 +end +@end example +@end itemize + @node Tcl Scripting API @chapter Tcl Scripting API @cindex Tcl Scripting API diff --git a/src/rtos/Makefile.am b/src/rtos/Makefile.am index bbf66a634..38adb6e92 100644 --- a/src/rtos/Makefile.am +++ b/src/rtos/Makefile.am @@ -17,6 +17,7 @@ noinst_LTLIBRARIES += %D%/librtos.la %D%/mqx.c \ %D%/uCOS-III.c \ %D%/nuttx.c \ + %D%/hwthread.c \ %D%/rtos.h \ %D%/rtos_standard_stackings.h \ %D%/rtos_ecos_stackings.h \ diff --git a/src/rtos/hwthread.c b/src/rtos/hwthread.c new file mode 100644 index 000000000..2d9e42fa6 --- /dev/null +++ b/src/rtos/hwthread.c @@ -0,0 +1,347 @@ +/*************************************************************************** + * * + * 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 * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see . * + ***************************************************************************/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include "target/target.h" +#include "target/target_type.h" +#include "target/register.h" +#include "rtos.h" +#include "helper/log.h" +#include "helper/types.h" +#include "server/gdb_server.h" + +static bool hwthread_detect_rtos(struct target *target); +static int hwthread_create(struct target *target); +static int hwthread_update_threads(struct rtos *rtos); +static int hwthread_get_thread_reg_list(struct rtos *rtos, int64_t thread_id, + struct rtos_reg **reg_list, int *num_regs); +static int hwthread_get_symbol_list_to_lookup(symbol_table_elem_t *symbol_list[]); +static int hwthread_smp_init(struct target *target); + +#define HW_THREAD_NAME_STR_SIZE (32) + +extern int rtos_thread_packet(struct connection *connection, const char *packet, int packet_size); + +static inline threadid_t threadid_from_target(const struct target *target) +{ + return target->coreid + 1; +} + +const struct rtos_type hwthread_rtos = { + .name = "hwthread", + .detect_rtos = hwthread_detect_rtos, + .create = hwthread_create, + .update_threads = hwthread_update_threads, + .get_thread_reg_list = hwthread_get_thread_reg_list, + .get_symbol_list_to_lookup = hwthread_get_symbol_list_to_lookup, + .smp_init = hwthread_smp_init, +}; + +struct hwthread_params { + int dummy_param; +}; + +static int hwthread_fill_thread(struct rtos *rtos, struct target *curr, int thread_num) +{ + char tmp_str[HW_THREAD_NAME_STR_SIZE]; + threadid_t tid = threadid_from_target(curr); + + memset(tmp_str, 0, HW_THREAD_NAME_STR_SIZE); + + /* thread-id is the core-id of this core inside the SMP group plus 1 */ + rtos->thread_details[thread_num].threadid = tid; + /* create the thread name */ + rtos->thread_details[thread_num].exists = true; + rtos->thread_details[thread_num].thread_name_str = strdup(target_name(curr)); + snprintf(tmp_str, HW_THREAD_NAME_STR_SIZE-1, "state: %s", debug_reason_name(curr)); + rtos->thread_details[thread_num].extra_info_str = strdup(tmp_str); + + return ERROR_OK; +} + +static int hwthread_update_threads(struct rtos *rtos) +{ + int threads_found = 0; + int thread_list_size = 0; + struct target_list *head; + struct target *target; + int64_t current_thread = 0; + enum target_debug_reason current_reason = DBG_REASON_UNDEFINED; + + if (rtos == NULL) + return -1; + + target = rtos->target; + + /* wipe out previous thread details if any */ + rtos_free_threadlist(rtos); + + /* determine the number of "threads" */ + if (target->smp) { + for (head = target->head; head != NULL; head = head->next) { + struct target *curr = head->target; + + if (!target_was_examined(curr)) + continue; + + ++thread_list_size; + } + } else + thread_list_size = 1; + + /* create space for new thread details */ + rtos->thread_details = malloc(sizeof(struct thread_detail) * thread_list_size); + + if (target->smp) { + /* loop over all threads */ + for (head = target->head; head != NULL; head = head->next) { + struct target *curr = head->target; + + if (!target_was_examined(curr)) + continue; + + threadid_t tid = threadid_from_target(curr); + + hwthread_fill_thread(rtos, curr, threads_found); + + /* find an interesting thread to set as current */ + switch (current_reason) { + case DBG_REASON_UNDEFINED: + current_reason = curr->debug_reason; + current_thread = tid; + break; + case DBG_REASON_SINGLESTEP: + /* single-step can only be overridden by itself */ + if (curr->debug_reason == DBG_REASON_SINGLESTEP) { + if (tid == rtos->current_threadid) + current_thread = tid; + } + break; + case DBG_REASON_BREAKPOINT: + /* single-step overrides breakpoint */ + if (curr->debug_reason == DBG_REASON_SINGLESTEP) { + current_reason = curr->debug_reason; + current_thread = tid; + } else + /* multiple breakpoints, prefer gdbs' threadid */ + if (curr->debug_reason == DBG_REASON_BREAKPOINT) { + if (tid == rtos->current_threadid) + current_thread = tid; + } + break; + case DBG_REASON_WATCHPOINT: + /* breakpoint and single-step override watchpoint */ + if (curr->debug_reason == DBG_REASON_SINGLESTEP || + curr->debug_reason == DBG_REASON_BREAKPOINT) { + current_reason = curr->debug_reason; + current_thread = tid; + } + break; + case DBG_REASON_DBGRQ: + /* all other reasons override debug-request */ + if (curr->debug_reason == DBG_REASON_SINGLESTEP || + curr->debug_reason == DBG_REASON_WATCHPOINT || + curr->debug_reason == DBG_REASON_BREAKPOINT) { + current_reason = curr->debug_reason; + current_thread = tid; + } else + if (curr->debug_reason == DBG_REASON_DBGRQ) { + if (tid == rtos->current_threadid) + current_thread = tid; + } + + break; + + default: + break; + } + + threads_found++; + } + } else { + hwthread_fill_thread(rtos, target, threads_found); + current_thread = threadid_from_target(target); + threads_found++; + } + + rtos->thread_count = threads_found; + + /* we found an interesting thread, set it as current */ + if (current_thread != 0) + rtos->current_thread = current_thread; + else if (rtos->current_threadid != 0) + rtos->current_thread = rtos->current_threadid; + else + rtos->current_thread = threadid_from_target(target); + + LOG_DEBUG("%s current_thread=%i", __func__, (int)rtos->current_thread); + return 0; +} + +static int hwthread_smp_init(struct target *target) +{ + return hwthread_update_threads(target->rtos); +} + +static int hwthread_get_thread_reg_list(struct rtos *rtos, int64_t thread_id, + struct rtos_reg **rtos_reg_list, int *num_regs) +{ + struct target_list *head; + struct target *target; + struct target *curr; + struct reg **reg_list; + int retval; + + if (rtos == NULL) + return ERROR_FAIL; + + target = rtos->target; + + /* Find the thread with that thread_id */ + if (target->smp) { + curr = NULL; + for (head = target->head; head != NULL; head = head->next) { + curr = head->target; + + if (thread_id == threadid_from_target(curr)) + break; + } + + if (head == NULL) + return ERROR_FAIL; + } else { + curr = target; + if (thread_id != threadid_from_target(curr)) + return ERROR_FAIL; + + } + + if (!target_was_examined(curr)) + return ERROR_FAIL; + + retval = target_get_gdb_reg_list(curr, ®_list, num_regs, + REG_CLASS_GENERAL); + if (retval != ERROR_OK) + return retval; + + *rtos_reg_list = calloc(*num_regs, sizeof(struct rtos_reg)); + if (*rtos_reg_list == NULL) { + free(reg_list); + return ERROR_FAIL; + } + + for (int i = 0; i < *num_regs; i++) { + (*rtos_reg_list)[i].number = (*reg_list)[i].number; + (*rtos_reg_list)[i].size = (*reg_list)[i].size; + memcpy((*rtos_reg_list)[i].value, (*reg_list)[i].value, + ((*reg_list)[i].size + 7) / 8); + } + + free(reg_list); + + return ERROR_OK; + +} + +static int hwthread_get_symbol_list_to_lookup(symbol_table_elem_t *symbol_list[]) +{ + /* return an empty list, we don't have any symbols to look up */ + *symbol_list = calloc(1, sizeof(symbol_table_elem_t)); + (*symbol_list)[0].symbol_name = NULL; + return 0; +} + +static int hwthread_target_for_threadid(struct connection *connection, int64_t thread_id, struct target **p_target) +{ + struct target *target = get_target_from_connection(connection); + struct target_list *head; + struct target *curr; + + if (target->smp) { + /* Find the thread with that thread_id */ + curr = NULL; + for (head = target->head; head != NULL; head = head->next) { + curr = head->target; + + if (thread_id == threadid_from_target(curr)) + break; + } + + if (head == NULL) + return ERROR_FAIL; + } else { + curr = target; + if (thread_id != threadid_from_target(curr)) + return ERROR_FAIL; + } + + *p_target = curr; + + return ERROR_OK; +} + +static bool hwthread_detect_rtos(struct target *target) +{ + /* always return 0, avoid auto-detection */ + return false; +} + +static int hwthread_thread_packet(struct connection *connection, const char *packet, int packet_size) +{ + struct target *target = get_target_from_connection(connection); + + struct target *curr = NULL; + int64_t current_threadid; + + if (packet[0] == 'H' && packet[1] == 'g') { + sscanf(packet, "Hg%16" SCNx64, ¤t_threadid); + + if (current_threadid > 0) { + if (hwthread_target_for_threadid(connection, current_threadid, &curr) != ERROR_OK) { + LOG_ERROR("hwthread: cannot find thread id %"PRId64, current_threadid); + gdb_put_packet(connection, "E01", 3); + return ERROR_FAIL; + } + target->rtos->current_thread = current_threadid; + } else + if (current_threadid == 0 || current_threadid == -1) + target->rtos->current_thread = threadid_from_target(target); + + target->rtos->current_threadid = current_threadid; + + gdb_put_packet(connection, "OK", 2); + return ERROR_OK; + } + + return rtos_thread_packet(connection, packet, packet_size); +} + +static int hwthread_create(struct target *target) +{ + LOG_INFO("Hardware thread awareness created"); + + target->rtos->rtos_specific_params = NULL; + target->rtos->current_thread = 0; + target->rtos->thread_details = NULL; + target->rtos->gdb_target_for_threadid = hwthread_target_for_threadid; + target->rtos->gdb_thread_packet = hwthread_thread_packet; + return 0; +} diff --git a/src/rtos/rtos.c b/src/rtos/rtos.c index cd2e271f6..da0a50362 100644 --- a/src/rtos/rtos.c +++ b/src/rtos/rtos.c @@ -37,6 +37,7 @@ extern struct rtos_type embKernel_rtos; extern struct rtos_type mqx_rtos; extern struct rtos_type uCOS_III_rtos; extern struct rtos_type nuttx_rtos; +extern struct rtos_type hwthread_rtos; static struct rtos_type *rtos_types[] = { &ThreadX_rtos, @@ -49,6 +50,7 @@ static struct rtos_type *rtos_types[] = { &mqx_rtos, &uCOS_III_rtos, &nuttx_rtos, + &hwthread_rtos, NULL }; From 57e30102ea440d77aa001e26eb901d0cbb305a30 Mon Sep 17 00:00:00 2001 From: Tim Newsome Date: Mon, 25 Feb 2019 14:02:30 -0800 Subject: [PATCH 48/70] gdb_server, target: Add target_address_bits() Targets can use this to expose how many address bits there are. gdb_server uses this to send gdb the appropriate upper limit in the memory-map. (Before this change the upper limit would only be correct for 32-bit targets.) Change-Id: Idb0933255ed53951fcfb05e040674bcdf19441e1 Signed-off-by: Tim Newsome Reviewed-on: http://openocd.zylin.com/4947 Tested-by: jenkins Reviewed-by: Peter Mamonov Reviewed-by: Tomas Vanek --- src/server/gdb_server.c | 9 ++++----- src/target/riscv/riscv.c | 9 ++++++++- src/target/target.c | 16 ++++++++++++++++ src/target/target.h | 10 ++++++++++ src/target/target_type.h | 5 +++++ 5 files changed, 43 insertions(+), 6 deletions(-) diff --git a/src/server/gdb_server.c b/src/server/gdb_server.c index 54cf9aff8..3ade195cb 100644 --- a/src/server/gdb_server.c +++ b/src/server/gdb_server.c @@ -1921,11 +1921,10 @@ static int gdb_memory_map(struct connection *connection, if (ram_start != 0) xml_printf(&retval, &xml, &pos, &size, "\n", - ram_start, 0-ram_start); - /* ELSE a flash chip could be at the very end of the 32 bit address - * space, in which case ram_start will be precisely 0 - */ + "length=\"" TARGET_ADDR_FMT "\"/>\n", + ram_start, target_address_max(target) - ram_start + 1); + /* ELSE a flash chip could be at the very end of the address space, in + * which case ram_start will be precisely 0 */ free(banks); diff --git a/src/target/riscv/riscv.c b/src/target/riscv/riscv.c index 02ba38055..9a6b9389a 100644 --- a/src/target/riscv/riscv.c +++ b/src/target/riscv/riscv.c @@ -1560,6 +1560,11 @@ const struct command_registration riscv_command_handlers[] = { COMMAND_REGISTRATION_DONE }; +unsigned riscv_address_bits(struct target *target) +{ + return riscv_xlen(target); +} + struct target_type riscv_target = { .name = "riscv", @@ -1594,7 +1599,9 @@ struct target_type riscv_target = { .run_algorithm = riscv_run_algorithm, - .commands = riscv_command_handlers + .commands = riscv_command_handlers, + + .address_bits = riscv_address_bits }; /*** RISC-V Interface ***/ diff --git a/src/target/target.c b/src/target/target.c index 1f8e0bfc3..5295dd626 100644 --- a/src/target/target.c +++ b/src/target/target.c @@ -1257,6 +1257,22 @@ int target_gdb_fileio_end(struct target *target, int retcode, int fileio_errno, return target->type->gdb_fileio_end(target, retcode, fileio_errno, ctrl_c); } +target_addr_t target_address_max(struct target *target) +{ + unsigned bits = target_address_bits(target); + if (sizeof(target_addr_t) * 8 == bits) + return (target_addr_t) -1; + else + return (((target_addr_t) 1) << bits) - 1; +} + +unsigned target_address_bits(struct target *target) +{ + if (target->type->address_bits) + return target->type->address_bits(target); + return 32; +} + int target_profiling(struct target *target, uint32_t *samples, uint32_t max_num_samples, uint32_t *num_samples, uint32_t seconds) { diff --git a/src/target/target.h b/src/target/target.h index 48793da6e..65494afd0 100644 --- a/src/target/target.h +++ b/src/target/target.h @@ -641,7 +641,17 @@ int target_get_gdb_fileio_info(struct target *target, struct gdb_fileio_info *fi */ int target_gdb_fileio_end(struct target *target, int retcode, int fileio_errno, bool ctrl_c); +/** + * Return the highest accessible address for this target. + */ +target_addr_t target_address_max(struct target *target); +/** + * Return the number of address bits this target supports. + * + * This routine is a wrapper for target->type->address_bits. + */ +unsigned target_address_bits(struct target *target); /** Return the *name* of this targets current state */ const char *target_state_name(struct target *target); diff --git a/src/target/target_type.h b/src/target/target_type.h index a8928911f..95745c9eb 100644 --- a/src/target/target_type.h +++ b/src/target/target_type.h @@ -284,6 +284,11 @@ struct target_type { */ int (*profiling)(struct target *target, uint32_t *samples, uint32_t max_num_samples, uint32_t *num_samples, uint32_t seconds); + + /* Return the number of address bits this target supports. This will + * typically be 32 for 32-bit targets, and 64 for 64-bit targets. If not + * implemented, it's assumed to be 32. */ + unsigned (*address_bits)(struct target *target); }; #endif /* OPENOCD_TARGET_TARGET_TYPE_H */ From c3b90c052acfb7e35a0f4ce22276d53a96d631c7 Mon Sep 17 00:00:00 2001 From: Tim Newsome Date: Thu, 14 Feb 2019 17:33:28 -0800 Subject: [PATCH 49/70] flash/nor: use target_addr_t for flash bank base This should allow users to configure flash at >32-bit addresses. Change-Id: I7c9d3c5762579011a2d9708e5317e5765349845c Signed-off-by: Tim Newsome Reviewed-on: http://openocd.zylin.com/4919 Tested-by: jenkins Reviewed-by: Tomas Vanek --- src/flash/nor/at91sam4.c | 6 ++++-- src/flash/nor/at91sam4l.c | 3 ++- src/flash/nor/at91samd.c | 3 ++- src/flash/nor/ath79.c | 2 +- src/flash/nor/atsame5.c | 5 ++--- src/flash/nor/bluenrg-x.c | 6 +++--- src/flash/nor/cfi.c | 30 ++++++++++++++++-------------- src/flash/nor/core.c | 33 ++++++++++++++++++--------------- src/flash/nor/core.h | 8 ++++---- src/flash/nor/fespi.c | 19 ++++++++++--------- src/flash/nor/fm4.c | 2 +- src/flash/nor/kinetis.c | 22 ++++++++++++++-------- src/flash/nor/kinetis_ke.c | 2 +- src/flash/nor/lpc2000.c | 6 +++--- src/flash/nor/lpcspifi.c | 2 +- src/flash/nor/niietcm4.c | 6 ++++-- src/flash/nor/nrf5.c | 2 +- src/flash/nor/numicro.c | 6 ++++-- src/flash/nor/pic32mx.c | 2 +- src/flash/nor/psoc5lp.c | 2 +- src/flash/nor/stm32h7x.c | 4 ++-- src/flash/nor/stm32lx.c | 5 +++-- src/flash/nor/stmsmi.c | 4 ++-- src/flash/nor/tcl.c | 22 ++++++++++++---------- src/flash/nor/tms470.c | 11 ++++++----- src/flash/nor/virtual.c | 2 +- src/flash/nor/xmc1xxx.c | 2 +- src/flash/nor/xmc4xxx.c | 2 +- 28 files changed, 121 insertions(+), 98 deletions(-) diff --git a/src/flash/nor/at91sam4.c b/src/flash/nor/at91sam4.c index 2eec15e2a..d4d48a74f 100644 --- a/src/flash/nor/at91sam4.c +++ b/src/flash/nor/at91sam4.c @@ -2598,7 +2598,7 @@ static int sam4_info(struct flash_bank *bank, char *buf, int buf_size) } snprintf(buf, buf_size, - "%s bank %d: %d kB at 0x%08" PRIx32, + "%s bank %d: %d kB at " TARGET_ADDR_FMT, pPrivate->pChip->details.name, pPrivate->bank_number, k, @@ -2642,7 +2642,9 @@ static int sam4_probe(struct flash_bank *bank) for (x = 0; x < SAM4_MAX_FLASH_BANKS; x++) { if (bank->base == pPrivate->pChip->details.bank[x].base_address) { bank->size = pPrivate->pChip->details.bank[x].size_bytes; - LOG_DEBUG("SAM4 Set flash bank to %08X - %08X, idx %d", bank->base, bank->base + bank->size, x); + LOG_DEBUG("SAM4 Set flash bank to " TARGET_ADDR_FMT " - " + TARGET_ADDR_FMT ", idx %d", bank->base, + bank->base + bank->size, x); break; } } diff --git a/src/flash/nor/at91sam4l.c b/src/flash/nor/at91sam4l.c index 794ccbb01..f3b065f40 100644 --- a/src/flash/nor/at91sam4l.c +++ b/src/flash/nor/at91sam4l.c @@ -203,7 +203,8 @@ static int sam4l_flash_command(struct target *target, uint8_t cmd, int page) FLASH_BANK_COMMAND_HANDLER(sam4l_flash_bank_command) { if (bank->base != SAM4L_FLASH) { - LOG_ERROR("Address 0x%08" PRIx32 " invalid bank address (try 0x%08" PRIx32 + LOG_ERROR("Address " TARGET_ADDR_FMT + " invalid bank address (try 0x%08" PRIx32 "[at91sam4l series] )", bank->base, SAM4L_FLASH); return ERROR_FAIL; diff --git a/src/flash/nor/at91samd.c b/src/flash/nor/at91samd.c index 90df8bee9..029579ba8 100644 --- a/src/flash/nor/at91samd.c +++ b/src/flash/nor/at91samd.c @@ -906,7 +906,8 @@ free_pb: FLASH_BANK_COMMAND_HANDLER(samd_flash_bank_command) { if (bank->base != SAMD_FLASH) { - LOG_ERROR("Address 0x%08" PRIx32 " invalid bank address (try 0x%08" PRIx32 + LOG_ERROR("Address " TARGET_ADDR_FMT + " invalid bank address (try 0x%08" PRIx32 "[at91samd series] )", bank->base, SAMD_FLASH); return ERROR_FAIL; diff --git a/src/flash/nor/ath79.c b/src/flash/nor/ath79.c index 520f6c5b9..af2112a9e 100644 --- a/src/flash/nor/ath79.c +++ b/src/flash/nor/ath79.c @@ -794,7 +794,7 @@ static int ath79_probe(struct flash_bank *bank) ath79_info->io_base = target_device->io_base; - LOG_DEBUG("Found device %s at address 0x%" PRIx32, + LOG_DEBUG("Found device %s at address " TARGET_ADDR_FMT, target_device->name, bank->base); retval = read_flash_id(bank, &id); diff --git a/src/flash/nor/atsame5.c b/src/flash/nor/atsame5.c index 7490d0ed3..ff99e7d7c 100644 --- a/src/flash/nor/atsame5.c +++ b/src/flash/nor/atsame5.c @@ -730,9 +730,8 @@ free_pb: FLASH_BANK_COMMAND_HANDLER(same5_flash_bank_command) { if (bank->base != SAMD_FLASH) { - LOG_ERROR("Address 0x%08" PRIx32 " invalid bank address (try 0x%08" PRIx32 - "[same5] )", - bank->base, SAMD_FLASH); + LOG_ERROR("Address " TARGET_ADDR_FMT " invalid bank address (try " + "0x%08" PRIx32 "[same5] )", bank->base, SAMD_FLASH); return ERROR_FAIL; } diff --git a/src/flash/nor/bluenrg-x.c b/src/flash/nor/bluenrg-x.c index 2b568593a..f1b206201 100644 --- a/src/flash/nor/bluenrg-x.c +++ b/src/flash/nor/bluenrg-x.c @@ -404,9 +404,9 @@ static int bluenrgx_write(struct flash_bank *bank, const uint8_t *buffer, /* Stack pointer for program working area */ buf_set_u32(reg_params[4].value, 0, 32, write_algorithm_sp->address); - LOG_DEBUG("source->address = %08" TARGET_PRIxADDR, source->address); - LOG_DEBUG("source->address+ source->size = %08" TARGET_PRIxADDR, source->address+source->size); - LOG_DEBUG("write_algorithm_sp->address = %08" TARGET_PRIxADDR, write_algorithm_sp->address); + LOG_DEBUG("source->address = " TARGET_ADDR_FMT, source->address); + LOG_DEBUG("source->address+ source->size = " TARGET_ADDR_FMT, source->address+source->size); + LOG_DEBUG("write_algorithm_sp->address = " TARGET_ADDR_FMT, write_algorithm_sp->address); LOG_DEBUG("address = %08x", address+pre_size); LOG_DEBUG("count = %08x", count); diff --git a/src/flash/nor/cfi.c b/src/flash/nor/cfi.c index a2db50f33..163862817 100644 --- a/src/flash/nor/cfi.c +++ b/src/flash/nor/cfi.c @@ -889,8 +889,8 @@ static int cfi_intel_erase(struct flash_bank *bank, int first, int last) if (retval != ERROR_OK) return retval; - LOG_ERROR("couldn't erase block %i of flash bank at base 0x%" - PRIx32, i, bank->base); + LOG_ERROR("couldn't erase block %i of flash bank at base " + TARGET_ADDR_FMT, i, bank->base); return ERROR_FLASH_OPERATION_FAILED; } } @@ -937,8 +937,8 @@ static int cfi_spansion_erase(struct flash_bank *bank, int first, int last) if (retval != ERROR_OK) return retval; - LOG_ERROR("couldn't erase block %i of flash bank at base 0x%" - PRIx32, i, bank->base); + LOG_ERROR("couldn't erase block %i of flash bank at base " + TARGET_ADDR_FMT, i, bank->base); return ERROR_FLASH_OPERATION_FAILED; } } @@ -2001,8 +2001,9 @@ static int cfi_intel_write_word(struct flash_bank *bank, uint8_t *word, uint32_t if (retval != ERROR_OK) return retval; - LOG_ERROR("couldn't write word at base 0x%" PRIx32 ", address 0x%" PRIx32, - bank->base, address); + LOG_ERROR("couldn't write word at base " TARGET_ADDR_FMT + ", address 0x%" PRIx32, + bank->base, address); return ERROR_FLASH_OPERATION_FAILED; } @@ -2026,9 +2027,9 @@ static int cfi_intel_write_words(struct flash_bank *bank, const uint8_t *word, /* Check for valid range */ if (address & buffermask) { - LOG_ERROR("Write address at base 0x%" PRIx32 ", address 0x%" PRIx32 - " not aligned to 2^%d boundary", - bank->base, address, cfi_info->max_buf_write_size); + LOG_ERROR("Write address at base " TARGET_ADDR_FMT ", address 0x%" + PRIx32 " not aligned to 2^%d boundary", + bank->base, address, cfi_info->max_buf_write_size); return ERROR_FLASH_OPERATION_FAILED; } @@ -2056,7 +2057,8 @@ static int cfi_intel_write_words(struct flash_bank *bank, const uint8_t *word, return retval; LOG_ERROR( - "couldn't start buffer write operation at base 0x%" PRIx32 ", address 0x%" PRIx32, + "couldn't start buffer write operation at base " TARGET_ADDR_FMT + ", address 0x%" PRIx32, bank->base, address); return ERROR_FLASH_OPERATION_FAILED; @@ -2085,7 +2087,7 @@ static int cfi_intel_write_words(struct flash_bank *bank, const uint8_t *word, if (retval != ERROR_OK) return retval; - LOG_ERROR("Buffer write at base 0x%" PRIx32 + LOG_ERROR("Buffer write at base " TARGET_ADDR_FMT ", address 0x%" PRIx32 " failed.", bank->base, address); return ERROR_FLASH_OPERATION_FAILED; } @@ -2121,7 +2123,7 @@ static int cfi_spansion_write_word(struct flash_bank *bank, uint8_t *word, uint3 if (retval != ERROR_OK) return retval; - LOG_ERROR("couldn't write word at base 0x%" PRIx32 + LOG_ERROR("couldn't write word at base " TARGET_ADDR_FMT ", address 0x%" PRIx32, bank->base, address); return ERROR_FLASH_OPERATION_FAILED; } @@ -2147,7 +2149,7 @@ static int cfi_spansion_write_words(struct flash_bank *bank, const uint8_t *word /* Check for valid range */ if (address & buffermask) { - LOG_ERROR("Write address at base 0x%" PRIx32 + LOG_ERROR("Write address at base " TARGET_ADDR_FMT ", address 0x%" PRIx32 " not aligned to 2^%d boundary", bank->base, address, cfi_info->max_buf_write_size); return ERROR_FLASH_OPERATION_FAILED; @@ -2193,7 +2195,7 @@ static int cfi_spansion_write_words(struct flash_bank *bank, const uint8_t *word if (retval != ERROR_OK) return retval; - LOG_ERROR("couldn't write block at base 0x%" PRIx32 + LOG_ERROR("couldn't write block at base " TARGET_ADDR_FMT ", address 0x%" PRIx32 ", size 0x%" PRIx32, bank->base, address, bufferwsize); return ERROR_FLASH_OPERATION_FAILED; diff --git a/src/flash/nor/core.c b/src/flash/nor/core.c index c541afcd0..11b7ce4a0 100644 --- a/src/flash/nor/core.c +++ b/src/flash/nor/core.c @@ -99,7 +99,8 @@ int flash_driver_write(struct flash_bank *bank, retval = bank->driver->write(bank, buffer, offset, count); if (retval != ERROR_OK) { LOG_ERROR( - "error writing to flash at address 0x%08" PRIx32 " at offset 0x%8.8" PRIx32, + "error writing to flash at address " TARGET_ADDR_FMT + " at offset 0x%8.8" PRIx32, bank->base, offset); } @@ -117,7 +118,8 @@ int flash_driver_read(struct flash_bank *bank, retval = bank->driver->read(bank, buffer, offset, count); if (retval != ERROR_OK) { LOG_ERROR( - "error reading to flash at address 0x%08" PRIx32 " at offset 0x%8.8" PRIx32, + "error reading to flash at address " TARGET_ADDR_FMT + " at offset 0x%8.8" PRIx32, bank->base, offset); } @@ -268,7 +270,7 @@ int get_flash_bank_by_num(int num, struct flash_bank **bank) /* lookup flash bank by address, bank not found is success, but * result_bank is set to NULL. */ int get_flash_bank_by_addr(struct target *target, - uint32_t addr, + target_addr_t addr, bool check, struct flash_bank **result_bank) { @@ -294,7 +296,7 @@ int get_flash_bank_by_addr(struct target *target, } *result_bank = NULL; if (check) { - LOG_ERROR("No flash at address 0x%08" PRIx32, addr); + LOG_ERROR("No flash at address " TARGET_ADDR_FMT, addr); return ERROR_FAIL; } return ERROR_OK; @@ -414,13 +416,13 @@ int default_flash_blank_check(struct flash_bank *bank) * warning about those additions. */ static int flash_iterate_address_range_inner(struct target *target, - char *pad_reason, uint32_t addr, uint32_t length, + char *pad_reason, target_addr_t addr, uint32_t length, bool iterate_protect_blocks, int (*callback)(struct flash_bank *bank, int first, int last)) { struct flash_bank *c; struct flash_sector *block_array; - uint32_t last_addr = addr + length; /* first address AFTER end */ + target_addr_t last_addr = addr + length; /* first address AFTER end */ int first = -1; int last = -1; int i; @@ -491,10 +493,10 @@ static int flash_iterate_address_range_inner(struct target *target, else if (addr < end && pad_reason) { /* FIXME say how many bytes (e.g. 80 KB) */ LOG_WARNING("Adding extra %s range, " - "%#8.8x to %#8.8x", + "%#8.8x to " TARGET_ADDR_FMT, pad_reason, (unsigned) f->offset, - (unsigned) addr - 1); + addr - 1); first = i; } else continue; @@ -527,10 +529,10 @@ static int flash_iterate_address_range_inner(struct target *target, /* invalid start or end address? */ if (first == -1 || last == -1) { - LOG_ERROR("address range 0x%8.8x .. 0x%8.8x " - "is not sector-aligned", - (unsigned) (c->base + addr), - (unsigned) (c->base + last_addr - 1)); + LOG_ERROR("address range " TARGET_ADDR_FMT " .. " TARGET_ADDR_FMT + " is not sector-aligned", + c->base + addr, + c->base + last_addr - 1); return ERROR_FLASH_DST_BREAKS_ALIGNMENT; } @@ -545,7 +547,7 @@ static int flash_iterate_address_range_inner(struct target *target, * multiple chips. */ static int flash_iterate_address_range(struct target *target, - char *pad_reason, uint32_t addr, uint32_t length, + char *pad_reason, target_addr_t addr, uint32_t length, bool iterate_protect_blocks, int (*callback)(struct flash_bank *bank, int first, int last)) { @@ -579,7 +581,7 @@ static int flash_iterate_address_range(struct target *target, } int flash_erase_address_range(struct target *target, - bool pad, uint32_t addr, uint32_t length) + bool pad, target_addr_t addr, uint32_t length) { return flash_iterate_address_range(target, pad ? "erase" : NULL, addr, length, false, &flash_driver_erase); @@ -590,7 +592,8 @@ static int flash_driver_unprotect(struct flash_bank *bank, int first, int last) return flash_driver_protect(bank, 0, first, last); } -int flash_unlock_address_range(struct target *target, uint32_t addr, uint32_t length) +int flash_unlock_address_range(struct target *target, target_addr_t addr, + uint32_t length) { /* By default, pad to sector boundaries ... the real issue here * is that our (only) caller *permanently* removes protection, diff --git a/src/flash/nor/core.h b/src/flash/nor/core.h index 67de94e70..bd3aa7039 100644 --- a/src/flash/nor/core.h +++ b/src/flash/nor/core.h @@ -91,7 +91,7 @@ struct flash_bank { void *driver_priv; /**< Private driver storage pointer */ int bank_number; /**< The 'bank' (or chip number) of this instance. */ - uint32_t base; /**< The base address of this bank */ + target_addr_t base; /**< The base address of this bank */ uint32_t size; /**< The size of this chip bank, in bytes */ int chip_width; /**< Width of the chip in bytes (1,2,4 bytes) */ @@ -149,9 +149,9 @@ int flash_register_commands(struct command_context *cmd_ctx); * @returns ERROR_OK if successful; otherwise, an error code. */ int flash_erase_address_range(struct target *target, - bool pad, uint32_t addr, uint32_t length); + bool pad, target_addr_t addr, uint32_t length); -int flash_unlock_address_range(struct target *target, uint32_t addr, +int flash_unlock_address_range(struct target *target, target_addr_t addr, uint32_t length); /** @@ -263,7 +263,7 @@ struct flash_bank *get_flash_bank_by_num_noprobe(int num); * @param check return ERROR_OK and result_bank NULL if the bank does not exist * @returns The struct flash_bank located at @a addr, or NULL. */ -int get_flash_bank_by_addr(struct target *target, uint32_t addr, bool check, +int get_flash_bank_by_addr(struct target *target, target_addr_t addr, bool check, struct flash_bank **result_bank); /** * Allocate and fill an array of sectors or protection blocks. diff --git a/src/flash/nor/fespi.c b/src/flash/nor/fespi.c index a07972edd..ea47afd23 100644 --- a/src/flash/nor/fespi.c +++ b/src/flash/nor/fespi.c @@ -162,7 +162,7 @@ FLASH_BANK_COMMAND_HANDLER(fespi_flash_bank_command) int temp; COMMAND_PARSE_NUMBER(int, CMD_ARGV[6], temp); fespi_info->ctrl_base = (uint32_t) temp; - LOG_DEBUG("ASSUMING FESPI device at ctrl_base = 0x%" TARGET_PRIxADDR, + LOG_DEBUG("ASSUMING FESPI device at ctrl_base = " TARGET_ADDR_FMT, fespi_info->ctrl_base); } @@ -176,7 +176,7 @@ static int fespi_read_reg(struct flash_bank *bank, uint32_t *value, target_addr_ int result = target_read_u32(target, fespi_info->ctrl_base + address, value); if (result != ERROR_OK) { - LOG_ERROR("fespi_read_reg() error at 0x%" TARGET_PRIxADDR, + LOG_ERROR("fespi_read_reg() error at " TARGET_ADDR_FMT, fespi_info->ctrl_base + address); return result; } @@ -190,7 +190,7 @@ static int fespi_write_reg(struct flash_bank *bank, target_addr_t address, uint3 int result = target_write_u32(target, fespi_info->ctrl_base + address, value); if (result != ERROR_OK) { - LOG_ERROR("fespi_write_reg() error writing 0x%x to 0x%" TARGET_PRIxADDR, + LOG_ERROR("fespi_write_reg() error writing 0x%x to " TARGET_ADDR_FMT, value, fespi_info->ctrl_base + address); return result; } @@ -709,7 +709,7 @@ static int steps_execute(struct algorithm_steps *as, data_buf); free(data_buf); if (retval != ERROR_OK) { - LOG_ERROR("Failed to write data to 0x%" TARGET_PRIxADDR ": %d", + LOG_ERROR("Failed to write data to " TARGET_ADDR_FMT ": %d", data_wa->address, retval); goto exit; } @@ -718,7 +718,7 @@ static int steps_execute(struct algorithm_steps *as, algorithm_wa->address, algorithm_wa->address + 4, 10000, NULL); if (retval != ERROR_OK) { - LOG_ERROR("Failed to execute algorithm at 0x%" TARGET_PRIxADDR ": %d", + LOG_ERROR("Failed to execute algorithm at " TARGET_ADDR_FMT ": %d", algorithm_wa->address, retval); goto exit; } @@ -775,7 +775,7 @@ static int fespi_write(struct flash_bank *bank, const uint8_t *buffer, retval = target_write_buffer(target, algorithm_wa->address, sizeof(algorithm_bin), algorithm_bin); if (retval != ERROR_OK) { - LOG_ERROR("Failed to write code to 0x%" TARGET_PRIxADDR ": %d", + LOG_ERROR("Failed to write code to " TARGET_ADDR_FMT ": %d", algorithm_wa->address, retval); target_free_working_area(target, algorithm_wa); algorithm_wa = NULL; @@ -935,12 +935,13 @@ static int fespi_probe(struct flash_bank *bank) fespi_info->ctrl_base = target_device->ctrl_base; - LOG_DEBUG("Valid FESPI on device %s at address 0x%" PRIx32, + LOG_DEBUG("Valid FESPI on device %s at address " TARGET_ADDR_FMT, target_device->name, bank->base); } else { - LOG_DEBUG("Assuming FESPI as specified at address 0x%" TARGET_PRIxADDR - " with ctrl at 0x%x", fespi_info->ctrl_base, bank->base); + LOG_DEBUG("Assuming FESPI as specified at address " TARGET_ADDR_FMT + " with ctrl at " TARGET_ADDR_FMT, fespi_info->ctrl_base, + bank->base); } /* read and decode flash ID; returns in SW mode */ diff --git a/src/flash/nor/fm4.c b/src/flash/nor/fm4.c index d4d0f76b4..171cbd73e 100644 --- a/src/flash/nor/fm4.c +++ b/src/flash/nor/fm4.c @@ -272,7 +272,7 @@ static int fm4_flash_write(struct flash_bank *bank, const uint8_t *buffer, uint32_t halfwords = MIN(halfword_count, data_workarea->size / 2); uint32_t addr = bank->base + offset; - LOG_DEBUG("copying %" PRId32 " bytes to SRAM 0x%08" TARGET_PRIxADDR, + LOG_DEBUG("copying %" PRId32 " bytes to SRAM " TARGET_ADDR_FMT, MIN(halfwords * 2, byte_count), data_workarea->address); retval = target_write_buffer(target, data_workarea->address, diff --git a/src/flash/nor/kinetis.c b/src/flash/nor/kinetis.c index eca74a8b8..d82735553 100644 --- a/src/flash/nor/kinetis.c +++ b/src/flash/nor/kinetis.c @@ -1755,13 +1755,15 @@ static int kinetis_write_sections(struct flash_bank *bank, const uint8_t *buffer result = target_write_memory(bank->target, k_chip->progr_accel_ram, 4, size_aligned / 4, buffer_aligned); - LOG_DEBUG("section @ %08" PRIx32 " aligned begin %" PRIu32 ", end %" PRIu32, + LOG_DEBUG("section @ " TARGET_ADDR_FMT " aligned begin %" PRIu32 + ", end %" PRIu32, bank->base + offset, align_begin, align_end); } else result = target_write_memory(bank->target, k_chip->progr_accel_ram, 4, size_aligned / 4, buffer); - LOG_DEBUG("write section @ %08" PRIx32 " with length %" PRIu32 " bytes", + LOG_DEBUG("write section @ " TARGET_ADDR_FMT " with length %" PRIu32 + " bytes", bank->base + offset, size); if (result != ERROR_OK) { @@ -1776,12 +1778,14 @@ static int kinetis_write_sections(struct flash_bank *bank, const uint8_t *buffer 0, 0, 0, 0, &ftfx_fstat); if (result != ERROR_OK) { - LOG_ERROR("Error writing section at %08" PRIx32, bank->base + offset); + LOG_ERROR("Error writing section at " TARGET_ADDR_FMT, + bank->base + offset); break; } if (ftfx_fstat & 0x01) { - LOG_ERROR("Flash write error at %08" PRIx32, bank->base + offset); + LOG_ERROR("Flash write error at " TARGET_ADDR_FMT, + bank->base + offset); if (k_bank->prog_base == 0 && offset == FCF_ADDRESS + FCF_SIZE && (k_chip->flash_support & FS_WIDTH_256BIT)) { LOG_ERROR("Flash write immediately after the end of Flash Config Field shows error"); @@ -1820,7 +1824,7 @@ static int kinetis_write_inner(struct flash_bank *bank, const uint8_t *buffer, } } - LOG_DEBUG("flash write @ %08" PRIx32, bank->base + offset); + LOG_DEBUG("flash write @ " TARGET_ADDR_FMT, bank->base + offset); if (fallback == 0) { /* program section command */ @@ -1873,12 +1877,14 @@ static int kinetis_write_inner(struct flash_bank *bank, const uint8_t *buffer, 0, 0, 0, 0, &ftfx_fstat); if (result != ERROR_OK) { - LOG_ERROR("Error writing longword at %08" PRIx32, bank->base + offset); + LOG_ERROR("Error writing longword at " TARGET_ADDR_FMT, + bank->base + offset); break; } if (ftfx_fstat & 0x01) - LOG_ERROR("Flash write error at %08" PRIx32, bank->base + offset); + LOG_ERROR("Flash write error at " TARGET_ADDR_FMT, + bank->base + offset); buffer += 4; offset += 4; @@ -2769,7 +2775,7 @@ static int kinetis_info(struct flash_bank *bank, char *buf, int buf_size) uint32_t size_k = bank->size / 1024; snprintf(buf, buf_size, - "%s %s: %" PRIu32 "k %s bank %s at 0x%08" PRIx32, + "%s %s: %" PRIu32 "k %s bank %s at " TARGET_ADDR_FMT, bank->driver->name, k_chip->name, size_k, bank_class_names[k_bank->flash_class], bank->name, bank->base); diff --git a/src/flash/nor/kinetis_ke.c b/src/flash/nor/kinetis_ke.c index 8103b6394..9441a9d64 100644 --- a/src/flash/nor/kinetis_ke.c +++ b/src/flash/nor/kinetis_ke.c @@ -1175,7 +1175,7 @@ static int kinetis_ke_auto_probe(struct flash_bank *bank) static int kinetis_ke_info(struct flash_bank *bank, char *buf, int buf_size) { (void) snprintf(buf, buf_size, - "%s driver for flash bank %s at 0x%8.8" PRIx32 "", + "%s driver for flash bank %s at " TARGET_ADDR_FMT, bank->driver->name, bank->name, bank->base); return ERROR_OK; diff --git a/src/flash/nor/lpc2000.c b/src/flash/nor/lpc2000.c index e62fc7948..58afd79ac 100644 --- a/src/flash/nor/lpc2000.c +++ b/src/flash/nor/lpc2000.c @@ -719,7 +719,7 @@ static int lpc2000_iap_working_area_init(struct flash_bank *bank, struct working int retval = target_write_memory(target, (*iap_working_area)->address, 4, 2, jump_gate); if (retval != ERROR_OK) { - LOG_ERROR("Write memory at address 0x%8.8" TARGET_PRIxADDR " failed (check work_area definition)", + LOG_ERROR("Write memory at address " TARGET_ADDR_FMT " failed (check work_area definition)", (*iap_working_area)->address); target_free_working_area(target, *iap_working_area); } @@ -1186,8 +1186,8 @@ static int lpc2000_write(struct flash_bank *bank, const uint8_t *buffer, uint32_ free(last_buffer); } - LOG_DEBUG("writing 0x%" PRIx32 " bytes to address 0x%" PRIx32, thisrun_bytes, - bank->base + offset + bytes_written); + LOG_DEBUG("writing 0x%" PRIx32 " bytes to address " TARGET_ADDR_FMT, + thisrun_bytes, bank->base + offset + bytes_written); /* Write data */ param_table[0] = bank->base + offset + bytes_written; diff --git a/src/flash/nor/lpcspifi.c b/src/flash/nor/lpcspifi.c index a50584f77..a7e65ec49 100644 --- a/src/flash/nor/lpcspifi.c +++ b/src/flash/nor/lpcspifi.c @@ -186,7 +186,7 @@ static int lpcspifi_set_hw_mode(struct flash_bank *bank) return retval; } - LOG_DEBUG("Writing algorithm to working area at 0x%08" TARGET_PRIxADDR, + LOG_DEBUG("Writing algorithm to working area at " TARGET_ADDR_FMT, spifi_init_algorithm->address); /* Write algorithm to working area */ retval = target_write_buffer(target, diff --git a/src/flash/nor/niietcm4.c b/src/flash/nor/niietcm4.c index fd7d519a8..f2f447004 100644 --- a/src/flash/nor/niietcm4.c +++ b/src/flash/nor/niietcm4.c @@ -1584,9 +1584,11 @@ static int niietcm4_probe_k1921vk01t(struct flash_bank *bank) char info_bootflash_addr_str[64]; if (niietcm4_info->bflash_info_remap) - snprintf(info_bootflash_addr_str, sizeof(info_bootflash_addr_str), "0x%08x base adress", bank->base); + snprintf(info_bootflash_addr_str, sizeof(info_bootflash_addr_str), + TARGET_ADDR_FMT " base adress", bank->base); else - snprintf(info_bootflash_addr_str, sizeof(info_bootflash_addr_str), "not maped to global adress space"); + snprintf(info_bootflash_addr_str, sizeof(info_bootflash_addr_str), + "not mapped to global adress space"); snprintf(niietcm4_info->chip_brief, sizeof(niietcm4_info->chip_brief), diff --git a/src/flash/nor/nrf5.c b/src/flash/nor/nrf5.c index ea99b39e6..1e8dda393 100644 --- a/src/flash/nor/nrf5.c +++ b/src/flash/nor/nrf5.c @@ -906,7 +906,7 @@ FLASH_BANK_COMMAND_HANDLER(nrf5_flash_bank_command) bank->bank_number = 1; break; default: - LOG_ERROR("Invalid bank address 0x%08" PRIx32, bank->base); + LOG_ERROR("Invalid bank address " TARGET_ADDR_FMT, bank->base); return ERROR_FAIL; } diff --git a/src/flash/nor/numicro.c b/src/flash/nor/numicro.c index 4d951f0ee..ebf9d534f 100644 --- a/src/flash/nor/numicro.c +++ b/src/flash/nor/numicro.c @@ -1496,7 +1496,8 @@ static int numicro_erase(struct flash_bank *bank, int first, int last) return retval; for (i = first; i <= last; i++) { - LOG_DEBUG("erasing sector %d at address 0x%" PRIx32 "", i, bank->base + bank->sectors[i].offset); + LOG_DEBUG("erasing sector %d at address " TARGET_ADDR_FMT, i, + bank->base + bank->sectors[i].offset); retval = target_write_u32(target, NUMICRO_FLASH_ISPADR, bank->base + bank->sectors[i].offset); if (retval != ERROR_OK) return retval; @@ -1678,7 +1679,8 @@ static int numicro_get_flash_size(struct flash_bank *bank, const struct numicro_ for (size_t i = 0; i < cpu->n_banks; i++) { if (bank->base == cpu->bank[i].base) { *flash_size = cpu->bank[i].size; - LOG_INFO("bank base = 0x%08" PRIx32 ", size = 0x%08" PRIx32 "", bank->base, *flash_size); + LOG_INFO("bank base = " TARGET_ADDR_FMT ", size = 0x%08" + PRIx32, bank->base, *flash_size); return ERROR_OK; } } diff --git a/src/flash/nor/pic32mx.c b/src/flash/nor/pic32mx.c index e3b802870..852a8bd6f 100644 --- a/src/flash/nor/pic32mx.c +++ b/src/flash/nor/pic32mx.c @@ -620,7 +620,7 @@ static int pic32mx_write(struct flash_bank *bank, const uint8_t *buffer, uint32_ return ERROR_TARGET_NOT_HALTED; } - LOG_DEBUG("writing to flash at address 0x%08" PRIx32 " at offset 0x%8.8" PRIx32 + LOG_DEBUG("writing to flash at address " TARGET_ADDR_FMT " at offset 0x%8.8" PRIx32 " count: 0x%8.8" PRIx32 "", bank->base, offset, count); if (offset & 0x3) { diff --git a/src/flash/nor/psoc5lp.c b/src/flash/nor/psoc5lp.c index d8e1c1568..47567e766 100644 --- a/src/flash/nor/psoc5lp.c +++ b/src/flash/nor/psoc5lp.c @@ -1227,7 +1227,7 @@ static int psoc5lp_write(struct flash_bank *bank, const uint8_t *buffer, struct working_area *data_area = even_row ? even_row_area : odd_row_area; unsigned len = MIN(ROW_SIZE, byte_count); - LOG_DEBUG("Writing load command for array %u row %u at 0x%08" TARGET_PRIxADDR, + LOG_DEBUG("Writing load command for array %u row %u at " TARGET_ADDR_FMT, array_id, row, data_area->address); psoc5lp_spc_write_opcode_buffer(target, buf, SPC_LOAD_ROW); diff --git a/src/flash/nor/stm32h7x.c b/src/flash/nor/stm32h7x.c index fcfcf9142..ad76af4ad 100644 --- a/src/flash/nor/stm32h7x.c +++ b/src/flash/nor/stm32h7x.c @@ -833,8 +833,8 @@ static int stm32x_probe(struct flash_bank *bank) /* This is the first bank */ flash_size_in_kb = stm32x_info->part_info->first_bank_size_kb; } else { - LOG_WARNING("STM32H flash bank base address config is incorrect." - " 0x%" PRIx32 " but should rather be 0x%" PRIx32 " or 0x%" PRIx32, + LOG_WARNING("STM32H flash bank base address config is incorrect. " + TARGET_ADDR_FMT " but should rather be 0x%" PRIx32 " or 0x%" PRIx32, bank->base, base_address, second_bank_base); return ERROR_FAIL; } diff --git a/src/flash/nor/stm32lx.c b/src/flash/nor/stm32lx.c index 1be950fe0..814df8f6f 100644 --- a/src/flash/nor/stm32lx.c +++ b/src/flash/nor/stm32lx.c @@ -816,8 +816,9 @@ static int stm32lx_probe(struct flash_bank *bank) /* This is the first bank */ flash_size_in_kb = stm32lx_info->part_info.first_bank_size_kb; } else { - LOG_WARNING("STM32L flash bank base address config is incorrect." - " 0x%" PRIx32 " but should rather be 0x%" PRIx32 " or 0x%" PRIx32, + LOG_WARNING("STM32L flash bank base address config is incorrect. " + TARGET_ADDR_FMT " but should rather be 0x%" PRIx32 + " or 0x%" PRIx32, bank->base, base_address, second_bank_base); return ERROR_FAIL; } diff --git a/src/flash/nor/stmsmi.c b/src/flash/nor/stmsmi.c index 4d38e949b..b55c8b90b 100644 --- a/src/flash/nor/stmsmi.c +++ b/src/flash/nor/stmsmi.c @@ -559,13 +559,13 @@ static int stmsmi_probe(struct flash_bank *bank) stmsmi_info->bank_num = SMI_SEL_BANK3; break; default: - LOG_ERROR("Invalid SMI base address 0x%" PRIx32, bank->base); + LOG_ERROR("Invalid SMI base address " TARGET_ADDR_FMT, bank->base); return ERROR_FAIL; } io_base = target_device->io_base; stmsmi_info->io_base = io_base; - LOG_DEBUG("Valid SMI on device %s at address 0x%" PRIx32, + LOG_DEBUG("Valid SMI on device %s at address " TARGET_ADDR_FMT, target_device->name, bank->base); /* read and decode flash ID; returns in SW mode */ diff --git a/src/flash/nor/tcl.c b/src/flash/nor/tcl.c index f056e0753..7a402b0e7 100644 --- a/src/flash/nor/tcl.c +++ b/src/flash/nor/tcl.c @@ -112,7 +112,7 @@ COMMAND_HANDLER(handle_flash_info_command) LOG_WARNING("Flash protection check is not implemented."); command_print(CMD_CTX, - "#%d : %s at 0x%8.8" PRIx32 ", size 0x%8.8" PRIx32 + "#%d : %s at " TARGET_ADDR_FMT ", size 0x%8.8" PRIx32 ", buswidth %i, chipwidth %i", p->bank_number, p->driver->name, @@ -177,7 +177,7 @@ COMMAND_HANDLER(handle_flash_probe_command) retval = p->driver->probe(p); if (retval == ERROR_OK) command_print(CMD_CTX, - "flash '%s' found at 0x%8.8" PRIx32, + "flash '%s' found at " TARGET_ADDR_FMT, p->driver->name, p->base); } else { @@ -205,7 +205,8 @@ COMMAND_HANDLER(handle_flash_erase_check_command) command_print(CMD_CTX, "successfully checked erase state"); else { command_print(CMD_CTX, - "unknown error when checking erase state of flash bank #%s at 0x%8.8" PRIx32, + "unknown error when checking erase state of flash bank #%s at " + TARGET_ADDR_FMT, CMD_ARGV[0], p->base); } @@ -239,7 +240,7 @@ COMMAND_HANDLER(handle_flash_erase_address_command) { struct flash_bank *p; int retval = ERROR_OK; - uint32_t address; + target_addr_t address; uint32_t length; bool do_pad = false; bool do_unlock = false; @@ -262,7 +263,7 @@ COMMAND_HANDLER(handle_flash_erase_address_command) if (CMD_ARGC != 2) return ERROR_COMMAND_SYNTAX_ERROR; - COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], address); + COMMAND_PARSE_ADDRESS(CMD_ARGV[0], address); COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], length); if (length <= 0) { @@ -288,7 +289,8 @@ COMMAND_HANDLER(handle_flash_erase_address_command) retval = flash_erase_address_range(target, do_pad, address, length); if ((ERROR_OK == retval) && (duration_measure(&bench) == ERROR_OK)) { - command_print(CMD_CTX, "erased address 0x%8.8" PRIx32 " (length %" PRIi32 ")" + command_print(CMD_CTX, "erased address " TARGET_ADDR_FMT " (length %" + PRIi32 ")" " in %fs (%0.3f KiB/s)", address, length, duration_elapsed(&bench), duration_kbps(&bench, length)); } @@ -1138,7 +1140,7 @@ COMMAND_HANDLER(handle_flash_bank_command) c->name = strdup(bank_name); c->target = target; c->driver = driver; - COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], c->base); + COMMAND_PARSE_NUMBER(target_addr, CMD_ARGV[1], c->base); COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], c->size); COMMAND_PARSE_NUMBER(int, CMD_ARGV[3], c->chip_width); COMMAND_PARSE_NUMBER(int, CMD_ARGV[4], c->bus_width); @@ -1148,8 +1150,8 @@ COMMAND_HANDLER(handle_flash_bank_command) int retval; retval = CALL_COMMAND_HANDLER(driver->flash_bank_command, c); if (ERROR_OK != retval) { - LOG_ERROR("'%s' driver rejected flash bank at 0x%8.8" PRIx32 "; usage: %s", - driver_name, c->base, driver->usage); + LOG_ERROR("'%s' driver rejected flash bank at " TARGET_ADDR_FMT + "; usage: %s", driver_name, c->base, driver->usage); free(c); return retval; } @@ -1169,7 +1171,7 @@ COMMAND_HANDLER(handle_flash_banks_command) unsigned n = 0; for (struct flash_bank *p = flash_bank_list(); p; p = p->next, n++) { - LOG_USER("#%d : %s (%s) at 0x%8.8" PRIx32 ", size 0x%8.8" PRIx32 ", " + LOG_USER("#%d : %s (%s) at " TARGET_ADDR_FMT ", size 0x%8.8" PRIx32 ", " "buswidth %u, chipwidth %u", p->bank_number, p->name, p->driver->name, p->base, p->size, p->bus_width, p->chip_width); diff --git a/src/flash/nor/tms470.c b/src/flash/nor/tms470.c index 2435e7990..62fe2f54b 100644 --- a/src/flash/nor/tms470.c +++ b/src/flash/nor/tms470.c @@ -165,7 +165,8 @@ static int tms470_read_part_info(struct flash_bank *bank) part_name = "TMS470R1A256"; if (bank->base >= 0x00040000) { - LOG_ERROR("No %s flash bank contains base address 0x%08" PRIx32 ".", + LOG_ERROR("No %s flash bank contains base address " + TARGET_ADDR_FMT ".", part_name, bank->base); return ERROR_FLASH_OPERATION_FAILED; @@ -204,7 +205,7 @@ static int tms470_read_part_info(struct flash_bank *bank) (void)memcpy(bank->sectors, TMS470R1A288_BANK1_SECTORS, sizeof(TMS470R1A288_BANK1_SECTORS)); } else { - LOG_ERROR("No %s flash bank contains base address 0x%08" PRIx32 ".", + LOG_ERROR("No %s flash bank contains base address " TARGET_ADDR_FMT ".", part_name, bank->base); return ERROR_FLASH_OPERATION_FAILED; } @@ -244,7 +245,7 @@ static int tms470_read_part_info(struct flash_bank *bank) (void)memcpy(bank->sectors, TMS470R1A384_BANK2_SECTORS, sizeof(TMS470R1A384_BANK2_SECTORS)); } else { - LOG_ERROR("No %s flash bank contains base address 0x%08" PRIx32 ".", + LOG_ERROR("No %s flash bank contains base address " TARGET_ADDR_FMT ".", part_name, bank->base); return ERROR_FLASH_OPERATION_FAILED; } @@ -900,8 +901,8 @@ static int tms470_write(struct flash_bank *bank, const uint8_t *buffer, uint32_t tms470_read_part_info(bank); - LOG_INFO("Writing %" PRId32 " bytes starting at 0x%08" PRIx32 "", count, bank->base + - offset); + LOG_INFO("Writing %" PRId32 " bytes starting at " TARGET_ADDR_FMT, + count, bank->base + offset); /* set GLBCTRL.4 */ target_read_u32(target, 0xFFFFFFDC, &glbctrl); diff --git a/src/flash/nor/virtual.c b/src/flash/nor/virtual.c index 15c4bffa7..217f7a4df 100644 --- a/src/flash/nor/virtual.c +++ b/src/flash/nor/virtual.c @@ -185,7 +185,7 @@ static int virtual_info(struct flash_bank *bank, char *buf, int buf_size) if (master_bank == NULL) return ERROR_FLASH_OPERATION_FAILED; - snprintf(buf, buf_size, "%s driver for flash bank %s at 0x%8.8" PRIx32 "", + snprintf(buf, buf_size, "%s driver for flash bank %s at " TARGET_ADDR_FMT, bank->driver->name, master_bank->name, master_bank->base); return ERROR_OK; diff --git a/src/flash/nor/xmc1xxx.c b/src/flash/nor/xmc1xxx.c index 4b25398bc..262300cc8 100644 --- a/src/flash/nor/xmc1xxx.c +++ b/src/flash/nor/xmc1xxx.c @@ -305,7 +305,7 @@ static int xmc1xxx_write(struct flash_bank *bank, const uint8_t *buffer, uint32_t blocks = MIN(block_count, data_workarea->size / NVM_BLOCK_SIZE); uint32_t addr = bank->base + offset; - LOG_DEBUG("copying %" PRId32 " bytes to SRAM 0x%08" TARGET_PRIxADDR, + LOG_DEBUG("copying %" PRId32 " bytes to SRAM " TARGET_ADDR_FMT, MIN(blocks * NVM_BLOCK_SIZE, byte_count), data_workarea->address); diff --git a/src/flash/nor/xmc4xxx.c b/src/flash/nor/xmc4xxx.c index 0b6d48c1b..d862e857e 100644 --- a/src/flash/nor/xmc4xxx.c +++ b/src/flash/nor/xmc4xxx.c @@ -778,7 +778,7 @@ static int xmc4xxx_write(struct flash_bank *bank, const uint8_t *buffer, memcpy(&tmp_buf[start_pad], buffer, remaining); if (end_pad) { - LOG_INFO("Padding end of page @%08"PRIx32" by %d bytes", + LOG_INFO("Padding end of page @" TARGET_ADDR_FMT " by %d bytes", bank->base + offset, end_pad); memset(&tmp_buf[256 - end_pad], 0xff, end_pad); } From d8e1622e4c1043fd05eafb6249afc995ebf03c4d Mon Sep 17 00:00:00 2001 From: Tomas Vanek Date: Wed, 27 Feb 2019 02:31:30 +0100 Subject: [PATCH 50/70] flash/nor/tcl.c: use COMMAND_PARSE_ADDRESS instead of conditional compilation #if BUILD_TARGET64 Change-Id: I005ae0b3a4ed127c0f59219b1c6b185a2c76c76e Signed-off-by: Tomas Vanek Reviewed-on: http://openocd.zylin.com/4977 Tested-by: jenkins Reviewed-by: Tim Newsome --- src/flash/nor/tcl.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/flash/nor/tcl.c b/src/flash/nor/tcl.c index 7a402b0e7..93c4d2846 100644 --- a/src/flash/nor/tcl.c +++ b/src/flash/nor/tcl.c @@ -486,11 +486,7 @@ COMMAND_HANDLER(handle_flash_fill_command) if (CMD_ARGC != 3) return ERROR_COMMAND_SYNTAX_ERROR; -#if BUILD_TARGET64 - COMMAND_PARSE_NUMBER(u64, CMD_ARGV[0], address); -#else - COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], address); -#endif + COMMAND_PARSE_ADDRESS(CMD_ARGV[0], address); COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], pattern); COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], count); From 380502d82074b799f10d9671c4fe0fe24eb93023 Mon Sep 17 00:00:00 2001 From: Tomas Vanek Date: Thu, 7 Feb 2019 14:17:03 +0100 Subject: [PATCH 51/70] target/breakpoints: make internal functions static While on it add two missing new lines. Change-Id: I0d54740479bc462b734f91686f0931824796b598 Signed-off-by: Tomas Vanek Reviewed-on: http://openocd.zylin.com/4888 Tested-by: jenkins Reviewed-by: Marc Schink --- src/target/breakpoints.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/target/breakpoints.c b/src/target/breakpoints.c index 94e8a823d..7ad194256 100644 --- a/src/target/breakpoints.c +++ b/src/target/breakpoints.c @@ -41,7 +41,7 @@ static const char * const watchpoint_rw_strings[] = { /* monotonic counter/id-number for breakpoints and watch points */ static int bpwp_unique_id; -int breakpoint_add_internal(struct target *target, +static int breakpoint_add_internal(struct target *target, target_addr_t address, uint32_t length, enum breakpoint_type type) @@ -106,7 +106,7 @@ fail: return ERROR_OK; } -int context_breakpoint_add_internal(struct target *target, +static int context_breakpoint_add_internal(struct target *target, uint32_t asid, uint32_t length, enum breakpoint_type type) @@ -158,7 +158,7 @@ int context_breakpoint_add_internal(struct target *target, return ERROR_OK; } -int hybrid_breakpoint_add_internal(struct target *target, +static int hybrid_breakpoint_add_internal(struct target *target, target_addr_t address, uint32_t asid, uint32_t length, @@ -241,6 +241,7 @@ int breakpoint_add(struct target *target, } else return breakpoint_add_internal(target, address, length, type); } + int context_breakpoint_add(struct target *target, uint32_t asid, uint32_t length, @@ -262,6 +263,7 @@ int context_breakpoint_add(struct target *target, } else return context_breakpoint_add_internal(target, asid, length, type); } + int hybrid_breakpoint_add(struct target *target, target_addr_t address, uint32_t asid, @@ -310,7 +312,7 @@ static void breakpoint_free(struct target *target, struct breakpoint *breakpoint free(breakpoint); } -int breakpoint_remove_internal(struct target *target, target_addr_t address) +static int breakpoint_remove_internal(struct target *target, target_addr_t address) { struct breakpoint *breakpoint = target->breakpoints; From 420a692e0fae34a59eb3c33932362812e33f5583 Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Thu, 28 Feb 2019 11:31:11 +0100 Subject: [PATCH 52/70] target/adi_v5_swd: update cached value on write to DP_SELECT When the register DP_SELECT is written directly, e.g. with command dpreg 8 the cached value in OpenOCD is not completely updated with the new value, thus creating issues in the following AP and DP read/write that rely on the cached value. Update the cached value while writing to DP_SELECT. Change-Id: I8221b10cd6fc1fbe73e6b834b68820b43480e1a2 Signed-off-by: Antonio Borneo Reviewed-on: http://openocd.zylin.com/4979 Tested-by: jenkins Reviewed-by: Tomas Vanek --- src/target/adi_v5_swd.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/target/adi_v5_swd.c b/src/target/adi_v5_swd.c index eb181cb65..d099f4e71 100644 --- a/src/target/adi_v5_swd.c +++ b/src/target/adi_v5_swd.c @@ -211,7 +211,10 @@ static int swd_queue_dp_write(struct adiv5_dap *dap, unsigned reg, return retval; swd_finish_read(dap); - swd_queue_dp_bankselect(dap, reg); + if (reg == DP_SELECT) + dap->select = data & (DP_SELECT_APSEL | DP_SELECT_APBANK | DP_SELECT_DPBANK); + else + swd_queue_dp_bankselect(dap, reg); swd->write_reg(swd_cmd(false, false, reg), data, 0); return check_sync(dap); From 0323c9bcbd608f74ab40f63eb62e0cdb4d022401 Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Thu, 28 Feb 2019 12:29:49 +0100 Subject: [PATCH 53/70] target/adi_v5_swd: improve error check while updating DP_SELECT Write to register DP_SELECT can fail, but both functions swd_queue_dp_bankselect() and swd_queue_ap_bankselect() return void and do not propagate the error. Change the return type of the two functions to int and check the returned value. Invalidate the cached value of DP_SELECT if the write fails. Change-Id: Iba6ef8b0c2332e7f7efb66337d558fb7a4a0d39c Signed-off-by: Antonio Borneo Reviewed-on: http://openocd.zylin.com/4980 Tested-by: jenkins Reviewed-by: Tomas Vanek --- src/target/adi_v5_swd.c | 55 +++++++++++++++++++++++++++++++---------- 1 file changed, 42 insertions(+), 13 deletions(-) diff --git a/src/target/adi_v5_swd.c b/src/target/adi_v5_swd.c index d099f4e71..d92e2961e 100644 --- a/src/target/adi_v5_swd.c +++ b/src/target/adi_v5_swd.c @@ -166,22 +166,26 @@ static int swd_queue_ap_abort(struct adiv5_dap *dap, uint8_t *ack) } /** Select the DP register bank matching bits 7:4 of reg. */ -static void swd_queue_dp_bankselect(struct adiv5_dap *dap, unsigned reg) +static int swd_queue_dp_bankselect(struct adiv5_dap *dap, unsigned reg) { /* Only register address 4 is banked. */ if ((reg & 0xf) != 4) - return; + return ERROR_OK; uint32_t select_dp_bank = (reg & 0x000000F0) >> 4; uint32_t sel = select_dp_bank | (dap->select & (DP_SELECT_APSEL | DP_SELECT_APBANK)); if (sel == dap->select) - return; + return ERROR_OK; dap->select = sel; - swd_queue_dp_write(dap, DP_SELECT, sel); + int retval = swd_queue_dp_write(dap, DP_SELECT, sel); + if (retval != ERROR_OK) + dap->select = DP_SELECT_INVALID; + + return retval; } static int swd_queue_dp_read(struct adiv5_dap *dap, unsigned reg, @@ -194,7 +198,10 @@ static int swd_queue_dp_read(struct adiv5_dap *dap, unsigned reg, if (retval != ERROR_OK) return retval; - swd_queue_dp_bankselect(dap, reg); + retval = swd_queue_dp_bankselect(dap, reg); + if (retval != ERROR_OK) + return retval; + swd->read_reg(swd_cmd(true, false, reg), data, 0); return check_sync(dap); @@ -211,17 +218,29 @@ static int swd_queue_dp_write(struct adiv5_dap *dap, unsigned reg, return retval; swd_finish_read(dap); - if (reg == DP_SELECT) + if (reg == DP_SELECT) { dap->select = data & (DP_SELECT_APSEL | DP_SELECT_APBANK | DP_SELECT_DPBANK); - else - swd_queue_dp_bankselect(dap, reg); + + swd->write_reg(swd_cmd(false, false, reg), data, 0); + + retval = check_sync(dap); + if (retval != ERROR_OK) + dap->select = DP_SELECT_INVALID; + + return retval; + } + + retval = swd_queue_dp_bankselect(dap, reg); + if (retval != ERROR_OK) + return retval; + swd->write_reg(swd_cmd(false, false, reg), data, 0); return check_sync(dap); } /** Select the AP register bank matching bits 7:4 of reg. */ -static void swd_queue_ap_bankselect(struct adiv5_ap *ap, unsigned reg) +static int swd_queue_ap_bankselect(struct adiv5_ap *ap, unsigned reg) { struct adiv5_dap *dap = ap->dap; uint32_t sel = ((uint32_t)ap->ap_num << 24) @@ -229,11 +248,15 @@ static void swd_queue_ap_bankselect(struct adiv5_ap *ap, unsigned reg) | (dap->select & DP_SELECT_DPBANK); if (sel == dap->select) - return; + return ERROR_OK; dap->select = sel; - swd_queue_dp_write(dap, DP_SELECT, sel); + int retval = swd_queue_dp_write(dap, DP_SELECT, sel); + if (retval != ERROR_OK) + dap->select = DP_SELECT_INVALID; + + return retval; } static int swd_queue_ap_read(struct adiv5_ap *ap, unsigned reg, @@ -247,7 +270,10 @@ static int swd_queue_ap_read(struct adiv5_ap *ap, unsigned reg, if (retval != ERROR_OK) return retval; - swd_queue_ap_bankselect(ap, reg); + retval = swd_queue_ap_bankselect(ap, reg); + if (retval != ERROR_OK) + return retval; + swd->read_reg(swd_cmd(true, true, reg), dap->last_read, ap->memaccess_tck); dap->last_read = data; @@ -266,7 +292,10 @@ static int swd_queue_ap_write(struct adiv5_ap *ap, unsigned reg, return retval; swd_finish_read(dap); - swd_queue_ap_bankselect(ap, reg); + retval = swd_queue_ap_bankselect(ap, reg); + if (retval != ERROR_OK) + return retval; + swd->write_reg(swd_cmd(false, true, reg), data, ap->memaccess_tck); return check_sync(dap); From 8d748f426c7a9c750ffc7cabfbb87bc2cecd82d3 Mon Sep 17 00:00:00 2001 From: Christopher Head Date: Tue, 30 Oct 2018 14:37:22 -0700 Subject: [PATCH 54/70] flash/stm32h7x: remove IWDG1_SW separate variable Bit 4 in OPTSR is IWDG1_SW (the code originally called it IWDG1_HW, but the reference manual refers to it as IWDG1_SW). This is broken out into a separate variable, independent_watchdog_selection, in stm32x_options. However, this is not necessary: bit 4 is included in the user_options field, which includes all of bits 2 through 7, and independent_watchdog_selection is not referenced anywhere else. Delete the field and just rely on user_options to transport that bit, along with all the other bits it contains, between stm32x_read_options and stm32x_write_options. Change-Id: I4da63df9272cf091267b956c412b95671ea1d3c9 Signed-off-by: Christopher Head Reviewed-on: http://openocd.zylin.com/4744 Tested-by: jenkins Reviewed-by: Tarek BOCHKATI Reviewed-by: Tomas Vanek --- src/flash/nor/stm32h7x.c | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/src/flash/nor/stm32h7x.c b/src/flash/nor/stm32h7x.c index ad76af4ad..d21e9fa5e 100644 --- a/src/flash/nor/stm32h7x.c +++ b/src/flash/nor/stm32h7x.c @@ -78,9 +78,6 @@ #define OPT_LOCK (1 << 0) #define OPT_START (1 << 1) -/* FLASH_OPTCUR bit definitions (reading) */ -#define IWDG1_HW (1 << 4) - /* register unlock keys */ #define KEY1 0x45670123 #define KEY2 0xCDEF89AB @@ -109,7 +106,6 @@ struct stm32x_options { uint8_t user_options; uint8_t user2_options; uint8_t user3_options; - uint8_t independent_watchdog_selection; }; struct stm32h7x_part_info { @@ -327,11 +323,6 @@ static int stm32x_read_options(struct flash_bank *bank) stm32x_info->option_bytes.user2_options = (optiondata >> 16) & 0xff; stm32x_info->option_bytes.user3_options = (optiondata >> 24) & 0x83; - if (optiondata & IWDG1_HW) - stm32x_info->option_bytes.independent_watchdog_selection = 1; - else - stm32x_info->option_bytes.independent_watchdog_selection = 0; - if (stm32x_info->option_bytes.RDP != 0xAA) LOG_INFO("Device Security Bit Set"); @@ -368,11 +359,6 @@ static int stm32x_write_options(struct flash_bank *bank) optiondata |= (stm32x_info->option_bytes.user2_options & 0xff) << 16; optiondata |= (stm32x_info->option_bytes.user3_options & 0x83) << 24; - if (stm32x_info->option_bytes.independent_watchdog_selection) - optiondata |= IWDG1_HW; - else - optiondata &= ~IWDG1_HW; - /* program options */ retval = target_write_u32(target, FLASH_REG_BASE_B0 + FLASH_OPTPRG, optiondata); if (retval != ERROR_OK) From 489eaadf5650099d5c42e9b2c1b1c871607b4771 Mon Sep 17 00:00:00 2001 From: Marc Schink Date: Tue, 26 Feb 2019 14:07:20 +0100 Subject: [PATCH 55/70] target/dsp563xx: Use 'bool' data type Change-Id: Ie7ee82bf04c76ef899ae8b19105158e71b69ae2c Signed-off-by: Marc Schink Reviewed-on: http://openocd.zylin.com/4962 Tested-by: jenkins Reviewed-by: Antonio Borneo --- src/target/dsp563xx.c | 46 +++++++++++++++++++++---------------------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/src/target/dsp563xx.c b/src/target/dsp563xx.c index 899161694..5f1338474 100644 --- a/src/target/dsp563xx.c +++ b/src/target/dsp563xx.c @@ -384,8 +384,8 @@ static int dsp563xx_read_core_reg(struct target *target, int num) reg_value = dsp563xx->core_regs[num]; buf_set_u32(dsp563xx->core_cache->reg_list[num].value, 0, 32, reg_value); - dsp563xx->core_cache->reg_list[num].valid = 1; - dsp563xx->core_cache->reg_list[num].dirty = 0; + dsp563xx->core_cache->reg_list[num].valid = true; + dsp563xx->core_cache->reg_list[num].dirty = false; return ERROR_OK; } @@ -400,8 +400,8 @@ static int dsp563xx_write_core_reg(struct target *target, int num) reg_value = buf_get_u32(dsp563xx->core_cache->reg_list[num].value, 0, 32); dsp563xx->core_regs[num] = reg_value; - dsp563xx->core_cache->reg_list[num].valid = 1; - dsp563xx->core_cache->reg_list[num].dirty = 0; + dsp563xx->core_cache->reg_list[num].valid = true; + dsp563xx->core_cache->reg_list[num].dirty = false; return ERROR_OK; } @@ -432,8 +432,8 @@ static int dsp563xx_set_core_reg(struct reg *reg, uint8_t *buf) return ERROR_TARGET_NOT_HALTED; buf_set_u32(reg->value, 0, reg->size, value); - reg->dirty = 1; - reg->valid = 1; + reg->dirty = true; + reg->valid = true; return ERROR_OK; } @@ -473,8 +473,8 @@ static void dsp563xx_build_reg_cache(struct target *target) reg_list[i].name = dsp563xx_regs[i].name; reg_list[i].size = 32; /* dsp563xx_regs[i].bits; */ reg_list[i].value = calloc(1, 4); - reg_list[i].dirty = 0; - reg_list[i].valid = 0; + reg_list[i].dirty = false; + reg_list[i].valid = false; reg_list[i].type = &dsp563xx_reg_type; reg_list[i].arch_info = &arch_info[i]; } @@ -508,7 +508,7 @@ static int dsp563xx_reg_read_high_io(struct target *target, uint32_t instr_mask, if (err != ERROR_OK) return err; /* r0 is no longer valid on target */ - dsp563xx->core_cache->reg_list[DSP563XX_REG_IDX_R0].dirty = 1; + dsp563xx->core_cache->reg_list[DSP563XX_REG_IDX_R0].dirty = true; return ERROR_OK; } @@ -534,7 +534,7 @@ static int dsp563xx_reg_write_high_io(struct target *target, uint32_t instr_mask return err; /* r0 is no longer valid on target */ - dsp563xx->core_cache->reg_list[DSP563XX_REG_IDX_R0].dirty = 1; + dsp563xx->core_cache->reg_list[DSP563XX_REG_IDX_R0].dirty = true; return ERROR_OK; } @@ -745,7 +745,7 @@ static int dsp563xx_read_register(struct target *target, int num, int force) struct dsp563xx_core_reg *arch_info; if (force) - dsp563xx->core_cache->reg_list[num].valid = 0; + dsp563xx->core_cache->reg_list[num].valid = false; if (!dsp563xx->core_cache->reg_list[num].valid) { arch_info = dsp563xx->core_cache->reg_list[num].arch_info; @@ -795,7 +795,7 @@ static int dsp563xx_write_register(struct target *target, int num, int force) struct dsp563xx_core_reg *arch_info; if (force) - dsp563xx->core_cache->reg_list[num].dirty = 1; + dsp563xx->core_cache->reg_list[num].dirty = true; if (dsp563xx->core_cache->reg_list[num].dirty) { arch_info = dsp563xx->core_cache->reg_list[num].arch_info; @@ -884,8 +884,8 @@ static void dsp563xx_invalidate_x_context(struct target *target, if ((arch_info->instr_mask >= addr_start) && (arch_info->instr_mask <= addr_end)) { - dsp563xx->core_cache->reg_list[i].valid = 0; - dsp563xx->core_cache->reg_list[i].dirty = 0; + dsp563xx->core_cache->reg_list[i].valid = false; + dsp563xx->core_cache->reg_list[i].dirty = false; } } } @@ -985,7 +985,7 @@ static int dsp563xx_debug_init(struct target *target) err = dsp563xx_once_execute_dw_ir(target->tap, 1, arch_info->instr_mask, sr); if (err != ERROR_OK) return err; - dsp563xx->core_cache->reg_list[DSP563XX_REG_IDX_SR].dirty = 1; + dsp563xx->core_cache->reg_list[DSP563XX_REG_IDX_SR].dirty = true; } err = dsp563xx_read_register(target, DSP563XX_REG_IDX_N0, 0); @@ -1007,7 +1007,7 @@ static int dsp563xx_debug_init(struct target *target) if (err != ERROR_OK) return err; } - dsp563xx->core_cache->reg_list[DSP563XX_REG_IDX_N0].dirty = 1; + dsp563xx->core_cache->reg_list[DSP563XX_REG_IDX_N0].dirty = true; if (dsp563xx->core_regs[DSP563XX_REG_IDX_N1] != 0x000000) { arch_info = dsp563xx->core_cache->reg_list[DSP563XX_REG_IDX_N1].arch_info; @@ -1015,7 +1015,7 @@ static int dsp563xx_debug_init(struct target *target) if (err != ERROR_OK) return err; } - dsp563xx->core_cache->reg_list[DSP563XX_REG_IDX_N1].dirty = 1; + dsp563xx->core_cache->reg_list[DSP563XX_REG_IDX_N1].dirty = true; if (dsp563xx->core_regs[DSP563XX_REG_IDX_M0] != 0xffffff) { arch_info = dsp563xx->core_cache->reg_list[DSP563XX_REG_IDX_M0].arch_info; @@ -1023,7 +1023,7 @@ static int dsp563xx_debug_init(struct target *target) if (err != ERROR_OK) return err; } - dsp563xx->core_cache->reg_list[DSP563XX_REG_IDX_M0].dirty = 1; + dsp563xx->core_cache->reg_list[DSP563XX_REG_IDX_M0].dirty = true; if (dsp563xx->core_regs[DSP563XX_REG_IDX_M1] != 0xffffff) { arch_info = dsp563xx->core_cache->reg_list[DSP563XX_REG_IDX_M1].arch_info; @@ -1031,7 +1031,7 @@ static int dsp563xx_debug_init(struct target *target) if (err != ERROR_OK) return err; } - dsp563xx->core_cache->reg_list[DSP563XX_REG_IDX_M1].dirty = 1; + dsp563xx->core_cache->reg_list[DSP563XX_REG_IDX_M1].dirty = true; err = dsp563xx_save_context(target); if (err != ERROR_OK) @@ -1552,9 +1552,9 @@ static int dsp563xx_read_memory_core(struct target *target, dsp563xx->read_core_reg(target, DSP563XX_REG_IDX_R1); /* r0 is no longer valid on target */ - dsp563xx->core_cache->reg_list[DSP563XX_REG_IDX_R0].dirty = 1; + dsp563xx->core_cache->reg_list[DSP563XX_REG_IDX_R0].dirty = true; /* r1 is no longer valid on target */ - dsp563xx->core_cache->reg_list[DSP563XX_REG_IDX_R1].dirty = 1; + dsp563xx->core_cache->reg_list[DSP563XX_REG_IDX_R1].dirty = true; x = count; b = buffer; @@ -1734,9 +1734,9 @@ static int dsp563xx_write_memory_core(struct target *target, dsp563xx->read_core_reg(target, DSP563XX_REG_IDX_R1); /* r0 is no longer valid on target */ - dsp563xx->core_cache->reg_list[DSP563XX_REG_IDX_R0].dirty = 1; + dsp563xx->core_cache->reg_list[DSP563XX_REG_IDX_R0].dirty = true; /* r1 is no longer valid on target */ - dsp563xx->core_cache->reg_list[DSP563XX_REG_IDX_R1].dirty = 1; + dsp563xx->core_cache->reg_list[DSP563XX_REG_IDX_R1].dirty = true; x = count; b = buffer; From b9eecd9c269b14d2458a38d47f98925dbe2d6e26 Mon Sep 17 00:00:00 2001 From: Marc Schink Date: Tue, 26 Feb 2019 14:09:46 +0100 Subject: [PATCH 56/70] target/xscale: Use 'bool' data type Change-Id: I4e117f4e6c8c0850f565587f68f41d88da0d6b0b Signed-off-by: Marc Schink Reviewed-on: http://openocd.zylin.com/4968 Tested-by: jenkins Reviewed-by: Tomas Vanek Reviewed-by: Antonio Borneo --- src/target/xscale.c | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/src/target/xscale.c b/src/target/xscale.c index 3ac455390..09abd9ef0 100644 --- a/src/target/xscale.c +++ b/src/target/xscale.c @@ -212,8 +212,8 @@ static int xscale_read_dcsr(struct target *target) return retval; } - xscale->reg_cache->reg_list[XSCALE_DCSR].dirty = 0; - xscale->reg_cache->reg_list[XSCALE_DCSR].valid = 1; + xscale->reg_cache->reg_list[XSCALE_DCSR].dirty = false; + xscale->reg_cache->reg_list[XSCALE_DCSR].valid = true; /* write the register with the value we just read * on this second pass, only the first bit of field0 is guaranteed to be 0) @@ -624,8 +624,8 @@ static int xscale_write_dcsr(struct target *target, int hold_rst, int ext_dbg_br return retval; } - xscale->reg_cache->reg_list[XSCALE_DCSR].dirty = 0; - xscale->reg_cache->reg_list[XSCALE_DCSR].valid = 1; + xscale->reg_cache->reg_list[XSCALE_DCSR].dirty = false; + xscale->reg_cache->reg_list[XSCALE_DCSR].valid = true; return ERROR_OK; } @@ -868,21 +868,21 @@ static int xscale_debug_entry(struct target *target) /* move r0 from buffer to register cache */ buf_set_u32(arm->core_cache->reg_list[0].value, 0, 32, buffer[0]); - arm->core_cache->reg_list[0].dirty = 1; - arm->core_cache->reg_list[0].valid = 1; + arm->core_cache->reg_list[0].dirty = true; + arm->core_cache->reg_list[0].valid = true; LOG_DEBUG("r0: 0x%8.8" PRIx32 "", buffer[0]); /* move pc from buffer to register cache */ buf_set_u32(arm->pc->value, 0, 32, buffer[1]); - arm->pc->dirty = 1; - arm->pc->valid = 1; + arm->pc->dirty = true; + arm->pc->valid = true; LOG_DEBUG("pc: 0x%8.8" PRIx32 "", buffer[1]); /* move data from buffer to register cache */ for (i = 1; i <= 7; i++) { buf_set_u32(arm->core_cache->reg_list[i].value, 0, 32, buffer[1 + i]); - arm->core_cache->reg_list[i].dirty = 1; - arm->core_cache->reg_list[i].valid = 1; + arm->core_cache->reg_list[i].dirty = true; + arm->core_cache->reg_list[i].valid = true; LOG_DEBUG("r%i: 0x%8.8" PRIx32 "", i, buffer[i + 1]); } @@ -920,7 +920,7 @@ static int xscale_debug_entry(struct target *target) /* mark xscale regs invalid to ensure they are retrieved from the * debug handler if requested */ for (i = 0; i < xscale->reg_cache->num_regs; i++) - xscale->reg_cache->reg_list[i].valid = 0; + xscale->reg_cache->reg_list[i].valid = false; /* examine debug reason */ xscale_read_dcsr(target); @@ -2423,8 +2423,8 @@ static int xscale_get_reg(struct reg *reg) xscale_read_tx(target, 1); buf_cpy(xscale->reg_cache->reg_list[XSCALE_TX].value, reg->value, 32); - reg->dirty = 0; - reg->valid = 1; + reg->dirty = false; + reg->valid = true; } return ERROR_OK; @@ -2890,8 +2890,8 @@ static void xscale_build_reg_cache(struct target *target) for (i = 0; i < num_regs; i++) { (*cache_p)->reg_list[i].name = xscale_reg_list[i]; (*cache_p)->reg_list[i].value = calloc(4, 1); - (*cache_p)->reg_list[i].dirty = 0; - (*cache_p)->reg_list[i].valid = 0; + (*cache_p)->reg_list[i].dirty = false; + (*cache_p)->reg_list[i].valid = false; (*cache_p)->reg_list[i].size = 32; (*cache_p)->reg_list[i].arch_info = &arch_info[i]; (*cache_p)->reg_list[i].type = &xscale_reg_type; From 8f518d3592dd80bfc7637d16498f2994038ab77c Mon Sep 17 00:00:00 2001 From: Marc Schink Date: Tue, 26 Feb 2019 14:10:48 +0100 Subject: [PATCH 57/70] target/mips: Use 'bool' data type Change-Id: Ifb114bfc062ed7c0ff6e4f37a1a6d546f5415344 Signed-off-by: Marc Schink Reviewed-on: http://openocd.zylin.com/4970 Tested-by: jenkins Reviewed-by: Antonio Borneo --- src/target/mips32.c | 22 +++++++++++----------- src/target/mips_m4k.c | 8 ++++---- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/src/target/mips32.c b/src/target/mips32.c index 9ac2507a3..d9d8ba975 100644 --- a/src/target/mips32.c +++ b/src/target/mips32.c @@ -190,8 +190,8 @@ static int mips32_set_core_reg(struct reg *reg, uint8_t *buf) return ERROR_TARGET_NOT_HALTED; buf_set_u32(reg->value, 0, 32, value); - reg->dirty = 1; - reg->valid = 1; + reg->dirty = true; + reg->valid = true; return ERROR_OK; } @@ -208,8 +208,8 @@ static int mips32_read_core_reg(struct target *target, unsigned int num) reg_value = mips32->core_regs[num]; buf_set_u32(mips32->core_cache->reg_list[num].value, 0, 32, reg_value); - mips32->core_cache->reg_list[num].valid = 1; - mips32->core_cache->reg_list[num].dirty = 0; + mips32->core_cache->reg_list[num].valid = true; + mips32->core_cache->reg_list[num].dirty = false; return ERROR_OK; } @@ -227,8 +227,8 @@ static int mips32_write_core_reg(struct target *target, unsigned int num) reg_value = buf_get_u32(mips32->core_cache->reg_list[num].value, 0, 32); mips32->core_regs[num] = reg_value; LOG_DEBUG("write core reg %i value 0x%" PRIx32 "", num , reg_value); - mips32->core_cache->reg_list[num].valid = 1; - mips32->core_cache->reg_list[num].dirty = 0; + mips32->core_cache->reg_list[num].valid = true; + mips32->core_cache->reg_list[num].dirty = false; return ERROR_OK; } @@ -336,12 +336,12 @@ struct reg_cache *mips32_build_reg_cache(struct target *target) if (mips32_regs[i].flag == MIPS32_GDB_DUMMY_FP_REG) { reg_list[i].value = mips32_gdb_dummy_fp_value; - reg_list[i].valid = 1; + reg_list[i].valid = true; reg_list[i].arch_info = NULL; register_init_dummy(®_list[i]); } else { reg_list[i].value = calloc(1, 4); - reg_list[i].valid = 0; + reg_list[i].valid = false; reg_list[i].type = &mips32_reg_type; reg_list[i].arch_info = &arch_info[i]; @@ -352,7 +352,7 @@ struct reg_cache *mips32_build_reg_cache(struct target *target) LOG_ERROR("unable to allocate reg type list"); } - reg_list[i].dirty = 0; + reg_list[i].dirty = false; reg_list[i].group = mips32_regs[i].group; reg_list[i].number = i; @@ -532,8 +532,8 @@ int mips32_run_algorithm(struct target *target, int num_mem_params, mips32->core_cache->reg_list[i].name, context[i]); buf_set_u32(mips32->core_cache->reg_list[i].value, 0, 32, context[i]); - mips32->core_cache->reg_list[i].valid = 1; - mips32->core_cache->reg_list[i].dirty = 1; + mips32->core_cache->reg_list[i].valid = true; + mips32->core_cache->reg_list[i].dirty = true; } } diff --git a/src/target/mips_m4k.c b/src/target/mips_m4k.c index 20c707bb6..6981c2ec8 100644 --- a/src/target/mips_m4k.c +++ b/src/target/mips_m4k.c @@ -458,8 +458,8 @@ static int mips_m4k_internal_restore(struct target *target, int current, if (!current) { mips_m4k_isa_filter(mips32->isa_imp, &address); buf_set_u32(mips32->core_cache->reg_list[MIPS32_PC].value, 0, 32, address); - mips32->core_cache->reg_list[MIPS32_PC].dirty = 1; - mips32->core_cache->reg_list[MIPS32_PC].valid = 1; + mips32->core_cache->reg_list[MIPS32_PC].dirty = true; + mips32->core_cache->reg_list[MIPS32_PC].valid = true; } if ((mips32->isa_imp > 1) && debug_execution) /* if more than one isa supported */ @@ -552,8 +552,8 @@ static int mips_m4k_step(struct target *target, int current, if (!current) { mips_m4k_isa_filter(mips32->isa_imp, &address); buf_set_u32(mips32->core_cache->reg_list[MIPS32_PC].value, 0, 32, address); - mips32->core_cache->reg_list[MIPS32_PC].dirty = 1; - mips32->core_cache->reg_list[MIPS32_PC].valid = 1; + mips32->core_cache->reg_list[MIPS32_PC].dirty = true; + mips32->core_cache->reg_list[MIPS32_PC].valid = true; } /* the front-end may request us not to handle breakpoints */ From 2b66816a4d88f1c15468b3d307b59f1242a6a4be Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Fri, 1 Mar 2019 13:56:44 +0100 Subject: [PATCH 58/70] mips32: pracc: Fix UPPER/LOWER macros These macros are missing parenthesis around the argument, which can lead to side effects, add them. Replace the argument name to avoid conflict with uint32_t data type, since the macro can be applied to other data types as well. Change-Id: I32d2ffec6c062795d7c8bb23d1dfa3378bfc3a58 Signed-off-by: Marek Vasut Reviewed-on: http://openocd.zylin.com/4994 Tested-by: jenkins Reviewed-by: Freddie Chopin --- src/target/mips32_pracc.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/target/mips32_pracc.h b/src/target/mips32_pracc.h index 888c847c0..cc11540b8 100644 --- a/src/target/mips32_pracc.h +++ b/src/target/mips32_pracc.h @@ -39,8 +39,8 @@ #define PRACC_OUT_OFFSET (MIPS32_PRACC_PARAM_OUT - MIPS32_PRACC_BASE_ADDR) #define MIPS32_FASTDATA_HANDLER_SIZE 0x80 -#define UPPER16(uint32_t) (uint32_t >> 16) -#define LOWER16(uint32_t) (uint32_t & 0xFFFF) +#define UPPER16(addr) ((addr) >> 16) +#define LOWER16(addr) ((addr) & 0xFFFF) #define NEG16(v) (((~(v)) + 1) & 0xFFFF) #define SWAP16(v) ((LOWER16(v) << 16) | (UPPER16(v))) /*#define NEG18(v) (((~(v)) + 1) & 0x3FFFF)*/ From b2e56656dcf3acecde8af73aa13a33814085bef3 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Fri, 1 Mar 2019 13:58:19 +0100 Subject: [PATCH 59/70] mips32: pracc: Fix indent Fix indent of the macros in header file, no functional change. Change-Id: I4d1dba5725155200148d1543c45bad919f6cd37e Signed-off-by: Marek Vasut Reviewed-on: http://openocd.zylin.com/4995 Tested-by: jenkins Reviewed-by: Freddie Chopin --- src/target/mips32_pracc.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/target/mips32_pracc.h b/src/target/mips32_pracc.h index cc11540b8..e31ba63e2 100644 --- a/src/target/mips32_pracc.h +++ b/src/target/mips32_pracc.h @@ -30,7 +30,7 @@ #define MIPS32_PRACC_FASTDATA_AREA 0xFF200000 #define MIPS32_PRACC_FASTDATA_SIZE 16 #define MIPS32_PRACC_BASE_ADDR 0xFF200000 -#define MIPS32_PRACC_TEXT 0xFF200200 +#define MIPS32_PRACC_TEXT 0xFF200200 #define MIPS32_PRACC_PARAM_OUT 0xFF202000 #define PRACC_UPPER_BASE_ADDR (MIPS32_PRACC_BASE_ADDR >> 16) @@ -38,10 +38,10 @@ #define PRACC_MAX_INSTRUCTIONS (PRACC_MAX_CODE / 4) #define PRACC_OUT_OFFSET (MIPS32_PRACC_PARAM_OUT - MIPS32_PRACC_BASE_ADDR) -#define MIPS32_FASTDATA_HANDLER_SIZE 0x80 +#define MIPS32_FASTDATA_HANDLER_SIZE 0x80 #define UPPER16(addr) ((addr) >> 16) #define LOWER16(addr) ((addr) & 0xFFFF) -#define NEG16(v) (((~(v)) + 1) & 0xFFFF) +#define NEG16(v) (((~(v)) + 1) & 0xFFFF) #define SWAP16(v) ((LOWER16(v) << 16) | (UPPER16(v))) /*#define NEG18(v) (((~(v)) + 1) & 0x3FFFF)*/ From 89f07325f2e7ca9d28ba0c54a26e3aab8b34984a Mon Sep 17 00:00:00 2001 From: Frans-Willem Hardijzer Date: Sat, 22 Dec 2018 12:03:43 +0100 Subject: [PATCH 60/70] stlink: Set speed before entering JTAG/SWD mode Some boards require a slower clock speed because of passive components on the JTAG/SWD lines. The previous implementation would first try to discover the chips on the default speed, and only after discovery switch to the requested adapter_khz speed. This patch moves the speed change to just before entering the SWD/JTAG mode, which should alleviate this problem. Tested on an STLink V2 clone. Change-Id: I9734452dcc8bb28d6629e64d9a7e32ef92868cf9 Signed-off-by: Frans-Willem Hardijzer Reviewed-on: http://openocd.zylin.com/4818 Tested-by: jenkins Reviewed-by: Antonio Borneo --- src/jtag/drivers/stlink_usb.c | 48 +++++++++++++++++++---------------- 1 file changed, 26 insertions(+), 22 deletions(-) diff --git a/src/jtag/drivers/stlink_usb.c b/src/jtag/drivers/stlink_usb.c index 491f2e4ff..12e1175f5 100644 --- a/src/jtag/drivers/stlink_usb.c +++ b/src/jtag/drivers/stlink_usb.c @@ -344,6 +344,9 @@ static const struct speed_map stlink_khz_to_speed_map_jtag[] = { static void stlink_usb_init_buffer(void *handle, uint8_t direction, uint32_t size); static int stlink_swim_status(void *handle); +void stlink_dump_speed_map(const struct speed_map *map, unsigned int map_size); +static int stlink_get_com_freq(void *handle, bool is_jtag, struct speed_map *map); +static int stlink_speed(void *handle, int khz, bool query); /** */ static unsigned int stlink_usb_block(void *handle) @@ -1244,7 +1247,7 @@ static enum stlink_mode stlink_get_mode(enum hl_transports t) } /** */ -static int stlink_usb_init_mode(void *handle, bool connect_under_reset) +static int stlink_usb_init_mode(void *handle, bool connect_under_reset, int initial_interface_speed) { int res; uint8_t mode; @@ -1323,6 +1326,27 @@ static int stlink_usb_init_mode(void *handle, bool connect_under_reset) return ERROR_FAIL; } + /* set the speed before entering the mode, as the chip discovery phase should be done at this speed too */ + if (h->transport == HL_TRANSPORT_JTAG) { + if (h->version.flags & STLINK_F_HAS_JTAG_SET_FREQ) { + stlink_dump_speed_map(stlink_khz_to_speed_map_jtag, ARRAY_SIZE(stlink_khz_to_speed_map_jtag)); + stlink_speed(h, initial_interface_speed, false); + } + } else if (h->transport == HL_TRANSPORT_SWD) { + if (h->version.flags & STLINK_F_HAS_SWD_SET_FREQ) { + stlink_dump_speed_map(stlink_khz_to_speed_map_swd, ARRAY_SIZE(stlink_khz_to_speed_map_swd)); + stlink_speed(h, initial_interface_speed, false); + } + } + + if (h->version.jtag_api == STLINK_JTAG_API_V3) { + struct speed_map map[STLINK_V3_MAX_FREQ_NB]; + + stlink_get_com_freq(h, (h->transport == HL_TRANSPORT_JTAG), map); + stlink_dump_speed_map(map, ARRAY_SIZE(map)); + stlink_speed(h, initial_interface_speed, false); + } + /* preliminary SRST assert: * We want SRST is asserted before activating debug signals (mode_enter). * As the required mode has not been set, the adapter may not know what pin to use. @@ -2814,7 +2838,7 @@ static int stlink_usb_open(struct hl_interface_param_s *param, void **fd) } /* initialize the debug hardware */ - err = stlink_usb_init_mode(h, param->connect_under_reset); + err = stlink_usb_init_mode(h, param->connect_under_reset, param->initial_interface_speed); if (err != ERROR_OK) { LOG_ERROR("init mode failed (unable to connect to the target)"); @@ -2832,26 +2856,6 @@ static int stlink_usb_open(struct hl_interface_param_s *param, void **fd) return ERROR_OK; } - if (h->transport == HL_TRANSPORT_JTAG) { - if (h->version.flags & STLINK_F_HAS_JTAG_SET_FREQ) { - stlink_dump_speed_map(stlink_khz_to_speed_map_jtag, ARRAY_SIZE(stlink_khz_to_speed_map_jtag)); - stlink_speed(h, param->initial_interface_speed, false); - } - } else if (h->transport == HL_TRANSPORT_SWD) { - if (h->version.flags & STLINK_F_HAS_SWD_SET_FREQ) { - stlink_dump_speed_map(stlink_khz_to_speed_map_swd, ARRAY_SIZE(stlink_khz_to_speed_map_swd)); - stlink_speed(h, param->initial_interface_speed, false); - } - } - - if (h->version.jtag_api == STLINK_JTAG_API_V3) { - struct speed_map map[STLINK_V3_MAX_FREQ_NB]; - - stlink_get_com_freq(h, (h->transport == HL_TRANSPORT_JTAG), map); - stlink_dump_speed_map(map, ARRAY_SIZE(map)); - stlink_speed(h, param->initial_interface_speed, false); - } - /* get cpuid, so we can determine the max page size * start with a safe default */ h->max_mem_packet = (1 << 10); From bc72695f6738951571502706bd48680de5ccc84c Mon Sep 17 00:00:00 2001 From: Tim Newsome Date: Fri, 15 Feb 2019 12:08:51 -0800 Subject: [PATCH 61/70] Lots of RISC-V improvements. This represents months of continuing RISC-V work, with too many changes to list individually. Some improvements: * Fixed memory leaks. * Better handling of dbus timeouts. * Add `riscv expose_custom` command. * Somewhat deal with cache coherency. * Deal with more timeouts during block memory accesses. * Basic debug compliance test. * Tell gdb which watchpoint hit. * SMP support for use with -rtos hwthread * Add `riscv set_ir` Change-Id: Ica507ee2a57eaf51b578ab1d9b7de71512fdf47f Signed-off-by: Tim Newsome Reviewed-on: http://openocd.zylin.com/4922 Tested-by: jenkins Reviewed-by: Philipp Guehring Reviewed-by: Liviu Ionescu Reviewed-by: Matthias Welwarsky --- doc/openocd.texi | 19 + src/target/riscv/batch.c | 27 +- src/target/riscv/opcodes.h | 3 + src/target/riscv/program.h | 4 +- src/target/riscv/riscv-011.c | 27 +- src/target/riscv/riscv-013.c | 1528 +++++++++++++++++++++++++++------- src/target/riscv/riscv.c | 667 ++++++++++++--- src/target/riscv/riscv.h | 21 +- 8 files changed, 1850 insertions(+), 446 deletions(-) diff --git a/doc/openocd.texi b/doc/openocd.texi index bbb907558..a17173ce8 100644 --- a/doc/openocd.texi +++ b/doc/openocd.texi @@ -9466,6 +9466,14 @@ command can be used if OpenOCD gets this wrong, or a target implements custom CSRs. @end deffn +@deffn Command {riscv expose_custom} n0[-m0][,n1[-m1]]... +The RISC-V Debug Specification allows targets to expose custom registers +through abstract commands. (See Section 3.5.1.1 in that document.) This command +configures a list of inclusive ranges of those registers to expose. Number 0 +indicates the first custom register, whose abstract command number is 0xc000. +This command must be executed before `init`. +@end deffn + @deffn Command {riscv set_command_timeout_sec} [seconds] Set the wall-clock timeout (in seconds) for individual commands. The default should work fine for all but the slowest targets (eg. simulators). @@ -9486,6 +9494,17 @@ When on, prefer to use System Bus Access to access memory. When off, prefer to use the Program Buffer to access memory. @end deffn +@deffn Command {riscv set_ir} (@option{idcode}|@option{dtmcs}|@option{dmi}) [value] +Set the IR value for the specified JTAG register. This is useful, for +example, when using the existing JTAG interface on a Xilinx FPGA by +way of BSCANE2 primitives that only permit a limited selection of IR +values. + +When utilizing version 0.11 of the RISC-V Debug Specification, +@option{dtmcs} and @option{dmi} set the IR values for the DTMCONTROL +and DBUS registers, respectively. +@end deffn + @subsection RISC-V Authentication Commands The following commands can be used to authenticate to a RISC-V system. Eg. a diff --git a/src/target/riscv/batch.c b/src/target/riscv/batch.c index 9327cb38b..d041ed119 100644 --- a/src/target/riscv/batch.c +++ b/src/target/riscv/batch.c @@ -9,23 +9,20 @@ #define get_field(reg, mask) (((reg) & (mask)) / ((mask) & ~((mask) << 1))) #define set_field(reg, mask, val) (((reg) & ~(mask)) | (((val) * ((mask) & ~((mask) << 1))) & (mask))) -static void dump_field(const struct scan_field *field); +static void dump_field(int idle, const struct scan_field *field); struct riscv_batch *riscv_batch_alloc(struct target *target, size_t scans, size_t idle) { scans += 4; - struct riscv_batch *out = malloc(sizeof(*out)); - memset(out, 0, sizeof(*out)); + struct riscv_batch *out = calloc(1, sizeof(*out)); out->target = target; out->allocated_scans = scans; - out->used_scans = 0; out->idle_count = idle; out->data_out = malloc(sizeof(*out->data_out) * (scans) * sizeof(uint64_t)); out->data_in = malloc(sizeof(*out->data_in) * (scans) * sizeof(uint64_t)); out->fields = malloc(sizeof(*out->fields) * (scans)); out->last_scan = RISCV_SCAN_TYPE_INVALID; out->read_keys = malloc(sizeof(*out->read_keys) * (scans)); - out->read_keys_used = 0; return out; } @@ -51,7 +48,6 @@ int riscv_batch_run(struct riscv_batch *batch) keep_alive(); - LOG_DEBUG("running a batch of %ld scans", (long)batch->used_scans); riscv_batch_add_nop(batch); for (size_t i = 0; i < batch->used_scans; ++i) { @@ -60,14 +56,13 @@ int riscv_batch_run(struct riscv_batch *batch) jtag_add_runtest(batch->idle_count, TAP_IDLE); } - LOG_DEBUG("executing queue"); if (jtag_execute_queue() != ERROR_OK) { LOG_ERROR("Unable to execute JTAG queue"); return ERROR_FAIL; } for (size_t i = 0; i < batch->used_scans; ++i) - dump_field(batch->fields + i); + dump_field(batch->idle_count, batch->fields + i); return ERROR_OK; } @@ -98,13 +93,10 @@ size_t riscv_batch_add_dmi_read(struct riscv_batch *batch, unsigned address) batch->used_scans++; /* FIXME We get the read response back on the next scan. For now I'm - * just sticking a NOP in there, but this should be coelesced away. */ + * just sticking a NOP in there, but this should be coalesced away. */ riscv_batch_add_nop(batch); batch->read_keys[batch->read_keys_used] = batch->used_scans - 1; - LOG_DEBUG("read key %u for batch 0x%p is %u (0x%p)", - (unsigned) batch->read_keys_used, batch, (unsigned) (batch->used_scans - 1), - batch->data_in + sizeof(uint64_t) * (batch->used_scans + 1)); return batch->read_keys_used++; } @@ -135,10 +127,9 @@ void riscv_batch_add_nop(struct riscv_batch *batch) riscv_fill_dmi_nop_u64(batch->target, (char *)field->in_value); batch->last_scan = RISCV_SCAN_TYPE_NOP; batch->used_scans++; - LOG_DEBUG(" added NOP with in_value=0x%p", field->in_value); } -void dump_field(const struct scan_field *field) +void dump_field(int idle, const struct scan_field *field) { static const char * const op_string[] = {"-", "r", "w", "?"}; static const char * const status_string[] = {"+", "?", "F", "b"}; @@ -160,13 +151,13 @@ void dump_field(const struct scan_field *field) log_printf_lf(LOG_LVL_DEBUG, __FILE__, __LINE__, __PRETTY_FUNCTION__, - "%db %s %08x @%02x -> %s %08x @%02x", - field->num_bits, + "%db %di %s %08x @%02x -> %s %08x @%02x", + field->num_bits, idle, op_string[out_op], out_data, out_address, status_string[in_op], in_data, in_address); } else { log_printf_lf(LOG_LVL_DEBUG, - __FILE__, __LINE__, __PRETTY_FUNCTION__, "%db %s %08x @%02x -> ?", - field->num_bits, op_string[out_op], out_data, out_address); + __FILE__, __LINE__, __PRETTY_FUNCTION__, "%db %di %s %08x @%02x -> ?", + field->num_bits, idle, op_string[out_op], out_data, out_address); } } diff --git a/src/target/riscv/opcodes.h b/src/target/riscv/opcodes.h index dd51c809d..de85aadd8 100644 --- a/src/target/riscv/opcodes.h +++ b/src/target/riscv/opcodes.h @@ -224,6 +224,9 @@ static uint32_t ebreak_c(void) return MATCH_C_EBREAK; } +static uint32_t wfi(void) __attribute__ ((unused)); +static uint32_t wfi(void) { return MATCH_WFI; } + static uint32_t fence_i(void) __attribute__ ((unused)); static uint32_t fence_i(void) { diff --git a/src/target/riscv/program.h b/src/target/riscv/program.h index d641be1be..310460c28 100644 --- a/src/target/riscv/program.h +++ b/src/target/riscv/program.h @@ -52,8 +52,8 @@ int riscv_program_insert(struct riscv_program *p, riscv_insn_t i); * memory. */ int riscv_program_save_to_dscratch(struct riscv_program *p, enum gdb_regno to_save); -/* Helpers to assembly various instructions. Return 0 on success. These might - * assembly into a multi-instruction sequence that overwrites some other +/* Helpers to assemble various instructions. Return 0 on success. These might + * assemble into a multi-instruction sequence that overwrites some other * register, but those will be properly saved and restored. */ int riscv_program_lwr(struct riscv_program *p, enum gdb_regno d, enum gdb_regno a, int o); int riscv_program_lhr(struct riscv_program *p, enum gdb_regno d, enum gdb_regno a, int o); diff --git a/src/target/riscv/riscv-011.c b/src/target/riscv/riscv-011.c index bd3f159fb..eded86246 100644 --- a/src/target/riscv/riscv-011.c +++ b/src/target/riscv/riscv-011.c @@ -358,6 +358,15 @@ static void add_dbus_scan(const struct target *target, struct scan_field *field, uint16_t address, uint64_t data) { riscv011_info_t *info = get_info(target); + RISCV_INFO(r); + + if (r->reset_delays_wait >= 0) { + r->reset_delays_wait--; + if (r->reset_delays_wait < 0) { + info->dbus_busy_delay = 0; + info->interrupt_high_delay = 0; + } + } field->num_bits = info->addrbits + DBUS_OP_SIZE + DBUS_DATA_SIZE; field->in_value = in_value; @@ -1408,12 +1417,6 @@ static int strict_step(struct target *target, bool announce) LOG_DEBUG("enter"); - struct breakpoint *breakpoint = target->breakpoints; - while (breakpoint) { - riscv_remove_breakpoint(target, breakpoint); - breakpoint = breakpoint->next; - } - struct watchpoint *watchpoint = target->watchpoints; while (watchpoint) { riscv_remove_watchpoint(target, watchpoint); @@ -1424,12 +1427,6 @@ static int strict_step(struct target *target, bool announce) if (result != ERROR_OK) return result; - breakpoint = target->breakpoints; - while (breakpoint) { - riscv_add_breakpoint(target, breakpoint); - breakpoint = breakpoint->next; - } - watchpoint = target->watchpoints; while (watchpoint) { riscv_add_watchpoint(target, watchpoint); @@ -1463,7 +1460,7 @@ static int step(struct target *target, int current, target_addr_t address, if (result != ERROR_OK) return result; } else { - return resume(target, 0, true); + return full_step(target, false); } return ERROR_OK; @@ -1676,7 +1673,7 @@ static riscv_error_t handle_halt_routine(struct target *target) break; default: LOG_ERROR("Got invalid bus access status: %d", status); - return ERROR_FAIL; + goto error; } if (data & DMCONTROL_INTERRUPT) { interrupt_set++; @@ -1850,7 +1847,7 @@ static int handle_halt(struct target *target, bool announce) target->debug_reason = DBG_REASON_BREAKPOINT; break; case DCSR_CAUSE_HWBP: - target->debug_reason = DBG_REASON_WPTANDBKPT; + target->debug_reason = DBG_REASON_WATCHPOINT; /* If we halted because of a data trigger, gdb doesn't know to do * the disable-breakpoints-step-enable-breakpoints dance. */ info->need_strict_step = true; diff --git a/src/target/riscv/riscv-013.c b/src/target/riscv/riscv-013.c index 4acd42754..5683e5a3f 100644 --- a/src/target/riscv/riscv-013.c +++ b/src/target/riscv/riscv-013.c @@ -64,6 +64,13 @@ static int read_memory(struct target *target, target_addr_t address, uint32_t size, uint32_t count, uint8_t *buffer); static int write_memory(struct target *target, target_addr_t address, uint32_t size, uint32_t count, const uint8_t *buffer); +static int riscv013_test_sba_config_reg(struct target *target, target_addr_t legal_address, + uint32_t num_words, target_addr_t illegal_address, bool run_sbbusyerror_test); +void write_memory_sba_simple(struct target *target, target_addr_t addr, uint32_t* write_data, + uint32_t write_size, uint32_t sbcs); +void read_memory_sba_simple(struct target *target, target_addr_t addr, + uint32_t *rd_buf, uint32_t read_size, uint32_t sbcs); +static int riscv013_test_compliance(struct target *target); /** * Since almost everything can be accomplish by scanning the dbus register, all @@ -169,7 +176,7 @@ typedef struct { /* Number of run-test/idle cycles the target requests we do after each dbus * access. */ - unsigned int dtmcontrol_idle; + unsigned int dtmcs_idle; /* This value is incremented every time a dbus access comes back as "busy". * It's used to determine how many run-test/idle cycles to feed the target @@ -187,8 +194,6 @@ typedef struct { * go low. */ unsigned int ac_busy_delay; - bool need_strict_step; - bool abstract_read_csr_supported; bool abstract_write_csr_supported; bool abstract_read_fpr_supported; @@ -351,7 +356,7 @@ static void decode_dmi(char *text, unsigned address, unsigned data) } } -static void dump_field(const struct scan_field *field) +static void dump_field(int idle, const struct scan_field *field) { static const char * const op_string[] = {"-", "r", "w", "?"}; static const char * const status_string[] = {"+", "?", "F", "b"}; @@ -371,8 +376,8 @@ static void dump_field(const struct scan_field *field) log_printf_lf(LOG_LVL_DEBUG, __FILE__, __LINE__, "scan", - "%db %s %08x @%02x -> %s %08x @%02x", - field->num_bits, + "%db %di %s %08x @%02x -> %s %08x @%02x", + field->num_bits, idle, op_string[out_op], out_data, out_address, status_string[in_op], in_data, in_address); @@ -390,16 +395,7 @@ static void dump_field(const struct scan_field *field) static void select_dmi(struct target *target) { - static uint8_t ir_dmi[1] = {DTM_DMI}; - struct scan_field field = { - .num_bits = target->tap->ir_length, - .out_value = ir_dmi, - .in_value = NULL, - .check_value = NULL, - .check_mask = NULL - }; - - jtag_add_ir_scan(target->tap, &field, TAP_IDLE); + jtag_add_ir_scan(target->tap, &select_dbus, TAP_IDLE); } static uint32_t dtmcontrol_scan(struct target *target, uint32_t out) @@ -436,8 +432,8 @@ static void increase_dmi_busy_delay(struct target *target) { riscv013_info_t *info = get_info(target); info->dmi_busy_delay += info->dmi_busy_delay / 10 + 1; - LOG_DEBUG("dtmcontrol_idle=%d, dmi_busy_delay=%d, ac_busy_delay=%d", - info->dtmcontrol_idle, info->dmi_busy_delay, + LOG_DEBUG("dtmcs_idle=%d, dmi_busy_delay=%d, ac_busy_delay=%d", + info->dtmcs_idle, info->dmi_busy_delay, info->ac_busy_delay); dtmcontrol_scan(target, DTM_DTMCS_DMIRESET); @@ -452,14 +448,27 @@ static dmi_status_t dmi_scan(struct target *target, uint32_t *address_in, bool exec) { riscv013_info_t *info = get_info(target); - uint8_t in[8] = {0}; - uint8_t out[8]; + RISCV_INFO(r); + unsigned num_bits = info->abits + DTM_DMI_OP_LENGTH + DTM_DMI_DATA_LENGTH; + size_t num_bytes = (num_bits + 7) / 8; + uint8_t in[num_bytes]; + uint8_t out[num_bytes]; struct scan_field field = { - .num_bits = info->abits + DTM_DMI_OP_LENGTH + DTM_DMI_DATA_LENGTH, + .num_bits = num_bits, .out_value = out, .in_value = in }; + if (r->reset_delays_wait >= 0) { + r->reset_delays_wait--; + if (r->reset_delays_wait < 0) { + info->dmi_busy_delay = 0; + info->ac_busy_delay = 0; + } + } + + memset(in, 0, num_bytes); + assert(info->abits != 0); buf_set_u32(out, DTM_DMI_OP_OFFSET, DTM_DMI_OP_LENGTH, op); @@ -488,19 +497,25 @@ static dmi_status_t dmi_scan(struct target *target, uint32_t *address_in, if (address_in) *address_in = buf_get_u32(in, DTM_DMI_ADDRESS_OFFSET, info->abits); - dump_field(&field); + dump_field(idle_count, &field); return buf_get_u32(in, DTM_DMI_OP_OFFSET, DTM_DMI_OP_LENGTH); } -static int dmi_op_timeout(struct target *target, uint32_t *data_in, int dmi_op, - uint32_t address, uint32_t data_out, int timeout_sec) +/* If dmi_busy_encountered is non-NULL, this function will use it to tell the + * caller whether DMI was ever busy during this call. */ +static int dmi_op_timeout(struct target *target, uint32_t *data_in, + bool *dmi_busy_encountered, int dmi_op, uint32_t address, + uint32_t data_out, int timeout_sec, bool exec) { select_dmi(target); dmi_status_t status; uint32_t address_in; + if (dmi_busy_encountered) + *dmi_busy_encountered = false; + const char *op_name; switch (dmi_op) { case DMI_OP_NOP: @@ -522,9 +537,11 @@ static int dmi_op_timeout(struct target *target, uint32_t *data_in, int dmi_op, * stays busy, it is actually due to the previous access. */ while (1) { status = dmi_scan(target, NULL, NULL, dmi_op, address, data_out, - false); + exec); if (status == DMI_STATUS_BUSY) { increase_dmi_busy_delay(target); + if (dmi_busy_encountered) + *dmi_busy_encountered = true; } else if (status == DMI_STATUS_SUCCESS) { break; } else { @@ -573,11 +590,12 @@ static int dmi_op_timeout(struct target *target, uint32_t *data_in, int dmi_op, return ERROR_OK; } -static int dmi_op(struct target *target, uint32_t *data_in, int dmi_op, - uint32_t address, uint32_t data_out) +static int dmi_op(struct target *target, uint32_t *data_in, + bool *dmi_busy_encountered, int dmi_op, uint32_t address, + uint32_t data_out, bool exec) { - int result = dmi_op_timeout(target, data_in, dmi_op, address, data_out, - riscv_command_timeout_sec); + int result = dmi_op_timeout(target, data_in, dmi_busy_encountered, dmi_op, + address, data_out, riscv_command_timeout_sec, exec); if (result == ERROR_TIMEOUT_REACHED) { LOG_ERROR("DMI operation didn't complete in %d seconds. The target is " "either really slow or broken. You could increase the " @@ -590,19 +608,29 @@ static int dmi_op(struct target *target, uint32_t *data_in, int dmi_op, static int dmi_read(struct target *target, uint32_t *value, uint32_t address) { - return dmi_op(target, value, DMI_OP_READ, address, 0); + return dmi_op(target, value, NULL, DMI_OP_READ, address, 0, false); +} + +static int dmi_read_exec(struct target *target, uint32_t *value, uint32_t address) +{ + return dmi_op(target, value, NULL, DMI_OP_READ, address, 0, true); } static int dmi_write(struct target *target, uint32_t address, uint32_t value) { - return dmi_op(target, NULL, DMI_OP_WRITE, address, value); + return dmi_op(target, NULL, NULL, DMI_OP_WRITE, address, value, false); +} + +static int dmi_write_exec(struct target *target, uint32_t address, uint32_t value) +{ + return dmi_op(target, NULL, NULL, DMI_OP_WRITE, address, value, true); } int dmstatus_read_timeout(struct target *target, uint32_t *dmstatus, bool authenticated, unsigned timeout_sec) { - int result = dmi_op_timeout(target, dmstatus, DMI_OP_READ, DMI_DMSTATUS, 0, - timeout_sec); + int result = dmi_op_timeout(target, dmstatus, NULL, DMI_OP_READ, + DMI_DMSTATUS, 0, timeout_sec, false); if (result != ERROR_OK) return result; if (authenticated && !get_field(*dmstatus, DMI_DMSTATUS_AUTHENTICATED)) { @@ -625,8 +653,8 @@ static void increase_ac_busy_delay(struct target *target) { riscv013_info_t *info = get_info(target); info->ac_busy_delay += info->ac_busy_delay / 10 + 1; - LOG_DEBUG("dtmcontrol_idle=%d, dmi_busy_delay=%d, ac_busy_delay=%d", - info->dtmcontrol_idle, info->dmi_busy_delay, + LOG_DEBUG("dtmcs_idle=%d, dmi_busy_delay=%d, ac_busy_delay=%d", + info->dtmcs_idle, info->dmi_busy_delay, info->ac_busy_delay); } @@ -687,8 +715,25 @@ static int wait_for_idle(struct target *target, uint32_t *abstractcs) static int execute_abstract_command(struct target *target, uint32_t command) { RISCV013_INFO(info); - LOG_DEBUG("command=0x%x", command); - dmi_write(target, DMI_COMMAND, command); + if (debug_level >= LOG_LVL_DEBUG) { + switch (get_field(command, DMI_COMMAND_CMDTYPE)) { + case 0: + LOG_DEBUG("command=0x%x; access register, size=%d, postexec=%d, " + "transfer=%d, write=%d, regno=0x%x", + command, + 8 << get_field(command, AC_ACCESS_REGISTER_SIZE), + get_field(command, AC_ACCESS_REGISTER_POSTEXEC), + get_field(command, AC_ACCESS_REGISTER_TRANSFER), + get_field(command, AC_ACCESS_REGISTER_WRITE), + get_field(command, AC_ACCESS_REGISTER_REGNO)); + break; + default: + LOG_DEBUG("command=0x%x", command); + break; + } + } + + dmi_write_exec(target, DMI_COMMAND, command); uint32_t abstractcs = 0; wait_for_idle(target, &abstractcs); @@ -744,10 +789,10 @@ static int write_abstract_arg(struct target *target, unsigned index, } /** - * @size in bits + * @par size in bits */ -static uint32_t access_register_command(uint32_t number, unsigned size, - uint32_t flags) +static uint32_t access_register_command(struct target *target, uint32_t number, + unsigned size, uint32_t flags) { uint32_t command = set_field(0, DMI_COMMAND_CMDTYPE, 0); switch (size) { @@ -770,8 +815,13 @@ static uint32_t access_register_command(uint32_t number, unsigned size, } else if (number >= GDB_REGNO_CSR0 && number <= GDB_REGNO_CSR4095) { command = set_field(command, AC_ACCESS_REGISTER_REGNO, number - GDB_REGNO_CSR0); - } else { - assert(0); + } else if (number >= GDB_REGNO_COUNT) { + /* Custom register. */ + assert(target->reg_cache->reg_list[number].arch_info); + riscv_reg_info_t *reg_info = target->reg_cache->reg_list[number].arch_info; + assert(reg_info); + command = set_field(command, AC_ACCESS_REGISTER_REGNO, + 0xc000 + reg_info->custom_number); } command |= flags; @@ -791,7 +841,7 @@ static int register_read_abstract(struct target *target, uint64_t *value, !info->abstract_read_csr_supported) return ERROR_FAIL; - uint32_t command = access_register_command(number, size, + uint32_t command = access_register_command(target, number, size, AC_ACCESS_REGISTER_TRANSFER); int result = execute_abstract_command(target, command); @@ -826,7 +876,7 @@ static int register_write_abstract(struct target *target, uint32_t number, !info->abstract_write_csr_supported) return ERROR_FAIL; - uint32_t command = access_register_command(number, size, + uint32_t command = access_register_command(target, number, size, AC_ACCESS_REGISTER_TRANSFER | AC_ACCESS_REGISTER_WRITE); @@ -1087,7 +1137,7 @@ static int register_write_direct(struct target *target, unsigned number, RISCV013_INFO(info); RISCV_INFO(r); - LOG_DEBUG("[%d] reg[0x%x] <- 0x%" PRIx64, riscv_current_hartid(target), + LOG_DEBUG("{%d} reg[0x%x] <- 0x%" PRIx64, riscv_current_hartid(target), number, value); int result = register_write_abstract(target, number, value, @@ -1095,7 +1145,6 @@ static int register_write_direct(struct target *target, unsigned number, if (result == ERROR_OK && target->reg_cache) { struct reg *reg = &target->reg_cache->reg_list[number]; buf_set_u64(reg->value, 0, reg->size, value); - reg->valid = true; } if (result == ERROR_OK || info->progbufsize + r->impebreak < 2 || !riscv_is_halted(target)) @@ -1154,7 +1203,6 @@ static int register_write_direct(struct target *target, unsigned number, if (exec_out == ERROR_OK && target->reg_cache) { struct reg *reg = &target->reg_cache->reg_list[number]; buf_set_u64(reg->value, 0, reg->size, value); - reg->valid = true; } if (use_scratch) @@ -1174,24 +1222,12 @@ static int register_read(struct target *target, uint64_t *value, uint32_t number *value = 0; return ERROR_OK; } - if (target->reg_cache && - (number <= GDB_REGNO_XPR31 || - (number >= GDB_REGNO_FPR0 && number <= GDB_REGNO_FPR31))) { - /* Only check the cache for registers that we know won't spontaneously - * change. */ - struct reg *reg = &target->reg_cache->reg_list[number]; - if (reg && reg->valid) { - *value = buf_get_u64(reg->value, 0, reg->size); - return ERROR_OK; - } - } int result = register_read_direct(target, value, number); if (result != ERROR_OK) return ERROR_FAIL; if (target->reg_cache) { struct reg *reg = &target->reg_cache->reg_list[number]; buf_set_u64(reg->value, 0, reg->size, *value); - reg->valid = true; } return ERROR_OK; } @@ -1284,7 +1320,7 @@ static int register_read_direct(struct target *target, uint64_t *value, uint32_t } if (result == ERROR_OK) { - LOG_DEBUG("[%d] reg[0x%x] = 0x%" PRIx64, riscv_current_hartid(target), + LOG_DEBUG("{%d} reg[0x%x] = 0x%" PRIx64, riscv_current_hartid(target), number, *value); } @@ -1321,6 +1357,7 @@ static void deinit_target(struct target *target) LOG_DEBUG("riscv_deinit_target()"); riscv_info_t *info = (riscv_info_t *) target->arch_info; free(info->version_specific); + /* TODO: free register arch_info */ info->version_specific = NULL; } @@ -1347,17 +1384,7 @@ static int examine(struct target *target) riscv013_info_t *info = get_info(target); info->abits = get_field(dtmcontrol, DTM_DTMCS_ABITS); - info->dtmcontrol_idle = get_field(dtmcontrol, DTM_DTMCS_IDLE); - - uint32_t dmstatus; - if (dmstatus_read(target, &dmstatus, false) != ERROR_OK) - return ERROR_FAIL; - LOG_DEBUG("dmstatus: 0x%08x", dmstatus); - if (get_field(dmstatus, DMI_DMSTATUS_VERSION) != 2) { - LOG_ERROR("OpenOCD only supports Debug Module version 2, not %d " - "(dmstatus=0x%x)", get_field(dmstatus, DMI_DMSTATUS_VERSION), dmstatus); - return ERROR_FAIL; - } + info->dtmcs_idle = get_field(dtmcontrol, DTM_DTMCS_IDLE); /* Reset the Debug Module. */ dm013_info_t *dm = get_dm(target); @@ -1379,6 +1406,16 @@ static int examine(struct target *target) return ERROR_FAIL; } + uint32_t dmstatus; + if (dmstatus_read(target, &dmstatus, false) != ERROR_OK) + return ERROR_FAIL; + LOG_DEBUG("dmstatus: 0x%08x", dmstatus); + if (get_field(dmstatus, DMI_DMSTATUS_VERSION) != 2) { + LOG_ERROR("OpenOCD only supports Debug Module version 2, not %d " + "(dmstatus=0x%x)", get_field(dmstatus, DMI_DMSTATUS_VERSION), dmstatus); + return ERROR_FAIL; + } + uint32_t hartsel = (get_field(dmcontrol, DMI_DMCONTROL_HARTSELHI) << DMI_DMCONTROL_HARTSELLO_LENGTH) | @@ -1454,7 +1491,8 @@ static int examine(struct target *target) dmi_write(target, DMI_DMCONTROL, set_hartsel(DMI_DMCONTROL_DMACTIVE | DMI_DMCONTROL_ACKHAVERESET, i)); - if (!riscv_is_halted(target)) { + bool halted = riscv_is_halted(target); + if (!halted) { if (riscv013_halt_current_hart(target) != ERROR_OK) { LOG_ERROR("Fatal: Hart %d failed to halt during examine()", i); return ERROR_FAIL; @@ -1484,6 +1522,9 @@ static int examine(struct target *target) * really slow simulators. */ LOG_DEBUG(" hart %d: XLEN=%d, misa=0x%" PRIx64, i, r->xlen[i], r->misa[i]); + + if (!halted) + riscv013_resume_current_hart(target); } LOG_DEBUG("Enumerated %d harts", r->hart_count); @@ -1493,11 +1534,6 @@ static int examine(struct target *target) return ERROR_FAIL; } - /* Resumes all the harts, so the debugger can later pause them. */ - /* TODO: Only do this if the harts were halted to start with. */ - riscv_resume_all_harts(target); - target->state = TARGET_RUNNING; - target_set_examined(target); /* Some regression suites rely on seeing 'Examined RISC-V core' to know @@ -1579,6 +1615,8 @@ static int init_target(struct command_context *cmd_ctx, generic_info->authdata_write = &riscv013_authdata_write; generic_info->dmi_read = &dmi_read; generic_info->dmi_write = &dmi_write; + generic_info->test_sba_config_reg = &riscv013_test_sba_config_reg; + generic_info->test_compliance = &riscv013_test_compliance; generic_info->version_specific = calloc(1, sizeof(riscv013_info_t)); if (!generic_info->version_specific) return ERROR_FAIL; @@ -1722,7 +1760,7 @@ static int deassert_reset(struct target *target) } /** - * @size in bytes + * @par size in bytes */ static void write_to_buf(uint8_t *buffer, uint64_t value, unsigned size) { @@ -1750,13 +1788,38 @@ static void write_to_buf(uint8_t *buffer, uint64_t value, unsigned size) static int execute_fence(struct target *target) { - struct riscv_program program; - riscv_program_init(&program, target); - riscv_program_fence(&program); - int result = riscv_program_exec(&program, target); - if (result != ERROR_OK) - LOG_ERROR("Unable to execute fence"); - return result; + int old_hartid = riscv_current_hartid(target); + + /* FIXME: For non-coherent systems we need to flush the caches right + * here, but there's no ISA-defined way of doing that. */ + { + struct riscv_program program; + riscv_program_init(&program, target); + riscv_program_fence_i(&program); + riscv_program_fence(&program); + int result = riscv_program_exec(&program, target); + if (result != ERROR_OK) + LOG_DEBUG("Unable to execute pre-fence"); + } + + for (int i = 0; i < riscv_count_harts(target); ++i) { + if (!riscv_hart_enabled(target, i)) + continue; + + riscv_set_current_hartid(target, i); + + struct riscv_program program; + riscv_program_init(&program, target); + riscv_program_fence_i(&program); + riscv_program_fence(&program); + int result = riscv_program_exec(&program, target); + if (result != ERROR_OK) + LOG_DEBUG("Unable to execute fence on hart %d", i); + } + + riscv_set_current_hartid(target, old_hartid); + + return ERROR_OK; } static void log_memory_access(target_addr_t address, uint64_t value, @@ -2015,22 +2078,241 @@ static int read_memory_bus_v1(struct target *target, target_addr_t address, return ERROR_OK; } +static int batch_run(const struct target *target, struct riscv_batch *batch) +{ + RISCV013_INFO(info); + RISCV_INFO(r); + if (r->reset_delays_wait >= 0) { + r->reset_delays_wait -= batch->used_scans; + if (r->reset_delays_wait <= 0) { + batch->idle_count = 0; + info->dmi_busy_delay = 0; + info->ac_busy_delay = 0; + } + } + return riscv_batch_run(batch); +} + /** * Read the requested memory, taking care to execute every read exactly once, * even if cmderr=busy is encountered. */ -static int read_memory_progbuf(struct target *target, target_addr_t address, +static int read_memory_progbuf_inner(struct target *target, target_addr_t address, uint32_t size, uint32_t count, uint8_t *buffer) { RISCV013_INFO(info); int result = ERROR_OK; + /* Write address to S0, and execute buffer. */ + result = register_write_direct(target, GDB_REGNO_S0, address); + if (result != ERROR_OK) + goto error; + uint32_t command = access_register_command(target, GDB_REGNO_S1, + riscv_xlen(target), + AC_ACCESS_REGISTER_TRANSFER | AC_ACCESS_REGISTER_POSTEXEC); + if (execute_abstract_command(target, command) != ERROR_OK) + return ERROR_FAIL; + + /* First read has just triggered. Result is in s1. */ + + if (count == 1) { + uint64_t value; + if (register_read_direct(target, &value, GDB_REGNO_S1) != ERROR_OK) + return ERROR_FAIL; + write_to_buf(buffer, value, size); + log_memory_access(address, value, size, true); + return ERROR_OK; + } + + if (dmi_write(target, DMI_ABSTRACTAUTO, + 1 << DMI_ABSTRACTAUTO_AUTOEXECDATA_OFFSET) != ERROR_OK) + goto error; + /* Read garbage from dmi_data0, which triggers another execution of the + * program. Now dmi_data0 contains the first good result, and s1 the next + * memory value. */ + if (dmi_read_exec(target, NULL, DMI_DATA0) != ERROR_OK) + goto error; + + /* read_addr is the next address that the hart will read from, which is the + * value in s0. */ + riscv_addr_t read_addr = address + 2 * size; + riscv_addr_t fin_addr = address + (count * size); + while (read_addr < fin_addr) { + LOG_DEBUG("read_addr=0x%" PRIx64 ", fin_addr=0x%" PRIx64, read_addr, + fin_addr); + /* The pipeline looks like this: + * memory -> s1 -> dm_data0 -> debugger + * Right now: + * s0 contains read_addr + * s1 contains mem[read_addr-size] + * dm_data0 contains[read_addr-size*2] + */ + + LOG_DEBUG("creating burst to read from 0x%" PRIx64 + " up to 0x%" PRIx64, read_addr, fin_addr); + assert(read_addr >= address && read_addr < fin_addr); + struct riscv_batch *batch = riscv_batch_alloc(target, 32, + info->dmi_busy_delay + info->ac_busy_delay); + + size_t reads = 0; + for (riscv_addr_t addr = read_addr; addr < fin_addr; addr += size) { + riscv_batch_add_dmi_read(batch, DMI_DATA0); + + reads++; + if (riscv_batch_full(batch)) + break; + } + + batch_run(target, batch); + + /* Wait for the target to finish performing the last abstract command, + * and update our copy of cmderr. If we see that DMI is busy here, + * dmi_busy_delay will be incremented. */ + uint32_t abstractcs; + if (dmi_read(target, &abstractcs, DMI_ABSTRACTCS) != ERROR_OK) + return ERROR_FAIL; + while (get_field(abstractcs, DMI_ABSTRACTCS_BUSY)) + if (dmi_read(target, &abstractcs, DMI_ABSTRACTCS) != ERROR_OK) + return ERROR_FAIL; + info->cmderr = get_field(abstractcs, DMI_ABSTRACTCS_CMDERR); + + riscv_addr_t next_read_addr; + unsigned ignore_last = 0; + switch (info->cmderr) { + case CMDERR_NONE: + LOG_DEBUG("successful (partial?) memory read"); + next_read_addr = read_addr + reads * size; + break; + case CMDERR_BUSY: + LOG_DEBUG("memory read resulted in busy response"); + + increase_ac_busy_delay(target); + riscv013_clear_abstract_error(target); + + dmi_write(target, DMI_ABSTRACTAUTO, 0); + + uint32_t dmi_data0; + /* This is definitely a good version of the value that we + * attempted to read when we discovered that the target was + * busy. */ + if (dmi_read(target, &dmi_data0, DMI_DATA0) != ERROR_OK) { + riscv_batch_free(batch); + goto error; + } + + /* See how far we got, clobbering dmi_data0. */ + result = register_read_direct(target, &next_read_addr, + GDB_REGNO_S0); + if (result != ERROR_OK) { + riscv_batch_free(batch); + goto error; + } + write_to_buf(buffer + next_read_addr - 2 * size - address, dmi_data0, size); + log_memory_access(next_read_addr - 2 * size, dmi_data0, size, true); + + /* Restore the command, and execute it. + * Now DMI_DATA0 contains the next value just as it would if no + * error had occurred. */ + dmi_write_exec(target, DMI_COMMAND, command); + next_read_addr += size; + + dmi_write(target, DMI_ABSTRACTAUTO, + 1 << DMI_ABSTRACTAUTO_AUTOEXECDATA_OFFSET); + + ignore_last = 1; + + break; + default: + LOG_DEBUG("error when reading memory, abstractcs=0x%08lx", (long)abstractcs); + riscv013_clear_abstract_error(target); + riscv_batch_free(batch); + result = ERROR_FAIL; + goto error; + } + + /* Now read whatever we got out of the batch. */ + dmi_status_t status = DMI_STATUS_SUCCESS; + for (size_t i = 0; i < reads; i++) { + riscv_addr_t receive_addr = read_addr + (i-2) * size; + assert(receive_addr < address + size * count); + if (receive_addr < address) + continue; + if (receive_addr > next_read_addr - (3 + ignore_last) * size) + break; + + uint64_t dmi_out = riscv_batch_get_dmi_read(batch, i); + status = get_field(dmi_out, DTM_DMI_OP); + if (status != DMI_STATUS_SUCCESS) { + /* If we're here because of busy count, dmi_busy_delay will + * already have been increased and busy state will have been + * cleared in dmi_read(). */ + /* In at least some implementations, we issue a read, and then + * can get busy back when we try to scan out the read result, + * and the actual read value is lost forever. Since this is + * rare in any case, we return error here and rely on our + * caller to reread the entire block. */ + LOG_WARNING("Batch memory read encountered DMI error %d. " + "Falling back on slower reads.", status); + riscv_batch_free(batch); + result = ERROR_FAIL; + goto error; + } + uint32_t value = get_field(dmi_out, DTM_DMI_DATA); + riscv_addr_t offset = receive_addr - address; + write_to_buf(buffer + offset, value, size); + log_memory_access(receive_addr, value, size, true); + + receive_addr += size; + } + + read_addr = next_read_addr; + + riscv_batch_free(batch); + } + + dmi_write(target, DMI_ABSTRACTAUTO, 0); + + if (count > 1) { + /* Read the penultimate word. */ + uint32_t value; + if (dmi_read(target, &value, DMI_DATA0) != ERROR_OK) + return ERROR_FAIL; + write_to_buf(buffer + size * (count-2), value, size); + log_memory_access(address + size * (count-2), value, size, true); + } + + /* Read the last word. */ + uint64_t value; + result = register_read_direct(target, &value, GDB_REGNO_S1); + if (result != ERROR_OK) + goto error; + write_to_buf(buffer + size * (count-1), value, size); + log_memory_access(address + size * (count-1), value, size, true); + + return ERROR_OK; + +error: + dmi_write(target, DMI_ABSTRACTAUTO, 0); + + return result; +} + +/** + * Read the requested memory, silently handling memory access errors. + */ +static int read_memory_progbuf(struct target *target, target_addr_t address, + uint32_t size, uint32_t count, uint8_t *buffer) +{ + int result = ERROR_OK; + LOG_DEBUG("reading %d words of %d bytes from 0x%" TARGET_PRIxADDR, count, size, address); select_dmi(target); + memset(buffer, 0, count*size); + /* s0 holds the next address to write to * s1 holds the next data value to write */ @@ -2066,198 +2348,34 @@ static int read_memory_progbuf(struct target *target, target_addr_t address, return ERROR_FAIL; riscv_program_write(&program); - /* Write address to S0, and execute buffer. */ - result = register_write_direct(target, GDB_REGNO_S0, address); - if (result != ERROR_OK) - goto error; - uint32_t command = access_register_command(GDB_REGNO_S1, riscv_xlen(target), - AC_ACCESS_REGISTER_TRANSFER | - AC_ACCESS_REGISTER_POSTEXEC); - result = execute_abstract_command(target, command); - if (result != ERROR_OK) - goto error; + result = read_memory_progbuf_inner(target, address, size, count, buffer); - /* First read has just triggered. Result is in s1. */ + if (result != ERROR_OK) { + /* The full read did not succeed, so we will try to read each word individually. */ + /* This will not be fast, but reading outside actual memory is a special case anyway. */ + /* It will make the toolchain happier, especially Eclipse Memory View as it reads ahead. */ + target_addr_t address_i = address; + uint32_t size_i = size; + uint32_t count_i = 1; + uint8_t *buffer_i = buffer; - dmi_write(target, DMI_ABSTRACTAUTO, - 1 << DMI_ABSTRACTAUTO_AUTOEXECDATA_OFFSET); + for (uint32_t i = 0; i < count; i++, address_i += size_i, buffer_i += size_i) { + /* TODO: This is much slower than it needs to be because we end up + * writing the address to read for every word we read. */ + result = read_memory_progbuf_inner(target, address_i, size_i, count_i, buffer_i); - /* read_addr is the next address that the hart will read from, which is the - * value in s0. */ - riscv_addr_t read_addr = address + size; - /* The next address that we need to receive data for. */ - riscv_addr_t receive_addr = address; - riscv_addr_t fin_addr = address + (count * size); - unsigned skip = 1; - while (read_addr < fin_addr) { - LOG_DEBUG("read_addr=0x%" PRIx64 ", receive_addr=0x%" PRIx64 - ", fin_addr=0x%" PRIx64, read_addr, receive_addr, fin_addr); - /* The pipeline looks like this: - * memory -> s1 -> dm_data0 -> debugger - * It advances every time the debugger reads dmdata0. - * So at any time the debugger has just read mem[s0 - 3*size], - * dm_data0 contains mem[s0 - 2*size] - * s1 contains mem[s0-size] */ + /* The read of a single word failed, so we will just return 0 for that instead */ + if (result != ERROR_OK) { + LOG_DEBUG("error reading single word of %d bytes from 0x%" TARGET_PRIxADDR, + size_i, address_i); - LOG_DEBUG("creating burst to read from 0x%" PRIx64 - " up to 0x%" PRIx64, read_addr, fin_addr); - assert(read_addr >= address && read_addr < fin_addr); - struct riscv_batch *batch = riscv_batch_alloc(target, 32, - info->dmi_busy_delay + info->ac_busy_delay); - - size_t reads = 0; - for (riscv_addr_t addr = read_addr; addr < fin_addr; addr += size) { - riscv_batch_add_dmi_read(batch, DMI_DATA0); - - reads++; - if (riscv_batch_full(batch)) - break; - } - - riscv_batch_run(batch); - - /* Wait for the target to finish performing the last abstract command, - * and update our copy of cmderr. */ - uint32_t abstractcs; - if (dmi_read(target, &abstractcs, DMI_ABSTRACTCS) != ERROR_OK) - return ERROR_FAIL; - while (get_field(abstractcs, DMI_ABSTRACTCS_BUSY)) - if (dmi_read(target, &abstractcs, DMI_ABSTRACTCS) != ERROR_OK) - return ERROR_FAIL; - info->cmderr = get_field(abstractcs, DMI_ABSTRACTCS_CMDERR); - - unsigned cmderr = info->cmderr; - riscv_addr_t next_read_addr; - uint32_t dmi_data0 = -1; - switch (info->cmderr) { - case CMDERR_NONE: - LOG_DEBUG("successful (partial?) memory read"); - next_read_addr = read_addr + reads * size; - break; - case CMDERR_BUSY: - LOG_DEBUG("memory read resulted in busy response"); - - /* - * If you want to exercise this code path, apply the following patch to spike: ---- a/riscv/debug_module.cc -+++ b/riscv/debug_module.cc -@@ -1,3 +1,5 @@ -+#include -+ - #include - - #include "debug_module.h" -@@ -398,6 +400,15 @@ bool debug_module_t::perform_abstract_command() - // Since the next instruction is what we will use, just use nother NOP - // to get there. - write32(debug_abstract, 1, addi(ZERO, ZERO, 0)); -+ -+ if (abstractauto.autoexecdata && -+ program_buffer[0] == 0x83 && -+ program_buffer[1] == 0x24 && -+ program_buffer[2] == 0x04 && -+ program_buffer[3] == 0 && -+ rand() < RAND_MAX / 10) { -+ usleep(1000000); -+ } - } else { - write32(debug_abstract, 1, ebreak()); - } - */ - increase_ac_busy_delay(target); - riscv013_clear_abstract_error(target); - - dmi_write(target, DMI_ABSTRACTAUTO, 0); - - /* This is definitely a good version of the value that we - * attempted to read when we discovered that the target was - * busy. */ - if (dmi_read(target, &dmi_data0, DMI_DATA0) != ERROR_OK) { - riscv_batch_free(batch); - goto error; - } - - /* Clobbers DMI_DATA0. */ - result = register_read_direct(target, &next_read_addr, - GDB_REGNO_S0); - if (result != ERROR_OK) { - riscv_batch_free(batch); - goto error; - } - /* Restore the command, and execute it. - * Now DMI_DATA0 contains the next value just as it would if no - * error had occurred. */ - dmi_write(target, DMI_COMMAND, command); - - dmi_write(target, DMI_ABSTRACTAUTO, - 1 << DMI_ABSTRACTAUTO_AUTOEXECDATA_OFFSET); - break; - default: - LOG_ERROR("error when reading memory, abstractcs=0x%08lx", (long)abstractcs); - riscv013_clear_abstract_error(target); - riscv_batch_free(batch); - result = ERROR_FAIL; - goto error; - } - - /* Now read whatever we got out of the batch. */ - for (size_t i = 0; i < reads; i++) { - if (read_addr >= next_read_addr) - break; - - read_addr += size; - - if (skip > 0) { - skip--; - continue; + uint64_t value_i = 0; + write_to_buf(buffer_i, value_i, size_i); } - - riscv_addr_t offset = receive_addr - address; - uint64_t dmi_out = riscv_batch_get_dmi_read(batch, i); - uint32_t value = get_field(dmi_out, DTM_DMI_DATA); - write_to_buf(buffer + offset, value, size); - log_memory_access(receive_addr, value, size, true); - - receive_addr += size; - } - riscv_batch_free(batch); - - if (cmderr == CMDERR_BUSY) { - riscv_addr_t offset = receive_addr - address; - write_to_buf(buffer + offset, dmi_data0, size); - log_memory_access(receive_addr, dmi_data0, size, true); - read_addr += size; - receive_addr += size; } + result = ERROR_OK; } - dmi_write(target, DMI_ABSTRACTAUTO, 0); - - if (count > 1) { - /* Read the penultimate word. */ - uint32_t value; - if (dmi_read(target, &value, DMI_DATA0) != ERROR_OK) - goto error; - write_to_buf(buffer + receive_addr - address, value, size); - log_memory_access(receive_addr, value, size, true); - receive_addr += size; - } - - /* Read the last word. */ - uint64_t value; - result = register_read_direct(target, &value, GDB_REGNO_S1); - if (result != ERROR_OK) - goto error; - write_to_buf(buffer + receive_addr - address, value, size); - log_memory_access(receive_addr, value, size, true); - - riscv_set_register(target, GDB_REGNO_S0, s0); - riscv_set_register(target, GDB_REGNO_S1, s1); - return ERROR_OK; - -error: - dmi_write(target, DMI_ABSTRACTAUTO, 0); - riscv_set_register(target, GDB_REGNO_S0, s0); riscv_set_register(target, GDB_REGNO_S1, s1); return result; @@ -2558,7 +2676,8 @@ static int write_memory_progbuf(struct target *target, target_addr_t address, /* Write and execute command that moves value into S1 and * executes program buffer. */ - uint32_t command = access_register_command(GDB_REGNO_S1, 32, + uint32_t command = access_register_command(target, + GDB_REGNO_S1, 32, AC_ACCESS_REGISTER_POSTEXEC | AC_ACCESS_REGISTER_TRANSFER | AC_ACCESS_REGISTER_WRITE); @@ -2580,7 +2699,7 @@ static int write_memory_progbuf(struct target *target, target_addr_t address, } } - result = riscv_batch_run(batch); + result = batch_run(target, batch); riscv_batch_free(batch); if (result != ERROR_OK) goto error; @@ -2590,33 +2709,34 @@ static int write_memory_progbuf(struct target *target, target_addr_t address, * to be incremented if necessary. */ uint32_t abstractcs; - if (dmi_read(target, &abstractcs, DMI_ABSTRACTCS) != ERROR_OK) + bool dmi_busy_encountered; + if (dmi_op(target, &abstractcs, &dmi_busy_encountered, DMI_OP_READ, + DMI_ABSTRACTCS, 0, false) != ERROR_OK) goto error; while (get_field(abstractcs, DMI_ABSTRACTCS_BUSY)) if (dmi_read(target, &abstractcs, DMI_ABSTRACTCS) != ERROR_OK) return ERROR_FAIL; info->cmderr = get_field(abstractcs, DMI_ABSTRACTCS_CMDERR); - switch (info->cmderr) { - case CMDERR_NONE: - LOG_DEBUG("successful (partial?) memory write"); - break; - case CMDERR_BUSY: - LOG_DEBUG("memory write resulted in busy response"); - riscv013_clear_abstract_error(target); - increase_ac_busy_delay(target); + if (info->cmderr == CMDERR_NONE && !dmi_busy_encountered) { + LOG_DEBUG("successful (partial?) memory write"); + } else if (info->cmderr == CMDERR_BUSY || dmi_busy_encountered) { + if (info->cmderr == CMDERR_BUSY) + LOG_DEBUG("Memory write resulted in abstract command busy response."); + else if (dmi_busy_encountered) + LOG_DEBUG("Memory write resulted in DMI busy response."); + riscv013_clear_abstract_error(target); + increase_ac_busy_delay(target); - dmi_write(target, DMI_ABSTRACTAUTO, 0); - result = register_read_direct(target, &cur_addr, GDB_REGNO_S0); - if (result != ERROR_OK) - goto error; - setup_needed = true; - break; - - default: - LOG_ERROR("error when writing memory, abstractcs=0x%08lx", (long)abstractcs); - riscv013_clear_abstract_error(target); - result = ERROR_FAIL; + dmi_write(target, DMI_ABSTRACTAUTO, 0); + result = register_read_direct(target, &cur_addr, GDB_REGNO_S0); + if (result != ERROR_OK) goto error; + setup_needed = true; + } else { + LOG_ERROR("error when writing memory, abstractcs=0x%08lx", (long)abstractcs); + riscv013_clear_abstract_error(target); + result = ERROR_FAIL; + goto error; } } @@ -2696,7 +2816,7 @@ static int riscv013_get_register(struct target *target, int result = ERROR_OK; if (rid == GDB_REGNO_PC) { result = register_read(target, value, GDB_REGNO_DPC); - LOG_DEBUG("read PC from DPC: 0x%016" PRIx64, *value); + LOG_DEBUG("read PC from DPC: 0x%" PRIx64, *value); } else if (rid == GDB_REGNO_PRIV) { uint64_t dcsr; result = register_read(target, &dcsr, GDB_REGNO_DCSR); @@ -2720,7 +2840,7 @@ static int riscv013_set_register(struct target *target, int hid, int rid, uint64 if (rid <= GDB_REGNO_XPR31) { return register_write_direct(target, rid, value); } else if (rid == GDB_REGNO_PC) { - LOG_DEBUG("writing PC to DPC: 0x%016" PRIx64, value); + LOG_DEBUG("writing PC to DPC: 0x%" PRIx64, value); register_write_direct(target, GDB_REGNO_DPC, value); uint64_t actual_value; register_read_direct(target, &actual_value, GDB_REGNO_DPC); @@ -2864,6 +2984,7 @@ static enum riscv_halt_reason riscv013_halt_reason(struct target *target) * already set when we connected. Force enumeration now, which has the * side effect of clearing any triggers we did not set. */ riscv_enumerate_triggers(target); + LOG_DEBUG("{%d} halted because of trigger", target->coreid); return RISCV_HALT_TRIGGER; case CSR_DCSR_CAUSE_STEP: return RISCV_HALT_SINGLESTEP; @@ -2924,6 +3045,357 @@ void riscv013_fill_dmi_nop_u64(struct target *target, char *buf) buf_set_u64((unsigned char *)buf, DTM_DMI_ADDRESS_OFFSET, info->abits, 0); } +/* Helper function for riscv013_test_sba_config_reg */ +static int get_max_sbaccess(struct target *target) +{ + RISCV013_INFO(info); + + uint32_t sbaccess128 = get_field(info->sbcs, DMI_SBCS_SBACCESS128); + uint32_t sbaccess64 = get_field(info->sbcs, DMI_SBCS_SBACCESS64); + uint32_t sbaccess32 = get_field(info->sbcs, DMI_SBCS_SBACCESS32); + uint32_t sbaccess16 = get_field(info->sbcs, DMI_SBCS_SBACCESS16); + uint32_t sbaccess8 = get_field(info->sbcs, DMI_SBCS_SBACCESS8); + + if (sbaccess128) + return 4; + else if (sbaccess64) + return 3; + else if (sbaccess32) + return 2; + else if (sbaccess16) + return 1; + else if (sbaccess8) + return 0; + else + return -1; +} + +static uint32_t get_num_sbdata_regs(struct target *target) +{ + RISCV013_INFO(info); + + uint32_t sbaccess128 = get_field(info->sbcs, DMI_SBCS_SBACCESS128); + uint32_t sbaccess64 = get_field(info->sbcs, DMI_SBCS_SBACCESS64); + uint32_t sbaccess32 = get_field(info->sbcs, DMI_SBCS_SBACCESS32); + + if (sbaccess128) + return 4; + else if (sbaccess64) + return 2; + else if (sbaccess32) + return 1; + else + return 0; +} + +static int riscv013_test_sba_config_reg(struct target *target, + target_addr_t legal_address, uint32_t num_words, + target_addr_t illegal_address, bool run_sbbusyerror_test) +{ + LOG_INFO("Testing System Bus Access as defined by RISC-V Debug Spec v0.13"); + + uint32_t tests_failed = 0; + + uint32_t rd_val; + uint32_t sbcs_orig; + dmi_read(target, &sbcs_orig, DMI_SBCS); + + uint32_t sbcs = sbcs_orig; + bool test_passed; + + int max_sbaccess = get_max_sbaccess(target); + + if (max_sbaccess == -1) { + LOG_ERROR("System Bus Access not supported in this config."); + return ERROR_FAIL; + } + + if (get_field(sbcs, DMI_SBCS_SBVERSION) != 1) { + LOG_ERROR("System Bus Access unsupported SBVERSION (%d). Only version 1 is supported.", + get_field(sbcs, DMI_SBCS_SBVERSION)); + return ERROR_FAIL; + } + + uint32_t num_sbdata_regs = get_num_sbdata_regs(target); + + uint32_t rd_buf[num_sbdata_regs]; + + /* Test 1: Simple write/read test */ + test_passed = true; + sbcs = set_field(sbcs_orig, DMI_SBCS_SBAUTOINCREMENT, 0); + dmi_write(target, DMI_SBCS, sbcs); + + uint32_t test_patterns[4] = {0xdeadbeef, 0xfeedbabe, 0x12345678, 0x08675309}; + for (uint32_t sbaccess = 0; sbaccess <= (uint32_t)max_sbaccess; sbaccess++) { + sbcs = set_field(sbcs, DMI_SBCS_SBACCESS, sbaccess); + dmi_write(target, DMI_SBCS, sbcs); + + uint32_t compare_mask = (sbaccess == 0) ? 0xff : (sbaccess == 1) ? 0xffff : 0xffffffff; + + for (uint32_t i = 0; i < num_words; i++) { + uint32_t addr = legal_address + (i << sbaccess); + uint32_t wr_data[num_sbdata_regs]; + for (uint32_t j = 0; j < num_sbdata_regs; j++) + wr_data[j] = test_patterns[j] + i; + write_memory_sba_simple(target, addr, wr_data, num_sbdata_regs, sbcs); + } + + for (uint32_t i = 0; i < num_words; i++) { + uint32_t addr = legal_address + (i << sbaccess); + read_memory_sba_simple(target, addr, rd_buf, num_sbdata_regs, sbcs); + for (uint32_t j = 0; j < num_sbdata_regs; j++) { + if (((test_patterns[j]+i)&compare_mask) != (rd_buf[j]&compare_mask)) { + LOG_ERROR("System Bus Access Test 1: Error reading non-autoincremented address %x," + "expected val = %x, read val = %x", addr, test_patterns[j]+i, rd_buf[j]); + test_passed = false; + tests_failed++; + } + } + } + } + if (test_passed) + LOG_INFO("System Bus Access Test 1: Simple write/read test PASSED."); + + /* Test 2: Address autoincrement test */ + target_addr_t curr_addr; + target_addr_t prev_addr; + test_passed = true; + sbcs = set_field(sbcs_orig, DMI_SBCS_SBAUTOINCREMENT, 1); + dmi_write(target, DMI_SBCS, sbcs); + + for (uint32_t sbaccess = 0; sbaccess <= (uint32_t)max_sbaccess; sbaccess++) { + sbcs = set_field(sbcs, DMI_SBCS_SBACCESS, sbaccess); + dmi_write(target, DMI_SBCS, sbcs); + + dmi_write(target, DMI_SBADDRESS0, legal_address); + read_sbcs_nonbusy(target, &sbcs); + curr_addr = legal_address; + for (uint32_t i = 0; i < num_words; i++) { + prev_addr = curr_addr; + read_sbcs_nonbusy(target, &sbcs); + curr_addr = sb_read_address(target); + if ((curr_addr - prev_addr != (uint32_t)(1 << sbaccess)) && (i != 0)) { + LOG_ERROR("System Bus Access Test 2: Error with address auto-increment, sbaccess = %x.", sbaccess); + test_passed = false; + tests_failed++; + } + dmi_write(target, DMI_SBDATA0, i); + } + + read_sbcs_nonbusy(target, &sbcs); + + dmi_write(target, DMI_SBADDRESS0, legal_address); + + uint32_t val; + sbcs = set_field(sbcs, DMI_SBCS_SBREADONDATA, 1); + dmi_write(target, DMI_SBCS, sbcs); + dmi_read(target, &val, DMI_SBDATA0); /* Dummy read to trigger first system bus read */ + curr_addr = legal_address; + for (uint32_t i = 0; i < num_words; i++) { + prev_addr = curr_addr; + read_sbcs_nonbusy(target, &sbcs); + curr_addr = sb_read_address(target); + if ((curr_addr - prev_addr != (uint32_t)(1 << sbaccess)) && (i != 0)) { + LOG_ERROR("System Bus Access Test 2: Error with address auto-increment, sbaccess = %x", sbaccess); + test_passed = false; + tests_failed++; + } + dmi_read(target, &val, DMI_SBDATA0); + read_sbcs_nonbusy(target, &sbcs); + if (i != val) { + LOG_ERROR("System Bus Access Test 2: Error reading auto-incremented address," + "expected val = %x, read val = %x.", i, val); + test_passed = false; + tests_failed++; + } + } + } + if (test_passed) + LOG_INFO("System Bus Access Test 2: Address auto-increment test PASSED."); + + /* Test 3: Read from illegal address */ + read_memory_sba_simple(target, illegal_address, rd_buf, 1, sbcs_orig); + + dmi_read(target, &rd_val, DMI_SBCS); + if (get_field(rd_val, DMI_SBCS_SBERROR) == 2) { + sbcs = set_field(sbcs_orig, DMI_SBCS_SBERROR, 2); + dmi_write(target, DMI_SBCS, sbcs); + dmi_read(target, &rd_val, DMI_SBCS); + if (get_field(rd_val, DMI_SBCS_SBERROR) == 0) + LOG_INFO("System Bus Access Test 3: Illegal address read test PASSED."); + else + LOG_ERROR("System Bus Access Test 3: Illegal address read test FAILED, unable to clear to 0."); + } else { + LOG_ERROR("System Bus Access Test 3: Illegal address read test FAILED, unable to set error code."); + } + + /* Test 4: Write to illegal address */ + write_memory_sba_simple(target, illegal_address, test_patterns, 1, sbcs_orig); + + dmi_read(target, &rd_val, DMI_SBCS); + if (get_field(rd_val, DMI_SBCS_SBERROR) == 2) { + sbcs = set_field(sbcs_orig, DMI_SBCS_SBERROR, 2); + dmi_write(target, DMI_SBCS, sbcs); + dmi_read(target, &rd_val, DMI_SBCS); + if (get_field(rd_val, DMI_SBCS_SBERROR) == 0) + LOG_INFO("System Bus Access Test 4: Illegal address write test PASSED."); + else { + LOG_ERROR("System Bus Access Test 4: Illegal address write test FAILED, unable to clear to 0."); + tests_failed++; + } + } else { + LOG_ERROR("System Bus Access Test 4: Illegal address write test FAILED, unable to set error code."); + tests_failed++; + } + + /* Test 5: Write with unsupported sbaccess size */ + uint32_t sbaccess128 = get_field(sbcs_orig, DMI_SBCS_SBACCESS128); + + if (sbaccess128) { + LOG_INFO("System Bus Access Test 5: SBCS sbaccess error test PASSED, all sbaccess sizes supported."); + } else { + sbcs = set_field(sbcs_orig, DMI_SBCS_SBACCESS, 4); + + write_memory_sba_simple(target, legal_address, test_patterns, 1, sbcs); + + dmi_read(target, &rd_val, DMI_SBCS); + if (get_field(rd_val, DMI_SBCS_SBERROR) == 4) { + sbcs = set_field(sbcs_orig, DMI_SBCS_SBERROR, 4); + dmi_write(target, DMI_SBCS, sbcs); + dmi_read(target, &rd_val, DMI_SBCS); + if (get_field(rd_val, DMI_SBCS_SBERROR) == 0) + LOG_INFO("System Bus Access Test 5: SBCS sbaccess error test PASSED."); + else { + LOG_ERROR("System Bus Access Test 5: SBCS sbaccess error test FAILED, unable to clear to 0."); + tests_failed++; + } + } else { + LOG_ERROR("System Bus Access Test 5: SBCS sbaccess error test FAILED, unable to set error code."); + tests_failed++; + } + } + + /* Test 6: Write to misaligned address */ + sbcs = set_field(sbcs_orig, DMI_SBCS_SBACCESS, 1); + + write_memory_sba_simple(target, legal_address+1, test_patterns, 1, sbcs); + + dmi_read(target, &rd_val, DMI_SBCS); + if (get_field(rd_val, DMI_SBCS_SBERROR) == 3) { + sbcs = set_field(sbcs_orig, DMI_SBCS_SBERROR, 3); + dmi_write(target, DMI_SBCS, sbcs); + dmi_read(target, &rd_val, DMI_SBCS); + if (get_field(rd_val, DMI_SBCS_SBERROR) == 0) + LOG_INFO("System Bus Access Test 6: SBCS address alignment error test PASSED"); + else { + LOG_ERROR("System Bus Access Test 6: SBCS address alignment error test FAILED, unable to clear to 0."); + tests_failed++; + } + } else { + LOG_ERROR("System Bus Access Test 6: SBCS address alignment error test FAILED, unable to set error code."); + tests_failed++; + } + + /* Test 7: Set sbbusyerror, only run this case in simulation as it is likely + * impossible to hit otherwise */ + if (run_sbbusyerror_test) { + sbcs = set_field(sbcs_orig, DMI_SBCS_SBREADONADDR, 1); + dmi_write(target, DMI_SBCS, sbcs); + + for (int i = 0; i < 16; i++) + dmi_write(target, DMI_SBDATA0, 0xdeadbeef); + + for (int i = 0; i < 16; i++) + dmi_write(target, DMI_SBADDRESS0, legal_address); + + dmi_read(target, &rd_val, DMI_SBCS); + if (get_field(rd_val, DMI_SBCS_SBBUSYERROR)) { + sbcs = set_field(sbcs_orig, DMI_SBCS_SBBUSYERROR, 1); + dmi_write(target, DMI_SBCS, sbcs); + dmi_read(target, &rd_val, DMI_SBCS); + if (get_field(rd_val, DMI_SBCS_SBBUSYERROR) == 0) + LOG_INFO("System Bus Access Test 7: SBCS sbbusyerror test PASSED."); + else { + LOG_ERROR("System Bus Access Test 7: SBCS sbbusyerror test FAILED, unable to clear to 0."); + tests_failed++; + } + } else { + LOG_ERROR("System Bus Access Test 7: SBCS sbbusyerror test FAILED, unable to set error code."); + tests_failed++; + } + } + + if (tests_failed == 0) { + LOG_INFO("ALL TESTS PASSED"); + return ERROR_OK; + } else { + LOG_ERROR("%d TESTS FAILED", tests_failed); + return ERROR_FAIL; + } + +} + +void write_memory_sba_simple(struct target *target, target_addr_t addr, + uint32_t *write_data, uint32_t write_size, uint32_t sbcs) +{ + RISCV013_INFO(info); + + uint32_t rd_sbcs; + uint32_t masked_addr; + + uint32_t sba_size = get_field(info->sbcs, DMI_SBCS_SBASIZE); + + read_sbcs_nonbusy(target, &rd_sbcs); + + uint32_t sbcs_no_readonaddr = set_field(sbcs, DMI_SBCS_SBREADONADDR, 0); + dmi_write(target, DMI_SBCS, sbcs_no_readonaddr); + + for (uint32_t i = 0; i < sba_size/32; i++) { + masked_addr = (addr >> 32*i) & 0xffffffff; + + if (i != 3) + dmi_write(target, DMI_SBADDRESS0+i, masked_addr); + else + dmi_write(target, DMI_SBADDRESS3, masked_addr); + } + + /* Write SBDATA registers starting with highest address, since write to + * SBDATA0 triggers write */ + for (int i = write_size-1; i >= 0; i--) + dmi_write(target, DMI_SBDATA0+i, write_data[i]); +} + +void read_memory_sba_simple(struct target *target, target_addr_t addr, + uint32_t *rd_buf, uint32_t read_size, uint32_t sbcs) +{ + RISCV013_INFO(info); + + uint32_t rd_sbcs; + uint32_t masked_addr; + + uint32_t sba_size = get_field(info->sbcs, DMI_SBCS_SBASIZE); + + read_sbcs_nonbusy(target, &rd_sbcs); + + uint32_t sbcs_readonaddr = set_field(sbcs, DMI_SBCS_SBREADONADDR, 1); + dmi_write(target, DMI_SBCS, sbcs_readonaddr); + + /* Write addresses starting with highest address register */ + for (int i = sba_size/32-1; i >= 0; i--) { + masked_addr = (addr >> 32*i) & 0xffffffff; + + if (i != 3) + dmi_write(target, DMI_SBADDRESS0+i, masked_addr); + else + dmi_write(target, DMI_SBADDRESS3, masked_addr); + } + + read_sbcs_nonbusy(target, &rd_sbcs); + + for (uint32_t i = 0; i < read_size; i++) + dmi_read(target, &(rd_buf[i]), DMI_SBDATA0+i); +} + int riscv013_dmi_write_u64_bits(struct target *target) { RISCV013_INFO(info); @@ -2934,16 +3406,8 @@ static int maybe_execute_fence_i(struct target *target) { RISCV013_INFO(info); RISCV_INFO(r); - if (info->progbufsize + r->impebreak >= 2) { - struct riscv_program program; - riscv_program_init(&program, target); - if (riscv_program_fence_i(&program) != ERROR_OK) - return ERROR_FAIL; - if (riscv_program_exec(&program, target) != ERROR_OK) { - LOG_ERROR("Failed to execute fence.i"); - return ERROR_FAIL; - } - } + if (info->progbufsize + r->impebreak >= 3) + return execute_fence(target); return ERROR_OK; } @@ -3034,3 +3498,459 @@ void riscv013_clear_abstract_error(struct target *target) /* Clear the error status. */ dmi_write(target, DMI_ABSTRACTCS, abstractcs & DMI_ABSTRACTCS_CMDERR); } + +#define COMPLIANCE_TEST(b, message) \ +{ \ + int pass = 0; \ + if (b) { \ + pass = 1; \ + passed_tests++; \ + } \ + LOG_INFO("%s test %d (%s)\n", (pass) ? "PASSED" : "FAILED", total_tests, message); \ + assert(pass); \ + total_tests++; \ +} + +#define COMPLIANCE_MUST_PASS(b) COMPLIANCE_TEST(ERROR_OK == (b), "Regular calls must return ERROR_OK") + +#define COMPLIANCE_READ(target, addr, value) COMPLIANCE_MUST_PASS(dmi_read(target, addr, value)) +#define COMPLIANCE_WRITE(target, addr, value) COMPLIANCE_MUST_PASS(dmi_write(target, addr, value)) + +#define COMPLIANCE_CHECK_RO(target, addr) \ +{ \ + uint32_t orig; \ + uint32_t inverse; \ + COMPLIANCE_READ(target, &orig, addr); \ + COMPLIANCE_WRITE(target, addr, ~orig); \ + COMPLIANCE_READ(target, &inverse, addr); \ + COMPLIANCE_TEST(orig == inverse, "Register must be read-only"); \ +} + +int riscv013_test_compliance(struct target *target) +{ + LOG_INFO("Testing Compliance against RISC-V Debug Spec v0.13"); + + if (!riscv_rtos_enabled(target)) { + LOG_ERROR("Please run with -rtos riscv to run compliance test."); + return ERROR_FAIL; + } + + int total_tests = 0; + int passed_tests = 0; + + uint32_t dmcontrol_orig = DMI_DMCONTROL_DMACTIVE; + uint32_t dmcontrol; + uint32_t testvar; + uint32_t testvar_read; + riscv_reg_t value; + RISCV013_INFO(info); + + /* All the bits of HARTSEL are covered by the examine sequence. */ + + /* hartreset */ + /* This field is optional. Either we can read and write it to 1/0, + or it is tied to 0. This check doesn't really do anything, but + it does attempt to set the bit to 1 and then back to 0, which needs to + work if its implemented. */ + COMPLIANCE_WRITE(target, DMI_DMCONTROL, set_field(dmcontrol_orig, DMI_DMCONTROL_HARTRESET, 1)); + COMPLIANCE_WRITE(target, DMI_DMCONTROL, set_field(dmcontrol_orig, DMI_DMCONTROL_HARTRESET, 0)); + COMPLIANCE_READ(target, &dmcontrol, DMI_DMCONTROL); + COMPLIANCE_TEST((get_field(dmcontrol, DMI_DMCONTROL_HARTRESET) == 0), + "DMCONTROL.hartreset can be 0 or RW."); + + /* hasel */ + COMPLIANCE_WRITE(target, DMI_DMCONTROL, set_field(dmcontrol_orig, DMI_DMCONTROL_HASEL, 1)); + COMPLIANCE_WRITE(target, DMI_DMCONTROL, set_field(dmcontrol_orig, DMI_DMCONTROL_HASEL, 0)); + COMPLIANCE_READ(target, &dmcontrol, DMI_DMCONTROL); + COMPLIANCE_TEST((get_field(dmcontrol, DMI_DMCONTROL_HASEL) == 0), + "DMCONTROL.hasel can be 0 or RW."); + /* TODO: test that hamask registers exist if hasel does. */ + + /* haltreq */ + COMPLIANCE_MUST_PASS(riscv_halt_all_harts(target)); + /* This bit is not actually readable according to the spec, so nothing to check.*/ + + /* DMSTATUS */ + COMPLIANCE_CHECK_RO(target, DMI_DMSTATUS); + + /* resumereq */ + /* This bit is not actually readable according to the spec, so nothing to check.*/ + COMPLIANCE_MUST_PASS(riscv_resume_all_harts(target)); + + /* Halt all harts again so the test can continue.*/ + COMPLIANCE_MUST_PASS(riscv_halt_all_harts(target)); + + /* HARTINFO: Read-Only. This is per-hart, so need to adjust hartsel. */ + uint32_t hartinfo; + COMPLIANCE_READ(target, &hartinfo, DMI_HARTINFO); + for (int hartsel = 0; hartsel < riscv_count_harts(target); hartsel++) { + COMPLIANCE_MUST_PASS(riscv_set_current_hartid(target, hartsel)); + + COMPLIANCE_CHECK_RO(target, DMI_HARTINFO); + + /* $dscratch CSRs */ + uint32_t nscratch = get_field(hartinfo, DMI_HARTINFO_NSCRATCH); + for (unsigned int d = 0; d < nscratch; d++) { + riscv_reg_t testval, testval_read; + /* Because DSCRATCH is not guaranteed to last across PB executions, need to put + this all into one PB execution. Which may not be possible on all implementations.*/ + if (info->progbufsize >= 5) { + for (testval = 0x0011223300112233; + testval != 0xDEAD; + testval = testval == 0x0011223300112233 ? ~testval : 0xDEAD) { + COMPLIANCE_TEST(register_write_direct(target, GDB_REGNO_S0, testval) == ERROR_OK, + "Need to be able to write S0 in order to test DSCRATCH."); + struct riscv_program program32; + riscv_program_init(&program32, target); + riscv_program_csrw(&program32, GDB_REGNO_S0, GDB_REGNO_DSCRATCH + d); + riscv_program_csrr(&program32, GDB_REGNO_S1, GDB_REGNO_DSCRATCH + d); + riscv_program_fence(&program32); + riscv_program_ebreak(&program32); + COMPLIANCE_TEST(riscv_program_exec(&program32, target) == ERROR_OK, + "Accessing DSCRATCH with program buffer should succeed."); + COMPLIANCE_TEST(register_read_direct(target, &testval_read, GDB_REGNO_S1) == ERROR_OK, + "Need to be able to read S1 in order to test DSCRATCH."); + if (riscv_xlen(target) > 32) { + COMPLIANCE_TEST(testval == testval_read, + "All DSCRATCH registers in HARTINFO must be R/W."); + } else { + COMPLIANCE_TEST(testval_read == (testval & 0xFFFFFFFF), + "All DSCRATCH registers in HARTINFO must be R/W."); + } + } + } + } + /* TODO: dataaccess */ + if (get_field(hartinfo, DMI_HARTINFO_DATAACCESS)) { + /* TODO: Shadowed in memory map. */ + /* TODO: datasize */ + /* TODO: dataaddr */ + } else { + /* TODO: Shadowed in CSRs. */ + /* TODO: datasize */ + /* TODO: dataaddr */ + } + + } + + /* HALTSUM -- TODO: More than 32 harts. Would need to loop over this to set hartsel */ + /* TODO: HALTSUM2, HALTSUM3 */ + /* HALTSUM0 */ + uint32_t expected_haltsum0 = 0; + for (int i = 0; i < MIN(riscv_count_harts(target), 32); i++) + expected_haltsum0 |= (1 << i); + + COMPLIANCE_READ(target, &testvar_read, DMI_HALTSUM0); + COMPLIANCE_TEST(testvar_read == expected_haltsum0, + "HALTSUM0 should report summary of up to 32 halted harts"); + + COMPLIANCE_WRITE(target, DMI_HALTSUM0, 0xffffffff); + COMPLIANCE_READ(target, &testvar_read, DMI_HALTSUM0); + COMPLIANCE_TEST(testvar_read == expected_haltsum0, "HALTSUM0 should be R/O"); + + COMPLIANCE_WRITE(target, DMI_HALTSUM0, 0x0); + COMPLIANCE_READ(target, &testvar_read, DMI_HALTSUM0); + COMPLIANCE_TEST(testvar_read == expected_haltsum0, "HALTSUM0 should be R/O"); + + /* HALTSUM1 */ + uint32_t expected_haltsum1 = 0; + for (int i = 0; i < MIN(riscv_count_harts(target), 1024); i += 32) + expected_haltsum1 |= (1 << (i/32)); + + COMPLIANCE_READ(target, &testvar_read, DMI_HALTSUM1); + COMPLIANCE_TEST(testvar_read == expected_haltsum1, + "HALTSUM1 should report summary of up to 1024 halted harts"); + + COMPLIANCE_WRITE(target, DMI_HALTSUM1, 0xffffffff); + COMPLIANCE_READ(target, &testvar_read, DMI_HALTSUM1); + COMPLIANCE_TEST(testvar_read == expected_haltsum1, "HALTSUM1 should be R/O"); + + COMPLIANCE_WRITE(target, DMI_HALTSUM1, 0x0); + COMPLIANCE_READ(target, &testvar_read, DMI_HALTSUM1); + COMPLIANCE_TEST(testvar_read == expected_haltsum1, "HALTSUM1 should be R/O"); + + /* TODO: HAWINDOWSEL */ + + /* TODO: HAWINDOW */ + + /* ABSTRACTCS */ + + uint32_t abstractcs; + COMPLIANCE_READ(target, &abstractcs, DMI_ABSTRACTCS); + + /* Check that all reported Data Words are really R/W */ + for (int invert = 0; invert < 2; invert++) { + for (unsigned int i = 0; i < get_field(abstractcs, DMI_ABSTRACTCS_DATACOUNT); i++) { + testvar = (i + 1) * 0x11111111; + if (invert) + testvar = ~testvar; + COMPLIANCE_WRITE(target, DMI_DATA0 + i, testvar); + } + for (unsigned int i = 0; i < get_field(abstractcs, DMI_ABSTRACTCS_DATACOUNT); i++) { + testvar = (i + 1) * 0x11111111; + if (invert) + testvar = ~testvar; + COMPLIANCE_READ(target, &testvar_read, DMI_DATA0 + i); + COMPLIANCE_TEST(testvar_read == testvar, "All reported DATA words must be R/W"); + } + } + + /* Check that all reported ProgBuf words are really R/W */ + for (int invert = 0; invert < 2; invert++) { + for (unsigned int i = 0; i < get_field(abstractcs, DMI_ABSTRACTCS_PROGBUFSIZE); i++) { + testvar = (i + 1) * 0x11111111; + if (invert) + testvar = ~testvar; + COMPLIANCE_WRITE(target, DMI_PROGBUF0 + i, testvar); + } + for (unsigned int i = 0; i < get_field(abstractcs, DMI_ABSTRACTCS_PROGBUFSIZE); i++) { + testvar = (i + 1) * 0x11111111; + if (invert) + testvar = ~testvar; + COMPLIANCE_READ(target, &testvar_read, DMI_PROGBUF0 + i); + COMPLIANCE_TEST(testvar_read == testvar, "All reported PROGBUF words must be R/W"); + } + } + + /* TODO: Cause and clear all error types */ + + /* COMMAND + According to the spec, this register is only W, so can't really check the read result. + But at any rate, this is not legal and should cause an error. */ + COMPLIANCE_WRITE(target, DMI_COMMAND, 0xAAAAAAAA); + COMPLIANCE_READ(target, &testvar_read, DMI_ABSTRACTCS); + COMPLIANCE_TEST(get_field(testvar_read, DMI_ABSTRACTCS_CMDERR) == CMDERR_NOT_SUPPORTED, \ + "Illegal COMMAND should result in UNSUPPORTED"); + COMPLIANCE_WRITE(target, DMI_ABSTRACTCS, DMI_ABSTRACTCS_CMDERR); + + COMPLIANCE_WRITE(target, DMI_COMMAND, 0x55555555); + COMPLIANCE_READ(target, &testvar_read, DMI_ABSTRACTCS); + COMPLIANCE_TEST(get_field(testvar_read, DMI_ABSTRACTCS_CMDERR) == CMDERR_NOT_SUPPORTED, \ + "Illegal COMMAND should result in UNSUPPORTED"); + COMPLIANCE_WRITE(target, DMI_ABSTRACTCS, DMI_ABSTRACTCS_CMDERR); + + /* Basic Abstract Commands */ + for (unsigned int i = 1; i < 32; i = i << 1) { + riscv_reg_t testval = i | ((i + 1ULL) << 32); + riscv_reg_t testval_read; + COMPLIANCE_TEST(ERROR_OK == register_write_direct(target, GDB_REGNO_ZERO + i, testval), + "GPR Writes should be supported."); + COMPLIANCE_MUST_PASS(write_abstract_arg(target, 0, 0xDEADBEEFDEADBEEF, 64)); + COMPLIANCE_TEST(ERROR_OK == register_read_direct(target, &testval_read, GDB_REGNO_ZERO + i), + "GPR Reads should be supported."); + if (riscv_xlen(target) > 32) { + /* Dummy comment to satisfy linter, since removing the brances here doesn't actually compile. */ + COMPLIANCE_TEST(testval == testval_read, "GPR Reads and writes should be supported."); + } else { + /* Dummy comment to satisfy linter, since removing the brances here doesn't actually compile. */ + COMPLIANCE_TEST((testval & 0xFFFFFFFF) == testval_read, "GPR Reads and writes should be supported."); + } + } + + /* ABSTRACTAUTO + See which bits are actually writable */ + COMPLIANCE_WRITE(target, DMI_ABSTRACTAUTO, 0xFFFFFFFF); + uint32_t abstractauto; + uint32_t busy; + COMPLIANCE_READ(target, &abstractauto, DMI_ABSTRACTAUTO); + COMPLIANCE_WRITE(target, DMI_ABSTRACTAUTO, 0x0); + if (abstractauto > 0) { + /* This mechanism only works when you have a reasonable sized progbuf, which is not + a true compliance requirement. */ + if (info->progbufsize >= 3) { + + testvar = 0; + COMPLIANCE_TEST(ERROR_OK == register_write_direct(target, GDB_REGNO_S0, 0), + "Need to be able to write S0 to test ABSTRACTAUTO"); + struct riscv_program program; + COMPLIANCE_MUST_PASS(riscv_program_init(&program, target)); + /* This is also testing that WFI() is a NOP during debug mode. */ + COMPLIANCE_MUST_PASS(riscv_program_insert(&program, wfi())); + COMPLIANCE_MUST_PASS(riscv_program_addi(&program, GDB_REGNO_S0, GDB_REGNO_S0, 1)); + COMPLIANCE_MUST_PASS(riscv_program_ebreak(&program)); + COMPLIANCE_WRITE(target, DMI_ABSTRACTAUTO, 0x0); + COMPLIANCE_MUST_PASS(riscv_program_exec(&program, target)); + testvar++; + COMPLIANCE_WRITE(target, DMI_ABSTRACTAUTO, 0xFFFFFFFF); + COMPLIANCE_READ(target, &abstractauto, DMI_ABSTRACTAUTO); + uint32_t autoexec_data = get_field(abstractauto, DMI_ABSTRACTAUTO_AUTOEXECDATA); + uint32_t autoexec_progbuf = get_field(abstractauto, DMI_ABSTRACTAUTO_AUTOEXECPROGBUF); + for (unsigned int i = 0; i < 12; i++) { + COMPLIANCE_READ(target, &testvar_read, DMI_DATA0 + i); + do { + COMPLIANCE_READ(target, &testvar_read, DMI_ABSTRACTCS); + busy = get_field(testvar_read, DMI_ABSTRACTCS_BUSY); + } while (busy); + if (autoexec_data & (1 << i)) { + COMPLIANCE_TEST(i < get_field(abstractcs, DMI_ABSTRACTCS_DATACOUNT), + "AUTOEXEC may be writable up to DATACOUNT bits."); + testvar++; + } + } + for (unsigned int i = 0; i < 16; i++) { + COMPLIANCE_READ(target, &testvar_read, DMI_PROGBUF0 + i); + do { + COMPLIANCE_READ(target, &testvar_read, DMI_ABSTRACTCS); + busy = get_field(testvar_read, DMI_ABSTRACTCS_BUSY); + } while (busy); + if (autoexec_progbuf & (1 << i)) { + COMPLIANCE_TEST(i < get_field(abstractcs, DMI_ABSTRACTCS_PROGBUFSIZE), + "AUTOEXEC may be writable up to PROGBUFSIZE bits."); + testvar++; + } + } + + COMPLIANCE_WRITE(target, DMI_ABSTRACTAUTO, 0); + COMPLIANCE_TEST(ERROR_OK == register_read_direct(target, &value, GDB_REGNO_S0), + "Need to be able to read S0 to test ABSTRACTAUTO"); + + COMPLIANCE_TEST(testvar == value, + "ABSTRACTAUTO should cause COMMAND to run the expected number of times."); + } + } + + /* Single-Step each hart. */ + for (int hartsel = 0; hartsel < riscv_count_harts(target); hartsel++) { + COMPLIANCE_MUST_PASS(riscv_set_current_hartid(target, hartsel)); + COMPLIANCE_MUST_PASS(riscv013_on_step(target)); + COMPLIANCE_MUST_PASS(riscv013_step_current_hart(target)); + COMPLIANCE_TEST(riscv_halt_reason(target, hartsel) == RISCV_HALT_SINGLESTEP, + "Single Step should result in SINGLESTEP"); + } + + /* Core Register Tests */ + uint64_t bogus_dpc = 0xdeadbeef; + for (int hartsel = 0; hartsel < riscv_count_harts(target); hartsel++) { + COMPLIANCE_MUST_PASS(riscv_set_current_hartid(target, hartsel)); + + /* DCSR Tests */ + COMPLIANCE_MUST_PASS(register_write_direct(target, GDB_REGNO_DCSR, 0x0)); + COMPLIANCE_MUST_PASS(register_read_direct(target, &value, GDB_REGNO_DCSR)); + COMPLIANCE_TEST(value != 0, "Not all bits in DCSR are writable by Debugger"); + COMPLIANCE_MUST_PASS(register_write_direct(target, GDB_REGNO_DCSR, 0xFFFFFFFF)); + COMPLIANCE_MUST_PASS(register_read_direct(target, &value, GDB_REGNO_DCSR)); + COMPLIANCE_TEST(value != 0, "At least some bits in DCSR must be 1"); + + /* DPC. Note that DPC is sign-extended. */ + riscv_reg_t dpcmask = 0xFFFFFFFCUL; + riscv_reg_t dpc; + + if (riscv_xlen(target) > 32) + dpcmask |= (0xFFFFFFFFULL << 32); + + if (riscv_supports_extension(target, riscv_current_hartid(target), 'C')) + dpcmask |= 0x2; + + COMPLIANCE_MUST_PASS(register_write_direct(target, GDB_REGNO_DPC, dpcmask)); + COMPLIANCE_MUST_PASS(register_read_direct(target, &dpc, GDB_REGNO_DPC)); + COMPLIANCE_TEST(dpcmask == dpc, + "DPC must be sign-extended to XLEN and writable to all-1s (except the least significant bits)"); + COMPLIANCE_MUST_PASS(register_write_direct(target, GDB_REGNO_DPC, 0)); + COMPLIANCE_MUST_PASS(register_read_direct(target, &dpc, GDB_REGNO_DPC)); + COMPLIANCE_TEST(dpc == 0, "DPC must be writable to 0."); + if (hartsel == 0) + bogus_dpc = dpc; /* For a later test step */ + } + + /* NDMRESET + Asserting non-debug module reset should not reset Debug Module state. + But it should reset Hart State, e.g. DPC should get a different value. + Also make sure that DCSR reports cause of 'HALT' even though previously we single-stepped. + */ + + /* Write some registers. They should not be impacted by ndmreset. */ + COMPLIANCE_WRITE(target, DMI_COMMAND, 0xFFFFFFFF); + + for (unsigned int i = 0; i < get_field(abstractcs, DMI_ABSTRACTCS_PROGBUFSIZE); i++) { + testvar = (i + 1) * 0x11111111; + COMPLIANCE_WRITE(target, DMI_PROGBUF0 + i, testvar); + } + + for (unsigned int i = 0; i < get_field(abstractcs, DMI_ABSTRACTCS_DATACOUNT); i++) { + testvar = (i + 1) * 0x11111111; + COMPLIANCE_WRITE(target, DMI_DATA0 + i, testvar); + } + + COMPLIANCE_WRITE(target, DMI_ABSTRACTAUTO, 0xFFFFFFFF); + COMPLIANCE_READ(target, &abstractauto, DMI_ABSTRACTAUTO); + + /* Pulse reset. */ + target->reset_halt = true; + COMPLIANCE_MUST_PASS(riscv_set_current_hartid(target, 0)); + COMPLIANCE_TEST(ERROR_OK == assert_reset(target), "Must be able to assert NDMRESET"); + COMPLIANCE_TEST(ERROR_OK == deassert_reset(target), "Must be able to deassert NDMRESET"); + + /* Verify that most stuff is not affected by ndmreset. */ + COMPLIANCE_READ(target, &testvar_read, DMI_ABSTRACTCS); + COMPLIANCE_TEST(get_field(testvar_read, DMI_ABSTRACTCS_CMDERR) == CMDERR_NOT_SUPPORTED, + "NDMRESET should not affect DMI_ABSTRACTCS"); + COMPLIANCE_READ(target, &testvar_read, DMI_ABSTRACTAUTO); + COMPLIANCE_TEST(testvar_read == abstractauto, "NDMRESET should not affect DMI_ABSTRACTAUTO"); + + /* Clean up to avoid future test failures */ + COMPLIANCE_WRITE(target, DMI_ABSTRACTCS, DMI_ABSTRACTCS_CMDERR); + COMPLIANCE_WRITE(target, DMI_ABSTRACTAUTO, 0); + + for (unsigned int i = 0; i < get_field(abstractcs, DMI_ABSTRACTCS_PROGBUFSIZE); i++) { + testvar = (i + 1) * 0x11111111; + COMPLIANCE_READ(target, &testvar_read, DMI_PROGBUF0 + i); + COMPLIANCE_TEST(testvar_read == testvar, "PROGBUF words must not be affected by NDMRESET"); + } + + for (unsigned int i = 0; i < get_field(abstractcs, DMI_ABSTRACTCS_DATACOUNT); i++) { + testvar = (i + 1) * 0x11111111; + COMPLIANCE_READ(target, &testvar_read, DMI_DATA0 + i); + COMPLIANCE_TEST(testvar_read == testvar, "DATA words must not be affected by NDMRESET"); + } + + /* Verify that DPC *is* affected by ndmreset. Since we don't know what it *should* be, + just verify that at least it's not the bogus value anymore. */ + + COMPLIANCE_TEST(bogus_dpc != 0xdeadbeef, "BOGUS DPC should have been set somehow (bug in compliance test)"); + COMPLIANCE_MUST_PASS(register_read_direct(target, &value, GDB_REGNO_DPC)); + COMPLIANCE_TEST(bogus_dpc != value, "NDMRESET should move DPC to reset value."); + + COMPLIANCE_TEST(riscv_halt_reason(target, 0) == RISCV_HALT_INTERRUPT, + "After NDMRESET halt, DCSR should report cause of halt"); + + /* DMACTIVE -- deasserting DMACTIVE should reset all the above values. */ + + /* Toggle dmactive */ + COMPLIANCE_WRITE(target, DMI_DMCONTROL, 0); + COMPLIANCE_WRITE(target, DMI_DMCONTROL, DMI_DMCONTROL_DMACTIVE); + COMPLIANCE_READ(target, &testvar_read, DMI_ABSTRACTCS); + COMPLIANCE_TEST(get_field(testvar_read, DMI_ABSTRACTCS_CMDERR) == 0, "ABSTRACTCS.cmderr should reset to 0"); + COMPLIANCE_READ(target, &testvar_read, DMI_ABSTRACTAUTO); + COMPLIANCE_TEST(testvar_read == 0, "ABSTRACTAUTO should reset to 0"); + + for (unsigned int i = 0; i < get_field(abstractcs, DMI_ABSTRACTCS_PROGBUFSIZE); i++) { + COMPLIANCE_READ(target, &testvar_read, DMI_PROGBUF0 + i); + COMPLIANCE_TEST(testvar_read == 0, "PROGBUF words should reset to 0"); + } + + for (unsigned int i = 0; i < get_field(abstractcs, DMI_ABSTRACTCS_DATACOUNT); i++) { + COMPLIANCE_READ(target, &testvar_read, DMI_DATA0 + i); + COMPLIANCE_TEST(testvar_read == 0, "DATA words should reset to 0"); + } + + /* + * TODO: + * DCSR.cause priorities + * DCSR.stoptime/stopcycle + * DCSR.stepie + * DCSR.ebreak + * DCSR.prv + */ + + /* Halt every hart for any follow-up tests*/ + COMPLIANCE_MUST_PASS(riscv_halt_all_harts(target)); + + uint32_t failed_tests = total_tests - passed_tests; + if (total_tests == passed_tests) { + LOG_INFO("ALL TESTS PASSED\n"); + return ERROR_OK; + } else { + LOG_INFO("%d TESTS FAILED\n", failed_tests); + return ERROR_FAIL; + } +} diff --git a/src/target/riscv/riscv.c b/src/target/riscv/riscv.c index 9a6b9389a..7bae39034 100644 --- a/src/target/riscv/riscv.c +++ b/src/target/riscv/riscv.c @@ -154,17 +154,17 @@ typedef enum slot { #define MAX_HWBPS 16 #define DRAM_CACHE_SIZE 16 -uint8_t ir_dtmcontrol[1] = {DTMCONTROL}; +uint8_t ir_dtmcontrol[4] = {DTMCONTROL}; struct scan_field select_dtmcontrol = { .in_value = NULL, .out_value = ir_dtmcontrol }; -uint8_t ir_dbus[1] = {DBUS}; +uint8_t ir_dbus[4] = {DBUS}; struct scan_field select_dbus = { .in_value = NULL, .out_value = ir_dbus }; -uint8_t ir_idcode[1] = {0x1}; +uint8_t ir_idcode[4] = {0x1}; struct scan_field select_idcode = { .in_value = NULL, .out_value = ir_idcode @@ -187,13 +187,17 @@ int riscv_reset_timeout_sec = DEFAULT_RESET_TIMEOUT_SEC; bool riscv_prefer_sba; +typedef struct { + uint16_t low, high; +} range_t; + /* In addition to the ones in the standard spec, we'll also expose additional * CSRs in this list. * The list is either NULL, or a series of ranges (inclusive), terminated with * 1,0. */ -struct { - uint16_t low, high; -} *expose_csr; +range_t *expose_csr; +/* Same, but for custom registers. */ +range_t *expose_custom; static uint32_t dtmcontrol_scan(struct target *target, uint32_t out) { @@ -262,6 +266,8 @@ static int riscv_init_target(struct command_context *cmd_ctx, riscv_semihosting_init(target); + target->debug_reason = DBG_REASON_DBGRQ; + return ERROR_OK; } @@ -272,8 +278,21 @@ static void riscv_deinit_target(struct target *target) if (tt) { tt->deinit_target(target); riscv_info_t *info = (riscv_info_t *) target->arch_info; + free(info->reg_names); free(info); } + /* Free the shared structure use for most registers. */ + if (target->reg_cache) { + if (target->reg_cache->reg_list) { + if (target->reg_cache->reg_list[0].arch_info) + free(target->reg_cache->reg_list[0].arch_info); + /* Free the ones we allocated separately. */ + for (unsigned i = GDB_REGNO_COUNT; i < target->reg_cache->num_regs; i++) + free(target->reg_cache->reg_list[i].arch_info); + free(target->reg_cache->reg_list); + } + free(target->reg_cache); + } target->arch_info = NULL; } @@ -470,8 +489,8 @@ static int add_trigger(struct target *target, struct trigger *trigger) if (result != ERROR_OK) continue; - LOG_DEBUG("Using trigger %d (type %d) for bp %d", i, type, - trigger->unique_id); + LOG_DEBUG("[%d] Using trigger %d (type %d) for bp %d", target->coreid, + i, type, trigger->unique_id); r->trigger_unique_id[i] = trigger->unique_id; break; } @@ -493,19 +512,31 @@ static int add_trigger(struct target *target, struct trigger *trigger) int riscv_add_breakpoint(struct target *target, struct breakpoint *breakpoint) { + LOG_DEBUG("[%d] @0x%" TARGET_PRIxADDR, target->coreid, breakpoint->address); + assert(breakpoint); if (breakpoint->type == BKPT_SOFT) { - if (target_read_memory(target, breakpoint->address, breakpoint->length, 1, + /** @todo check RVC for size/alignment */ + if (!(breakpoint->length == 4 || breakpoint->length == 2)) { + LOG_ERROR("Invalid breakpoint length %d", breakpoint->length); + return ERROR_FAIL; + } + + if (0 != (breakpoint->address % 2)) { + LOG_ERROR("Invalid breakpoint alignment for address 0x%" TARGET_PRIxADDR, breakpoint->address); + return ERROR_FAIL; + } + + if (target_read_memory(target, breakpoint->address, 2, breakpoint->length / 2, breakpoint->orig_instr) != ERROR_OK) { LOG_ERROR("Failed to read original instruction at 0x%" TARGET_PRIxADDR, breakpoint->address); return ERROR_FAIL; } - int retval; - if (breakpoint->length == 4) - retval = target_write_u32(target, breakpoint->address, ebreak()); - else - retval = target_write_u16(target, breakpoint->address, ebreak_c()); + uint8_t buff[4]; + buf_set_u32(buff, 0, breakpoint->length * CHAR_BIT, breakpoint->length == 4 ? ebreak() : ebreak_c()); + int const retval = target_write_memory(target, breakpoint->address, 2, breakpoint->length / 2, buff); + if (retval != ERROR_OK) { LOG_ERROR("Failed to write %d-byte breakpoint instruction at 0x%" TARGET_PRIxADDR, breakpoint->length, breakpoint->address); @@ -515,17 +546,15 @@ int riscv_add_breakpoint(struct target *target, struct breakpoint *breakpoint) } else if (breakpoint->type == BKPT_HARD) { struct trigger trigger; trigger_from_breakpoint(&trigger, breakpoint); - int result = add_trigger(target, &trigger); + int const result = add_trigger(target, &trigger); if (result != ERROR_OK) return result; - } else { LOG_INFO("OpenOCD only supports hardware and software breakpoints."); return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; } breakpoint->set = true; - return ERROR_OK; } @@ -557,7 +586,8 @@ static int remove_trigger(struct target *target, struct trigger *trigger) "trigger."); return ERROR_FAIL; } - LOG_DEBUG("Stop using resource %d for bp %d", i, trigger->unique_id); + LOG_DEBUG("[%d] Stop using resource %d for bp %d", target->coreid, i, + trigger->unique_id); for (int hartid = first_hart; hartid < riscv_count_harts(target); ++hartid) { if (!riscv_hart_enabled(target, hartid)) continue; @@ -578,7 +608,7 @@ int riscv_remove_breakpoint(struct target *target, struct breakpoint *breakpoint) { if (breakpoint->type == BKPT_SOFT) { - if (target_write_memory(target, breakpoint->address, breakpoint->length, 1, + if (target_write_memory(target, breakpoint->address, 2, breakpoint->length / 2, breakpoint->orig_instr) != ERROR_OK) { LOG_ERROR("Failed to restore instruction for %d-byte breakpoint at " "0x%" TARGET_PRIxADDR, breakpoint->length, breakpoint->address); @@ -632,6 +662,8 @@ int riscv_add_watchpoint(struct target *target, struct watchpoint *watchpoint) int riscv_remove_watchpoint(struct target *target, struct watchpoint *watchpoint) { + LOG_DEBUG("[%d] @0x%" TARGET_PRIxADDR, target->coreid, watchpoint->address); + struct trigger trigger; trigger_from_watchpoint(&trigger, watchpoint); @@ -643,6 +675,89 @@ int riscv_remove_watchpoint(struct target *target, return ERROR_OK; } +/* Sets *hit_watchpoint to the first watchpoint identified as causing the + * current halt. + * + * The GDB server uses this information to tell GDB what data address has + * been hit, which enables GDB to print the hit variable along with its old + * and new value. */ +int riscv_hit_watchpoint(struct target *target, struct watchpoint **hit_watchpoint) +{ + struct watchpoint *wp = target->watchpoints; + + LOG_DEBUG("Current hartid = %d", riscv_current_hartid(target)); + + /*TODO instead of disassembling the instruction that we think caused the + * trigger, check the hit bit of each watchpoint first. The hit bit is + * simpler and more reliable to check but as it is optional and relatively + * new, not all hardware will implement it */ + riscv_reg_t dpc; + riscv_get_register(target, &dpc, GDB_REGNO_DPC); + const uint8_t length = 4; + LOG_DEBUG("dpc is 0x%" PRIx64, dpc); + + /* fetch the instruction at dpc */ + uint8_t buffer[length]; + if (target_read_buffer(target, dpc, length, buffer) != ERROR_OK) { + LOG_ERROR("Failed to read instruction at dpc 0x%" PRIx64, dpc); + return ERROR_FAIL; + } + + uint32_t instruction = 0; + + for (int i = 0; i < length; i++) { + LOG_DEBUG("Next byte is %x", buffer[i]); + instruction += (buffer[i] << 8 * i); + } + LOG_DEBUG("Full instruction is %x", instruction); + + /* find out which memory address is accessed by the instruction at dpc */ + /* opcode is first 7 bits of the instruction */ + uint8_t opcode = instruction & 0x7F; + uint32_t rs1; + int16_t imm; + riscv_reg_t mem_addr; + + if (opcode == MATCH_LB || opcode == MATCH_SB) { + rs1 = (instruction & 0xf8000) >> 15; + riscv_get_register(target, &mem_addr, rs1); + + if (opcode == MATCH_SB) { + LOG_DEBUG("%x is store instruction", instruction); + imm = ((instruction & 0xf80) >> 7) | ((instruction & 0xfe000000) >> 20); + } else { + LOG_DEBUG("%x is load instruction", instruction); + imm = (instruction & 0xfff00000) >> 20; + } + /* sign extend 12-bit imm to 16-bits */ + if (imm & (1 << 11)) + imm |= 0xf000; + mem_addr += imm; + LOG_DEBUG("memory address=0x%" PRIx64, mem_addr); + } else { + LOG_DEBUG("%x is not a RV32I load or store", instruction); + return ERROR_FAIL; + } + + while (wp) { + /*TODO support length/mask */ + if (wp->address == mem_addr) { + *hit_watchpoint = wp; + LOG_DEBUG("Hit address=%" TARGET_PRIxADDR, wp->address); + return ERROR_OK; + } + wp = wp->next; + } + + /* No match found - either we hit a watchpoint caused by an instruction that + * this function does not yet disassemble, or we hit a breakpoint. + * + * OpenOCD will behave as if this function had never been implemented i.e. + * report the halt to GDB with no address information. */ + return ERROR_FAIL; +} + + static int oldriscv_step(struct target *target, int current, uint32_t address, int handle_breakpoints) { @@ -718,13 +833,15 @@ static int old_or_new_riscv_halt(struct target *target) static int riscv_assert_reset(struct target *target) { + LOG_DEBUG("[%d]", target->coreid); struct target_type *tt = get_target_type(target); + riscv_invalidate_register_cache(target); return tt->assert_reset(target); } static int riscv_deassert_reset(struct target *target) { - LOG_DEBUG("RISCV DEASSERT RESET"); + LOG_DEBUG("[%d]", target->coreid); struct target_type *tt = get_target_type(target); return tt->deassert_reset(target); } @@ -745,8 +862,28 @@ static int old_or_new_riscv_resume( int handle_breakpoints, int debug_execution ){ - RISCV_INFO(r); LOG_DEBUG("handle_breakpoints=%d", handle_breakpoints); + if (target->smp) { + struct target_list *targets = target->head; + int result = ERROR_OK; + while (targets) { + struct target *t = targets->target; + riscv_info_t *r = riscv_info(t); + if (r->is_halted == NULL) { + if (oldriscv_resume(t, current, address, handle_breakpoints, + debug_execution) != ERROR_OK) + result = ERROR_FAIL; + } else { + if (riscv_openocd_resume(t, current, address, + handle_breakpoints, debug_execution) != ERROR_OK) + result = ERROR_FAIL; + } + targets = targets->next; + } + return result; + } + + RISCV_INFO(r); if (r->is_halted == NULL) return oldriscv_resume(target, current, address, handle_breakpoints, debug_execution); else @@ -756,9 +893,11 @@ static int old_or_new_riscv_resume( static int riscv_select_current_hart(struct target *target) { RISCV_INFO(r); - if (r->rtos_hartid != -1 && riscv_rtos_enabled(target)) + if (riscv_rtos_enabled(target)) { + if (r->rtos_hartid == -1) + r->rtos_hartid = target->rtos->current_threadid - 1; return riscv_set_current_hartid(target, r->rtos_hartid); - else + } else return riscv_set_current_hartid(target, target->coreid); } @@ -780,13 +919,13 @@ static int riscv_write_memory(struct target *target, target_addr_t address, return tt->write_memory(target, address, size, count, buffer); } -static int riscv_get_gdb_reg_list(struct target *target, +static int riscv_get_gdb_reg_list_internal(struct target *target, struct reg **reg_list[], int *reg_list_size, - enum target_register_class reg_class) + enum target_register_class reg_class, bool read) { RISCV_INFO(r); - LOG_DEBUG("reg_class=%d", reg_class); - LOG_DEBUG("rtos_hartid=%d current_hartid=%d", r->rtos_hartid, r->current_hartid); + LOG_DEBUG("rtos_hartid=%d, current_hartid=%d, reg_class=%d, read=%d", + r->rtos_hartid, r->current_hartid, reg_class, read); if (!target->reg_cache) { LOG_ERROR("Target not initialized. Return ERROR_FAIL."); @@ -798,10 +937,10 @@ static int riscv_get_gdb_reg_list(struct target *target, switch (reg_class) { case REG_CLASS_GENERAL: - *reg_list_size = 32; + *reg_list_size = 33; break; case REG_CLASS_ALL: - *reg_list_size = GDB_REGNO_COUNT; + *reg_list_size = target->reg_cache->num_regs; break; default: LOG_ERROR("Unsupported reg_class: %d", reg_class); @@ -816,11 +955,28 @@ static int riscv_get_gdb_reg_list(struct target *target, assert(!target->reg_cache->reg_list[i].valid || target->reg_cache->reg_list[i].size > 0); (*reg_list)[i] = &target->reg_cache->reg_list[i]; + if (read && !target->reg_cache->reg_list[i].valid) { + if (target->reg_cache->reg_list[i].type->get( + &target->reg_cache->reg_list[i]) != ERROR_OK) + /* This function is called when first connecting to gdb, + * resulting in an attempt to read all kinds of registers which + * probably will fail. Ignore these failures, and when + * encountered stop reading to save time. */ + read = false; + } } return ERROR_OK; } +static int riscv_get_gdb_reg_list(struct target *target, + struct reg **reg_list[], int *reg_list_size, + enum target_register_class reg_class) +{ + return riscv_get_gdb_reg_list_internal(target, reg_list, reg_list_size, + reg_class, true); +} + static int riscv_arch_state(struct target *target) { struct target_type *tt = get_target_type(target); @@ -853,7 +1009,7 @@ static int riscv_run_algorithm(struct target *target, int num_mem_params, uint64_t saved_regs[32]; for (int i = 0; i < num_reg_params; i++) { - if (mem_params[i].direction == PARAM_IN) + if (reg_params[i].direction == PARAM_IN) continue; LOG_DEBUG("save %s", reg_params[i].reg_name); @@ -1000,6 +1156,30 @@ static enum riscv_poll_hart riscv_poll_hart(struct target *target, int hartid) return RPH_NO_CHANGE; } +int set_debug_reason(struct target *target, int hartid) +{ + switch (riscv_halt_reason(target, hartid)) { + case RISCV_HALT_BREAKPOINT: + target->debug_reason = DBG_REASON_BREAKPOINT; + break; + case RISCV_HALT_TRIGGER: + target->debug_reason = DBG_REASON_WATCHPOINT; + break; + case RISCV_HALT_INTERRUPT: + target->debug_reason = DBG_REASON_DBGRQ; + break; + case RISCV_HALT_SINGLESTEP: + target->debug_reason = DBG_REASON_SINGLESTEP; + break; + case RISCV_HALT_UNKNOWN: + target->debug_reason = DBG_REASON_UNDEFINED; + break; + case RISCV_HALT_ERROR: + return ERROR_FAIL; + } + return ERROR_OK; +} + /*** OpenOCD Interface ***/ int riscv_openocd_poll(struct target *target) { @@ -1034,6 +1214,64 @@ int riscv_openocd_poll(struct target *target) * harts. */ for (int i = 0; i < riscv_count_harts(target); ++i) riscv_halt_one_hart(target, i); + + } else if (target->smp) { + bool halt_discovered = false; + bool newly_halted[128] = {0}; + unsigned i = 0; + for (struct target_list *list = target->head; list != NULL; + list = list->next, i++) { + struct target *t = list->target; + riscv_info_t *r = riscv_info(t); + assert(i < DIM(newly_halted)); + enum riscv_poll_hart out = riscv_poll_hart(t, r->current_hartid); + switch (out) { + case RPH_NO_CHANGE: + break; + case RPH_DISCOVERED_RUNNING: + t->state = TARGET_RUNNING; + break; + case RPH_DISCOVERED_HALTED: + halt_discovered = true; + newly_halted[i] = true; + t->state = TARGET_HALTED; + if (set_debug_reason(t, r->current_hartid) != ERROR_OK) + return ERROR_FAIL; + break; + case RPH_ERROR: + return ERROR_FAIL; + } + } + + if (halt_discovered) { + LOG_DEBUG("Halt other targets in this SMP group."); + i = 0; + for (struct target_list *list = target->head; list != NULL; + list = list->next, i++) { + struct target *t = list->target; + riscv_info_t *r = riscv_info(t); + if (t->state != TARGET_HALTED) { + if (riscv_halt_one_hart(t, r->current_hartid) != ERROR_OK) + return ERROR_FAIL; + t->state = TARGET_HALTED; + if (set_debug_reason(t, r->current_hartid) != ERROR_OK) + return ERROR_FAIL; + newly_halted[i] = true; + } + } + + /* Now that we have all our ducks in a row, tell the higher layers + * what just happened. */ + i = 0; + for (struct target_list *list = target->head; list != NULL; + list = list->next, i++) { + struct target *t = list->target; + if (newly_halted[i]) + target_call_event_callbacks(t, TARGET_EVENT_HALTED); + } + } + return ERROR_OK; + } else { enum riscv_poll_hart out = riscv_poll_hart(target, riscv_current_hartid(target)); @@ -1047,29 +1285,13 @@ int riscv_openocd_poll(struct target *target) } target->state = TARGET_HALTED; - switch (riscv_halt_reason(target, halted_hart)) { - case RISCV_HALT_BREAKPOINT: - target->debug_reason = DBG_REASON_BREAKPOINT; - break; - case RISCV_HALT_TRIGGER: - target->debug_reason = DBG_REASON_WATCHPOINT; - break; - case RISCV_HALT_INTERRUPT: - target->debug_reason = DBG_REASON_DBGRQ; - break; - case RISCV_HALT_SINGLESTEP: - target->debug_reason = DBG_REASON_SINGLESTEP; - break; - case RISCV_HALT_UNKNOWN: - target->debug_reason = DBG_REASON_UNDEFINED; - break; - case RISCV_HALT_ERROR: + if (set_debug_reason(target, halted_hart) != ERROR_OK) return ERROR_FAIL; - } if (riscv_rtos_enabled(target)) { target->rtos->current_threadid = halted_hart + 1; target->rtos->current_thread = halted_hart + 1; + riscv_set_rtos_hartid(target, halted_hart); } target->state = TARGET_HALTED; @@ -1087,25 +1309,39 @@ int riscv_openocd_poll(struct target *target) int riscv_openocd_halt(struct target *target) { RISCV_INFO(r); + int result; - LOG_DEBUG("halting all harts"); + LOG_DEBUG("[%d] halting all harts", target->coreid); - int out = riscv_halt_all_harts(target); - if (out != ERROR_OK) { - LOG_ERROR("Unable to halt all harts"); - return out; + if (target->smp) { + LOG_DEBUG("Halt other targets in this SMP group."); + struct target_list *targets = target->head; + result = ERROR_OK; + while (targets) { + struct target *t = targets->target; + targets = targets->next; + if (t->state != TARGET_HALTED) { + if (riscv_halt_all_harts(t) != ERROR_OK) + result = ERROR_FAIL; + } + } + } else { + result = riscv_halt_all_harts(target); } - register_cache_invalidate(target->reg_cache); if (riscv_rtos_enabled(target)) { - target->rtos->current_threadid = r->rtos_hartid + 1; - target->rtos->current_thread = r->rtos_hartid + 1; + if (r->rtos_hartid != -1) { + LOG_DEBUG("halt requested on RTOS hartid %d", r->rtos_hartid); + target->rtos->current_threadid = r->rtos_hartid + 1; + target->rtos->current_thread = r->rtos_hartid + 1; + } else + LOG_DEBUG("halt requested, but no known RTOS hartid"); } target->state = TARGET_HALTED; target->debug_reason = DBG_REASON_DBGRQ; target_call_event_callbacks(target, TARGET_EVENT_HALTED); - return out; + return result; } int riscv_openocd_resume( @@ -1230,6 +1466,25 @@ COMMAND_HANDLER(riscv_set_reset_timeout_sec) return ERROR_OK; } +COMMAND_HANDLER(riscv_test_compliance) { + + struct target *target = get_current_target(CMD_CTX); + + RISCV_INFO(r); + + if (CMD_ARGC > 0) { + LOG_ERROR("Command does not take any parameters."); + return ERROR_COMMAND_SYNTAX_ERROR; + } + + if (r->test_compliance) { + return r->test_compliance(target); + } else { + LOG_ERROR("This target does not support this command (may implement an older version of the spec)."); + return ERROR_FAIL; + } +} + COMMAND_HANDLER(riscv_set_prefer_sba) { if (CMD_ARGC != 1) { @@ -1253,20 +1508,15 @@ void parse_error(const char *string, char c, unsigned position) LOG_ERROR("%s", buf); } -COMMAND_HANDLER(riscv_set_expose_csrs) +int parse_ranges(range_t **ranges, const char **argv) { - if (CMD_ARGC != 1) { - LOG_ERROR("Command takes exactly 1 parameter"); - return ERROR_COMMAND_SYNTAX_ERROR; - } - for (unsigned pass = 0; pass < 2; pass++) { unsigned range = 0; unsigned low = 0; bool parse_low = true; unsigned high = 0; - for (unsigned i = 0; i == 0 || CMD_ARGV[0][i-1]; i++) { - char c = CMD_ARGV[0][i]; + for (unsigned i = 0; i == 0 || argv[0][i-1]; i++) { + char c = argv[0][i]; if (isspace(c)) { /* Ignore whitespace. */ continue; @@ -1280,13 +1530,13 @@ COMMAND_HANDLER(riscv_set_expose_csrs) parse_low = false; } else if (c == ',' || c == 0) { if (pass == 1) { - expose_csr[range].low = low; - expose_csr[range].high = low; + (*ranges)[range].low = low; + (*ranges)[range].high = low; } low = 0; range++; } else { - parse_error(CMD_ARGV[0], c, i); + parse_error(argv[0], c, i); return ERROR_COMMAND_SYNTAX_ERROR; } @@ -1297,31 +1547,52 @@ COMMAND_HANDLER(riscv_set_expose_csrs) } else if (c == ',' || c == 0) { parse_low = true; if (pass == 1) { - expose_csr[range].low = low; - expose_csr[range].high = high; + (*ranges)[range].low = low; + (*ranges)[range].high = high; } low = 0; high = 0; range++; } else { - parse_error(CMD_ARGV[0], c, i); + parse_error(argv[0], c, i); return ERROR_COMMAND_SYNTAX_ERROR; } } } if (pass == 0) { - if (expose_csr) - free(expose_csr); - expose_csr = calloc(range + 2, sizeof(*expose_csr)); + if (*ranges) + free(*ranges); + *ranges = calloc(range + 2, sizeof(range_t)); } else { - expose_csr[range].low = 1; - expose_csr[range].high = 0; + (*ranges)[range].low = 1; + (*ranges)[range].high = 0; } } + return ERROR_OK; } +COMMAND_HANDLER(riscv_set_expose_csrs) +{ + if (CMD_ARGC != 1) { + LOG_ERROR("Command takes exactly 1 parameter"); + return ERROR_COMMAND_SYNTAX_ERROR; + } + + return parse_ranges(&expose_csr, CMD_ARGV); +} + +COMMAND_HANDLER(riscv_set_expose_custom) +{ + if (CMD_ARGC != 1) { + LOG_ERROR("Command takes exactly 1 parameter"); + return ERROR_COMMAND_SYNTAX_ERROR; + } + + return parse_ranges(&expose_custom, CMD_ARGV); +} + COMMAND_HANDLER(riscv_authdata_read) { if (CMD_ARGC != 0) { @@ -1429,7 +1700,85 @@ COMMAND_HANDLER(riscv_dmi_write) } } +COMMAND_HANDLER(riscv_test_sba_config_reg) +{ + if (CMD_ARGC != 4) { + LOG_ERROR("Command takes exactly 4 arguments"); + return ERROR_COMMAND_SYNTAX_ERROR; + } + + struct target *target = get_current_target(CMD_CTX); + RISCV_INFO(r); + + target_addr_t legal_address; + uint32_t num_words; + target_addr_t illegal_address; + bool run_sbbusyerror_test; + + COMMAND_PARSE_NUMBER(target_addr, CMD_ARGV[0], legal_address); + COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], num_words); + COMMAND_PARSE_NUMBER(target_addr, CMD_ARGV[2], illegal_address); + COMMAND_PARSE_ON_OFF(CMD_ARGV[3], run_sbbusyerror_test); + + if (r->test_sba_config_reg) { + return r->test_sba_config_reg(target, legal_address, num_words, + illegal_address, run_sbbusyerror_test); + } else { + LOG_ERROR("test_sba_config_reg is not implemented for this target."); + return ERROR_FAIL; + } +} + +COMMAND_HANDLER(riscv_reset_delays) +{ + int wait = 0; + + if (CMD_ARGC > 1) { + LOG_ERROR("Command takes at most one argument"); + return ERROR_COMMAND_SYNTAX_ERROR; + } + + if (CMD_ARGC == 1) + COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], wait); + + struct target *target = get_current_target(CMD_CTX); + RISCV_INFO(r); + r->reset_delays_wait = wait; + return ERROR_OK; +} + +COMMAND_HANDLER(riscv_set_ir) +{ + if (CMD_ARGC != 2) { + LOG_ERROR("Command takes exactly 2 arguments"); + return ERROR_COMMAND_SYNTAX_ERROR; + } + + uint32_t value; + COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], value); + + if (!strcmp(CMD_ARGV[0], "idcode")) { + buf_set_u32(ir_idcode, 0, 32, value); + return ERROR_OK; + } else if (!strcmp(CMD_ARGV[0], "dtmcs")) { + buf_set_u32(ir_dtmcontrol, 0, 32, value); + return ERROR_OK; + } else if (!strcmp(CMD_ARGV[0], "dmi")) { + buf_set_u32(ir_dbus, 0, 32, value); + return ERROR_OK; + } else { + return ERROR_FAIL; + } +} + static const struct command_registration riscv_exec_command_handlers[] = { + { + .name = "test_compliance", + .handler = riscv_test_compliance, + .mode = COMMAND_EXEC, + .usage = "riscv test_compliance", + .help = "Runs a basic compliance test suite against the RISC-V Debug Spec." + }, { .name = "set_command_timeout_sec", .handler = riscv_set_command_timeout_sec, @@ -1461,6 +1810,15 @@ static const struct command_registration riscv_exec_command_handlers[] = { "addition to the standard ones. This must be executed before " "`init`." }, + { + .name = "expose_custom", + .handler = riscv_set_expose_custom, + .mode = COMMAND_ANY, + .usage = "riscv expose_custom n0[-m0][,n1[-m1]]...", + .help = "Configure a list of inclusive ranges for custom registers to " + "expose. custom0 is accessed as abstract register number 0xc000, " + "etc. This must be executed before `init`." + }, { .name = "authdata_read", .handler = riscv_authdata_read, @@ -1489,6 +1847,36 @@ static const struct command_registration riscv_exec_command_handlers[] = { .usage = "riscv dmi_write address value", .help = "Perform a 32-bit DMI write of value at address." }, + { + .name = "test_sba_config_reg", + .handler = riscv_test_sba_config_reg, + .mode = COMMAND_ANY, + .usage = "riscv test_sba_config_reg legal_address num_words" + "illegal_address run_sbbusyerror_test[on/off]", + .help = "Perform a series of tests on the SBCS register." + "Inputs are a legal, 128-byte aligned address and a number of words to" + "read/write starting at that address (i.e., address range [legal address," + "legal_address+word_size*num_words) must be legally readable/writable)" + ", an illegal, 128-byte aligned address for error flag/handling cases," + "and whether sbbusyerror test should be run." + }, + { + .name = "reset_delays", + .handler = riscv_reset_delays, + .mode = COMMAND_ANY, + .usage = "reset_delays [wait]", + .help = "OpenOCD learns how many Run-Test/Idle cycles are required " + "between scans to avoid encountering the target being busy. This " + "command resets those learned values after `wait` scans. It's only " + "useful for testing OpenOCD itself." + }, + { + .name = "set_ir", + .handler = riscv_set_ir, + .mode = COMMAND_ANY, + .usage = "riscv set_ir_idcode [idcode|dtmcs|dmi] value", + .help = "Set IR value for specified JTAG register." + }, COMMAND_REGISTRATION_DONE }; @@ -1594,6 +1982,7 @@ struct target_type riscv_target = { .add_watchpoint = riscv_add_watchpoint, .remove_watchpoint = riscv_remove_watchpoint, + .hit_watchpoint = riscv_hit_watchpoint, .arch_state = riscv_arch_state, @@ -1632,6 +2021,8 @@ int riscv_halt_all_harts(struct target *target) riscv_halt_one_hart(target, i); } + riscv_invalidate_register_cache(target); + return ERROR_OK; } @@ -1646,7 +2037,9 @@ int riscv_halt_one_hart(struct target *target, int hartid) return ERROR_OK; } - return r->halt_current_hart(target); + int result = r->halt_current_hart(target); + register_cache_invalidate(target->reg_cache); + return result; } int riscv_resume_all_harts(struct target *target) @@ -1684,7 +2077,7 @@ int riscv_step_rtos_hart(struct target *target) if (riscv_rtos_enabled(target)) { hartid = r->rtos_hartid; if (hartid == -1) { - LOG_USER("GDB has asked me to step \"any\" thread, so I'm stepping hart 0."); + LOG_DEBUG("GDB has asked me to step \"any\" thread, so I'm stepping hart 0."); hartid = 0; } } @@ -1734,9 +2127,10 @@ int riscv_xlen_of_hart(const struct target *target, int hartid) return r->xlen[hartid]; } +extern struct rtos_type riscv_rtos; bool riscv_rtos_enabled(const struct target *target) { - return target->rtos != NULL; + return false; } int riscv_set_current_hartid(struct target *target, int hartid) @@ -1754,19 +2148,9 @@ int riscv_set_current_hartid(struct target *target, int hartid) /* This might get called during init, in which case we shouldn't be * setting up the register cache. */ - if (!target_was_examined(target)) - return ERROR_OK; + if (target_was_examined(target) && riscv_rtos_enabled(target)) + riscv_invalidate_register_cache(target); - /* Avoid invalidating the register cache all the time. */ - if (r->registers_initialized - && (!riscv_rtos_enabled(target) || (previous_hartid == hartid)) - && target->reg_cache->reg_list[GDB_REGNO_ZERO].size == (unsigned)riscv_xlen(target) - && (!riscv_rtos_enabled(target) || (r->rtos_hartid != -1))) { - return ERROR_OK; - } else - LOG_DEBUG("Initializing registers: xlen=%d", riscv_xlen(target)); - - riscv_invalidate_register_cache(target); return ERROR_OK; } @@ -1774,8 +2158,9 @@ void riscv_invalidate_register_cache(struct target *target) { RISCV_INFO(r); + LOG_DEBUG("[%d]", target->coreid); register_cache_invalidate(target->reg_cache); - for (size_t i = 0; i < GDB_REGNO_COUNT; ++i) { + for (size_t i = 0; i < target->reg_cache->num_regs; ++i) { struct reg *reg = &target->reg_cache->reg_list[i]; reg->valid = false; } @@ -1830,7 +2215,7 @@ int riscv_set_register_on_hart(struct target *target, int hartid, enum gdb_regno regid, uint64_t value) { RISCV_INFO(r); - LOG_DEBUG("[%d] %s <- %" PRIx64, hartid, gdb_regno_name(regid), value); + LOG_DEBUG("{%d} %s <- %" PRIx64, hartid, gdb_regno_name(regid), value); assert(r->set_register); return r->set_register(target, hartid, regid, value); } @@ -1846,8 +2231,17 @@ int riscv_get_register_on_hart(struct target *target, riscv_reg_t *value, int hartid, enum gdb_regno regid) { RISCV_INFO(r); + + struct reg *reg = &target->reg_cache->reg_list[regid]; + + if (reg && reg->valid && hartid == riscv_current_hartid(target)) { + *value = buf_get_u64(reg->value, 0, reg->size); + return ERROR_OK; + } + int result = r->get_register(target, value, hartid, regid); - LOG_DEBUG("[%d] %s: %" PRIx64, hartid, gdb_regno_name(regid), *value); + + LOG_DEBUG("{%d} %s: %" PRIx64, hartid, gdb_regno_name(regid), *value); return result; } @@ -2048,24 +2442,42 @@ const char *gdb_regno_name(enum gdb_regno regno) static int register_get(struct reg *reg) { - struct target *target = (struct target *) reg->arch_info; + riscv_reg_info_t *reg_info = reg->arch_info; + struct target *target = reg_info->target; uint64_t value; int result = riscv_get_register(target, &value, reg->number); if (result != ERROR_OK) return result; buf_set_u64(reg->value, 0, reg->size, value); + /* CSRs (and possibly other extension) registers may change value at any + * time. */ + if (reg->number <= GDB_REGNO_XPR31 || + (reg->number >= GDB_REGNO_FPR0 && reg->number <= GDB_REGNO_FPR31) || + reg->number == GDB_REGNO_PC) + reg->valid = true; + LOG_DEBUG("[%d]{%d} read 0x%" PRIx64 " from %s (valid=%d)", + target->coreid, riscv_current_hartid(target), value, reg->name, + reg->valid); return ERROR_OK; } static int register_set(struct reg *reg, uint8_t *buf) { - struct target *target = (struct target *) reg->arch_info; + riscv_reg_info_t *reg_info = reg->arch_info; + struct target *target = reg_info->target; uint64_t value = buf_get_u64(buf, 0, reg->size); - LOG_DEBUG("write 0x%" PRIx64 " to %s", value, reg->name); + LOG_DEBUG("[%d]{%d} write 0x%" PRIx64 " to %s (valid=%d)", + target->coreid, riscv_current_hartid(target), value, reg->name, + reg->valid); struct reg *r = &target->reg_cache->reg_list[reg->number]; - r->valid = true; + /* CSRs (and possibly other extension) registers may change value at any + * time. */ + if (reg->number <= GDB_REGNO_XPR31 || + (reg->number >= GDB_REGNO_FPR0 && reg->number <= GDB_REGNO_FPR31) || + reg->number == GDB_REGNO_PC) + r->valid = true; memcpy(r->value, buf, (r->size + 7) / 8); riscv_set_register(target, reg->number, value); @@ -2101,12 +2513,26 @@ int riscv_init_registers(struct target *target) target->reg_cache->name = "RISC-V Registers"; target->reg_cache->num_regs = GDB_REGNO_COUNT; - target->reg_cache->reg_list = calloc(GDB_REGNO_COUNT, sizeof(struct reg)); + if (expose_custom) { + for (unsigned i = 0; expose_custom[i].low <= expose_custom[i].high; i++) { + for (unsigned number = expose_custom[i].low; + number <= expose_custom[i].high; + number++) + target->reg_cache->num_regs++; + } + } + + LOG_DEBUG("create register cache for %d registers", + target->reg_cache->num_regs); + + target->reg_cache->reg_list = + calloc(target->reg_cache->num_regs, sizeof(struct reg)); const unsigned int max_reg_name_len = 12; if (info->reg_names) free(info->reg_names); - info->reg_names = calloc(1, GDB_REGNO_COUNT * max_reg_name_len); + info->reg_names = + calloc(target->reg_cache->num_regs, max_reg_name_len); char *reg_name = info->reg_names; static struct reg_feature feature_cpu = { @@ -2121,6 +2547,9 @@ int riscv_init_registers(struct target *target) static struct reg_feature feature_virtual = { .name = "org.gnu.gdb.riscv.virtual" }; + static struct reg_feature feature_custom = { + .name = "org.gnu.gdb.riscv.custom" + }; static struct reg_data_type type_ieee_single = { .type = REG_TYPE_IEEE_SINGLE, @@ -2139,18 +2568,24 @@ int riscv_init_registers(struct target *target) qsort(csr_info, DIM(csr_info), sizeof(*csr_info), cmp_csr_info); unsigned csr_info_index = 0; - /* When gdb request register N, gdb_get_register_packet() assumes that this + unsigned custom_range_index = 0; + int custom_within_range = 0; + + riscv_reg_info_t *shared_reg_info = calloc(1, sizeof(riscv_reg_info_t)); + shared_reg_info->target = target; + + /* When gdb requests register N, gdb_get_register_packet() assumes that this * is register at index N in reg_list. So if there are certain registers * that don't exist, we need to leave holes in the list (or renumber, but * it would be nice not to have yet another set of numbers to translate * between). */ - for (uint32_t number = 0; number < GDB_REGNO_COUNT; number++) { + for (uint32_t number = 0; number < target->reg_cache->num_regs; number++) { struct reg *r = &target->reg_cache->reg_list[number]; r->dirty = false; r->valid = false; r->exist = true; r->type = &riscv_reg_arch_type; - r->arch_info = target; + r->arch_info = shared_reg_info; r->number = number; r->size = riscv_xlen(target); /* r->size is set in riscv_invalidate_register_cache, maybe because the @@ -2510,11 +2945,35 @@ int riscv_init_registers(struct target *target) r->group = "general"; r->feature = &feature_virtual; r->size = 8; + + } else { + /* Custom registers. */ + assert(expose_custom); + + range_t *range = &expose_custom[custom_range_index]; + assert(range->low <= range->high); + unsigned custom_number = range->low + custom_within_range; + + r->group = "custom"; + r->feature = &feature_custom; + r->arch_info = calloc(1, sizeof(riscv_reg_info_t)); + assert(r->arch_info); + ((riscv_reg_info_t *) r->arch_info)->target = target; + ((riscv_reg_info_t *) r->arch_info)->custom_number = custom_number; + sprintf(reg_name, "custom%d", custom_number); + + custom_within_range++; + if (custom_within_range > range->high - range->low) { + custom_within_range = 0; + custom_range_index++; + } } + if (reg_name[0]) r->name = reg_name; reg_name += strlen(reg_name) + 1; - assert(reg_name < info->reg_names + GDB_REGNO_COUNT * max_reg_name_len); + assert(reg_name < info->reg_names + target->reg_cache->num_regs * + max_reg_name_len); r->value = &info->reg_cache_values[number]; } diff --git a/src/target/riscv/riscv.h b/src/target/riscv/riscv.h index 31f3cf63c..59414fc08 100644 --- a/src/target/riscv/riscv.h +++ b/src/target/riscv/riscv.h @@ -35,6 +35,11 @@ enum riscv_halt_reason { RISCV_HALT_ERROR }; +typedef struct { + struct target *target; + unsigned custom_number; +} riscv_reg_info_t; + typedef struct { unsigned dtm_version; @@ -91,6 +96,10 @@ typedef struct { bool triggers_enumerated; + /* Decremented every scan, and when it reaches 0 we clear the learned + * delays, causing them to be relearned. Used for testing. */ + int reset_delays_wait; + /* Helper functions that target the various RISC-V debug spec * implementations. */ int (*get_register)(struct target *target, @@ -120,6 +129,11 @@ typedef struct { int (*dmi_read)(struct target *target, uint32_t *value, uint32_t address); int (*dmi_write)(struct target *target, uint32_t address, uint32_t value); + + int (*test_sba_config_reg)(struct target *target, target_addr_t legal_address, + uint32_t num_words, target_addr_t illegal_address, bool run_sbbusyerror_test); + + int (*test_compliance)(struct target *target); } riscv_info_t; /* Wall-clock timeout for a command/access. Settable via RISC-V Target commands.*/ @@ -137,11 +151,11 @@ static inline riscv_info_t *riscv_info(const struct target *target) { return target->arch_info; } #define RISCV_INFO(R) riscv_info_t *R = riscv_info(target); -extern uint8_t ir_dtmcontrol[1]; +extern uint8_t ir_dtmcontrol[4]; extern struct scan_field select_dtmcontrol; -extern uint8_t ir_dbus[1]; +extern uint8_t ir_dbus[4]; extern struct scan_field select_dbus; -extern uint8_t ir_idcode[1]; +extern uint8_t ir_idcode[4]; extern struct scan_field select_idcode; /*** OpenOCD Interface */ @@ -253,6 +267,7 @@ int riscv_remove_breakpoint(struct target *target, int riscv_add_watchpoint(struct target *target, struct watchpoint *watchpoint); int riscv_remove_watchpoint(struct target *target, struct watchpoint *watchpoint); +int riscv_hit_watchpoint(struct target *target, struct watchpoint **hit_wp_address); int riscv_init_registers(struct target *target); From 21ef7e30d4f47a78e2b3aacedd425f0966465352 Mon Sep 17 00:00:00 2001 From: Tomas Vanek Date: Sat, 2 Mar 2019 09:51:23 +0100 Subject: [PATCH 62/70] flash/nor/core: adjust flash_iterate_address_range_inner() for 64-bit Use target_addr_t exclusively for comparison of sector boudaries and address range. Use the last addres for both address range end and sector end. It avoids problems with a flash bank mapped at the very end of target address space. Change-Id: Idf97c837453d97cbc4cf8a1c76ad799f4142f19e Signed-off-by: Tomas Vanek Reviewed-on: http://openocd.zylin.com/4985 Tested-by: jenkins Reviewed-by: Tim Newsome Reviewed-by: Matthias Welwarsky --- src/flash/nor/core.c | 36 +++++++++++++++++------------------- 1 file changed, 17 insertions(+), 19 deletions(-) diff --git a/src/flash/nor/core.c b/src/flash/nor/core.c index 11b7ce4a0..043ff13c8 100644 --- a/src/flash/nor/core.c +++ b/src/flash/nor/core.c @@ -422,7 +422,7 @@ static int flash_iterate_address_range_inner(struct target *target, { struct flash_bank *c; struct flash_sector *block_array; - target_addr_t last_addr = addr + length; /* first address AFTER end */ + target_addr_t last_addr = addr + length - 1; /* the last address of range */ int first = -1; int last = -1; int i; @@ -448,7 +448,7 @@ static int flash_iterate_address_range_inner(struct target *target, } /* check whether it all fits in this bank */ - if (addr + length - 1 > c->base + c->size - 1) { + if (last_addr > c->base + c->size - 1) { LOG_ERROR("Flash access does not fit into bank."); return ERROR_FLASH_DST_BREAKS_ALIGNMENT; } @@ -466,21 +466,19 @@ static int flash_iterate_address_range_inner(struct target *target, num_blocks = c->num_sectors; } - addr -= c->base; - last_addr -= c->base; - for (i = 0; i < num_blocks; i++) { struct flash_sector *f = &block_array[i]; - uint32_t end = f->offset + f->size; + target_addr_t sector_addr = c->base + f->offset; + target_addr_t sector_last_addr = sector_addr + f->size - 1; /* start only on a sector boundary */ if (first < 0) { /* scanned past the first sector? */ - if (addr < f->offset) + if (addr < sector_addr) break; /* is this the first sector? */ - if (addr == f->offset) + if (addr == sector_addr) first = i; /* Does this need head-padding? If so, pad and warn; @@ -490,12 +488,12 @@ static int flash_iterate_address_range_inner(struct target *target, * ever know if that data was in use. The warning * should help users sort out messes later. */ - else if (addr < end && pad_reason) { + else if (addr <= sector_last_addr && pad_reason) { /* FIXME say how many bytes (e.g. 80 KB) */ LOG_WARNING("Adding extra %s range, " - "%#8.8x to " TARGET_ADDR_FMT, + TARGET_ADDR_FMT " .. " TARGET_ADDR_FMT, pad_reason, - (unsigned) f->offset, + sector_addr, addr - 1); first = i; } else @@ -503,7 +501,7 @@ static int flash_iterate_address_range_inner(struct target *target, } /* is this (also?) the last sector? */ - if (last_addr == end) { + if (last_addr == sector_last_addr) { last = i; break; } @@ -511,19 +509,19 @@ static int flash_iterate_address_range_inner(struct target *target, /* Does this need tail-padding? If so, pad and warn; * or else force an error. */ - if (last_addr < end && pad_reason) { + if (last_addr < sector_last_addr && pad_reason) { /* FIXME say how many bytes (e.g. 80 KB) */ LOG_WARNING("Adding extra %s range, " - "%#8.8x to %#8.8x", + TARGET_ADDR_FMT " .. " TARGET_ADDR_FMT, pad_reason, - (unsigned) last_addr, - (unsigned) end - 1); + last_addr + 1, + sector_last_addr); last = i; break; } /* MUST finish on a sector boundary */ - if (last_addr <= f->offset) + if (last_addr < sector_addr) break; } @@ -531,8 +529,8 @@ static int flash_iterate_address_range_inner(struct target *target, if (first == -1 || last == -1) { LOG_ERROR("address range " TARGET_ADDR_FMT " .. " TARGET_ADDR_FMT " is not sector-aligned", - c->base + addr, - c->base + last_addr - 1); + addr, + last_addr); return ERROR_FLASH_DST_BREAKS_ALIGNMENT; } From d496da2c20e579f0f8af09928049bfb04d328190 Mon Sep 17 00:00:00 2001 From: Angus Ainslie Date: Thu, 19 Apr 2018 13:21:55 -0600 Subject: [PATCH 63/70] imx8m: add an m4 target to the imx8m The imx8m also has a Cortex m4 so add a target for it. Change-Id: I2abf62b6232c547fe9b12507f459835b11c63a6d Signed-off-by: Angus Ainslie Reviewed-on: http://openocd.zylin.com/4501 Tested-by: jenkins Reviewed-by: Matthias Welwarsky --- tcl/target/imx8m.cfg | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tcl/target/imx8m.cfg b/tcl/target/imx8m.cfg index 33149540a..5d7acbed1 100644 --- a/tcl/target/imx8m.cfg +++ b/tcl/target/imx8m.cfg @@ -53,3 +53,6 @@ for { set _core 0 } { $_core < $_cores } { incr _core } { eval $_smp_command targets $_TARGETNAME.0 + +# declare the auxiliary Cortex-M4 core on AP #4 +target create ${_CHIPNAME}.m4 cortex_m -dap ${_CHIPNAME}.dap -ap-num 4 From 246782229f8f7536bee66322dbe7f366b85628ec Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Thu, 19 Jul 2018 11:50:56 +0200 Subject: [PATCH 64/70] smp: replace commands smp_on/smp_off with "smp [on|off]" Seams over-engineered having two separate commands to turn SMP on/off. Plus it is missing the possibility to dump the current status of SMP and would be weird adding an additional command for it. Moreover, such commands are replicated in few targets so it would make sense centralizing them. - Deprecate the commands "smp_on" and "smp_off". - Add a new command "smp" that accepts optional parameters "[on|off]" and prints the SMP status when run without parameters. This replaces the two commands above. - Put the deprecated and the new command handlers in smp.c - Update the documentation, except for mips_m4k, since it is not available yet. - Promote the macro foreach_smp_target to global context and use it where possible. Change-Id: Ia72841c1a3bd6edd4db4cc809046322f498617e6 Signed-off-by: Antonio Borneo Reviewed-on: http://openocd.zylin.com/4615 Tested-by: jenkins Reviewed-by: Graham Sanderson Reviewed-by: Matthias Welwarsky --- doc/openocd.texi | 17 ++++------ src/target/aarch64.c | 56 +++--------------------------- src/target/cortex_a.c | 55 +++--------------------------- src/target/mips_m4k.c | 55 +++--------------------------- src/target/smp.c | 79 +++++++++++++++++++++++++++++++++++++++++++ src/target/smp.h | 5 +++ tcl/target/u8500.cfg | 4 +-- 7 files changed, 105 insertions(+), 166 deletions(-) diff --git a/doc/openocd.texi b/doc/openocd.texi index a17173ce8..027e6d2ed 100644 --- a/doc/openocd.texi +++ b/doc/openocd.texi @@ -1802,10 +1802,11 @@ displayed by the GDB session @pxref{usingopenocdsmpwithgdb,,Using OpenOCD SMP wi The SMP behaviour can be disabled/enabled dynamically. On cortex_a following command have been implemented. @itemize @bullet -@item cortex_a smp_on : enable SMP mode, behaviour is as described above. -@item cortex_a smp_off : disable SMP mode, the current target is the one +@item cortex_a smp on : enable SMP mode, behaviour is as described above. +@item cortex_a smp off : disable SMP mode, the current target is the one displayed in the GDB session, only this target is now controlled by GDB session. This behaviour is useful during system boot up. +@item cortex_a smp : display current SMP mode. @item cortex_a smp_gdb : display/fix the core id displayed in GDB session see following example. @end itemize @@ -8940,12 +8941,8 @@ Initialize core debug Enables debug by unlocking the Software Lock and clearing sticky powerdown indications @end deffn -@deffn Command {cortex_a smp_off} -Disable SMP mode -@end deffn - -@deffn Command {cortex_a smp_on} -Enable SMP mode +@deffn Command {cortex_a smp} [on|off] +Display/set the current SMP mode @end deffn @deffn Command {cortex_a smp_gdb} [core_id] @@ -9156,8 +9153,8 @@ target code relies on. In a configuration file, the command would typically be c However, normally it is not necessary to use the command at all. @end deffn -@deffn Command {aarch64 smp_on|smp_off} -Enable and disable SMP handling. The state of SMP handling influences the way targets in an SMP group +@deffn Command {aarch64 smp} [on|off] +Display, enable or disable SMP handling mode. The state of SMP handling influences the way targets in an SMP group are handled by the run control. With SMP handling enabled, issuing halt or resume to one core will trigger halting or resuming of all cores in the group. The command @code{target smp} defines which targets are in the SMP group. With SMP handling disabled, all targets need to be treated individually. diff --git a/src/target/aarch64.c b/src/target/aarch64.c index 1fafcfd45..ff68e3adb 100644 --- a/src/target/aarch64.c +++ b/src/target/aarch64.c @@ -29,6 +29,7 @@ #include "armv8_opcodes.h" #include "armv8_cache.h" #include "arm_semihosting.h" +#include "smp.h" #include enum restart_mode { @@ -63,9 +64,6 @@ static int aarch64_virt2phys(struct target *target, static int aarch64_read_cpu_memory(struct target *target, uint64_t address, uint32_t size, uint32_t count, uint8_t *buffer); -#define foreach_smp_target(pos, head) \ - for (pos = head; (pos != NULL); pos = pos->next) - static int aarch64_restore_system_control_reg(struct target *target) { enum arm_mode target_mode = ARM_MODE_ANY; @@ -2550,42 +2548,6 @@ COMMAND_HANDLER(aarch64_handle_dbginit_command) return aarch64_init_debug_access(target); } -COMMAND_HANDLER(aarch64_handle_smp_off_command) -{ - struct target *target = get_current_target(CMD_CTX); - /* check target is an smp target */ - struct target_list *head; - struct target *curr; - head = target->head; - target->smp = 0; - if (head != (struct target_list *)NULL) { - while (head != (struct target_list *)NULL) { - curr = head->target; - curr->smp = 0; - head = head->next; - } - /* fixes the target display to the debugger */ - target->gdb_service->target = target; - } - return ERROR_OK; -} - -COMMAND_HANDLER(aarch64_handle_smp_on_command) -{ - struct target *target = get_current_target(CMD_CTX); - struct target_list *head; - struct target *curr; - head = target->head; - if (head != (struct target_list *)NULL) { - target->smp = 1; - while (head != (struct target_list *)NULL) { - curr = head->target; - curr->smp = 1; - head = head->next; - } - } - return ERROR_OK; -} COMMAND_HANDLER(aarch64_mask_interrupts_command) { @@ -2767,19 +2729,6 @@ static const struct command_registration aarch64_exec_command_handlers[] = { .help = "Initialize core debug", .usage = "", }, - { .name = "smp_off", - .handler = aarch64_handle_smp_off_command, - .mode = COMMAND_EXEC, - .help = "Stop smp handling", - .usage = "", - }, - { - .name = "smp_on", - .handler = aarch64_handle_smp_on_command, - .mode = COMMAND_EXEC, - .help = "Restart smp handling", - .usage = "", - }, { .name = "maskisr", .handler = aarch64_mask_interrupts_command, @@ -2801,6 +2750,9 @@ static const struct command_registration aarch64_exec_command_handlers[] = { .help = "read coprocessor register", .usage = "cpnum op1 CRn CRm op2", }, + { + .chain = smp_command_handlers, + }, COMMAND_REGISTRATION_DONE diff --git a/src/target/cortex_a.c b/src/target/cortex_a.c index e460f3b70..c9ef68c21 100644 --- a/src/target/cortex_a.c +++ b/src/target/cortex_a.c @@ -56,11 +56,9 @@ #include "arm_opcodes.h" #include "arm_semihosting.h" #include "transport/transport.h" +#include "smp.h" #include -#define foreach_smp_target(pos, head) \ - for (pos = head; (pos != NULL); pos = pos->next) - static int cortex_a_poll(struct target *target); static int cortex_a_debug_entry(struct target *target); static int cortex_a_restore_context(struct target *target, bool bpwp); @@ -2969,42 +2967,6 @@ COMMAND_HANDLER(cortex_a_handle_dbginit_command) return cortex_a_init_debug_access(target); } -COMMAND_HANDLER(cortex_a_handle_smp_off_command) -{ - struct target *target = get_current_target(CMD_CTX); - /* check target is an smp target */ - struct target_list *head; - struct target *curr; - head = target->head; - target->smp = 0; - if (head != (struct target_list *)NULL) { - while (head != (struct target_list *)NULL) { - curr = head->target; - curr->smp = 0; - head = head->next; - } - /* fixes the target display to the debugger */ - target->gdb_service->target = target; - } - return ERROR_OK; -} - -COMMAND_HANDLER(cortex_a_handle_smp_on_command) -{ - struct target *target = get_current_target(CMD_CTX); - struct target_list *head; - struct target *curr; - head = target->head; - if (head != (struct target_list *)NULL) { - target->smp = 1; - while (head != (struct target_list *)NULL) { - curr = head->target; - curr->smp = 1; - head = head->next; - } - } - return ERROR_OK; -} COMMAND_HANDLER(cortex_a_handle_smp_gdb_command) { @@ -3096,18 +3058,6 @@ static const struct command_registration cortex_a_exec_command_handlers[] = { .help = "Initialize core debug", .usage = "", }, - { .name = "smp_off", - .handler = cortex_a_handle_smp_off_command, - .mode = COMMAND_EXEC, - .help = "Stop smp handling", - .usage = "",}, - { - .name = "smp_on", - .handler = cortex_a_handle_smp_on_command, - .mode = COMMAND_EXEC, - .help = "Restart smp handling", - .usage = "", - }, { .name = "smp_gdb", .handler = cortex_a_handle_smp_gdb_command, @@ -3133,6 +3083,9 @@ static const struct command_registration cortex_a_exec_command_handlers[] = { { .chain = armv7a_mmu_command_handlers, }, + { + .chain = smp_command_handlers, + }, COMMAND_REGISTRATION_DONE }; diff --git a/src/target/mips_m4k.c b/src/target/mips_m4k.c index 6981c2ec8..016b5a9c5 100644 --- a/src/target/mips_m4k.c +++ b/src/target/mips_m4k.c @@ -33,6 +33,7 @@ #include "mips32_dmaacc.h" #include "target_type.h" #include "register.h" +#include "smp.h" static void mips_m4k_enable_breakpoints(struct target *target); static void mips_m4k_enable_watchpoints(struct target *target); @@ -1333,43 +1334,6 @@ COMMAND_HANDLER(mips_m4k_handle_cp0_command) return ERROR_OK; } -COMMAND_HANDLER(mips_m4k_handle_smp_off_command) -{ - struct target *target = get_current_target(CMD_CTX); - /* check target is an smp target */ - struct target_list *head; - struct target *curr; - head = target->head; - target->smp = 0; - if (head != (struct target_list *)NULL) { - while (head != (struct target_list *)NULL) { - curr = head->target; - curr->smp = 0; - head = head->next; - } - /* fixes the target display to the debugger */ - target->gdb_service->target = target; - } - return ERROR_OK; -} - -COMMAND_HANDLER(mips_m4k_handle_smp_on_command) -{ - struct target *target = get_current_target(CMD_CTX); - struct target_list *head; - struct target *curr; - head = target->head; - if (head != (struct target_list *)NULL) { - target->smp = 1; - while (head != (struct target_list *)NULL) { - curr = head->target; - curr->smp = 1; - head = head->next; - } - } - return ERROR_OK; -} - COMMAND_HANDLER(mips_m4k_handle_smp_gdb_command) { struct target *target = get_current_target(CMD_CTX); @@ -1422,20 +1386,6 @@ static const struct command_registration mips_m4k_exec_command_handlers[] = { .usage = "regnum [value]", .help = "display/modify cp0 register", }, - { - .name = "smp_off", - .handler = mips_m4k_handle_smp_off_command, - .mode = COMMAND_EXEC, - .help = "Stop smp handling", - .usage = "",}, - - { - .name = "smp_on", - .handler = mips_m4k_handle_smp_on_command, - .mode = COMMAND_EXEC, - .help = "Restart smp handling", - .usage = "", - }, { .name = "smp_gdb", .handler = mips_m4k_handle_smp_gdb_command, @@ -1450,6 +1400,9 @@ static const struct command_registration mips_m4k_exec_command_handlers[] = { .help = "display/set scan delay in nano seconds", .usage = "[value]", }, + { + .chain = smp_command_handlers, + }, COMMAND_REGISTRATION_DONE }; diff --git a/src/target/smp.c b/src/target/smp.c index bdf81a0ee..87944331e 100644 --- a/src/target/smp.c +++ b/src/target/smp.c @@ -96,3 +96,82 @@ int gdb_write_smp_packet(struct connection *connection, return retval; } + +COMMAND_HANDLER(default_handle_smp_command) +{ + struct target *target = get_current_target(CMD_CTX); + struct target_list *head; + + if (CMD_ARGC > 1) + return ERROR_COMMAND_SYNTAX_ERROR; + + if (!CMD_ARGC) { + command_print(CMD_CTX, "%s", target->smp ? "on" : "off"); + return ERROR_OK; + } + + if (!strcmp(CMD_ARGV[0], "on")) { + foreach_smp_target(head, target->head) + head->target->smp = 1; + + return ERROR_OK; + } + + if (!strcmp(CMD_ARGV[0], "off")) { + foreach_smp_target(head, target->head) + head->target->smp = 0; + + /* fixes the target display to the debugger */ + if (target->head) + target->gdb_service->target = target; + + return ERROR_OK; + } + + return ERROR_COMMAND_SYNTAX_ERROR; +} + +COMMAND_HANDLER(deprecated_handle_smp_on_command) +{ + const char *argv[] = {"on", NULL}; + + LOG_WARNING("\'smp_on\' is deprecated, please use \'smp on\' instead."); + CMD_ARGC = 1; + CMD_ARGV = argv; + return CALL_COMMAND_HANDLER(default_handle_smp_command); +} + +COMMAND_HANDLER(deprecated_handle_smp_off_command) +{ + const char *argv[] = {"off", NULL}; + + LOG_WARNING("\'smp_off\' is deprecated, please use \'smp off\' instead."); + CMD_ARGC = 1; + CMD_ARGV = argv; + return CALL_COMMAND_HANDLER(default_handle_smp_command); +} + +const struct command_registration smp_command_handlers[] = { + { + .name = "smp", + .handler = default_handle_smp_command, + .mode = COMMAND_EXEC, + .help = "smp handling", + .usage = "[on|off]", + }, + { + .name = "smp_on", + .handler = deprecated_handle_smp_on_command, + .mode = COMMAND_EXEC, + .help = "Restart smp handling", + .usage = "", + }, + { + .name = "smp_off", + .handler = deprecated_handle_smp_off_command, + .mode = COMMAND_EXEC, + .help = "Stop smp handling", + .usage = "", + }, + COMMAND_REGISTRATION_DONE +}; diff --git a/src/target/smp.h b/src/target/smp.h index c3e6c6cea..f024b4023 100644 --- a/src/target/smp.h +++ b/src/target/smp.h @@ -21,6 +21,11 @@ #include "server/server.h" +#define foreach_smp_target(pos, head) \ + for (pos = head; (pos != NULL); pos = pos->next) + +extern const struct command_registration smp_command_handlers[]; + int gdb_read_smp_packet(struct connection *connection, char const *packet, int packet_size); int gdb_write_smp_packet(struct connection *connection, diff --git a/tcl/target/u8500.cfg b/tcl/target/u8500.cfg index 1313efd3a..7ff39291b 100644 --- a/tcl/target/u8500.cfg +++ b/tcl/target/u8500.cfg @@ -19,12 +19,12 @@ proc ocd_gdb_restart {target_id} { global _SMP targets $_TARGETNAME_1 if { [expr ($_SMP == 1)] } { - cortex_a smp_off + cortex_a smp off } rst_run halt if { [expr ($_SMP == 1)]} { - cortex_a smp_on + cortex_a smp on } } From 84a2cab596a0621fab3424c72b43280ccdc240c2 Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Thu, 7 Mar 2019 22:34:29 +0100 Subject: [PATCH 65/70] smp: move sub-command "smp_gdb" in file smp.c The code for this command is currently replicated in cortex_a and in mips_m4k and is going to be added again for cortex_m. Plus, it is going to be obsoleted by the HW thread pseudo RTOS. Consolidate in smp.c a single instance of the command. This will simplify both obsoleting it and adding it to cortex_m, whatever change comes first. Change-Id: I03cd857e21fa3f7202fdcee36bcbd5aae30a609d Signed-off-by: Antonio Borneo Reviewed-on: http://openocd.zylin.com/4991 Tested-by: jenkins Reviewed-by: Tarek BOCHKATI Reviewed-by: Matthias Welwarsky --- src/target/cortex_a.c | 28 ---------------------------- src/target/mips_m4k.c | 28 ---------------------------- src/target/smp.c | 28 ++++++++++++++++++++++++++++ 3 files changed, 28 insertions(+), 56 deletions(-) diff --git a/src/target/cortex_a.c b/src/target/cortex_a.c index c9ef68c21..6eb6aa933 100644 --- a/src/target/cortex_a.c +++ b/src/target/cortex_a.c @@ -2968,27 +2968,6 @@ COMMAND_HANDLER(cortex_a_handle_dbginit_command) return cortex_a_init_debug_access(target); } -COMMAND_HANDLER(cortex_a_handle_smp_gdb_command) -{ - struct target *target = get_current_target(CMD_CTX); - int retval = ERROR_OK; - struct target_list *head; - head = target->head; - if (head != (struct target_list *)NULL) { - if (CMD_ARGC == 1) { - int coreid = 0; - COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], coreid); - if (ERROR_OK != retval) - return retval; - target->gdb_service->core[1] = coreid; - - } - command_print(CMD_CTX, "gdb coreid %" PRId32 " -> %" PRId32, target->gdb_service->core[0] - , target->gdb_service->core[1]); - } - return ERROR_OK; -} - COMMAND_HANDLER(handle_cortex_a_mask_interrupts_command) { struct target *target = get_current_target(CMD_CTX); @@ -3058,13 +3037,6 @@ static const struct command_registration cortex_a_exec_command_handlers[] = { .help = "Initialize core debug", .usage = "", }, - { - .name = "smp_gdb", - .handler = cortex_a_handle_smp_gdb_command, - .mode = COMMAND_EXEC, - .help = "display/fix current core played to gdb", - .usage = "", - }, { .name = "maskisr", .handler = handle_cortex_a_mask_interrupts_command, diff --git a/src/target/mips_m4k.c b/src/target/mips_m4k.c index 016b5a9c5..653d732f1 100644 --- a/src/target/mips_m4k.c +++ b/src/target/mips_m4k.c @@ -1334,27 +1334,6 @@ COMMAND_HANDLER(mips_m4k_handle_cp0_command) return ERROR_OK; } -COMMAND_HANDLER(mips_m4k_handle_smp_gdb_command) -{ - struct target *target = get_current_target(CMD_CTX); - int retval = ERROR_OK; - struct target_list *head; - head = target->head; - if (head != (struct target_list *)NULL) { - if (CMD_ARGC == 1) { - int coreid = 0; - COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], coreid); - if (ERROR_OK != retval) - return retval; - target->gdb_service->core[1] = coreid; - - } - command_print(CMD_CTX, "gdb coreid %" PRId32 " -> %" PRId32, target->gdb_service->core[0] - , target->gdb_service->core[1]); - } - return ERROR_OK; -} - COMMAND_HANDLER(mips_m4k_handle_scan_delay_command) { struct target *target = get_current_target(CMD_CTX); @@ -1386,13 +1365,6 @@ static const struct command_registration mips_m4k_exec_command_handlers[] = { .usage = "regnum [value]", .help = "display/modify cp0 register", }, - { - .name = "smp_gdb", - .handler = mips_m4k_handle_smp_gdb_command, - .mode = COMMAND_EXEC, - .help = "display/fix current core played to gdb", - .usage = "", - }, { .name = "scan_delay", .handler = mips_m4k_handle_scan_delay_command, diff --git a/src/target/smp.c b/src/target/smp.c index 87944331e..f42d8abed 100644 --- a/src/target/smp.c +++ b/src/target/smp.c @@ -151,6 +151,27 @@ COMMAND_HANDLER(deprecated_handle_smp_off_command) return CALL_COMMAND_HANDLER(default_handle_smp_command); } +COMMAND_HANDLER(handle_smp_gdb_command) +{ + struct target *target = get_current_target(CMD_CTX); + int retval = ERROR_OK; + struct target_list *head; + head = target->head; + if (head != (struct target_list *)NULL) { + if (CMD_ARGC == 1) { + int coreid = 0; + COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], coreid); + if (ERROR_OK != retval) + return retval; + target->gdb_service->core[1] = coreid; + + } + command_print(CMD_CTX, "gdb coreid %" PRId32 " -> %" PRId32, target->gdb_service->core[0] + , target->gdb_service->core[1]); + } + return ERROR_OK; +} + const struct command_registration smp_command_handlers[] = { { .name = "smp", @@ -173,5 +194,12 @@ const struct command_registration smp_command_handlers[] = { .help = "Stop smp handling", .usage = "", }, + { + .name = "smp_gdb", + .handler = handle_smp_gdb_command, + .mode = COMMAND_EXEC, + .help = "display/fix current core played to gdb", + .usage = "", + }, COMMAND_REGISTRATION_DONE }; From a7479fa89def9d8b1854d629dfdaa0ba17132617 Mon Sep 17 00:00:00 2001 From: Christopher Head Date: Thu, 13 Dec 2018 11:53:59 -0800 Subject: [PATCH 66/70] Constify struct flash_driver instances Instances of struct flash_driver are never written to at runtime. For a small amount of memory saving and also robustness (fewer things for stray pointer writes to hit), mark them const. Change-Id: Iadbbbc2fac0976d892699200000c5f02856729f3 Signed-off-by: Christopher Head Reviewed-on: http://openocd.zylin.com/4803 Reviewed-by: Antonio Borneo Tested-by: jenkins Reviewed-by: Matthias Welwarsky --- src/flash/nor/aduc702x.c | 2 +- src/flash/nor/aducm360.c | 2 +- src/flash/nor/ambiqmicro.c | 2 +- src/flash/nor/at91sam3.c | 4 +- src/flash/nor/at91sam4.c | 4 +- src/flash/nor/at91sam4l.c | 2 +- src/flash/nor/at91sam7.c | 2 +- src/flash/nor/at91samd.c | 2 +- src/flash/nor/ath79.c | 2 +- src/flash/nor/atsame5.c | 2 +- src/flash/nor/atsamv.c | 4 +- src/flash/nor/avrf.c | 2 +- src/flash/nor/bluenrg-x.c | 2 +- src/flash/nor/cc26xx.c | 2 +- src/flash/nor/cc3220sf.c | 2 +- src/flash/nor/cfi.c | 2 +- src/flash/nor/core.h | 2 +- src/flash/nor/driver.h | 2 +- src/flash/nor/drivers.c | 130 ++++++++++++++++---------------- src/flash/nor/dsp5680xx_flash.c | 2 +- src/flash/nor/efm32.c | 2 +- src/flash/nor/em357.c | 2 +- src/flash/nor/esirisc_flash.c | 2 +- src/flash/nor/faux.c | 2 +- src/flash/nor/fespi.c | 2 +- src/flash/nor/fm3.c | 2 +- src/flash/nor/fm4.c | 2 +- src/flash/nor/jtagspi.c | 2 +- src/flash/nor/kinetis.c | 4 +- src/flash/nor/kinetis_ke.c | 2 +- src/flash/nor/lpc2000.c | 2 +- src/flash/nor/lpc288x.c | 2 +- src/flash/nor/lpc2900.c | 2 +- src/flash/nor/lpcspifi.c | 2 +- src/flash/nor/max32xxx.c | 2 +- src/flash/nor/mdr.c | 2 +- src/flash/nor/mrvlqspi.c | 2 +- src/flash/nor/msp432.c | 2 +- src/flash/nor/niietcm4.c | 2 +- src/flash/nor/nrf5.c | 4 +- src/flash/nor/numicro.c | 2 +- src/flash/nor/ocl.c | 2 +- src/flash/nor/pic32mx.c | 2 +- src/flash/nor/psoc4.c | 2 +- src/flash/nor/psoc5lp.c | 6 +- src/flash/nor/psoc6.c | 2 +- src/flash/nor/sim3x.c | 2 +- src/flash/nor/stellaris.c | 2 +- src/flash/nor/stm32f1x.c | 2 +- src/flash/nor/stm32f2x.c | 2 +- src/flash/nor/stm32h7x.c | 2 +- src/flash/nor/stm32l4x.c | 2 +- src/flash/nor/stm32lx.c | 2 +- src/flash/nor/stmsmi.c | 2 +- src/flash/nor/str7x.c | 2 +- src/flash/nor/str9x.c | 2 +- src/flash/nor/str9xpec.c | 2 +- src/flash/nor/tcl.c | 2 +- src/flash/nor/tms470.c | 2 +- src/flash/nor/virtual.c | 2 +- src/flash/nor/w600.c | 2 +- src/flash/nor/xcf.c | 2 +- src/flash/nor/xmc1xxx.c | 2 +- src/flash/nor/xmc4xxx.c | 2 +- 64 files changed, 135 insertions(+), 135 deletions(-) diff --git a/src/flash/nor/aduc702x.c b/src/flash/nor/aduc702x.c index 824112b1b..b6e19376c 100644 --- a/src/flash/nor/aduc702x.c +++ b/src/flash/nor/aduc702x.c @@ -378,7 +378,7 @@ static int aduc702x_check_flash_completion(struct target *target, unsigned int t return ERROR_OK; } -struct flash_driver aduc702x_flash = { +const struct flash_driver aduc702x_flash = { .name = "aduc702x", .flash_bank_command = aduc702x_flash_bank_command, .erase = aduc702x_erase, diff --git a/src/flash/nor/aducm360.c b/src/flash/nor/aducm360.c index 766378347..f468c89a5 100644 --- a/src/flash/nor/aducm360.c +++ b/src/flash/nor/aducm360.c @@ -554,7 +554,7 @@ static int aducm360_check_flash_completion(struct target *target, unsigned int t } /* ----------------------------------------------------------------------- */ -struct flash_driver aducm360_flash = { +const struct flash_driver aducm360_flash = { .name = "aducm360", .flash_bank_command = aducm360_flash_bank_command, .erase = aducm360_erase, diff --git a/src/flash/nor/ambiqmicro.c b/src/flash/nor/ambiqmicro.c index 13b2b26ae..a536d5456 100644 --- a/src/flash/nor/ambiqmicro.c +++ b/src/flash/nor/ambiqmicro.c @@ -888,7 +888,7 @@ static const struct command_registration ambiqmicro_command_handlers[] = { COMMAND_REGISTRATION_DONE }; -struct flash_driver ambiqmicro_flash = { +const struct flash_driver ambiqmicro_flash = { .name = "ambiqmicro", .commands = ambiqmicro_command_handlers, .flash_bank_command = ambiqmicro_flash_bank_command, diff --git a/src/flash/nor/at91sam3.c b/src/flash/nor/at91sam3.c index 711918862..2d61a8780 100644 --- a/src/flash/nor/at91sam3.c +++ b/src/flash/nor/at91sam3.c @@ -109,7 +109,7 @@ #define offset_EFC_FSR 8 #define offset_EFC_FRR 12 -extern struct flash_driver at91sam3_flash; +extern const struct flash_driver at91sam3_flash; static float _tomhz(uint32_t freq_hz) { @@ -3753,7 +3753,7 @@ static const struct command_registration at91sam3_command_handlers[] = { COMMAND_REGISTRATION_DONE }; -struct flash_driver at91sam3_flash = { +const struct flash_driver at91sam3_flash = { .name = "at91sam3", .commands = at91sam3_command_handlers, .flash_bank_command = sam3_flash_bank_command, diff --git a/src/flash/nor/at91sam4.c b/src/flash/nor/at91sam4.c index d4d48a74f..446f7983b 100644 --- a/src/flash/nor/at91sam4.c +++ b/src/flash/nor/at91sam4.c @@ -103,7 +103,7 @@ #define offset_EFC_FSR 8 #define offset_EFC_FRR 12 -extern struct flash_driver at91sam4_flash; +extern const struct flash_driver at91sam4_flash; static float _tomhz(uint32_t freq_hz) { @@ -3234,7 +3234,7 @@ static const struct command_registration at91sam4_command_handlers[] = { COMMAND_REGISTRATION_DONE }; -struct flash_driver at91sam4_flash = { +const struct flash_driver at91sam4_flash = { .name = "at91sam4", .commands = at91sam4_command_handlers, .flash_bank_command = sam4_flash_bank_command, diff --git a/src/flash/nor/at91sam4l.c b/src/flash/nor/at91sam4l.c index f3b065f40..1c2402ff0 100644 --- a/src/flash/nor/at91sam4l.c +++ b/src/flash/nor/at91sam4l.c @@ -684,7 +684,7 @@ static const struct command_registration at91sam4l_command_handlers[] = { COMMAND_REGISTRATION_DONE }; -struct flash_driver at91sam4l_flash = { +const struct flash_driver at91sam4l_flash = { .name = "at91sam4l", .commands = at91sam4l_command_handlers, .flash_bank_command = sam4l_flash_bank_command, diff --git a/src/flash/nor/at91sam7.c b/src/flash/nor/at91sam7.c index 9de829327..15b93a29f 100644 --- a/src/flash/nor/at91sam7.c +++ b/src/flash/nor/at91sam7.c @@ -1140,7 +1140,7 @@ static const struct command_registration at91sam7_command_handlers[] = { COMMAND_REGISTRATION_DONE }; -struct flash_driver at91sam7_flash = { +const struct flash_driver at91sam7_flash = { .name = "at91sam7", .usage = "gpnvm ", .commands = at91sam7_command_handlers, diff --git a/src/flash/nor/at91samd.c b/src/flash/nor/at91samd.c index 029579ba8..ad0da5d7e 100644 --- a/src/flash/nor/at91samd.c +++ b/src/flash/nor/at91samd.c @@ -1287,7 +1287,7 @@ static const struct command_registration at91samd_command_handlers[] = { COMMAND_REGISTRATION_DONE }; -struct flash_driver at91samd_flash = { +const struct flash_driver at91samd_flash = { .name = "at91samd", .commands = at91samd_command_handlers, .flash_bank_command = samd_flash_bank_command, diff --git a/src/flash/nor/ath79.c b/src/flash/nor/ath79.c index af2112a9e..c551f2722 100644 --- a/src/flash/nor/ath79.c +++ b/src/flash/nor/ath79.c @@ -895,7 +895,7 @@ static int get_ath79_info(struct flash_bank *bank, char *buf, int buf_size) return ERROR_OK; } -struct flash_driver ath79_flash = { +const struct flash_driver ath79_flash = { .name = "ath79", .flash_bank_command = ath79_flash_bank_command, .erase = ath79_erase, diff --git a/src/flash/nor/atsame5.c b/src/flash/nor/atsame5.c index ff99e7d7c..833177e1a 100644 --- a/src/flash/nor/atsame5.c +++ b/src/flash/nor/atsame5.c @@ -938,7 +938,7 @@ static const struct command_registration same5_command_handlers[] = { COMMAND_REGISTRATION_DONE }; -struct flash_driver atsame5_flash = { +const struct flash_driver atsame5_flash = { .name = "atsame5", .commands = same5_command_handlers, .flash_bank_command = same5_flash_bank_command, diff --git a/src/flash/nor/atsamv.c b/src/flash/nor/atsamv.c index 9c07bdf15..5beeefc5a 100644 --- a/src/flash/nor/atsamv.c +++ b/src/flash/nor/atsamv.c @@ -94,7 +94,7 @@ #define SAMV_PAGE_SIZE 512 #define SAMV_FLASH_BASE 0x00400000 -extern struct flash_driver atsamv_flash; +extern const struct flash_driver atsamv_flash; struct samv_flash_bank { int probed; @@ -726,7 +726,7 @@ static const struct command_registration atsamv_command_handlers[] = { COMMAND_REGISTRATION_DONE }; -struct flash_driver atsamv_flash = { +const struct flash_driver atsamv_flash = { .name = "atsamv", .commands = atsamv_command_handlers, .flash_bank_command = samv_flash_bank_command, diff --git a/src/flash/nor/avrf.c b/src/flash/nor/avrf.c index b88f6f61c..6969f7741 100644 --- a/src/flash/nor/avrf.c +++ b/src/flash/nor/avrf.c @@ -462,7 +462,7 @@ static const struct command_registration avrf_command_handlers[] = { COMMAND_REGISTRATION_DONE }; -struct flash_driver avr_flash = { +const struct flash_driver avr_flash = { .name = "avr", .commands = avrf_command_handlers, .flash_bank_command = avrf_flash_bank_command, diff --git a/src/flash/nor/bluenrg-x.c b/src/flash/nor/bluenrg-x.c index f1b206201..f6a249273 100644 --- a/src/flash/nor/bluenrg-x.c +++ b/src/flash/nor/bluenrg-x.c @@ -539,7 +539,7 @@ static int bluenrgx_get_info(struct flash_bank *bank, char *buf, int buf_size) return ERROR_OK; } -struct flash_driver bluenrgx_flash = { +const struct flash_driver bluenrgx_flash = { .name = "bluenrg-x", .flash_bank_command = bluenrgx_flash_bank_command, .erase = bluenrgx_erase, diff --git a/src/flash/nor/cc26xx.c b/src/flash/nor/cc26xx.c index 0320e92c4..176211a07 100644 --- a/src/flash/nor/cc26xx.c +++ b/src/flash/nor/cc26xx.c @@ -535,7 +535,7 @@ static int cc26xx_info(struct flash_bank *bank, char *buf, int buf_size) return ERROR_OK; } -struct flash_driver cc26xx_flash = { +const struct flash_driver cc26xx_flash = { .name = "cc26xx", .flash_bank_command = cc26xx_flash_bank_command, .erase = cc26xx_erase, diff --git a/src/flash/nor/cc3220sf.c b/src/flash/nor/cc3220sf.c index 244112467..afdb7f491 100644 --- a/src/flash/nor/cc3220sf.c +++ b/src/flash/nor/cc3220sf.c @@ -489,7 +489,7 @@ static int cc3220sf_info(struct flash_bank *bank, char *buf, int buf_size) return ERROR_OK; } -struct flash_driver cc3220sf_flash = { +const struct flash_driver cc3220sf_flash = { .name = "cc3220sf", .flash_bank_command = cc3220sf_flash_bank_command, .erase = cc3220sf_erase, diff --git a/src/flash/nor/cfi.c b/src/flash/nor/cfi.c index 163862817..04fa83b55 100644 --- a/src/flash/nor/cfi.c +++ b/src/flash/nor/cfi.c @@ -3112,7 +3112,7 @@ static void cfi_fixup_0002_write_buffer(struct flash_bank *bank, const void *par cfi_info->buf_write_timeout_typ = 0; } -struct flash_driver cfi_flash = { +const struct flash_driver cfi_flash = { .name = "cfi", .flash_bank_command = cfi_flash_bank_command, .erase = cfi_erase, diff --git a/src/flash/nor/core.h b/src/flash/nor/core.h index bd3aa7039..f6bd0cf1a 100644 --- a/src/flash/nor/core.h +++ b/src/flash/nor/core.h @@ -87,7 +87,7 @@ struct flash_bank { struct target *target; /**< Target to which this bank belongs. */ - struct flash_driver *driver; /**< Driver for this bank. */ + const struct flash_driver *driver; /**< Driver for this bank. */ void *driver_priv; /**< Private driver storage pointer */ int bank_number; /**< The 'bank' (or chip number) of this instance. */ diff --git a/src/flash/nor/driver.h b/src/flash/nor/driver.h index ef69a0f42..9c56d4ea8 100644 --- a/src/flash/nor/driver.h +++ b/src/flash/nor/driver.h @@ -231,6 +231,6 @@ struct flash_driver { * @param name The name of the requested driver. * @returns The flash_driver called @c name, or NULL if not found. */ -struct flash_driver *flash_driver_find_by_name(const char *name); +const struct flash_driver *flash_driver_find_by_name(const char *name); #endif /* OPENOCD_FLASH_NOR_DRIVER_H */ diff --git a/src/flash/nor/drivers.c b/src/flash/nor/drivers.c index 31caa5a55..955d149b5 100644 --- a/src/flash/nor/drivers.c +++ b/src/flash/nor/drivers.c @@ -20,75 +20,75 @@ #endif #include "imp.h" -extern struct flash_driver aduc702x_flash; -extern struct flash_driver aducm360_flash; -extern struct flash_driver ambiqmicro_flash; -extern struct flash_driver at91sam3_flash; -extern struct flash_driver at91sam4_flash; -extern struct flash_driver at91sam4l_flash; -extern struct flash_driver at91sam7_flash; -extern struct flash_driver at91samd_flash; -extern struct flash_driver ath79_flash; -extern struct flash_driver atsame5_flash; -extern struct flash_driver atsamv_flash; -extern struct flash_driver avr_flash; -extern struct flash_driver bluenrgx_flash; -extern struct flash_driver cc3220sf_flash; -extern struct flash_driver cc26xx_flash; -extern struct flash_driver cfi_flash; -extern struct flash_driver dsp5680xx_flash; -extern struct flash_driver efm32_flash; -extern struct flash_driver em357_flash; -extern struct flash_driver esirisc_flash; -extern struct flash_driver faux_flash; -extern struct flash_driver fm3_flash; -extern struct flash_driver fm4_flash; -extern struct flash_driver fespi_flash; -extern struct flash_driver jtagspi_flash; -extern struct flash_driver kinetis_flash; -extern struct flash_driver kinetis_ke_flash; -extern struct flash_driver lpc2000_flash; -extern struct flash_driver lpc288x_flash; -extern struct flash_driver lpc2900_flash; -extern struct flash_driver lpcspifi_flash; -extern struct flash_driver max32xxx_flash; -extern struct flash_driver mdr_flash; -extern struct flash_driver mrvlqspi_flash; -extern struct flash_driver msp432_flash; -extern struct flash_driver niietcm4_flash; -extern struct flash_driver nrf5_flash; -extern struct flash_driver nrf51_flash; -extern struct flash_driver numicro_flash; -extern struct flash_driver ocl_flash; -extern struct flash_driver pic32mx_flash; -extern struct flash_driver psoc4_flash; -extern struct flash_driver psoc5lp_flash; -extern struct flash_driver psoc5lp_eeprom_flash; -extern struct flash_driver psoc5lp_nvl_flash; -extern struct flash_driver psoc6_flash; -extern struct flash_driver sim3x_flash; -extern struct flash_driver stellaris_flash; -extern struct flash_driver stm32f1x_flash; -extern struct flash_driver stm32f2x_flash; -extern struct flash_driver stm32lx_flash; -extern struct flash_driver stm32l4x_flash; -extern struct flash_driver stm32h7x_flash; -extern struct flash_driver stmsmi_flash; -extern struct flash_driver str7x_flash; -extern struct flash_driver str9x_flash; -extern struct flash_driver str9xpec_flash; -extern struct flash_driver tms470_flash; -extern struct flash_driver virtual_flash; -extern struct flash_driver w600_flash; -extern struct flash_driver xcf_flash; -extern struct flash_driver xmc1xxx_flash; -extern struct flash_driver xmc4xxx_flash; +extern const struct flash_driver aduc702x_flash; +extern const struct flash_driver aducm360_flash; +extern const struct flash_driver ambiqmicro_flash; +extern const struct flash_driver at91sam3_flash; +extern const struct flash_driver at91sam4_flash; +extern const struct flash_driver at91sam4l_flash; +extern const struct flash_driver at91sam7_flash; +extern const struct flash_driver at91samd_flash; +extern const struct flash_driver ath79_flash; +extern const struct flash_driver atsame5_flash; +extern const struct flash_driver atsamv_flash; +extern const struct flash_driver avr_flash; +extern const struct flash_driver bluenrgx_flash; +extern const struct flash_driver cc3220sf_flash; +extern const struct flash_driver cc26xx_flash; +extern const struct flash_driver cfi_flash; +extern const struct flash_driver dsp5680xx_flash; +extern const struct flash_driver efm32_flash; +extern const struct flash_driver em357_flash; +extern const struct flash_driver esirisc_flash; +extern const struct flash_driver faux_flash; +extern const struct flash_driver fm3_flash; +extern const struct flash_driver fm4_flash; +extern const struct flash_driver fespi_flash; +extern const struct flash_driver jtagspi_flash; +extern const struct flash_driver kinetis_flash; +extern const struct flash_driver kinetis_ke_flash; +extern const struct flash_driver lpc2000_flash; +extern const struct flash_driver lpc288x_flash; +extern const struct flash_driver lpc2900_flash; +extern const struct flash_driver lpcspifi_flash; +extern const struct flash_driver max32xxx_flash; +extern const struct flash_driver mdr_flash; +extern const struct flash_driver mrvlqspi_flash; +extern const struct flash_driver msp432_flash; +extern const struct flash_driver niietcm4_flash; +extern const struct flash_driver nrf5_flash; +extern const struct flash_driver nrf51_flash; +extern const struct flash_driver numicro_flash; +extern const struct flash_driver ocl_flash; +extern const struct flash_driver pic32mx_flash; +extern const struct flash_driver psoc4_flash; +extern const struct flash_driver psoc5lp_flash; +extern const struct flash_driver psoc5lp_eeprom_flash; +extern const struct flash_driver psoc5lp_nvl_flash; +extern const struct flash_driver psoc6_flash; +extern const struct flash_driver sim3x_flash; +extern const struct flash_driver stellaris_flash; +extern const struct flash_driver stm32f1x_flash; +extern const struct flash_driver stm32f2x_flash; +extern const struct flash_driver stm32lx_flash; +extern const struct flash_driver stm32l4x_flash; +extern const struct flash_driver stm32h7x_flash; +extern const struct flash_driver stmsmi_flash; +extern const struct flash_driver str7x_flash; +extern const struct flash_driver str9x_flash; +extern const struct flash_driver str9xpec_flash; +extern const struct flash_driver tms470_flash; +extern const struct flash_driver virtual_flash; +extern const struct flash_driver w600_flash; +extern const struct flash_driver xcf_flash; +extern const struct flash_driver xmc1xxx_flash; +extern const struct flash_driver xmc4xxx_flash; /** * The list of built-in flash drivers. * @todo Make this dynamically extendable with loadable modules. */ -static struct flash_driver *flash_drivers[] = { +static const struct flash_driver * const flash_drivers[] = { &aduc702x_flash, &aducm360_flash, &ambiqmicro_flash, @@ -155,7 +155,7 @@ static struct flash_driver *flash_drivers[] = { NULL, }; -struct flash_driver *flash_driver_find_by_name(const char *name) +const struct flash_driver *flash_driver_find_by_name(const char *name) { for (unsigned i = 0; flash_drivers[i]; i++) { if (strcmp(name, flash_drivers[i]->name) == 0) diff --git a/src/flash/nor/dsp5680xx_flash.c b/src/flash/nor/dsp5680xx_flash.c index 38649ff04..37b60f001 100644 --- a/src/flash/nor/dsp5680xx_flash.c +++ b/src/flash/nor/dsp5680xx_flash.c @@ -256,7 +256,7 @@ static int dsp5680xx_flash_erase_check(struct flash_bank *bank) return retval; } -struct flash_driver dsp5680xx_flash = { +const struct flash_driver dsp5680xx_flash = { .name = "dsp5680xx_flash", .flash_bank_command = dsp5680xx_flash_bank_command, .erase = dsp5680xx_flash_erase, diff --git a/src/flash/nor/efm32.c b/src/flash/nor/efm32.c index 8ff689cc0..d2ac3a8fb 100644 --- a/src/flash/nor/efm32.c +++ b/src/flash/nor/efm32.c @@ -1120,7 +1120,7 @@ static const struct command_registration efm32x_command_handlers[] = { COMMAND_REGISTRATION_DONE }; -struct flash_driver efm32_flash = { +const struct flash_driver efm32_flash = { .name = "efm32", .commands = efm32x_command_handlers, .flash_bank_command = efm32x_flash_bank_command, diff --git a/src/flash/nor/em357.c b/src/flash/nor/em357.c index b14e0323c..e6b27283b 100644 --- a/src/flash/nor/em357.c +++ b/src/flash/nor/em357.c @@ -929,7 +929,7 @@ static const struct command_registration em357_command_handlers[] = { COMMAND_REGISTRATION_DONE }; -struct flash_driver em357_flash = { +const struct flash_driver em357_flash = { .name = "em357", .commands = em357_command_handlers, .flash_bank_command = em357_flash_bank_command, diff --git a/src/flash/nor/esirisc_flash.c b/src/flash/nor/esirisc_flash.c index 9e11571bd..948d001a0 100644 --- a/src/flash/nor/esirisc_flash.c +++ b/src/flash/nor/esirisc_flash.c @@ -571,7 +571,7 @@ static const struct command_registration esirisc_flash_command_handlers[] = { COMMAND_REGISTRATION_DONE }; -struct flash_driver esirisc_flash = { +const struct flash_driver esirisc_flash = { .name = "esirisc", .usage = "flash bank bank_id 'esirisc' base_address size_bytes 0 0 target " "cfg_address clock_hz wait_states", diff --git a/src/flash/nor/faux.c b/src/flash/nor/faux.c index d68940fc6..49b6dccd0 100644 --- a/src/flash/nor/faux.c +++ b/src/flash/nor/faux.c @@ -113,7 +113,7 @@ static const struct command_registration faux_command_handlers[] = { COMMAND_REGISTRATION_DONE }; -struct flash_driver faux_flash = { +const struct flash_driver faux_flash = { .name = "faux", .commands = faux_command_handlers, .flash_bank_command = faux_flash_bank_command, diff --git a/src/flash/nor/fespi.c b/src/flash/nor/fespi.c index ea47afd23..1c343a84c 100644 --- a/src/flash/nor/fespi.c +++ b/src/flash/nor/fespi.c @@ -1038,7 +1038,7 @@ static int get_fespi_info(struct flash_bank *bank, char *buf, int buf_size) return ERROR_OK; } -struct flash_driver fespi_flash = { +const struct flash_driver fespi_flash = { .name = "fespi", .flash_bank_command = fespi_flash_bank_command, .erase = fespi_erase, diff --git a/src/flash/nor/fm3.c b/src/flash/nor/fm3.c index 6c619775a..f2da2af8a 100644 --- a/src/flash/nor/fm3.c +++ b/src/flash/nor/fm3.c @@ -988,7 +988,7 @@ static const struct command_registration fm3_command_handlers[] = { COMMAND_REGISTRATION_DONE }; -struct flash_driver fm3_flash = { +const struct flash_driver fm3_flash = { .name = "fm3", .commands = fm3_command_handlers, .flash_bank_command = fm3_flash_bank_command, diff --git a/src/flash/nor/fm4.c b/src/flash/nor/fm4.c index 171cbd73e..a8877b4fb 100644 --- a/src/flash/nor/fm4.c +++ b/src/flash/nor/fm4.c @@ -702,7 +702,7 @@ static const struct command_registration fm4_command_handlers[] = { COMMAND_REGISTRATION_DONE }; -struct flash_driver fm4_flash = { +const struct flash_driver fm4_flash = { .name = "fm4", .commands = fm4_command_handlers, .flash_bank_command = fm4_flash_bank_command, diff --git a/src/flash/nor/jtagspi.c b/src/flash/nor/jtagspi.c index 0750fdfd5..a9f2dd4a4 100644 --- a/src/flash/nor/jtagspi.c +++ b/src/flash/nor/jtagspi.c @@ -427,7 +427,7 @@ static int jtagspi_info(struct flash_bank *bank, char *buf, int buf_size) return ERROR_OK; } -struct flash_driver jtagspi_flash = { +const struct flash_driver jtagspi_flash = { .name = "jtagspi", .flash_bank_command = jtagspi_flash_bank_command, .erase = jtagspi_erase, diff --git a/src/flash/nor/kinetis.c b/src/flash/nor/kinetis.c index d82735553..22c5d5c2d 100644 --- a/src/flash/nor/kinetis.c +++ b/src/flash/nor/kinetis.c @@ -393,7 +393,7 @@ static bool fcf_fopt_configured; static bool create_banks; -struct flash_driver kinetis_flash; +const struct flash_driver kinetis_flash; static int kinetis_write_inner(struct flash_bank *bank, const uint8_t *buffer, uint32_t offset, uint32_t count); static int kinetis_probe_chip(struct kinetis_chip *k_chip); @@ -3143,7 +3143,7 @@ static const struct command_registration kinetis_command_handler[] = { -struct flash_driver kinetis_flash = { +const struct flash_driver kinetis_flash = { .name = "kinetis", .commands = kinetis_command_handler, .flash_bank_command = kinetis_flash_bank_command, diff --git a/src/flash/nor/kinetis_ke.c b/src/flash/nor/kinetis_ke.c index 9441a9d64..27b6d3a83 100644 --- a/src/flash/nor/kinetis_ke.c +++ b/src/flash/nor/kinetis_ke.c @@ -1297,7 +1297,7 @@ static const struct command_registration kinetis_ke_command_handler[] = { COMMAND_REGISTRATION_DONE }; -struct flash_driver kinetis_ke_flash = { +const struct flash_driver kinetis_ke_flash = { .name = "kinetis_ke", .commands = kinetis_ke_command_handler, .flash_bank_command = kinetis_ke_flash_bank_command, diff --git a/src/flash/nor/lpc2000.c b/src/flash/nor/lpc2000.c index 58afd79ac..cb3f58e87 100644 --- a/src/flash/nor/lpc2000.c +++ b/src/flash/nor/lpc2000.c @@ -1609,7 +1609,7 @@ static const struct command_registration lpc2000_command_handlers[] = { COMMAND_REGISTRATION_DONE }; -struct flash_driver lpc2000_flash = { +const struct flash_driver lpc2000_flash = { .name = "lpc2000", .commands = lpc2000_command_handlers, .flash_bank_command = lpc2000_flash_bank_command, diff --git a/src/flash/nor/lpc288x.c b/src/flash/nor/lpc288x.c index afa8d7948..8852c859c 100644 --- a/src/flash/nor/lpc288x.c +++ b/src/flash/nor/lpc288x.c @@ -412,7 +412,7 @@ static int lpc288x_protect(struct flash_bank *bank, int set, int first, int last return ERROR_OK; } -struct flash_driver lpc288x_flash = { +const struct flash_driver lpc288x_flash = { .name = "lpc288x", .flash_bank_command = lpc288x_flash_bank_command, .erase = lpc288x_erase, diff --git a/src/flash/nor/lpc2900.c b/src/flash/nor/lpc2900.c index 022fb82a3..c798e4455 100644 --- a/src/flash/nor/lpc2900.c +++ b/src/flash/nor/lpc2900.c @@ -1581,7 +1581,7 @@ static int lpc2900_protect_check(struct flash_bank *bank) return lpc2900_read_security_status(bank); } -struct flash_driver lpc2900_flash = { +const struct flash_driver lpc2900_flash = { .name = "lpc2900", .commands = lpc2900_command_handlers, .flash_bank_command = lpc2900_flash_bank_command, diff --git a/src/flash/nor/lpcspifi.c b/src/flash/nor/lpcspifi.c index a7e65ec49..19d754b0f 100644 --- a/src/flash/nor/lpcspifi.c +++ b/src/flash/nor/lpcspifi.c @@ -946,7 +946,7 @@ static int get_lpcspifi_info(struct flash_bank *bank, char *buf, int buf_size) return ERROR_OK; } -struct flash_driver lpcspifi_flash = { +const struct flash_driver lpcspifi_flash = { .name = "lpcspifi", .flash_bank_command = lpcspifi_flash_bank_command, .erase = lpcspifi_erase, diff --git a/src/flash/nor/max32xxx.c b/src/flash/nor/max32xxx.c index ca037de4d..12e3db940 100644 --- a/src/flash/nor/max32xxx.c +++ b/src/flash/nor/max32xxx.c @@ -981,7 +981,7 @@ static const struct command_registration max32xxx_command_handlers[] = { COMMAND_REGISTRATION_DONE }; -struct flash_driver max32xxx_flash = { +const struct flash_driver max32xxx_flash = { .name = "max32xxx", .commands = max32xxx_command_handlers, .flash_bank_command = max32xxx_flash_bank_command, diff --git a/src/flash/nor/mdr.c b/src/flash/nor/mdr.c index c4a4458f9..379625994 100644 --- a/src/flash/nor/mdr.c +++ b/src/flash/nor/mdr.c @@ -609,7 +609,7 @@ static int get_mdr_info(struct flash_bank *bank, char *buf, int buf_size) return ERROR_OK; } -struct flash_driver mdr_flash = { +const struct flash_driver mdr_flash = { .name = "mdr", .usage = "flash bank mdr 0 0 \n" ": 0 for main memory, 1 for info memory", diff --git a/src/flash/nor/mrvlqspi.c b/src/flash/nor/mrvlqspi.c index cb2cfdbd5..803e84a91 100644 --- a/src/flash/nor/mrvlqspi.c +++ b/src/flash/nor/mrvlqspi.c @@ -953,7 +953,7 @@ FLASH_BANK_COMMAND_HANDLER(mrvlqspi_flash_bank_command) return ERROR_OK; } -struct flash_driver mrvlqspi_flash = { +const struct flash_driver mrvlqspi_flash = { .name = "mrvlqspi", .flash_bank_command = mrvlqspi_flash_bank_command, .erase = mrvlqspi_flash_erase, diff --git a/src/flash/nor/msp432.c b/src/flash/nor/msp432.c index e2e65d4f0..e9e4be33a 100644 --- a/src/flash/nor/msp432.c +++ b/src/flash/nor/msp432.c @@ -1075,7 +1075,7 @@ static const struct command_registration msp432_command_handlers[] = { COMMAND_REGISTRATION_DONE }; -struct flash_driver msp432_flash = { +const struct flash_driver msp432_flash = { .name = "msp432", .commands = msp432_command_handlers, .flash_bank_command = msp432_flash_bank_command, diff --git a/src/flash/nor/niietcm4.c b/src/flash/nor/niietcm4.c index f2f447004..b034ee127 100644 --- a/src/flash/nor/niietcm4.c +++ b/src/flash/nor/niietcm4.c @@ -1729,7 +1729,7 @@ static int get_niietcm4_info(struct flash_bank *bank, char *buf, int buf_size) } -struct flash_driver niietcm4_flash = { +const struct flash_driver niietcm4_flash = { .name = "niietcm4", .usage = "flash bank niietcm4 0 0 ", .commands = niietcm4_command_handlers, diff --git a/src/flash/nor/nrf5.c b/src/flash/nor/nrf5.c index 1e8dda393..aab80f9bc 100644 --- a/src/flash/nor/nrf5.c +++ b/src/flash/nor/nrf5.c @@ -1140,7 +1140,7 @@ static const struct command_registration nrf5_command_handlers[] = { COMMAND_REGISTRATION_DONE }; -struct flash_driver nrf5_flash = { +const struct flash_driver nrf5_flash = { .name = "nrf5", .commands = nrf5_command_handlers, .flash_bank_command = nrf5_flash_bank_command, @@ -1158,7 +1158,7 @@ struct flash_driver nrf5_flash = { /* We need to retain the flash-driver name as well as the commands * for backwards compatability */ -struct flash_driver nrf51_flash = { +const struct flash_driver nrf51_flash = { .name = "nrf51", .commands = nrf5_command_handlers, .flash_bank_command = nrf5_flash_bank_command, diff --git a/src/flash/nor/numicro.c b/src/flash/nor/numicro.c index ebf9d534f..8d8abd5ed 100644 --- a/src/flash/nor/numicro.c +++ b/src/flash/nor/numicro.c @@ -1871,7 +1871,7 @@ static const struct command_registration numicro_command_handlers[] = { COMMAND_REGISTRATION_DONE }; -struct flash_driver numicro_flash = { +const struct flash_driver numicro_flash = { .name = "numicro", .commands = numicro_command_handlers, .flash_bank_command = numicro_flash_bank_command, diff --git a/src/flash/nor/ocl.c b/src/flash/nor/ocl.c index acc464b0b..d2a659418 100644 --- a/src/flash/nor/ocl.c +++ b/src/flash/nor/ocl.c @@ -314,7 +314,7 @@ static int ocl_auto_probe(struct flash_bank *bank) return ERROR_OK; } -struct flash_driver ocl_flash = { +const struct flash_driver ocl_flash = { .name = "ocl", .flash_bank_command = ocl_flash_bank_command, .erase = ocl_erase, diff --git a/src/flash/nor/pic32mx.c b/src/flash/nor/pic32mx.c index 852a8bd6f..5ad4cb7e5 100644 --- a/src/flash/nor/pic32mx.c +++ b/src/flash/nor/pic32mx.c @@ -967,7 +967,7 @@ static const struct command_registration pic32mx_command_handlers[] = { COMMAND_REGISTRATION_DONE }; -struct flash_driver pic32mx_flash = { +const struct flash_driver pic32mx_flash = { .name = "pic32mx", .commands = pic32mx_command_handlers, .flash_bank_command = pic32mx_flash_bank_command, diff --git a/src/flash/nor/psoc4.c b/src/flash/nor/psoc4.c index 47d60dee4..0058f2dad 100644 --- a/src/flash/nor/psoc4.c +++ b/src/flash/nor/psoc4.c @@ -950,7 +950,7 @@ static const struct command_registration psoc4_command_handlers[] = { COMMAND_REGISTRATION_DONE }; -struct flash_driver psoc4_flash = { +const struct flash_driver psoc4_flash = { .name = "psoc4", .commands = psoc4_command_handlers, .flash_bank_command = psoc4_flash_bank_command, diff --git a/src/flash/nor/psoc5lp.c b/src/flash/nor/psoc5lp.c index 47567e766..66e2b071e 100644 --- a/src/flash/nor/psoc5lp.c +++ b/src/flash/nor/psoc5lp.c @@ -838,7 +838,7 @@ static const struct command_registration psoc5lp_nvl_command_handlers[] = { COMMAND_REGISTRATION_DONE }; -struct flash_driver psoc5lp_nvl_flash = { +const struct flash_driver psoc5lp_nvl_flash = { .name = "psoc5lp_nvl", .commands = psoc5lp_nvl_command_handlers, .flash_bank_command = psoc5lp_nvl_flash_bank_command, @@ -1036,7 +1036,7 @@ static const struct command_registration psoc5lp_eeprom_command_handlers[] = { COMMAND_REGISTRATION_DONE }; -struct flash_driver psoc5lp_eeprom_flash = { +const struct flash_driver psoc5lp_eeprom_flash = { .name = "psoc5lp_eeprom", .commands = psoc5lp_eeprom_command_handlers, .flash_bank_command = psoc5lp_eeprom_flash_bank_command, @@ -1548,7 +1548,7 @@ static const struct command_registration psoc5lp_command_handlers[] = { COMMAND_REGISTRATION_DONE }; -struct flash_driver psoc5lp_flash = { +const struct flash_driver psoc5lp_flash = { .name = "psoc5lp", .commands = psoc5lp_command_handlers, .flash_bank_command = psoc5lp_flash_bank_command, diff --git a/src/flash/nor/psoc6.c b/src/flash/nor/psoc6.c index 9352ad41b..386075e2c 100644 --- a/src/flash/nor/psoc6.c +++ b/src/flash/nor/psoc6.c @@ -1048,7 +1048,7 @@ static const struct command_registration psoc6_command_handlers[] = { COMMAND_REGISTRATION_DONE }; -struct flash_driver psoc6_flash = { +const struct flash_driver psoc6_flash = { .name = "psoc6", .commands = psoc6_command_handlers, .flash_bank_command = psoc6_flash_bank_command, diff --git a/src/flash/nor/sim3x.c b/src/flash/nor/sim3x.c index f282ba089..7ccf56b6e 100644 --- a/src/flash/nor/sim3x.c +++ b/src/flash/nor/sim3x.c @@ -1110,7 +1110,7 @@ static const struct command_registration sim3x_command_handlers[] = { COMMAND_REGISTRATION_DONE }; -struct flash_driver sim3x_flash = { +const struct flash_driver sim3x_flash = { .name = "sim3x", .commands = sim3x_command_handlers, .flash_bank_command = sim3x_flash_bank_command, diff --git a/src/flash/nor/stellaris.c b/src/flash/nor/stellaris.c index 8731f8b88..6b6f6e802 100644 --- a/src/flash/nor/stellaris.c +++ b/src/flash/nor/stellaris.c @@ -1441,7 +1441,7 @@ static const struct command_registration stellaris_command_handlers[] = { COMMAND_REGISTRATION_DONE }; -struct flash_driver stellaris_flash = { +const struct flash_driver stellaris_flash = { .name = "stellaris", .commands = stellaris_command_handlers, .flash_bank_command = stellaris_flash_bank_command, diff --git a/src/flash/nor/stm32f1x.c b/src/flash/nor/stm32f1x.c index cd060daae..d5d59c611 100644 --- a/src/flash/nor/stm32f1x.c +++ b/src/flash/nor/stm32f1x.c @@ -1570,7 +1570,7 @@ static const struct command_registration stm32x_command_handlers[] = { COMMAND_REGISTRATION_DONE }; -struct flash_driver stm32f1x_flash = { +const struct flash_driver stm32f1x_flash = { .name = "stm32f1x", .commands = stm32x_command_handlers, .flash_bank_command = stm32x_flash_bank_command, diff --git a/src/flash/nor/stm32f2x.c b/src/flash/nor/stm32f2x.c index 63c83479d..23f003085 100644 --- a/src/flash/nor/stm32f2x.c +++ b/src/flash/nor/stm32f2x.c @@ -1792,7 +1792,7 @@ static const struct command_registration stm32x_command_handlers[] = { COMMAND_REGISTRATION_DONE }; -struct flash_driver stm32f2x_flash = { +const struct flash_driver stm32f2x_flash = { .name = "stm32f2x", .commands = stm32x_command_handlers, .flash_bank_command = stm32x_flash_bank_command, diff --git a/src/flash/nor/stm32h7x.c b/src/flash/nor/stm32h7x.c index d21e9fa5e..ce89bb446 100644 --- a/src/flash/nor/stm32h7x.c +++ b/src/flash/nor/stm32h7x.c @@ -1114,7 +1114,7 @@ static const struct command_registration stm32x_command_handlers[] = { COMMAND_REGISTRATION_DONE }; -struct flash_driver stm32h7x_flash = { +const struct flash_driver stm32h7x_flash = { .name = "stm32h7x", .commands = stm32x_command_handlers, .flash_bank_command = stm32x_flash_bank_command, diff --git a/src/flash/nor/stm32l4x.c b/src/flash/nor/stm32l4x.c index 7d1e42984..3d4303bee 100644 --- a/src/flash/nor/stm32l4x.c +++ b/src/flash/nor/stm32l4x.c @@ -1053,7 +1053,7 @@ static const struct command_registration stm32l4_command_handlers[] = { COMMAND_REGISTRATION_DONE }; -struct flash_driver stm32l4x_flash = { +const struct flash_driver stm32l4x_flash = { .name = "stm32l4x", .commands = stm32l4_command_handlers, .flash_bank_command = stm32l4_flash_bank_command, diff --git a/src/flash/nor/stm32lx.c b/src/flash/nor/stm32lx.c index 814df8f6f..27780103e 100644 --- a/src/flash/nor/stm32lx.c +++ b/src/flash/nor/stm32lx.c @@ -944,7 +944,7 @@ static const struct command_registration stm32lx_command_handlers[] = { COMMAND_REGISTRATION_DONE }; -struct flash_driver stm32lx_flash = { +const struct flash_driver stm32lx_flash = { .name = "stm32lx", .commands = stm32lx_command_handlers, .flash_bank_command = stm32lx_flash_bank_command, diff --git a/src/flash/nor/stmsmi.c b/src/flash/nor/stmsmi.c index b55c8b90b..f56b9b7be 100644 --- a/src/flash/nor/stmsmi.c +++ b/src/flash/nor/stmsmi.c @@ -652,7 +652,7 @@ static int get_stmsmi_info(struct flash_bank *bank, char *buf, int buf_size) return ERROR_OK; } -struct flash_driver stmsmi_flash = { +const struct flash_driver stmsmi_flash = { .name = "stmsmi", .flash_bank_command = stmsmi_flash_bank_command, .erase = stmsmi_erase, diff --git a/src/flash/nor/str7x.c b/src/flash/nor/str7x.c index 015202a0e..eaef1970e 100644 --- a/src/flash/nor/str7x.c +++ b/src/flash/nor/str7x.c @@ -799,7 +799,7 @@ static const struct command_registration str7x_command_handlers[] = { COMMAND_REGISTRATION_DONE }; -struct flash_driver str7x_flash = { +const struct flash_driver str7x_flash = { .name = "str7x", .commands = str7x_command_handlers, .flash_bank_command = str7x_flash_bank_command, diff --git a/src/flash/nor/str9x.c b/src/flash/nor/str9x.c index 37700ce36..85cbe6a4f 100644 --- a/src/flash/nor/str9x.c +++ b/src/flash/nor/str9x.c @@ -667,7 +667,7 @@ static const struct command_registration str9x_command_handlers[] = { COMMAND_REGISTRATION_DONE }; -struct flash_driver str9x_flash = { +const struct flash_driver str9x_flash = { .name = "str9x", .commands = str9x_command_handlers, .flash_bank_command = str9x_flash_bank_command, diff --git a/src/flash/nor/str9xpec.c b/src/flash/nor/str9xpec.c index 29e0977bb..b618706b9 100644 --- a/src/flash/nor/str9xpec.c +++ b/src/flash/nor/str9xpec.c @@ -1195,7 +1195,7 @@ static const struct command_registration str9xpec_command_handlers[] = { COMMAND_REGISTRATION_DONE }; -struct flash_driver str9xpec_flash = { +const struct flash_driver str9xpec_flash = { .name = "str9xpec", .commands = str9xpec_command_handlers, .flash_bank_command = str9xpec_flash_bank_command, diff --git a/src/flash/nor/tcl.c b/src/flash/nor/tcl.c index 93c4d2846..6e216e68e 100644 --- a/src/flash/nor/tcl.c +++ b/src/flash/nor/tcl.c @@ -1107,7 +1107,7 @@ COMMAND_HANDLER(handle_flash_bank_command) } const char *driver_name = CMD_ARGV[0]; - struct flash_driver *driver = flash_driver_find_by_name(driver_name); + const struct flash_driver *driver = flash_driver_find_by_name(driver_name); if (NULL == driver) { /* no matching flash driver found */ LOG_ERROR("flash driver '%s' not found", driver_name); diff --git a/src/flash/nor/tms470.c b/src/flash/nor/tms470.c index 62fe2f54b..195d1ae1f 100644 --- a/src/flash/nor/tms470.c +++ b/src/flash/nor/tms470.c @@ -1162,7 +1162,7 @@ FLASH_BANK_COMMAND_HANDLER(tms470_flash_bank_command) return ERROR_OK; } -struct flash_driver tms470_flash = { +const struct flash_driver tms470_flash = { .name = "tms470", .commands = tms470_command_handlers, .flash_bank_command = tms470_flash_bank_command, diff --git a/src/flash/nor/virtual.c b/src/flash/nor/virtual.c index 217f7a4df..fa5153740 100644 --- a/src/flash/nor/virtual.c +++ b/src/flash/nor/virtual.c @@ -224,7 +224,7 @@ static int virtual_flash_read(struct flash_bank *bank, return ERROR_OK; } -struct flash_driver virtual_flash = { +const struct flash_driver virtual_flash = { .name = "virtual", .flash_bank_command = virtual_flash_bank_command, .erase = virtual_erase, diff --git a/src/flash/nor/w600.c b/src/flash/nor/w600.c index 3d3761617..3a6f3ff83 100644 --- a/src/flash/nor/w600.c +++ b/src/flash/nor/w600.c @@ -376,7 +376,7 @@ static int get_w600_info(struct flash_bank *bank, char *buf, int buf_size) return ERROR_OK; } -struct flash_driver w600_flash = { +const struct flash_driver w600_flash = { .name = "w600", .flash_bank_command = w600_flash_bank_command, .erase = w600_erase, diff --git a/src/flash/nor/xcf.c b/src/flash/nor/xcf.c index bc4b1be5e..a0c35c5e5 100644 --- a/src/flash/nor/xcf.c +++ b/src/flash/nor/xcf.c @@ -881,7 +881,7 @@ static const struct command_registration xcf_command_handlers[] = { COMMAND_REGISTRATION_DONE }; -struct flash_driver xcf_flash = { +const struct flash_driver xcf_flash = { .name = "xcf", .usage = NULL, .commands = xcf_command_handlers, diff --git a/src/flash/nor/xmc1xxx.c b/src/flash/nor/xmc1xxx.c index 262300cc8..758977190 100644 --- a/src/flash/nor/xmc1xxx.c +++ b/src/flash/nor/xmc1xxx.c @@ -534,7 +534,7 @@ static const struct command_registration xmc1xxx_command_handlers[] = { COMMAND_REGISTRATION_DONE }; -struct flash_driver xmc1xxx_flash = { +const struct flash_driver xmc1xxx_flash = { .name = "xmc1xxx", .commands = xmc1xxx_command_handlers, .flash_bank_command = xmc1xxx_flash_bank_command, diff --git a/src/flash/nor/xmc4xxx.c b/src/flash/nor/xmc4xxx.c index d862e857e..c56adb500 100644 --- a/src/flash/nor/xmc4xxx.c +++ b/src/flash/nor/xmc4xxx.c @@ -1343,7 +1343,7 @@ static const struct command_registration xmc4xxx_command_handlers[] = { COMMAND_REGISTRATION_DONE }; -struct flash_driver xmc4xxx_flash = { +const struct flash_driver xmc4xxx_flash = { .name = "xmc4xxx", .commands = xmc4xxx_command_handlers, .flash_bank_command = xmc4xxx_flash_bank_command, From 16432e681e0d776d7f40f14ad0aed3f7e17b848b Mon Sep 17 00:00:00 2001 From: Tomas Vanek Date: Thu, 7 Feb 2019 14:18:17 +0100 Subject: [PATCH 67/70] target/cortex_m: simplify cortex_m_unset_breakpoint() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cortex-M uses only 2 byte breakpoint instruction. cortex_m_unset_breakpoint() does not need to check breakpoint->length, use the length as the size argument in target_write_memory() Change-Id: I20bb869f6abce2fc61f0469e34a638bc4dc6f7ce Signed-off-by: Tomas Vanek Reviewed-on: http://openocd.zylin.com/4889 Tested-by: jenkins Reviewed-by: Matthias Welwarsky Reviewed-by: Jānis Skujenieks Reviewed-by: Christopher Head --- src/target/cortex_m.c | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/src/target/cortex_m.c b/src/target/cortex_m.c index 4bada398d..8223de77f 100644 --- a/src/target/cortex_m.c +++ b/src/target/cortex_m.c @@ -1260,17 +1260,11 @@ int cortex_m_unset_breakpoint(struct target *target, struct breakpoint *breakpoi comparator_list[fp_num].fpcr_value); } else { /* restore original instruction (kept in target endianness) */ - if (breakpoint->length == 4) { - retval = target_write_memory(target, breakpoint->address & 0xFFFFFFFE, 4, 1, + retval = target_write_memory(target, breakpoint->address & 0xFFFFFFFE, + breakpoint->length, 1, breakpoint->orig_instr); - if (retval != ERROR_OK) - return retval; - } else { - retval = target_write_memory(target, breakpoint->address & 0xFFFFFFFE, 2, 1, - breakpoint->orig_instr); - if (retval != ERROR_OK) - return retval; - } + if (retval != ERROR_OK) + return retval; } breakpoint->set = false; From 4db5299b5bd2c3e853f7383c076f9726dc588680 Mon Sep 17 00:00:00 2001 From: Tomas Vanek Date: Thu, 24 Jan 2019 13:36:39 +0100 Subject: [PATCH 68/70] target/cortex_m: remove fp_code_available counting MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit fp_code_available looses sync with the real number of free comparators as soon as cortex_m_set_breakpoint() returns an error. Remove the counter and always go through the fp_comparator_list to find a free one. Change-Id: I9f6e06c36d8a57ad11df5155e8a1a3aff6d833a5 Signed-off-by: Tomas Vanek Reviewed-on: http://openocd.zylin.com/4870 Tested-by: jenkins Reviewed-by: Jānis Skujenieks Reviewed-by: Christopher Head Reviewed-by: Matthias Welwarsky --- src/target/cortex_m.c | 18 +----------------- src/target/cortex_m.h | 1 - 2 files changed, 1 insertion(+), 18 deletions(-) diff --git a/src/target/cortex_m.c b/src/target/cortex_m.c index 8223de77f..8c43016cb 100644 --- a/src/target/cortex_m.c +++ b/src/target/cortex_m.c @@ -1164,7 +1164,7 @@ int cortex_m_set_breakpoint(struct target *target, struct breakpoint *breakpoint fp_num++; if (fp_num >= cortex_m->fp_num_code) { LOG_ERROR("Can not find free FPB Comparator!"); - return ERROR_FAIL; + return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; } breakpoint->set = fp_num + 1; fpcr_value = breakpoint->address | 1; @@ -1273,13 +1273,6 @@ int cortex_m_unset_breakpoint(struct target *target, struct breakpoint *breakpoi int cortex_m_add_breakpoint(struct target *target, struct breakpoint *breakpoint) { - struct cortex_m_common *cortex_m = target_to_cm(target); - - if ((breakpoint->type == BKPT_HARD) && (cortex_m->fp_code_available < 1)) { - LOG_INFO("no flash patch comparator unit available for hardware breakpoint"); - return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; - } - if (breakpoint->length == 3) { LOG_DEBUG("Using a two byte breakpoint for 32bit Thumb-2 request"); breakpoint->length = 2; @@ -1290,16 +1283,11 @@ int cortex_m_add_breakpoint(struct target *target, struct breakpoint *breakpoint return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; } - if (breakpoint->type == BKPT_HARD) - cortex_m->fp_code_available--; - return cortex_m_set_breakpoint(target, breakpoint); } int cortex_m_remove_breakpoint(struct target *target, struct breakpoint *breakpoint) { - struct cortex_m_common *cortex_m = target_to_cm(target); - /* REVISIT why check? FPB can be updated with core running ... */ if (target->state != TARGET_HALTED) { LOG_WARNING("target not halted"); @@ -1309,9 +1297,6 @@ int cortex_m_remove_breakpoint(struct target *target, struct breakpoint *breakpo if (breakpoint->set) cortex_m_unset_breakpoint(target, breakpoint); - if (breakpoint->type == BKPT_HARD) - cortex_m->fp_code_available++; - return ERROR_OK; } @@ -2121,7 +2106,6 @@ int cortex_m_examine(struct target *target) /* bits [14:12] and [7:4] */ cortex_m->fp_num_code = ((fpcr >> 8) & 0x70) | ((fpcr >> 4) & 0xF); cortex_m->fp_num_lit = (fpcr >> 8) & 0xF; - cortex_m->fp_code_available = cortex_m->fp_num_code; /* Detect flash patch revision, see RM DDI 0403E.b page C1-817. Revision is zero base, fp_rev == 1 means Rev.2 ! */ cortex_m->fp_rev = (fpcr >> 28) & 0xf; diff --git a/src/target/cortex_m.h b/src/target/cortex_m.h index b375d1111..4b207467e 100644 --- a/src/target/cortex_m.h +++ b/src/target/cortex_m.h @@ -172,7 +172,6 @@ struct cortex_m_common { /* Flash Patch and Breakpoint (FPB) */ int fp_num_lit; int fp_num_code; - int fp_code_available; int fp_rev; bool fpb_enabled; struct cortex_m_fp_comparator *fp_comparator_list; From d73de4c07c726fb0dc86f6ee6bac53fccbd62a87 Mon Sep 17 00:00:00 2001 From: Tomas Vanek Date: Wed, 6 Feb 2019 19:07:15 +0100 Subject: [PATCH 69/70] target/cortex_m: remove target halted check when removing a breakpoint MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Remove the target halted check from cortex_m_remove_breakpoint() as there is no such check in cortex_m_set_breakpoint() and bp can be safely removed from the running target. While on it return the error code from cortex_m_unset_breakpoint() to higher level. Change-Id: I2b358c3661feed84297913e9f589bdf1e4de7e64 Signed-off-by: Tomas Vanek Reviewed-on: http://openocd.zylin.com/4887 Tested-by: jenkins Reviewed-by: Matthias Welwarsky Reviewed-by: Jānis Skujenieks Reviewed-by: Christopher Head --- src/target/cortex_m.c | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/src/target/cortex_m.c b/src/target/cortex_m.c index 8c43016cb..d341d4572 100644 --- a/src/target/cortex_m.c +++ b/src/target/cortex_m.c @@ -1288,16 +1288,10 @@ int cortex_m_add_breakpoint(struct target *target, struct breakpoint *breakpoint int cortex_m_remove_breakpoint(struct target *target, struct breakpoint *breakpoint) { - /* REVISIT why check? FPB can be updated with core running ... */ - if (target->state != TARGET_HALTED) { - LOG_WARNING("target not halted"); - return ERROR_TARGET_NOT_HALTED; - } + if (!breakpoint->set) + return ERROR_OK; - if (breakpoint->set) - cortex_m_unset_breakpoint(target, breakpoint); - - return ERROR_OK; + return cortex_m_unset_breakpoint(target, breakpoint); } int cortex_m_set_watchpoint(struct target *target, struct watchpoint *watchpoint) From 11a2bfc2bcedfad0ecb1b8d7f68ac7208cd6b8c0 Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Sat, 30 Mar 2019 18:20:07 -0700 Subject: [PATCH 70/70] armv7a_mmu: Remove warning on va = pa Depending on how the MMU is configured it is possible to have a 1:1 mapping between virtual and physical addresses, thus making this warning bogus. We already check that the MMU is enabled in the caller: cortex_a_virt2phys(). Change-Id: I09f4c53ef933c8d1e268da5215a769449be014bc Signed-off-by: Florian Fainelli Reviewed-on: http://openocd.zylin.com/5007 Tested-by: jenkins Reviewed-by: Antonio Borneo Reviewed-by: Kamal Dasu Reviewed-by: Matthias Welwarsky --- src/target/armv7a_mmu.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/target/armv7a_mmu.c b/src/target/armv7a_mmu.c index 23d201f7b..153bfccf2 100644 --- a/src/target/armv7a_mmu.c +++ b/src/target/armv7a_mmu.c @@ -152,8 +152,6 @@ int armv7a_mmu_translate_va_pa(struct target *target, uint32_t va, if (retval != ERROR_OK) goto done; *val = (*val & ~0xfff) + (va & 0xfff); - if (*val == va) - LOG_WARNING("virt = phys : MMU disable !!"); if (meminfo) { LOG_INFO("%" PRIx32 " : %" PRIx32 " %s outer shareable %s secured", va, *val,