diff --git a/config_subdir.m4 b/config_subdir.m4 index 45a1c6c4f..2be590e44 100644 --- a/config_subdir.m4 +++ b/config_subdir.m4 @@ -7,6 +7,6 @@ AC_DEFUN([AX_CONFIG_SUBDIR_OPTION], AC_CONFIG_SUBDIRS([$1]) m4_ifblank([$2], [rm -f $srcdir/$1/configure.gnu], -[echo -e '#!/bin/sh\nexec "`dirname "'\$'0"`/configure" $2 "'\$'@"' > "$srcdir/$1/configure.gnu" +[echo -e '#!/bin/sh\nexec "`dirname "'\$'0"`/configure" '"$2"' "'\$'@"' > "$srcdir/$1/configure.gnu" ]) ]) diff --git a/configure.ac b/configure.ac index f70dc2fb5..066c14b93 100644 --- a/configure.ac +++ b/configure.ac @@ -355,6 +355,10 @@ AC_ARG_ENABLE([internal-jimtcl], AS_HELP_STRING([--disable-internal-jimtcl], [Disable building internal jimtcl]), [use_internal_jimtcl=$enableval], [use_internal_jimtcl=yes]) +AC_ARG_ENABLE([jimtcl-maintainer], + AS_HELP_STRING([--enable-jimtcl-maintainer], [Enable maintainer mode when building internal jimtcl]), + [use_internal_jimtcl_maintainer=$enableval], [use_internal_jimtcl_maintainer=no]) + AC_ARG_ENABLE([internal-libjaylink], AS_HELP_STRING([--disable-internal-libjaylink], [Disable building internal libjaylink]), @@ -551,7 +555,12 @@ AS_IF([test "x$enable_buspirate" != "xno"], [ AS_IF([test "x$use_internal_jimtcl" = "xyes"], [ AS_IF([test -f "$srcdir/jimtcl/configure.ac"], [ - AX_CONFIG_SUBDIR_OPTION([jimtcl], [--disable-install-jim]) + AS_IF([test "x$use_internal_jimtcl_maintainer" = "xyes"], [ + jimtcl_config_options="--disable-install-jim --maintainer" + ], [ + jimtcl_config_options="--disable-install-jim" + ]) + AX_CONFIG_SUBDIR_OPTION([jimtcl], [$jimtcl_config_options]) ], [ AC_MSG_ERROR([jimtcl not found, run git submodule init and git submodule update.]) ]) diff --git a/contrib/rpc_examples/ocd_rpc_example.py b/contrib/rpc_examples/ocd_rpc_example.py index 3470d848b..e6146f617 100755 --- a/contrib/rpc_examples/ocd_rpc_example.py +++ b/contrib/rpc_examples/ocd_rpc_example.py @@ -95,24 +95,16 @@ class OpenOcd: return None if (len(raw) < 2) else strToHex(raw[1]) def readMemory(self, wordLen, address, n): - self.send("array unset output") # better to clear the array before - self.send("mem2array output %d 0x%x %d" % (wordLen, address, n)) - - output = [*map(int, self.send("return $output").split(" "))] - d = dict([tuple(output[i:i + 2]) for i in range(0, len(output), 2)]) - - return [d[k] for k in sorted(d.keys())] + output = self.send("read_memory 0x%x %d %d" % (address, wordLen, n)) + return [*map(lambda x: int(x, 16), output.split(" "))] def writeVariable(self, address, value): assert value is not None self.send("mww 0x%x 0x%x" % (address, value)) - def writeMemory(self, wordLen, address, n, data): - array = " ".join(["%d 0x%x" % (a, b) for a, b in enumerate(data)]) - - self.send("array unset 1986ве1т") # better to clear the array before - self.send("array set 1986ве1т { %s }" % array) - self.send("array2mem 1986ве1т 0x%x %s %d" % (wordLen, address, n)) + def writeMemory(self, wordLen, address, data): + data = "{" + ' '.join(['0x%x' % x for x in data]) + "}" + self.send("write_memory 0x%x %d %s" % (address, wordLen, data)) if __name__ == "__main__": diff --git a/doc/openocd.texi b/doc/openocd.texi index f826a0b7f..a4fa6847e 100644 --- a/doc/openocd.texi +++ b/doc/openocd.texi @@ -4980,27 +4980,76 @@ use these to deal with specific reset cases. They are not otherwise documented here. @end deffn -@deffn {Command} {$target_name array2mem} arrayname width address count -@deffnx {Command} {$target_name mem2array} arrayname width address count -These provide an efficient script-oriented interface to memory. -The @code{array2mem} primitive writes bytes, halfwords, words -or double-words; while @code{mem2array} reads them. -In both cases, the TCL side uses an array, and -the target side uses raw memory. - -The efficiency comes from enabling the use of -bulk JTAG data transfer operations. -The script orientation comes from working with data -values that are packaged for use by TCL scripts; -@command{mdw} type primitives only print data they retrieve, -and neither store nor return those values. +@deffn {Command} {$target_name set_reg} dict +Set register values of the target. @itemize -@item @var{arrayname} ... is the name of an array variable -@item @var{width} ... is 8/16/32/64 - indicating the memory access size -@item @var{address} ... is the target memory address -@item @var{count} ... is the number of elements to process +@item @var{dict} ... Tcl dictionary with pairs of register names and values. @end itemize + +For example, the following command sets the value 0 to the program counter (pc) +register and 0x1000 to the stack pointer (sp) register: + +@example +set_reg @{pc 0 sp 0x1000@} +@end example +@end deffn + +@deffn {Command} {$target_name get_reg} [-force] list +Get register values from the target and return them as Tcl dictionary with pairs +of register names and values. +If option "-force" is set, the register values are read directly from the +target, bypassing any caching. + +@itemize +@item @var{list} ... List of register names +@end itemize + +For example, the following command retrieves the values from the program +counter (pc) and stack pointer (sp) register: + +@example +get_reg @{pc sp@} +@end example +@end deffn + +@deffn {Command} {$target_name write_memory} address width data ['phys'] +This function provides an efficient way to write to the target memory from a Tcl +script. + +@itemize +@item @var{address} ... target memory address +@item @var{width} ... memory access bit size, can be 8, 16, 32 or 64 +@item @var{data} ... Tcl list with the elements to write +@item ['phys'] ... treat the memory address as physical instead of virtual address +@end itemize + +For example, the following command writes two 32 bit words into the target +memory at address 0x20000000: + +@example +write_memory 0x20000000 32 @{0xdeadbeef 0x00230500@} +@end example +@end deffn + +@deffn {Command} {$target_name read_memory} address width count ['phys'] +This function provides an efficient way to read the target memory from a Tcl +script. +A Tcl list containing the requested memory elements is returned by this function. + +@itemize +@item @var{address} ... target memory address +@item @var{width} ... memory access bit size, can be 8, 16, 32 or 64 +@item @var{count} ... number of elements to read +@item ['phys'] ... treat the memory address as physical instead of virtual address +@end itemize + +For example, the following command reads two 32 bit words from the target +memory at address 0x20000000: + +@example +read_memory 0x20000000 32 2 +@end example @end deffn @deffn {Command} {$target_name cget} queryparm @@ -5070,8 +5119,8 @@ When the current target has an MMU which is present and active, Otherwise, or if the optional @var{phys} flag is specified, @var{addr} is interpreted as a physical address. If @var{count} is specified, displays that many units. -(If you want to manipulate the data instead of displaying it, -see the @code{mem2array} primitives.) +(If you want to process the data instead of displaying it, +see the @code{read_memory} primitives.) @end deffn @deffn {Command} {$target_name mwd} [phys] addr doubleword [count] @@ -8491,6 +8540,78 @@ Debug and trace infrastructure: @end example @end deffn +@deffn {Command} {set_reg} dict +Set register values of the target. + +@itemize +@item @var{dict} ... Tcl dictionary with pairs of register names and values. +@end itemize + +For example, the following command sets the value 0 to the program counter (pc) +register and 0x1000 to the stack pointer (sp) register: + +@example +set_reg @{pc 0 sp 0x1000@} +@end example +@end deffn + +@deffn {Command} {get_reg} [-force] list +Get register values from the target and return them as Tcl dictionary with pairs +of register names and values. +If option "-force" is set, the register values are read directly from the +target, bypassing any caching. + +@itemize +@item @var{list} ... List of register names +@end itemize + +For example, the following command retrieves the values from the program +counter (pc) and stack pointer (sp) register: + +@example +get_reg @{pc sp@} +@end example +@end deffn + +@deffn {Command} {write_memory} address width data ['phys'] +This function provides an efficient way to write to the target memory from a Tcl +script. + +@itemize +@item @var{address} ... target memory address +@item @var{width} ... memory access bit size, can be 8, 16, 32 or 64 +@item @var{data} ... Tcl list with the elements to write +@item ['phys'] ... treat the memory address as physical instead of virtual address +@end itemize + +For example, the following command writes two 32 bit words into the target +memory at address 0x20000000: + +@example +write_memory 0x20000000 32 @{0xdeadbeef 0x00230500@} +@end example +@end deffn + +@deffn {Command} {read_memory} address width count ['phys'] +This function provides an efficient way to read the target memory from a Tcl +script. +A Tcl list containing the requested memory elements is returned by this function. + +@itemize +@item @var{address} ... target memory address +@item @var{width} ... memory access bit size, can be 8, 16, 32 or 64 +@item @var{count} ... number of elements to read +@item ['phys'] ... treat the memory address as physical instead of virtual address +@end itemize + +For example, the following command reads two 32 bit words from the target +memory at address 0x20000000: + +@example +read_memory 0x20000000 32 2 +@end example +@end deffn + @deffn {Command} {halt} [ms] @deffnx {Command} {wait_halt} [ms] The @command{halt} command first sends a halt request to the target, @@ -8628,8 +8749,8 @@ When the current target has an MMU which is present and active, Otherwise, or if the optional @var{phys} flag is specified, @var{addr} is interpreted as a physical address. If @var{count} is specified, displays that many units. -(If you want to manipulate the data instead of displaying it, -see the @code{mem2array} primitives.) +(If you want to process the data instead of displaying it, +see the @code{read_memory} primitives.) @end deffn @deffn {Command} {mwd} [phys] addr doubleword [count] @@ -9249,6 +9370,17 @@ requests by using a special SVC instruction that is trapped at the Supervisor Call vector by OpenOCD. @end deffn +@deffn {Command} {arm semihosting_redirect} (@option{disable} | @option{tcp} +[@option{debug}|@option{stdio}|@option{all}) +@cindex ARM semihosting +Redirect semihosting messages to a specified TCP port. + +This command redirects debug (READC, WRITEC and WRITE0) and stdio (READ, WRITE) +semihosting operations to the specified TCP port. +The command allows to select which type of operations to redirect (debug, stdio, all (default)). +Note: for stdio operations, only I/O from/to ':tt' file descriptors are redirected. +@end deffn + @deffn {Command} {arm semihosting_cmdline} [@option{enable}|@option{disable}] @cindex ARM semihosting Set the command line to be passed to the debugger. @@ -11584,13 +11716,7 @@ should be passed in to the proc in question. By "low-level", we mean commands that a human would typically not invoke directly. -@itemize @bullet -@item @b{mem2array} <@var{varname}> <@var{width}> <@var{addr}> <@var{nelems}> - -Read memory and return as a Tcl array for script processing -@item @b{array2mem} <@var{varname}> <@var{width}> <@var{addr}> <@var{nelems}> - -Convert a Tcl array to memory locations and write the values +@itemize @item @b{flash banks} <@var{driver}> <@var{base}> <@var{size}> <@var{chip_width}> <@var{bus_width}> <@var{target}> [@option{driver options} ...] Return information about the flash banks diff --git a/src/flash/nor/efm32.c b/src/flash/nor/efm32.c index 653878ae7..2c5a5020e 100644 --- a/src/flash/nor/efm32.c +++ b/src/flash/nor/efm32.c @@ -257,23 +257,19 @@ static int efm32x_write_reg_u32(struct flash_bank *bank, target_addr_t offset, static int efm32x_read_info(struct flash_bank *bank) { int ret; - uint32_t cpuid = 0; struct efm32x_flash_chip *efm32x_info = bank->driver_priv; struct efm32_info *efm32_info = &(efm32x_info->info); memset(efm32_info, 0, sizeof(struct efm32_info)); - ret = target_read_u32(bank->target, CPUID, &cpuid); - if (ret != ERROR_OK) - return ret; + const struct cortex_m_common *cortex_m = target_to_cm(bank->target); - if (((cpuid >> 4) & 0xfff) == 0xc23) { - /* Cortex-M3 device */ - } else if (((cpuid >> 4) & 0xfff) == 0xc24) { - /* Cortex-M4 device (WONDER GECKO) */ - } else if (((cpuid >> 4) & 0xfff) == 0xc60) { - /* Cortex-M0+ device */ - } else { + switch (cortex_m->core_info->partno) { + case CORTEX_M3_PARTNO: + case CORTEX_M4_PARTNO: + case CORTEX_M0P_PARTNO: + break; + default: LOG_ERROR("Target is not Cortex-Mx Device"); return ERROR_FAIL; } diff --git a/src/flash/nor/sim3x.c b/src/flash/nor/sim3x.c index 2938ed1ab..891383860 100644 --- a/src/flash/nor/sim3x.c +++ b/src/flash/nor/sim3x.c @@ -983,7 +983,7 @@ COMMAND_HANDLER(sim3x_lock) if (!dap) { /* Used debug interface doesn't support direct DAP access */ - LOG_INFO("Target can't by unlocked by this debug interface"); + LOG_INFO("Target can't be unlocked by this debug interface"); /* Core check */ ret = target_read_u32(target, CPUID, &val); diff --git a/src/flash/nor/stm32f1x.c b/src/flash/nor/stm32f1x.c index 29a3b7e06..6972bae2d 100644 --- a/src/flash/nor/stm32f1x.c +++ b/src/flash/nor/stm32f1x.c @@ -592,10 +592,7 @@ static int stm32x_write(struct flash_bank *bank, const uint8_t *buffer, LOG_WARNING("couldn't use block writes, falling back to single memory accesses"); while (words_remaining > 0) { - uint16_t value; - memcpy(&value, buffer, sizeof(uint16_t)); - - retval = target_write_u16(target, bank->base + offset, value); + retval = target_write_memory(target, bank->base + offset, 2, 1, buffer); if (retval != ERROR_OK) goto reset_pg_and_lock; diff --git a/src/flash/nor/stm32f2x.c b/src/flash/nor/stm32f2x.c index 58edca7e1..622ef3423 100644 --- a/src/flash/nor/stm32f2x.c +++ b/src/flash/nor/stm32f2x.c @@ -856,15 +856,12 @@ static int stm32x_write(struct flash_bank *bank, const uint8_t *buffer, Wait for the BSY bit to be cleared */ while (words_remaining > 0) { - uint16_t value; - memcpy(&value, buffer + bytes_written, sizeof(uint16_t)); - retval = target_write_u32(target, stm32x_get_flash_reg(bank, STM32_FLASH_CR), FLASH_PG | FLASH_PSIZE_16); if (retval != ERROR_OK) return retval; - retval = target_write_u16(target, address, value); + retval = target_write_memory(target, address, 2, 1, buffer + bytes_written); if (retval != ERROR_OK) return retval; diff --git a/src/flash/nor/stm32h7x.c b/src/flash/nor/stm32h7x.c index 6d3149f94..d2914eb39 100644 --- a/src/flash/nor/stm32h7x.c +++ b/src/flash/nor/stm32h7x.c @@ -531,6 +531,7 @@ static int stm32x_protect(struct flash_bank *bank, int set, unsigned int first, unsigned int last) { struct target *target = bank->target; + struct stm32h7x_flash_bank *stm32x_info = bank->driver_priv; uint32_t protection; if (target->state != TARGET_HALTED) { @@ -553,7 +554,7 @@ static int stm32x_protect(struct flash_bank *bank, int set, unsigned int first, } /* apply WRPSN mask */ - protection &= 0xff; + protection &= stm32x_info->part_info->wps_mask; LOG_DEBUG("stm32x_protect, option_bytes written WPSN 0x%" PRIx32, protection); diff --git a/src/flash/nor/stm32l4x.c b/src/flash/nor/stm32l4x.c index fd0338899..7b35a0635 100644 --- a/src/flash/nor/stm32l4x.c +++ b/src/flash/nor/stm32l4x.c @@ -1757,7 +1757,7 @@ static int stm32l4_probe(struct flash_bank *bank) * Ask the flash infrastructure to ensure required alignment */ bank->write_start_alignment = bank->write_end_alignment = stm32l4_info->data_width; - /* initialise the flash registers layout */ + /* Initialize the flash registers layout */ if (part_info->flags & F_HAS_L5_FLASH_REGS) stm32l4_info->flash_regs = stm32l5_ns_flash_regs; else @@ -1770,7 +1770,7 @@ static int stm32l4_probe(struct flash_bank *bank) stm32l4_sync_rdp_tzen(bank); - /* for devices with trustzone, use flash secure registers when TZEN=1 and RDP is LEVEL_0 */ + /* for devices with TrustZone, use flash secure registers when TZEN=1 and RDP is LEVEL_0 */ if (stm32l4_info->tzen && (stm32l4_info->rdp == RDP_LEVEL_0)) { if (part_info->flags & F_HAS_L5_FLASH_REGS) { stm32l4_info->flash_regs_base |= STM32L5_REGS_SEC_OFFSET; @@ -2046,8 +2046,19 @@ static int stm32l4_auto_probe(struct flash_bank *bank) if (stm32l4_info->probed) { uint32_t optr_cur; + /* save flash_regs_base */ + uint32_t saved_flash_regs_base = stm32l4_info->flash_regs_base; + + /* for devices with TrustZone, use NS flash registers to read OPTR */ + if (stm32l4_info->part_info->flags & F_HAS_L5_FLASH_REGS) + stm32l4_info->flash_regs_base &= ~STM32L5_REGS_SEC_OFFSET; + /* read flash option register and re-probe if optr value is changed */ int retval = stm32l4_read_flash_reg_by_index(bank, STM32_FLASH_OPTR_INDEX, &optr_cur); + + /* restore saved flash_regs_base */ + stm32l4_info->flash_regs_base = saved_flash_regs_base; + if (retval != ERROR_OK) return retval; diff --git a/src/helper/bits.h b/src/helper/bits.h index 00d3c0270..6151b3340 100644 --- a/src/helper/bits.h +++ b/src/helper/bits.h @@ -28,8 +28,12 @@ #include #define BIT(nr) (1UL << (nr)) +#define BIT_ULL(nr) (1ULL << (nr)) #define BITS_PER_BYTE 8 #define BITS_PER_LONG (BITS_PER_BYTE * sizeof(long)) +#define BITS_PER_LONG_LONG (BITS_PER_BYTE * sizeof(long long)) +#define GENMASK(h, l) (((~0UL) - (1UL << (l)) + 1) & (~0UL >> (BITS_PER_LONG - 1 - (h)))) +#define GENMASK_ULL(h, l) (((~0ULL) - (1ULL << (l)) + 1) & (~0ULL >> (BITS_PER_LONG_LONG - 1 - (h)))) #define BITS_TO_LONGS(nr) DIV_ROUND_UP(nr, BITS_PER_BYTE * sizeof(long)) #define BIT_MASK(nr) (1UL << ((nr) % BITS_PER_LONG)) #define BIT_WORD(nr) ((nr) / BITS_PER_LONG) diff --git a/src/helper/jim-nvp.c b/src/helper/jim-nvp.c index 738ed7943..0409a83cd 100644 --- a/src/helper/jim-nvp.c +++ b/src/helper/jim-nvp.c @@ -41,6 +41,10 @@ * official policies, either expressed or implied, of the Jim Tcl Project. */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include "jim-nvp.h" #include diff --git a/src/helper/log.c b/src/helper/log.c index 686560742..106d22867 100644 --- a/src/helper/log.c +++ b/src/helper/log.c @@ -30,6 +30,7 @@ #include "command.h" #include "replacements.h" #include "time_support.h" +#include #include @@ -47,7 +48,6 @@ static FILE *log_output; static struct log_callback *log_callbacks; static int64_t last_time; -static int64_t current_time; static int64_t start; @@ -111,32 +111,27 @@ static void log_puts(enum log_levels level, if (f) file = f + 1; - if (strlen(string) > 0) { - if (debug_level >= LOG_LVL_DEBUG) { - /* print with count and time information */ - int64_t t = timeval_ms() - start; + if (debug_level >= LOG_LVL_DEBUG) { + /* print with count and time information */ + int64_t t = timeval_ms() - start; #ifdef _DEBUG_FREE_SPACE_ - struct mallinfo info; - info = mallinfo(); + struct mallinfo info; + info = mallinfo(); #endif - fprintf(log_output, "%s%d %" PRId64 " %s:%d %s()" + fprintf(log_output, "%s%d %" PRId64 " %s:%d %s()" #ifdef _DEBUG_FREE_SPACE_ - " %d" + " %d" #endif - ": %s", log_strings[level + 1], count, t, file, line, function, + ": %s", log_strings[level + 1], count, t, file, line, function, #ifdef _DEBUG_FREE_SPACE_ - info.fordblks, + info.fordblks, #endif - string); - } else { - /* if we are using gdb through pipes then we do not want any output - * to the pipe otherwise we get repeated strings */ - fprintf(log_output, "%s%s", - (level > LOG_LVL_USER) ? log_strings[level + 1] : "", string); - } + string); } else { - /* Empty strings are sent to log callbacks to keep e.g. gdbserver alive, here we do - *nothing. */ + /* if we are using gdb through pipes then we do not want any output + * to the pipe otherwise we get repeated strings */ + fprintf(log_output, "%s%s", + (level > LOG_LVL_USER) ? log_strings[level + 1] : "", string); } fflush(log_output); @@ -440,8 +435,7 @@ static void gdb_timeout_warning(int64_t delta_time) void keep_alive(void) { - current_time = timeval_ms(); - + int64_t current_time = timeval_ms(); int64_t delta_time = current_time - last_time; if (delta_time > KEEP_ALIVE_TIMEOUT_MS) { @@ -454,7 +448,7 @@ void keep_alive(void) last_time = current_time; /* this will keep the GDB connection alive */ - LOG_USER_N("%s", ""); + server_keep_clients_alive(); /* DANGER!!!! do not add code to invoke e.g. target event processing, * jim timer processing, etc. it can cause infinite recursion + @@ -469,7 +463,7 @@ void keep_alive(void) /* reset keep alive timer without sending message */ void kept_alive(void) { - current_time = timeval_ms(); + int64_t current_time = timeval_ms(); int64_t delta_time = current_time - last_time; diff --git a/src/jtag/drivers/cmsis_dap.c b/src/jtag/drivers/cmsis_dap.c index e7562d087..63407be42 100644 --- a/src/jtag/drivers/cmsis_dap.c +++ b/src/jtag/drivers/cmsis_dap.c @@ -48,6 +48,7 @@ #include #include "cmsis_dap.h" +#include "libusb_helper.h" static const struct cmsis_dap_backend *const cmsis_dap_backends[] = { #if BUILD_CMSIS_DAP_USB == 1 @@ -79,8 +80,6 @@ static uint16_t cmsis_dap_pid[MAX_USB_IDS + 1] = { 0 }; static int cmsis_dap_backend = -1; static bool swd_mode; -#define USB_TIMEOUT 1000 - /* CMSIS-DAP General Commands */ #define CMD_DAP_INFO 0x00 #define CMD_DAP_LED 0x01 @@ -210,7 +209,7 @@ static bool swd_mode; * None as yet... */ static const char * const info_caps_str[INFO_CAPS__NUM_CAPS] = { - "SWD supported", + "SWD supported", "JTAG supported", "SWO-UART supported", "SWO-MANCHESTER supported", @@ -360,12 +359,12 @@ static int cmsis_dap_xfer(struct cmsis_dap *dap, int txlen) } uint8_t current_cmd = cmsis_dap_handle->command[0]; - int retval = dap->backend->write(dap, txlen, USB_TIMEOUT); + int retval = dap->backend->write(dap, txlen, LIBUSB_TIMEOUT_MS); if (retval < 0) return retval; /* get reply */ - retval = dap->backend->read(dap, USB_TIMEOUT); + retval = dap->backend->read(dap, LIBUSB_TIMEOUT_MS); if (retval < 0) return retval; @@ -826,7 +825,7 @@ static void cmsis_dap_swd_write_from_queue(struct cmsis_dap *dap) } } - int retval = dap->backend->write(dap, idx, USB_TIMEOUT); + int retval = dap->backend->write(dap, idx, LIBUSB_TIMEOUT_MS); if (retval < 0) { queued_retval = retval; goto skip; @@ -854,7 +853,7 @@ static void cmsis_dap_swd_read_process(struct cmsis_dap *dap, int timeout_ms) /* get reply */ int retval = dap->backend->read(dap, timeout_ms); - if (retval == ERROR_TIMEOUT_REACHED && timeout_ms < USB_TIMEOUT) + if (retval == ERROR_TIMEOUT_REACHED && timeout_ms < LIBUSB_TIMEOUT_MS) return; if (retval <= 0) { @@ -929,7 +928,7 @@ static int cmsis_dap_swd_run_queue(void) cmsis_dap_swd_write_from_queue(cmsis_dap_handle); while (pending_fifo_block_count) - cmsis_dap_swd_read_process(cmsis_dap_handle, USB_TIMEOUT); + cmsis_dap_swd_read_process(cmsis_dap_handle, LIBUSB_TIMEOUT_MS); pending_fifo_put_idx = 0; pending_fifo_get_idx = 0; @@ -953,7 +952,7 @@ static void cmsis_dap_swd_queue_cmd(uint8_t cmd, uint32_t *dst, uint32_t data) cmsis_dap_swd_write_from_queue(cmsis_dap_handle); if (pending_fifo_block_count >= cmsis_dap_handle->packet_count) - cmsis_dap_swd_read_process(cmsis_dap_handle, USB_TIMEOUT); + cmsis_dap_swd_read_process(cmsis_dap_handle, LIBUSB_TIMEOUT_MS); } if (queued_retval != ERROR_OK) diff --git a/src/jtag/drivers/jtag_vpi.c b/src/jtag/drivers/jtag_vpi.c index 0fc688edf..eb53a5b06 100644 --- a/src/jtag/drivers/jtag_vpi.c +++ b/src/jtag/drivers/jtag_vpi.c @@ -38,8 +38,8 @@ #define NO_TAP_SHIFT 0 #define TAP_SHIFT 1 -#define SERVER_ADDRESS "127.0.0.1" -#define SERVER_PORT 5555 +#define DEFAULT_SERVER_ADDRESS "127.0.0.1" +#define DEFAULT_SERVER_PORT 5555 #define XFERT_MAX_SIZE 512 @@ -50,7 +50,7 @@ #define CMD_STOP_SIMU 4 /* jtag_vpi server port and address to connect to */ -static int server_port = SERVER_PORT; +static int server_port = DEFAULT_SERVER_PORT; static char *server_address; /* Send CMD_STOP_SIMU to server when OpenOCD exits? */ @@ -551,7 +551,7 @@ static int jtag_vpi_init(void) serv_addr.sin_port = htons(server_port); if (!server_address) - server_address = strdup(SERVER_ADDRESS); + server_address = strdup(DEFAULT_SERVER_ADDRESS); serv_addr.sin_addr.s_addr = inet_addr(server_address); @@ -604,27 +604,28 @@ static int jtag_vpi_quit(void) COMMAND_HANDLER(jtag_vpi_set_port) { - if (CMD_ARGC == 0) - LOG_WARNING("You need to set a port number"); - else - COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], server_port); + if (CMD_ARGC == 0) { + LOG_ERROR("Command \"jtag_vpi set_port\" expects 1 argument (TCP port number)"); + return ERROR_COMMAND_SYNTAX_ERROR; + } - LOG_INFO("Set server port to %u", server_port); + COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], server_port); + LOG_INFO("jtag_vpi: server port set to %u", server_port); return ERROR_OK; } COMMAND_HANDLER(jtag_vpi_set_address) { - free(server_address); if (CMD_ARGC == 0) { - LOG_WARNING("You need to set an address"); - server_address = strdup(SERVER_ADDRESS); - } else - server_address = strdup(CMD_ARGV[0]); + LOG_ERROR("Command \"jtag_vpi set_address\" expects 1 argument (IP address)"); + return ERROR_COMMAND_SYNTAX_ERROR; + } - LOG_INFO("Set server address to %s", server_address); + free(server_address); + server_address = strdup(CMD_ARGV[0]); + LOG_INFO("jtag_vpi: server address set to %s", server_address); return ERROR_OK; } @@ -632,11 +633,11 @@ COMMAND_HANDLER(jtag_vpi_set_address) COMMAND_HANDLER(jtag_vpi_stop_sim_on_exit_handler) { if (CMD_ARGC != 1) { - LOG_ERROR("jtag_vpi_stop_sim_on_exit expects 1 argument (on|off)"); + LOG_ERROR("Command \"jtag_vpi stop_sim_on_exit\" expects 1 argument (on|off)"); return ERROR_COMMAND_SYNTAX_ERROR; - } else { - COMMAND_PARSE_ON_OFF(CMD_ARGV[0], stop_sim_on_exit); } + + COMMAND_PARSE_ON_OFF(CMD_ARGV[0], stop_sim_on_exit); return ERROR_OK; } @@ -645,14 +646,14 @@ static const struct command_registration jtag_vpi_subcommand_handlers[] = { .name = "set_port", .handler = &jtag_vpi_set_port, .mode = COMMAND_CONFIG, - .help = "set the port of the VPI server", + .help = "set the TCP port number of the jtag_vpi server (default: 5555)", .usage = "tcp_port_num", }, { .name = "set_address", .handler = &jtag_vpi_set_address, .mode = COMMAND_CONFIG, - .help = "set the address of the VPI server", + .help = "set the IP address of the jtag_vpi server (default: 127.0.0.1)", .usage = "ipv4_addr", }, { diff --git a/src/jtag/drivers/libusb_helper.h b/src/jtag/drivers/libusb_helper.h index 2ddb246b3..9d51464a7 100644 --- a/src/jtag/drivers/libusb_helper.h +++ b/src/jtag/drivers/libusb_helper.h @@ -22,6 +22,20 @@ #include +/* When we debug a target that works as a USB device, halting the target causes the + * USB communication with the USB host to become unresponsive. The host will try + * to reconnect/reset/setup the unresponsive device during which communication + * with other devices on the same USB bus can get stalled for several seconds. + * If the JTAG adapter is on the same bus, we need to make sure openOCD will wait + * for packets at least as long as the host USB stack. Otherwise the USB stack + * might deliver a valid packet, but openOCD would ignore it due to the timeout. + * The xHCI spec uses 5 sec timeouts, so let's use that in openOCD with some margin. + * + * Use this value in all libusb calls. HID API might have a libusb backend and + * would probably be victim to the same bug, so it should use this timeout, too. + */ +#define LIBUSB_TIMEOUT_MS (6000) + /* this callback should return a non NULL value only when the serial could not * be retrieved by the standard 'libusb_get_string_descriptor_ascii' */ typedef char * (*adapter_get_alternate_serial_fn)(struct libusb_device_handle *device, diff --git a/src/jtag/drivers/nulink_usb.c b/src/jtag/drivers/nulink_usb.c index d4b8b53bc..84a4420e8 100644 --- a/src/jtag/drivers/nulink_usb.c +++ b/src/jtag/drivers/nulink_usb.c @@ -33,7 +33,9 @@ #include -#define NULINK_READ_TIMEOUT 1000 +#include "libusb_helper.h" + +#define NULINK_READ_TIMEOUT LIBUSB_TIMEOUT_MS #define NULINK_HID_MAX_SIZE (64) #define NULINK2_HID_MAX_SIZE (1024) diff --git a/src/jtag/drivers/rlink.c b/src/jtag/drivers/rlink.c index 73be3c57e..0cf9dbbb2 100644 --- a/src/jtag/drivers/rlink.c +++ b/src/jtag/drivers/rlink.c @@ -59,8 +59,6 @@ #define USB_EP2IN_SIZE (USB_EP2OUT_SIZE) #define USB_EP2BANK_SIZE (512) -#define USB_TIMEOUT_MS (3 * 1000) - #define DTC_STATUS_POLL_BYTE (ST7_USB_BUF_EP0OUT + 0xff) #define ST7_PD_NBUSY_LED ST7_PD0 @@ -133,7 +131,7 @@ static int ep1_generic_commandl(struct libusb_device_handle *hdev_param, size_t hdev_param, USB_EP1OUT_ADDR, (char *)usb_buffer, sizeof(usb_buffer), - USB_TIMEOUT_MS, + LIBUSB_TIMEOUT_MS, &transferred ); @@ -176,7 +174,7 @@ static ssize_t ep1_memory_read( usb_ret = jtag_libusb_bulk_write( hdev_param, USB_EP1OUT_ADDR, (char *)usb_buffer, sizeof(usb_buffer), - USB_TIMEOUT_MS, + LIBUSB_TIMEOUT_MS, &transferred ); @@ -186,7 +184,7 @@ static ssize_t ep1_memory_read( usb_ret = jtag_libusb_bulk_read( hdev_param, USB_EP1IN_ADDR, (char *)buffer, length, - USB_TIMEOUT_MS, + LIBUSB_TIMEOUT_MS, &transferred ); @@ -241,7 +239,7 @@ static ssize_t ep1_memory_write(struct libusb_device_handle *hdev_param, uint16_ usb_ret = jtag_libusb_bulk_write( hdev_param, USB_EP1OUT_ADDR, (char *)usb_buffer, sizeof(usb_buffer), - USB_TIMEOUT_MS, + LIBUSB_TIMEOUT_MS, &transferred ); @@ -432,7 +430,7 @@ static int dtc_start_download(void) usb_err = jtag_libusb_bulk_read( hdev, USB_EP1IN_ADDR, (char *)&ep2txr, 1, - USB_TIMEOUT_MS, + LIBUSB_TIMEOUT_MS, &transferred ); if (usb_err != ERROR_OK) @@ -462,7 +460,7 @@ static int dtc_start_download(void) usb_err = jtag_libusb_bulk_read( hdev, USB_EP1IN_ADDR, (char *)&ep2txr, 1, - USB_TIMEOUT_MS, + LIBUSB_TIMEOUT_MS, &transferred ); @@ -488,7 +486,7 @@ static int dtc_run_download( hdev_param, USB_EP2OUT_ADDR, (char *)command_buffer, USB_EP2BANK_SIZE, - USB_TIMEOUT_MS, + LIBUSB_TIMEOUT_MS, &transferred ); if (usb_err < 0) @@ -512,7 +510,7 @@ static int dtc_run_download( hdev_param, USB_EP1IN_ADDR, &dtc_status, 1, - USB_TIMEOUT_MS, + LIBUSB_TIMEOUT_MS, &transferred ); if (usb_err < 0) @@ -533,7 +531,7 @@ static int dtc_run_download( hdev_param, USB_EP2IN_ADDR, (char *)reply_buffer, reply_buffer_size, - USB_TIMEOUT_MS, + LIBUSB_TIMEOUT_MS, &transferred ); @@ -954,7 +952,7 @@ static void rlink_reset(int trst, int srst) usb_err = jtag_libusb_bulk_read( hdev, USB_EP1IN_ADDR, (char *)&bitmap, 1, - USB_TIMEOUT_MS, + LIBUSB_TIMEOUT_MS, &transferred ); if (usb_err != ERROR_OK || transferred < 1) { @@ -990,7 +988,7 @@ static void rlink_reset(int trst, int srst) usb_err = jtag_libusb_bulk_read( hdev, USB_EP1IN_ADDR, (char *)&bitmap, 1, - USB_TIMEOUT_MS, + LIBUSB_TIMEOUT_MS, &transferred ); if (usb_err != ERROR_OK || transferred < 1) { @@ -1021,7 +1019,7 @@ static void rlink_reset(int trst, int srst) usb_err = jtag_libusb_bulk_read( hdev, USB_EP1IN_ADDR, (char *)&bitmap, 1, - USB_TIMEOUT_MS, + LIBUSB_TIMEOUT_MS, &transferred ); if (usb_err != ERROR_OK || transferred < 1) { @@ -1576,7 +1574,7 @@ static int rlink_init(void) jtag_libusb_bulk_read( hdev, USB_EP1IN_ADDR, (char *)reply_buffer, 1, - USB_TIMEOUT_MS, + LIBUSB_TIMEOUT_MS, &transferred ); @@ -1601,7 +1599,7 @@ static int rlink_init(void) jtag_libusb_bulk_read( hdev, USB_EP1IN_ADDR, (char *)reply_buffer, 1, - USB_TIMEOUT_MS, + LIBUSB_TIMEOUT_MS, &transferred ); diff --git a/src/jtag/drivers/stlink_usb.c b/src/jtag/drivers/stlink_usb.c index 2f61bf946..2785d9b96 100644 --- a/src/jtag/drivers/stlink_usb.c +++ b/src/jtag/drivers/stlink_usb.c @@ -71,8 +71,8 @@ #define ENDPOINT_IN 0x80 #define ENDPOINT_OUT 0x00 -#define STLINK_WRITE_TIMEOUT 1000 -#define STLINK_READ_TIMEOUT 1000 +#define STLINK_WRITE_TIMEOUT (LIBUSB_TIMEOUT_MS) +#define STLINK_READ_TIMEOUT (LIBUSB_TIMEOUT_MS) #define STLINK_RX_EP (1|ENDPOINT_IN) #define STLINK_TX_EP (2|ENDPOINT_OUT) @@ -156,6 +156,13 @@ struct stlink_usb_priv_s { struct libusb_transfer *trans; }; +struct stlink_tcp_version { + uint32_t api; + uint32_t major; + uint32_t minor; + uint32_t build; +}; + struct stlink_tcp_priv_s { /** */ int fd; @@ -169,6 +176,8 @@ struct stlink_tcp_priv_s { uint8_t *send_buf; /** */ uint8_t *recv_buf; + /** */ + struct stlink_tcp_version version; }; struct stlink_backend_s { @@ -3532,16 +3541,19 @@ static int stlink_tcp_open(void *handle, struct hl_interface_param_s *param) return ERROR_FAIL; } - uint32_t api_ver = le_to_h_u32(&h->tcp_backend_priv.recv_buf[0]); - uint32_t ver_major = le_to_h_u32(&h->tcp_backend_priv.recv_buf[4]); - uint32_t ver_minor = le_to_h_u32(&h->tcp_backend_priv.recv_buf[8]); - uint32_t ver_build = le_to_h_u32(&h->tcp_backend_priv.recv_buf[12]); + h->tcp_backend_priv.version.api = le_to_h_u32(&h->tcp_backend_priv.recv_buf[0]); + h->tcp_backend_priv.version.major = le_to_h_u32(&h->tcp_backend_priv.recv_buf[4]); + h->tcp_backend_priv.version.minor = le_to_h_u32(&h->tcp_backend_priv.recv_buf[8]); + h->tcp_backend_priv.version.build = le_to_h_u32(&h->tcp_backend_priv.recv_buf[12]); LOG_INFO("stlink-server API v%d, version %d.%d.%d", - api_ver, ver_major, ver_minor, ver_build); + h->tcp_backend_priv.version.api, + h->tcp_backend_priv.version.major, + h->tcp_backend_priv.version.minor, + h->tcp_backend_priv.version.build); /* in stlink-server API v1 sending more than 1428 bytes will cause stlink-server * to crash in windows: select a safe default value (1K) */ - if (api_ver < 2) + if (h->tcp_backend_priv.version.api < 2) h->max_mem_packet = (1 << 10); /* refresh stlink list (re-enumerate) */ @@ -4468,11 +4480,12 @@ static int stlink_usb_count_misc_rw_queue(void *handle, const struct dap_queue * if (!(h->version.flags & STLINK_F_HAS_RW_MISC)) return 0; /* - * RW_MISC sequence doesn't lock the st-link, so are not safe in shared mode. + * Before stlink-server API v3, RW_MISC sequence doesn't lock the st-link, + * so are not safe in shared mode. * Don't use it with TCP backend to prevent any issue in case of sharing. * This further degrades the performance, on top of TCP server overhead. */ - if (h->backend == &stlink_tcp_backend) + if (h->backend == &stlink_tcp_backend && h->tcp_backend_priv.version.api < 3) return 0; for (i = 0; i < len; i++) { diff --git a/src/jtag/drivers/ti_icdi_usb.c b/src/jtag/drivers/ti_icdi_usb.c index c94a1102f..e48d0e269 100644 --- a/src/jtag/drivers/ti_icdi_usb.c +++ b/src/jtag/drivers/ti_icdi_usb.c @@ -37,8 +37,8 @@ #define ICDI_WRITE_ENDPOINT 0x02 #define ICDI_READ_ENDPOINT 0x83 -#define ICDI_WRITE_TIMEOUT 1000 -#define ICDI_READ_TIMEOUT 1000 +#define ICDI_WRITE_TIMEOUT (LIBUSB_TIMEOUT_MS) +#define ICDI_READ_TIMEOUT (LIBUSB_TIMEOUT_MS) #define ICDI_PACKET_SIZE 2048 #define PACKET_START "$" diff --git a/src/jtag/drivers/ulink.c b/src/jtag/drivers/ulink.c index 20a036a78..50609a64b 100644 --- a/src/jtag/drivers/ulink.c +++ b/src/jtag/drivers/ulink.c @@ -56,9 +56,6 @@ /** USB interface number */ #define USB_INTERFACE 0 -/** libusb timeout in ms */ -#define USB_TIMEOUT 5000 - /** Delay (in microseconds) to wait while EZ-USB performs ReNumeration. */ #define ULINK_RENUMERATION_DELAY 1500000 @@ -335,7 +332,7 @@ static int ulink_cpu_reset(struct ulink *device, unsigned char reset_bit) ret = libusb_control_transfer(device->usb_device_handle, (LIBUSB_ENDPOINT_OUT | LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE), - REQUEST_FIRMWARE_LOAD, CPUCS_REG, 0, &reset_bit, 1, USB_TIMEOUT); + REQUEST_FIRMWARE_LOAD, CPUCS_REG, 0, &reset_bit, 1, LIBUSB_TIMEOUT_MS); /* usb_control_msg() returns the number of bytes transferred during the * DATA stage of the control transfer - must be exactly 1 in this case! */ @@ -478,7 +475,7 @@ static int ulink_write_firmware_section(struct ulink *device, ret = libusb_control_transfer(device->usb_device_handle, (LIBUSB_ENDPOINT_OUT | LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE), REQUEST_FIRMWARE_LOAD, addr, FIRMWARE_ADDR, (unsigned char *)data_ptr, - chunk_size, USB_TIMEOUT); + chunk_size, LIBUSB_TIMEOUT_MS); if (ret != (int)chunk_size) { /* Abort if libusb sent less data than requested */ @@ -662,7 +659,7 @@ static int ulink_append_queue(struct ulink *device, struct ulink_cmd *ulink_cmd) if ((newsize_out > 64) || (newsize_in > 64)) { /* New command does not fit. Execute all commands in queue before starting * new queue with the current command as first entry. */ - ret = ulink_execute_queued_commands(device, USB_TIMEOUT); + ret = ulink_execute_queued_commands(device, LIBUSB_TIMEOUT_MS); if (ret == ERROR_OK) ret = ulink_post_process_queue(device); @@ -1960,7 +1957,7 @@ static int ulink_execute_queue(void) } if (ulink_handle->commands_in_queue > 0) { - ret = ulink_execute_queued_commands(ulink_handle, USB_TIMEOUT); + ret = ulink_execute_queued_commands(ulink_handle, LIBUSB_TIMEOUT_MS); if (ret != ERROR_OK) return ret; diff --git a/src/rtos/chromium-ec.c b/src/rtos/chromium-ec.c index 1c8f4e3f4..95a228d0d 100644 --- a/src/rtos/chromium-ec.c +++ b/src/rtos/chromium-ec.c @@ -7,6 +7,11 @@ * Chromium-EC RTOS Task Awareness */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include #include #include #include @@ -16,7 +21,6 @@ #define CROS_EC_MAX_TASKS 32 #define CROS_EC_MAX_NAME 200 #define CROS_EC_IDLE_STRING "<< idle >>" -#define BIT(x) (1 << (x)) struct chromium_ec_params { const char *target_name; diff --git a/src/rtt/rtt.c b/src/rtt/rtt.c index bf3cca51b..3da3cce81 100644 --- a/src/rtt/rtt.c +++ b/src/rtt/rtt.c @@ -15,6 +15,10 @@ * along with this program. If not, see . */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include #include #include diff --git a/src/rtt/tcl.c b/src/rtt/tcl.c index f5abf2e5e..4a34d8b98 100644 --- a/src/rtt/tcl.c +++ b/src/rtt/tcl.c @@ -15,6 +15,10 @@ * along with this program. If not, see . */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include #include diff --git a/src/server/gdb_server.c b/src/server/gdb_server.c index 4db305cde..07dfaec4c 100644 --- a/src/server/gdb_server.c +++ b/src/server/gdb_server.c @@ -61,6 +61,13 @@ * found in most modern embedded processors. */ +enum gdb_output_flag { + /* GDB doesn't accept 'O' packets */ + GDB_OUTPUT_NO, + /* GDB accepts 'O' packets */ + GDB_OUTPUT_ALL, +}; + struct target_desc_format { char *tdesc; uint32_t tdesc_length; @@ -97,6 +104,8 @@ struct gdb_connection { struct target_desc_format target_desc; /* temporarily used for thread list support */ char *thread_list; + /* flag to mask the output from gdb_log_callback() */ + enum gdb_output_flag output_flag; }; #if 0 @@ -362,11 +371,13 @@ static int gdb_write(struct connection *connection, void *data, int len) return ERROR_SERVER_REMOTE_CLOSED; } -static void gdb_log_incoming_packet(char *packet) +static void gdb_log_incoming_packet(struct connection *connection, char *packet) { if (!LOG_LEVEL_IS(LOG_LVL_DEBUG)) return; + struct target *target = get_target_from_connection(connection); + /* Avoid dumping non-printable characters to the terminal */ const unsigned packet_len = strlen(packet); const char *nonprint = find_nonprint_char(packet, packet_len); @@ -380,25 +391,31 @@ static void gdb_log_incoming_packet(char *packet) if (packet_prefix_printable) { const unsigned int prefix_len = colon - packet + 1; /* + 1 to include the ':' */ const unsigned int payload_len = packet_len - prefix_len; - LOG_DEBUG("received packet: %.*s", prefix_len, packet, payload_len); + LOG_TARGET_DEBUG(target, "received packet: %.*s", prefix_len, + packet, payload_len); } else { - LOG_DEBUG("received packet: ", packet_len); + LOG_TARGET_DEBUG(target, "received packet: ", packet_len); } } else { /* All chars printable, dump the packet as is */ - LOG_DEBUG("received packet: %s", packet); + LOG_TARGET_DEBUG(target, "received packet: %s", packet); } } -static void gdb_log_outgoing_packet(char *packet_buf, unsigned int packet_len, unsigned char checksum) +static void gdb_log_outgoing_packet(struct connection *connection, char *packet_buf, + unsigned int packet_len, unsigned char checksum) { if (!LOG_LEVEL_IS(LOG_LVL_DEBUG)) return; + struct target *target = get_target_from_connection(connection); + if (find_nonprint_char(packet_buf, packet_len)) - LOG_DEBUG("sending packet: $#%2.2x", packet_len, checksum); + LOG_TARGET_DEBUG(target, "sending packet: $#%2.2x", + packet_len, checksum); else - LOG_DEBUG("sending packet: $%.*s#%2.2x'", packet_len, packet_buf, checksum); + LOG_TARGET_DEBUG(target, "sending packet: $%.*s#%2.2x", packet_len, packet_buf, + checksum); } static int gdb_put_packet_inner(struct connection *connection, @@ -443,7 +460,7 @@ static int gdb_put_packet_inner(struct connection *connection, #endif while (1) { - gdb_log_outgoing_packet(buffer, len, my_checksum); + gdb_log_outgoing_packet(connection, buffer, len, my_checksum); char local_buffer[1024]; local_buffer[0] = '$'; @@ -476,22 +493,27 @@ static int gdb_put_packet_inner(struct connection *connection, if (retval != ERROR_OK) return retval; - if (reply == '+') + if (reply == '+') { + gdb_log_incoming_packet(connection, "+"); break; - else if (reply == '-') { + } else if (reply == '-') { /* Stop sending output packets for now */ - log_remove_callback(gdb_log_callback, connection); + gdb_con->output_flag = GDB_OUTPUT_NO; + gdb_log_incoming_packet(connection, "-"); LOG_WARNING("negative reply, retrying"); } else if (reply == 0x3) { gdb_con->ctrl_c = true; + gdb_log_incoming_packet(connection, ""); retval = gdb_get_char(connection, &reply); if (retval != ERROR_OK) return retval; - if (reply == '+') + if (reply == '+') { + gdb_log_incoming_packet(connection, "+"); break; - else if (reply == '-') { + } else if (reply == '-') { /* Stop sending output packets for now */ - log_remove_callback(gdb_log_callback, connection); + gdb_con->output_flag = GDB_OUTPUT_NO; + gdb_log_incoming_packet(connection, "-"); LOG_WARNING("negative reply, retrying"); } else if (reply == '$') { LOG_ERROR("GDB missing ack(1) - assumed good"); @@ -668,6 +690,7 @@ static int gdb_get_packet_inner(struct connection *connection, case '$': break; case '+': + gdb_log_incoming_packet(connection, "+"); /* According to the GDB documentation * (https://sourceware.org/gdb/onlinedocs/gdb/Packet-Acknowledgment.html): * "gdb sends a final `+` acknowledgment of the stub's `OK` @@ -685,9 +708,11 @@ static int gdb_get_packet_inner(struct connection *connection, } break; case '-': + gdb_log_incoming_packet(connection, "-"); LOG_WARNING("negative acknowledgment, but no packet pending"); break; case 0x3: + gdb_log_incoming_packet(connection, ""); gdb_con->ctrl_c = true; *len = 0; return ERROR_OK; @@ -937,7 +962,7 @@ static void gdb_frontend_halted(struct target *target, struct connection *connec */ if (gdb_connection->frontend_state == TARGET_RUNNING) { /* stop forwarding log packets! */ - log_remove_callback(gdb_log_callback, connection); + gdb_connection->output_flag = GDB_OUTPUT_NO; /* check fileio first */ if (target_get_gdb_fileio_info(target, target->fileio_info) == ERROR_OK) @@ -997,6 +1022,7 @@ static int gdb_new_connection(struct connection *connection) gdb_connection->target_desc.tdesc = NULL; gdb_connection->target_desc.tdesc_length = 0; gdb_connection->thread_list = NULL; + gdb_connection->output_flag = GDB_OUTPUT_NO; /* send ACK to GDB for debug request */ gdb_write(connection, "+", 1); @@ -1081,6 +1107,8 @@ static int gdb_new_connection(struct connection *connection) * register callback to be informed about target events */ target_register_event_callback(gdb_target_callback_event_handler, connection); + log_add_callback(gdb_log_callback, connection); + return ERROR_OK; } @@ -2735,7 +2763,7 @@ static int gdb_query_packet(struct connection *connection, LOG_DEBUG("qRcmd: %s", cmd); /* We want to print all debug output to GDB connection */ - log_add_callback(gdb_log_callback, connection); + gdb_connection->output_flag = GDB_OUTPUT_ALL; target_call_timer_callbacks_now(); /* some commands need to know the GDB connection, make note of current * GDB connection. */ @@ -2743,7 +2771,7 @@ static int gdb_query_packet(struct connection *connection, command_run_line(cmd_ctx, cmd); current_gdb_connection = NULL; target_call_timer_callbacks_now(); - log_remove_callback(gdb_log_callback, connection); + gdb_connection->output_flag = GDB_OUTPUT_NO; free(cmd); } gdb_put_packet(connection, "OK", 2); @@ -2924,7 +2952,7 @@ static bool gdb_handle_vcont_packet(struct connection *connection, const char *p if (parse[0] == 'c') { gdb_running_type = 'c'; LOG_DEBUG("target %s continue", target_name(target)); - log_add_callback(gdb_log_callback, connection); + gdb_connection->output_flag = GDB_OUTPUT_ALL; retval = target_resume(target, 1, 0, 0, 0); if (retval == ERROR_TARGET_NOT_HALTED) LOG_INFO("target %s was not halted when resume was requested", target_name(target)); @@ -3028,7 +3056,7 @@ static bool gdb_handle_vcont_packet(struct connection *connection, const char *p } LOG_DEBUG("target %s single-step thread %"PRIx64, target_name(ct), thread_id); - log_add_callback(gdb_log_callback, connection); + gdb_connection->output_flag = GDB_OUTPUT_ALL; target_call_event_callbacks(ct, TARGET_EVENT_GDB_START); if (fake_step) { @@ -3045,7 +3073,7 @@ static bool gdb_handle_vcont_packet(struct connection *connection, const char *p "T05thread:%016"PRIx64";", thread_id); gdb_put_packet(connection, sig_reply, sig_reply_len); - log_remove_callback(gdb_log_callback, connection); + gdb_connection->output_flag = GDB_OUTPUT_NO; return true; } @@ -3057,7 +3085,7 @@ static bool gdb_handle_vcont_packet(struct connection *connection, const char *p 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); + gdb_connection->output_flag = GDB_OUTPUT_NO; } else gdb_connection->frontend_state = TARGET_RUNNING; return true; @@ -3075,7 +3103,7 @@ static bool gdb_handle_vcont_packet(struct connection *connection, const char *p /* send back signal information */ gdb_signal_reply(ct, connection); /* stop forwarding log packets! */ - log_remove_callback(gdb_log_callback, connection); + gdb_connection->output_flag = GDB_OUTPUT_NO; } else gdb_connection->frontend_state = TARGET_RUNNING; } else { @@ -3410,6 +3438,10 @@ static void gdb_log_callback(void *priv, const char *file, unsigned line, struct connection *connection = priv; struct gdb_connection *gdb_con = connection->priv; + if (gdb_con->output_flag == GDB_OUTPUT_NO) + /* No out allowed */ + return; + if (gdb_con->busy) { /* do not reply this using the O packet */ return; @@ -3459,9 +3491,10 @@ static int gdb_input_inner(struct connection *connection) /* terminate with zero */ gdb_packet_buffer[packet_size] = '\0'; - gdb_log_incoming_packet(gdb_packet_buffer); - if (packet_size > 0) { + + gdb_log_incoming_packet(connection, gdb_packet_buffer); + retval = ERROR_OK; switch (packet[0]) { case 'T': /* Is thread alive? */ @@ -3512,7 +3545,7 @@ static int gdb_input_inner(struct connection *connection) case 's': { gdb_thread_packet(connection, packet, packet_size); - log_add_callback(gdb_log_callback, connection); + gdb_con->output_flag = GDB_OUTPUT_ALL; if (gdb_con->mem_write_error) { LOG_ERROR("Memory write failure!"); @@ -3555,7 +3588,7 @@ static int gdb_input_inner(struct connection *connection) gdb_sig_halted(connection); /* stop forwarding log packets! */ - log_remove_callback(gdb_log_callback, connection); + gdb_con->output_flag = GDB_OUTPUT_NO; } else { /* We're running/stepping, in which case we can * forward log output until the target is halted @@ -3627,7 +3660,7 @@ static int gdb_input_inner(struct connection *connection) * Fretcode,errno,Ctrl-C flag;call-specific attachment */ gdb_con->frontend_state = TARGET_RUNNING; - log_add_callback(gdb_log_callback, connection); + gdb_con->output_flag = GDB_OUTPUT_ALL; gdb_fileio_response_packet(connection, packet, packet_size); break; @@ -3680,6 +3713,37 @@ static int gdb_input(struct connection *connection) return ERROR_OK; } +static void gdb_keep_client_alive(struct connection *connection) +{ + struct gdb_connection *gdb_con = connection->priv; + + if (gdb_con->busy) { + /* do not send packets, retry asap */ + return; + } + + switch (gdb_con->output_flag) { + case GDB_OUTPUT_NO: + /* no need for keep-alive */ + break; + case GDB_OUTPUT_ALL: + /* send an empty O packet */ + gdb_output_con(connection, ""); + break; + default: + break; + } +} + +static const struct service_driver gdb_service_driver = { + .name = "gdb", + .new_connection_during_keep_alive_handler = NULL, + .new_connection_handler = gdb_new_connection, + .input_handler = gdb_input, + .connection_closed_handler = gdb_connection_closed, + .keep_client_alive_handler = gdb_keep_client_alive, +}; + static int gdb_target_start(struct target *target, const char *port) { struct gdb_service *gdb_service; @@ -3696,9 +3760,7 @@ static int gdb_target_start(struct target *target, const char *port) gdb_service->core[1] = -1; target->gdb_service = gdb_service; - ret = add_service("gdb", - port, target->gdb_max_connections, &gdb_new_connection, &gdb_input, - &gdb_connection_closed, gdb_service); + ret = add_service(&gdb_service_driver, port, target->gdb_max_connections, gdb_service); /* initialize all targets gdb service with the same pointer */ { struct target_list *head; diff --git a/src/server/ipdbg.c b/src/server/ipdbg.c index ec2fae8c0..3bbcf0714 100644 --- a/src/server/ipdbg.c +++ b/src/server/ipdbg.c @@ -587,6 +587,15 @@ static int ipdbg_on_connection_closed(struct connection *connection) return ipdbg_stop_polling(connection->service->priv); } +static const struct service_driver ipdbg_service_driver = { + .name = "ipdbg", + .new_connection_during_keep_alive_handler = NULL, + .new_connection_handler = ipdbg_on_new_connection, + .input_handler = ipdbg_on_connection_input, + .connection_closed_handler = ipdbg_on_connection_closed, + .keep_client_alive_handler = NULL, +}; + static int ipdbg_start(uint16_t port, struct jtag_tap *tap, uint32_t user_instruction, uint8_t data_register_length, struct ipdbg_virtual_ir_info *virtual_ir, uint8_t tool) { @@ -618,8 +627,7 @@ static int ipdbg_start(uint16_t port, struct jtag_tap *tap, uint32_t user_instru char port_str_buffer[IPDBG_TCP_PORT_STR_MAX_LENGTH]; snprintf(port_str_buffer, IPDBG_TCP_PORT_STR_MAX_LENGTH, "%u", port); - retval = add_service("ipdbg", port_str_buffer, 1, &ipdbg_on_new_connection, - &ipdbg_on_connection_input, &ipdbg_on_connection_closed, service); + retval = add_service(&ipdbg_service_driver, port_str_buffer, 1, service); if (retval == ERROR_OK) { ipdbg_add_service(service); if (hub->active_services == 0 && hub->active_connections == 0) diff --git a/src/server/rtt_server.c b/src/server/rtt_server.c index d49e4d000..3850c2687 100644 --- a/src/server/rtt_server.c +++ b/src/server/rtt_server.c @@ -15,6 +15,10 @@ * along with this program. If not, see . */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include #include @@ -110,6 +114,15 @@ static int rtt_input(struct connection *connection) return ERROR_OK; } +static const struct service_driver rtt_service_driver = { + .name = "rtt", + .new_connection_during_keep_alive_handler = NULL, + .new_connection_handler = rtt_new_connection, + .input_handler = rtt_input, + .connection_closed_handler = rtt_connection_closed, + .keep_client_alive_handler = NULL, +}; + COMMAND_HANDLER(handle_rtt_start_command) { int ret; @@ -125,8 +138,7 @@ COMMAND_HANDLER(handle_rtt_start_command) COMMAND_PARSE_NUMBER(uint, CMD_ARGV[1], service->channel); - ret = add_service("rtt", CMD_ARGV[0], CONNECTION_LIMIT_UNLIMITED, - rtt_new_connection, rtt_input, rtt_connection_closed, service); + ret = add_service(&rtt_service_driver, CMD_ARGV[0], CONNECTION_LIMIT_UNLIMITED, service); if (ret != ERROR_OK) { free(service); diff --git a/src/server/server.c b/src/server/server.c index 1569f5a2c..7b0004d64 100644 --- a/src/server/server.c +++ b/src/server/server.c @@ -205,13 +205,8 @@ static void free_service(struct service *c) free(c); } -int add_service(char *name, - const char *port, - int max_connections, - new_connection_handler_t new_connection_handler, - input_handler_t input_handler, - connection_closed_handler_t connection_closed_handler, - void *priv) +int add_service(const struct service_driver *driver, const char *port, + int max_connections, void *priv) { struct service *c, **p; struct hostent *hp; @@ -219,14 +214,16 @@ int add_service(char *name, c = malloc(sizeof(struct service)); - c->name = strdup(name); + c->name = strdup(driver->name); c->port = strdup(port); c->max_connections = 1; /* Only TCP/IP ports can support more than one connection */ c->fd = -1; c->connections = NULL; - c->new_connection = new_connection_handler; - c->input = input_handler; - c->connection_closed = connection_closed_handler; + c->new_connection_during_keep_alive = driver->new_connection_during_keep_alive_handler; + c->new_connection = driver->new_connection_handler; + c->input = driver->input_handler; + c->connection_closed = driver->connection_closed_handler; + c->keep_client_alive = driver->keep_client_alive_handler; c->priv = priv; c->next = NULL; long portnumber; @@ -278,7 +275,7 @@ int add_service(char *name, c->sin.sin_port = htons(c->portnumber); if (bind(c->fd, (struct sockaddr *)&c->sin, sizeof(c->sin)) == -1) { - LOG_ERROR("couldn't bind %s to socket on port %d: %s", name, c->portnumber, strerror(errno)); + LOG_ERROR("couldn't bind %s to socket on port %d: %s", c->name, c->portnumber, strerror(errno)); close_socket(c->fd); free_service(c); return ERROR_FAIL; @@ -309,7 +306,7 @@ int add_service(char *name, socklen_t addr_in_size = sizeof(addr_in); if (getsockname(c->fd, (struct sockaddr *)&addr_in, &addr_in_size) == 0) LOG_INFO("Listening on port %hu for %s connections", - ntohs(addr_in.sin_port), name); + ntohs(addr_in.sin_port), c->name); } else if (c->type == CONNECTION_STDINOUT) { c->fd = fileno(stdin); @@ -424,6 +421,14 @@ static int remove_services(void) return ERROR_OK; } +void server_keep_clients_alive(void) +{ + for (struct service *s = services; s; s = s->next) + if (s->keep_client_alive) + for (struct connection *c = s->connections; c; c = c->next) + s->keep_client_alive(c); +} + int server_loop(struct command_context *command_context) { struct service *service; diff --git a/src/server/server.h b/src/server/server.h index bacd1116a..a6b1963a6 100644 --- a/src/server/server.h +++ b/src/server/server.h @@ -55,9 +55,25 @@ struct connection { struct connection *next; }; -typedef int (*new_connection_handler_t)(struct connection *connection); -typedef int (*input_handler_t)(struct connection *connection); -typedef int (*connection_closed_handler_t)(struct connection *connection); +struct service_driver { + /** the name of the server */ + const char *name; + /** optional minimal setup to accept a connection during keep-alive */ + int (*new_connection_during_keep_alive_handler)(struct connection *connection); + /** + * complete code to accept a new connection. + * If 'new_connection_during_keep_alive_handler' above is present, this can be + * either called alone during the server_loop, or after the function above. + * Check the implementation in gdb_server. + * */ + int (*new_connection_handler)(struct connection *connection); + /** callback to handle incoming data */ + int (*input_handler)(struct connection *connection); + /** callback to tear down the connection */ + int (*connection_closed_handler)(struct connection *connection); + /** called periodically to send keep-alive messages on the connection */ + void (*keep_client_alive_handler)(struct connection *connection); +}; struct service { char *name; @@ -68,17 +84,17 @@ struct service { struct sockaddr_in sin; int max_connections; struct connection *connections; - new_connection_handler_t new_connection; - input_handler_t input; - connection_closed_handler_t connection_closed; + int (*new_connection_during_keep_alive)(struct connection *connection); + int (*new_connection)(struct connection *connection); + int (*input)(struct connection *connection); + int (*connection_closed)(struct connection *connection); + void (*keep_client_alive)(struct connection *connection); void *priv; struct service *next; }; -int add_service(char *name, const char *port, - int max_connections, new_connection_handler_t new_connection_handler, - input_handler_t in_handler, connection_closed_handler_t close_handler, - void *priv); +int add_service(const struct service_driver *driver, const char *port, + int max_connections, void *priv); int remove_service(const char *name, const char *port); int server_host_os_entry(void); @@ -90,6 +106,8 @@ int server_quit(void); void server_free(void); void exit_on_signal(int sig); +void server_keep_clients_alive(void); + int server_loop(struct command_context *command_context); int server_register_commands(struct command_context *context); diff --git a/src/server/tcl_server.c b/src/server/tcl_server.c index e08823224..458d7eada 100644 --- a/src/server/tcl_server.c +++ b/src/server/tcl_server.c @@ -276,6 +276,15 @@ static int tcl_closed(struct connection *connection) return ERROR_OK; } +static const struct service_driver tcl_service_driver = { + .name = "tcl", + .new_connection_during_keep_alive_handler = NULL, + .new_connection_handler = tcl_new_connection, + .input_handler = tcl_input, + .connection_closed_handler = tcl_closed, + .keep_client_alive_handler = NULL, +}; + int tcl_init(void) { if (strcmp(tcl_port, "disabled") == 0) { @@ -283,9 +292,7 @@ int tcl_init(void) return ERROR_OK; } - return add_service("tcl", tcl_port, CONNECTION_LIMIT_UNLIMITED, - &tcl_new_connection, &tcl_input, - &tcl_closed, NULL); + return add_service(&tcl_service_driver, tcl_port, CONNECTION_LIMIT_UNLIMITED, NULL); } COMMAND_HANDLER(handle_tcl_port_command) diff --git a/src/server/telnet_server.c b/src/server/telnet_server.c index 2ebcff163..791a1a548 100644 --- a/src/server/telnet_server.c +++ b/src/server/telnet_server.c @@ -946,6 +946,15 @@ static int telnet_connection_closed(struct connection *connection) return ERROR_OK; } +static const struct service_driver telnet_service_driver = { + .name = "telnet", + .new_connection_during_keep_alive_handler = NULL, + .new_connection_handler = telnet_new_connection, + .input_handler = telnet_input, + .connection_closed_handler = telnet_connection_closed, + .keep_client_alive_handler = NULL, +}; + int telnet_init(char *banner) { if (strcmp(telnet_port, "disabled") == 0) { @@ -963,8 +972,7 @@ int telnet_init(char *banner) telnet_service->banner = banner; - int ret = add_service("telnet", telnet_port, CONNECTION_LIMIT_UNLIMITED, - telnet_new_connection, telnet_input, telnet_connection_closed, + int ret = add_service(&telnet_service_driver, telnet_port, CONNECTION_LIMIT_UNLIMITED, telnet_service); if (ret != ERROR_OK) { diff --git a/src/target/aarch64.c b/src/target/aarch64.c index a45322d2f..8838da927 100644 --- a/src/target/aarch64.c +++ b/src/target/aarch64.c @@ -1236,7 +1236,7 @@ static int aarch64_set_breakpoint(struct target *target, struct armv8_common *armv8 = &aarch64->armv8_common; struct aarch64_brp *brp_list = aarch64->brp_list; - if (breakpoint->set) { + if (breakpoint->is_set) { LOG_WARNING("breakpoint already set"); return ERROR_OK; } @@ -1249,7 +1249,7 @@ static int aarch64_set_breakpoint(struct target *target, LOG_ERROR("ERROR Can not find free Breakpoint Register Pair"); return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; } - breakpoint->set = brp_i + 1; + breakpoint_hw_set(breakpoint, brp_i); if (breakpoint->length == 2) byte_addr_select = (3 << (breakpoint->address & 0x02)); control = ((matchmode & 0x7) << 20) @@ -1333,7 +1333,7 @@ static int aarch64_set_breakpoint(struct target *target, breakpoint->address & 0xFFFFFFFFFFFFFFFE, breakpoint->length); - breakpoint->set = 0x11; /* Any nice value but 0 */ + breakpoint->is_set = true; } /* Ensure that halting debug mode is enable */ @@ -1357,7 +1357,7 @@ static int aarch64_set_context_breakpoint(struct target *target, struct armv8_common *armv8 = &aarch64->armv8_common; struct aarch64_brp *brp_list = aarch64->brp_list; - if (breakpoint->set) { + if (breakpoint->is_set) { LOG_WARNING("breakpoint already set"); return retval; } @@ -1371,7 +1371,7 @@ static int aarch64_set_context_breakpoint(struct target *target, return ERROR_FAIL; } - breakpoint->set = brp_i + 1; + breakpoint_hw_set(breakpoint, brp_i); control = ((matchmode & 0x7) << 20) | (1 << 13) | (byte_addr_select << 5) @@ -1410,7 +1410,7 @@ static int aarch64_set_hybrid_breakpoint(struct target *target, struct breakpoin struct armv8_common *armv8 = &aarch64->armv8_common; struct aarch64_brp *brp_list = aarch64->brp_list; - if (breakpoint->set) { + if (breakpoint->is_set) { LOG_WARNING("breakpoint already set"); return retval; } @@ -1435,7 +1435,7 @@ static int aarch64_set_hybrid_breakpoint(struct target *target, struct breakpoin return ERROR_FAIL; } - breakpoint->set = brp_1 + 1; + breakpoint_hw_set(breakpoint, brp_1); breakpoint->linked_brp = brp_2; control_ctx = ((ctx_machmode & 0x7) << 20) | (brp_2 << 16) @@ -1490,16 +1490,16 @@ static int aarch64_unset_breakpoint(struct target *target, struct breakpoint *br struct armv8_common *armv8 = &aarch64->armv8_common; struct aarch64_brp *brp_list = aarch64->brp_list; - if (!breakpoint->set) { + if (!breakpoint->is_set) { LOG_WARNING("breakpoint not set"); return ERROR_OK; } if (breakpoint->type == BKPT_HARD) { if ((breakpoint->address != 0) && (breakpoint->asid != 0)) { - int brp_i = breakpoint->set - 1; + int brp_i = breakpoint->number; int brp_j = breakpoint->linked_brp; - if ((brp_i < 0) || (brp_i >= aarch64->brp_num)) { + if (brp_i >= aarch64->brp_num) { LOG_DEBUG("Invalid BRP number in breakpoint"); return ERROR_OK; } @@ -1549,12 +1549,12 @@ static int aarch64_unset_breakpoint(struct target *target, struct breakpoint *br return retval; breakpoint->linked_brp = 0; - breakpoint->set = 0; + breakpoint->is_set = false; return ERROR_OK; } else { - int brp_i = breakpoint->set - 1; - if ((brp_i < 0) || (brp_i >= aarch64->brp_num)) { + int brp_i = breakpoint->number; + if (brp_i >= aarch64->brp_num) { LOG_DEBUG("Invalid BRP number in breakpoint"); return ERROR_OK; } @@ -1579,7 +1579,7 @@ static int aarch64_unset_breakpoint(struct target *target, struct breakpoint *br (uint32_t)brp_list[brp_i].value); if (retval != ERROR_OK) return retval; - breakpoint->set = 0; + breakpoint->is_set = false; return ERROR_OK; } } else { @@ -1611,7 +1611,7 @@ static int aarch64_unset_breakpoint(struct target *target, struct breakpoint *br breakpoint->address & 0xFFFFFFFFFFFFFFFE, breakpoint->length); } - breakpoint->set = 0; + breakpoint->is_set = false; return ERROR_OK; } @@ -1676,7 +1676,7 @@ static int aarch64_remove_breakpoint(struct target *target, struct breakpoint *b } #endif - if (breakpoint->set) { + if (breakpoint->is_set) { aarch64_unset_breakpoint(target, breakpoint); if (breakpoint->type == BKPT_HARD) aarch64->brp_num_available++; @@ -1696,7 +1696,7 @@ static int aarch64_set_watchpoint(struct target *target, struct armv8_common *armv8 = &aarch64->armv8_common; struct aarch64_brp *wp_list = aarch64->wp_list; - if (watchpoint->set) { + if (watchpoint->is_set) { LOG_WARNING("watchpoint already set"); return ERROR_OK; } @@ -1764,7 +1764,7 @@ static int aarch64_set_watchpoint(struct target *target, } wp_list[wp_i].used = 1; - watchpoint->set = wp_i + 1; + watchpoint_set(watchpoint, wp_i); return ERROR_OK; } @@ -1773,18 +1773,18 @@ static int aarch64_set_watchpoint(struct target *target, static int aarch64_unset_watchpoint(struct target *target, struct watchpoint *watchpoint) { - int retval, wp_i; + int retval; struct aarch64_common *aarch64 = target_to_aarch64(target); struct armv8_common *armv8 = &aarch64->armv8_common; struct aarch64_brp *wp_list = aarch64->wp_list; - if (!watchpoint->set) { + if (!watchpoint->is_set) { LOG_WARNING("watchpoint not set"); return ERROR_OK; } - wp_i = watchpoint->set - 1; - if ((wp_i < 0) || (wp_i >= aarch64->wp_num)) { + int wp_i = watchpoint->number; + if (wp_i >= aarch64->wp_num) { LOG_DEBUG("Invalid WP number in watchpoint"); return ERROR_OK; } @@ -1809,7 +1809,7 @@ static int aarch64_unset_watchpoint(struct target *target, (uint32_t)wp_list[wp_i].value); if (retval != ERROR_OK) return retval; - watchpoint->set = 0; + watchpoint->is_set = false; return ERROR_OK; } @@ -1837,7 +1837,7 @@ static int aarch64_remove_watchpoint(struct target *target, { struct aarch64_common *aarch64 = target_to_aarch64(target); - if (watchpoint->set) { + if (watchpoint->is_set) { aarch64_unset_watchpoint(target, watchpoint); aarch64->wp_num_available++; } diff --git a/src/target/arc.c b/src/target/arc.c index 4b546c3b4..471f16a98 100644 --- a/src/target/arc.c +++ b/src/target/arc.c @@ -1500,7 +1500,7 @@ static int arc_configure_actionpoint(struct target *target, uint32_t ap_num, static int arc_set_breakpoint(struct target *target, struct breakpoint *breakpoint) { - if (breakpoint->set) { + if (breakpoint->is_set) { LOG_WARNING("breakpoint already set"); return ERROR_OK; } @@ -1542,7 +1542,7 @@ static int arc_set_breakpoint(struct target *target, return ERROR_COMMAND_ARGUMENT_INVALID; } - breakpoint->set = 64; /* Any nice value but 0 */ + breakpoint->is_set = true; } else if (breakpoint->type == BKPT_HARD) { struct arc_common *arc = target_to_arc(target); struct arc_actionpoint *ap_list = arc->actionpoints_list; @@ -1563,7 +1563,7 @@ static int arc_set_breakpoint(struct target *target, breakpoint->address, AP_AC_TT_READWRITE, AP_AC_AT_INST_ADDR); if (retval == ERROR_OK) { - breakpoint->set = bp_num + 1; + breakpoint_hw_set(breakpoint, bp_num); ap_list[bp_num].used = 1; ap_list[bp_num].bp_value = breakpoint->address; ap_list[bp_num].type = ARC_AP_BREAKPOINT; @@ -1588,7 +1588,7 @@ static int arc_unset_breakpoint(struct target *target, { int retval = ERROR_OK; - if (!breakpoint->set) { + if (!breakpoint->is_set) { LOG_WARNING("breakpoint not set"); return ERROR_OK; } @@ -1633,14 +1633,14 @@ static int arc_unset_breakpoint(struct target *target, LOG_ERROR("Invalid breakpoint length: target supports only 2 or 4"); return ERROR_COMMAND_ARGUMENT_INVALID; } - breakpoint->set = 0; + breakpoint->is_set = false; } else if (breakpoint->type == BKPT_HARD) { struct arc_common *arc = target_to_arc(target); struct arc_actionpoint *ap_list = arc->actionpoints_list; - unsigned int bp_num = breakpoint->set - 1; + unsigned int bp_num = breakpoint->number; - if ((breakpoint->set == 0) || (bp_num >= arc->actionpoints_num)) { + if (bp_num >= arc->actionpoints_num) { LOG_DEBUG("Invalid actionpoint ID: %u in breakpoint: %" PRIu32, bp_num, breakpoint->unique_id); return ERROR_OK; @@ -1650,11 +1650,11 @@ static int arc_unset_breakpoint(struct target *target, breakpoint->address, AP_AC_TT_DISABLE, AP_AC_AT_INST_ADDR); if (retval == ERROR_OK) { - breakpoint->set = 0; + breakpoint->is_set = false; ap_list[bp_num].used = 0; ap_list[bp_num].bp_value = 0; - LOG_DEBUG("bpid: %" PRIu32 " - released actionpoint ID: %i", + LOG_DEBUG("bpid: %" PRIu32 " - released actionpoint ID: %u", breakpoint->unique_id, bp_num); } } else { @@ -1684,7 +1684,7 @@ static int arc_remove_breakpoint(struct target *target, struct breakpoint *breakpoint) { if (target->state == TARGET_HALTED) { - if (breakpoint->set) + if (breakpoint->is_set) CHECK_RETVAL(arc_unset_breakpoint(target, breakpoint)); } else { LOG_WARNING("target not halted"); @@ -1818,7 +1818,7 @@ static int arc_set_watchpoint(struct target *target, struct arc_common *arc = target_to_arc(target); struct arc_actionpoint *ap_list = arc->actionpoints_list; - if (watchpoint->set) { + if (watchpoint->is_set) { LOG_WARNING("watchpoint already set"); return ERROR_OK; } @@ -1859,7 +1859,7 @@ static int arc_set_watchpoint(struct target *target, watchpoint->address, enable, AP_AC_AT_MEMORY_ADDR); if (retval == ERROR_OK) { - watchpoint->set = wp_num + 1; + watchpoint_set(watchpoint, wp_num); ap_list[wp_num].used = 1; ap_list[wp_num].bp_value = watchpoint->address; ap_list[wp_num].type = ARC_AP_WATCHPOINT; @@ -1878,13 +1878,13 @@ static int arc_unset_watchpoint(struct target *target, struct arc_common *arc = target_to_arc(target); struct arc_actionpoint *ap_list = arc->actionpoints_list; - if (!watchpoint->set) { + if (!watchpoint->is_set) { LOG_WARNING("watchpoint not set"); return ERROR_OK; } - unsigned int wp_num = watchpoint->set - 1; - if ((watchpoint->set == 0) || (wp_num >= arc->actionpoints_num)) { + unsigned int wp_num = watchpoint->number; + if (wp_num >= arc->actionpoints_num) { LOG_DEBUG("Invalid actionpoint ID: %u in watchpoint: %" PRIu32, wp_num, watchpoint->unique_id); return ERROR_OK; @@ -1894,7 +1894,7 @@ static int arc_unset_watchpoint(struct target *target, watchpoint->address, AP_AC_TT_DISABLE, AP_AC_AT_MEMORY_ADDR); if (retval == ERROR_OK) { - watchpoint->set = 0; + watchpoint->is_set = false; ap_list[wp_num].used = 0; ap_list[wp_num].bp_value = 0; @@ -1926,7 +1926,7 @@ static int arc_remove_watchpoint(struct target *target, return ERROR_TARGET_NOT_HALTED; } - if (watchpoint->set) + if (watchpoint->is_set) CHECK_RETVAL(arc_unset_watchpoint(target, watchpoint)); return ERROR_OK; @@ -1953,8 +1953,8 @@ static int arc_hit_watchpoint(struct target *target, struct watchpoint **hit_wat watchpoint = watchpoint->next) { if (actionpoint->bp_value == watchpoint->address) { *hit_watchpoint = watchpoint; - LOG_DEBUG("Hit watchpoint, wpid: %" PRIu32 ", watchpoint num: %i", - watchpoint->unique_id, watchpoint->set - 1); + LOG_DEBUG("Hit watchpoint, wpid: %" PRIu32 ", watchpoint num: %u", + watchpoint->unique_id, watchpoint->number); return ERROR_OK; } } diff --git a/src/target/arm7_9_common.c b/src/target/arm7_9_common.c index cf77a81a7..da047c3d0 100644 --- a/src/target/arm7_9_common.c +++ b/src/target/arm7_9_common.c @@ -93,19 +93,20 @@ static void arm7_9_assign_wp(struct arm7_9_common *arm7_9, struct breakpoint *br { if (!arm7_9->wp0_used) { arm7_9->wp0_used = 1; - breakpoint->set = 1; + breakpoint_hw_set(breakpoint, 0); arm7_9->wp_available--; } else if (!arm7_9->wp1_used) { arm7_9->wp1_used = 1; - breakpoint->set = 2; + breakpoint_hw_set(breakpoint, 1); arm7_9->wp_available--; - } else + } else { LOG_ERROR("BUG: no hardware comparator available"); + } - LOG_DEBUG("BPID: %" PRIu32 " (0x%08" TARGET_PRIxADDR ") using hw wp: %d", + LOG_DEBUG("BPID: %" PRIu32 " (0x%08" TARGET_PRIxADDR ") using hw wp: %u", breakpoint->unique_id, breakpoint->address, - breakpoint->set); + breakpoint->number); } /** @@ -203,16 +204,16 @@ static int arm7_9_set_breakpoint(struct target *target, struct breakpoint *break uint32_t mask = (breakpoint->length == 4) ? 0x3u : 0x1u; /* reassign a hw breakpoint */ - if (breakpoint->set == 0) + if (!breakpoint->is_set) arm7_9_assign_wp(arm7_9, breakpoint); - if (breakpoint->set == 1) { + if (breakpoint->number == 0) { embeddedice_set_reg(&arm7_9->eice_cache->reg_list[EICE_W0_ADDR_VALUE], breakpoint->address); embeddedice_set_reg(&arm7_9->eice_cache->reg_list[EICE_W0_ADDR_MASK], mask); embeddedice_set_reg(&arm7_9->eice_cache->reg_list[EICE_W0_DATA_MASK], 0xffffffffu); embeddedice_set_reg(&arm7_9->eice_cache->reg_list[EICE_W0_CONTROL_MASK], ~EICE_W_CTRL_NOPC & 0xff); embeddedice_set_reg(&arm7_9->eice_cache->reg_list[EICE_W0_CONTROL_VALUE], EICE_W_CTRL_ENABLE); - } else if (breakpoint->set == 2) { + } else if (breakpoint->number == 1) { embeddedice_set_reg(&arm7_9->eice_cache->reg_list[EICE_W1_ADDR_VALUE], breakpoint->address); embeddedice_set_reg(&arm7_9->eice_cache->reg_list[EICE_W1_ADDR_MASK], mask); embeddedice_set_reg(&arm7_9->eice_cache->reg_list[EICE_W1_DATA_MASK], 0xffffffffu); @@ -226,7 +227,7 @@ static int arm7_9_set_breakpoint(struct target *target, struct breakpoint *break retval = jtag_execute_queue(); } else if (breakpoint->type == BKPT_SOFT) { /* did we already set this breakpoint? */ - if (breakpoint->set) + if (breakpoint->is_set) return ERROR_OK; if (breakpoint->length == 4) { @@ -277,7 +278,7 @@ static int arm7_9_set_breakpoint(struct target *target, struct breakpoint *break arm7_9->sw_breakpoint_count++; - breakpoint->set = 1; + breakpoint->is_set = true; } return retval; @@ -304,7 +305,7 @@ static int arm7_9_unset_breakpoint(struct target *target, struct breakpoint *bre breakpoint->unique_id, breakpoint->address); - if (!breakpoint->set) { + if (!breakpoint->is_set) { LOG_WARNING("breakpoint not set"); return ERROR_OK; } @@ -312,18 +313,18 @@ static int arm7_9_unset_breakpoint(struct target *target, struct breakpoint *bre if (breakpoint->type == BKPT_HARD) { LOG_DEBUG("BPID: %" PRIu32 " Releasing hw wp: %d", breakpoint->unique_id, - breakpoint->set); - if (breakpoint->set == 1) { + breakpoint->is_set); + if (breakpoint->number == 0) { embeddedice_set_reg(&arm7_9->eice_cache->reg_list[EICE_W0_CONTROL_VALUE], 0x0); arm7_9->wp0_used = 0; arm7_9->wp_available++; - } else if (breakpoint->set == 2) { + } else if (breakpoint->number == 1) { embeddedice_set_reg(&arm7_9->eice_cache->reg_list[EICE_W1_CONTROL_VALUE], 0x0); arm7_9->wp1_used = 0; arm7_9->wp_available++; } retval = jtag_execute_queue(); - breakpoint->set = 0; + breakpoint->is_set = false; } else { /* restore original instruction (kept in target endianness) */ if (breakpoint->length == 4) { @@ -368,7 +369,7 @@ static int arm7_9_unset_breakpoint(struct target *target, struct breakpoint *bre EICE_W1_CONTROL_VALUE], 0); } - breakpoint->set = 0; + breakpoint->is_set = false; } return retval; @@ -491,7 +492,7 @@ static int arm7_9_set_watchpoint(struct target *target, struct watchpoint *watch retval = jtag_execute_queue(); if (retval != ERROR_OK) return retval; - watchpoint->set = 1; + watchpoint_set(watchpoint, 1); arm7_9->wp0_used = 2; } else if (!arm7_9->wp1_used) { embeddedice_set_reg(&arm7_9->eice_cache->reg_list[EICE_W1_ADDR_VALUE], @@ -510,7 +511,7 @@ static int arm7_9_set_watchpoint(struct target *target, struct watchpoint *watch retval = jtag_execute_queue(); if (retval != ERROR_OK) return retval; - watchpoint->set = 2; + watchpoint_set(watchpoint, 2); arm7_9->wp1_used = 2; } else { LOG_ERROR("BUG: no hardware comparator available"); @@ -538,25 +539,25 @@ static int arm7_9_unset_watchpoint(struct target *target, struct watchpoint *wat return ERROR_TARGET_NOT_HALTED; } - if (!watchpoint->set) { + if (!watchpoint->is_set) { LOG_WARNING("breakpoint not set"); return ERROR_OK; } - if (watchpoint->set == 1) { + if (watchpoint->number == 1) { embeddedice_set_reg(&arm7_9->eice_cache->reg_list[EICE_W0_CONTROL_VALUE], 0x0); retval = jtag_execute_queue(); if (retval != ERROR_OK) return retval; arm7_9->wp0_used = 0; - } else if (watchpoint->set == 2) { + } else if (watchpoint->number == 2) { embeddedice_set_reg(&arm7_9->eice_cache->reg_list[EICE_W1_CONTROL_VALUE], 0x0); retval = jtag_execute_queue(); if (retval != ERROR_OK) return retval; arm7_9->wp1_used = 0; } - watchpoint->set = 0; + watchpoint->is_set = false; return ERROR_OK; } @@ -597,7 +598,7 @@ int arm7_9_remove_watchpoint(struct target *target, struct watchpoint *watchpoin int retval = ERROR_OK; struct arm7_9_common *arm7_9 = target_to_arm7_9(target); - if (watchpoint->set) { + if (watchpoint->is_set) { retval = arm7_9_unset_watchpoint(target, watchpoint); if (retval != ERROR_OK) return retval; @@ -1684,7 +1685,7 @@ static void arm7_9_enable_watchpoints(struct target *target) struct watchpoint *watchpoint = target->watchpoints; while (watchpoint) { - if (watchpoint->set == 0) + if (!watchpoint->is_set) arm7_9_set_watchpoint(target, watchpoint); watchpoint = watchpoint->next; } diff --git a/src/target/arm_dpm.c b/src/target/arm_dpm.c index 3e55e2e3a..e60ef225d 100644 --- a/src/target/arm_dpm.c +++ b/src/target/arm_dpm.c @@ -398,7 +398,7 @@ fail: * or running debugger code. */ static int dpm_maybe_update_bpwp(struct arm_dpm *dpm, bool bpwp, - struct dpm_bpwp *xp, int *set_p) + struct dpm_bpwp *xp, bool *set_p) { int retval = ERROR_OK; bool disable; @@ -473,7 +473,7 @@ int arm_dpm_write_dirty_registers(struct arm_dpm *dpm, bool bpwp) struct breakpoint *bp = dbp->bp; retval = dpm_maybe_update_bpwp(dpm, bpwp, &dbp->bpwp, - bp ? &bp->set : NULL); + bp ? &bp->is_set : NULL); if (retval != ERROR_OK) goto done; } @@ -485,7 +485,7 @@ int arm_dpm_write_dirty_registers(struct arm_dpm *dpm, bool bpwp) struct watchpoint *wp = dwp->wp; retval = dpm_maybe_update_bpwp(dpm, bpwp, &dwp->bpwp, - wp ? &wp->set : NULL); + wp ? &wp->is_set : NULL); if (retval != ERROR_OK) goto done; } diff --git a/src/target/arm_tpiu_swo.c b/src/target/arm_tpiu_swo.c index 024521364..fba3fec4f 100644 --- a/src/target/arm_tpiu_swo.c +++ b/src/target/arm_tpiu_swo.c @@ -582,6 +582,15 @@ static int wrap_read_u32(struct target *target, struct adiv5_ap *tpiu_ap, return mem_ap_read_atomic_u32(tpiu_ap, address, value); } +static const struct service_driver arm_tpiu_swo_service_driver = { + .name = "tpiu_swo_trace", + .new_connection_during_keep_alive_handler = NULL, + .new_connection_handler = arm_tpiu_swo_service_new_connection, + .input_handler = arm_tpiu_swo_service_input, + .connection_closed_handler = arm_tpiu_swo_service_connection_closed, + .keep_client_alive_handler = NULL, +}; + static int jim_arm_tpiu_swo_enable(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { struct command *c = jim_to_command(interp); @@ -616,10 +625,8 @@ static int jim_arm_tpiu_swo_enable(Jim_Interp *interp, int argc, Jim_Obj *const } if (obj->pin_protocol == TPIU_SPPR_PROTOCOL_MANCHESTER || obj->pin_protocol == TPIU_SPPR_PROTOCOL_UART) - if (!obj->swo_pin_freq) { - LOG_ERROR("SWO pin frequency not set"); - return JIM_ERR; - } + if (!obj->swo_pin_freq) + LOG_DEBUG("SWO pin frequency not set, will be autodetected by the adapter"); struct target *target = get_current_target(cmd_ctx); @@ -700,10 +707,8 @@ static int jim_arm_tpiu_swo_enable(Jim_Interp *interp, int argc, Jim_Obj *const } priv->obj = obj; LOG_INFO("starting trace server for %s on %s", obj->name, &obj->out_filename[1]); - retval = add_service("tpiu_swo_trace", &obj->out_filename[1], - CONNECTION_LIMIT_UNLIMITED, arm_tpiu_swo_service_new_connection, - arm_tpiu_swo_service_input, arm_tpiu_swo_service_connection_closed, - priv); + retval = add_service(&arm_tpiu_swo_service_driver, &obj->out_filename[1], + CONNECTION_LIMIT_UNLIMITED, priv); if (retval != ERROR_OK) { LOG_ERROR("Can't configure trace TCP port %s", &obj->out_filename[1]); return JIM_ERR; @@ -724,6 +729,17 @@ static int jim_arm_tpiu_swo_enable(Jim_Interp *interp, int argc, Jim_Obj *const return JIM_ERR; } + if (obj->pin_protocol == TPIU_SPPR_PROTOCOL_MANCHESTER || obj->pin_protocol == TPIU_SPPR_PROTOCOL_UART) + if (!swo_pin_freq) { + if (obj->swo_pin_freq) + LOG_ERROR("Adapter rejected SWO pin frequency %d Hz", obj->swo_pin_freq); + else + LOG_ERROR("Adapter does not support auto-detection of SWO pin frequency nor a default value"); + + arm_tpiu_swo_close_output(obj); + return JIM_ERR; + } + if (obj->swo_pin_freq != swo_pin_freq) LOG_INFO("SWO pin data rate adjusted by adapter to %d Hz", swo_pin_freq); obj->swo_pin_freq = swo_pin_freq; @@ -886,7 +902,8 @@ static int arm_tpiu_swo_create(Jim_Interp *interp, struct arm_tpiu_swo_object *o /* does this command exist? */ cmd = Jim_GetCommand(interp, Jim_NewStringObj(interp, obj->name, -1), JIM_NONE); if (cmd) { - Jim_SetResultFormatted(interp, "Command: %s Exists", obj->name); + Jim_SetResultFormatted(interp, "cannot create TPIU object because a command with name '%s' already exists", + obj->name); return JIM_ERR; } @@ -915,7 +932,7 @@ static int jim_arm_tpiu_swo_create(Jim_Interp *interp, int argc, Jim_Obj *const struct jim_getopt_info goi; jim_getopt_setup(&goi, interp, argc - 1, argv + 1); if (goi.argc < 1) { - Jim_WrongNumArgs(goi.interp, 1, goi.argv, "?name? ..options..."); + Jim_WrongNumArgs(interp, 1, argv, "name ?option option ...?"); return JIM_ERR; } @@ -1160,7 +1177,7 @@ static const struct command_registration arm_tpiu_swo_subcommand_handlers[] = { .name = "create", .mode = COMMAND_ANY, .jim_handler = jim_arm_tpiu_swo_create, - .usage = "name [-dap dap] [-ap-num num] [-address baseaddr]", + .usage = "name [-dap dap] [-ap-num num] [-baseaddr baseaddr]", .help = "Creates a new TPIU or SWO object", }, { diff --git a/src/target/armv8_dpm.c b/src/target/armv8_dpm.c index 188e58822..765f1b777 100644 --- a/src/target/armv8_dpm.c +++ b/src/target/armv8_dpm.c @@ -818,7 +818,7 @@ fail: * or running debugger code. */ static int dpmv8_maybe_update_bpwp(struct arm_dpm *dpm, bool bpwp, - struct dpm_bpwp *xp, int *set_p) + struct dpm_bpwp *xp, bool *set_p) { int retval = ERROR_OK; bool disable; @@ -892,7 +892,7 @@ int armv8_dpm_write_dirty_registers(struct arm_dpm *dpm, bool bpwp) struct breakpoint *bp = dbp->bp; retval = dpmv8_maybe_update_bpwp(dpm, bpwp, &dbp->bpwp, - bp ? &bp->set : NULL); + bp ? &bp->is_set : NULL); if (retval != ERROR_OK) goto done; } @@ -904,7 +904,7 @@ int armv8_dpm_write_dirty_registers(struct arm_dpm *dpm, bool bpwp) struct watchpoint *wp = dwp->wp; retval = dpmv8_maybe_update_bpwp(dpm, bpwp, &dwp->bpwp, - wp ? &wp->set : NULL); + wp ? &wp->is_set : NULL); if (retval != ERROR_OK) goto done; } diff --git a/src/target/breakpoints.c b/src/target/breakpoints.c index 44c7a2c71..3bfdbde91 100644 --- a/src/target/breakpoints.c +++ b/src/target/breakpoints.c @@ -72,7 +72,7 @@ static int breakpoint_add_internal(struct target *target, (*breakpoint_p)->asid = 0; (*breakpoint_p)->length = length; (*breakpoint_p)->type = type; - (*breakpoint_p)->set = 0; + (*breakpoint_p)->is_set = false; (*breakpoint_p)->orig_instr = malloc(length); (*breakpoint_p)->next = NULL; (*breakpoint_p)->unique_id = bpwp_unique_id++; @@ -135,7 +135,7 @@ static int context_breakpoint_add_internal(struct target *target, (*breakpoint_p)->asid = asid; (*breakpoint_p)->length = length; (*breakpoint_p)->type = type; - (*breakpoint_p)->set = 0; + (*breakpoint_p)->is_set = false; (*breakpoint_p)->orig_instr = malloc(length); (*breakpoint_p)->next = NULL; (*breakpoint_p)->unique_id = bpwp_unique_id++; @@ -189,7 +189,7 @@ static int hybrid_breakpoint_add_internal(struct target *target, (*breakpoint_p)->asid = asid; (*breakpoint_p)->length = length; (*breakpoint_p)->type = type; - (*breakpoint_p)->set = 0; + (*breakpoint_p)->is_set = false; (*breakpoint_p)->orig_instr = malloc(length); (*breakpoint_p)->next = NULL; (*breakpoint_p)->unique_id = bpwp_unique_id++; diff --git a/src/target/breakpoints.h b/src/target/breakpoints.h index b4a3511d2..0a5949594 100644 --- a/src/target/breakpoints.h +++ b/src/target/breakpoints.h @@ -39,7 +39,8 @@ struct breakpoint { uint32_t asid; int length; enum breakpoint_type type; - int set; + bool is_set; + unsigned int number; uint8_t *orig_instr; struct breakpoint *next; uint32_t unique_id; @@ -52,7 +53,8 @@ struct watchpoint { uint32_t mask; uint32_t value; enum watchpoint_rw rw; - int set; + bool is_set; + unsigned int number; struct watchpoint *next; int unique_id; }; @@ -69,6 +71,12 @@ void breakpoint_remove_all(struct target *target); struct breakpoint *breakpoint_find(struct target *target, target_addr_t address); +static inline void breakpoint_hw_set(struct breakpoint *breakpoint, unsigned int hw_number) +{ + breakpoint->is_set = true; + breakpoint->number = hw_number; +} + void watchpoint_clear_target(struct target *target); int watchpoint_add(struct target *target, target_addr_t address, uint32_t length, @@ -79,4 +87,10 @@ void watchpoint_remove(struct target *target, target_addr_t address); int watchpoint_hit(struct target *target, enum watchpoint_rw *rw, target_addr_t *address); +static inline void watchpoint_set(struct watchpoint *watchpoint, unsigned int number) +{ + watchpoint->is_set = true; + watchpoint->number = number; +} + #endif /* OPENOCD_TARGET_BREAKPOINTS_H */ diff --git a/src/target/cortex_a.c b/src/target/cortex_a.c index 272411359..2dc109108 100644 --- a/src/target/cortex_a.c +++ b/src/target/cortex_a.c @@ -1185,7 +1185,7 @@ static int cortex_a_step(struct target *target, int current, target_addr_t addre stepbreakpoint.length = (arm->core_state == ARM_STATE_THUMB) ? 2 : 4; stepbreakpoint.type = BKPT_HARD; - stepbreakpoint.set = 0; + stepbreakpoint.is_set = false; /* Disable interrupts during single step if requested */ if (cortex_a->isrmasking_mode == CORTEX_A_ISRMASK_ON) { @@ -1265,7 +1265,7 @@ static int cortex_a_set_breakpoint(struct target *target, struct armv7a_common *armv7a = &cortex_a->armv7a_common; struct cortex_a_brp *brp_list = cortex_a->brp_list; - if (breakpoint->set) { + if (breakpoint->is_set) { LOG_WARNING("breakpoint already set"); return ERROR_OK; } @@ -1277,7 +1277,7 @@ static int cortex_a_set_breakpoint(struct target *target, LOG_ERROR("ERROR Can not find free Breakpoint Register Pair"); return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; } - breakpoint->set = brp_i + 1; + breakpoint_hw_set(breakpoint, brp_i); if (breakpoint->length == 2) byte_addr_select = (3 << (breakpoint->address & 0x02)); control = ((matchmode & 0x7) << 20) @@ -1342,7 +1342,7 @@ static int cortex_a_set_breakpoint(struct target *target, armv7a_l1_i_cache_inval_virt(target, breakpoint->address, breakpoint->length); - breakpoint->set = 0x11; /* Any nice value but 0 */ + breakpoint->is_set = true; } return ERROR_OK; @@ -1359,7 +1359,7 @@ static int cortex_a_set_context_breakpoint(struct target *target, struct armv7a_common *armv7a = &cortex_a->armv7a_common; struct cortex_a_brp *brp_list = cortex_a->brp_list; - if (breakpoint->set) { + if (breakpoint->is_set) { LOG_WARNING("breakpoint already set"); return retval; } @@ -1373,7 +1373,7 @@ static int cortex_a_set_context_breakpoint(struct target *target, return ERROR_FAIL; } - breakpoint->set = brp_i + 1; + breakpoint_hw_set(breakpoint, brp_i); control = ((matchmode & 0x7) << 20) | (byte_addr_select << 5) | (3 << 1) | 1; @@ -1411,7 +1411,7 @@ static int cortex_a_set_hybrid_breakpoint(struct target *target, struct breakpoi struct armv7a_common *armv7a = &cortex_a->armv7a_common; struct cortex_a_brp *brp_list = cortex_a->brp_list; - if (breakpoint->set) { + if (breakpoint->is_set) { LOG_WARNING("breakpoint already set"); return retval; } @@ -1436,7 +1436,7 @@ static int cortex_a_set_hybrid_breakpoint(struct target *target, struct breakpoi return ERROR_FAIL; } - breakpoint->set = brp_1 + 1; + breakpoint_hw_set(breakpoint, brp_1); breakpoint->linked_brp = brp_2; control_ctx = ((ctx_machmode & 0x7) << 20) | (brp_2 << 16) @@ -1485,16 +1485,16 @@ static int cortex_a_unset_breakpoint(struct target *target, struct breakpoint *b struct armv7a_common *armv7a = &cortex_a->armv7a_common; struct cortex_a_brp *brp_list = cortex_a->brp_list; - if (!breakpoint->set) { + if (!breakpoint->is_set) { LOG_WARNING("breakpoint not set"); return ERROR_OK; } if (breakpoint->type == BKPT_HARD) { if ((breakpoint->address != 0) && (breakpoint->asid != 0)) { - int brp_i = breakpoint->set - 1; + int brp_i = breakpoint->number; int brp_j = breakpoint->linked_brp; - if ((brp_i < 0) || (brp_i >= cortex_a->brp_num)) { + if (brp_i >= cortex_a->brp_num) { LOG_DEBUG("Invalid BRP number in breakpoint"); return ERROR_OK; } @@ -1533,12 +1533,12 @@ static int cortex_a_unset_breakpoint(struct target *target, struct breakpoint *b if (retval != ERROR_OK) return retval; breakpoint->linked_brp = 0; - breakpoint->set = 0; + breakpoint->is_set = false; return ERROR_OK; } else { - int brp_i = breakpoint->set - 1; - if ((brp_i < 0) || (brp_i >= cortex_a->brp_num)) { + int brp_i = breakpoint->number; + if (brp_i >= cortex_a->brp_num) { LOG_DEBUG("Invalid BRP number in breakpoint"); return ERROR_OK; } @@ -1557,7 +1557,7 @@ static int cortex_a_unset_breakpoint(struct target *target, struct breakpoint *b brp_list[brp_i].value); if (retval != ERROR_OK) return retval; - breakpoint->set = 0; + breakpoint->is_set = false; return ERROR_OK; } } else { @@ -1589,7 +1589,7 @@ static int cortex_a_unset_breakpoint(struct target *target, struct breakpoint *b armv7a_l1_i_cache_inval_virt(target, breakpoint->address, breakpoint->length); } - breakpoint->set = 0; + breakpoint->is_set = false; return ERROR_OK; } @@ -1655,7 +1655,7 @@ static int cortex_a_remove_breakpoint(struct target *target, struct breakpoint * } #endif - if (breakpoint->set) { + if (breakpoint->is_set) { cortex_a_unset_breakpoint(target, breakpoint); if (breakpoint->type == BKPT_HARD) cortex_a->brp_num_available++; @@ -1688,7 +1688,7 @@ static int cortex_a_set_watchpoint(struct target *target, struct watchpoint *wat struct armv7a_common *armv7a = &cortex_a->armv7a_common; struct cortex_a_wrp *wrp_list = cortex_a->wrp_list; - if (watchpoint->set) { + if (watchpoint->is_set) { LOG_WARNING("watchpoint already set"); return retval; } @@ -1741,7 +1741,7 @@ static int cortex_a_set_watchpoint(struct target *target, struct watchpoint *wat break; } - watchpoint->set = wrp_i + 1; + watchpoint_set(watchpoint, wrp_i); control = (address_mask << 24) | (byte_address_select << 5) | (load_store_access_control << 3) | @@ -1784,13 +1784,13 @@ static int cortex_a_unset_watchpoint(struct target *target, struct watchpoint *w struct armv7a_common *armv7a = &cortex_a->armv7a_common; struct cortex_a_wrp *wrp_list = cortex_a->wrp_list; - if (!watchpoint->set) { + if (!watchpoint->is_set) { LOG_WARNING("watchpoint not set"); return ERROR_OK; } - int wrp_i = watchpoint->set - 1; - if (wrp_i < 0 || wrp_i >= cortex_a->wrp_num) { + int wrp_i = watchpoint->number; + if (wrp_i >= cortex_a->wrp_num) { LOG_DEBUG("Invalid WRP number in watchpoint"); return ERROR_OK; } @@ -1809,7 +1809,7 @@ static int cortex_a_unset_watchpoint(struct target *target, struct watchpoint *w wrp_list[wrp_i].value); if (retval != ERROR_OK) return retval; - watchpoint->set = 0; + watchpoint->is_set = false; return ERROR_OK; } @@ -1851,7 +1851,7 @@ static int cortex_a_remove_watchpoint(struct target *target, struct watchpoint * { struct cortex_a_common *cortex_a = target_to_cortex_a(target); - if (watchpoint->set) { + if (watchpoint->is_set) { cortex_a->wrp_num_available++; cortex_a_unset_watchpoint(target, watchpoint); } diff --git a/src/target/cortex_m.c b/src/target/cortex_m.c index 7125e9e83..344cfcf61 100644 --- a/src/target/cortex_m.c +++ b/src/target/cortex_m.c @@ -185,7 +185,7 @@ static int cortex_m_load_core_reg_u32(struct target *target, break; cortex_m->slow_register_read = true; /* Polling (still) needed. */ if (timeval_ms() > then + DHCSR_S_REGRDY_TIMEOUT) { - LOG_ERROR("Timeout waiting for DCRDR transfer ready"); + LOG_TARGET_ERROR(target, "Timeout waiting for DCRDR transfer ready"); return ERROR_TIMEOUT_REACHED; } keep_alive(); @@ -223,7 +223,7 @@ static int cortex_m_slow_read_all_regs(struct target *target) } if (!cortex_m->slow_register_read) - LOG_DEBUG("Switching back to fast register reads"); + LOG_TARGET_DEBUG(target, "Switching back to fast register reads"); return ERROR_OK; } @@ -319,7 +319,7 @@ static int cortex_m_fast_read_all_regs(struct target *target) for (unsigned int i = 0; i < wi; i++) { if ((dhcsr[i] & S_REGRDY) == 0) { not_ready = true; - LOG_DEBUG("Register %u was not ready during fast read", i); + LOG_TARGET_DEBUG(target, "Register %u was not ready during fast read", i); } cortex_m_cumulate_dhcsr_sticky(cortex_m, dhcsr[i]); } @@ -330,7 +330,7 @@ static int cortex_m_fast_read_all_regs(struct target *target) return ERROR_TIMEOUT_REACHED; } - LOG_DEBUG("read %u 32-bit registers", wi); + LOG_TARGET_DEBUG(target, "read %u 32-bit registers", wi); unsigned int ri = 0; /* read index from r_vals array */ for (reg_id = 0; reg_id < num_regs; reg_id++) { @@ -403,7 +403,7 @@ static int cortex_m_store_core_reg_u32(struct target *target, if (cortex_m->dcb_dhcsr & S_REGRDY) break; if (timeval_ms() > then + DHCSR_S_REGRDY_TIMEOUT) { - LOG_ERROR("Timeout waiting for DCRDR transfer ready"); + LOG_TARGET_ERROR(target, "Timeout waiting for DCRDR transfer ready"); return ERROR_TIMEOUT_REACHED; } keep_alive(); @@ -528,7 +528,7 @@ static int cortex_m_clear_halt(struct target *target) retval = mem_ap_write_atomic_u32(armv7m->debug_ap, NVIC_DFSR, cortex_m->nvic_dfsr); if (retval != ERROR_OK) return retval; - LOG_DEBUG(" NVIC_DFSR 0x%" PRIx32 "", cortex_m->nvic_dfsr); + LOG_TARGET_DEBUG(target, "NVIC_DFSR 0x%" PRIx32 "", cortex_m->nvic_dfsr); return ERROR_OK; } @@ -550,7 +550,7 @@ static int cortex_m_single_step_core(struct target *target) retval = cortex_m_write_debug_halt_mask(target, C_STEP, C_HALT); if (retval != ERROR_OK) return retval; - LOG_DEBUG(" "); + LOG_TARGET_DEBUG(target, "single step"); /* restore dhcsr reg */ cortex_m_clear_halt(target); @@ -590,7 +590,7 @@ static int cortex_m_endreset_event(struct target *target) retval = mem_ap_read_atomic_u32(armv7m->debug_ap, DCB_DEMCR, &dcb_demcr); if (retval != ERROR_OK) return retval; - LOG_DEBUG("DCB_DEMCR = 0x%8.8" PRIx32 "", dcb_demcr); + LOG_TARGET_DEBUG(target, "DCB_DEMCR = 0x%8.8" PRIx32 "", dcb_demcr); /* this register is used for emulated dcc channel */ retval = mem_ap_write_u32(armv7m->debug_ap, DCB_DCRDR, 0); @@ -629,7 +629,7 @@ static int cortex_m_endreset_event(struct target *target) /* Enable FPB */ retval = cortex_m_enable_fpb(target); if (retval != ERROR_OK) { - LOG_ERROR("Failed to enable the FPB"); + LOG_TARGET_ERROR(target, "Failed to enable the FPB"); return retval; } @@ -766,7 +766,7 @@ static int cortex_m_examine_exception_reason(struct target *target) } retval = dap_run(swjdp); if (retval == ERROR_OK) - LOG_DEBUG("%s SHCSR 0x%" PRIx32 ", SR 0x%" PRIx32 + LOG_TARGET_DEBUG(target, "%s SHCSR 0x%" PRIx32 ", SR 0x%" PRIx32 ", CFSR 0x%" PRIx32 ", AR 0x%" PRIx32, armv7m_exception_string(armv7m->exception_number), shcsr, except_sr, cfsr, except_ar); @@ -782,7 +782,7 @@ static int cortex_m_debug_entry(struct target *target) struct arm *arm = &armv7m->arm; struct reg *r; - LOG_DEBUG(" "); + LOG_TARGET_DEBUG(target, " "); /* Do this really early to minimize the window where the MASKINTS erratum * can pile up pending interrupts. */ @@ -815,7 +815,7 @@ static int cortex_m_debug_entry(struct target *target) retval = cortex_m_fast_read_all_regs(target); if (retval == ERROR_TIMEOUT_REACHED) { cortex_m->slow_register_read = true; - LOG_DEBUG("Switched to slow register read"); + LOG_TARGET_DEBUG(target, "Switched to slow register read"); } } @@ -855,7 +855,8 @@ static int cortex_m_debug_entry(struct target *target) if (armv7m->exception_number) cortex_m_examine_exception_reason(target); - LOG_DEBUG("entered debug state in core mode: %s at PC 0x%" PRIx32 ", cpu in %s state, target->state: %s", + LOG_TARGET_DEBUG(target, "entered debug state in core mode: %s at PC 0x%" PRIx32 + ", cpu in %s state, target->state: %s", arm_mode_name(arm->core_mode), buf_get_u32(arm->pc->value, 0, 32), secure_state ? "Secure" : "Non-Secure", @@ -889,8 +890,7 @@ static int cortex_m_poll(struct target *target) * section B1.5.15 "Unrecoverable exception cases". */ if (cortex_m->dcb_dhcsr & S_LOCKUP) { - LOG_ERROR("%s -- clearing lockup after double fault", - target_name(target)); + LOG_TARGET_ERROR(target, "clearing lockup after double fault"); cortex_m_write_debug_halt_mask(target, C_HALT, 0); target->debug_reason = DBG_REASON_DBGRQ; @@ -909,7 +909,7 @@ static int cortex_m_poll(struct target *target) cortex_m->dcb_dhcsr_cumulated_sticky &= ~S_RESET_ST; if (target->state != TARGET_RESET) { target->state = TARGET_RESET; - LOG_INFO("%s: external reset detected", target_name(target)); + LOG_TARGET_INFO(target, "external reset detected"); } return ERROR_OK; } @@ -918,7 +918,7 @@ static int cortex_m_poll(struct target *target) /* Cannot switch context while running so endreset is * called with target->state == TARGET_RESET */ - LOG_DEBUG("Exit from reset with dcb_dhcsr 0x%" PRIx32, + LOG_TARGET_DEBUG(target, "Exit from reset with dcb_dhcsr 0x%" PRIx32, cortex_m->dcb_dhcsr); retval = cortex_m_endreset_event(target); if (retval != ERROR_OK) { @@ -943,7 +943,6 @@ static int cortex_m_poll(struct target *target) target_call_event_callbacks(target, TARGET_EVENT_HALTED); } if (prev_target_state == TARGET_DEBUG_RUNNING) { - LOG_DEBUG(" "); retval = cortex_m_debug_entry(target); if (retval != ERROR_OK) return retval; @@ -971,7 +970,7 @@ static int cortex_m_poll(struct target *target) register_cache_invalidate(armv7m->arm.core_cache); target->state = TARGET_RUNNING; - LOG_WARNING("%s: external resume detected", target_name(target)); + LOG_TARGET_WARNING(target, "external resume detected"); target_call_event_callbacks(target, TARGET_EVENT_RESUMED); retval = ERROR_OK; } @@ -984,20 +983,19 @@ static int cortex_m_poll(struct target *target) static int cortex_m_halt(struct target *target) { - LOG_DEBUG("target->state: %s", - target_state_name(target)); + LOG_TARGET_DEBUG(target, "target->state: %s", target_state_name(target)); if (target->state == TARGET_HALTED) { - LOG_DEBUG("target was already halted"); + LOG_TARGET_DEBUG(target, "target was already halted"); return ERROR_OK; } if (target->state == TARGET_UNKNOWN) - LOG_WARNING("target was in unknown state when halt was requested"); + LOG_TARGET_WARNING(target, "target was in unknown state when halt was requested"); if (target->state == TARGET_RESET) { if ((jtag_get_reset_config() & RESET_SRST_PULLS_TRST) && jtag_get_srst()) { - LOG_ERROR("can't request a halt while in reset if nSRST pulls nTRST"); + LOG_TARGET_ERROR(target, "can't request a halt while in reset if nSRST pulls nTRST"); return ERROR_TARGET_FAILURE; } else { /* we came here in a reset_halt or reset_init sequence @@ -1031,10 +1029,10 @@ static int cortex_m_soft_reset_halt(struct target *target) * can be obtained by using 'reset halt' and 'cortex_m reset_config vectreset'. * As this reset only uses VC_CORERESET it would only ever reset the cortex_m * core, not the peripherals */ - LOG_DEBUG("soft_reset_halt is discouraged, please use 'reset halt' instead."); + LOG_TARGET_DEBUG(target, "soft_reset_halt is discouraged, please use 'reset halt' instead."); if (!cortex_m->vectreset_supported) { - LOG_ERROR("VECTRESET is not supported on this Cortex-M core"); + LOG_TARGET_ERROR(target, "VECTRESET is not supported on this Cortex-M core"); return ERROR_FAIL; } @@ -1068,15 +1066,16 @@ static int cortex_m_soft_reset_halt(struct target *target) return retval; if ((cortex_m->dcb_dhcsr & S_HALT) && (cortex_m->nvic_dfsr & DFSR_VCATCH)) { - LOG_DEBUG("system reset-halted, DHCSR 0x%08" PRIx32 ", DFSR 0x%08" PRIx32, - cortex_m->dcb_dhcsr, cortex_m->nvic_dfsr); + LOG_TARGET_DEBUG(target, "system reset-halted, DHCSR 0x%08" PRIx32 ", DFSR 0x%08" PRIx32, + cortex_m->dcb_dhcsr, cortex_m->nvic_dfsr); cortex_m_poll(target); /* FIXME restore user's vector catch config */ return ERROR_OK; - } else - LOG_DEBUG("waiting for system reset-halt, " + } else { + LOG_TARGET_DEBUG(target, "waiting for system reset-halt, " "DHCSR 0x%08" PRIx32 ", %d ms", cortex_m->dcb_dhcsr, timeout); + } } timeout++; alive_sleep(1); @@ -1091,7 +1090,7 @@ void cortex_m_enable_breakpoints(struct target *target) /* set any pending breakpoints */ while (breakpoint) { - if (!breakpoint->set) + if (!breakpoint->is_set) cortex_m_set_breakpoint(target, breakpoint); breakpoint = breakpoint->next; } @@ -1106,7 +1105,7 @@ static int cortex_m_resume(struct target *target, int current, struct reg *r; if (target->state != TARGET_HALTED) { - LOG_WARNING("target not halted"); + LOG_TARGET_WARNING(target, "target not halted"); return ERROR_TARGET_NOT_HALTED; } @@ -1170,7 +1169,7 @@ static int cortex_m_resume(struct target *target, int current, /* Single step past breakpoint at current address */ breakpoint = breakpoint_find(target, resume_pc); if (breakpoint) { - LOG_DEBUG("unset breakpoint at " TARGET_ADDR_FMT " (ID: %" PRIu32 ")", + LOG_TARGET_DEBUG(target, "unset breakpoint at " TARGET_ADDR_FMT " (ID: %" PRIu32 ")", breakpoint->address, breakpoint->unique_id); cortex_m_unset_breakpoint(target, breakpoint); @@ -1191,11 +1190,11 @@ static int cortex_m_resume(struct target *target, int current, if (!debug_execution) { target->state = TARGET_RUNNING; target_call_event_callbacks(target, TARGET_EVENT_RESUMED); - LOG_DEBUG("target resumed at 0x%" PRIx32 "", resume_pc); + LOG_TARGET_DEBUG(target, "target resumed at 0x%" PRIx32 "", resume_pc); } else { target->state = TARGET_DEBUG_RUNNING; target_call_event_callbacks(target, TARGET_EVENT_DEBUG_RESUMED); - LOG_DEBUG("target debug resumed at 0x%" PRIx32 "", resume_pc); + LOG_TARGET_DEBUG(target, "target debug resumed at 0x%" PRIx32 "", resume_pc); } return ERROR_OK; @@ -1214,7 +1213,7 @@ static int cortex_m_step(struct target *target, int current, bool isr_timed_out = false; if (target->state != TARGET_HALTED) { - LOG_WARNING("target not halted"); + LOG_TARGET_WARNING(target, "target not halted"); return ERROR_TARGET_NOT_HALTED; } @@ -1287,7 +1286,7 @@ static int cortex_m_step(struct target *target, int current, * */ if ((pc_value & 0x02) && breakpoint_find(target, pc_value & ~0x03)) { - LOG_DEBUG("Stepping over next instruction with interrupts disabled"); + LOG_TARGET_DEBUG(target, "Stepping over next instruction with interrupts disabled"); cortex_m_write_debug_halt_mask(target, C_HALT | C_MASKINTS, 0); cortex_m_write_debug_halt_mask(target, C_STEP, C_HALT); /* Re-enable interrupts if appropriate */ @@ -1318,7 +1317,7 @@ static int cortex_m_step(struct target *target, int current, cortex_m_set_maskints_for_halt(target); } else { /* Start the core */ - LOG_DEBUG("Starting core to serve pending interrupts"); + LOG_TARGET_DEBUG(target, "Starting core to serve pending interrupts"); int64_t t_start = timeval_ms(); cortex_m_set_maskints_for_run(target); cortex_m_write_debug_halt_mask(target, 0, C_HALT | C_STEP); @@ -1342,7 +1341,7 @@ static int cortex_m_step(struct target *target, int current, } if (isr_timed_out) { - LOG_DEBUG("Interrupt handlers didn't complete within time, " + LOG_TARGET_DEBUG(target, "Interrupt handlers didn't complete within time, " "leaving target running"); } else { /* Step over next instruction with interrupts disabled */ @@ -1377,7 +1376,7 @@ static int cortex_m_step(struct target *target, int current, return ERROR_OK; } - LOG_DEBUG("target stepped dcb_dhcsr = 0x%" PRIx32 + LOG_TARGET_DEBUG(target, "target stepped dcb_dhcsr = 0x%" PRIx32 " nvic_icsr = 0x%" PRIx32, cortex_m->dcb_dhcsr, cortex_m->nvic_icsr); @@ -1386,7 +1385,7 @@ static int cortex_m_step(struct target *target, int current, return retval; target_call_event_callbacks(target, TARGET_EVENT_HALTED); - LOG_DEBUG("target stepped dcb_dhcsr = 0x%" PRIx32 + LOG_TARGET_DEBUG(target, "target stepped dcb_dhcsr = 0x%" PRIx32 " nvic_icsr = 0x%" PRIx32, cortex_m->dcb_dhcsr, cortex_m->nvic_icsr); @@ -1399,7 +1398,7 @@ static int cortex_m_assert_reset(struct target *target) struct armv7m_common *armv7m = &cortex_m->armv7m; enum cortex_m_soft_reset_config reset_config = cortex_m->soft_reset_config; - LOG_DEBUG("target->state: %s", + LOG_TARGET_DEBUG(target, "target->state: %s", target_state_name(target)); enum reset_types jtag_reset_config = jtag_get_reset_config(); @@ -1423,10 +1422,10 @@ static int cortex_m_assert_reset(struct target *target) if (jtag_reset_config & RESET_HAS_SRST) { adapter_assert_reset(); if (target->reset_halt) - LOG_ERROR("Target not examined, will not halt after reset!"); + LOG_TARGET_ERROR(target, "Target not examined, will not halt after reset!"); return ERROR_OK; } else { - LOG_ERROR("Target not examined, reset NOT asserted!"); + LOG_TARGET_ERROR(target, "Target not examined, reset NOT asserted!"); return ERROR_FAIL; } } @@ -1473,7 +1472,7 @@ static int cortex_m_assert_reset(struct target *target) retval2 = mem_ap_write_atomic_u32(armv7m->debug_ap, DCB_DEMCR, TRCENA | VC_HARDERR | VC_BUSERR | VC_CORERESET); if (retval != ERROR_OK || retval2 != ERROR_OK) - LOG_INFO("AP write error, reset will not halt"); + LOG_TARGET_INFO(target, "AP write error, reset will not halt"); } if (jtag_reset_config & RESET_HAS_SRST) { @@ -1493,15 +1492,15 @@ static int cortex_m_assert_reset(struct target *target) if (!cortex_m->vectreset_supported && reset_config == CORTEX_M_RESET_VECTRESET) { reset_config = CORTEX_M_RESET_SYSRESETREQ; - LOG_WARNING("VECTRESET is not supported on this Cortex-M core, using SYSRESETREQ instead."); - LOG_WARNING("Set 'cortex_m reset_config sysresetreq'."); + LOG_TARGET_WARNING(target, "VECTRESET is not supported on this Cortex-M core, using SYSRESETREQ instead."); + LOG_TARGET_WARNING(target, "Set 'cortex_m reset_config sysresetreq'."); } - LOG_DEBUG("Using Cortex-M %s", (reset_config == CORTEX_M_RESET_SYSRESETREQ) + LOG_TARGET_DEBUG(target, "Using Cortex-M %s", (reset_config == CORTEX_M_RESET_SYSRESETREQ) ? "SYSRESETREQ" : "VECTRESET"); if (reset_config == CORTEX_M_RESET_VECTRESET) { - LOG_WARNING("Only resetting the Cortex-M core, use a reset-init event " + LOG_TARGET_WARNING(target, "Only resetting the Cortex-M core, use a reset-init event " "handler to reset any peripherals or configure hardware srst support."); } @@ -1510,11 +1509,11 @@ static int cortex_m_assert_reset(struct target *target) AIRCR_VECTKEY | ((reset_config == CORTEX_M_RESET_SYSRESETREQ) ? AIRCR_SYSRESETREQ : AIRCR_VECTRESET)); if (retval3 != ERROR_OK) - LOG_DEBUG("Ignoring AP write error right after reset"); + LOG_TARGET_DEBUG(target, "Ignoring AP write error right after reset"); retval3 = dap_dp_init_or_reconnect(armv7m->debug_ap->dap); if (retval3 != ERROR_OK) { - LOG_ERROR("DP initialisation failed"); + LOG_TARGET_ERROR(target, "DP initialisation failed"); /* The error return value must not be propagated in this case. * SYSRESETREQ or VECTRESET have been possibly triggered * so reset processing should continue */ @@ -1550,7 +1549,7 @@ static int cortex_m_deassert_reset(struct target *target) { struct armv7m_common *armv7m = &target_to_cm(target)->armv7m; - LOG_DEBUG("target->state: %s", + LOG_TARGET_DEBUG(target, "target->state: %s", target_state_name(target)); /* deassert reset lines */ @@ -1564,7 +1563,7 @@ static int cortex_m_deassert_reset(struct target *target) int retval = dap_dp_init_or_reconnect(armv7m->debug_ap->dap); if (retval != ERROR_OK) { - LOG_ERROR("DP initialisation failed"); + LOG_TARGET_ERROR(target, "DP initialisation failed"); return retval; } } @@ -1579,8 +1578,8 @@ int cortex_m_set_breakpoint(struct target *target, struct breakpoint *breakpoint struct cortex_m_common *cortex_m = target_to_cm(target); struct cortex_m_fp_comparator *comparator_list = cortex_m->fp_comparator_list; - if (breakpoint->set) { - LOG_WARNING("breakpoint (BPID: %" PRIu32 ") already set", breakpoint->unique_id); + if (breakpoint->is_set) { + LOG_TARGET_WARNING(target, "breakpoint (BPID: %" PRIu32 ") already set", breakpoint->unique_id); return ERROR_OK; } @@ -1589,35 +1588,36 @@ int cortex_m_set_breakpoint(struct target *target, struct breakpoint *breakpoint while (comparator_list[fp_num].used && (fp_num < cortex_m->fp_num_code)) fp_num++; if (fp_num >= cortex_m->fp_num_code) { - LOG_ERROR("Can not find free FPB Comparator!"); + LOG_TARGET_ERROR(target, "Can not find free FPB Comparator!"); return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; } - breakpoint->set = fp_num + 1; + breakpoint_hw_set(breakpoint, fp_num); fpcr_value = breakpoint->address | 1; if (cortex_m->fp_rev == 0) { if (breakpoint->address > 0x1FFFFFFF) { - LOG_ERROR("Cortex-M Flash Patch Breakpoint rev.1 cannot handle HW breakpoint above address 0x1FFFFFFE"); + LOG_TARGET_ERROR(target, "Cortex-M Flash Patch Breakpoint rev.1 " + "cannot handle HW breakpoint above address 0x1FFFFFFE"); return ERROR_FAIL; } uint32_t hilo; hilo = (breakpoint->address & 0x2) ? FPCR_REPLACE_BKPT_HIGH : FPCR_REPLACE_BKPT_LOW; fpcr_value = (fpcr_value & 0x1FFFFFFC) | hilo | 1; } else if (cortex_m->fp_rev > 1) { - LOG_ERROR("Unhandled Cortex-M Flash Patch Breakpoint architecture revision"); + LOG_TARGET_ERROR(target, "Unhandled Cortex-M Flash Patch Breakpoint architecture revision"); return ERROR_FAIL; } 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); - LOG_DEBUG("fpc_num %i fpcr_value 0x%" PRIx32 "", + LOG_TARGET_DEBUG(target, "fpc_num %i fpcr_value 0x%" PRIx32 "", fp_num, comparator_list[fp_num].fpcr_value); if (!cortex_m->fpb_enabled) { - LOG_DEBUG("FPB wasn't enabled, do it now"); + LOG_TARGET_DEBUG(target, "FPB wasn't enabled, do it now"); retval = cortex_m_enable_fpb(target); if (retval != ERROR_OK) { - LOG_ERROR("Failed to enable the FPB"); + LOG_TARGET_ERROR(target, "Failed to enable the FPB"); return retval; } @@ -1643,15 +1643,15 @@ int cortex_m_set_breakpoint(struct target *target, struct breakpoint *breakpoint code); if (retval != ERROR_OK) return retval; - breakpoint->set = true; + breakpoint->is_set = true; } - LOG_DEBUG("BPID: %" PRIu32 ", Type: %d, Address: " TARGET_ADDR_FMT " Length: %d (set=%d)", + LOG_TARGET_DEBUG(target, "BPID: %" PRIu32 ", Type: %d, Address: " TARGET_ADDR_FMT " Length: %d (n=%u)", breakpoint->unique_id, (int)(breakpoint->type), breakpoint->address, breakpoint->length, - breakpoint->set); + (breakpoint->type == BKPT_SOFT) ? 0 : breakpoint->number); return ERROR_OK; } @@ -1662,22 +1662,22 @@ int cortex_m_unset_breakpoint(struct target *target, struct breakpoint *breakpoi struct cortex_m_common *cortex_m = target_to_cm(target); struct cortex_m_fp_comparator *comparator_list = cortex_m->fp_comparator_list; - if (breakpoint->set <= 0) { - LOG_WARNING("breakpoint not set"); + if (!breakpoint->is_set) { + LOG_TARGET_WARNING(target, "breakpoint not set"); return ERROR_OK; } - LOG_DEBUG("BPID: %" PRIu32 ", Type: %d, Address: " TARGET_ADDR_FMT " Length: %d (set=%d)", + LOG_TARGET_DEBUG(target, "BPID: %" PRIu32 ", Type: %d, Address: " TARGET_ADDR_FMT " Length: %d (n=%u)", breakpoint->unique_id, (int)(breakpoint->type), breakpoint->address, breakpoint->length, - breakpoint->set); + (breakpoint->type == BKPT_SOFT) ? 0 : breakpoint->number); if (breakpoint->type == BKPT_HARD) { - unsigned int fp_num = breakpoint->set - 1; + unsigned int fp_num = breakpoint->number; if (fp_num >= cortex_m->fp_num_code) { - LOG_DEBUG("Invalid FP Comparator number in breakpoint"); + LOG_TARGET_DEBUG(target, "Invalid FP Comparator number in breakpoint"); return ERROR_OK; } comparator_list[fp_num].used = false; @@ -1692,7 +1692,7 @@ int cortex_m_unset_breakpoint(struct target *target, struct breakpoint *breakpoi if (retval != ERROR_OK) return retval; } - breakpoint->set = false; + breakpoint->is_set = false; return ERROR_OK; } @@ -1700,12 +1700,12 @@ int cortex_m_unset_breakpoint(struct target *target, struct breakpoint *breakpoi int cortex_m_add_breakpoint(struct target *target, struct breakpoint *breakpoint) { if (breakpoint->length == 3) { - LOG_DEBUG("Using a two byte breakpoint for 32bit Thumb-2 request"); + LOG_TARGET_DEBUG(target, "Using a two byte breakpoint for 32bit Thumb-2 request"); breakpoint->length = 2; } if ((breakpoint->length != 2)) { - LOG_INFO("only breakpoints of two bytes length supported"); + LOG_TARGET_INFO(target, "only breakpoints of two bytes length supported"); return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; } @@ -1714,7 +1714,7 @@ int cortex_m_add_breakpoint(struct target *target, struct breakpoint *breakpoint int cortex_m_remove_breakpoint(struct target *target, struct breakpoint *breakpoint) { - if (!breakpoint->set) + if (!breakpoint->is_set) return ERROR_OK; return cortex_m_unset_breakpoint(target, breakpoint); @@ -1737,11 +1737,11 @@ static int cortex_m_set_watchpoint(struct target *target, struct watchpoint *wat comparator++, dwt_num++) continue; if (dwt_num >= cortex_m->dwt_num_comp) { - LOG_ERROR("Can not find free DWT Comparator"); + LOG_TARGET_ERROR(target, "Can not find free DWT Comparator"); return ERROR_FAIL; } comparator->used = true; - watchpoint->set = dwt_num + 1; + watchpoint_set(watchpoint, dwt_num); comparator->comp = watchpoint->address; target_write_u32(target, comparator->dwt_comparator_address + 0, @@ -1795,7 +1795,7 @@ static int cortex_m_set_watchpoint(struct target *target, struct watchpoint *wat target_write_u32(target, comparator->dwt_comparator_address + 8, comparator->function); - LOG_DEBUG("Watchpoint (ID %d) DWT%d 0x%08x 0x%x 0x%05x", + LOG_TARGET_DEBUG(target, "Watchpoint (ID %d) DWT%d 0x%08x 0x%x 0x%05x", watchpoint->unique_id, dwt_num, (unsigned) comparator->comp, (unsigned) comparator->mask, @@ -1808,20 +1808,20 @@ static int cortex_m_unset_watchpoint(struct target *target, struct watchpoint *w struct cortex_m_common *cortex_m = target_to_cm(target); struct cortex_m_dwt_comparator *comparator; - if (watchpoint->set <= 0) { - LOG_WARNING("watchpoint (wpid: %d) not set", + if (!watchpoint->is_set) { + LOG_TARGET_WARNING(target, "watchpoint (wpid: %d) not set", watchpoint->unique_id); return ERROR_OK; } - unsigned int dwt_num = watchpoint->set - 1; + unsigned int dwt_num = watchpoint->number; - LOG_DEBUG("Watchpoint (ID %d) DWT%d address: 0x%08x clear", + LOG_TARGET_DEBUG(target, "Watchpoint (ID %d) DWT%u address: 0x%08x clear", watchpoint->unique_id, dwt_num, (unsigned) watchpoint->address); if (dwt_num >= cortex_m->dwt_num_comp) { - LOG_DEBUG("Invalid DWT Comparator number in watchpoint"); + LOG_TARGET_DEBUG(target, "Invalid DWT Comparator number in watchpoint"); return ERROR_OK; } @@ -1831,7 +1831,7 @@ static int cortex_m_unset_watchpoint(struct target *target, struct watchpoint *w target_write_u32(target, comparator->dwt_comparator_address + 8, comparator->function); - watchpoint->set = false; + watchpoint->is_set = false; return ERROR_OK; } @@ -1841,13 +1841,13 @@ int cortex_m_add_watchpoint(struct target *target, struct watchpoint *watchpoint struct cortex_m_common *cortex_m = target_to_cm(target); if (cortex_m->dwt_comp_available < 1) { - LOG_DEBUG("no comparators?"); + LOG_TARGET_DEBUG(target, "no comparators?"); return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; } /* hardware doesn't support data value masking */ if (watchpoint->mask != ~(uint32_t)0) { - LOG_DEBUG("watchpoint value masks not supported"); + LOG_TARGET_DEBUG(target, "watchpoint value masks not supported"); return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; } @@ -1859,11 +1859,11 @@ int cortex_m_add_watchpoint(struct target *target, struct watchpoint *watchpoint break; } if (mask == 16) { - LOG_DEBUG("unsupported watchpoint length"); + LOG_TARGET_DEBUG(target, "unsupported watchpoint length"); return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; } if (watchpoint->address & ((1 << mask) - 1)) { - LOG_DEBUG("watchpoint address is unaligned"); + LOG_TARGET_DEBUG(target, "watchpoint address is unaligned"); return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; } @@ -1875,12 +1875,12 @@ int cortex_m_add_watchpoint(struct target *target, struct watchpoint *watchpoint * the data, and another comparator (DATAVADDR0) matching addr. */ if (watchpoint->value) { - LOG_DEBUG("data value watchpoint not YET supported"); + LOG_TARGET_DEBUG(target, "data value watchpoint not YET supported"); return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; } cortex_m->dwt_comp_available--; - LOG_DEBUG("dwt_comp_available: %d", cortex_m->dwt_comp_available); + LOG_TARGET_DEBUG(target, "dwt_comp_available: %d", cortex_m->dwt_comp_available); return ERROR_OK; } @@ -1891,15 +1891,15 @@ int cortex_m_remove_watchpoint(struct target *target, struct watchpoint *watchpo /* REVISIT why check? DWT can be updated with core running ... */ if (target->state != TARGET_HALTED) { - LOG_WARNING("target not halted"); + LOG_TARGET_WARNING(target, "target not halted"); return ERROR_TARGET_NOT_HALTED; } - if (watchpoint->set) + if (watchpoint->is_set) cortex_m_unset_watchpoint(target, watchpoint); cortex_m->dwt_comp_available++; - LOG_DEBUG("dwt_comp_available: %d", cortex_m->dwt_comp_available); + LOG_TARGET_DEBUG(target, "dwt_comp_available: %d", cortex_m->dwt_comp_available); return ERROR_OK; } @@ -1912,10 +1912,10 @@ int cortex_m_hit_watchpoint(struct target *target, struct watchpoint **hit_watch struct cortex_m_common *cortex_m = target_to_cm(target); for (struct watchpoint *wp = target->watchpoints; wp; wp = wp->next) { - if (!wp->set) + if (!wp->is_set) continue; - unsigned int dwt_num = wp->set - 1; + unsigned int dwt_num = wp->number; struct cortex_m_dwt_comparator *comparator = cortex_m->dwt_comparator_list + dwt_num; uint32_t dwt_function; @@ -1939,7 +1939,7 @@ void cortex_m_enable_watchpoints(struct target *target) /* set any pending watchpoints */ while (watchpoint) { - if (!watchpoint->set) + if (!watchpoint->is_set) cortex_m_set_watchpoint(target, watchpoint); watchpoint = watchpoint->next; } @@ -2004,18 +2004,18 @@ int cortex_m_profiling(struct target *target, uint32_t *samples, retval = target_read_u32(target, DWT_PCSR, ®_value); if (retval != ERROR_OK) { - LOG_ERROR("Error while reading PCSR"); + LOG_TARGET_ERROR(target, "Error while reading PCSR"); return retval; } if (reg_value == 0) { - LOG_INFO("PCSR sampling not supported on this processor."); + LOG_TARGET_INFO(target, "PCSR sampling not supported on this processor."); return target_profiling_default(target, samples, max_num_samples, num_samples, seconds); } gettimeofday(&timeout, NULL); timeval_add_time(&timeout, seconds, 0); - LOG_INFO("Starting Cortex-M profiling. Sampling DWT_PCSR as fast as we can..."); + LOG_TARGET_INFO(target, "Starting Cortex-M profiling. Sampling DWT_PCSR as fast as we can..."); /* Make sure the target is running */ target_poll(target); @@ -2023,7 +2023,7 @@ int cortex_m_profiling(struct target *target, uint32_t *samples, retval = target_resume(target, 1, 0, 0, 0); if (retval != ERROR_OK) { - LOG_ERROR("Error while resuming target"); + LOG_TARGET_ERROR(target, "Error while resuming target"); return retval; } @@ -2044,14 +2044,14 @@ int cortex_m_profiling(struct target *target, uint32_t *samples, } if (retval != ERROR_OK) { - LOG_ERROR("Error while reading PCSR"); + LOG_TARGET_ERROR(target, "Error while reading PCSR"); return retval; } gettimeofday(&now, NULL); if (sample_count >= max_num_samples || timeval_compare(&now, &timeout) > 0) { - LOG_INFO("Profiling completed. %" PRIu32 " samples.", sample_count); + LOG_TARGET_INFO(target, "Profiling completed. %" PRIu32 " samples.", sample_count); break; } } @@ -2162,14 +2162,14 @@ static void cortex_m_dwt_setup(struct cortex_m_common *cm, struct target *target int reg; target_read_u32(target, DWT_CTRL, &dwtcr); - LOG_DEBUG("DWT_CTRL: 0x%" PRIx32, dwtcr); + LOG_TARGET_DEBUG(target, "DWT_CTRL: 0x%" PRIx32, dwtcr); if (!dwtcr) { - LOG_DEBUG("no DWT"); + LOG_TARGET_DEBUG(target, "no DWT"); return; } target_read_u32(target, DWT_DEVARCH, &cm->dwt_devarch); - LOG_DEBUG("DWT_DEVARCH: 0x%" PRIx32, cm->dwt_devarch); + LOG_TARGET_DEBUG(target, "DWT_DEVARCH: 0x%" PRIx32, cm->dwt_devarch); cm->dwt_num_comp = (dwtcr >> 28) & 0xF; cm->dwt_comp_available = cm->dwt_num_comp; @@ -2178,7 +2178,7 @@ static void cortex_m_dwt_setup(struct cortex_m_common *cm, struct target *target if (!cm->dwt_comparator_list) { fail0: cm->dwt_num_comp = 0; - LOG_ERROR("out of mem"); + LOG_TARGET_ERROR(target, "out of mem"); return; } @@ -2216,7 +2216,7 @@ fail1: *register_get_last_cache_p(&target->reg_cache) = cache; cm->dwt_cache = cache; - LOG_DEBUG("DWT dwtcr 0x%" PRIx32 ", comp %d, watch%s", + LOG_TARGET_DEBUG(target, "DWT dwtcr 0x%" PRIx32 ", comp %d, watch%s", dwtcr, cm->dwt_num_comp, (dwtcr & (0xf << 24)) ? " only" : "/trigger"); @@ -2283,7 +2283,7 @@ int cortex_m_examine(struct target *target) /* Search for the MEM-AP */ retval = cortex_m_find_mem_ap(swjdp, &armv7m->debug_ap); if (retval != ERROR_OK) { - LOG_ERROR("Could not find MEM-AP to control the core"); + LOG_TARGET_ERROR(target, "Could not find MEM-AP to control the core"); return retval; } } else { @@ -2316,14 +2316,13 @@ int cortex_m_examine(struct target *target) } if (!cortex_m->core_info) { - LOG_ERROR("Cortex-M PARTNO 0x%x is unrecognized", core_partno); + LOG_TARGET_ERROR(target, "Cortex-M PARTNO 0x%x is unrecognized", core_partno); return ERROR_FAIL; } armv7m->arm.arch = cortex_m->core_info->arch; - LOG_INFO("%s: %s r%" PRId8 "p%" PRId8 " processor detected", - target_name(target), + LOG_TARGET_INFO(target, "%s r%" PRId8 "p%" PRId8 " processor detected", cortex_m->core_info->name, (uint8_t)((cpuid >> 20) & 0xf), (uint8_t)((cpuid >> 0) & 0xf)); @@ -2334,11 +2333,11 @@ int cortex_m_examine(struct target *target) rev = (cpuid >> 20) & 0xf; patch = (cpuid >> 0) & 0xf; if ((rev == 0) && (patch < 2)) { - LOG_WARNING("Silicon bug: single stepping may enter pending exception handler!"); + LOG_TARGET_WARNING(target, "Silicon bug: single stepping may enter pending exception handler!"); cortex_m->maskints_erratum = true; } } - LOG_DEBUG("cpuid: 0x%8.8" PRIx32 "", cpuid); + LOG_TARGET_DEBUG(target, "cpuid: 0x%8.8" PRIx32 "", cpuid); if (cortex_m->core_info->flags & CORTEX_M_F_HAS_FPV4) { target_read_u32(target, MVFR0, &mvfr0); @@ -2346,7 +2345,7 @@ int cortex_m_examine(struct target *target) /* test for floating point feature on Cortex-M4 */ if ((mvfr0 == MVFR0_DEFAULT_M4) && (mvfr1 == MVFR1_DEFAULT_M4)) { - LOG_DEBUG("%s floating point feature FPv4_SP found", cortex_m->core_info->name); + LOG_TARGET_DEBUG(target, "%s floating point feature FPv4_SP found", cortex_m->core_info->name); armv7m->fp_feature = FPV4_SP; } } else if (cortex_m->core_info->flags & CORTEX_M_F_HAS_FPV5) { @@ -2355,10 +2354,10 @@ int cortex_m_examine(struct target *target) /* test for floating point features on Cortex-M7 */ if ((mvfr0 == MVFR0_DEFAULT_M7_SP) && (mvfr1 == MVFR1_DEFAULT_M7_SP)) { - LOG_DEBUG("%s floating point feature FPv5_SP found", cortex_m->core_info->name); + LOG_TARGET_DEBUG(target, "%s floating point feature FPv5_SP found", cortex_m->core_info->name); armv7m->fp_feature = FPV5_SP; } else if ((mvfr0 == MVFR0_DEFAULT_M7_DP) && (mvfr1 == MVFR1_DEFAULT_M7_DP)) { - LOG_DEBUG("%s floating point feature FPv5_DP found", cortex_m->core_info->name); + LOG_TARGET_DEBUG(target, "%s floating point feature FPv5_DP found", cortex_m->core_info->name); armv7m->fp_feature = FPV5_DP; } } @@ -2428,7 +2427,7 @@ int cortex_m_examine(struct target *target) /* make sure we clear any breakpoints enabled on the target */ target_write_u32(target, cortex_m->fp_comparator_list[i].fpcr_address, 0); } - LOG_DEBUG("FPB fpcr 0x%" PRIx32 ", numcode %i, numlit %i", + LOG_TARGET_DEBUG(target, "FPB fpcr 0x%" PRIx32 ", numcode %i, numlit %i", fpcr, cortex_m->fp_num_code, cortex_m->fp_num_lit); @@ -2438,8 +2437,7 @@ int cortex_m_examine(struct target *target) cortex_m_dwt_setup(cortex_m, target); /* These hardware breakpoints only work for code in flash! */ - LOG_INFO("%s: target has %d breakpoints, %d watchpoints", - target_name(target), + LOG_TARGET_INFO(target, "target has %d breakpoints, %d watchpoints", cortex_m->fp_num_code, cortex_m->dwt_num_comp); } @@ -2462,7 +2460,7 @@ static int cortex_m_dcc_read(struct target *target, uint8_t *value, uint8_t *ctr *ctrl = (uint8_t)dcrdr; *value = (uint8_t)(dcrdr >> 8); - LOG_DEBUG("data 0x%x ctrl 0x%x", *value, *ctrl); + LOG_TARGET_DEBUG(target, "data 0x%x ctrl 0x%x", *value, *ctrl); /* write ack back to software dcc register * signify we have read data */ @@ -2569,7 +2567,7 @@ static int cortex_m_target_create(struct target *target, Jim_Interp *interp) struct cortex_m_common *cortex_m = calloc(1, sizeof(struct cortex_m_common)); if (!cortex_m) { - LOG_ERROR("No memory creating target"); + LOG_TARGET_ERROR(target, "No memory creating target"); return ERROR_FAIL; } @@ -2626,7 +2624,7 @@ COMMAND_HANDLER(handle_cortex_m_vector_catch_command) return retval; if (!target_was_examined(target)) { - LOG_ERROR("Target not examined yet"); + LOG_TARGET_ERROR(target, "Target not examined yet"); return ERROR_FAIL; } @@ -2655,7 +2653,7 @@ COMMAND_HANDLER(handle_cortex_m_vector_catch_command) break; } if (i == ARRAY_SIZE(vec_ids)) { - LOG_ERROR("No CM3 vector '%s'", CMD_ARGV[CMD_ARGC]); + LOG_TARGET_ERROR(target, "No CM3 vector '%s'", CMD_ARGV[CMD_ARGC]); return ERROR_COMMAND_SYNTAX_ERROR; } } @@ -2745,7 +2743,7 @@ COMMAND_HANDLER(handle_cortex_m_reset_config_command) else if (strcmp(*CMD_ARGV, "vectreset") == 0) { if (target_was_examined(target) && !cortex_m->vectreset_supported) - LOG_WARNING("VECTRESET is not supported on your Cortex-M core!"); + LOG_TARGET_WARNING(target, "VECTRESET is not supported on your Cortex-M core!"); else cortex_m->soft_reset_config = CORTEX_M_RESET_VECTRESET; diff --git a/src/target/esirisc.c b/src/target/esirisc.c index e49f5f659..aadd111ee 100644 --- a/src/target/esirisc.c +++ b/src/target/esirisc.c @@ -504,7 +504,7 @@ static int esirisc_add_breakpoint(struct target *target, struct breakpoint *brea return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; } - breakpoint->set = bp_index + 1; + breakpoint_hw_set(breakpoint, bp_index); esirisc->breakpoints_p[bp_index] = breakpoint; /* specify instruction breakpoint address */ @@ -540,7 +540,7 @@ static int esirisc_add_breakpoints(struct target *target) LOG_DEBUG("-"); while (breakpoint) { - if (breakpoint->set == 0) + if (!breakpoint->is_set) esirisc_add_breakpoint(target, breakpoint); breakpoint = breakpoint->next; @@ -553,7 +553,7 @@ static int esirisc_remove_breakpoint(struct target *target, struct breakpoint *b { struct esirisc_common *esirisc = target_to_esirisc(target); struct esirisc_jtag *jtag_info = &esirisc->jtag_info; - int bp_index = breakpoint->set - 1; + unsigned int bp_index = breakpoint->number; uint32_t ibc; int retval; @@ -575,7 +575,7 @@ static int esirisc_remove_breakpoint(struct target *target, struct breakpoint *b } esirisc->breakpoints_p[bp_index] = NULL; - breakpoint->set = 0; + breakpoint->is_set = false; return ERROR_OK; } @@ -630,7 +630,7 @@ static int esirisc_add_watchpoint(struct target *target, struct watchpoint *watc return ERROR_FAIL; } - watchpoint->set = wp_index + 1; + watchpoint_set(watchpoint, wp_index); esirisc->watchpoints_p[wp_index] = watchpoint; /* specify data breakpoint address */ @@ -724,7 +724,7 @@ static int esirisc_add_watchpoints(struct target *target) LOG_DEBUG("-"); while (watchpoint) { - if (watchpoint->set == 0) + if (!watchpoint->is_set) esirisc_add_watchpoint(target, watchpoint); watchpoint = watchpoint->next; @@ -737,7 +737,7 @@ static int esirisc_remove_watchpoint(struct target *target, struct watchpoint *w { struct esirisc_common *esirisc = target_to_esirisc(target); struct esirisc_jtag *jtag_info = &esirisc->jtag_info; - int wp_index = watchpoint->set - 1; + unsigned int wp_index = watchpoint->number; uint32_t dbc; int retval; @@ -759,7 +759,7 @@ static int esirisc_remove_watchpoint(struct target *target, struct watchpoint *w } esirisc->watchpoints_p[wp_index] = NULL; - watchpoint->set = 0; + watchpoint->is_set = false; return ERROR_OK; } diff --git a/src/target/lakemont.c b/src/target/lakemont.c index e46ee5cf8..230f53fe0 100644 --- a/src/target/lakemont.c +++ b/src/target/lakemont.c @@ -1024,10 +1024,10 @@ int lakemont_resume(struct target *t, int current, target_addr_t address, /* if breakpoints are enabled, we need to redirect these into probe mode */ struct breakpoint *activeswbp = t->breakpoints; - while (activeswbp && activeswbp->set == 0) + while (activeswbp && !activeswbp->is_set) activeswbp = activeswbp->next; struct watchpoint *activehwbp = t->watchpoints; - while (activehwbp && activehwbp->set == 0) + while (activehwbp && !activehwbp->is_set) activehwbp = activehwbp->next; if (activeswbp || activehwbp) buf_set_u32(x86_32->cache->reg_list[PMCR].value, 0, 32, 1); diff --git a/src/target/mips_m4k.c b/src/target/mips_m4k.c index 8627bce6e..860119345 100644 --- a/src/target/mips_m4k.c +++ b/src/target/mips_m4k.c @@ -593,7 +593,7 @@ static void mips_m4k_enable_breakpoints(struct target *target) /* set any pending breakpoints */ while (breakpoint) { - if (breakpoint->set == 0) + if (!breakpoint->is_set) mips_m4k_set_breakpoint(target, breakpoint); breakpoint = breakpoint->next; } @@ -607,7 +607,7 @@ static int mips_m4k_set_breakpoint(struct target *target, struct mips32_comparator *comparator_list = mips32->inst_break_list; int retval; - if (breakpoint->set) { + if (breakpoint->is_set) { LOG_WARNING("breakpoint already set"); return ERROR_OK; } @@ -622,7 +622,7 @@ static int mips_m4k_set_breakpoint(struct target *target, breakpoint->unique_id); return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; } - breakpoint->set = bp_num + 1; + breakpoint_hw_set(breakpoint, bp_num); comparator_list[bp_num].used = 1; comparator_list[bp_num].bp_value = breakpoint->address; @@ -724,7 +724,7 @@ static int mips_m4k_set_breakpoint(struct target *target, } } - breakpoint->set = 20; /* Any nice value but 0 */ + breakpoint->is_set = true; } return ERROR_OK; @@ -739,14 +739,14 @@ static int mips_m4k_unset_breakpoint(struct target *target, struct mips32_comparator *comparator_list = mips32->inst_break_list; int retval; - if (!breakpoint->set) { + if (!breakpoint->is_set) { LOG_WARNING("breakpoint not set"); return ERROR_OK; } if (breakpoint->type == BKPT_HARD) { - int bp_num = breakpoint->set - 1; - if ((bp_num < 0) || (bp_num >= mips32->num_inst_bpoints)) { + int bp_num = breakpoint->number; + if (bp_num >= mips32->num_inst_bpoints) { LOG_DEBUG("Invalid FP Comparator number in breakpoint (bpid: %" PRIu32 ")", breakpoint->unique_id); return ERROR_OK; @@ -813,7 +813,7 @@ static int mips_m4k_unset_breakpoint(struct target *target, } } - breakpoint->set = 0; + breakpoint->is_set = false; return ERROR_OK; } @@ -851,7 +851,7 @@ static int mips_m4k_remove_breakpoint(struct target *target, return ERROR_TARGET_NOT_HALTED; } - if (breakpoint->set) + if (breakpoint->is_set) mips_m4k_unset_breakpoint(target, breakpoint); if (breakpoint->type == BKPT_HARD) @@ -875,7 +875,7 @@ static int mips_m4k_set_watchpoint(struct target *target, int enable = EJTAG_DBCN_NOSB | EJTAG_DBCN_NOLB | EJTAG_DBCN_BE | (0xff << EJTAG_DBCN_BLM_SHIFT); - if (watchpoint->set) { + if (watchpoint->is_set) { LOG_WARNING("watchpoint already set"); return ERROR_OK; } @@ -911,7 +911,7 @@ static int mips_m4k_set_watchpoint(struct target *target, LOG_ERROR("BUG: watchpoint->rw neither read, write nor access"); } - watchpoint->set = wp_num + 1; + watchpoint->number = wp_num; comparator_list[wp_num].used = 1; comparator_list[wp_num].bp_value = watchpoint->address; @@ -946,13 +946,13 @@ static int mips_m4k_unset_watchpoint(struct target *target, struct mips_ejtag *ejtag_info = &mips32->ejtag_info; struct mips32_comparator *comparator_list = mips32->data_break_list; - if (!watchpoint->set) { + if (!watchpoint->is_set) { LOG_WARNING("watchpoint not set"); return ERROR_OK; } - int wp_num = watchpoint->set - 1; - if ((wp_num < 0) || (wp_num >= mips32->num_data_bpoints)) { + int wp_num = watchpoint->number; + if (wp_num >= mips32->num_data_bpoints) { LOG_DEBUG("Invalid FP Comparator number in watchpoint"); return ERROR_OK; } @@ -960,7 +960,7 @@ static int mips_m4k_unset_watchpoint(struct target *target, comparator_list[wp_num].bp_value = 0; target_write_u32(target, comparator_list[wp_num].reg_address + ejtag_info->ejtag_dbc_offs, 0); - watchpoint->set = 0; + watchpoint->is_set = false; return ERROR_OK; } @@ -991,7 +991,7 @@ static int mips_m4k_remove_watchpoint(struct target *target, return ERROR_TARGET_NOT_HALTED; } - if (watchpoint->set) + if (watchpoint->is_set) mips_m4k_unset_watchpoint(target, watchpoint); mips32->num_data_bpoints_avail++; @@ -1005,7 +1005,7 @@ static void mips_m4k_enable_watchpoints(struct target *target) /* set any pending watchpoints */ while (watchpoint) { - if (watchpoint->set == 0) + if (!watchpoint->is_set) mips_m4k_set_watchpoint(target, watchpoint); watchpoint = watchpoint->next; } diff --git a/src/target/mips_mips64.c b/src/target/mips_mips64.c index 56b0194e7..5d821d7cb 100644 --- a/src/target/mips_mips64.c +++ b/src/target/mips_mips64.c @@ -346,7 +346,7 @@ static int mips_mips64_set_breakpoint(struct target *target, { int retval; - if (bp->set) { + if (bp->is_set) { LOG_WARNING("breakpoint already set"); return ERROR_OK; } @@ -373,7 +373,7 @@ static int mips_mips64_set_breakpoint(struct target *target, return retval; } - bp->set = true; + bp->is_set = true; return ERROR_OK; } @@ -385,7 +385,7 @@ static int mips_mips64_enable_breakpoints(struct target *target) /* set any pending breakpoints */ while (bp) { - if (!bp->set) { + if (!bp->is_set) { retval = mips_mips64_set_breakpoint(target, bp); if (retval != ERROR_OK) return retval; @@ -413,7 +413,7 @@ static int mips_mips64_set_watchpoint(struct target *target, int enable = EJTAG_DBCN_NOSB | EJTAG_DBCN_NOLB | EJTAG_DBCN_BE | (0xff << EJTAG_DBCN_BLM_SHIFT); - if (watchpoint->set) { + if (watchpoint->is_set) { LOG_WARNING("watchpoint already set"); return ERROR_OK; } @@ -451,7 +451,7 @@ static int mips_mips64_set_watchpoint(struct target *target, } c = &cl[wp_num]; - watchpoint->set = wp_num + 1; + watchpoint_set(watchpoint, wp_num); c->used = true; c->bp_value = watchpoint->address; @@ -491,7 +491,7 @@ static int mips_mips64_enable_watchpoints(struct target *target) /* set any pending watchpoints */ while (watchpoint) { - if (watchpoint->set == 0) { + if (!watchpoint->is_set) { retval = mips_mips64_set_watchpoint(target, watchpoint); if (retval != ERROR_OK) return retval; @@ -506,11 +506,10 @@ static int mips_mips64_unset_hwbp(struct target *target, struct breakpoint *bp) { struct mips64_common *mips64 = target->arch_info; struct mips64_comparator *comparator_list = mips64->inst_break_list; - int bp_num; - bp_num = bp->set - 1; + int bp_num = bp->number; - if ((bp_num < 0) || (bp_num >= mips64->num_inst_bpoints)) { + if (bp_num >= mips64->num_inst_bpoints) { LOG_DEBUG("Invalid FP Comparator number in breakpoint (bpid: %" PRIu32 ")", bp->unique_id); return ERROR_OK; @@ -568,7 +567,7 @@ static int mips_mips64_unset_breakpoint(struct target *target, /* get pointers to arch-specific information */ int retval; - if (!bp->set) { + if (!bp->is_set) { LOG_WARNING("breakpoint not set"); return ERROR_OK; } @@ -594,7 +593,7 @@ static int mips_mips64_unset_breakpoint(struct target *target, return retval; } - bp->set = false; + bp->is_set = false; return ERROR_OK; } @@ -815,7 +814,7 @@ static int mips_mips64_remove_breakpoint(struct target *target, return ERROR_TARGET_NOT_HALTED; } - if (bp->set) + if (bp->is_set) retval = mips_mips64_unset_breakpoint(target, bp); if (bp->type == BKPT_HARD) @@ -831,20 +830,20 @@ static int mips_mips64_unset_watchpoint(struct target *target, struct mips64_common *mips64 = target->arch_info; struct mips64_comparator *comparator_list = mips64->data_break_list; - if (!watchpoint->set) { + if (!watchpoint->is_set) { LOG_WARNING("watchpoint not set"); return ERROR_OK; } - int wp_num = watchpoint->set - 1; - if ((wp_num < 0) || (wp_num >= mips64->num_data_bpoints)) { + int wp_num = watchpoint->number; + if (wp_num >= mips64->num_data_bpoints) { LOG_DEBUG("Invalid FP Comparator number in watchpoint"); return ERROR_OK; } comparator_list[wp_num].used = false; comparator_list[wp_num].bp_value = 0; target_write_u64(target, comparator_list[wp_num].reg_address + 0x18, 0); - watchpoint->set = 0; + watchpoint->is_set = false; return ERROR_OK; } @@ -876,7 +875,7 @@ static int mips_mips64_remove_watchpoint(struct target *target, return ERROR_TARGET_NOT_HALTED; } - if (watchpoint->set) + if (watchpoint->is_set) retval = mips_mips64_unset_watchpoint(target, watchpoint); mips64->num_data_bpoints_avail++; diff --git a/src/target/nds32.c b/src/target/nds32.c index 12340ac2c..f0fb74d31 100644 --- a/src/target/nds32.c +++ b/src/target/nds32.c @@ -1653,7 +1653,7 @@ int nds32_init_arch_info(struct target *target, struct nds32 *nds32) nds32->syscall_break.asid = 0; nds32->syscall_break.length = 4; - nds32->syscall_break.set = 0; + nds32->syscall_break.is_set = false; nds32->syscall_break.orig_instr = NULL; nds32->syscall_break.next = NULL; nds32->syscall_break.unique_id = 0x515CAll + target->target_number; diff --git a/src/target/nds32_v3_common.c b/src/target/nds32_v3_common.c index b0c3de622..8ff8e30c6 100644 --- a/src/target/nds32_v3_common.c +++ b/src/target/nds32_v3_common.c @@ -78,12 +78,12 @@ static int nds32_v3_debug_entry(struct nds32 *nds32, bool enable_watchpoint) struct breakpoint *syscall_break = &(nds32->syscall_break); if (nds32->virtual_hosting) { - if (syscall_break->set) { + if (syscall_break->is_set) { /** disable virtual hosting */ /* remove breakpoint at syscall entry */ target_remove_breakpoint(nds32->target, syscall_break); - syscall_break->set = 0; + syscall_break->is_set = false; uint32_t value_pc; nds32_get_mapped_reg(nds32, PC, &value_pc); @@ -209,7 +209,7 @@ static int nds32_v3_leave_debug_state(struct nds32 *nds32, bool enable_watchpoin syscall_break->address = syscall_address; syscall_break->type = BKPT_SOFT; - syscall_break->set = 1; + syscall_break->is_set = true; target_add_breakpoint(target, syscall_break); } diff --git a/src/target/openrisc/jsp_server.c b/src/target/openrisc/jsp_server.c index e0a4475cf..54c969424 100644 --- a/src/target/openrisc/jsp_server.c +++ b/src/target/openrisc/jsp_server.c @@ -195,19 +195,22 @@ static int jsp_connection_closed(struct connection *connection) return ERROR_OK; } +static const struct service_driver jsp_service_driver = { + .name = "jsp", + .new_connection_during_keep_alive_handler = NULL, + .new_connection_handler = jsp_new_connection, + .input_handler = jsp_input, + .connection_closed_handler = jsp_connection_closed, + .keep_client_alive_handler = NULL, +}; + int jsp_init(struct or1k_jtag *jtag_info, char *banner) { struct jsp_service *jsp_service = malloc(sizeof(struct jsp_service)); jsp_service->banner = banner; jsp_service->jtag_info = jtag_info; - return add_service("jsp", - jsp_port, - 1, - jsp_new_connection, - jsp_input, - jsp_connection_closed, - jsp_service); + return add_service(&jsp_service_driver, jsp_port, 1, jsp_service); } COMMAND_HANDLER(handle_jsp_port_command) diff --git a/src/target/openrisc/or1k.c b/src/target/openrisc/or1k.c index 8fbcd9620..77fa15d50 100644 --- a/src/target/openrisc/or1k.c +++ b/src/target/openrisc/or1k.c @@ -923,9 +923,9 @@ static int or1k_add_breakpoint(struct target *target, struct or1k_du *du_core = or1k_to_du(or1k); uint8_t data; - LOG_DEBUG("Adding breakpoint: addr 0x%08" TARGET_PRIxADDR ", len %d, type %d, set: %d, id: %" PRIu32, + LOG_DEBUG("Adding breakpoint: addr 0x%08" TARGET_PRIxADDR ", len %d, type %d, id: %" PRIu32, breakpoint->address, breakpoint->length, breakpoint->type, - breakpoint->set, breakpoint->unique_id); + breakpoint->unique_id); /* Only support SW breakpoints for now. */ if (breakpoint->type == BKPT_HARD) @@ -981,9 +981,9 @@ static int or1k_remove_breakpoint(struct target *target, struct or1k_common *or1k = target_to_or1k(target); struct or1k_du *du_core = or1k_to_du(or1k); - LOG_DEBUG("Removing breakpoint: addr 0x%08" TARGET_PRIxADDR ", len %d, type %d, set: %d, id: %" PRIu32, + LOG_DEBUG("Removing breakpoint: addr 0x%08" TARGET_PRIxADDR ", len %d, type %d, id: %" PRIu32, breakpoint->address, breakpoint->length, breakpoint->type, - breakpoint->set, breakpoint->unique_id); + breakpoint->unique_id); /* Only support SW breakpoints for now. */ if (breakpoint->type == BKPT_HARD) diff --git a/src/target/riscv/riscv.c b/src/target/riscv/riscv.c index cc38bd4c7..484db7485 100644 --- a/src/target/riscv/riscv.c +++ b/src/target/riscv/riscv.c @@ -909,7 +909,7 @@ int riscv_add_breakpoint(struct target *target, struct breakpoint *breakpoint) return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; } - breakpoint->set = true; + breakpoint->is_set = true; return ERROR_OK; } @@ -969,7 +969,7 @@ int riscv_remove_breakpoint(struct target *target, return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; } - breakpoint->set = false; + breakpoint->is_set = false; return ERROR_OK; } @@ -996,7 +996,7 @@ int riscv_add_watchpoint(struct target *target, struct watchpoint *watchpoint) int result = add_trigger(target, &trigger); if (result != ERROR_OK) return result; - watchpoint->set = true; + watchpoint->is_set = true; return ERROR_OK; } @@ -1012,7 +1012,7 @@ int riscv_remove_watchpoint(struct target *target, int result = remove_trigger(target, &trigger); if (result != ERROR_OK) return result; - watchpoint->set = false; + watchpoint->is_set = false; return ERROR_OK; } @@ -1381,9 +1381,9 @@ static int disable_triggers(struct target *target, riscv_reg_t *state) struct watchpoint *watchpoint = target->watchpoints; int i = 0; while (watchpoint) { - LOG_DEBUG("watchpoint %d: set=%d", i, watchpoint->set); - state[i] = watchpoint->set; - if (watchpoint->set) { + LOG_DEBUG("watchpoint %d: set=%d", i, watchpoint->is_set); + state[i] = watchpoint->is_set; + if (watchpoint->is_set) { if (riscv_remove_watchpoint(target, watchpoint) != ERROR_OK) return ERROR_FAIL; } diff --git a/src/target/rtt.c b/src/target/rtt.c index 7e556e1cb..41830213d 100644 --- a/src/target/rtt.c +++ b/src/target/rtt.c @@ -15,6 +15,10 @@ * along with this program. If not, see . */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include #include #include diff --git a/src/target/semihosting_common.c b/src/target/semihosting_common.c index 9e60de572..9141c883e 100644 --- a/src/target/semihosting_common.c +++ b/src/target/semihosting_common.c @@ -68,7 +68,7 @@ enum { }; /* GDB remote protocol does not differentiate between text and binary open modes. */ -static const int open_modeflags[12] = { +static const int open_gdb_modeflags[12] = { TARGET_O_RDONLY, TARGET_O_RDONLY, TARGET_O_RDWR, @@ -83,6 +83,21 @@ static const int open_modeflags[12] = { TARGET_O_RDWR | TARGET_O_CREAT | TARGET_O_APPEND }; +static const int open_host_modeflags[12] = { + O_RDONLY, + O_RDONLY | O_BINARY, + O_RDWR, + O_RDWR | O_BINARY, + O_WRONLY | O_CREAT | O_TRUNC, + O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, + O_RDWR | O_CREAT | O_TRUNC, + O_RDWR | O_CREAT | O_TRUNC | O_BINARY, + O_WRONLY | O_CREAT | O_APPEND, + O_WRONLY | O_CREAT | O_APPEND | O_BINARY, + O_RDWR | O_CREAT | O_APPEND, + O_RDWR | O_CREAT | O_APPEND | O_BINARY +}; + static int semihosting_common_fileio_info(struct target *target, struct gdb_fileio_info *fileio_info); static int semihosting_common_fileio_end(struct target *target, int result, @@ -129,6 +144,11 @@ int semihosting_common_init(struct target *target, void *setup, } semihosting->is_active = false; + semihosting->redirect_cfg = SEMIHOSTING_REDIRECT_CFG_NONE; + semihosting->tcp_connection = NULL; + semihosting->stdin_fd = -1; + semihosting->stdout_fd = -1; + semihosting->stderr_fd = -1; semihosting->is_fileio = false; semihosting->hit_fileio = false; semihosting->is_resumable = false; @@ -154,6 +174,147 @@ int semihosting_common_init(struct target *target, void *setup, return ERROR_OK; } +struct semihosting_tcp_service { + struct semihosting *semihosting; + char *name; + int error; +}; + +static bool semihosting_is_redirected(struct semihosting *semihosting, int fd) +{ + if (semihosting->redirect_cfg == SEMIHOSTING_REDIRECT_CFG_NONE) + return false; + + bool is_read_op = false; + + switch (semihosting->op) { + /* check debug semihosting operations: READC, WRITEC and WRITE0 */ + case SEMIHOSTING_SYS_READC: + is_read_op = true; + /* fall through */ + case SEMIHOSTING_SYS_WRITEC: + case SEMIHOSTING_SYS_WRITE0: + /* debug operations are redirected when CFG is either DEBUG or ALL */ + if (semihosting->redirect_cfg == SEMIHOSTING_REDIRECT_CFG_STDIO) + return false; + break; + + /* check stdio semihosting operations: READ and WRITE */ + case SEMIHOSTING_SYS_READ: + is_read_op = true; + /* fall through */ + case SEMIHOSTING_SYS_WRITE: + /* stdio operations are redirected when CFG is either STDIO or ALL */ + if (semihosting->redirect_cfg == SEMIHOSTING_REDIRECT_CFG_DEBUG) + return false; + break; + + default: + return false; + } + + if (is_read_op) + return fd == semihosting->stdin_fd; + + /* write operation */ + return fd == semihosting->stdout_fd || fd == semihosting->stderr_fd; +} + +static ssize_t semihosting_redirect_write(struct semihosting *semihosting, void *buf, int size) +{ + if (!semihosting->tcp_connection) { + LOG_ERROR("No connected TCP client for semihosting"); + semihosting->sys_errno = EBADF; /* Bad file number */ + return -1; + } + + struct semihosting_tcp_service *service = semihosting->tcp_connection->service->priv; + + int retval = connection_write(semihosting->tcp_connection, buf, size); + + if (retval < 0) + log_socket_error(service->name); + + return retval; +} + +static ssize_t semihosting_write(struct semihosting *semihosting, int fd, void *buf, int size) +{ + if (semihosting_is_redirected(semihosting, fd)) + return semihosting_redirect_write(semihosting, buf, size); + + /* default write */ + return write(fd, buf, size); +} + +static ssize_t semihosting_redirect_read(struct semihosting *semihosting, void *buf, int size) +{ + if (!semihosting->tcp_connection) { + LOG_ERROR("No connected TCP client for semihosting"); + semihosting->sys_errno = EBADF; /* Bad file number */ + return -1; + } + + struct semihosting_tcp_service *service = semihosting->tcp_connection->service->priv; + + service->error = ERROR_OK; + semihosting->tcp_connection->input_pending = true; + + int retval = connection_read(semihosting->tcp_connection, buf, size); + + if (retval <= 0) + service->error = ERROR_SERVER_REMOTE_CLOSED; + + if (retval < 0) + log_socket_error(service->name); + + semihosting->tcp_connection->input_pending = false; + + return retval; +} + +static inline int semihosting_putchar(struct semihosting *semihosting, int fd, int c) +{ + if (semihosting_is_redirected(semihosting, fd)) + return semihosting_redirect_write(semihosting, &c, 1); + + /* default putchar */ + return putchar(c); +} + +static inline ssize_t semihosting_read(struct semihosting *semihosting, int fd, void *buf, int size) +{ + if (semihosting_is_redirected(semihosting, fd)) + return semihosting_redirect_read(semihosting, buf, size); + + /* default read */ + ssize_t result = read(fd, buf, size); + semihosting->sys_errno = errno; + + return result; +} + +static inline int semihosting_getchar(struct semihosting *semihosting, int fd) +{ + if (semihosting_is_redirected(semihosting, fd)) { + unsigned char c; + + if (semihosting_redirect_read(semihosting, &c, 1) > 0) + return c; + + return EOF; + } + + /* default getchar */ + return getchar(); +} + +/** + * User operation parameter string storage buffer. Contains valid data when the + * TARGET_EVENT_SEMIHOSTING_USER_CMD_xxxxx event callbacks are running. + */ +static char *semihosting_user_op_params; + /** * User operation parameter string storage buffer. Contains valid data when the * TARGET_EVENT_SEMIHOSTING_USER_CMD_xxxxx event callbacks are running. @@ -746,7 +907,7 @@ int semihosting_common(struct target *target) fileio_info->identifier = "open"; fileio_info->param_1 = addr; fileio_info->param_2 = len; - fileio_info->param_3 = open_modeflags[mode]; + fileio_info->param_3 = open_gdb_modeflags[mode]; fileio_info->param_4 = 0644; } } else { @@ -756,20 +917,23 @@ int semihosting_common(struct target *target) * - 4-7 ("w") for stdout, * - 8-11 ("a") for stderr */ if (mode < 4) { - semihosting->result = dup( - STDIN_FILENO); + int fd = dup(STDIN_FILENO); + semihosting->result = fd; + semihosting->stdin_fd = fd; semihosting->sys_errno = errno; LOG_DEBUG("dup(STDIN)=%d", (int)semihosting->result); } else if (mode < 8) { - semihosting->result = dup( - STDOUT_FILENO); + int fd = dup(STDOUT_FILENO); + semihosting->result = fd; + semihosting->stdout_fd = fd; semihosting->sys_errno = errno; LOG_DEBUG("dup(STDOUT)=%d", (int)semihosting->result); } else { - semihosting->result = dup( - STDERR_FILENO); + int fd = dup(STDERR_FILENO); + semihosting->result = fd; + semihosting->stderr_fd = fd; semihosting->sys_errno = errno; LOG_DEBUG("dup(STDERR)=%d", (int)semihosting->result); @@ -779,7 +943,7 @@ int semihosting_common(struct target *target) * otherwise it will fail to reopen a previously * written file */ semihosting->result = open((char *)fn, - open_modeflags[mode], + open_host_modeflags[mode], 0644); semihosting->sys_errno = errno; LOG_DEBUG("open('%s')=%d", fn, @@ -845,8 +1009,7 @@ int semihosting_common(struct target *target) semihosting->result = -1; semihosting->sys_errno = ENOMEM; } else { - semihosting->result = read(fd, buf, len); - semihosting->sys_errno = errno; + semihosting->result = semihosting_read(semihosting, fd, buf, len); LOG_DEBUG("read(%d, 0x%" PRIx64 ", %zu)=%d", fd, addr, @@ -886,7 +1049,7 @@ int semihosting_common(struct target *target) LOG_ERROR("SYS_READC not supported by semihosting fileio"); return ERROR_FAIL; } - semihosting->result = getchar(); + semihosting->result = semihosting_getchar(semihosting, semihosting->stdin_fd); LOG_DEBUG("getchar()=%d", (int)semihosting->result); break; @@ -1189,7 +1352,7 @@ int semihosting_common(struct target *target) free(buf); return retval; } - semihosting->result = write(fd, buf, len); + semihosting->result = semihosting_write(semihosting, fd, buf, len); semihosting->sys_errno = errno; LOG_DEBUG("write(%d, 0x%" PRIx64 ", %zu)=%d", fd, @@ -1234,7 +1397,7 @@ int semihosting_common(struct target *target) retval = target_read_memory(target, addr, 1, 1, &c); if (retval != ERROR_OK) return retval; - putchar(c); + semihosting_putchar(semihosting, semihosting->stdout_fd, c); semihosting->result = 0; } break; @@ -1278,7 +1441,7 @@ int semihosting_common(struct target *target) return retval; if (!c) break; - putchar(c); + semihosting_putchar(semihosting, semihosting->stdout_fd, c); } while (1); semihosting->result = 0; } @@ -1557,6 +1720,70 @@ static void semihosting_set_field(struct target *target, uint64_t value, target_buffer_set_u32(target, fields + (index * 4), value); } +/* ------------------------------------------------------------------------- + * Semihosting redirect over TCP structs and functions */ + +static int semihosting_service_new_connection_handler(struct connection *connection) +{ + struct semihosting_tcp_service *service = connection->service->priv; + service->semihosting->tcp_connection = connection; + + return ERROR_OK; +} + +static int semihosting_service_input_handler(struct connection *connection) +{ + struct semihosting_tcp_service *service = connection->service->priv; + + if (!connection->input_pending) { + /* consume received data, not for semihosting IO */ + const int buf_len = 100; + char buf[buf_len]; + int bytes_read = connection_read(connection, buf, buf_len); + + if (bytes_read == 0) { + return ERROR_SERVER_REMOTE_CLOSED; + } else if (bytes_read == -1) { + LOG_ERROR("error during read: %s", strerror(errno)); + return ERROR_SERVER_REMOTE_CLOSED; + } + } else if (service->error != ERROR_OK) { + return ERROR_SERVER_REMOTE_CLOSED; + } + + return ERROR_OK; +} + +static int semihosting_service_connection_closed_handler(struct connection *connection) +{ + struct semihosting_tcp_service *service = connection->service->priv; + if (service) { + free(service->name); + free(service); + } + + return ERROR_OK; +} + +static void semihosting_tcp_close_cnx(struct semihosting *semihosting) +{ + if (!semihosting->tcp_connection) + return; + + struct service *service = semihosting->tcp_connection->service; + remove_service(service->name, service->port); + semihosting->tcp_connection = NULL; + +} + +static const struct service_driver semihosting_service_driver = { + .name = "semihosting", + .new_connection_during_keep_alive_handler = NULL, + .new_connection_handler = semihosting_service_new_connection_handler, + .input_handler = semihosting_service_input_handler, + .connection_closed_handler = semihosting_service_connection_closed_handler, + .keep_client_alive_handler = NULL, +}; /* ------------------------------------------------------------------------- * Common semihosting commands handlers. */ @@ -1602,6 +1829,91 @@ COMMAND_HANDLER(handle_common_semihosting_command) return ERROR_OK; } +COMMAND_HANDLER(handle_common_semihosting_redirect_command) +{ + struct target *target = get_current_target(CMD_CTX); + + if (target == NULL) { + LOG_ERROR("No target selected"); + return ERROR_FAIL; + } + + struct semihosting *semihosting = target->semihosting; + if (!semihosting) { + command_print(CMD, "semihosting not supported for current target"); + return ERROR_FAIL; + } + + if (!semihosting->is_active) { + command_print(CMD, "semihosting not yet enabled for current target"); + return ERROR_FAIL; + } + + enum semihosting_redirect_config cfg; + const char *port; + + if (CMD_ARGC < 1) + return ERROR_COMMAND_SYNTAX_ERROR; + + if (strcmp(CMD_ARGV[0], "disable") == 0) { + cfg = SEMIHOSTING_REDIRECT_CFG_NONE; + if (CMD_ARGC > 1) + return ERROR_COMMAND_SYNTAX_ERROR; + } else if (strcmp(CMD_ARGV[0], "tcp") == 0) { + if (CMD_ARGC < 2 || CMD_ARGC > 3) + return ERROR_COMMAND_SYNTAX_ERROR; + + port = CMD_ARGV[1]; + + cfg = SEMIHOSTING_REDIRECT_CFG_ALL; + if (CMD_ARGC == 3) { + if (strcmp(CMD_ARGV[2], "debug") == 0) + cfg = SEMIHOSTING_REDIRECT_CFG_DEBUG; + else if (strcmp(CMD_ARGV[2], "stdio") == 0) + cfg = SEMIHOSTING_REDIRECT_CFG_STDIO; + else if (strcmp(CMD_ARGV[2], "all") != 0) + return ERROR_COMMAND_SYNTAX_ERROR; + } + } else { + return ERROR_COMMAND_SYNTAX_ERROR; + } + + semihosting_tcp_close_cnx(semihosting); + semihosting->redirect_cfg = SEMIHOSTING_REDIRECT_CFG_NONE; + + if (cfg != SEMIHOSTING_REDIRECT_CFG_NONE) { + struct semihosting_tcp_service *service = + calloc(1, sizeof(struct semihosting_tcp_service)); + if (!service) { + LOG_ERROR("Failed to allocate semihosting TCP service."); + return ERROR_FAIL; + } + + service->semihosting = semihosting; + + service->name = alloc_printf("%s semihosting service", target_name(target)); + if (!service->name) { + LOG_ERROR("Out of memory"); + free(service); + return ERROR_FAIL; + } + + int ret = add_service(&semihosting_service_driver, + port, 1, service); + + if (ret != ERROR_OK) { + LOG_ERROR("failed to initialize %s", service->name); + free(service->name); + free(service); + return ERROR_FAIL; + } + } + + semihosting->redirect_cfg = cfg; + + return ERROR_OK; +} + COMMAND_HANDLER(handle_common_semihosting_fileio_command) { struct target *target = get_current_target(CMD_CTX); @@ -1721,35 +2033,42 @@ COMMAND_HANDLER(handle_common_semihosting_read_user_param_command) const struct command_registration semihosting_common_handlers[] = { { - "semihosting", + .name = "semihosting", .handler = handle_common_semihosting_command, .mode = COMMAND_EXEC, .usage = "['enable'|'disable']", .help = "activate support for semihosting operations", }, { - "semihosting_cmdline", + .name = "semihosting_redirect", + .handler = handle_common_semihosting_redirect_command, + .mode = COMMAND_EXEC, + .usage = "(disable | tcp ['debug'|'stdio'|'all'])", + .help = "redirect semihosting IO", + }, + { + .name = "semihosting_cmdline", .handler = handle_common_semihosting_cmdline, .mode = COMMAND_EXEC, .usage = "arguments", .help = "command line arguments to be passed to program", }, { - "semihosting_fileio", + .name = "semihosting_fileio", .handler = handle_common_semihosting_fileio_command, .mode = COMMAND_EXEC, .usage = "['enable'|'disable']", .help = "activate support for semihosting fileio operations", }, { - "semihosting_resexit", + .name = "semihosting_resexit", .handler = handle_common_semihosting_resumable_exit_command, .mode = COMMAND_EXEC, .usage = "['enable'|'disable']", .help = "activate support for semihosting resumable exit", }, { - "semihosting_read_user_param", + .name = "semihosting_read_user_param", .handler = handle_common_semihosting_read_user_param_command, .mode = COMMAND_EXEC, .usage = "", diff --git a/src/target/semihosting_common.h b/src/target/semihosting_common.h index 6eb9ca252..459faf656 100644 --- a/src/target/semihosting_common.h +++ b/src/target/semihosting_common.h @@ -26,6 +26,7 @@ #include #include #include "helper/replacements.h" +#include /* * According to: @@ -95,6 +96,13 @@ enum semihosting_reported_exceptions { ADP_STOPPED_RUN_TIME_ERROR = ((2 << 16) + 35), }; +enum semihosting_redirect_config { + SEMIHOSTING_REDIRECT_CFG_NONE, + SEMIHOSTING_REDIRECT_CFG_DEBUG, + SEMIHOSTING_REDIRECT_CFG_STDIO, + SEMIHOSTING_REDIRECT_CFG_ALL, +}; + struct target; /* @@ -105,6 +113,15 @@ struct semihosting { /** A flag reporting whether semihosting is active. */ bool is_active; + /** Semihosting STDIO file descriptors */ + int stdin_fd, stdout_fd, stderr_fd; + + /** redirection configuration, NONE by default */ + enum semihosting_redirect_config redirect_cfg; + + /** Handle to redirect semihosting print via tcp */ + struct connection *tcp_connection; + /** A flag reporting whether semihosting fileio is active. */ bool is_fileio; diff --git a/src/target/startup.tcl b/src/target/startup.tcl index cd98d68e4..0e46992b7 100644 --- a/src/target/startup.tcl +++ b/src/target/startup.tcl @@ -206,6 +206,32 @@ proc init_target_events {} { proc init_board {} { } +proc mem2array {arrayname bitwidth address count {phys ""}} { + echo "DEPRECATED! use 'read_memory' not 'mem2array'" + + upvar $arrayname $arrayname + set $arrayname "" + set i 0 + + foreach elem [read_memory $address $bitwidth $count {*}$phys] { + set ${arrayname}($i) $elem + incr i + } +} + +proc array2mem {arrayname bitwidth address count {phys ""}} { + echo "DEPRECATED! use 'write_memory' not 'array2mem'" + + upvar $arrayname $arrayname + set data "" + + for {set i 0} {$i < $count} {incr i} { + lappend data [expr $${arrayname}($i)] + } + + write_memory $address $bitwidth $data {*}$phys +} + # smp_on/smp_off were already DEPRECATED in v0.11.0 through http://openocd.zylin.com/4615 lappend _telnet_autocomplete_skip "aarch64 smp_on" proc "aarch64 smp_on" {args} { diff --git a/src/target/stm8.c b/src/target/stm8.c index 21fc8c54f..4102082ff 100644 --- a/src/target/stm8.c +++ b/src/target/stm8.c @@ -1370,7 +1370,7 @@ static void stm8_enable_breakpoints(struct target *target) /* set any pending breakpoints */ while (breakpoint) { - if (breakpoint->set == 0) + if (!breakpoint->is_set) stm8_set_breakpoint(target, breakpoint); breakpoint = breakpoint->next; } @@ -1383,7 +1383,7 @@ static int stm8_set_breakpoint(struct target *target, struct stm8_comparator *comparator_list = stm8->hw_break_list; int retval; - if (breakpoint->set) { + if (breakpoint->is_set) { LOG_WARNING("breakpoint already set"); return ERROR_OK; } @@ -1398,7 +1398,7 @@ static int stm8_set_breakpoint(struct target *target, breakpoint->unique_id); return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; } - breakpoint->set = bp_num + 1; + breakpoint_hw_set(breakpoint, bp_num); comparator_list[bp_num].used = true; comparator_list[bp_num].bp_value = breakpoint->address; comparator_list[bp_num].type = HWBRK_EXEC; @@ -1435,7 +1435,7 @@ static int stm8_set_breakpoint(struct target *target, } else { return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; } - breakpoint->set = 1; /* Any nice value but 0 */ + breakpoint->is_set = true; } return ERROR_OK; @@ -1476,14 +1476,14 @@ static int stm8_unset_breakpoint(struct target *target, struct stm8_comparator *comparator_list = stm8->hw_break_list; int retval; - if (!breakpoint->set) { + if (!breakpoint->is_set) { LOG_WARNING("breakpoint not set"); return ERROR_OK; } if (breakpoint->type == BKPT_HARD) { - int bp_num = breakpoint->set - 1; - if ((bp_num < 0) || (bp_num >= stm8->num_hw_bpoints)) { + int bp_num = breakpoint->number; + if (bp_num >= stm8->num_hw_bpoints) { LOG_DEBUG("Invalid comparator number in breakpoint (bpid: %" PRIu32 ")", breakpoint->unique_id); return ERROR_OK; @@ -1517,7 +1517,7 @@ static int stm8_unset_breakpoint(struct target *target, } else return ERROR_FAIL; } - breakpoint->set = 0; + breakpoint->is_set = false; return ERROR_OK; } @@ -1533,7 +1533,7 @@ static int stm8_remove_breakpoint(struct target *target, return ERROR_TARGET_NOT_HALTED; } - if (breakpoint->set) + if (breakpoint->is_set) stm8_unset_breakpoint(target, breakpoint); if (breakpoint->type == BKPT_HARD) @@ -1550,7 +1550,7 @@ static int stm8_set_watchpoint(struct target *target, int wp_num = 0; int ret; - if (watchpoint->set) { + if (watchpoint->is_set) { LOG_WARNING("watchpoint already set"); return ERROR_OK; } @@ -1593,7 +1593,7 @@ static int stm8_set_watchpoint(struct target *target, return ret; } - watchpoint->set = wp_num + 1; + watchpoint_set(watchpoint, wp_num); LOG_DEBUG("wp_num %i bp_value 0x%" PRIx32 "", wp_num, @@ -1627,7 +1627,7 @@ static void stm8_enable_watchpoints(struct target *target) /* set any pending watchpoints */ while (watchpoint) { - if (watchpoint->set == 0) + if (!watchpoint->is_set) stm8_set_watchpoint(target, watchpoint); watchpoint = watchpoint->next; } @@ -1640,18 +1640,18 @@ static int stm8_unset_watchpoint(struct target *target, struct stm8_common *stm8 = target_to_stm8(target); struct stm8_comparator *comparator_list = stm8->hw_break_list; - if (!watchpoint->set) { + if (!watchpoint->is_set) { LOG_WARNING("watchpoint not set"); return ERROR_OK; } - int wp_num = watchpoint->set - 1; - if ((wp_num < 0) || (wp_num >= stm8->num_hw_bpoints)) { + int wp_num = watchpoint->number; + if (wp_num >= stm8->num_hw_bpoints) { LOG_DEBUG("Invalid hw comparator number in watchpoint"); return ERROR_OK; } comparator_list[wp_num].used = false; - watchpoint->set = 0; + watchpoint->is_set = false; stm8_set_hwbreak(target, comparator_list); @@ -1669,7 +1669,7 @@ static int stm8_remove_watchpoint(struct target *target, return ERROR_TARGET_NOT_HALTED; } - if (watchpoint->set) + if (watchpoint->is_set) stm8_unset_watchpoint(target, watchpoint); stm8->num_hw_bpoints_avail++; diff --git a/src/target/target.c b/src/target/target.c index 1959bbe0b..6cbfc6e2e 100644 --- a/src/target/target.c +++ b/src/target/target.c @@ -3972,26 +3972,26 @@ static int handle_bp_command_list(struct command_invocation *cmd) if (breakpoint->type == BKPT_SOFT) { char *buf = buf_to_hex_str(breakpoint->orig_instr, breakpoint->length); - command_print(cmd, "IVA breakpoint: " TARGET_ADDR_FMT ", 0x%x, %i, 0x%s", + command_print(cmd, "IVA breakpoint: " TARGET_ADDR_FMT ", 0x%x, 0x%s", breakpoint->address, breakpoint->length, - breakpoint->set, buf); + buf); free(buf); } else { if ((breakpoint->address == 0) && (breakpoint->asid != 0)) - command_print(cmd, "Context breakpoint: 0x%8.8" PRIx32 ", 0x%x, %i", + command_print(cmd, "Context breakpoint: 0x%8.8" PRIx32 ", 0x%x, %u", breakpoint->asid, - breakpoint->length, breakpoint->set); + breakpoint->length, breakpoint->number); else if ((breakpoint->address != 0) && (breakpoint->asid != 0)) { - command_print(cmd, "Hybrid breakpoint(IVA): " TARGET_ADDR_FMT ", 0x%x, %i", + command_print(cmd, "Hybrid breakpoint(IVA): " TARGET_ADDR_FMT ", 0x%x, %u", breakpoint->address, - breakpoint->length, breakpoint->set); + breakpoint->length, breakpoint->number); command_print(cmd, "\t|--->linked with ContextID: 0x%8.8" PRIx32, breakpoint->asid); } else - command_print(cmd, "Breakpoint(IVA): " TARGET_ADDR_FMT ", 0x%x, %i", + command_print(cmd, "Breakpoint(IVA): " TARGET_ADDR_FMT ", 0x%x, %u", breakpoint->address, - breakpoint->length, breakpoint->set); + breakpoint->length, breakpoint->number); } breakpoint = breakpoint->next; @@ -4436,27 +4436,12 @@ static int new_u64_array_element(Jim_Interp *interp, const char *varname, int id return result; } -static int jim_mem2array(Jim_Interp *interp, int argc, Jim_Obj *const *argv) -{ - struct command_context *context; - struct target *target; - - context = current_command_context(interp); - assert(context); - - target = get_current_target(context); - if (!target) { - LOG_ERROR("mem2array: no current target"); - return JIM_ERR; - } - - return target_mem2array(interp, target, argc - 1, argv + 1); -} - static int target_mem2array(Jim_Interp *interp, struct target *target, int argc, Jim_Obj *const *argv) { int e; + LOG_WARNING("DEPRECATED! use 'read_memory' not 'mem2array'"); + /* argv[0] = name of array to receive the data * argv[1] = desired element width in bits * argv[2] = memory address @@ -4609,6 +4594,161 @@ static int target_mem2array(Jim_Interp *interp, struct target *target, int argc, return e; } +static int target_jim_read_memory(Jim_Interp *interp, int argc, + Jim_Obj * const *argv) +{ + /* + * argv[1] = memory address + * argv[2] = desired element width in bits + * argv[3] = number of elements to read + * argv[4] = optional "phys" + */ + + if (argc < 4 || argc > 5) { + Jim_WrongNumArgs(interp, 1, argv, "address width count ['phys']"); + return JIM_ERR; + } + + /* Arg 1: Memory address. */ + jim_wide wide_addr; + int e; + e = Jim_GetWide(interp, argv[1], &wide_addr); + + if (e != JIM_OK) + return e; + + target_addr_t addr = (target_addr_t)wide_addr; + + /* Arg 2: Bit width of one element. */ + long l; + e = Jim_GetLong(interp, argv[2], &l); + + if (e != JIM_OK) + return e; + + const unsigned int width_bits = l; + + /* Arg 3: Number of elements to read. */ + e = Jim_GetLong(interp, argv[3], &l); + + if (e != JIM_OK) + return e; + + size_t count = l; + + /* Arg 4: Optional 'phys'. */ + bool is_phys = false; + + if (argc > 4) { + const char *phys = Jim_GetString(argv[4], NULL); + + if (strcmp(phys, "phys")) { + Jim_SetResultFormatted(interp, "invalid argument '%s', must be 'phys'", phys); + return JIM_ERR; + } + + is_phys = true; + } + + switch (width_bits) { + case 8: + case 16: + case 32: + case 64: + break; + default: + Jim_SetResultString(interp, "invalid width, must be 8, 16, 32 or 64", -1); + return JIM_ERR; + } + + const unsigned int width = width_bits / 8; + + if ((addr + (count * width)) < addr) { + Jim_SetResultString(interp, "read_memory: addr + count wraps to zero", -1); + return JIM_ERR; + } + + if (count > 65536) { + Jim_SetResultString(interp, "read_memory: too large read request, exeeds 64K elements", -1); + return JIM_ERR; + } + + struct command_context *cmd_ctx = current_command_context(interp); + assert(cmd_ctx != NULL); + struct target *target = get_current_target(cmd_ctx); + + const size_t buffersize = 4096; + uint8_t *buffer = malloc(buffersize); + + if (!buffer) { + LOG_ERROR("Failed to allocate memory"); + return JIM_ERR; + } + + Jim_Obj *result_list = Jim_NewListObj(interp, NULL, 0); + Jim_IncrRefCount(result_list); + + while (count > 0) { + const unsigned int max_chunk_len = buffersize / width; + const size_t chunk_len = MIN(count, max_chunk_len); + + int retval; + + if (is_phys) + retval = target_read_phys_memory(target, addr, width, chunk_len, buffer); + else + retval = target_read_memory(target, addr, width, chunk_len, buffer); + + if (retval != ERROR_OK) { + LOG_ERROR("read_memory: read at " TARGET_ADDR_FMT " with width=%u and count=%zu failed", + addr, width_bits, chunk_len); + Jim_SetResultString(interp, "read_memory: failed to read memory", -1); + e = JIM_ERR; + break; + } + + for (size_t i = 0; i < chunk_len ; i++) { + uint64_t v = 0; + + switch (width) { + case 8: + v = target_buffer_get_u64(target, &buffer[i * width]); + break; + case 4: + v = target_buffer_get_u32(target, &buffer[i * width]); + break; + case 2: + v = target_buffer_get_u16(target, &buffer[i * width]); + break; + case 1: + v = buffer[i]; + break; + } + + char value_buf[11]; + snprintf(value_buf, sizeof(value_buf), "0x%" PRIx64, v); + + Jim_ListAppendElement(interp, result_list, + Jim_NewStringObj(interp, value_buf, -1)); + } + + count -= chunk_len; + addr += chunk_len * width; + } + + free(buffer); + + if (e != JIM_OK) { + Jim_DecrRefCount(interp, result_list); + return e; + } + + Jim_SetResult(interp, result_list); + Jim_DecrRefCount(interp, result_list); + + return JIM_OK; +} + static int get_u64_array_element(Jim_Interp *interp, const char *varname, size_t idx, uint64_t *val) { char *namebuf = alloc_printf("%s(%zu)", varname, idx); @@ -4634,28 +4774,13 @@ static int get_u64_array_element(Jim_Interp *interp, const char *varname, size_t return result; } -static int jim_array2mem(Jim_Interp *interp, int argc, Jim_Obj *const *argv) -{ - struct command_context *context; - struct target *target; - - context = current_command_context(interp); - assert(context); - - target = get_current_target(context); - if (!target) { - LOG_ERROR("array2mem: no current target"); - return JIM_ERR; - } - - return target_array2mem(interp, target, argc-1, argv + 1); -} - static int target_array2mem(Jim_Interp *interp, struct target *target, int argc, Jim_Obj *const *argv) { int e; + LOG_WARNING("DEPRECATED! use 'write_memory' not 'array2mem'"); + /* argv[0] = name of array from which to read the data * argv[1] = desired element width in bits * argv[2] = memory address @@ -4819,6 +4944,144 @@ static int target_array2mem(Jim_Interp *interp, struct target *target, return e; } +static int target_jim_write_memory(Jim_Interp *interp, int argc, + Jim_Obj * const *argv) +{ + /* + * argv[1] = memory address + * argv[2] = desired element width in bits + * argv[3] = list of data to write + * argv[4] = optional "phys" + */ + + if (argc < 4 || argc > 5) { + Jim_WrongNumArgs(interp, 1, argv, "address width data ['phys']"); + return JIM_ERR; + } + + /* Arg 1: Memory address. */ + int e; + jim_wide wide_addr; + e = Jim_GetWide(interp, argv[1], &wide_addr); + + if (e != JIM_OK) + return e; + + target_addr_t addr = (target_addr_t)wide_addr; + + /* Arg 2: Bit width of one element. */ + long l; + e = Jim_GetLong(interp, argv[2], &l); + + if (e != JIM_OK) + return e; + + const unsigned int width_bits = l; + size_t count = Jim_ListLength(interp, argv[3]); + + /* Arg 4: Optional 'phys'. */ + bool is_phys = false; + + if (argc > 4) { + const char *phys = Jim_GetString(argv[4], NULL); + + if (strcmp(phys, "phys")) { + Jim_SetResultFormatted(interp, "invalid argument '%s', must be 'phys'", phys); + return JIM_ERR; + } + + is_phys = true; + } + + switch (width_bits) { + case 8: + case 16: + case 32: + case 64: + break; + default: + Jim_SetResultString(interp, "invalid width, must be 8, 16, 32 or 64", -1); + return JIM_ERR; + } + + const unsigned int width = width_bits / 8; + + if ((addr + (count * width)) < addr) { + Jim_SetResultString(interp, "write_memory: addr + len wraps to zero", -1); + return JIM_ERR; + } + + if (count > 65536) { + Jim_SetResultString(interp, "write_memory: too large memory write request, exceeds 64K elements", -1); + return JIM_ERR; + } + + struct command_context *cmd_ctx = current_command_context(interp); + assert(cmd_ctx != NULL); + struct target *target = get_current_target(cmd_ctx); + + const size_t buffersize = 4096; + uint8_t *buffer = malloc(buffersize); + + if (!buffer) { + LOG_ERROR("Failed to allocate memory"); + return JIM_ERR; + } + + size_t j = 0; + + while (count > 0) { + const unsigned int max_chunk_len = buffersize / width; + const size_t chunk_len = MIN(count, max_chunk_len); + + for (size_t i = 0; i < chunk_len; i++, j++) { + Jim_Obj *tmp = Jim_ListGetIndex(interp, argv[3], j); + jim_wide element_wide; + Jim_GetWide(interp, tmp, &element_wide); + + const uint64_t v = element_wide; + + switch (width) { + case 8: + target_buffer_set_u64(target, &buffer[i * width], v); + break; + case 4: + target_buffer_set_u32(target, &buffer[i * width], v); + break; + case 2: + target_buffer_set_u16(target, &buffer[i * width], v); + break; + case 1: + buffer[i] = v & 0x0ff; + break; + } + } + + count -= chunk_len; + + int retval; + + if (is_phys) + retval = target_write_phys_memory(target, addr, width, chunk_len, buffer); + else + retval = target_write_memory(target, addr, width, chunk_len, buffer); + + if (retval != ERROR_OK) { + LOG_ERROR("write_memory: write at " TARGET_ADDR_FMT " with width=%u and count=%zu failed", + addr, width_bits, chunk_len); + Jim_SetResultString(interp, "write_memory: failed to write memory", -1); + e = JIM_ERR; + break; + } + + addr += chunk_len * width; + } + + free(buffer); + + return e; +} + /* FIX? should we propagate errors here rather than printing them * and continuing? */ @@ -4868,6 +5131,144 @@ void target_handle_event(struct target *target, enum target_event e) } } +static int target_jim_get_reg(Jim_Interp *interp, int argc, + Jim_Obj * const *argv) +{ + bool force = false; + + if (argc == 3) { + const char *option = Jim_GetString(argv[1], NULL); + + if (!strcmp(option, "-force")) { + argc--; + argv++; + force = true; + } else { + Jim_SetResultFormatted(interp, "invalid option '%s'", option); + return JIM_ERR; + } + } + + if (argc != 2) { + Jim_WrongNumArgs(interp, 1, argv, "[-force] list"); + return JIM_ERR; + } + + const int length = Jim_ListLength(interp, argv[1]); + + Jim_Obj *result_dict = Jim_NewDictObj(interp, NULL, 0); + + if (!result_dict) + return JIM_ERR; + + struct command_context *cmd_ctx = current_command_context(interp); + assert(cmd_ctx != NULL); + const struct target *target = get_current_target(cmd_ctx); + + for (int i = 0; i < length; i++) { + Jim_Obj *elem = Jim_ListGetIndex(interp, argv[1], i); + + if (!elem) + return JIM_ERR; + + const char *reg_name = Jim_String(elem); + + struct reg *reg = register_get_by_name(target->reg_cache, reg_name, + false); + + if (!reg || !reg->exist) { + Jim_SetResultFormatted(interp, "unknown register '%s'", reg_name); + return JIM_ERR; + } + + if (force) { + int retval = reg->type->get(reg); + + if (retval != ERROR_OK) { + Jim_SetResultFormatted(interp, "failed to read register '%s'", + reg_name); + return JIM_ERR; + } + } + + char *reg_value = buf_to_hex_str(reg->value, reg->size); + + if (!reg_value) { + LOG_ERROR("Failed to allocate memory"); + return JIM_ERR; + } + + char *tmp = alloc_printf("0x%s", reg_value); + + free(reg_value); + + if (!tmp) { + LOG_ERROR("Failed to allocate memory"); + return JIM_ERR; + } + + Jim_DictAddElement(interp, result_dict, elem, + Jim_NewStringObj(interp, tmp, -1)); + + free(tmp); + } + + Jim_SetResult(interp, result_dict); + + return JIM_OK; +} + +static int target_jim_set_reg(Jim_Interp *interp, int argc, + Jim_Obj * const *argv) +{ + if (argc != 2) { + Jim_WrongNumArgs(interp, 1, argv, "dict"); + return JIM_ERR; + } + + int tmp; + Jim_Obj **dict = Jim_DictPairs(interp, argv[1], &tmp); + + if (!dict) + return JIM_ERR; + + const unsigned int length = tmp; + struct command_context *cmd_ctx = current_command_context(interp); + assert(cmd_ctx); + const struct target *target = get_current_target(cmd_ctx); + + for (unsigned int i = 0; i < length; i += 2) { + const char *reg_name = Jim_String(dict[i]); + const char *reg_value = Jim_String(dict[i + 1]); + struct reg *reg = register_get_by_name(target->reg_cache, reg_name, + false); + + if (!reg || !reg->exist) { + Jim_SetResultFormatted(interp, "unknown register '%s'", reg_name); + return JIM_ERR; + } + + uint8_t *buf = malloc(DIV_ROUND_UP(reg->size, 8)); + + if (!buf) { + LOG_ERROR("Failed to allocate memory"); + return JIM_ERR; + } + + str_to_buf(reg_value, strlen(reg_value), buf, reg->size, 0); + int retval = reg->type->set(reg, buf); + free(buf); + + if (retval != ERROR_OK) { + Jim_SetResultFormatted(interp, "failed to set '%s' to register '%s'", + reg_value, reg_name); + return JIM_ERR; + } + } + + return JIM_OK; +} + /** * Returns true only if the target has a handler for the specified event. */ @@ -5650,6 +6051,34 @@ static const struct command_registration target_instance_command_handlers[] = { "from target memory", .usage = "arrayname bitwidth address count", }, + { + .name = "get_reg", + .mode = COMMAND_EXEC, + .jim_handler = target_jim_get_reg, + .help = "Get register values from the target", + .usage = "list", + }, + { + .name = "set_reg", + .mode = COMMAND_EXEC, + .jim_handler = target_jim_set_reg, + .help = "Set target register values", + .usage = "dict", + }, + { + .name = "read_memory", + .mode = COMMAND_EXEC, + .jim_handler = target_jim_read_memory, + .help = "Read Tcl list of 8/16/32/64 bit numbers from target memory", + .usage = "address width count ['phys']", + }, + { + .name = "write_memory", + .mode = COMMAND_EXEC, + .jim_handler = target_jim_write_memory, + .help = "Write Tcl list of 8/16/32/64 bit numbers to target memory", + .usage = "address width data ['phys']", + }, { .name = "eventlist", .handler = handle_target_event_list, @@ -6720,20 +7149,32 @@ static const struct command_registration target_exec_command_handlers[] = { .usage = "filename [offset [type]]", }, { - .name = "mem2array", + .name = "get_reg", .mode = COMMAND_EXEC, - .jim_handler = jim_mem2array, - .help = "read 8/16/32 bit memory and return as a TCL array " - "for script processing", - .usage = "arrayname bitwidth address count", + .jim_handler = target_jim_get_reg, + .help = "Get register values from the target", + .usage = "list", }, { - .name = "array2mem", + .name = "set_reg", .mode = COMMAND_EXEC, - .jim_handler = jim_array2mem, - .help = "convert a TCL array to memory locations " - "and write the 8/16/32 bit values", - .usage = "arrayname bitwidth address count", + .jim_handler = target_jim_set_reg, + .help = "Set target register values", + .usage = "dict", + }, + { + .name = "read_memory", + .mode = COMMAND_EXEC, + .jim_handler = target_jim_read_memory, + .help = "Read Tcl list of 8/16/32/64 bit numbers from target memory", + .usage = "address width count ['phys']", + }, + { + .name = "write_memory", + .mode = COMMAND_EXEC, + .jim_handler = target_jim_write_memory, + .help = "Write Tcl list of 8/16/32/64 bit numbers to target memory", + .usage = "address width data ['phys']", }, { .name = "reset_nag", diff --git a/src/target/x86_32_common.c b/src/target/x86_32_common.c index a009bfe92..d119be148 100644 --- a/src/target/x86_32_common.c +++ b/src/target/x86_32_common.c @@ -862,7 +862,7 @@ int x86_32_common_remove_watchpoint(struct target *t, struct watchpoint *wp) { if (check_not_halted(t)) return ERROR_TARGET_NOT_HALTED; - if (wp->set) + if (wp->is_set) unset_watchpoint(t, wp); return ERROR_OK; } @@ -883,7 +883,7 @@ int x86_32_common_remove_breakpoint(struct target *t, struct breakpoint *bp) LOG_DEBUG("type=%d, addr=" TARGET_ADDR_FMT, bp->type, bp->address); if (check_not_halted(t)) return ERROR_TARGET_NOT_HALTED; - if (bp->set) + if (bp->is_set) unset_breakpoint(t, bp); return ERROR_OK; @@ -995,7 +995,7 @@ static int set_hwbp(struct target *t, struct breakpoint *bp) } if (set_debug_regs(t, bp->address, hwbp_num, DR7_BP_EXECUTE, 1) != ERROR_OK) return ERROR_FAIL; - bp->set = hwbp_num + 1; + breakpoint_hw_set(bp, hwbp_num); debug_reg_list[hwbp_num].used = 1; debug_reg_list[hwbp_num].bp_value = bp->address; LOG_USER("%s hardware breakpoint %" PRIu32 " set at 0x%08" PRIx32 " (hwreg=%" PRIu8 ")", __func__, @@ -1007,9 +1007,9 @@ static int unset_hwbp(struct target *t, struct breakpoint *bp) { struct x86_32_common *x86_32 = target_to_x86_32(t); struct x86_32_dbg_reg *debug_reg_list = x86_32->hw_break_list; - int hwbp_num = bp->set - 1; + int hwbp_num = bp->number; - if ((hwbp_num < 0) || (hwbp_num >= x86_32->num_hw_bpoints)) { + if (hwbp_num >= x86_32->num_hw_bpoints) { LOG_ERROR("%s invalid breakpoint number=%d, bpid=%" PRIu32, __func__, hwbp_num, bp->unique_id); return ERROR_OK; @@ -1055,7 +1055,7 @@ static int set_swbp(struct target *t, struct breakpoint *bp) __func__, readback, *bp->orig_instr); return ERROR_FAIL; } - bp->set = SW_BP_OPCODE; /* just non 0 */ + bp->is_set = true; /* add the memory patch */ struct swbp_mem_patch *new_patch = malloc(sizeof(struct swbp_mem_patch)); @@ -1134,7 +1134,7 @@ static int set_breakpoint(struct target *t, struct breakpoint *bp) int error = ERROR_OK; struct x86_32_common *x86_32 = target_to_x86_32(t); LOG_DEBUG("type=%d, addr=" TARGET_ADDR_FMT, bp->type, bp->address); - if (bp->set) { + if (bp->is_set) { LOG_ERROR("breakpoint already set"); return error; } @@ -1164,7 +1164,7 @@ static int set_breakpoint(struct target *t, struct breakpoint *bp) static int unset_breakpoint(struct target *t, struct breakpoint *bp) { LOG_DEBUG("type=%d, addr=" TARGET_ADDR_FMT, bp->type, bp->address); - if (!bp->set) { + if (!bp->is_set) { LOG_WARNING("breakpoint not set"); return ERROR_OK; } @@ -1182,7 +1182,7 @@ static int unset_breakpoint(struct target *t, struct breakpoint *bp) return ERROR_FAIL; } } - bp->set = 0; + bp->is_set = false; return ERROR_OK; } @@ -1193,7 +1193,7 @@ static int set_watchpoint(struct target *t, struct watchpoint *wp) int wp_num = 0; LOG_DEBUG("type=%d, addr=" TARGET_ADDR_FMT, wp->rw, wp->address); - if (wp->set) { + if (wp->is_set) { LOG_ERROR("%s watchpoint already set", __func__); return ERROR_OK; } @@ -1233,7 +1233,7 @@ static int set_watchpoint(struct target *t, struct watchpoint *wp) LOG_ERROR("%s only 'access' or 'write' watchpoints are supported", __func__); break; } - wp->set = wp_num + 1; + watchpoint_set(wp, wp_num); debug_reg_list[wp_num].used = 1; debug_reg_list[wp_num].bp_value = wp->address; LOG_USER("'%s' watchpoint %d set at " TARGET_ADDR_FMT " with length %" PRIu32 " (hwreg=%d)", @@ -1248,13 +1248,13 @@ static int unset_watchpoint(struct target *t, struct watchpoint *wp) struct x86_32_common *x86_32 = target_to_x86_32(t); struct x86_32_dbg_reg *debug_reg_list = x86_32->hw_break_list; LOG_DEBUG("type=%d, addr=" TARGET_ADDR_FMT, wp->rw, wp->address); - if (!wp->set) { + if (!wp->is_set) { LOG_WARNING("watchpoint not set"); return ERROR_OK; } - int wp_num = wp->set - 1; - if ((wp_num < 0) || (wp_num >= x86_32->num_hw_bpoints)) { + int wp_num = wp->number; + if (wp_num >= x86_32->num_hw_bpoints) { LOG_DEBUG("Invalid FP Comparator number in watchpoint"); return ERROR_OK; } @@ -1263,7 +1263,7 @@ static int unset_watchpoint(struct target *t, struct watchpoint *wp) debug_reg_list[wp_num].used = 0; debug_reg_list[wp_num].bp_value = 0; - wp->set = 0; + wp->is_set = false; LOG_USER("'%s' watchpoint %d removed from " TARGET_ADDR_FMT " with length %" PRIu32 " (hwreg=%d)", wp->rw == WPT_READ ? "read" : wp->rw == WPT_WRITE ? diff --git a/src/target/xscale.c b/src/target/xscale.c index dd383b6e4..78bd09922 100644 --- a/src/target/xscale.c +++ b/src/target/xscale.c @@ -1087,7 +1087,7 @@ static void xscale_enable_watchpoints(struct target *target) struct watchpoint *watchpoint = target->watchpoints; while (watchpoint) { - if (watchpoint->set == 0) + if (!watchpoint->is_set) xscale_set_watchpoint(target, watchpoint); watchpoint = watchpoint->next; } @@ -1099,7 +1099,7 @@ static void xscale_enable_breakpoints(struct target *target) /* set any pending breakpoints */ while (breakpoint) { - if (breakpoint->set == 0) + if (!breakpoint->is_set) xscale_set_breakpoint(target, breakpoint); breakpoint = breakpoint->next; } @@ -1506,7 +1506,7 @@ static int xscale_deassert_reset(struct target *target) /* mark all hardware breakpoints as unset */ while (breakpoint) { if (breakpoint->type == BKPT_HARD) - breakpoint->set = 0; + breakpoint->is_set = false; breakpoint = breakpoint->next; } @@ -2088,7 +2088,7 @@ static int xscale_set_breakpoint(struct target *target, return ERROR_TARGET_NOT_HALTED; } - if (breakpoint->set) { + if (breakpoint->is_set) { LOG_WARNING("breakpoint already set"); return ERROR_OK; } @@ -2098,11 +2098,13 @@ static int xscale_set_breakpoint(struct target *target, if (!xscale->ibcr0_used) { xscale_set_reg_u32(&xscale->reg_cache->reg_list[XSCALE_IBCR0], value); xscale->ibcr0_used = 1; - breakpoint->set = 1; /* breakpoint set on first breakpoint register */ + /* breakpoint set on first breakpoint register */ + breakpoint_hw_set(breakpoint, 0); } else if (!xscale->ibcr1_used) { xscale_set_reg_u32(&xscale->reg_cache->reg_list[XSCALE_IBCR1], value); xscale->ibcr1_used = 1; - breakpoint->set = 2; /* breakpoint set on second breakpoint register */ + /* breakpoint set on second breakpoint register */ + breakpoint_hw_set(breakpoint, 1); } else {/* bug: availability previously verified in xscale_add_breakpoint() */ LOG_ERROR("BUG: no hardware comparator available"); return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; @@ -2133,7 +2135,7 @@ static int xscale_set_breakpoint(struct target *target, if (retval != ERROR_OK) return retval; } - breakpoint->set = 1; + breakpoint->is_set = true; xscale_send_u32(target, 0x50); /* clean dcache */ xscale_send_u32(target, xscale->cache_clean_address); @@ -2176,20 +2178,20 @@ static int xscale_unset_breakpoint(struct target *target, return ERROR_TARGET_NOT_HALTED; } - if (!breakpoint->set) { + if (!breakpoint->is_set) { LOG_WARNING("breakpoint not set"); return ERROR_OK; } if (breakpoint->type == BKPT_HARD) { - if (breakpoint->set == 1) { + if (breakpoint->number == 0) { xscale_set_reg_u32(&xscale->reg_cache->reg_list[XSCALE_IBCR0], 0x0); xscale->ibcr0_used = 0; - } else if (breakpoint->set == 2) { + } else if (breakpoint->number == 1) { xscale_set_reg_u32(&xscale->reg_cache->reg_list[XSCALE_IBCR1], 0x0); xscale->ibcr1_used = 0; } - breakpoint->set = 0; + breakpoint->is_set = false; } else { /* restore original instruction (kept in target endianness) */ if (breakpoint->length == 4) { @@ -2203,7 +2205,7 @@ static int xscale_unset_breakpoint(struct target *target, if (retval != ERROR_OK) return retval; } - breakpoint->set = 0; + breakpoint->is_set = false; xscale_send_u32(target, 0x50); /* clean dcache */ xscale_send_u32(target, xscale->cache_clean_address); @@ -2223,7 +2225,7 @@ static int xscale_remove_breakpoint(struct target *target, struct breakpoint *br return ERROR_TARGET_NOT_HALTED; } - if (breakpoint->set) + if (breakpoint->is_set) xscale_unset_breakpoint(target, breakpoint); if (breakpoint->type == BKPT_HARD) @@ -2279,13 +2281,13 @@ static int xscale_set_watchpoint(struct target *target, xscale_set_reg_u32(&xscale->reg_cache->reg_list[XSCALE_DBR0], watchpoint->address); dbcon_value |= enable; xscale_set_reg_u32(dbcon, dbcon_value); - watchpoint->set = 1; + watchpoint_set(watchpoint, 0); xscale->dbr0_used = 1; } else if (!xscale->dbr1_used) { xscale_set_reg_u32(&xscale->reg_cache->reg_list[XSCALE_DBR1], watchpoint->address); dbcon_value |= enable << 2; xscale_set_reg_u32(dbcon, dbcon_value); - watchpoint->set = 2; + watchpoint_set(watchpoint, 1); xscale->dbr1_used = 1; } else { LOG_ERROR("BUG: no hardware comparator available"); @@ -2349,12 +2351,12 @@ static int xscale_unset_watchpoint(struct target *target, return ERROR_TARGET_NOT_HALTED; } - if (!watchpoint->set) { + if (!watchpoint->is_set) { LOG_WARNING("breakpoint not set"); return ERROR_OK; } - if (watchpoint->set == 1) { + if (watchpoint->number == 0) { if (watchpoint->length > 4) { dbcon_value &= ~0x103; /* clear DBCON[M] as well */ xscale->dbr1_used = 0; /* DBR1 was used for mask */ @@ -2363,12 +2365,12 @@ static int xscale_unset_watchpoint(struct target *target, xscale_set_reg_u32(dbcon, dbcon_value); xscale->dbr0_used = 0; - } else if (watchpoint->set == 2) { + } else if (watchpoint->number == 1) { dbcon_value &= ~0xc; xscale_set_reg_u32(dbcon, dbcon_value); xscale->dbr1_used = 0; } - watchpoint->set = 0; + watchpoint->is_set = false; return ERROR_OK; } @@ -2382,7 +2384,7 @@ static int xscale_remove_watchpoint(struct target *target, struct watchpoint *wa return ERROR_TARGET_NOT_HALTED; } - if (watchpoint->set) + if (watchpoint->is_set) xscale_unset_watchpoint(target, watchpoint); if (watchpoint->length > 4) diff --git a/tcl/board/at91cap7a-stk-sdram.cfg b/tcl/board/at91cap7a-stk-sdram.cfg index 8a371e064..182a4067f 100644 --- a/tcl/board/at91cap7a-stk-sdram.cfg +++ b/tcl/board/at91cap7a-stk-sdram.cfg @@ -32,8 +32,7 @@ $_TARGETNAME configure -event reset-start { } proc peek32 {address} { - mem2array t 32 $address 1 - return $t(0) + return [read_memory $address 32 1] } # Wait for an expression to be true with a timeout diff --git a/tcl/board/at91sam9g20-ek.cfg b/tcl/board/at91sam9g20-ek.cfg index e1cbb9120..04d9a197c 100644 --- a/tcl/board/at91sam9g20-ek.cfg +++ b/tcl/board/at91sam9g20-ek.cfg @@ -40,9 +40,7 @@ at91sam9 rdy_busy 0 0xfffff800 13 at91sam9 ce 0 0xfffff800 14 proc read_register {register} { - set result "" - mem2array result 32 $register 1 - return $result(0) + return [read_memory $register 32 1] } proc at91sam9g20_reset_start { } { diff --git a/tcl/board/embedded-artists_lpc2478-32.cfg b/tcl/board/embedded-artists_lpc2478-32.cfg index 38f5e1b8e..a73d83263 100644 --- a/tcl/board/embedded-artists_lpc2478-32.cfg +++ b/tcl/board/embedded-artists_lpc2478-32.cfg @@ -8,9 +8,7 @@ source [find target/lpc2478.cfg] # Helper # proc read_register {register} { - set result "" - mem2array result 32 $register 1 - return $result(0) + return [read_memory $register 32 1] } proc init_board {} { diff --git a/tcl/board/hilscher_nxhx10.cfg b/tcl/board/hilscher_nxhx10.cfg index 1875dacc0..6e2eba79e 100644 --- a/tcl/board/hilscher_nxhx10.cfg +++ b/tcl/board/hilscher_nxhx10.cfg @@ -26,9 +26,7 @@ proc flash_init { } { } proc mread32 {addr} { - set value(0) 0 - mem2array value 32 $addr 1 - return $value(0) + return [read_memory $addr 32 1] } proc init_clocks { } { diff --git a/tcl/board/icnova_sam9g45_sodimm.cfg b/tcl/board/icnova_sam9g45_sodimm.cfg index 8a0736b1f..91e0107c2 100644 --- a/tcl/board/icnova_sam9g45_sodimm.cfg +++ b/tcl/board/icnova_sam9g45_sodimm.cfg @@ -43,9 +43,7 @@ flash bank $_FLASHNAME cfi 0x10000000 0x00800000 2 2 $_TARGETNAME proc read_register {register} { - set result "" - mem2array result 32 $register 1 - return $result(0) + return [read_memory $register 32 1] } proc at91sam9g45_start { } { diff --git a/tcl/board/lemaker_hikey.cfg b/tcl/board/lemaker_hikey.cfg index ee677c34b..325b6fdda 100644 --- a/tcl/board/lemaker_hikey.cfg +++ b/tcl/board/lemaker_hikey.cfg @@ -17,7 +17,7 @@ proc core_up { args } { global _TARGETNAME # examine remaining cores - foreach _core [set args] { + foreach _core $args { ${_TARGETNAME}$_core arp_examine } } diff --git a/tcl/board/nxp_frdm-k64f.cfg b/tcl/board/nxp_frdm-k64f.cfg new file mode 100644 index 000000000..1581c9594 --- /dev/null +++ b/tcl/board/nxp_frdm-k64f.cfg @@ -0,0 +1,15 @@ +# SPDX-License-Identifier: GPL-2.0-or-later + +# This is an NXP Freedom eval board with a single MK64FN1M0VLL12 chip. +# https://www.nxp.com/design/development-boards/freedom-development-boards/mcu-boards/freedom-development-platform-for-kinetis-k64-k63-and-k24-mcus:FRDM-K64F +# + +source [find interface/cmsis-dap.cfg] + +# Set working area to 16 KiB +set WORKAREASIZE 0x4000 + +set CHIPNAME k64f +reset_config srst_only + +source [find target/kx.cfg] diff --git a/tcl/board/nxp_rdb-ls1046a.cfg b/tcl/board/nxp_rdb-ls1046a.cfg new file mode 100644 index 000000000..fde1829fb --- /dev/null +++ b/tcl/board/nxp_rdb-ls1046a.cfg @@ -0,0 +1,17 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# NXP LS1046ARDB (Reference Design Board) +# This is for the "console" USB port on the front panel +# You must ensure that SW4-7 is in the "off" position + +# NXP K20 +# The firmware implements the old CMSIS-DAP v1 USB HID interface +# You must pass --enable-cmsis-dap to ./configure to enable it +source [find interface/cmsis-dap.cfg] + +transport select jtag +reset_config srst_only + +source [find target/ls1046a.cfg] + +# The adapter can't handle 10MHz +adapter speed 5000 diff --git a/tcl/board/ti_am625evm.cfg b/tcl/board/ti_am625evm.cfg new file mode 100644 index 000000000..4906fd096 --- /dev/null +++ b/tcl/board/ti_am625evm.cfg @@ -0,0 +1,25 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2021-2022 Texas Instruments Incorporated - http://www.ti.com/ +# +# Texas Instruments am625 EVM/SK +# Link: https://www.ti.com/lit/zip/sprr448 +# + +# AM625 EVM has an xds110 onboard. +source [find interface/xds110.cfg] + +transport select jtag + +# default JTAG configuration has only SRST and no TRST +reset_config srst_only srst_push_pull + +# delay after SRST goes inactive +adapter srst delay 20 + +if { ![info exists SOC] } { + set SOC am625 +} + +source [find target/ti_k3.cfg] + +adapter speed 2500 diff --git a/tcl/board/ti_j721s2evm.cfg b/tcl/board/ti_j721s2evm.cfg new file mode 100644 index 000000000..72418b57b --- /dev/null +++ b/tcl/board/ti_j721s2evm.cfg @@ -0,0 +1,25 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2021 Texas Instruments Incorporated - http://www.ti.com/ +# +# Texas Instruments J721s2 EVM +# Link(SoM): https://www.ti.com/lit/zip/sprr439 +# + +# J721s2 EVM has an xds110 onboard. +source [find interface/xds110.cfg] + +transport select jtag + +# default JTAG configuration has only SRST and no TRST +reset_config srst_only srst_push_pull + +# delay after SRST goes inactive +adapter srst delay 20 + +if { ![info exists SOC] } { + set SOC j721s2 +} + +source [find target/ti_k3.cfg] + +adapter speed 2500 diff --git a/tcl/board/tocoding_poplar.cfg b/tcl/board/tocoding_poplar.cfg index 6d2e6354e..36d5aec47 100644 --- a/tcl/board/tocoding_poplar.cfg +++ b/tcl/board/tocoding_poplar.cfg @@ -19,7 +19,7 @@ proc core_up { args } { global _TARGETNAME # examine remaining cores - foreach _core [set args] { + foreach _core $args { ${_TARGETNAME}$_core arp_examine } } diff --git a/tcl/chip/atmel/at91/aic.tcl b/tcl/chip/atmel/at91/aic.tcl index b0b100270..8b8a48f3b 100644 --- a/tcl/chip/atmel/at91/aic.tcl +++ b/tcl/chip/atmel/at91/aic.tcl @@ -54,36 +54,36 @@ proc show_AIC_IMR_helper { NAME ADDR VAL } { proc show_AIC { } { global AIC_SMR - if [catch { mem2array aaa 32 $AIC_SMR [expr {32 * 4}] } msg ] { + if [catch { set aaa [read_memory $AIC_SMR 32 [expr {32 * 4}]] } msg ] { error [format "%s (%s)" $msg AIC_SMR] } echo "AIC_SMR: Mode & Type" global AT91C_ID for { set x 0 } { $x < 32 } { } { echo -n " " - echo -n [format "%2d: %5s 0x%08x | " $x $AT91C_ID($x) $aaa($x)] + echo -n [format "%2d: %5s 0x%08x | " $x $AT91C_ID($x) [lindex $aaa $x]] incr x - echo -n [format "%2d: %5s 0x%08x | " $x $AT91C_ID($x) $aaa($x)] + echo -n [format "%2d: %5s 0x%08x | " $x $AT91C_ID($x) [lindex $aaa $x]] incr x - echo -n [format "%2d: %5s 0x%08x | " $x $AT91C_ID($x) $aaa($x)] + echo -n [format "%2d: %5s 0x%08x | " $x $AT91C_ID($x) [lindex $aaa $x]] incr x - echo [format "%2d: %5s 0x%08x" $x $AT91C_ID($x) $aaa($x)] + echo [format "%2d: %5s 0x%08x" $x $AT91C_ID($x) [lindex $aaa $x]] incr x } global AIC_SVR - if [catch { mem2array aaa 32 $AIC_SVR [expr {32 * 4}] } msg ] { + if [catch { set aaa [read_memory $AIC_SVR 32 [expr {32 * 4}]] } msg ] { error [format "%s (%s)" $msg AIC_SVR] } echo "AIC_SVR: Vectors" for { set x 0 } { $x < 32 } { } { echo -n " " - echo -n [format "%2d: %5s 0x%08x | " $x $AT91C_ID($x) $aaa($x)] + echo -n [format "%2d: %5s 0x%08x | " $x $AT91C_ID($x) [lindex $aaa $x]] incr x - echo -n [format "%2d: %5s 0x%08x | " $x $AT91C_ID($x) $aaa($x)] + echo -n [format "%2d: %5s 0x%08x | " $x $AT91C_ID($x) [lindex $aaa $x]] incr x - echo -n [format "%2d: %5s 0x%08x | " $x $AT91C_ID($x) $aaa($x)] + echo -n [format "%2d: %5s 0x%08x | " $x $AT91C_ID($x) [lindex $aaa $x]] incr x - echo [format "%2d: %5s 0x%08x" $x $AT91C_ID($x) $aaa($x)] + echo [format "%2d: %5s 0x%08x" $x $AT91C_ID($x) [lindex $aaa $x]] incr x } diff --git a/tcl/cpu/arc/common.tcl b/tcl/cpu/arc/common.tcl index e9a915717..b31e31a34 100644 --- a/tcl/cpu/arc/common.tcl +++ b/tcl/cpu/arc/common.tcl @@ -29,9 +29,8 @@ proc arc_common_reset { {target ""} } { # vector located at the interrupt vector base address, which is the first # entry (offset 0x00) in the vector table. set int_vector_base [arc jtag get-aux-reg 0x25] - set start_pc "" - mem2array start_pc 32 $int_vector_base 1 - arc jtag set-aux-reg 0x6 $start_pc(0) + set start_pc [read_memory $int_vector_base 32 1] + arc jtag set-aux-reg 0x6 $start_pc # It is OK to do uncached writes - register cache will be invalidated by # the reset_assert() function. diff --git a/tcl/mem_helper.tcl b/tcl/mem_helper.tcl index 9ea285a22..1c860119a 100644 --- a/tcl/mem_helper.tcl +++ b/tcl/mem_helper.tcl @@ -2,9 +2,7 @@ # mrw: "memory read word", returns value of $reg proc mrw {reg} { - set value "" - mem2array value 32 $reg 1 - return $value(0) + return [read_memory $reg 32 1] } add_usage_text mrw "address" @@ -12,9 +10,7 @@ add_help_text mrw "Returns value of word in memory." # mrh: "memory read halfword", returns value of $reg proc mrh {reg} { - set value "" - mem2array value 16 $reg 1 - return $value(0) + return [read_memory $reg 16 1] } add_usage_text mrh "address" @@ -22,9 +18,7 @@ add_help_text mrh "Returns value of halfword in memory." # mrb: "memory read byte", returns value of $reg proc mrb {reg} { - set value "" - mem2array value 8 $reg 1 - return $value(0) + return [read_memory $reg 8 1] } add_usage_text mrb "address" diff --git a/tcl/memory.tcl b/tcl/memory.tcl index 8d50ba853..ac273451d 100644 --- a/tcl/memory.tcl +++ b/tcl/memory.tcl @@ -79,108 +79,96 @@ proc address_info { ADDRESS } { } proc memread32 {ADDR} { - set foo(0) 0 - if ![ catch { mem2array foo 32 $ADDR 1 } msg ] { - return $foo(0) + if ![ catch { set foo [read_memory $ADDR 32 1] } msg ] { + return $foo } else { error "memread32: $msg" } } proc memread16 {ADDR} { - set foo(0) 0 - if ![ catch { mem2array foo 16 $ADDR 1 } msg ] { - return $foo(0) + if ![ catch { set foo [read_memory $ADDR 16 1] } msg ] { + return $foo } else { error "memread16: $msg" } } proc memread8 {ADDR} { - set foo(0) 0 - if ![ catch { mem2array foo 8 $ADDR 1 } msg ] { - return $foo(0) + if ![ catch { set foo [read_memory $ADDR 8 1] } msg ] { + return $foo } else { error "memread8: $msg" } } proc memwrite32 {ADDR DATA} { - set foo(0) $DATA - if ![ catch { array2mem foo 32 $ADDR 1 } msg ] { - return $foo(0) + if ![ catch { write_memory $ADDR 32 $DATA } msg ] { + return $DATA } else { error "memwrite32: $msg" } } proc memwrite16 {ADDR DATA} { - set foo(0) $DATA - if ![ catch { array2mem foo 16 $ADDR 1 } msg ] { - return $foo(0) + if ![ catch { write_memory $ADDR 16 $DATA } msg ] { + return $DATA } else { error "memwrite16: $msg" } } proc memwrite8 {ADDR DATA} { - set foo(0) $DATA - if ![ catch { array2mem foo 8 $ADDR 1 } msg ] { - return $foo(0) + if ![ catch { write_memory $ADDR 8 $DATA } msg ] { + return $DATA } else { error "memwrite8: $msg" } } proc memread32_phys {ADDR} { - set foo(0) 0 - if ![ catch { mem2array foo 32 $ADDR 1 phys } msg ] { - return $foo(0) + if ![ catch { set foo [read_memory $ADDR 32 1 phys] } msg ] { + return $foo } else { error "memread32: $msg" } } proc memread16_phys {ADDR} { - set foo(0) 0 - if ![ catch { mem2array foo 16 $ADDR 1 phys } msg ] { - return $foo(0) + if ![ catch { set foo [read_memory $ADDR 16 1 phys] } msg ] { + return $foo } else { error "memread16: $msg" } } proc memread8_phys {ADDR} { - set foo(0) 0 - if ![ catch { mem2array foo 8 $ADDR 1 phys } msg ] { - return $foo(0) + if ![ catch { set foo [read_memory $ADDR 8 1 phys] } msg ] { + return $foo } else { error "memread8: $msg" } } proc memwrite32_phys {ADDR DATA} { - set foo(0) $DATA - if ![ catch { array2mem foo 32 $ADDR 1 phys } msg ] { - return $foo(0) + if ![ catch { write_memory $ADDR 32 $DATA phys } msg ] { + return $DATA } else { error "memwrite32: $msg" } } proc memwrite16_phys {ADDR DATA} { - set foo(0) $DATA - if ![ catch { array2mem foo 16 $ADDR 1 phys } msg ] { - return $foo(0) + if ![ catch { write_memory $ADDR 16 $DATA phys } msg ] { + return $DATA } else { error "memwrite16: $msg" } } proc memwrite8_phys {ADDR DATA} { - set foo(0) $DATA - if ![ catch { array2mem foo 8 $ADDR 1 phys } msg ] { - return $foo(0) + if ![ catch { write_memory $ADDR 8 $DATA phys } msg ] { + return $DATA } else { error "memwrite8: $msg" } diff --git a/tcl/target/bluefield.cfg b/tcl/target/bluefield.cfg index 62b1e3165..dcebb2fb1 100644 --- a/tcl/target/bluefield.cfg +++ b/tcl/target/bluefield.cfg @@ -72,7 +72,7 @@ proc core_up { args } { global _TARGETNAME # Examine remaining cores - foreach _core [set args] { + foreach _core $args { ${_TARGETNAME}$_core arp_examine } } diff --git a/tcl/target/c100helper.tcl b/tcl/target/c100helper.tcl index bdcfd8cf5..ecd7edf11 100644 --- a/tcl/target/c100helper.tcl +++ b/tcl/target/c100helper.tcl @@ -29,9 +29,7 @@ source [find mem_helper.tcl] # read a 64-bit register (memory mapped) proc mr64bit {reg} { - set value "" - mem2array value 32 $reg 2 - return $value + return [read_memory $reg 32 2] } @@ -117,19 +115,19 @@ proc showAmbaClk {} { set PLL_CLK_BYPASS [regs PLL_CLK_BYPASS] echo [format "CLKCORE_AHB_CLK_CNTRL (0x%x): 0x%x" $CLKCORE_AHB_CLK_CNTRL [mrw $CLKCORE_AHB_CLK_CNTRL]] - mem2array value 32 $CLKCORE_AHB_CLK_CNTRL 1 + set value [read_memory $CLKCORE_AHB_CLK_CNTRL 32 1] # see if the PLL is in bypass mode - set bypass [expr {($value(0) & $PLL_CLK_BYPASS) >> 24}] + set bypass [expr {($value & $PLL_CLK_BYPASS) >> 24}] echo [format "PLL bypass bit: %d" $bypass] if {$bypass == 1} { echo [format "Amba Clk is set to REFCLK: %d (MHz)" [expr {$CFG_REFCLKFREQ/1000000}]] } else { # nope, extract x,y,w and compute the PLL output freq. - set x [expr {($value(0) & 0x0001F0000) >> 16}] + set x [expr {($value & 0x0001F0000) >> 16}] echo [format "x: %d" $x] - set y [expr {($value(0) & 0x00000007F)}] + set y [expr {($value & 0x00000007F)}] echo [format "y: %d" $y] - set w [expr {($value(0) & 0x000000300) >> 8}] + set w [expr {($value & 0x000000300) >> 8}] echo [format "w: %d" $w] echo [format "Amba PLL Clk: %d (MHz)" [expr {($CFG_REFCLKFREQ * $y / (($w + 1) * ($x + 1) * 2))/1000000}]] } @@ -192,19 +190,19 @@ proc showArmClk {} { set PLL_CLK_BYPASS [regs PLL_CLK_BYPASS] echo [format "CLKCORE_ARM_CLK_CNTRL (0x%x): 0x%x" $CLKCORE_ARM_CLK_CNTRL [mrw $CLKCORE_ARM_CLK_CNTRL]] - mem2array value 32 $CLKCORE_ARM_CLK_CNTRL 1 + set value [read_memory $CLKCORE_ARM_CLK_CNTRL 32 1] # see if the PLL is in bypass mode - set bypass [expr {($value(0) & $PLL_CLK_BYPASS) >> 24}] + set bypass [expr {($value & $PLL_CLK_BYPASS) >> 24}] echo [format "PLL bypass bit: %d" $bypass] if {$bypass == 1} { echo [format "Amba Clk is set to REFCLK: %d (MHz)" [expr {$CFG_REFCLKFREQ/1000000}]] } else { # nope, extract x,y,w and compute the PLL output freq. - set x [expr {($value(0) & 0x0001F0000) >> 16}] + set x [expr {($value & 0x0001F0000) >> 16}] echo [format "x: %d" $x] - set y [expr {($value(0) & 0x00000007F)}] + set y [expr {($value & 0x00000007F)}] echo [format "y: %d" $y] - set w [expr {($value(0) & 0x000000300) >> 8}] + set w [expr {($value & 0x000000300) >> 8}] echo [format "w: %d" $w] echo [format "Arm PLL Clk: %d (MHz)" [expr {($CFG_REFCLKFREQ * $y / (($w + 1) * ($x + 1) * 2))/1000000}]] } diff --git a/tcl/target/hilscher_netx500.cfg b/tcl/target/hilscher_netx500.cfg index 6d919f9dd..131bef221 100644 --- a/tcl/target/hilscher_netx500.cfg +++ b/tcl/target/hilscher_netx500.cfg @@ -26,9 +26,7 @@ set _TARGETNAME $_CHIPNAME.cpu target create $_TARGETNAME arm926ejs -endian $_ENDIAN -chain-position $_TARGETNAME proc mread32 {addr} { - set value(0) 0 - mem2array value 32 $addr 1 - return $value(0) + return [read_memory $addr 32 1] } # This function must be called on netX100/500 right after halt diff --git a/tcl/target/ls1046a.cfg b/tcl/target/ls1046a.cfg new file mode 100644 index 000000000..3d96a994e --- /dev/null +++ b/tcl/target/ls1046a.cfg @@ -0,0 +1,56 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# NXP LS1046A + +if { [info exists CHIPNAME] } { + set _CHIPNAME $CHIPNAME +} else { + set _CHIPNAME ls1046a +} + +if { [info exists DAP_TAPID] } { + set _DAP_TAPID $DAP_TAPID +} else { + set _DAP_TAPID 0x5ba00477 +} + +if { [info exists SAP_TAPID] } { + set _SAP_TAPID $SAP_TAPID +} else { + set _SAP_TAPID 0x06b3001d +} + +jtag newtap $_CHIPNAME dap -irlen 4 -expected-id $_DAP_TAPID +dap create $_CHIPNAME.dap -chain-position $_CHIPNAME.dap + +target create $_CHIPNAME.axi mem_ap -dap $_CHIPNAME.dap -ap-num 0 + +set _CPU_BASE 0x80400000 +set _CPU_STRIDE 0x100000 +set _CPU_DBGOFF 0x10000 +set _CPU_CTIOFF 0x20000 + +set _TARGETS {} +for {set i 0} {$i < 4} {incr i} { + set _BASE [expr {$_CPU_BASE + $_CPU_STRIDE * $i}] + cti create $_CHIPNAME.cti$i -dap $_CHIPNAME.dap -ap-num 1 \ + -baseaddr [expr {$_BASE + $_CPU_CTIOFF}] + target create $_CHIPNAME.cpu$i aarch64 -dap $_CHIPNAME.dap \ + -cti $_CHIPNAME.cti$i -dbgbase [expr {$_BASE + $_CPU_DBGOFF}] \ + -coreid $i {*}[expr {$i ? {-defer-examine} : {-rtos hwthread} }] + lappend _TARGETS $_CHIPNAME.cpu$i +} + +target smp {*}$_TARGETS + +jtag newtap $_CHIPNAME sap -irlen 8 -expected-id $_SAP_TAPID +target create $_CHIPNAME.sap ls1_sap -chain-position $_CHIPNAME.sap -endian big + +proc core_up { args } { + foreach core $args { + $::_CHIPNAME.cpu$core arp_examine + } +} + +targets $_CHIPNAME.cpu0 + +adapter speed 10000 diff --git a/tcl/target/psoc4.cfg b/tcl/target/psoc4.cfg index cffcbc753..40f2fcab3 100644 --- a/tcl/target/psoc4.cfg +++ b/tcl/target/psoc4.cfg @@ -74,22 +74,22 @@ if {![using_hla]} { } proc psoc4_get_family_id {} { - set err [catch "mem2array romtable_pid 32 0xF0000FE0 3"] + set err [catch {set romtable_pid [read_memory 0xF0000FE0 32 3]}] if { $err } { return 0 } - if { [expr {$romtable_pid(0) & 0xffffff00 }] - || [expr {$romtable_pid(1) & 0xffffff00 }] - || [expr {$romtable_pid(2) & 0xffffff00 }] } { + if { [expr {[lindex $romtable_pid 0] & 0xffffff00 }] + || [expr {[lindex $romtable_pid 1] & 0xffffff00 }] + || [expr {[lindex $romtable_pid 2] & 0xffffff00 }] } { echo "Unexpected data in ROMTABLE" return 0 } - set designer_id [expr {(( $romtable_pid(1) & 0xf0 ) >> 4) | (( $romtable_pid(2) & 0xf ) << 4 ) }] + set designer_id [expr {(( [lindex $romtable_pid 1] & 0xf0 ) >> 4) | (( [lindex $romtable_pid 2] & 0xf ) << 4 ) }] if { $designer_id != 0xb4 } { echo [format "ROMTABLE Designer ID 0x%02x is not Cypress" $designer_id] return 0 } - set family_id [expr {( $romtable_pid(0) & 0xff ) | (( $romtable_pid(1) & 0xf ) << 8 ) }] + set family_id [expr {( [lindex $romtable_pid 0] & 0xff ) | (( [lindex $romtable_pid 1] & 0xf ) << 8 ) }] return $family_id } @@ -193,9 +193,9 @@ proc ocd_process_reset_inner { MODE } { } # Set registers to reset vector values - mem2array value 32 0 2 - reg pc [expr {$value(1) & 0xfffffffe} ] - reg msp $value(0) + set value [read_memory 0x0 32 2] + reg pc [expr {[lindex $value 1] & 0xfffffffe}] + reg msp [lindex $value 0] if { $PSOC4_TEST_MODE_WORKAROUND } { catch { mww $TEST_MODE 0 } diff --git a/tcl/target/stm32h7x.cfg b/tcl/target/stm32h7x.cfg index f2a5c42c6..ca685c2f2 100644 --- a/tcl/target/stm32h7x.cfg +++ b/tcl/target/stm32h7x.cfg @@ -232,9 +232,7 @@ if {[set $_CHIPNAME.DUAL_CORE]} { # like mrw, but with target selection proc stm32h7x_mrw {used_target reg} { - set value "" - $used_target mem2array value 32 $reg 1 - return $value(0) + return [$used_target read_memory $reg 32 1] } # like mmw, but with target selection diff --git a/tcl/target/stm32l5x.cfg b/tcl/target/stm32l5x.cfg index 0616df1cb..c43b699d2 100644 --- a/tcl/target/stm32l5x.cfg +++ b/tcl/target/stm32l5x.cfg @@ -1,10 +1,8 @@ # SPDX-License-Identifier: GPL-2.0-or-later # script for stm32l5x family +# stm32l5x devices support both JTAG and SWD transports. -# -# stm32l5 devices support both JTAG and SWD transports. -# source [find target/swj-dp.tcl] source [find mem_helper.tcl] @@ -14,78 +12,10 @@ if { [info exists CHIPNAME] } { set _CHIPNAME stm32l5x } -set _ENDIAN little +source [find target/stm32x5x_common.cfg] -# Work-area is a space in RAM used for flash programming -# By default use 64kB -if { [info exists WORKAREASIZE] } { - set _WORKAREASIZE $WORKAREASIZE -} else { - set _WORKAREASIZE 0x10000 -} - -#jtag scan chain -if { [info exists CPUTAPID] } { - set _CPUTAPID $CPUTAPID -} else { - if { [using_jtag] } { - # See STM Document RM0438 - # RM0438 Rev5, Section 52.2.8 JTAG debug port - Table 425. JTAG-DP data registers - # Corresponds to Cortex®-M33 JTAG debug port ID code - set _CPUTAPID 0x0ba04477 - } { - # SWD IDCODE (single drop, arm) - set _CPUTAPID 0x0be12477 - } -} - -swj_newdap $_CHIPNAME cpu -irlen 4 -ircapture 0x1 -irmask 0xf -expected-id $_CPUTAPID -dap create $_CHIPNAME.dap -chain-position $_CHIPNAME.cpu - -if {[using_jtag]} { - jtag newtap $_CHIPNAME bs -irlen 5 -} - -set _TARGETNAME $_CHIPNAME.cpu -target create $_TARGETNAME cortex_m -endian $_ENDIAN -dap $_CHIPNAME.dap - -# use non-secure RAM by default -$_TARGETNAME configure -work-area-phys 0x20000000 -work-area-size $_WORKAREASIZE -work-area-backup 0 - -# create sec/ns flash and otp memories (sizes will be probed) -flash bank $_CHIPNAME.flash_ns stm32l4x 0x08000000 0 0 0 $_TARGETNAME -flash bank $_CHIPNAME.flash_alias_s stm32l4x 0x0C000000 0 0 0 $_TARGETNAME -flash bank $_CHIPNAME.otp stm32l4x 0x0BFA0000 0 0 0 $_TARGETNAME - -# Common knowledges tells JTAG speed should be <= F_CPU/6. -# F_CPU after reset is MSI 4MHz, so use F_JTAG = 500 kHz to stay on -# the safe side. -# -# Note that there is a pretty wide band where things are -# more or less stable, see http://openocd.zylin.com/#/c/3366/ -adapter speed 500 - -adapter srst delay 100 -if {[using_jtag]} { - jtag_ntrst_delay 100 -} - -reset_config srst_nogate - -if {![using_hla]} { - # if srst is not fitted use SYSRESETREQ to - # perform a soft reset - cortex_m reset_config sysresetreq -} - -proc is_secure {} { - # read Debug Security Control and Status Regsiter (DSCSR) and check CDS (bit 16) - set DSCSR [mrw 0xE000EE08] - return [expr {($DSCSR & (1 << 16)) != 0}] -} - -proc clock_config_110_mhz {} { - set offset [expr {[is_secure] ? 0x10000000 : 0}] +proc stm32l5x_clock_config {} { + set offset [expr {[stm32x5x_is_secure] ? 0x10000000 : 0}] # MCU clock is MSI (4MHz) after reset, set MCU freq at 110 MHz with PLL # RCC_APB1ENR1 = PWREN mww [expr {0x40021058 + $offset}] 0x10000000 @@ -111,90 +41,8 @@ proc clock_config_110_mhz {} { while {([mrw [expr {0x40021008 + $offset}]] & 0x0C) != 0x0C} {} } -proc ahb_ap_non_secure_access {} { - # SPROT=1=Non Secure access, Priv=1 - [[target current] cget -dap] apcsw 0x4B000000 0x4F000000 -} - -proc ahb_ap_secure_access {} { - # SPROT=0=Secure access, Priv=1 - [[target current] cget -dap] apcsw 0x0B000000 0x4F000000 -} - $_TARGETNAME configure -event reset-init { - clock_config_110_mhz + stm32l5x_clock_config # Boost JTAG frequency adapter speed 4000 } - -$_TARGETNAME configure -event reset-start { - # Reset clock is MSI (4 MHz) - adapter speed 480 -} - -$_TARGETNAME configure -event examine-end { - # DBGMCU_CR |= DBG_STANDBY | DBG_STOP - mmw 0xE0044004 0x00000006 0 - - # Stop watchdog counters during halt - # DBGMCU_APB1_FZ |= DBG_IWDG_STOP | DBG_WWDG_STOP - mmw 0xE0044008 0x00001800 0 -} - -$_TARGETNAME configure -event halted { - set secure [is_secure] - - if {$secure} { - set secure_str "Secure" - ahb_ap_secure_access - } else { - set secure_str "Non-Secure" - ahb_ap_non_secure_access - } - - # print the secure state only when it changes - set _TARGETNAME [target current] - global $_TARGETNAME.secure - - if {![info exists $_TARGETNAME.secure] || $secure != [set $_TARGETNAME.secure]} { - echo "CPU in $secure_str state" - # update saved security state - set $_TARGETNAME.secure $secure - } -} - -$_TARGETNAME configure -event gdb-flash-erase-start { - set use_secure_workarea 0 - # check if FLASH_OPTR.TZEN is enabled - set FLASH_OPTR [mrw 0x40022040] - if {[expr {$FLASH_OPTR & 0x80000000}] == 0} { - echo "TZEN option bit disabled" - ahb_ap_non_secure_access - } { - ahb_ap_secure_access - echo "TZEN option bit enabled" - - # check if FLASH_OPTR.RDP is not Level 0.5 - if {[expr {$FLASH_OPTR & 0xFF}] != 0x55} { - set use_secure_workarea 1 - } - } - - set workarea_addr [$_TARGETNAME cget -work-area-phys] - echo "workarea_addr $workarea_addr" - - if {$use_secure_workarea} { - set workarea_addr [expr {$workarea_addr | 0x10000000}] - } { - set workarea_addr [expr {$workarea_addr & ~0x10000000}] - } - - $_TARGETNAME configure -work-area-phys $workarea_addr -} - -$_TARGETNAME configure -event trace-config { - # Set TRACE_IOEN; TRACE_MODE is set to async; when using sync - # change this value accordingly to configure trace pins - # assignment - mmw 0xE0044004 0x00000020 0 -} diff --git a/tcl/target/stm32mp15x.cfg b/tcl/target/stm32mp15x.cfg index 639fbabe0..afd5d2413 100644 --- a/tcl/target/stm32mp15x.cfg +++ b/tcl/target/stm32mp15x.cfg @@ -109,8 +109,8 @@ proc toggle_cpu0_dbg_claim0 {} { } proc detect_cpu1 {} { - $::_CHIPNAME.ap1 mem2array cpu1_prsr 32 0xE00D2314 1 - set dual_core [expr {$cpu1_prsr(0) & 1}] + set cpu1_prsr [$::_CHIPNAME.ap1 read_memory 0xE00D2314 32 1] + set dual_core [expr {$cpu1_prsr & 1}] if {! $dual_core} {$::_CHIPNAME.cpu1 configure -defer-examine} } diff --git a/tcl/target/stm32u5x.cfg b/tcl/target/stm32u5x.cfg index 2c2c0e037..44b51e2b6 100644 --- a/tcl/target/stm32u5x.cfg +++ b/tcl/target/stm32u5x.cfg @@ -1,10 +1,8 @@ # SPDX-License-Identifier: GPL-2.0-or-later # script for stm32u5x family +# stm32u5x devices support both JTAG and SWD transports. -# -# stm32u5 devices support both JTAG and SWD transports. -# source [find target/swj-dp.tcl] source [find mem_helper.tcl] @@ -14,99 +12,34 @@ if { [info exists CHIPNAME] } { set _CHIPNAME stm32u5x } -set _ENDIAN little +source [find target/stm32x5x_common.cfg] -# Work-area is a space in RAM used for flash programming -# By default use 64kB -if { [info exists WORKAREASIZE] } { - set _WORKAREASIZE $WORKAREASIZE -} else { - set _WORKAREASIZE 0x10000 -} - -#jtag scan chain -if { [info exists CPUTAPID] } { - set _CPUTAPID $CPUTAPID -} else { - if { [using_jtag] } { - # See STM Document RM0438 - # RM0456 Rev1, Section 65.2.8 JTAG debug port - Table 661. JTAG-DP data registers - # Corresponds to Cortex®-M33 JTAG debug port ID code - set _CPUTAPID 0x0ba04477 - } { - # SWD IDCODE (single drop, arm) - set _CPUTAPID 0x0be12477 - } -} - -swj_newdap $_CHIPNAME cpu -irlen 4 -ircapture 0x1 -irmask 0xf -expected-id $_CPUTAPID -dap create $_CHIPNAME.dap -chain-position $_CHIPNAME.cpu - -if {[using_jtag]} { - jtag newtap $_CHIPNAME bs -irlen 5 -} - -set _TARGETNAME $_CHIPNAME.cpu -target create $_TARGETNAME cortex_m -endian $_ENDIAN -dap $_CHIPNAME.dap - -# use non-secure RAM by default -$_TARGETNAME configure -work-area-phys 0x20000000 -work-area-size $_WORKAREASIZE -work-area-backup 0 - -# create sec/ns flash and otp memories (sizes will be probed) -flash bank $_CHIPNAME.flash_ns stm32l4x 0x08000000 0 0 0 $_TARGETNAME -flash bank $_CHIPNAME.flash_alias_s stm32l4x 0x0C000000 0 0 0 $_TARGETNAME -flash bank $_CHIPNAME.otp stm32l4x 0x0BFA0000 0 0 0 $_TARGETNAME - -# Common knowledges tells JTAG speed should be <= F_CPU/6. -# F_CPU after reset is MSI 4MHz, so use F_JTAG = 500 kHz to stay on -# the safe side. -# -# Note that there is a pretty wide band where things are -# more or less stable, see http://openocd.zylin.com/#/c/3366/ -adapter speed 500 - -adapter srst delay 100 -if {[using_jtag]} { - jtag_ntrst_delay 100 -} - -reset_config srst_nogate - -if {![using_hla]} { - # if srst is not fitted use SYSRESETREQ to - # perform a soft reset - cortex_m reset_config sysresetreq -} - -proc is_secure {} { - # read Debug Security Control and Status Regsiter (DSCSR) and check CDS (bit 16) - set DSCSR [mrw 0xE000EE08] - return [expr {($DSCSR & (1 << 16)) != 0}] -} - -proc clock_config_160_mhz {} { - set offset [expr {[is_secure] ? 0x10000000 : 0}] +proc stm32u5x_clock_config {} { + set offset [expr {[stm32x5x_is_secure] ? 0x10000000 : 0}] # MCU clock is at MSI 4MHz after reset, set MCU freq at 160 MHz with PLL # Enable voltage range 1 for frequency above 100 Mhz # RCC_AHB3ENR = PWREN mww [expr {0x46020C94 + $offset}] 0x00000004 # delay for register clock enable (read back reg) - mrw [expr {0x56020C94 + $offset}] + mrw [expr {0x46020C94 + $offset}] # PWR_VOSR : VOS Range 1 - mww [expr {0x4602080C + $offset}] 0x00030000 - # delay for register write (read back reg) - mrw [expr {0x4602080C + $offset}] + mmw [expr {0x4602080C + $offset}] 0x00030000 0 + # while !(PWR_VOSR & VOSRDY) + while {!([mrw [expr {0x4602080C + $offset}]] & 0x00008000)} {} # FLASH_ACR : 4 WS for 160 MHz HCLK mww [expr {0x40022000 + $offset}] 0x00000004 - # RCC_PLL1CFGR => PLL1M=0000=/1, PLL1SRC=MSI 4MHz - mww [expr {0x46020C28 + $offset}] 0x00000001 + # RCC_PLL1CFGR => PLL1MBOOST=0, PLL1M=0=/1, PLL1FRACEN=0, PLL1SRC=MSI 4MHz + # PLL1REN=1, PLL1RGE => VCOInputRange=PLLInputRange_4_8 + mww [expr {0x46020C28 + $offset}] 0x00040009 + # Enable EPOD Booster + mmw [expr {0x4602080C + $offset}] 0x00040000 0 + # while !(PWR_VOSR & BOOSTRDY) + while {!([mrw [expr {0x4602080C + $offset}]] & 0x00004000)} {} # RCC_PLL1DIVR => PLL1P=PLL1Q=PLL1R=000001=/2, PLL1N=0x4F=80 # fVCO = 4 x 80 /1 = 320 # SYSCLOCK = fVCO/PLL1R = 320/2 = 160 MHz - mmw [expr {0x46020C34 + $offset}] 0x0000004F 0 - # RCC_PLL1CFGR => PLL1REN=1 - mmw [expr {0x46020C28 + $offset}] 0x00040000 0 + mww [expr {0x46020C34 + $offset}] 0x0101024F # RCC_CR |= PLL1ON mmw [expr {0x46020C00 + $offset}] 0x01000000 0 # while !(RCC_CR & PLL1RDY) @@ -117,91 +50,8 @@ proc clock_config_160_mhz {} { while {([mrw [expr {0x46020C1C + $offset}]] & 0x0C) != 0x0C} {} } -proc ahb_ap_non_secure_access {} { - # SPROT=1=Non Secure access, Priv=1 - [[target current] cget -dap] apcsw 0x4B000000 0x4F000000 -} - -proc ahb_ap_secure_access {} { - # SPROT=0=Secure access, Priv=1 - [[target current] cget -dap] apcsw 0x0B000000 0x4F000000 -} - $_TARGETNAME configure -event reset-init { - clock_config_160_mhz + stm32u5x_clock_config # Boost JTAG frequency adapter speed 4000 } - -$_TARGETNAME configure -event reset-start { - # Reset clock is MSI (4 MHz) - adapter speed 480 -} - -$_TARGETNAME configure -event examine-end { - # DBGMCU_CR |= DBG_STANDBY | DBG_STOP - mmw 0xE0044004 0x00000006 0 - - # Stop watchdog counters during halt - # DBGMCU_APB1_FZ |= DBG_IWDG_STOP | DBG_WWDG_STOP - mmw 0xE0044008 0x00001800 0 -} - -$_TARGETNAME configure -event halted { - set secure [is_secure] - - if {$secure} { - set secure_str "Secure" - ahb_ap_secure_access - } else { - set secure_str "Non-Secure" - ahb_ap_non_secure_access - } - - # print the secure state only when it changes - set _TARGETNAME [target current] - global $_TARGETNAME.secure - - if {![info exists $_TARGETNAME.secure] || $secure != [set $_TARGETNAME.secure]} { - echo "CPU in $secure_str state" - # update saved security state - set $_TARGETNAME.secure $secure - } -} - -$_TARGETNAME configure -event gdb-flash-erase-start { - set use_secure_workarea 0 - # check if FLASH_OPTR.TZEN is enabled - set FLASH_OPTR [mrw 0x40022040] - if {[expr {$FLASH_OPTR & 0x80000000}] == 0} { - echo "TZEN option bit disabled" - ahb_ap_non_secure_access - } else { - ahb_ap_secure_access - echo "TZEN option bit enabled" - - # check if FLASH_OPTR.RDP is not Level 0.5 - if {[expr {$FLASH_OPTR & 0xFF}] != 0x55} { - set use_secure_workarea 1 - } - } - - set _TARGETNAME [target current] - set workarea_addr [$_TARGETNAME cget -work-area-phys] - echo "workarea_addr $workarea_addr" - - if {$use_secure_workarea} { - set workarea_addr [expr {$workarea_addr | 0x10000000}] - } else { - set workarea_addr [expr {$workarea_addr & ~0x10000000}] - } - - $_TARGETNAME configure -work-area-phys $workarea_addr -} - -$_TARGETNAME configure -event trace-config { - # Set TRACE_IOEN; TRACE_MODE is set to async; when using sync - # change this value accordingly to configure trace pins - # assignment - mmw 0xE0044004 0x00000020 0 -} diff --git a/tcl/target/stm32wlx.cfg b/tcl/target/stm32wlx.cfg index fafe9bcba..75f6f0288 100644 --- a/tcl/target/stm32wlx.cfg +++ b/tcl/target/stm32wlx.cfg @@ -156,9 +156,7 @@ proc stm32wlx_get_chipname {} { # like mrw, but with target selection proc stm32wlx_mrw {used_target reg} { - set value "" - $used_target mem2array value 32 $reg 1 - return $value(0) + return [$used_target read_memory $reg 32 1] } # like mmw, but with target selection diff --git a/tcl/target/stm32x5x_common.cfg b/tcl/target/stm32x5x_common.cfg new file mode 100644 index 000000000..276d0cca0 --- /dev/null +++ b/tcl/target/stm32x5x_common.cfg @@ -0,0 +1,154 @@ +# SPDX-License-Identifier: GPL-2.0-or-later + +# common script for stm32l5x and stm32u5x families + +# Work-area is a space in RAM used for flash programming +# By default use 64kB +if { [info exists WORKAREASIZE] } { + set _WORKAREASIZE $WORKAREASIZE +} else { + set _WORKAREASIZE 0x10000 +} + +#jtag scan chain +if { [info exists CPUTAPID] } { + set _CPUTAPID $CPUTAPID +} else { + if { [using_jtag] } { + # STM32L5x: RM0438 Rev5, Section 52.2.8 JTAG debug port - Table 425. JTAG-DP data registers + # STM32U5x: RM0456 Rev1, Section 65.2.8 JTAG debug port - Table 661. JTAG-DP data registers + # Corresponds to Cortex®-M33 JTAG debug port ID code + set _CPUTAPID 0x0ba04477 + } { + # SWD IDCODE (single drop, arm) + set _CPUTAPID 0x0be12477 + } +} + +swj_newdap $_CHIPNAME cpu -irlen 4 -ircapture 0x1 -irmask 0xf -expected-id $_CPUTAPID +dap create $_CHIPNAME.dap -chain-position $_CHIPNAME.cpu + +if {[using_jtag]} { + jtag newtap $_CHIPNAME bs -irlen 5 +} + +set _TARGETNAME $_CHIPNAME.cpu +target create $_TARGETNAME cortex_m -endian little -dap $_CHIPNAME.dap + +# use non-secure RAM by default +$_TARGETNAME configure -work-area-phys 0x20000000 -work-area-size $_WORKAREASIZE -work-area-backup 0 + +# create sec/ns flash and otp memories (sizes will be probed) +flash bank $_CHIPNAME.flash_ns stm32l4x 0x08000000 0 0 0 $_TARGETNAME +flash bank $_CHIPNAME.flash_alias_s stm32l4x 0x0C000000 0 0 0 $_TARGETNAME +flash bank $_CHIPNAME.otp stm32l4x 0x0BFA0000 0 0 0 $_TARGETNAME + +# Common knowledge tells JTAG speed should be <= F_CPU/6. +# F_CPU after reset is MSI 4MHz, so use F_JTAG = 500 kHz to stay on +# the safe side. +# +# Note that there is a pretty wide band where things are +# more or less stable, see http://review.openocd.org/3366 +adapter speed 500 + +adapter srst delay 100 +if {[using_jtag]} { + jtag_ntrst_delay 100 +} + +reset_config srst_nogate + +if {![using_hla]} { + # if srst is not fitted use SYSRESETREQ to + # perform a soft reset + cortex_m reset_config sysresetreq +} + +proc stm32x5x_is_secure {} { + # read Debug Security Control and Status Register (DSCSR) and check CDS (bit 16) + set DSCSR [mrw 0xE000EE08] + return [expr {($DSCSR & (1 << 16)) != 0}] +} + +proc stm32x5x_ahb_ap_non_secure_access {} { + # SPROT=1=Non Secure access, Priv=1 + [[target current] cget -dap] apcsw 0x4B000000 0x4F000000 +} + +proc stm32x5x_ahb_ap_secure_access {} { + # SPROT=0=Secure access, Priv=1 + [[target current] cget -dap] apcsw 0x0B000000 0x4F000000 +} + +$_TARGETNAME configure -event reset-start { + # Reset clock is MSI (4 MHz) + adapter speed 480 +} + +$_TARGETNAME configure -event examine-end { + # DBGMCU_CR |= DBG_STANDBY | DBG_STOP + mmw 0xE0044004 0x00000006 0 + + # Stop watchdog counters during halt + # DBGMCU_APB1_FZ |= DBG_IWDG_STOP | DBG_WWDG_STOP + mmw 0xE0044008 0x00001800 0 +} + +$_TARGETNAME configure -event halted { + set secure [stm32x5x_is_secure] + + if {$secure} { + set secure_str "Secure" + stm32x5x_ahb_ap_secure_access + } else { + set secure_str "Non-Secure" + stm32x5x_ahb_ap_non_secure_access + } + + # print the secure state only when it changes + set _TARGETNAME [target current] + global $_TARGETNAME.secure + + if {![info exists $_TARGETNAME.secure] || $secure != [set $_TARGETNAME.secure]} { + echo "CPU in $secure_str state" + # update saved security state + set $_TARGETNAME.secure $secure + } +} + +$_TARGETNAME configure -event gdb-flash-erase-start { + set use_secure_workarea 0 + # check if FLASH_OPTR.TZEN is enabled + set FLASH_OPTR [mrw 0x40022040] + if {[expr {$FLASH_OPTR & 0x80000000}] == 0} { + echo "TZEN option bit disabled" + stm32x5x_ahb_ap_non_secure_access + } else { + stm32x5x_ahb_ap_secure_access + echo "TZEN option bit enabled" + + # check if FLASH_OPTR.RDP is not Level 0.5 + if {[expr {$FLASH_OPTR & 0xFF}] != 0x55} { + set use_secure_workarea 1 + } + } + + set _TARGETNAME [target current] + set workarea_addr [$_TARGETNAME cget -work-area-phys] + echo "workarea_addr $workarea_addr" + + if {$use_secure_workarea} { + set workarea_addr [expr {$workarea_addr | 0x10000000}] + } else { + set workarea_addr [expr {$workarea_addr & ~0x10000000}] + } + + $_TARGETNAME configure -work-area-phys $workarea_addr +} + +$_TARGETNAME configure -event trace-config { + # Set TRACE_IOEN; TRACE_MODE is set to async; when using sync + # change this value accordingly to configure trace pins + # assignment + mmw 0xE0044004 0x00000020 0 +} diff --git a/tcl/target/ti_cc3220sf.cfg b/tcl/target/ti_cc3220sf.cfg index 74269aa66..c0a7b568d 100644 --- a/tcl/target/ti_cc3220sf.cfg +++ b/tcl/target/ti_cc3220sf.cfg @@ -26,11 +26,11 @@ proc ocd_process_reset_inner { MODE } { soft_reset_halt # Initialize MSP, PSP, and PC from vector table at flash 0x01000800 - mem2array boot 32 0x01000800 2 + set boot [read_memory 0x01000800 32 2] - reg msp $boot(0) - reg psp $boot(0) - reg pc $boot(1) + reg msp [lindex $boot 0] + reg psp [lindex $boot 0] + reg pc [lindex $boot 1] if { 0 == [string compare $MODE run ] } { resume diff --git a/tcl/target/ti_k3.cfg b/tcl/target/ti_k3.cfg index d2aa53160..254bb6971 100644 --- a/tcl/target/ti_k3.cfg +++ b/tcl/target/ti_k3.cfg @@ -27,11 +27,11 @@ if { [info exists V8_SMP_DEBUG] } { # Common Definitions -# CM3 the very first processor - all current SoCs have it. +# System Controller is the very first processor - all current SoCs have it. set CM3_CTIBASE {0x3C016000} -# M3 power-ap unlock offsets -set _m3_ap_unlock_offsets {0xf0 0x44} +# sysctrl power-ap unlock offsets +set _sysctrl_ap_unlock_offsets {0xf0 0x44} # All the ARMV8s are the next processors. # CL0,CORE0 CL0,CORE1 CL1,CORE0 CL1,CORE1 @@ -42,14 +42,15 @@ set ARMV8_CTIBASE {0x90420000 0x90520000 0x90820000 0x90920000} # (0)MCU 0 (1)MCU 1 (2)MAIN_0_0 (3)MAIN_0_1 (4)MAIN_1_0 (5)MAIN_1_1 set R5_DBGBASE {0x9d010000 0x9d012000 0x9d410000 0x9d412000 0x9d510000 0x9d512000} set R5_CTIBASE {0x9d018000 0x9d019000 0x9d418000 0x9d419000 0x9d518000 0x9d519000} +set R5_NAMES {mcu_r5.0 mcu_r5.1 main0_r5.0 main0_r5.1 main1_r5.0 main1_r5.1} -# Finally an M4F +# Finally an General Purpose(GP) MCU set CM4_CTIBASE {0x20001000} -# M4 may be present on some very few SoCs -set _mcu_m4_cores 0 -# M4 power-ap unlock offsets -set _m4_ap_unlock_offsets {0xf0 0x60} +# General Purpose MCU (M4) may be present on some very few SoCs +set _gp_mcu_cores 0 +# General Purpose MCU power-ap unlock offsets +set _gp_mcu_ap_unlock_offsets {0xf0 0x60} # Set configuration overrides for each SOC switch $_soc { @@ -63,15 +64,10 @@ switch $_soc { # AM654 has 1 cluster of 2 R5s cores. set _r5_cores 2 - set _mcu_r5_cores 2 - set _mcu_base_core_id 0 - set _main0_r5_cores 0 - set _main0_base_core_id 0 - set _main1_r5_cores 0 - set _main1_base_core_id 0 + set R5_NAMES {mcu_r5.0 mcu_r5.1} - # M3 power-ap unlock offsets - set _m3_ap_unlock_offsets {0xf0 0x50} + # Sysctrl power-ap unlock offsets + set _sysctrl_ap_unlock_offsets {0xf0 0x50} } am642 { set _CHIPNAME am642 @@ -85,17 +81,37 @@ switch $_soc { # AM642 has 2 cluster of 2 R5s cores. set _r5_cores 4 - set _mcu_r5_cores 0 - set _mcu_base_core_id 0 - set _main0_r5_cores 2 - set _main0_base_core_id 0 - set _main1_r5_cores 2 - set _main1_base_core_id 2 + set R5_NAMES {main0_r5.0 main0_r5.1 main1_r5.0 main1_r5.1} set R5_DBGBASE {0x9d410000 0x9d412000 0x9d510000 0x9d512000} set R5_CTIBASE {0x9d418000 0x9d419000 0x9d518000 0x9d519000} # M4 processor - set _mcu_m4_cores 1 + set _gp_mcu_cores 1 + } + am625 { + set _CHIPNAME am625 + set _K3_DAP_TAPID 0x0bb7e02f + + # AM625 has 1 clusters of 4 A53 cores. + set _armv8_cpu_name a53 + set _armv8_cores 4 + set ARMV8_DBGBASE {0x90010000 0x90110000 0x90210000 0x90310000} + set ARMV8_CTIBASE {0x90020000 0x90120000 0x90220000 0x90320000} + + # AM625 has 1 cluster of 1 R5s core. + set _r5_cores 1 + set R5_NAMES {main0_r5.0} + set R5_DBGBASE {0x9d410000} + set R5_CTIBASE {0x9d418000} + + # sysctrl CTI base + set CM3_CTIBASE {0x20001000} + # Sysctrl power-ap unlock offsets + set _sysctrl_ap_unlock_offsets {0xf0 0x78} + + # M4 processor + set _gp_mcu_cores 1 + set _gp_mcu_ap_unlock_offsets {0xf0 0x7c} } j721e { set _CHIPNAME j721e @@ -106,12 +122,6 @@ switch $_soc { # J721E has 3 clusters of 2 R5 cores each. set _r5_cores 6 - set _mcu_r5_cores 2 - set _mcu_base_core_id 0 - set _main0_r5_cores 2 - set _main0_base_core_id 2 - set _main1_r5_cores 2 - set _main1_base_core_id 4 } j7200 { set _CHIPNAME j7200 @@ -123,18 +133,32 @@ switch $_soc { # J7200 has 2 clusters of 2 R5 cores each. set _r5_cores 4 - set _mcu_r5_cores 2 - set _mcu_base_core_id 0 - set _main0_r5_cores 2 - set _main0_base_core_id 2 - set _main1_r5_cores 0 - set _main1_base_core_id 0 set R5_DBGBASE {0x9d010000 0x9d012000 0x9d110000 0x9d112000} set R5_CTIBASE {0x9d018000 0x9d019000 0x9d118000 0x9d119000} # M3 CTI base set CM3_CTIBASE {0x20001000} } + j721s2 { + set _CHIPNAME j721s2 + set _K3_DAP_TAPID 0x0bb7502f + + # J721s2 has 1 cluster of 2 A72 cores. + set _armv8_cpu_name a72 + set _armv8_cores 2 + + # J721s2 has 3 clusters of 2 R5 cores each. + set _r5_cores 6 + + # sysctrl CTI base + set CM3_CTIBASE {0x20001000} + # Sysctrl power-ap unlock offsets + set _sysctrl_ap_unlock_offsets {0xf0 0x78} + + # M4 processor + set _gp_mcu_cores 1 + set _gp_mcu_ap_unlock_offsets {0xf0 0x7c} + } default { echo "'$_soc' is invalid!" } @@ -147,18 +171,42 @@ set _TARGETNAME $_CHIPNAME.cpu set _CTINAME $_CHIPNAME.cti -# M3 is always present -cti create $_CTINAME.m3 -dap $_CHIPNAME.dap -ap-num 7 -baseaddr [lindex $CM3_CTIBASE 0] -target create $_TARGETNAME.m3 cortex_m -dap $_CHIPNAME.dap -ap-num 7 -defer-examine -$_TARGETNAME.m3 configure -event reset-assert { } +# sysctrl is always present +cti create $_CTINAME.sysctrl -dap $_CHIPNAME.dap -ap-num 7 -baseaddr [lindex $CM3_CTIBASE 0] +target create $_TARGETNAME.sysctrl cortex_m -dap $_CHIPNAME.dap -ap-num 7 -defer-examine +$_TARGETNAME.sysctrl configure -event reset-assert { } -proc m3_up { args } { - # To access M3, we need to enable the JTAG access for the same. +proc sysctrl_up {} { + # To access sysctrl, we need to enable the JTAG access for the same. # Ensure Power-AP unlocked - $::_CHIPNAME.dap apreg 3 [lindex $::_m3_ap_unlock_offsets 0] 0x00190000 - $::_CHIPNAME.dap apreg 3 [lindex $::_m3_ap_unlock_offsets 1] 0x00102098 + $::_CHIPNAME.dap apreg 3 [lindex $::_sysctrl_ap_unlock_offsets 0] 0x00190000 + $::_CHIPNAME.dap apreg 3 [lindex $::_sysctrl_ap_unlock_offsets 1] 0x00102098 - $::_TARGETNAME.m3 arp_examine + $::_TARGETNAME.sysctrl arp_examine +} + +$_TARGETNAME.sysctrl configure -event gdb-attach { + sysctrl_up + # gdb-attach default rule + halt 1000 +} + +proc _cpu_no_smp_up {} { + set _current_target [target current] + set _current_type [$_current_target cget -type] + + $_current_target arp_examine + $_current_target $_current_type dbginit +} + +proc _armv8_smp_up {} { + for { set _core 0 } { $_core < $::_armv8_cores } { incr _core } { + $::_TARGETNAME.$::_armv8_cpu_name.$_core arp_examine + $::_TARGETNAME.$::_armv8_cpu_name.$_core aarch64 dbginit + $::_TARGETNAME.$::_armv8_cpu_name.$_core aarch64 smp on + } + # Set Default target as core 0 + targets $::_TARGETNAME.$::_armv8_cpu_name.0 } set _v8_smp_targets "" @@ -172,6 +220,20 @@ for { set _core 0 } { $_core < $_armv8_cores } { incr _core } { -dbgbase [lindex $ARMV8_DBGBASE $_core] -cti $_CTINAME.$_armv8_cpu_name.$_core -defer-examine set _v8_smp_targets "$_v8_smp_targets $_TARGETNAME.$_armv8_cpu_name.$_core" + + if { $_v8_smp_debug == 0 } { + $_TARGETNAME.$_armv8_cpu_name.$_core configure -event gdb-attach { + _cpu_no_smp_up + # gdb-attach default rule + halt 1000 + } + } else { + $_TARGETNAME.$_armv8_cpu_name.$_core configure -event gdb-attach { + _armv8_smp_up + # gdb-attach default rule + halt 1000 + } + } } # Setup ARMV8 proc commands based on CPU to prevent people confusing SoCs @@ -181,76 +243,59 @@ set _armv8_smp_cmd "$_armv8_cpu_name"_smp if { $_v8_smp_debug == 0 } { proc $_armv8_up_cmd { args } { - foreach { _core } [set args] { - $::_TARGETNAME.$::_armv8_cpu_name.$_core arp_examine - $::_TARGETNAME.$::_armv8_cpu_name.$_core aarch64 dbginit + foreach _core $args { + targets $_core + _cpu_no_smp_up } } } else { proc $_armv8_smp_cmd { args } { - for { set _core 0 } { $_core < $::_armv8_cores } { incr _core } { - $::_TARGETNAME.$::_armv8_cpu_name.$_core arp_examine - $::_TARGETNAME.$::_armv8_cpu_name.$_core aarch64 dbginit - $::_TARGETNAME.$::_armv8_cpu_name.$_core aarch64 smp on - } - # Set Default target are core 0 - targets $::_TARGETNAME.$::_armv8_cpu_name.0 + _armv8_smp_up } - # Declare SMP target smp $:::_v8_smp_targets } for { set _core 0 } { $_core < $_r5_cores } { incr _core } { - cti create $_CTINAME.r5.$_core -dap $_CHIPNAME.dap -ap-num 1 \ + set _r5_name [lindex $R5_NAMES $_core] + cti create $_CTINAME.$_r5_name -dap $_CHIPNAME.dap -ap-num 1 \ -baseaddr [lindex $R5_CTIBASE $_core] # inactive core examination will fail - wait till startup of additional core - target create $_TARGETNAME.r5.$_core cortex_r4 -dap $_CHIPNAME.dap \ + target create $_TARGETNAME.$_r5_name cortex_r4 -dap $_CHIPNAME.dap \ -dbgbase [lindex $R5_DBGBASE $_core] -ap-num 1 -defer-examine -} -if { $_mcu_r5_cores != 0 } { - proc mcu_r5_up { args } { - foreach { _core } [set args] { - set _core [expr {$_core + $::_mcu_base_core_id}] - $::_TARGETNAME.r5.$_core arp_examine - $::_TARGETNAME.r5.$_core cortex_r4 dbginit - } + $_TARGETNAME.$_r5_name configure -event gdb-attach { + _cpu_no_smp_up + # gdb-attach default rule + halt 1000 } } -if { $_main0_r5_cores != 0 } { - proc main0_r5_up { args } { - foreach { _core } [set args] { - set _core [expr {$_core + $::_main0_base_core_id}] - $::_TARGETNAME.r5.$_core arp_examine - $::_TARGETNAME.r5.$_core cortex_r4 dbginit - } +proc r5_up { args } { + foreach _core $args { + targets $_core + _cpu_no_smp_up } } -if { $_main1_r5_cores != 0 } { - proc main1_r5_up { args } { - foreach { _core } [set args] { - set _core [expr {$_core + $::_main1_base_core_id}] - $::_TARGETNAME.r5.$_core arp_examine - $::_TARGETNAME.r5.$_core cortex_r4 dbginit - } - } -} +if { $_gp_mcu_cores != 0 } { + cti create $_CTINAME.gp_mcu -dap $_CHIPNAME.dap -ap-num 8 -baseaddr [lindex $CM4_CTIBASE 0] + target create $_TARGETNAME.gp_mcu cortex_m -dap $_CHIPNAME.dap -ap-num 8 -defer-examine + $_TARGETNAME.gp_mcu configure -event reset-assert { } -if { $_mcu_m4_cores != 0 } { - cti create $_CTINAME.m4 -dap $_CHIPNAME.dap -ap-num 8 -baseaddr [lindex $CM4_CTIBASE 0] - target create $_TARGETNAME.m4 cortex_m -dap $_CHIPNAME.dap -ap-num 8 -defer-examine - $_TARGETNAME.m4 configure -event reset-assert { } - - proc m4_up { args } { - # To access M4, we need to enable the JTAG access for the same. + proc gp_mcu_up {} { + # To access GP MCU, we need to enable the JTAG access for the same. # Ensure Power-AP unlocked - $::_CHIPNAME.dap apreg 3 [lindex $::_m4_ap_unlock_offsets 0] 0x00190000 - $::_CHIPNAME.dap apreg 3 [lindex $::_m4_ap_unlock_offsets 1] 0x00102098 + $::_CHIPNAME.dap apreg 3 [lindex $::_gp_mcu_ap_unlock_offsets 0] 0x00190000 + $::_CHIPNAME.dap apreg 3 [lindex $::_gp_mcu_ap_unlock_offsets 1] 0x00102098 - $::_TARGETNAME.m4 arp_examine + $::_TARGETNAME.gp_mcu arp_examine + } + + $_TARGETNAME.gp_mcu configure -event gdb-attach { + gp_mcu_up + # gdb-attach default rule + halt 1000 } } diff --git a/tcl/target/xilinx_zynqmp.cfg b/tcl/target/xilinx_zynqmp.cfg index e66289a70..2df7a4ff9 100644 --- a/tcl/target/xilinx_zynqmp.cfg +++ b/tcl/target/xilinx_zynqmp.cfg @@ -99,7 +99,7 @@ targets $_TARGETNAME.0 proc core_up { args } { global _TARGETNAME - foreach { core } [set args] { + foreach core $args { $_TARGETNAME.$core arp_examine } } diff --git a/tcl/tools/test_cpu_speed.tcl b/tcl/tools/test_cpu_speed.tcl new file mode 100644 index 000000000..cef2bbbd7 --- /dev/null +++ b/tcl/tools/test_cpu_speed.tcl @@ -0,0 +1,50 @@ +# SPDX-License-Identifier: GPL-2.0-or-later + +# Description: +# Measure the CPU clock frequency of an ARM Cortex-M based device. +# +# Return: +# The CPU clock frequency in Hz. A negative value indicates that the loop +# counter was saturated. +# +# Note: +# You may need to adapt the number of cycles for your device. +# +add_help_text cortex_m_test_cpu_speed "Measure the CPU clock frequency of an ARM Cortex-M based device" +add_usage_text cortex_m_test_cpu_speed {address [timeout [cycles_per_loop]]} +proc cortex_m_test_cpu_speed { address { timeout 200 } { cycles_per_loop 4 } } { + set loop_counter_start 0xffffffff + + halt + + # Backup registers and memory. + set backup_regs [get_reg -force {pc r0 xPSR}] + set backup_mem [read_memory $address 16 3] + + # We place the following code at the given address to measure the + # CPU clock frequency: + # + # 3801: subs r0, #1 + # d1fd: bne #-2 + # e7fe: b #-4 + write_memory $address 16 {0x3801 0xd1fd 0xe7fe} + + set_reg "pc $address r0 $loop_counter_start" + resume + sleep $timeout + halt + + # Get the loop counter value from register r0. + set loop_counter_end [dict values [get_reg r0]] + set loop_counter_diff [expr {$loop_counter_start - $loop_counter_end}] + + # Restore registers and memory. + set_reg $backup_regs + write_memory $address 16 $backup_mem + + if { [expr {$loop_counter_end == 0}] } { + return -1 + } + + return [expr {double($loop_counter_diff) * $cycles_per_loop / $timeout * 1000}] +} diff --git a/testing/examples/cortex/cm3-ftest.cfg b/testing/examples/cortex/cm3-ftest.cfg index 6f3fa5c81..02c8da11a 100644 --- a/testing/examples/cortex/cm3-ftest.cfg +++ b/testing/examples/cortex/cm3-ftest.cfg @@ -50,7 +50,7 @@ proc load_and_run { name halfwords n_instr } { echo "# code to trigger $name vector" set addr 0x20000000 - # array2mem should be faster, though we'd need to + # write_memory should be faster, though we'd need to # compute the resulting $addr ourselves foreach opcode $halfwords { mwh $addr $opcode