Merge branch 'master' into from_upstream

Conflicts:
	src/server/server.c
	src/target/breakpoints.c
	src/target/semihosting_common.c
	src/target/target.c

Change-Id: I48bd3608c688c69d8aac0667fc46e2de5466a9f1
This commit is contained in:
Tim Newsome 2022-04-11 11:13:20 -07:00
commit 00d7c7994a
89 changed files with 2352 additions and 1175 deletions

View File

@ -7,6 +7,6 @@ AC_DEFUN([AX_CONFIG_SUBDIR_OPTION],
AC_CONFIG_SUBDIRS([$1]) AC_CONFIG_SUBDIRS([$1])
m4_ifblank([$2], [rm -f $srcdir/$1/configure.gnu], 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"
]) ])
]) ])

View File

@ -355,6 +355,10 @@ AC_ARG_ENABLE([internal-jimtcl],
AS_HELP_STRING([--disable-internal-jimtcl], [Disable building internal jimtcl]), AS_HELP_STRING([--disable-internal-jimtcl], [Disable building internal jimtcl]),
[use_internal_jimtcl=$enableval], [use_internal_jimtcl=yes]) [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], AC_ARG_ENABLE([internal-libjaylink],
AS_HELP_STRING([--disable-internal-libjaylink], AS_HELP_STRING([--disable-internal-libjaylink],
[Disable building 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 "x$use_internal_jimtcl" = "xyes"], [
AS_IF([test -f "$srcdir/jimtcl/configure.ac"], [ 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.]) AC_MSG_ERROR([jimtcl not found, run git submodule init and git submodule update.])
]) ])

View File

@ -95,24 +95,16 @@ class OpenOcd:
return None if (len(raw) < 2) else strToHex(raw[1]) return None if (len(raw) < 2) else strToHex(raw[1])
def readMemory(self, wordLen, address, n): def readMemory(self, wordLen, address, n):
self.send("array unset output") # better to clear the array before output = self.send("read_memory 0x%x %d %d" % (address, wordLen, n))
self.send("mem2array output %d 0x%x %d" % (wordLen, address, n)) return [*map(lambda x: int(x, 16), output.split(" "))]
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())]
def writeVariable(self, address, value): def writeVariable(self, address, value):
assert value is not None assert value is not None
self.send("mww 0x%x 0x%x" % (address, value)) self.send("mww 0x%x 0x%x" % (address, value))
def writeMemory(self, wordLen, address, n, data): def writeMemory(self, wordLen, address, data):
array = " ".join(["%d 0x%x" % (a, b) for a, b in enumerate(data)]) data = "{" + ' '.join(['0x%x' % x for x in data]) + "}"
self.send("write_memory 0x%x %d %s" % (address, wordLen, data))
self.send("array unset 1986ве") # better to clear the array before
self.send("array set 1986ве{ %s }" % array)
self.send("array2mem 1986ве1т 0x%x %s %d" % (wordLen, address, n))
if __name__ == "__main__": if __name__ == "__main__":

View File

@ -4980,27 +4980,76 @@ use these to deal with specific reset cases.
They are not otherwise documented here. They are not otherwise documented here.
@end deffn @end deffn
@deffn {Command} {$target_name array2mem} arrayname width address count @deffn {Command} {$target_name set_reg} dict
@deffnx {Command} {$target_name mem2array} arrayname width address count Set register values of the target.
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.
@itemize @itemize
@item @var{arrayname} ... is the name of an array variable @item @var{dict} ... Tcl dictionary with pairs of register names and values.
@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
@end itemize @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 @end deffn
@deffn {Command} {$target_name cget} queryparm @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, Otherwise, or if the optional @var{phys} flag is specified,
@var{addr} is interpreted as a physical address. @var{addr} is interpreted as a physical address.
If @var{count} is specified, displays that many units. If @var{count} is specified, displays that many units.
(If you want to manipulate the data instead of displaying it, (If you want to process the data instead of displaying it,
see the @code{mem2array} primitives.) see the @code{read_memory} primitives.)
@end deffn @end deffn
@deffn {Command} {$target_name mwd} [phys] addr doubleword [count] @deffn {Command} {$target_name mwd} [phys] addr doubleword [count]
@ -8491,6 +8540,78 @@ Debug and trace infrastructure:
@end example @end example
@end deffn @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] @deffn {Command} {halt} [ms]
@deffnx {Command} {wait_halt} [ms] @deffnx {Command} {wait_halt} [ms]
The @command{halt} command first sends a halt request to the target, 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, Otherwise, or if the optional @var{phys} flag is specified,
@var{addr} is interpreted as a physical address. @var{addr} is interpreted as a physical address.
If @var{count} is specified, displays that many units. If @var{count} is specified, displays that many units.
(If you want to manipulate the data instead of displaying it, (If you want to process the data instead of displaying it,
see the @code{mem2array} primitives.) see the @code{read_memory} primitives.)
@end deffn @end deffn
@deffn {Command} {mwd} [phys] addr doubleword [count] @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. Supervisor Call vector by OpenOCD.
@end deffn @end deffn
@deffn {Command} {arm semihosting_redirect} (@option{disable} | @option{tcp} <port>
[@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}] @deffn {Command} {arm semihosting_cmdline} [@option{enable}|@option{disable}]
@cindex ARM semihosting @cindex ARM semihosting
Set the command line to be passed to the debugger. 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 By "low-level", we mean commands that a human would typically not
invoke directly. invoke directly.
@itemize @bullet @itemize
@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
@item @b{flash banks} <@var{driver}> <@var{base}> <@var{size}> <@var{chip_width}> <@var{bus_width}> <@var{target}> [@option{driver options} ...] @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 Return information about the flash banks

View File

@ -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) static int efm32x_read_info(struct flash_bank *bank)
{ {
int ret; int ret;
uint32_t cpuid = 0;
struct efm32x_flash_chip *efm32x_info = bank->driver_priv; struct efm32x_flash_chip *efm32x_info = bank->driver_priv;
struct efm32_info *efm32_info = &(efm32x_info->info); struct efm32_info *efm32_info = &(efm32x_info->info);
memset(efm32_info, 0, sizeof(struct efm32_info)); memset(efm32_info, 0, sizeof(struct efm32_info));
ret = target_read_u32(bank->target, CPUID, &cpuid); const struct cortex_m_common *cortex_m = target_to_cm(bank->target);
if (ret != ERROR_OK)
return ret;
if (((cpuid >> 4) & 0xfff) == 0xc23) { switch (cortex_m->core_info->partno) {
/* Cortex-M3 device */ case CORTEX_M3_PARTNO:
} else if (((cpuid >> 4) & 0xfff) == 0xc24) { case CORTEX_M4_PARTNO:
/* Cortex-M4 device (WONDER GECKO) */ case CORTEX_M0P_PARTNO:
} else if (((cpuid >> 4) & 0xfff) == 0xc60) { break;
/* Cortex-M0+ device */ default:
} else {
LOG_ERROR("Target is not Cortex-Mx Device"); LOG_ERROR("Target is not Cortex-Mx Device");
return ERROR_FAIL; return ERROR_FAIL;
} }

View File

@ -983,7 +983,7 @@ COMMAND_HANDLER(sim3x_lock)
if (!dap) { if (!dap) {
/* Used debug interface doesn't support direct DAP access */ /* 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 */ /* Core check */
ret = target_read_u32(target, CPUID, &val); ret = target_read_u32(target, CPUID, &val);

View File

@ -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"); LOG_WARNING("couldn't use block writes, falling back to single memory accesses");
while (words_remaining > 0) { while (words_remaining > 0) {
uint16_t value; retval = target_write_memory(target, bank->base + offset, 2, 1, buffer);
memcpy(&value, buffer, sizeof(uint16_t));
retval = target_write_u16(target, bank->base + offset, value);
if (retval != ERROR_OK) if (retval != ERROR_OK)
goto reset_pg_and_lock; goto reset_pg_and_lock;

View File

@ -856,15 +856,12 @@ static int stm32x_write(struct flash_bank *bank, const uint8_t *buffer,
Wait for the BSY bit to be cleared Wait for the BSY bit to be cleared
*/ */
while (words_remaining > 0) { 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), retval = target_write_u32(target, stm32x_get_flash_reg(bank, STM32_FLASH_CR),
FLASH_PG | FLASH_PSIZE_16); FLASH_PG | FLASH_PSIZE_16);
if (retval != ERROR_OK) if (retval != ERROR_OK)
return retval; return retval;
retval = target_write_u16(target, address, value); retval = target_write_memory(target, address, 2, 1, buffer + bytes_written);
if (retval != ERROR_OK) if (retval != ERROR_OK)
return retval; return retval;

View File

@ -531,6 +531,7 @@ static int stm32x_protect(struct flash_bank *bank, int set, unsigned int first,
unsigned int last) unsigned int last)
{ {
struct target *target = bank->target; struct target *target = bank->target;
struct stm32h7x_flash_bank *stm32x_info = bank->driver_priv;
uint32_t protection; uint32_t protection;
if (target->state != TARGET_HALTED) { 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 */ /* apply WRPSN mask */
protection &= 0xff; protection &= stm32x_info->part_info->wps_mask;
LOG_DEBUG("stm32x_protect, option_bytes written WPSN 0x%" PRIx32, protection); LOG_DEBUG("stm32x_protect, option_bytes written WPSN 0x%" PRIx32, protection);

View File

@ -1757,7 +1757,7 @@ static int stm32l4_probe(struct flash_bank *bank)
* Ask the flash infrastructure to ensure required alignment */ * Ask the flash infrastructure to ensure required alignment */
bank->write_start_alignment = bank->write_end_alignment = stm32l4_info->data_width; 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) if (part_info->flags & F_HAS_L5_FLASH_REGS)
stm32l4_info->flash_regs = stm32l5_ns_flash_regs; stm32l4_info->flash_regs = stm32l5_ns_flash_regs;
else else
@ -1770,7 +1770,7 @@ static int stm32l4_probe(struct flash_bank *bank)
stm32l4_sync_rdp_tzen(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 (stm32l4_info->tzen && (stm32l4_info->rdp == RDP_LEVEL_0)) {
if (part_info->flags & F_HAS_L5_FLASH_REGS) { if (part_info->flags & F_HAS_L5_FLASH_REGS) {
stm32l4_info->flash_regs_base |= STM32L5_REGS_SEC_OFFSET; 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) { if (stm32l4_info->probed) {
uint32_t optr_cur; 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 */ /* 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); 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) if (retval != ERROR_OK)
return retval; return retval;

View File

@ -28,8 +28,12 @@
#include <helper/types.h> #include <helper/types.h>
#define BIT(nr) (1UL << (nr)) #define BIT(nr) (1UL << (nr))
#define BIT_ULL(nr) (1ULL << (nr))
#define BITS_PER_BYTE 8 #define BITS_PER_BYTE 8
#define BITS_PER_LONG (BITS_PER_BYTE * sizeof(long)) #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 BITS_TO_LONGS(nr) DIV_ROUND_UP(nr, BITS_PER_BYTE * sizeof(long))
#define BIT_MASK(nr) (1UL << ((nr) % BITS_PER_LONG)) #define BIT_MASK(nr) (1UL << ((nr) % BITS_PER_LONG))
#define BIT_WORD(nr) ((nr) / BITS_PER_LONG) #define BIT_WORD(nr) ((nr) / BITS_PER_LONG)

View File

@ -41,6 +41,10 @@
* official policies, either expressed or implied, of the Jim Tcl Project. * official policies, either expressed or implied, of the Jim Tcl Project.
*/ */
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "jim-nvp.h" #include "jim-nvp.h"
#include <string.h> #include <string.h>

View File

@ -30,6 +30,7 @@
#include "command.h" #include "command.h"
#include "replacements.h" #include "replacements.h"
#include "time_support.h" #include "time_support.h"
#include <server/server.h>
#include <stdarg.h> #include <stdarg.h>
@ -47,7 +48,6 @@ static FILE *log_output;
static struct log_callback *log_callbacks; static struct log_callback *log_callbacks;
static int64_t last_time; static int64_t last_time;
static int64_t current_time;
static int64_t start; static int64_t start;
@ -111,7 +111,6 @@ static void log_puts(enum log_levels level,
if (f) if (f)
file = f + 1; file = f + 1;
if (strlen(string) > 0) {
if (debug_level >= LOG_LVL_DEBUG) { if (debug_level >= LOG_LVL_DEBUG) {
/* print with count and time information */ /* print with count and time information */
int64_t t = timeval_ms() - start; int64_t t = timeval_ms() - start;
@ -134,10 +133,6 @@ static void log_puts(enum log_levels level,
fprintf(log_output, "%s%s", fprintf(log_output, "%s%s",
(level > LOG_LVL_USER) ? log_strings[level + 1] : "", string); (level > LOG_LVL_USER) ? log_strings[level + 1] : "", string);
} }
} else {
/* Empty strings are sent to log callbacks to keep e.g. gdbserver alive, here we do
*nothing. */
}
fflush(log_output); fflush(log_output);
@ -440,8 +435,7 @@ static void gdb_timeout_warning(int64_t delta_time)
void keep_alive(void) void keep_alive(void)
{ {
current_time = timeval_ms(); int64_t current_time = timeval_ms();
int64_t delta_time = current_time - last_time; int64_t delta_time = current_time - last_time;
if (delta_time > KEEP_ALIVE_TIMEOUT_MS) { if (delta_time > KEEP_ALIVE_TIMEOUT_MS) {
@ -454,7 +448,7 @@ void keep_alive(void)
last_time = current_time; last_time = current_time;
/* this will keep the GDB connection alive */ /* 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, /* DANGER!!!! do not add code to invoke e.g. target event processing,
* jim timer processing, etc. it can cause infinite recursion + * jim timer processing, etc. it can cause infinite recursion +
@ -469,7 +463,7 @@ void keep_alive(void)
/* reset keep alive timer without sending message */ /* reset keep alive timer without sending message */
void kept_alive(void) void kept_alive(void)
{ {
current_time = timeval_ms(); int64_t current_time = timeval_ms();
int64_t delta_time = current_time - last_time; int64_t delta_time = current_time - last_time;

View File

@ -48,6 +48,7 @@
#include <target/cortex_m.h> #include <target/cortex_m.h>
#include "cmsis_dap.h" #include "cmsis_dap.h"
#include "libusb_helper.h"
static const struct cmsis_dap_backend *const cmsis_dap_backends[] = { static const struct cmsis_dap_backend *const cmsis_dap_backends[] = {
#if BUILD_CMSIS_DAP_USB == 1 #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 int cmsis_dap_backend = -1;
static bool swd_mode; static bool swd_mode;
#define USB_TIMEOUT 1000
/* CMSIS-DAP General Commands */ /* CMSIS-DAP General Commands */
#define CMD_DAP_INFO 0x00 #define CMD_DAP_INFO 0x00
#define CMD_DAP_LED 0x01 #define CMD_DAP_LED 0x01
@ -360,12 +359,12 @@ static int cmsis_dap_xfer(struct cmsis_dap *dap, int txlen)
} }
uint8_t current_cmd = cmsis_dap_handle->command[0]; 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) if (retval < 0)
return retval; return retval;
/* get reply */ /* get reply */
retval = dap->backend->read(dap, USB_TIMEOUT); retval = dap->backend->read(dap, LIBUSB_TIMEOUT_MS);
if (retval < 0) if (retval < 0)
return retval; 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) { if (retval < 0) {
queued_retval = retval; queued_retval = retval;
goto skip; goto skip;
@ -854,7 +853,7 @@ static void cmsis_dap_swd_read_process(struct cmsis_dap *dap, int timeout_ms)
/* get reply */ /* get reply */
int retval = dap->backend->read(dap, timeout_ms); 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; return;
if (retval <= 0) { if (retval <= 0) {
@ -929,7 +928,7 @@ static int cmsis_dap_swd_run_queue(void)
cmsis_dap_swd_write_from_queue(cmsis_dap_handle); cmsis_dap_swd_write_from_queue(cmsis_dap_handle);
while (pending_fifo_block_count) 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_put_idx = 0;
pending_fifo_get_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); cmsis_dap_swd_write_from_queue(cmsis_dap_handle);
if (pending_fifo_block_count >= cmsis_dap_handle->packet_count) 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) if (queued_retval != ERROR_OK)

View File

@ -38,8 +38,8 @@
#define NO_TAP_SHIFT 0 #define NO_TAP_SHIFT 0
#define TAP_SHIFT 1 #define TAP_SHIFT 1
#define SERVER_ADDRESS "127.0.0.1" #define DEFAULT_SERVER_ADDRESS "127.0.0.1"
#define SERVER_PORT 5555 #define DEFAULT_SERVER_PORT 5555
#define XFERT_MAX_SIZE 512 #define XFERT_MAX_SIZE 512
@ -50,7 +50,7 @@
#define CMD_STOP_SIMU 4 #define CMD_STOP_SIMU 4
/* jtag_vpi server port and address to connect to */ /* 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; static char *server_address;
/* Send CMD_STOP_SIMU to server when OpenOCD exits? */ /* 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); serv_addr.sin_port = htons(server_port);
if (!server_address) if (!server_address)
server_address = strdup(SERVER_ADDRESS); server_address = strdup(DEFAULT_SERVER_ADDRESS);
serv_addr.sin_addr.s_addr = inet_addr(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) COMMAND_HANDLER(jtag_vpi_set_port)
{ {
if (CMD_ARGC == 0) if (CMD_ARGC == 0) {
LOG_WARNING("You need to set a port number"); LOG_ERROR("Command \"jtag_vpi set_port\" expects 1 argument (TCP port number)");
else return ERROR_COMMAND_SYNTAX_ERROR;
COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], server_port); }
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; return ERROR_OK;
} }
COMMAND_HANDLER(jtag_vpi_set_address) COMMAND_HANDLER(jtag_vpi_set_address)
{ {
free(server_address);
if (CMD_ARGC == 0) { if (CMD_ARGC == 0) {
LOG_WARNING("You need to set an address"); LOG_ERROR("Command \"jtag_vpi set_address\" expects 1 argument (IP address)");
server_address = strdup(SERVER_ADDRESS); return ERROR_COMMAND_SYNTAX_ERROR;
} else }
server_address = strdup(CMD_ARGV[0]);
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; return ERROR_OK;
} }
@ -632,11 +633,11 @@ COMMAND_HANDLER(jtag_vpi_set_address)
COMMAND_HANDLER(jtag_vpi_stop_sim_on_exit_handler) COMMAND_HANDLER(jtag_vpi_stop_sim_on_exit_handler)
{ {
if (CMD_ARGC != 1) { 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; 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; return ERROR_OK;
} }
@ -645,14 +646,14 @@ static const struct command_registration jtag_vpi_subcommand_handlers[] = {
.name = "set_port", .name = "set_port",
.handler = &jtag_vpi_set_port, .handler = &jtag_vpi_set_port,
.mode = COMMAND_CONFIG, .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", .usage = "tcp_port_num",
}, },
{ {
.name = "set_address", .name = "set_address",
.handler = &jtag_vpi_set_address, .handler = &jtag_vpi_set_address,
.mode = COMMAND_CONFIG, .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", .usage = "ipv4_addr",
}, },
{ {

View File

@ -22,6 +22,20 @@
#include <libusb.h> #include <libusb.h>
/* 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 /* this callback should return a non NULL value only when the serial could not
* be retrieved by the standard 'libusb_get_string_descriptor_ascii' */ * be retrieved by the standard 'libusb_get_string_descriptor_ascii' */
typedef char * (*adapter_get_alternate_serial_fn)(struct libusb_device_handle *device, typedef char * (*adapter_get_alternate_serial_fn)(struct libusb_device_handle *device,

View File

@ -33,7 +33,9 @@
#include <hidapi.h> #include <hidapi.h>
#define NULINK_READ_TIMEOUT 1000 #include "libusb_helper.h"
#define NULINK_READ_TIMEOUT LIBUSB_TIMEOUT_MS
#define NULINK_HID_MAX_SIZE (64) #define NULINK_HID_MAX_SIZE (64)
#define NULINK2_HID_MAX_SIZE (1024) #define NULINK2_HID_MAX_SIZE (1024)

View File

@ -59,8 +59,6 @@
#define USB_EP2IN_SIZE (USB_EP2OUT_SIZE) #define USB_EP2IN_SIZE (USB_EP2OUT_SIZE)
#define USB_EP2BANK_SIZE (512) #define USB_EP2BANK_SIZE (512)
#define USB_TIMEOUT_MS (3 * 1000)
#define DTC_STATUS_POLL_BYTE (ST7_USB_BUF_EP0OUT + 0xff) #define DTC_STATUS_POLL_BYTE (ST7_USB_BUF_EP0OUT + 0xff)
#define ST7_PD_NBUSY_LED ST7_PD0 #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, hdev_param,
USB_EP1OUT_ADDR, USB_EP1OUT_ADDR,
(char *)usb_buffer, sizeof(usb_buffer), (char *)usb_buffer, sizeof(usb_buffer),
USB_TIMEOUT_MS, LIBUSB_TIMEOUT_MS,
&transferred &transferred
); );
@ -176,7 +174,7 @@ static ssize_t ep1_memory_read(
usb_ret = jtag_libusb_bulk_write( usb_ret = jtag_libusb_bulk_write(
hdev_param, USB_EP1OUT_ADDR, hdev_param, USB_EP1OUT_ADDR,
(char *)usb_buffer, sizeof(usb_buffer), (char *)usb_buffer, sizeof(usb_buffer),
USB_TIMEOUT_MS, LIBUSB_TIMEOUT_MS,
&transferred &transferred
); );
@ -186,7 +184,7 @@ static ssize_t ep1_memory_read(
usb_ret = jtag_libusb_bulk_read( usb_ret = jtag_libusb_bulk_read(
hdev_param, USB_EP1IN_ADDR, hdev_param, USB_EP1IN_ADDR,
(char *)buffer, length, (char *)buffer, length,
USB_TIMEOUT_MS, LIBUSB_TIMEOUT_MS,
&transferred &transferred
); );
@ -241,7 +239,7 @@ static ssize_t ep1_memory_write(struct libusb_device_handle *hdev_param, uint16_
usb_ret = jtag_libusb_bulk_write( usb_ret = jtag_libusb_bulk_write(
hdev_param, USB_EP1OUT_ADDR, hdev_param, USB_EP1OUT_ADDR,
(char *)usb_buffer, sizeof(usb_buffer), (char *)usb_buffer, sizeof(usb_buffer),
USB_TIMEOUT_MS, LIBUSB_TIMEOUT_MS,
&transferred &transferred
); );
@ -432,7 +430,7 @@ static int dtc_start_download(void)
usb_err = jtag_libusb_bulk_read( usb_err = jtag_libusb_bulk_read(
hdev, USB_EP1IN_ADDR, hdev, USB_EP1IN_ADDR,
(char *)&ep2txr, 1, (char *)&ep2txr, 1,
USB_TIMEOUT_MS, LIBUSB_TIMEOUT_MS,
&transferred &transferred
); );
if (usb_err != ERROR_OK) if (usb_err != ERROR_OK)
@ -462,7 +460,7 @@ static int dtc_start_download(void)
usb_err = jtag_libusb_bulk_read( usb_err = jtag_libusb_bulk_read(
hdev, USB_EP1IN_ADDR, hdev, USB_EP1IN_ADDR,
(char *)&ep2txr, 1, (char *)&ep2txr, 1,
USB_TIMEOUT_MS, LIBUSB_TIMEOUT_MS,
&transferred &transferred
); );
@ -488,7 +486,7 @@ static int dtc_run_download(
hdev_param, hdev_param,
USB_EP2OUT_ADDR, USB_EP2OUT_ADDR,
(char *)command_buffer, USB_EP2BANK_SIZE, (char *)command_buffer, USB_EP2BANK_SIZE,
USB_TIMEOUT_MS, LIBUSB_TIMEOUT_MS,
&transferred &transferred
); );
if (usb_err < 0) if (usb_err < 0)
@ -512,7 +510,7 @@ static int dtc_run_download(
hdev_param, hdev_param,
USB_EP1IN_ADDR, USB_EP1IN_ADDR,
&dtc_status, 1, &dtc_status, 1,
USB_TIMEOUT_MS, LIBUSB_TIMEOUT_MS,
&transferred &transferred
); );
if (usb_err < 0) if (usb_err < 0)
@ -533,7 +531,7 @@ static int dtc_run_download(
hdev_param, hdev_param,
USB_EP2IN_ADDR, USB_EP2IN_ADDR,
(char *)reply_buffer, reply_buffer_size, (char *)reply_buffer, reply_buffer_size,
USB_TIMEOUT_MS, LIBUSB_TIMEOUT_MS,
&transferred &transferred
); );
@ -954,7 +952,7 @@ static void rlink_reset(int trst, int srst)
usb_err = jtag_libusb_bulk_read( usb_err = jtag_libusb_bulk_read(
hdev, USB_EP1IN_ADDR, hdev, USB_EP1IN_ADDR,
(char *)&bitmap, 1, (char *)&bitmap, 1,
USB_TIMEOUT_MS, LIBUSB_TIMEOUT_MS,
&transferred &transferred
); );
if (usb_err != ERROR_OK || transferred < 1) { 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( usb_err = jtag_libusb_bulk_read(
hdev, USB_EP1IN_ADDR, hdev, USB_EP1IN_ADDR,
(char *)&bitmap, 1, (char *)&bitmap, 1,
USB_TIMEOUT_MS, LIBUSB_TIMEOUT_MS,
&transferred &transferred
); );
if (usb_err != ERROR_OK || transferred < 1) { 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( usb_err = jtag_libusb_bulk_read(
hdev, USB_EP1IN_ADDR, hdev, USB_EP1IN_ADDR,
(char *)&bitmap, 1, (char *)&bitmap, 1,
USB_TIMEOUT_MS, LIBUSB_TIMEOUT_MS,
&transferred &transferred
); );
if (usb_err != ERROR_OK || transferred < 1) { if (usb_err != ERROR_OK || transferred < 1) {
@ -1576,7 +1574,7 @@ static int rlink_init(void)
jtag_libusb_bulk_read( jtag_libusb_bulk_read(
hdev, USB_EP1IN_ADDR, hdev, USB_EP1IN_ADDR,
(char *)reply_buffer, 1, (char *)reply_buffer, 1,
USB_TIMEOUT_MS, LIBUSB_TIMEOUT_MS,
&transferred &transferred
); );
@ -1601,7 +1599,7 @@ static int rlink_init(void)
jtag_libusb_bulk_read( jtag_libusb_bulk_read(
hdev, USB_EP1IN_ADDR, hdev, USB_EP1IN_ADDR,
(char *)reply_buffer, 1, (char *)reply_buffer, 1,
USB_TIMEOUT_MS, LIBUSB_TIMEOUT_MS,
&transferred &transferred
); );

View File

@ -71,8 +71,8 @@
#define ENDPOINT_IN 0x80 #define ENDPOINT_IN 0x80
#define ENDPOINT_OUT 0x00 #define ENDPOINT_OUT 0x00
#define STLINK_WRITE_TIMEOUT 1000 #define STLINK_WRITE_TIMEOUT (LIBUSB_TIMEOUT_MS)
#define STLINK_READ_TIMEOUT 1000 #define STLINK_READ_TIMEOUT (LIBUSB_TIMEOUT_MS)
#define STLINK_RX_EP (1|ENDPOINT_IN) #define STLINK_RX_EP (1|ENDPOINT_IN)
#define STLINK_TX_EP (2|ENDPOINT_OUT) #define STLINK_TX_EP (2|ENDPOINT_OUT)
@ -156,6 +156,13 @@ struct stlink_usb_priv_s {
struct libusb_transfer *trans; 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 { struct stlink_tcp_priv_s {
/** */ /** */
int fd; int fd;
@ -169,6 +176,8 @@ struct stlink_tcp_priv_s {
uint8_t *send_buf; uint8_t *send_buf;
/** */ /** */
uint8_t *recv_buf; uint8_t *recv_buf;
/** */
struct stlink_tcp_version version;
}; };
struct stlink_backend_s { struct stlink_backend_s {
@ -3532,16 +3541,19 @@ static int stlink_tcp_open(void *handle, struct hl_interface_param_s *param)
return ERROR_FAIL; return ERROR_FAIL;
} }
uint32_t api_ver = le_to_h_u32(&h->tcp_backend_priv.recv_buf[0]); h->tcp_backend_priv.version.api = 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]); h->tcp_backend_priv.version.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]); h->tcp_backend_priv.version.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.build = le_to_h_u32(&h->tcp_backend_priv.recv_buf[12]);
LOG_INFO("stlink-server API v%d, version %d.%d.%d", 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 /* in stlink-server API v1 sending more than 1428 bytes will cause stlink-server
* to crash in windows: select a safe default value (1K) */ * 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); h->max_mem_packet = (1 << 10);
/* refresh stlink list (re-enumerate) */ /* 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)) if (!(h->version.flags & STLINK_F_HAS_RW_MISC))
return 0; 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. * 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. * 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; return 0;
for (i = 0; i < len; i++) { for (i = 0; i < len; i++) {

View File

@ -37,8 +37,8 @@
#define ICDI_WRITE_ENDPOINT 0x02 #define ICDI_WRITE_ENDPOINT 0x02
#define ICDI_READ_ENDPOINT 0x83 #define ICDI_READ_ENDPOINT 0x83
#define ICDI_WRITE_TIMEOUT 1000 #define ICDI_WRITE_TIMEOUT (LIBUSB_TIMEOUT_MS)
#define ICDI_READ_TIMEOUT 1000 #define ICDI_READ_TIMEOUT (LIBUSB_TIMEOUT_MS)
#define ICDI_PACKET_SIZE 2048 #define ICDI_PACKET_SIZE 2048
#define PACKET_START "$" #define PACKET_START "$"

View File

@ -56,9 +56,6 @@
/** USB interface number */ /** USB interface number */
#define USB_INTERFACE 0 #define USB_INTERFACE 0
/** libusb timeout in ms */
#define USB_TIMEOUT 5000
/** Delay (in microseconds) to wait while EZ-USB performs ReNumeration. */ /** Delay (in microseconds) to wait while EZ-USB performs ReNumeration. */
#define ULINK_RENUMERATION_DELAY 1500000 #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, ret = libusb_control_transfer(device->usb_device_handle,
(LIBUSB_ENDPOINT_OUT | LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE), (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 /* usb_control_msg() returns the number of bytes transferred during the
* DATA stage of the control transfer - must be exactly 1 in this case! */ * 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, ret = libusb_control_transfer(device->usb_device_handle,
(LIBUSB_ENDPOINT_OUT | LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE), (LIBUSB_ENDPOINT_OUT | LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE),
REQUEST_FIRMWARE_LOAD, addr, FIRMWARE_ADDR, (unsigned char *)data_ptr, REQUEST_FIRMWARE_LOAD, addr, FIRMWARE_ADDR, (unsigned char *)data_ptr,
chunk_size, USB_TIMEOUT); chunk_size, LIBUSB_TIMEOUT_MS);
if (ret != (int)chunk_size) { if (ret != (int)chunk_size) {
/* Abort if libusb sent less data than requested */ /* 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)) { if ((newsize_out > 64) || (newsize_in > 64)) {
/* New command does not fit. Execute all commands in queue before starting /* New command does not fit. Execute all commands in queue before starting
* new queue with the current command as first entry. */ * 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) if (ret == ERROR_OK)
ret = ulink_post_process_queue(device); ret = ulink_post_process_queue(device);
@ -1960,7 +1957,7 @@ static int ulink_execute_queue(void)
} }
if (ulink_handle->commands_in_queue > 0) { 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) if (ret != ERROR_OK)
return ret; return ret;

View File

@ -7,6 +7,11 @@
* Chromium-EC RTOS Task Awareness * Chromium-EC RTOS Task Awareness
*/ */
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <helper/bits.h>
#include <rtos/rtos.h> #include <rtos/rtos.h>
#include <target/target.h> #include <target/target.h>
#include <target/target_type.h> #include <target/target_type.h>
@ -16,7 +21,6 @@
#define CROS_EC_MAX_TASKS 32 #define CROS_EC_MAX_TASKS 32
#define CROS_EC_MAX_NAME 200 #define CROS_EC_MAX_NAME 200
#define CROS_EC_IDLE_STRING "<< idle >>" #define CROS_EC_IDLE_STRING "<< idle >>"
#define BIT(x) (1 << (x))
struct chromium_ec_params { struct chromium_ec_params {
const char *target_name; const char *target_name;

View File

@ -15,6 +15,10 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <stdint.h> #include <stdint.h>
#include <stdbool.h> #include <stdbool.h>
#include <string.h> #include <string.h>

View File

@ -15,6 +15,10 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <helper/log.h> #include <helper/log.h>
#include <target/rtt.h> #include <target/rtt.h>

View File

@ -61,6 +61,13 @@
* found in most modern embedded processors. * 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 { struct target_desc_format {
char *tdesc; char *tdesc;
uint32_t tdesc_length; uint32_t tdesc_length;
@ -97,6 +104,8 @@ struct gdb_connection {
struct target_desc_format target_desc; struct target_desc_format target_desc;
/* temporarily used for thread list support */ /* temporarily used for thread list support */
char *thread_list; char *thread_list;
/* flag to mask the output from gdb_log_callback() */
enum gdb_output_flag output_flag;
}; };
#if 0 #if 0
@ -362,11 +371,13 @@ static int gdb_write(struct connection *connection, void *data, int len)
return ERROR_SERVER_REMOTE_CLOSED; 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)) if (!LOG_LEVEL_IS(LOG_LVL_DEBUG))
return; return;
struct target *target = get_target_from_connection(connection);
/* Avoid dumping non-printable characters to the terminal */ /* Avoid dumping non-printable characters to the terminal */
const unsigned packet_len = strlen(packet); const unsigned packet_len = strlen(packet);
const char *nonprint = find_nonprint_char(packet, packet_len); 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) { if (packet_prefix_printable) {
const unsigned int prefix_len = colon - packet + 1; /* + 1 to include the ':' */ const unsigned int prefix_len = colon - packet + 1; /* + 1 to include the ':' */
const unsigned int payload_len = packet_len - prefix_len; const unsigned int payload_len = packet_len - prefix_len;
LOG_DEBUG("received packet: %.*s<binary-data-%u-bytes>", prefix_len, packet, payload_len); LOG_TARGET_DEBUG(target, "received packet: %.*s<binary-data-%u-bytes>", prefix_len,
packet, payload_len);
} else { } else {
LOG_DEBUG("received packet: <binary-data-%u-bytes>", packet_len); LOG_TARGET_DEBUG(target, "received packet: <binary-data-%u-bytes>", packet_len);
} }
} else { } else {
/* All chars printable, dump the packet as is */ /* 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)) if (!LOG_LEVEL_IS(LOG_LVL_DEBUG))
return; return;
struct target *target = get_target_from_connection(connection);
if (find_nonprint_char(packet_buf, packet_len)) if (find_nonprint_char(packet_buf, packet_len))
LOG_DEBUG("sending packet: $<binary-data-%u-bytes>#%2.2x", packet_len, checksum); LOG_TARGET_DEBUG(target, "sending packet: $<binary-data-%u-bytes>#%2.2x",
packet_len, checksum);
else 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, static int gdb_put_packet_inner(struct connection *connection,
@ -443,7 +460,7 @@ static int gdb_put_packet_inner(struct connection *connection,
#endif #endif
while (1) { while (1) {
gdb_log_outgoing_packet(buffer, len, my_checksum); gdb_log_outgoing_packet(connection, buffer, len, my_checksum);
char local_buffer[1024]; char local_buffer[1024];
local_buffer[0] = '$'; local_buffer[0] = '$';
@ -476,22 +493,27 @@ static int gdb_put_packet_inner(struct connection *connection,
if (retval != ERROR_OK) if (retval != ERROR_OK)
return retval; return retval;
if (reply == '+') if (reply == '+') {
gdb_log_incoming_packet(connection, "+");
break; break;
else if (reply == '-') { } else if (reply == '-') {
/* Stop sending output packets for now */ /* 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"); LOG_WARNING("negative reply, retrying");
} else if (reply == 0x3) { } else if (reply == 0x3) {
gdb_con->ctrl_c = true; gdb_con->ctrl_c = true;
gdb_log_incoming_packet(connection, "<Ctrl-C>");
retval = gdb_get_char(connection, &reply); retval = gdb_get_char(connection, &reply);
if (retval != ERROR_OK) if (retval != ERROR_OK)
return retval; return retval;
if (reply == '+') if (reply == '+') {
gdb_log_incoming_packet(connection, "+");
break; break;
else if (reply == '-') { } else if (reply == '-') {
/* Stop sending output packets for now */ /* 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"); LOG_WARNING("negative reply, retrying");
} else if (reply == '$') { } else if (reply == '$') {
LOG_ERROR("GDB missing ack(1) - assumed good"); LOG_ERROR("GDB missing ack(1) - assumed good");
@ -668,6 +690,7 @@ static int gdb_get_packet_inner(struct connection *connection,
case '$': case '$':
break; break;
case '+': case '+':
gdb_log_incoming_packet(connection, "+");
/* According to the GDB documentation /* According to the GDB documentation
* (https://sourceware.org/gdb/onlinedocs/gdb/Packet-Acknowledgment.html): * (https://sourceware.org/gdb/onlinedocs/gdb/Packet-Acknowledgment.html):
* "gdb sends a final `+` acknowledgment of the stub's `OK` * "gdb sends a final `+` acknowledgment of the stub's `OK`
@ -685,9 +708,11 @@ static int gdb_get_packet_inner(struct connection *connection,
} }
break; break;
case '-': case '-':
gdb_log_incoming_packet(connection, "-");
LOG_WARNING("negative acknowledgment, but no packet pending"); LOG_WARNING("negative acknowledgment, but no packet pending");
break; break;
case 0x3: case 0x3:
gdb_log_incoming_packet(connection, "<Ctrl-C>");
gdb_con->ctrl_c = true; gdb_con->ctrl_c = true;
*len = 0; *len = 0;
return ERROR_OK; 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) { if (gdb_connection->frontend_state == TARGET_RUNNING) {
/* stop forwarding log packets! */ /* stop forwarding log packets! */
log_remove_callback(gdb_log_callback, connection); gdb_connection->output_flag = GDB_OUTPUT_NO;
/* check fileio first */ /* check fileio first */
if (target_get_gdb_fileio_info(target, target->fileio_info) == ERROR_OK) 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 = NULL;
gdb_connection->target_desc.tdesc_length = 0; gdb_connection->target_desc.tdesc_length = 0;
gdb_connection->thread_list = NULL; gdb_connection->thread_list = NULL;
gdb_connection->output_flag = GDB_OUTPUT_NO;
/* send ACK to GDB for debug request */ /* send ACK to GDB for debug request */
gdb_write(connection, "+", 1); gdb_write(connection, "+", 1);
@ -1081,6 +1107,8 @@ static int gdb_new_connection(struct connection *connection)
* register callback to be informed about target events */ * register callback to be informed about target events */
target_register_event_callback(gdb_target_callback_event_handler, connection); target_register_event_callback(gdb_target_callback_event_handler, connection);
log_add_callback(gdb_log_callback, connection);
return ERROR_OK; return ERROR_OK;
} }
@ -2735,7 +2763,7 @@ static int gdb_query_packet(struct connection *connection,
LOG_DEBUG("qRcmd: %s", cmd); LOG_DEBUG("qRcmd: %s", cmd);
/* We want to print all debug output to GDB connection */ /* 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(); target_call_timer_callbacks_now();
/* some commands need to know the GDB connection, make note of current /* some commands need to know the GDB connection, make note of current
* GDB connection. */ * GDB connection. */
@ -2743,7 +2771,7 @@ static int gdb_query_packet(struct connection *connection,
command_run_line(cmd_ctx, cmd); command_run_line(cmd_ctx, cmd);
current_gdb_connection = NULL; current_gdb_connection = NULL;
target_call_timer_callbacks_now(); target_call_timer_callbacks_now();
log_remove_callback(gdb_log_callback, connection); gdb_connection->output_flag = GDB_OUTPUT_NO;
free(cmd); free(cmd);
} }
gdb_put_packet(connection, "OK", 2); 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') { if (parse[0] == 'c') {
gdb_running_type = 'c'; gdb_running_type = 'c';
LOG_DEBUG("target %s continue", target_name(target)); 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); retval = target_resume(target, 1, 0, 0, 0);
if (retval == ERROR_TARGET_NOT_HALTED) if (retval == ERROR_TARGET_NOT_HALTED)
LOG_INFO("target %s was not halted when resume was requested", target_name(target)); 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_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); target_call_event_callbacks(ct, TARGET_EVENT_GDB_START);
if (fake_step) { if (fake_step) {
@ -3045,7 +3073,7 @@ static bool gdb_handle_vcont_packet(struct connection *connection, const char *p
"T05thread:%016"PRIx64";", thread_id); "T05thread:%016"PRIx64";", thread_id);
gdb_put_packet(connection, sig_reply, sig_reply_len); 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; 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 " LOG_DEBUG("stepi ignored. GDB will now fetch the register state "
"from the target."); "from the target.");
gdb_sig_halted(connection); gdb_sig_halted(connection);
log_remove_callback(gdb_log_callback, connection); gdb_connection->output_flag = GDB_OUTPUT_NO;
} else } else
gdb_connection->frontend_state = TARGET_RUNNING; gdb_connection->frontend_state = TARGET_RUNNING;
return true; return true;
@ -3075,7 +3103,7 @@ static bool gdb_handle_vcont_packet(struct connection *connection, const char *p
/* send back signal information */ /* send back signal information */
gdb_signal_reply(ct, connection); gdb_signal_reply(ct, connection);
/* stop forwarding log packets! */ /* stop forwarding log packets! */
log_remove_callback(gdb_log_callback, connection); gdb_connection->output_flag = GDB_OUTPUT_NO;
} else } else
gdb_connection->frontend_state = TARGET_RUNNING; gdb_connection->frontend_state = TARGET_RUNNING;
} else { } else {
@ -3410,6 +3438,10 @@ static void gdb_log_callback(void *priv, const char *file, unsigned line,
struct connection *connection = priv; struct connection *connection = priv;
struct gdb_connection *gdb_con = 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) { if (gdb_con->busy) {
/* do not reply this using the O packet */ /* do not reply this using the O packet */
return; return;
@ -3459,9 +3491,10 @@ static int gdb_input_inner(struct connection *connection)
/* terminate with zero */ /* terminate with zero */
gdb_packet_buffer[packet_size] = '\0'; gdb_packet_buffer[packet_size] = '\0';
gdb_log_incoming_packet(gdb_packet_buffer);
if (packet_size > 0) { if (packet_size > 0) {
gdb_log_incoming_packet(connection, gdb_packet_buffer);
retval = ERROR_OK; retval = ERROR_OK;
switch (packet[0]) { switch (packet[0]) {
case 'T': /* Is thread alive? */ case 'T': /* Is thread alive? */
@ -3512,7 +3545,7 @@ static int gdb_input_inner(struct connection *connection)
case 's': case 's':
{ {
gdb_thread_packet(connection, packet, packet_size); 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) { if (gdb_con->mem_write_error) {
LOG_ERROR("Memory write failure!"); LOG_ERROR("Memory write failure!");
@ -3555,7 +3588,7 @@ static int gdb_input_inner(struct connection *connection)
gdb_sig_halted(connection); gdb_sig_halted(connection);
/* stop forwarding log packets! */ /* stop forwarding log packets! */
log_remove_callback(gdb_log_callback, connection); gdb_con->output_flag = GDB_OUTPUT_NO;
} else { } else {
/* We're running/stepping, in which case we can /* We're running/stepping, in which case we can
* forward log output until the target is halted * 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 * Fretcode,errno,Ctrl-C flag;call-specific attachment
*/ */
gdb_con->frontend_state = TARGET_RUNNING; 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); gdb_fileio_response_packet(connection, packet, packet_size);
break; break;
@ -3680,6 +3713,37 @@ static int gdb_input(struct connection *connection)
return ERROR_OK; 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) static int gdb_target_start(struct target *target, const char *port)
{ {
struct gdb_service *gdb_service; 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; gdb_service->core[1] = -1;
target->gdb_service = gdb_service; target->gdb_service = gdb_service;
ret = add_service("gdb", ret = add_service(&gdb_service_driver, port, target->gdb_max_connections, gdb_service);
port, target->gdb_max_connections, &gdb_new_connection, &gdb_input,
&gdb_connection_closed, gdb_service);
/* initialize all targets gdb service with the same pointer */ /* initialize all targets gdb service with the same pointer */
{ {
struct target_list *head; struct target_list *head;

View File

@ -587,6 +587,15 @@ static int ipdbg_on_connection_closed(struct connection *connection)
return ipdbg_stop_polling(connection->service->priv); 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, 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) 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]; char port_str_buffer[IPDBG_TCP_PORT_STR_MAX_LENGTH];
snprintf(port_str_buffer, IPDBG_TCP_PORT_STR_MAX_LENGTH, "%u", port); snprintf(port_str_buffer, IPDBG_TCP_PORT_STR_MAX_LENGTH, "%u", port);
retval = add_service("ipdbg", port_str_buffer, 1, &ipdbg_on_new_connection, retval = add_service(&ipdbg_service_driver, port_str_buffer, 1, service);
&ipdbg_on_connection_input, &ipdbg_on_connection_closed, service);
if (retval == ERROR_OK) { if (retval == ERROR_OK) {
ipdbg_add_service(service); ipdbg_add_service(service);
if (hub->active_services == 0 && hub->active_connections == 0) if (hub->active_services == 0 && hub->active_connections == 0)

View File

@ -15,6 +15,10 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <stdint.h> #include <stdint.h>
#include <rtt/rtt.h> #include <rtt/rtt.h>
@ -110,6 +114,15 @@ static int rtt_input(struct connection *connection)
return ERROR_OK; 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) COMMAND_HANDLER(handle_rtt_start_command)
{ {
int ret; int ret;
@ -125,8 +138,7 @@ COMMAND_HANDLER(handle_rtt_start_command)
COMMAND_PARSE_NUMBER(uint, CMD_ARGV[1], service->channel); COMMAND_PARSE_NUMBER(uint, CMD_ARGV[1], service->channel);
ret = add_service("rtt", CMD_ARGV[0], CONNECTION_LIMIT_UNLIMITED, ret = add_service(&rtt_service_driver, CMD_ARGV[0], CONNECTION_LIMIT_UNLIMITED, service);
rtt_new_connection, rtt_input, rtt_connection_closed, service);
if (ret != ERROR_OK) { if (ret != ERROR_OK) {
free(service); free(service);

View File

@ -205,13 +205,8 @@ static void free_service(struct service *c)
free(c); free(c);
} }
int add_service(char *name, int add_service(const struct service_driver *driver, const char *port,
const char *port, int max_connections, void *priv)
int max_connections,
new_connection_handler_t new_connection_handler,
input_handler_t input_handler,
connection_closed_handler_t connection_closed_handler,
void *priv)
{ {
struct service *c, **p; struct service *c, **p;
struct hostent *hp; struct hostent *hp;
@ -219,14 +214,16 @@ int add_service(char *name,
c = malloc(sizeof(struct service)); c = malloc(sizeof(struct service));
c->name = strdup(name); c->name = strdup(driver->name);
c->port = strdup(port); c->port = strdup(port);
c->max_connections = 1; /* Only TCP/IP ports can support more than one connection */ c->max_connections = 1; /* Only TCP/IP ports can support more than one connection */
c->fd = -1; c->fd = -1;
c->connections = NULL; c->connections = NULL;
c->new_connection = new_connection_handler; c->new_connection_during_keep_alive = driver->new_connection_during_keep_alive_handler;
c->input = input_handler; c->new_connection = driver->new_connection_handler;
c->connection_closed = connection_closed_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->priv = priv;
c->next = NULL; c->next = NULL;
long portnumber; long portnumber;
@ -278,7 +275,7 @@ int add_service(char *name,
c->sin.sin_port = htons(c->portnumber); c->sin.sin_port = htons(c->portnumber);
if (bind(c->fd, (struct sockaddr *)&c->sin, sizeof(c->sin)) == -1) { 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); close_socket(c->fd);
free_service(c); free_service(c);
return ERROR_FAIL; return ERROR_FAIL;
@ -309,7 +306,7 @@ int add_service(char *name,
socklen_t addr_in_size = sizeof(addr_in); socklen_t addr_in_size = sizeof(addr_in);
if (getsockname(c->fd, (struct sockaddr *)&addr_in, &addr_in_size) == 0) if (getsockname(c->fd, (struct sockaddr *)&addr_in, &addr_in_size) == 0)
LOG_INFO("Listening on port %hu for %s connections", 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) { } else if (c->type == CONNECTION_STDINOUT) {
c->fd = fileno(stdin); c->fd = fileno(stdin);
@ -424,6 +421,14 @@ static int remove_services(void)
return ERROR_OK; 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) int server_loop(struct command_context *command_context)
{ {
struct service *service; struct service *service;

View File

@ -55,9 +55,25 @@ struct connection {
struct connection *next; struct connection *next;
}; };
typedef int (*new_connection_handler_t)(struct connection *connection); struct service_driver {
typedef int (*input_handler_t)(struct connection *connection); /** the name of the server */
typedef int (*connection_closed_handler_t)(struct connection *connection); 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 { struct service {
char *name; char *name;
@ -68,17 +84,17 @@ struct service {
struct sockaddr_in sin; struct sockaddr_in sin;
int max_connections; int max_connections;
struct connection *connections; struct connection *connections;
new_connection_handler_t new_connection; int (*new_connection_during_keep_alive)(struct connection *connection);
input_handler_t input; int (*new_connection)(struct connection *connection);
connection_closed_handler_t connection_closed; int (*input)(struct connection *connection);
int (*connection_closed)(struct connection *connection);
void (*keep_client_alive)(struct connection *connection);
void *priv; void *priv;
struct service *next; struct service *next;
}; };
int add_service(char *name, const char *port, int add_service(const struct service_driver *driver, const char *port,
int max_connections, new_connection_handler_t new_connection_handler, int max_connections, void *priv);
input_handler_t in_handler, connection_closed_handler_t close_handler,
void *priv);
int remove_service(const char *name, const char *port); int remove_service(const char *name, const char *port);
int server_host_os_entry(void); int server_host_os_entry(void);
@ -90,6 +106,8 @@ int server_quit(void);
void server_free(void); void server_free(void);
void exit_on_signal(int sig); void exit_on_signal(int sig);
void server_keep_clients_alive(void);
int server_loop(struct command_context *command_context); int server_loop(struct command_context *command_context);
int server_register_commands(struct command_context *context); int server_register_commands(struct command_context *context);

View File

@ -276,6 +276,15 @@ static int tcl_closed(struct connection *connection)
return ERROR_OK; 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) int tcl_init(void)
{ {
if (strcmp(tcl_port, "disabled") == 0) { if (strcmp(tcl_port, "disabled") == 0) {
@ -283,9 +292,7 @@ int tcl_init(void)
return ERROR_OK; return ERROR_OK;
} }
return add_service("tcl", tcl_port, CONNECTION_LIMIT_UNLIMITED, return add_service(&tcl_service_driver, tcl_port, CONNECTION_LIMIT_UNLIMITED, NULL);
&tcl_new_connection, &tcl_input,
&tcl_closed, NULL);
} }
COMMAND_HANDLER(handle_tcl_port_command) COMMAND_HANDLER(handle_tcl_port_command)

View File

@ -946,6 +946,15 @@ static int telnet_connection_closed(struct connection *connection)
return ERROR_OK; 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) int telnet_init(char *banner)
{ {
if (strcmp(telnet_port, "disabled") == 0) { if (strcmp(telnet_port, "disabled") == 0) {
@ -963,8 +972,7 @@ int telnet_init(char *banner)
telnet_service->banner = banner; telnet_service->banner = banner;
int ret = add_service("telnet", telnet_port, CONNECTION_LIMIT_UNLIMITED, int ret = add_service(&telnet_service_driver, telnet_port, CONNECTION_LIMIT_UNLIMITED,
telnet_new_connection, telnet_input, telnet_connection_closed,
telnet_service); telnet_service);
if (ret != ERROR_OK) { if (ret != ERROR_OK) {

View File

@ -1236,7 +1236,7 @@ static int aarch64_set_breakpoint(struct target *target,
struct armv8_common *armv8 = &aarch64->armv8_common; struct armv8_common *armv8 = &aarch64->armv8_common;
struct aarch64_brp *brp_list = aarch64->brp_list; struct aarch64_brp *brp_list = aarch64->brp_list;
if (breakpoint->set) { if (breakpoint->is_set) {
LOG_WARNING("breakpoint already set"); LOG_WARNING("breakpoint already set");
return ERROR_OK; 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"); LOG_ERROR("ERROR Can not find free Breakpoint Register Pair");
return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
} }
breakpoint->set = brp_i + 1; breakpoint_hw_set(breakpoint, brp_i);
if (breakpoint->length == 2) if (breakpoint->length == 2)
byte_addr_select = (3 << (breakpoint->address & 0x02)); byte_addr_select = (3 << (breakpoint->address & 0x02));
control = ((matchmode & 0x7) << 20) control = ((matchmode & 0x7) << 20)
@ -1333,7 +1333,7 @@ static int aarch64_set_breakpoint(struct target *target,
breakpoint->address & 0xFFFFFFFFFFFFFFFE, breakpoint->address & 0xFFFFFFFFFFFFFFFE,
breakpoint->length); breakpoint->length);
breakpoint->set = 0x11; /* Any nice value but 0 */ breakpoint->is_set = true;
} }
/* Ensure that halting debug mode is enable */ /* 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 armv8_common *armv8 = &aarch64->armv8_common;
struct aarch64_brp *brp_list = aarch64->brp_list; struct aarch64_brp *brp_list = aarch64->brp_list;
if (breakpoint->set) { if (breakpoint->is_set) {
LOG_WARNING("breakpoint already set"); LOG_WARNING("breakpoint already set");
return retval; return retval;
} }
@ -1371,7 +1371,7 @@ static int aarch64_set_context_breakpoint(struct target *target,
return ERROR_FAIL; return ERROR_FAIL;
} }
breakpoint->set = brp_i + 1; breakpoint_hw_set(breakpoint, brp_i);
control = ((matchmode & 0x7) << 20) control = ((matchmode & 0x7) << 20)
| (1 << 13) | (1 << 13)
| (byte_addr_select << 5) | (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 armv8_common *armv8 = &aarch64->armv8_common;
struct aarch64_brp *brp_list = aarch64->brp_list; struct aarch64_brp *brp_list = aarch64->brp_list;
if (breakpoint->set) { if (breakpoint->is_set) {
LOG_WARNING("breakpoint already set"); LOG_WARNING("breakpoint already set");
return retval; return retval;
} }
@ -1435,7 +1435,7 @@ static int aarch64_set_hybrid_breakpoint(struct target *target, struct breakpoin
return ERROR_FAIL; return ERROR_FAIL;
} }
breakpoint->set = brp_1 + 1; breakpoint_hw_set(breakpoint, brp_1);
breakpoint->linked_brp = brp_2; breakpoint->linked_brp = brp_2;
control_ctx = ((ctx_machmode & 0x7) << 20) control_ctx = ((ctx_machmode & 0x7) << 20)
| (brp_2 << 16) | (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 armv8_common *armv8 = &aarch64->armv8_common;
struct aarch64_brp *brp_list = aarch64->brp_list; struct aarch64_brp *brp_list = aarch64->brp_list;
if (!breakpoint->set) { if (!breakpoint->is_set) {
LOG_WARNING("breakpoint not set"); LOG_WARNING("breakpoint not set");
return ERROR_OK; return ERROR_OK;
} }
if (breakpoint->type == BKPT_HARD) { if (breakpoint->type == BKPT_HARD) {
if ((breakpoint->address != 0) && (breakpoint->asid != 0)) { if ((breakpoint->address != 0) && (breakpoint->asid != 0)) {
int brp_i = breakpoint->set - 1; int brp_i = breakpoint->number;
int brp_j = breakpoint->linked_brp; 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"); LOG_DEBUG("Invalid BRP number in breakpoint");
return ERROR_OK; return ERROR_OK;
} }
@ -1549,12 +1549,12 @@ static int aarch64_unset_breakpoint(struct target *target, struct breakpoint *br
return retval; return retval;
breakpoint->linked_brp = 0; breakpoint->linked_brp = 0;
breakpoint->set = 0; breakpoint->is_set = false;
return ERROR_OK; return ERROR_OK;
} else { } else {
int brp_i = breakpoint->set - 1; int brp_i = breakpoint->number;
if ((brp_i < 0) || (brp_i >= aarch64->brp_num)) { if (brp_i >= aarch64->brp_num) {
LOG_DEBUG("Invalid BRP number in breakpoint"); LOG_DEBUG("Invalid BRP number in breakpoint");
return ERROR_OK; 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); (uint32_t)brp_list[brp_i].value);
if (retval != ERROR_OK) if (retval != ERROR_OK)
return retval; return retval;
breakpoint->set = 0; breakpoint->is_set = false;
return ERROR_OK; return ERROR_OK;
} }
} else { } else {
@ -1611,7 +1611,7 @@ static int aarch64_unset_breakpoint(struct target *target, struct breakpoint *br
breakpoint->address & 0xFFFFFFFFFFFFFFFE, breakpoint->address & 0xFFFFFFFFFFFFFFFE,
breakpoint->length); breakpoint->length);
} }
breakpoint->set = 0; breakpoint->is_set = false;
return ERROR_OK; return ERROR_OK;
} }
@ -1676,7 +1676,7 @@ static int aarch64_remove_breakpoint(struct target *target, struct breakpoint *b
} }
#endif #endif
if (breakpoint->set) { if (breakpoint->is_set) {
aarch64_unset_breakpoint(target, breakpoint); aarch64_unset_breakpoint(target, breakpoint);
if (breakpoint->type == BKPT_HARD) if (breakpoint->type == BKPT_HARD)
aarch64->brp_num_available++; aarch64->brp_num_available++;
@ -1696,7 +1696,7 @@ static int aarch64_set_watchpoint(struct target *target,
struct armv8_common *armv8 = &aarch64->armv8_common; struct armv8_common *armv8 = &aarch64->armv8_common;
struct aarch64_brp *wp_list = aarch64->wp_list; struct aarch64_brp *wp_list = aarch64->wp_list;
if (watchpoint->set) { if (watchpoint->is_set) {
LOG_WARNING("watchpoint already set"); LOG_WARNING("watchpoint already set");
return ERROR_OK; return ERROR_OK;
} }
@ -1764,7 +1764,7 @@ static int aarch64_set_watchpoint(struct target *target,
} }
wp_list[wp_i].used = 1; wp_list[wp_i].used = 1;
watchpoint->set = wp_i + 1; watchpoint_set(watchpoint, wp_i);
return ERROR_OK; return ERROR_OK;
} }
@ -1773,18 +1773,18 @@ static int aarch64_set_watchpoint(struct target *target,
static int aarch64_unset_watchpoint(struct target *target, static int aarch64_unset_watchpoint(struct target *target,
struct watchpoint *watchpoint) struct watchpoint *watchpoint)
{ {
int retval, wp_i; int retval;
struct aarch64_common *aarch64 = target_to_aarch64(target); struct aarch64_common *aarch64 = target_to_aarch64(target);
struct armv8_common *armv8 = &aarch64->armv8_common; struct armv8_common *armv8 = &aarch64->armv8_common;
struct aarch64_brp *wp_list = aarch64->wp_list; struct aarch64_brp *wp_list = aarch64->wp_list;
if (!watchpoint->set) { if (!watchpoint->is_set) {
LOG_WARNING("watchpoint not set"); LOG_WARNING("watchpoint not set");
return ERROR_OK; return ERROR_OK;
} }
wp_i = watchpoint->set - 1; int wp_i = watchpoint->number;
if ((wp_i < 0) || (wp_i >= aarch64->wp_num)) { if (wp_i >= aarch64->wp_num) {
LOG_DEBUG("Invalid WP number in watchpoint"); LOG_DEBUG("Invalid WP number in watchpoint");
return ERROR_OK; return ERROR_OK;
} }
@ -1809,7 +1809,7 @@ static int aarch64_unset_watchpoint(struct target *target,
(uint32_t)wp_list[wp_i].value); (uint32_t)wp_list[wp_i].value);
if (retval != ERROR_OK) if (retval != ERROR_OK)
return retval; return retval;
watchpoint->set = 0; watchpoint->is_set = false;
return ERROR_OK; return ERROR_OK;
} }
@ -1837,7 +1837,7 @@ static int aarch64_remove_watchpoint(struct target *target,
{ {
struct aarch64_common *aarch64 = target_to_aarch64(target); struct aarch64_common *aarch64 = target_to_aarch64(target);
if (watchpoint->set) { if (watchpoint->is_set) {
aarch64_unset_watchpoint(target, watchpoint); aarch64_unset_watchpoint(target, watchpoint);
aarch64->wp_num_available++; aarch64->wp_num_available++;
} }

View File

@ -1500,7 +1500,7 @@ static int arc_configure_actionpoint(struct target *target, uint32_t ap_num,
static int arc_set_breakpoint(struct target *target, static int arc_set_breakpoint(struct target *target,
struct breakpoint *breakpoint) struct breakpoint *breakpoint)
{ {
if (breakpoint->set) { if (breakpoint->is_set) {
LOG_WARNING("breakpoint already set"); LOG_WARNING("breakpoint already set");
return ERROR_OK; return ERROR_OK;
} }
@ -1542,7 +1542,7 @@ static int arc_set_breakpoint(struct target *target,
return ERROR_COMMAND_ARGUMENT_INVALID; return ERROR_COMMAND_ARGUMENT_INVALID;
} }
breakpoint->set = 64; /* Any nice value but 0 */ breakpoint->is_set = true;
} else if (breakpoint->type == BKPT_HARD) { } else if (breakpoint->type == BKPT_HARD) {
struct arc_common *arc = target_to_arc(target); struct arc_common *arc = target_to_arc(target);
struct arc_actionpoint *ap_list = arc->actionpoints_list; 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); breakpoint->address, AP_AC_TT_READWRITE, AP_AC_AT_INST_ADDR);
if (retval == ERROR_OK) { 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].used = 1;
ap_list[bp_num].bp_value = breakpoint->address; ap_list[bp_num].bp_value = breakpoint->address;
ap_list[bp_num].type = ARC_AP_BREAKPOINT; ap_list[bp_num].type = ARC_AP_BREAKPOINT;
@ -1588,7 +1588,7 @@ static int arc_unset_breakpoint(struct target *target,
{ {
int retval = ERROR_OK; int retval = ERROR_OK;
if (!breakpoint->set) { if (!breakpoint->is_set) {
LOG_WARNING("breakpoint not set"); LOG_WARNING("breakpoint not set");
return ERROR_OK; 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"); LOG_ERROR("Invalid breakpoint length: target supports only 2 or 4");
return ERROR_COMMAND_ARGUMENT_INVALID; return ERROR_COMMAND_ARGUMENT_INVALID;
} }
breakpoint->set = 0; breakpoint->is_set = false;
} else if (breakpoint->type == BKPT_HARD) { } else if (breakpoint->type == BKPT_HARD) {
struct arc_common *arc = target_to_arc(target); struct arc_common *arc = target_to_arc(target);
struct arc_actionpoint *ap_list = arc->actionpoints_list; 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, LOG_DEBUG("Invalid actionpoint ID: %u in breakpoint: %" PRIu32,
bp_num, breakpoint->unique_id); bp_num, breakpoint->unique_id);
return ERROR_OK; 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); breakpoint->address, AP_AC_TT_DISABLE, AP_AC_AT_INST_ADDR);
if (retval == ERROR_OK) { if (retval == ERROR_OK) {
breakpoint->set = 0; breakpoint->is_set = false;
ap_list[bp_num].used = 0; ap_list[bp_num].used = 0;
ap_list[bp_num].bp_value = 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); breakpoint->unique_id, bp_num);
} }
} else { } else {
@ -1684,7 +1684,7 @@ static int arc_remove_breakpoint(struct target *target,
struct breakpoint *breakpoint) struct breakpoint *breakpoint)
{ {
if (target->state == TARGET_HALTED) { if (target->state == TARGET_HALTED) {
if (breakpoint->set) if (breakpoint->is_set)
CHECK_RETVAL(arc_unset_breakpoint(target, breakpoint)); CHECK_RETVAL(arc_unset_breakpoint(target, breakpoint));
} else { } else {
LOG_WARNING("target not halted"); 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_common *arc = target_to_arc(target);
struct arc_actionpoint *ap_list = arc->actionpoints_list; struct arc_actionpoint *ap_list = arc->actionpoints_list;
if (watchpoint->set) { if (watchpoint->is_set) {
LOG_WARNING("watchpoint already set"); LOG_WARNING("watchpoint already set");
return ERROR_OK; return ERROR_OK;
} }
@ -1859,7 +1859,7 @@ static int arc_set_watchpoint(struct target *target,
watchpoint->address, enable, AP_AC_AT_MEMORY_ADDR); watchpoint->address, enable, AP_AC_AT_MEMORY_ADDR);
if (retval == ERROR_OK) { if (retval == ERROR_OK) {
watchpoint->set = wp_num + 1; watchpoint_set(watchpoint, wp_num);
ap_list[wp_num].used = 1; ap_list[wp_num].used = 1;
ap_list[wp_num].bp_value = watchpoint->address; ap_list[wp_num].bp_value = watchpoint->address;
ap_list[wp_num].type = ARC_AP_WATCHPOINT; 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_common *arc = target_to_arc(target);
struct arc_actionpoint *ap_list = arc->actionpoints_list; struct arc_actionpoint *ap_list = arc->actionpoints_list;
if (!watchpoint->set) { if (!watchpoint->is_set) {
LOG_WARNING("watchpoint not set"); LOG_WARNING("watchpoint not set");
return ERROR_OK; return ERROR_OK;
} }
unsigned int wp_num = watchpoint->set - 1; unsigned int wp_num = watchpoint->number;
if ((watchpoint->set == 0) || (wp_num >= arc->actionpoints_num)) { if (wp_num >= arc->actionpoints_num) {
LOG_DEBUG("Invalid actionpoint ID: %u in watchpoint: %" PRIu32, LOG_DEBUG("Invalid actionpoint ID: %u in watchpoint: %" PRIu32,
wp_num, watchpoint->unique_id); wp_num, watchpoint->unique_id);
return ERROR_OK; 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); watchpoint->address, AP_AC_TT_DISABLE, AP_AC_AT_MEMORY_ADDR);
if (retval == ERROR_OK) { if (retval == ERROR_OK) {
watchpoint->set = 0; watchpoint->is_set = false;
ap_list[wp_num].used = 0; ap_list[wp_num].used = 0;
ap_list[wp_num].bp_value = 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; return ERROR_TARGET_NOT_HALTED;
} }
if (watchpoint->set) if (watchpoint->is_set)
CHECK_RETVAL(arc_unset_watchpoint(target, watchpoint)); CHECK_RETVAL(arc_unset_watchpoint(target, watchpoint));
return ERROR_OK; return ERROR_OK;
@ -1953,8 +1953,8 @@ static int arc_hit_watchpoint(struct target *target, struct watchpoint **hit_wat
watchpoint = watchpoint->next) { watchpoint = watchpoint->next) {
if (actionpoint->bp_value == watchpoint->address) { if (actionpoint->bp_value == watchpoint->address) {
*hit_watchpoint = watchpoint; *hit_watchpoint = watchpoint;
LOG_DEBUG("Hit watchpoint, wpid: %" PRIu32 ", watchpoint num: %i", LOG_DEBUG("Hit watchpoint, wpid: %" PRIu32 ", watchpoint num: %u",
watchpoint->unique_id, watchpoint->set - 1); watchpoint->unique_id, watchpoint->number);
return ERROR_OK; return ERROR_OK;
} }
} }

View File

@ -93,19 +93,20 @@ static void arm7_9_assign_wp(struct arm7_9_common *arm7_9, struct breakpoint *br
{ {
if (!arm7_9->wp0_used) { if (!arm7_9->wp0_used) {
arm7_9->wp0_used = 1; arm7_9->wp0_used = 1;
breakpoint->set = 1; breakpoint_hw_set(breakpoint, 0);
arm7_9->wp_available--; arm7_9->wp_available--;
} else if (!arm7_9->wp1_used) { } else if (!arm7_9->wp1_used) {
arm7_9->wp1_used = 1; arm7_9->wp1_used = 1;
breakpoint->set = 2; breakpoint_hw_set(breakpoint, 1);
arm7_9->wp_available--; arm7_9->wp_available--;
} else } else {
LOG_ERROR("BUG: no hardware comparator available"); 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->unique_id,
breakpoint->address, 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; uint32_t mask = (breakpoint->length == 4) ? 0x3u : 0x1u;
/* reassign a hw breakpoint */ /* reassign a hw breakpoint */
if (breakpoint->set == 0) if (!breakpoint->is_set)
arm7_9_assign_wp(arm7_9, breakpoint); 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_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_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_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_MASK], ~EICE_W_CTRL_NOPC & 0xff);
embeddedice_set_reg(&arm7_9->eice_cache->reg_list[EICE_W0_CONTROL_VALUE], EICE_W_CTRL_ENABLE); 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_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_ADDR_MASK], mask);
embeddedice_set_reg(&arm7_9->eice_cache->reg_list[EICE_W1_DATA_MASK], 0xffffffffu); 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(); retval = jtag_execute_queue();
} else if (breakpoint->type == BKPT_SOFT) { } else if (breakpoint->type == BKPT_SOFT) {
/* did we already set this breakpoint? */ /* did we already set this breakpoint? */
if (breakpoint->set) if (breakpoint->is_set)
return ERROR_OK; return ERROR_OK;
if (breakpoint->length == 4) { 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++; arm7_9->sw_breakpoint_count++;
breakpoint->set = 1; breakpoint->is_set = true;
} }
return retval; return retval;
@ -304,7 +305,7 @@ static int arm7_9_unset_breakpoint(struct target *target, struct breakpoint *bre
breakpoint->unique_id, breakpoint->unique_id,
breakpoint->address); breakpoint->address);
if (!breakpoint->set) { if (!breakpoint->is_set) {
LOG_WARNING("breakpoint not set"); LOG_WARNING("breakpoint not set");
return ERROR_OK; return ERROR_OK;
} }
@ -312,18 +313,18 @@ static int arm7_9_unset_breakpoint(struct target *target, struct breakpoint *bre
if (breakpoint->type == BKPT_HARD) { if (breakpoint->type == BKPT_HARD) {
LOG_DEBUG("BPID: %" PRIu32 " Releasing hw wp: %d", LOG_DEBUG("BPID: %" PRIu32 " Releasing hw wp: %d",
breakpoint->unique_id, breakpoint->unique_id,
breakpoint->set); breakpoint->is_set);
if (breakpoint->set == 1) { if (breakpoint->number == 0) {
embeddedice_set_reg(&arm7_9->eice_cache->reg_list[EICE_W0_CONTROL_VALUE], 0x0); embeddedice_set_reg(&arm7_9->eice_cache->reg_list[EICE_W0_CONTROL_VALUE], 0x0);
arm7_9->wp0_used = 0; arm7_9->wp0_used = 0;
arm7_9->wp_available++; 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); embeddedice_set_reg(&arm7_9->eice_cache->reg_list[EICE_W1_CONTROL_VALUE], 0x0);
arm7_9->wp1_used = 0; arm7_9->wp1_used = 0;
arm7_9->wp_available++; arm7_9->wp_available++;
} }
retval = jtag_execute_queue(); retval = jtag_execute_queue();
breakpoint->set = 0; breakpoint->is_set = false;
} else { } else {
/* restore original instruction (kept in target endianness) */ /* restore original instruction (kept in target endianness) */
if (breakpoint->length == 4) { 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); EICE_W1_CONTROL_VALUE], 0);
} }
breakpoint->set = 0; breakpoint->is_set = false;
} }
return retval; return retval;
@ -491,7 +492,7 @@ static int arm7_9_set_watchpoint(struct target *target, struct watchpoint *watch
retval = jtag_execute_queue(); retval = jtag_execute_queue();
if (retval != ERROR_OK) if (retval != ERROR_OK)
return retval; return retval;
watchpoint->set = 1; watchpoint_set(watchpoint, 1);
arm7_9->wp0_used = 2; arm7_9->wp0_used = 2;
} else if (!arm7_9->wp1_used) { } else if (!arm7_9->wp1_used) {
embeddedice_set_reg(&arm7_9->eice_cache->reg_list[EICE_W1_ADDR_VALUE], 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(); retval = jtag_execute_queue();
if (retval != ERROR_OK) if (retval != ERROR_OK)
return retval; return retval;
watchpoint->set = 2; watchpoint_set(watchpoint, 2);
arm7_9->wp1_used = 2; arm7_9->wp1_used = 2;
} else { } else {
LOG_ERROR("BUG: no hardware comparator available"); 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; return ERROR_TARGET_NOT_HALTED;
} }
if (!watchpoint->set) { if (!watchpoint->is_set) {
LOG_WARNING("breakpoint not set"); LOG_WARNING("breakpoint not set");
return ERROR_OK; 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); embeddedice_set_reg(&arm7_9->eice_cache->reg_list[EICE_W0_CONTROL_VALUE], 0x0);
retval = jtag_execute_queue(); retval = jtag_execute_queue();
if (retval != ERROR_OK) if (retval != ERROR_OK)
return retval; return retval;
arm7_9->wp0_used = 0; 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); embeddedice_set_reg(&arm7_9->eice_cache->reg_list[EICE_W1_CONTROL_VALUE], 0x0);
retval = jtag_execute_queue(); retval = jtag_execute_queue();
if (retval != ERROR_OK) if (retval != ERROR_OK)
return retval; return retval;
arm7_9->wp1_used = 0; arm7_9->wp1_used = 0;
} }
watchpoint->set = 0; watchpoint->is_set = false;
return ERROR_OK; return ERROR_OK;
} }
@ -597,7 +598,7 @@ int arm7_9_remove_watchpoint(struct target *target, struct watchpoint *watchpoin
int retval = ERROR_OK; int retval = ERROR_OK;
struct arm7_9_common *arm7_9 = target_to_arm7_9(target); 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); retval = arm7_9_unset_watchpoint(target, watchpoint);
if (retval != ERROR_OK) if (retval != ERROR_OK)
return retval; return retval;
@ -1684,7 +1685,7 @@ static void arm7_9_enable_watchpoints(struct target *target)
struct watchpoint *watchpoint = target->watchpoints; struct watchpoint *watchpoint = target->watchpoints;
while (watchpoint) { while (watchpoint) {
if (watchpoint->set == 0) if (!watchpoint->is_set)
arm7_9_set_watchpoint(target, watchpoint); arm7_9_set_watchpoint(target, watchpoint);
watchpoint = watchpoint->next; watchpoint = watchpoint->next;
} }

View File

@ -398,7 +398,7 @@ fail:
* or running debugger code. * or running debugger code.
*/ */
static int dpm_maybe_update_bpwp(struct arm_dpm *dpm, bool bpwp, 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; int retval = ERROR_OK;
bool disable; bool disable;
@ -473,7 +473,7 @@ int arm_dpm_write_dirty_registers(struct arm_dpm *dpm, bool bpwp)
struct breakpoint *bp = dbp->bp; struct breakpoint *bp = dbp->bp;
retval = dpm_maybe_update_bpwp(dpm, bpwp, &dbp->bpwp, retval = dpm_maybe_update_bpwp(dpm, bpwp, &dbp->bpwp,
bp ? &bp->set : NULL); bp ? &bp->is_set : NULL);
if (retval != ERROR_OK) if (retval != ERROR_OK)
goto done; goto done;
} }
@ -485,7 +485,7 @@ int arm_dpm_write_dirty_registers(struct arm_dpm *dpm, bool bpwp)
struct watchpoint *wp = dwp->wp; struct watchpoint *wp = dwp->wp;
retval = dpm_maybe_update_bpwp(dpm, bpwp, &dwp->bpwp, retval = dpm_maybe_update_bpwp(dpm, bpwp, &dwp->bpwp,
wp ? &wp->set : NULL); wp ? &wp->is_set : NULL);
if (retval != ERROR_OK) if (retval != ERROR_OK)
goto done; goto done;
} }

View File

@ -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); 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) static int jim_arm_tpiu_swo_enable(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{ {
struct command *c = jim_to_command(interp); 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->pin_protocol == TPIU_SPPR_PROTOCOL_MANCHESTER || obj->pin_protocol == TPIU_SPPR_PROTOCOL_UART)
if (!obj->swo_pin_freq) { if (!obj->swo_pin_freq)
LOG_ERROR("SWO pin frequency not set"); LOG_DEBUG("SWO pin frequency not set, will be autodetected by the adapter");
return JIM_ERR;
}
struct target *target = get_current_target(cmd_ctx); 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; priv->obj = obj;
LOG_INFO("starting trace server for %s on %s", obj->name, &obj->out_filename[1]); 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], retval = add_service(&arm_tpiu_swo_service_driver, &obj->out_filename[1],
CONNECTION_LIMIT_UNLIMITED, arm_tpiu_swo_service_new_connection, CONNECTION_LIMIT_UNLIMITED, priv);
arm_tpiu_swo_service_input, arm_tpiu_swo_service_connection_closed,
priv);
if (retval != ERROR_OK) { if (retval != ERROR_OK) {
LOG_ERROR("Can't configure trace TCP port %s", &obj->out_filename[1]); LOG_ERROR("Can't configure trace TCP port %s", &obj->out_filename[1]);
return JIM_ERR; 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; 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) if (obj->swo_pin_freq != swo_pin_freq)
LOG_INFO("SWO pin data rate adjusted by adapter to %d Hz", 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; 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? */ /* does this command exist? */
cmd = Jim_GetCommand(interp, Jim_NewStringObj(interp, obj->name, -1), JIM_NONE); cmd = Jim_GetCommand(interp, Jim_NewStringObj(interp, obj->name, -1), JIM_NONE);
if (cmd) { 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; 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; struct jim_getopt_info goi;
jim_getopt_setup(&goi, interp, argc - 1, argv + 1); jim_getopt_setup(&goi, interp, argc - 1, argv + 1);
if (goi.argc < 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; return JIM_ERR;
} }
@ -1160,7 +1177,7 @@ static const struct command_registration arm_tpiu_swo_subcommand_handlers[] = {
.name = "create", .name = "create",
.mode = COMMAND_ANY, .mode = COMMAND_ANY,
.jim_handler = jim_arm_tpiu_swo_create, .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", .help = "Creates a new TPIU or SWO object",
}, },
{ {

View File

@ -818,7 +818,7 @@ fail:
* or running debugger code. * or running debugger code.
*/ */
static int dpmv8_maybe_update_bpwp(struct arm_dpm *dpm, bool bpwp, 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; int retval = ERROR_OK;
bool disable; bool disable;
@ -892,7 +892,7 @@ int armv8_dpm_write_dirty_registers(struct arm_dpm *dpm, bool bpwp)
struct breakpoint *bp = dbp->bp; struct breakpoint *bp = dbp->bp;
retval = dpmv8_maybe_update_bpwp(dpm, bpwp, &dbp->bpwp, retval = dpmv8_maybe_update_bpwp(dpm, bpwp, &dbp->bpwp,
bp ? &bp->set : NULL); bp ? &bp->is_set : NULL);
if (retval != ERROR_OK) if (retval != ERROR_OK)
goto done; goto done;
} }
@ -904,7 +904,7 @@ int armv8_dpm_write_dirty_registers(struct arm_dpm *dpm, bool bpwp)
struct watchpoint *wp = dwp->wp; struct watchpoint *wp = dwp->wp;
retval = dpmv8_maybe_update_bpwp(dpm, bpwp, &dwp->bpwp, retval = dpmv8_maybe_update_bpwp(dpm, bpwp, &dwp->bpwp,
wp ? &wp->set : NULL); wp ? &wp->is_set : NULL);
if (retval != ERROR_OK) if (retval != ERROR_OK)
goto done; goto done;
} }

View File

@ -72,7 +72,7 @@ static int breakpoint_add_internal(struct target *target,
(*breakpoint_p)->asid = 0; (*breakpoint_p)->asid = 0;
(*breakpoint_p)->length = length; (*breakpoint_p)->length = length;
(*breakpoint_p)->type = type; (*breakpoint_p)->type = type;
(*breakpoint_p)->set = 0; (*breakpoint_p)->is_set = false;
(*breakpoint_p)->orig_instr = malloc(length); (*breakpoint_p)->orig_instr = malloc(length);
(*breakpoint_p)->next = NULL; (*breakpoint_p)->next = NULL;
(*breakpoint_p)->unique_id = bpwp_unique_id++; (*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)->asid = asid;
(*breakpoint_p)->length = length; (*breakpoint_p)->length = length;
(*breakpoint_p)->type = type; (*breakpoint_p)->type = type;
(*breakpoint_p)->set = 0; (*breakpoint_p)->is_set = false;
(*breakpoint_p)->orig_instr = malloc(length); (*breakpoint_p)->orig_instr = malloc(length);
(*breakpoint_p)->next = NULL; (*breakpoint_p)->next = NULL;
(*breakpoint_p)->unique_id = bpwp_unique_id++; (*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)->asid = asid;
(*breakpoint_p)->length = length; (*breakpoint_p)->length = length;
(*breakpoint_p)->type = type; (*breakpoint_p)->type = type;
(*breakpoint_p)->set = 0; (*breakpoint_p)->is_set = false;
(*breakpoint_p)->orig_instr = malloc(length); (*breakpoint_p)->orig_instr = malloc(length);
(*breakpoint_p)->next = NULL; (*breakpoint_p)->next = NULL;
(*breakpoint_p)->unique_id = bpwp_unique_id++; (*breakpoint_p)->unique_id = bpwp_unique_id++;

View File

@ -39,7 +39,8 @@ struct breakpoint {
uint32_t asid; uint32_t asid;
int length; int length;
enum breakpoint_type type; enum breakpoint_type type;
int set; bool is_set;
unsigned int number;
uint8_t *orig_instr; uint8_t *orig_instr;
struct breakpoint *next; struct breakpoint *next;
uint32_t unique_id; uint32_t unique_id;
@ -52,7 +53,8 @@ struct watchpoint {
uint32_t mask; uint32_t mask;
uint32_t value; uint32_t value;
enum watchpoint_rw rw; enum watchpoint_rw rw;
int set; bool is_set;
unsigned int number;
struct watchpoint *next; struct watchpoint *next;
int unique_id; 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); 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); void watchpoint_clear_target(struct target *target);
int watchpoint_add(struct target *target, int watchpoint_add(struct target *target,
target_addr_t address, uint32_t length, 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, int watchpoint_hit(struct target *target, enum watchpoint_rw *rw,
target_addr_t *address); 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 */ #endif /* OPENOCD_TARGET_BREAKPOINTS_H */

View File

@ -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) stepbreakpoint.length = (arm->core_state == ARM_STATE_THUMB)
? 2 : 4; ? 2 : 4;
stepbreakpoint.type = BKPT_HARD; stepbreakpoint.type = BKPT_HARD;
stepbreakpoint.set = 0; stepbreakpoint.is_set = false;
/* Disable interrupts during single step if requested */ /* Disable interrupts during single step if requested */
if (cortex_a->isrmasking_mode == CORTEX_A_ISRMASK_ON) { 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 armv7a_common *armv7a = &cortex_a->armv7a_common;
struct cortex_a_brp *brp_list = cortex_a->brp_list; struct cortex_a_brp *brp_list = cortex_a->brp_list;
if (breakpoint->set) { if (breakpoint->is_set) {
LOG_WARNING("breakpoint already set"); LOG_WARNING("breakpoint already set");
return ERROR_OK; 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"); LOG_ERROR("ERROR Can not find free Breakpoint Register Pair");
return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
} }
breakpoint->set = brp_i + 1; breakpoint_hw_set(breakpoint, brp_i);
if (breakpoint->length == 2) if (breakpoint->length == 2)
byte_addr_select = (3 << (breakpoint->address & 0x02)); byte_addr_select = (3 << (breakpoint->address & 0x02));
control = ((matchmode & 0x7) << 20) 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, armv7a_l1_i_cache_inval_virt(target, breakpoint->address,
breakpoint->length); breakpoint->length);
breakpoint->set = 0x11; /* Any nice value but 0 */ breakpoint->is_set = true;
} }
return ERROR_OK; 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 armv7a_common *armv7a = &cortex_a->armv7a_common;
struct cortex_a_brp *brp_list = cortex_a->brp_list; struct cortex_a_brp *brp_list = cortex_a->brp_list;
if (breakpoint->set) { if (breakpoint->is_set) {
LOG_WARNING("breakpoint already set"); LOG_WARNING("breakpoint already set");
return retval; return retval;
} }
@ -1373,7 +1373,7 @@ static int cortex_a_set_context_breakpoint(struct target *target,
return ERROR_FAIL; return ERROR_FAIL;
} }
breakpoint->set = brp_i + 1; breakpoint_hw_set(breakpoint, brp_i);
control = ((matchmode & 0x7) << 20) control = ((matchmode & 0x7) << 20)
| (byte_addr_select << 5) | (byte_addr_select << 5)
| (3 << 1) | 1; | (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 armv7a_common *armv7a = &cortex_a->armv7a_common;
struct cortex_a_brp *brp_list = cortex_a->brp_list; struct cortex_a_brp *brp_list = cortex_a->brp_list;
if (breakpoint->set) { if (breakpoint->is_set) {
LOG_WARNING("breakpoint already set"); LOG_WARNING("breakpoint already set");
return retval; return retval;
} }
@ -1436,7 +1436,7 @@ static int cortex_a_set_hybrid_breakpoint(struct target *target, struct breakpoi
return ERROR_FAIL; return ERROR_FAIL;
} }
breakpoint->set = brp_1 + 1; breakpoint_hw_set(breakpoint, brp_1);
breakpoint->linked_brp = brp_2; breakpoint->linked_brp = brp_2;
control_ctx = ((ctx_machmode & 0x7) << 20) control_ctx = ((ctx_machmode & 0x7) << 20)
| (brp_2 << 16) | (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 armv7a_common *armv7a = &cortex_a->armv7a_common;
struct cortex_a_brp *brp_list = cortex_a->brp_list; struct cortex_a_brp *brp_list = cortex_a->brp_list;
if (!breakpoint->set) { if (!breakpoint->is_set) {
LOG_WARNING("breakpoint not set"); LOG_WARNING("breakpoint not set");
return ERROR_OK; return ERROR_OK;
} }
if (breakpoint->type == BKPT_HARD) { if (breakpoint->type == BKPT_HARD) {
if ((breakpoint->address != 0) && (breakpoint->asid != 0)) { if ((breakpoint->address != 0) && (breakpoint->asid != 0)) {
int brp_i = breakpoint->set - 1; int brp_i = breakpoint->number;
int brp_j = breakpoint->linked_brp; 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"); LOG_DEBUG("Invalid BRP number in breakpoint");
return ERROR_OK; return ERROR_OK;
} }
@ -1533,12 +1533,12 @@ static int cortex_a_unset_breakpoint(struct target *target, struct breakpoint *b
if (retval != ERROR_OK) if (retval != ERROR_OK)
return retval; return retval;
breakpoint->linked_brp = 0; breakpoint->linked_brp = 0;
breakpoint->set = 0; breakpoint->is_set = false;
return ERROR_OK; return ERROR_OK;
} else { } else {
int brp_i = breakpoint->set - 1; int brp_i = breakpoint->number;
if ((brp_i < 0) || (brp_i >= cortex_a->brp_num)) { if (brp_i >= cortex_a->brp_num) {
LOG_DEBUG("Invalid BRP number in breakpoint"); LOG_DEBUG("Invalid BRP number in breakpoint");
return ERROR_OK; return ERROR_OK;
} }
@ -1557,7 +1557,7 @@ static int cortex_a_unset_breakpoint(struct target *target, struct breakpoint *b
brp_list[brp_i].value); brp_list[brp_i].value);
if (retval != ERROR_OK) if (retval != ERROR_OK)
return retval; return retval;
breakpoint->set = 0; breakpoint->is_set = false;
return ERROR_OK; return ERROR_OK;
} }
} else { } 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, armv7a_l1_i_cache_inval_virt(target, breakpoint->address,
breakpoint->length); breakpoint->length);
} }
breakpoint->set = 0; breakpoint->is_set = false;
return ERROR_OK; return ERROR_OK;
} }
@ -1655,7 +1655,7 @@ static int cortex_a_remove_breakpoint(struct target *target, struct breakpoint *
} }
#endif #endif
if (breakpoint->set) { if (breakpoint->is_set) {
cortex_a_unset_breakpoint(target, breakpoint); cortex_a_unset_breakpoint(target, breakpoint);
if (breakpoint->type == BKPT_HARD) if (breakpoint->type == BKPT_HARD)
cortex_a->brp_num_available++; 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 armv7a_common *armv7a = &cortex_a->armv7a_common;
struct cortex_a_wrp *wrp_list = cortex_a->wrp_list; struct cortex_a_wrp *wrp_list = cortex_a->wrp_list;
if (watchpoint->set) { if (watchpoint->is_set) {
LOG_WARNING("watchpoint already set"); LOG_WARNING("watchpoint already set");
return retval; return retval;
} }
@ -1741,7 +1741,7 @@ static int cortex_a_set_watchpoint(struct target *target, struct watchpoint *wat
break; break;
} }
watchpoint->set = wrp_i + 1; watchpoint_set(watchpoint, wrp_i);
control = (address_mask << 24) | control = (address_mask << 24) |
(byte_address_select << 5) | (byte_address_select << 5) |
(load_store_access_control << 3) | (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 armv7a_common *armv7a = &cortex_a->armv7a_common;
struct cortex_a_wrp *wrp_list = cortex_a->wrp_list; struct cortex_a_wrp *wrp_list = cortex_a->wrp_list;
if (!watchpoint->set) { if (!watchpoint->is_set) {
LOG_WARNING("watchpoint not set"); LOG_WARNING("watchpoint not set");
return ERROR_OK; return ERROR_OK;
} }
int wrp_i = watchpoint->set - 1; int wrp_i = watchpoint->number;
if (wrp_i < 0 || wrp_i >= cortex_a->wrp_num) { if (wrp_i >= cortex_a->wrp_num) {
LOG_DEBUG("Invalid WRP number in watchpoint"); LOG_DEBUG("Invalid WRP number in watchpoint");
return ERROR_OK; return ERROR_OK;
} }
@ -1809,7 +1809,7 @@ static int cortex_a_unset_watchpoint(struct target *target, struct watchpoint *w
wrp_list[wrp_i].value); wrp_list[wrp_i].value);
if (retval != ERROR_OK) if (retval != ERROR_OK)
return retval; return retval;
watchpoint->set = 0; watchpoint->is_set = false;
return ERROR_OK; 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); 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->wrp_num_available++;
cortex_a_unset_watchpoint(target, watchpoint); cortex_a_unset_watchpoint(target, watchpoint);
} }

View File

@ -185,7 +185,7 @@ static int cortex_m_load_core_reg_u32(struct target *target,
break; break;
cortex_m->slow_register_read = true; /* Polling (still) needed. */ cortex_m->slow_register_read = true; /* Polling (still) needed. */
if (timeval_ms() > then + DHCSR_S_REGRDY_TIMEOUT) { 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; return ERROR_TIMEOUT_REACHED;
} }
keep_alive(); keep_alive();
@ -223,7 +223,7 @@ static int cortex_m_slow_read_all_regs(struct target *target)
} }
if (!cortex_m->slow_register_read) 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; 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++) { for (unsigned int i = 0; i < wi; i++) {
if ((dhcsr[i] & S_REGRDY) == 0) { if ((dhcsr[i] & S_REGRDY) == 0) {
not_ready = true; 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]); 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; 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 */ unsigned int ri = 0; /* read index from r_vals array */
for (reg_id = 0; reg_id < num_regs; reg_id++) { 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) if (cortex_m->dcb_dhcsr & S_REGRDY)
break; break;
if (timeval_ms() > then + DHCSR_S_REGRDY_TIMEOUT) { 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; return ERROR_TIMEOUT_REACHED;
} }
keep_alive(); 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); retval = mem_ap_write_atomic_u32(armv7m->debug_ap, NVIC_DFSR, cortex_m->nvic_dfsr);
if (retval != ERROR_OK) if (retval != ERROR_OK)
return retval; 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; 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); retval = cortex_m_write_debug_halt_mask(target, C_STEP, C_HALT);
if (retval != ERROR_OK) if (retval != ERROR_OK)
return retval; return retval;
LOG_DEBUG(" "); LOG_TARGET_DEBUG(target, "single step");
/* restore dhcsr reg */ /* restore dhcsr reg */
cortex_m_clear_halt(target); 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); retval = mem_ap_read_atomic_u32(armv7m->debug_ap, DCB_DEMCR, &dcb_demcr);
if (retval != ERROR_OK) if (retval != ERROR_OK)
return retval; 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 */ /* this register is used for emulated dcc channel */
retval = mem_ap_write_u32(armv7m->debug_ap, DCB_DCRDR, 0); 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 */ /* Enable FPB */
retval = cortex_m_enable_fpb(target); retval = cortex_m_enable_fpb(target);
if (retval != ERROR_OK) { if (retval != ERROR_OK) {
LOG_ERROR("Failed to enable the FPB"); LOG_TARGET_ERROR(target, "Failed to enable the FPB");
return retval; return retval;
} }
@ -766,7 +766,7 @@ static int cortex_m_examine_exception_reason(struct target *target)
} }
retval = dap_run(swjdp); retval = dap_run(swjdp);
if (retval == ERROR_OK) 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, ", CFSR 0x%" PRIx32 ", AR 0x%" PRIx32,
armv7m_exception_string(armv7m->exception_number), armv7m_exception_string(armv7m->exception_number),
shcsr, except_sr, cfsr, except_ar); 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 arm *arm = &armv7m->arm;
struct reg *r; struct reg *r;
LOG_DEBUG(" "); LOG_TARGET_DEBUG(target, " ");
/* Do this really early to minimize the window where the MASKINTS erratum /* Do this really early to minimize the window where the MASKINTS erratum
* can pile up pending interrupts. */ * 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); retval = cortex_m_fast_read_all_regs(target);
if (retval == ERROR_TIMEOUT_REACHED) { if (retval == ERROR_TIMEOUT_REACHED) {
cortex_m->slow_register_read = true; 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) if (armv7m->exception_number)
cortex_m_examine_exception_reason(target); 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), arm_mode_name(arm->core_mode),
buf_get_u32(arm->pc->value, 0, 32), buf_get_u32(arm->pc->value, 0, 32),
secure_state ? "Secure" : "Non-Secure", secure_state ? "Secure" : "Non-Secure",
@ -889,8 +890,7 @@ static int cortex_m_poll(struct target *target)
* section B1.5.15 "Unrecoverable exception cases". * section B1.5.15 "Unrecoverable exception cases".
*/ */
if (cortex_m->dcb_dhcsr & S_LOCKUP) { if (cortex_m->dcb_dhcsr & S_LOCKUP) {
LOG_ERROR("%s -- clearing lockup after double fault", LOG_TARGET_ERROR(target, "clearing lockup after double fault");
target_name(target));
cortex_m_write_debug_halt_mask(target, C_HALT, 0); cortex_m_write_debug_halt_mask(target, C_HALT, 0);
target->debug_reason = DBG_REASON_DBGRQ; 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; cortex_m->dcb_dhcsr_cumulated_sticky &= ~S_RESET_ST;
if (target->state != TARGET_RESET) { if (target->state != TARGET_RESET) {
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; return ERROR_OK;
} }
@ -918,7 +918,7 @@ static int cortex_m_poll(struct target *target)
/* Cannot switch context while running so endreset is /* Cannot switch context while running so endreset is
* called with target->state == TARGET_RESET * 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); cortex_m->dcb_dhcsr);
retval = cortex_m_endreset_event(target); retval = cortex_m_endreset_event(target);
if (retval != ERROR_OK) { if (retval != ERROR_OK) {
@ -943,7 +943,6 @@ static int cortex_m_poll(struct target *target)
target_call_event_callbacks(target, TARGET_EVENT_HALTED); target_call_event_callbacks(target, TARGET_EVENT_HALTED);
} }
if (prev_target_state == TARGET_DEBUG_RUNNING) { if (prev_target_state == TARGET_DEBUG_RUNNING) {
LOG_DEBUG(" ");
retval = cortex_m_debug_entry(target); retval = cortex_m_debug_entry(target);
if (retval != ERROR_OK) if (retval != ERROR_OK)
return retval; return retval;
@ -971,7 +970,7 @@ static int cortex_m_poll(struct target *target)
register_cache_invalidate(armv7m->arm.core_cache); register_cache_invalidate(armv7m->arm.core_cache);
target->state = TARGET_RUNNING; 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); target_call_event_callbacks(target, TARGET_EVENT_RESUMED);
retval = ERROR_OK; retval = ERROR_OK;
} }
@ -984,20 +983,19 @@ static int cortex_m_poll(struct target *target)
static int cortex_m_halt(struct target *target) static int cortex_m_halt(struct target *target)
{ {
LOG_DEBUG("target->state: %s", LOG_TARGET_DEBUG(target, "target->state: %s", target_state_name(target));
target_state_name(target));
if (target->state == TARGET_HALTED) { if (target->state == TARGET_HALTED) {
LOG_DEBUG("target was already halted"); LOG_TARGET_DEBUG(target, "target was already halted");
return ERROR_OK; return ERROR_OK;
} }
if (target->state == TARGET_UNKNOWN) 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 (target->state == TARGET_RESET) {
if ((jtag_get_reset_config() & RESET_SRST_PULLS_TRST) && jtag_get_srst()) { 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; return ERROR_TARGET_FAILURE;
} else { } else {
/* we came here in a reset_halt or reset_init sequence /* 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'. * 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 * As this reset only uses VC_CORERESET it would only ever reset the cortex_m
* core, not the peripherals */ * 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) { 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; return ERROR_FAIL;
} }
@ -1068,16 +1066,17 @@ static int cortex_m_soft_reset_halt(struct target *target)
return retval; return retval;
if ((cortex_m->dcb_dhcsr & S_HALT) if ((cortex_m->dcb_dhcsr & S_HALT)
&& (cortex_m->nvic_dfsr & DFSR_VCATCH)) { && (cortex_m->nvic_dfsr & DFSR_VCATCH)) {
LOG_DEBUG("system reset-halted, DHCSR 0x%08" PRIx32 ", DFSR 0x%08" PRIx32, 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->dcb_dhcsr, cortex_m->nvic_dfsr);
cortex_m_poll(target); cortex_m_poll(target);
/* FIXME restore user's vector catch config */ /* FIXME restore user's vector catch config */
return ERROR_OK; return ERROR_OK;
} else } else {
LOG_DEBUG("waiting for system reset-halt, " LOG_TARGET_DEBUG(target, "waiting for system reset-halt, "
"DHCSR 0x%08" PRIx32 ", %d ms", "DHCSR 0x%08" PRIx32 ", %d ms",
cortex_m->dcb_dhcsr, timeout); cortex_m->dcb_dhcsr, timeout);
} }
}
timeout++; timeout++;
alive_sleep(1); alive_sleep(1);
} }
@ -1091,7 +1090,7 @@ void cortex_m_enable_breakpoints(struct target *target)
/* set any pending breakpoints */ /* set any pending breakpoints */
while (breakpoint) { while (breakpoint) {
if (!breakpoint->set) if (!breakpoint->is_set)
cortex_m_set_breakpoint(target, breakpoint); cortex_m_set_breakpoint(target, breakpoint);
breakpoint = breakpoint->next; breakpoint = breakpoint->next;
} }
@ -1106,7 +1105,7 @@ static int cortex_m_resume(struct target *target, int current,
struct reg *r; struct reg *r;
if (target->state != TARGET_HALTED) { if (target->state != TARGET_HALTED) {
LOG_WARNING("target not halted"); LOG_TARGET_WARNING(target, "target not halted");
return ERROR_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 */ /* Single step past breakpoint at current address */
breakpoint = breakpoint_find(target, resume_pc); breakpoint = breakpoint_find(target, resume_pc);
if (breakpoint) { 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->address,
breakpoint->unique_id); breakpoint->unique_id);
cortex_m_unset_breakpoint(target, breakpoint); cortex_m_unset_breakpoint(target, breakpoint);
@ -1191,11 +1190,11 @@ static int cortex_m_resume(struct target *target, int current,
if (!debug_execution) { if (!debug_execution) {
target->state = TARGET_RUNNING; target->state = TARGET_RUNNING;
target_call_event_callbacks(target, TARGET_EVENT_RESUMED); 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 { } else {
target->state = TARGET_DEBUG_RUNNING; target->state = TARGET_DEBUG_RUNNING;
target_call_event_callbacks(target, TARGET_EVENT_DEBUG_RESUMED); 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; return ERROR_OK;
@ -1214,7 +1213,7 @@ static int cortex_m_step(struct target *target, int current,
bool isr_timed_out = false; bool isr_timed_out = false;
if (target->state != TARGET_HALTED) { if (target->state != TARGET_HALTED) {
LOG_WARNING("target not halted"); LOG_TARGET_WARNING(target, "target not halted");
return ERROR_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)) { 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_HALT | C_MASKINTS, 0);
cortex_m_write_debug_halt_mask(target, C_STEP, C_HALT); cortex_m_write_debug_halt_mask(target, C_STEP, C_HALT);
/* Re-enable interrupts if appropriate */ /* 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); cortex_m_set_maskints_for_halt(target);
} else { } else {
/* Start the core */ /* 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(); int64_t t_start = timeval_ms();
cortex_m_set_maskints_for_run(target); cortex_m_set_maskints_for_run(target);
cortex_m_write_debug_halt_mask(target, 0, C_HALT | C_STEP); 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) { 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"); "leaving target running");
} else { } else {
/* Step over next instruction with interrupts disabled */ /* Step over next instruction with interrupts disabled */
@ -1377,7 +1376,7 @@ static int cortex_m_step(struct target *target, int current,
return ERROR_OK; 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, " nvic_icsr = 0x%" PRIx32,
cortex_m->dcb_dhcsr, cortex_m->nvic_icsr); cortex_m->dcb_dhcsr, cortex_m->nvic_icsr);
@ -1386,7 +1385,7 @@ static int cortex_m_step(struct target *target, int current,
return retval; return retval;
target_call_event_callbacks(target, TARGET_EVENT_HALTED); 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, " nvic_icsr = 0x%" PRIx32,
cortex_m->dcb_dhcsr, cortex_m->nvic_icsr); 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; struct armv7m_common *armv7m = &cortex_m->armv7m;
enum cortex_m_soft_reset_config reset_config = cortex_m->soft_reset_config; 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)); target_state_name(target));
enum reset_types jtag_reset_config = jtag_get_reset_config(); 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) { if (jtag_reset_config & RESET_HAS_SRST) {
adapter_assert_reset(); adapter_assert_reset();
if (target->reset_halt) 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; return ERROR_OK;
} else { } else {
LOG_ERROR("Target not examined, reset NOT asserted!"); LOG_TARGET_ERROR(target, "Target not examined, reset NOT asserted!");
return ERROR_FAIL; 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, retval2 = mem_ap_write_atomic_u32(armv7m->debug_ap, DCB_DEMCR,
TRCENA | VC_HARDERR | VC_BUSERR | VC_CORERESET); TRCENA | VC_HARDERR | VC_BUSERR | VC_CORERESET);
if (retval != ERROR_OK || retval2 != ERROR_OK) 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) { 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 if (!cortex_m->vectreset_supported
&& reset_config == CORTEX_M_RESET_VECTRESET) { && reset_config == CORTEX_M_RESET_VECTRESET) {
reset_config = CORTEX_M_RESET_SYSRESETREQ; reset_config = CORTEX_M_RESET_SYSRESETREQ;
LOG_WARNING("VECTRESET is not supported on this Cortex-M core, using SYSRESETREQ instead."); LOG_TARGET_WARNING(target, "VECTRESET is not supported on this Cortex-M core, using SYSRESETREQ instead.");
LOG_WARNING("Set 'cortex_m reset_config sysresetreq'."); 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"); ? "SYSRESETREQ" : "VECTRESET");
if (reset_config == CORTEX_M_RESET_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."); "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_VECTKEY | ((reset_config == CORTEX_M_RESET_SYSRESETREQ)
? AIRCR_SYSRESETREQ : AIRCR_VECTRESET)); ? AIRCR_SYSRESETREQ : AIRCR_VECTRESET));
if (retval3 != ERROR_OK) 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); retval3 = dap_dp_init_or_reconnect(armv7m->debug_ap->dap);
if (retval3 != ERROR_OK) { 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. /* The error return value must not be propagated in this case.
* SYSRESETREQ or VECTRESET have been possibly triggered * SYSRESETREQ or VECTRESET have been possibly triggered
* so reset processing should continue */ * 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; 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)); target_state_name(target));
/* deassert reset lines */ /* 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); int retval = dap_dp_init_or_reconnect(armv7m->debug_ap->dap);
if (retval != ERROR_OK) { if (retval != ERROR_OK) {
LOG_ERROR("DP initialisation failed"); LOG_TARGET_ERROR(target, "DP initialisation failed");
return retval; 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_common *cortex_m = target_to_cm(target);
struct cortex_m_fp_comparator *comparator_list = cortex_m->fp_comparator_list; struct cortex_m_fp_comparator *comparator_list = cortex_m->fp_comparator_list;
if (breakpoint->set) { if (breakpoint->is_set) {
LOG_WARNING("breakpoint (BPID: %" PRIu32 ") already set", breakpoint->unique_id); LOG_TARGET_WARNING(target, "breakpoint (BPID: %" PRIu32 ") already set", breakpoint->unique_id);
return ERROR_OK; 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)) while (comparator_list[fp_num].used && (fp_num < cortex_m->fp_num_code))
fp_num++; fp_num++;
if (fp_num >= cortex_m->fp_num_code) { 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; return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
} }
breakpoint->set = fp_num + 1; breakpoint_hw_set(breakpoint, fp_num);
fpcr_value = breakpoint->address | 1; fpcr_value = breakpoint->address | 1;
if (cortex_m->fp_rev == 0) { if (cortex_m->fp_rev == 0) {
if (breakpoint->address > 0x1FFFFFFF) { 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; return ERROR_FAIL;
} }
uint32_t hilo; uint32_t hilo;
hilo = (breakpoint->address & 0x2) ? FPCR_REPLACE_BKPT_HIGH : FPCR_REPLACE_BKPT_LOW; hilo = (breakpoint->address & 0x2) ? FPCR_REPLACE_BKPT_HIGH : FPCR_REPLACE_BKPT_LOW;
fpcr_value = (fpcr_value & 0x1FFFFFFC) | hilo | 1; fpcr_value = (fpcr_value & 0x1FFFFFFC) | hilo | 1;
} else if (cortex_m->fp_rev > 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; return ERROR_FAIL;
} }
comparator_list[fp_num].used = true; comparator_list[fp_num].used = true;
comparator_list[fp_num].fpcr_value = fpcr_value; comparator_list[fp_num].fpcr_value = fpcr_value;
target_write_u32(target, comparator_list[fp_num].fpcr_address, target_write_u32(target, comparator_list[fp_num].fpcr_address,
comparator_list[fp_num].fpcr_value); 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, fp_num,
comparator_list[fp_num].fpcr_value); comparator_list[fp_num].fpcr_value);
if (!cortex_m->fpb_enabled) { 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); retval = cortex_m_enable_fpb(target);
if (retval != ERROR_OK) { if (retval != ERROR_OK) {
LOG_ERROR("Failed to enable the FPB"); LOG_TARGET_ERROR(target, "Failed to enable the FPB");
return retval; return retval;
} }
@ -1643,15 +1643,15 @@ int cortex_m_set_breakpoint(struct target *target, struct breakpoint *breakpoint
code); code);
if (retval != ERROR_OK) if (retval != ERROR_OK)
return retval; 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, breakpoint->unique_id,
(int)(breakpoint->type), (int)(breakpoint->type),
breakpoint->address, breakpoint->address,
breakpoint->length, breakpoint->length,
breakpoint->set); (breakpoint->type == BKPT_SOFT) ? 0 : breakpoint->number);
return ERROR_OK; 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_common *cortex_m = target_to_cm(target);
struct cortex_m_fp_comparator *comparator_list = cortex_m->fp_comparator_list; struct cortex_m_fp_comparator *comparator_list = cortex_m->fp_comparator_list;
if (breakpoint->set <= 0) { if (!breakpoint->is_set) {
LOG_WARNING("breakpoint not set"); LOG_TARGET_WARNING(target, "breakpoint not set");
return ERROR_OK; 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, breakpoint->unique_id,
(int)(breakpoint->type), (int)(breakpoint->type),
breakpoint->address, breakpoint->address,
breakpoint->length, breakpoint->length,
breakpoint->set); (breakpoint->type == BKPT_SOFT) ? 0 : breakpoint->number);
if (breakpoint->type == BKPT_HARD) { 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) { 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; return ERROR_OK;
} }
comparator_list[fp_num].used = false; 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) if (retval != ERROR_OK)
return retval; return retval;
} }
breakpoint->set = false; breakpoint->is_set = false;
return ERROR_OK; 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) int cortex_m_add_breakpoint(struct target *target, struct breakpoint *breakpoint)
{ {
if (breakpoint->length == 3) { 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; breakpoint->length = 2;
} }
if ((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; 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) int cortex_m_remove_breakpoint(struct target *target, struct breakpoint *breakpoint)
{ {
if (!breakpoint->set) if (!breakpoint->is_set)
return ERROR_OK; return ERROR_OK;
return cortex_m_unset_breakpoint(target, breakpoint); 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++) comparator++, dwt_num++)
continue; continue;
if (dwt_num >= cortex_m->dwt_num_comp) { 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; return ERROR_FAIL;
} }
comparator->used = true; comparator->used = true;
watchpoint->set = dwt_num + 1; watchpoint_set(watchpoint, dwt_num);
comparator->comp = watchpoint->address; comparator->comp = watchpoint->address;
target_write_u32(target, comparator->dwt_comparator_address + 0, 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, target_write_u32(target, comparator->dwt_comparator_address + 8,
comparator->function); 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, watchpoint->unique_id, dwt_num,
(unsigned) comparator->comp, (unsigned) comparator->comp,
(unsigned) comparator->mask, (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_common *cortex_m = target_to_cm(target);
struct cortex_m_dwt_comparator *comparator; struct cortex_m_dwt_comparator *comparator;
if (watchpoint->set <= 0) { if (!watchpoint->is_set) {
LOG_WARNING("watchpoint (wpid: %d) not set", LOG_TARGET_WARNING(target, "watchpoint (wpid: %d) not set",
watchpoint->unique_id); watchpoint->unique_id);
return ERROR_OK; 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, watchpoint->unique_id, dwt_num,
(unsigned) watchpoint->address); (unsigned) watchpoint->address);
if (dwt_num >= cortex_m->dwt_num_comp) { 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; 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, target_write_u32(target, comparator->dwt_comparator_address + 8,
comparator->function); comparator->function);
watchpoint->set = false; watchpoint->is_set = false;
return ERROR_OK; 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); struct cortex_m_common *cortex_m = target_to_cm(target);
if (cortex_m->dwt_comp_available < 1) { if (cortex_m->dwt_comp_available < 1) {
LOG_DEBUG("no comparators?"); LOG_TARGET_DEBUG(target, "no comparators?");
return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
} }
/* hardware doesn't support data value masking */ /* hardware doesn't support data value masking */
if (watchpoint->mask != ~(uint32_t)0) { 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; return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
} }
@ -1859,11 +1859,11 @@ int cortex_m_add_watchpoint(struct target *target, struct watchpoint *watchpoint
break; break;
} }
if (mask == 16) { if (mask == 16) {
LOG_DEBUG("unsupported watchpoint length"); LOG_TARGET_DEBUG(target, "unsupported watchpoint length");
return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
} }
if (watchpoint->address & ((1 << mask) - 1)) { 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; 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. * the data, and another comparator (DATAVADDR0) matching addr.
*/ */
if (watchpoint->value) { 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; return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
} }
cortex_m->dwt_comp_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; 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 ... */ /* REVISIT why check? DWT can be updated with core running ... */
if (target->state != TARGET_HALTED) { if (target->state != TARGET_HALTED) {
LOG_WARNING("target not halted"); LOG_TARGET_WARNING(target, "target not halted");
return ERROR_TARGET_NOT_HALTED; return ERROR_TARGET_NOT_HALTED;
} }
if (watchpoint->set) if (watchpoint->is_set)
cortex_m_unset_watchpoint(target, watchpoint); cortex_m_unset_watchpoint(target, watchpoint);
cortex_m->dwt_comp_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; 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); struct cortex_m_common *cortex_m = target_to_cm(target);
for (struct watchpoint *wp = target->watchpoints; wp; wp = wp->next) { for (struct watchpoint *wp = target->watchpoints; wp; wp = wp->next) {
if (!wp->set) if (!wp->is_set)
continue; 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; struct cortex_m_dwt_comparator *comparator = cortex_m->dwt_comparator_list + dwt_num;
uint32_t dwt_function; uint32_t dwt_function;
@ -1939,7 +1939,7 @@ void cortex_m_enable_watchpoints(struct target *target)
/* set any pending watchpoints */ /* set any pending watchpoints */
while (watchpoint) { while (watchpoint) {
if (!watchpoint->set) if (!watchpoint->is_set)
cortex_m_set_watchpoint(target, watchpoint); cortex_m_set_watchpoint(target, watchpoint);
watchpoint = watchpoint->next; watchpoint = watchpoint->next;
} }
@ -2004,18 +2004,18 @@ int cortex_m_profiling(struct target *target, uint32_t *samples,
retval = target_read_u32(target, DWT_PCSR, &reg_value); retval = target_read_u32(target, DWT_PCSR, &reg_value);
if (retval != ERROR_OK) { if (retval != ERROR_OK) {
LOG_ERROR("Error while reading PCSR"); LOG_TARGET_ERROR(target, "Error while reading PCSR");
return retval; return retval;
} }
if (reg_value == 0) { 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); return target_profiling_default(target, samples, max_num_samples, num_samples, seconds);
} }
gettimeofday(&timeout, NULL); gettimeofday(&timeout, NULL);
timeval_add_time(&timeout, seconds, 0); 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 */ /* Make sure the target is running */
target_poll(target); 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); retval = target_resume(target, 1, 0, 0, 0);
if (retval != ERROR_OK) { if (retval != ERROR_OK) {
LOG_ERROR("Error while resuming target"); LOG_TARGET_ERROR(target, "Error while resuming target");
return retval; return retval;
} }
@ -2044,14 +2044,14 @@ int cortex_m_profiling(struct target *target, uint32_t *samples,
} }
if (retval != ERROR_OK) { if (retval != ERROR_OK) {
LOG_ERROR("Error while reading PCSR"); LOG_TARGET_ERROR(target, "Error while reading PCSR");
return retval; return retval;
} }
gettimeofday(&now, NULL); gettimeofday(&now, NULL);
if (sample_count >= max_num_samples || timeval_compare(&now, &timeout) > 0) { 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; break;
} }
} }
@ -2162,14 +2162,14 @@ static void cortex_m_dwt_setup(struct cortex_m_common *cm, struct target *target
int reg; int reg;
target_read_u32(target, DWT_CTRL, &dwtcr); 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) { if (!dwtcr) {
LOG_DEBUG("no DWT"); LOG_TARGET_DEBUG(target, "no DWT");
return; return;
} }
target_read_u32(target, DWT_DEVARCH, &cm->dwt_devarch); 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_num_comp = (dwtcr >> 28) & 0xF;
cm->dwt_comp_available = cm->dwt_num_comp; 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) { if (!cm->dwt_comparator_list) {
fail0: fail0:
cm->dwt_num_comp = 0; cm->dwt_num_comp = 0;
LOG_ERROR("out of mem"); LOG_TARGET_ERROR(target, "out of mem");
return; return;
} }
@ -2216,7 +2216,7 @@ fail1:
*register_get_last_cache_p(&target->reg_cache) = cache; *register_get_last_cache_p(&target->reg_cache) = cache;
cm->dwt_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, cm->dwt_num_comp,
(dwtcr & (0xf << 24)) ? " only" : "/trigger"); (dwtcr & (0xf << 24)) ? " only" : "/trigger");
@ -2283,7 +2283,7 @@ int cortex_m_examine(struct target *target)
/* Search for the MEM-AP */ /* Search for the MEM-AP */
retval = cortex_m_find_mem_ap(swjdp, &armv7m->debug_ap); retval = cortex_m_find_mem_ap(swjdp, &armv7m->debug_ap);
if (retval != ERROR_OK) { 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; return retval;
} }
} else { } else {
@ -2316,14 +2316,13 @@ int cortex_m_examine(struct target *target)
} }
if (!cortex_m->core_info) { 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; return ERROR_FAIL;
} }
armv7m->arm.arch = cortex_m->core_info->arch; armv7m->arm.arch = cortex_m->core_info->arch;
LOG_INFO("%s: %s r%" PRId8 "p%" PRId8 " processor detected", LOG_TARGET_INFO(target, "%s r%" PRId8 "p%" PRId8 " processor detected",
target_name(target),
cortex_m->core_info->name, cortex_m->core_info->name,
(uint8_t)((cpuid >> 20) & 0xf), (uint8_t)((cpuid >> 20) & 0xf),
(uint8_t)((cpuid >> 0) & 0xf)); (uint8_t)((cpuid >> 0) & 0xf));
@ -2334,11 +2333,11 @@ int cortex_m_examine(struct target *target)
rev = (cpuid >> 20) & 0xf; rev = (cpuid >> 20) & 0xf;
patch = (cpuid >> 0) & 0xf; patch = (cpuid >> 0) & 0xf;
if ((rev == 0) && (patch < 2)) { 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; 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) { if (cortex_m->core_info->flags & CORTEX_M_F_HAS_FPV4) {
target_read_u32(target, MVFR0, &mvfr0); 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 */ /* test for floating point feature on Cortex-M4 */
if ((mvfr0 == MVFR0_DEFAULT_M4) && (mvfr1 == MVFR1_DEFAULT_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; armv7m->fp_feature = FPV4_SP;
} }
} else if (cortex_m->core_info->flags & CORTEX_M_F_HAS_FPV5) { } 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 */ /* test for floating point features on Cortex-M7 */
if ((mvfr0 == MVFR0_DEFAULT_M7_SP) && (mvfr1 == MVFR1_DEFAULT_M7_SP)) { 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; armv7m->fp_feature = FPV5_SP;
} else if ((mvfr0 == MVFR0_DEFAULT_M7_DP) && (mvfr1 == MVFR1_DEFAULT_M7_DP)) { } 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; 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 */ /* make sure we clear any breakpoints enabled on the target */
target_write_u32(target, cortex_m->fp_comparator_list[i].fpcr_address, 0); 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, fpcr,
cortex_m->fp_num_code, cortex_m->fp_num_code,
cortex_m->fp_num_lit); cortex_m->fp_num_lit);
@ -2438,8 +2437,7 @@ int cortex_m_examine(struct target *target)
cortex_m_dwt_setup(cortex_m, target); cortex_m_dwt_setup(cortex_m, target);
/* These hardware breakpoints only work for code in flash! */ /* These hardware breakpoints only work for code in flash! */
LOG_INFO("%s: target has %d breakpoints, %d watchpoints", LOG_TARGET_INFO(target, "target has %d breakpoints, %d watchpoints",
target_name(target),
cortex_m->fp_num_code, cortex_m->fp_num_code,
cortex_m->dwt_num_comp); 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; *ctrl = (uint8_t)dcrdr;
*value = (uint8_t)(dcrdr >> 8); *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 /* write ack back to software dcc register
* signify we have read data */ * 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)); struct cortex_m_common *cortex_m = calloc(1, sizeof(struct cortex_m_common));
if (!cortex_m) { if (!cortex_m) {
LOG_ERROR("No memory creating target"); LOG_TARGET_ERROR(target, "No memory creating target");
return ERROR_FAIL; return ERROR_FAIL;
} }
@ -2626,7 +2624,7 @@ COMMAND_HANDLER(handle_cortex_m_vector_catch_command)
return retval; return retval;
if (!target_was_examined(target)) { if (!target_was_examined(target)) {
LOG_ERROR("Target not examined yet"); LOG_TARGET_ERROR(target, "Target not examined yet");
return ERROR_FAIL; return ERROR_FAIL;
} }
@ -2655,7 +2653,7 @@ COMMAND_HANDLER(handle_cortex_m_vector_catch_command)
break; break;
} }
if (i == ARRAY_SIZE(vec_ids)) { 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; return ERROR_COMMAND_SYNTAX_ERROR;
} }
} }
@ -2745,7 +2743,7 @@ COMMAND_HANDLER(handle_cortex_m_reset_config_command)
else if (strcmp(*CMD_ARGV, "vectreset") == 0) { else if (strcmp(*CMD_ARGV, "vectreset") == 0) {
if (target_was_examined(target) if (target_was_examined(target)
&& !cortex_m->vectreset_supported) && !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 else
cortex_m->soft_reset_config = CORTEX_M_RESET_VECTRESET; cortex_m->soft_reset_config = CORTEX_M_RESET_VECTRESET;

View File

@ -504,7 +504,7 @@ static int esirisc_add_breakpoint(struct target *target, struct breakpoint *brea
return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
} }
breakpoint->set = bp_index + 1; breakpoint_hw_set(breakpoint, bp_index);
esirisc->breakpoints_p[bp_index] = breakpoint; esirisc->breakpoints_p[bp_index] = breakpoint;
/* specify instruction breakpoint address */ /* specify instruction breakpoint address */
@ -540,7 +540,7 @@ static int esirisc_add_breakpoints(struct target *target)
LOG_DEBUG("-"); LOG_DEBUG("-");
while (breakpoint) { while (breakpoint) {
if (breakpoint->set == 0) if (!breakpoint->is_set)
esirisc_add_breakpoint(target, breakpoint); esirisc_add_breakpoint(target, breakpoint);
breakpoint = breakpoint->next; 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_common *esirisc = target_to_esirisc(target);
struct esirisc_jtag *jtag_info = &esirisc->jtag_info; struct esirisc_jtag *jtag_info = &esirisc->jtag_info;
int bp_index = breakpoint->set - 1; unsigned int bp_index = breakpoint->number;
uint32_t ibc; uint32_t ibc;
int retval; int retval;
@ -575,7 +575,7 @@ static int esirisc_remove_breakpoint(struct target *target, struct breakpoint *b
} }
esirisc->breakpoints_p[bp_index] = NULL; esirisc->breakpoints_p[bp_index] = NULL;
breakpoint->set = 0; breakpoint->is_set = false;
return ERROR_OK; return ERROR_OK;
} }
@ -630,7 +630,7 @@ static int esirisc_add_watchpoint(struct target *target, struct watchpoint *watc
return ERROR_FAIL; return ERROR_FAIL;
} }
watchpoint->set = wp_index + 1; watchpoint_set(watchpoint, wp_index);
esirisc->watchpoints_p[wp_index] = watchpoint; esirisc->watchpoints_p[wp_index] = watchpoint;
/* specify data breakpoint address */ /* specify data breakpoint address */
@ -724,7 +724,7 @@ static int esirisc_add_watchpoints(struct target *target)
LOG_DEBUG("-"); LOG_DEBUG("-");
while (watchpoint) { while (watchpoint) {
if (watchpoint->set == 0) if (!watchpoint->is_set)
esirisc_add_watchpoint(target, watchpoint); esirisc_add_watchpoint(target, watchpoint);
watchpoint = watchpoint->next; 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_common *esirisc = target_to_esirisc(target);
struct esirisc_jtag *jtag_info = &esirisc->jtag_info; struct esirisc_jtag *jtag_info = &esirisc->jtag_info;
int wp_index = watchpoint->set - 1; unsigned int wp_index = watchpoint->number;
uint32_t dbc; uint32_t dbc;
int retval; int retval;
@ -759,7 +759,7 @@ static int esirisc_remove_watchpoint(struct target *target, struct watchpoint *w
} }
esirisc->watchpoints_p[wp_index] = NULL; esirisc->watchpoints_p[wp_index] = NULL;
watchpoint->set = 0; watchpoint->is_set = false;
return ERROR_OK; return ERROR_OK;
} }

View File

@ -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 */ /* if breakpoints are enabled, we need to redirect these into probe mode */
struct breakpoint *activeswbp = t->breakpoints; struct breakpoint *activeswbp = t->breakpoints;
while (activeswbp && activeswbp->set == 0) while (activeswbp && !activeswbp->is_set)
activeswbp = activeswbp->next; activeswbp = activeswbp->next;
struct watchpoint *activehwbp = t->watchpoints; struct watchpoint *activehwbp = t->watchpoints;
while (activehwbp && activehwbp->set == 0) while (activehwbp && !activehwbp->is_set)
activehwbp = activehwbp->next; activehwbp = activehwbp->next;
if (activeswbp || activehwbp) if (activeswbp || activehwbp)
buf_set_u32(x86_32->cache->reg_list[PMCR].value, 0, 32, 1); buf_set_u32(x86_32->cache->reg_list[PMCR].value, 0, 32, 1);

View File

@ -593,7 +593,7 @@ static void mips_m4k_enable_breakpoints(struct target *target)
/* set any pending breakpoints */ /* set any pending breakpoints */
while (breakpoint) { while (breakpoint) {
if (breakpoint->set == 0) if (!breakpoint->is_set)
mips_m4k_set_breakpoint(target, breakpoint); mips_m4k_set_breakpoint(target, breakpoint);
breakpoint = breakpoint->next; 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; struct mips32_comparator *comparator_list = mips32->inst_break_list;
int retval; int retval;
if (breakpoint->set) { if (breakpoint->is_set) {
LOG_WARNING("breakpoint already set"); LOG_WARNING("breakpoint already set");
return ERROR_OK; return ERROR_OK;
} }
@ -622,7 +622,7 @@ static int mips_m4k_set_breakpoint(struct target *target,
breakpoint->unique_id); breakpoint->unique_id);
return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; 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].used = 1;
comparator_list[bp_num].bp_value = breakpoint->address; 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; 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; struct mips32_comparator *comparator_list = mips32->inst_break_list;
int retval; int retval;
if (!breakpoint->set) { if (!breakpoint->is_set) {
LOG_WARNING("breakpoint not set"); LOG_WARNING("breakpoint not set");
return ERROR_OK; return ERROR_OK;
} }
if (breakpoint->type == BKPT_HARD) { if (breakpoint->type == BKPT_HARD) {
int bp_num = breakpoint->set - 1; int bp_num = breakpoint->number;
if ((bp_num < 0) || (bp_num >= mips32->num_inst_bpoints)) { if (bp_num >= mips32->num_inst_bpoints) {
LOG_DEBUG("Invalid FP Comparator number in breakpoint (bpid: %" PRIu32 ")", LOG_DEBUG("Invalid FP Comparator number in breakpoint (bpid: %" PRIu32 ")",
breakpoint->unique_id); breakpoint->unique_id);
return ERROR_OK; 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; return ERROR_OK;
} }
@ -851,7 +851,7 @@ static int mips_m4k_remove_breakpoint(struct target *target,
return ERROR_TARGET_NOT_HALTED; return ERROR_TARGET_NOT_HALTED;
} }
if (breakpoint->set) if (breakpoint->is_set)
mips_m4k_unset_breakpoint(target, breakpoint); mips_m4k_unset_breakpoint(target, breakpoint);
if (breakpoint->type == BKPT_HARD) 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 | int enable = EJTAG_DBCN_NOSB | EJTAG_DBCN_NOLB | EJTAG_DBCN_BE |
(0xff << EJTAG_DBCN_BLM_SHIFT); (0xff << EJTAG_DBCN_BLM_SHIFT);
if (watchpoint->set) { if (watchpoint->is_set) {
LOG_WARNING("watchpoint already set"); LOG_WARNING("watchpoint already set");
return ERROR_OK; 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"); 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].used = 1;
comparator_list[wp_num].bp_value = watchpoint->address; 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 mips_ejtag *ejtag_info = &mips32->ejtag_info;
struct mips32_comparator *comparator_list = mips32->data_break_list; struct mips32_comparator *comparator_list = mips32->data_break_list;
if (!watchpoint->set) { if (!watchpoint->is_set) {
LOG_WARNING("watchpoint not set"); LOG_WARNING("watchpoint not set");
return ERROR_OK; return ERROR_OK;
} }
int wp_num = watchpoint->set - 1; int wp_num = watchpoint->number;
if ((wp_num < 0) || (wp_num >= mips32->num_data_bpoints)) { if (wp_num >= mips32->num_data_bpoints) {
LOG_DEBUG("Invalid FP Comparator number in watchpoint"); LOG_DEBUG("Invalid FP Comparator number in watchpoint");
return ERROR_OK; return ERROR_OK;
} }
@ -960,7 +960,7 @@ static int mips_m4k_unset_watchpoint(struct target *target,
comparator_list[wp_num].bp_value = 0; comparator_list[wp_num].bp_value = 0;
target_write_u32(target, comparator_list[wp_num].reg_address + target_write_u32(target, comparator_list[wp_num].reg_address +
ejtag_info->ejtag_dbc_offs, 0); ejtag_info->ejtag_dbc_offs, 0);
watchpoint->set = 0; watchpoint->is_set = false;
return ERROR_OK; return ERROR_OK;
} }
@ -991,7 +991,7 @@ static int mips_m4k_remove_watchpoint(struct target *target,
return ERROR_TARGET_NOT_HALTED; return ERROR_TARGET_NOT_HALTED;
} }
if (watchpoint->set) if (watchpoint->is_set)
mips_m4k_unset_watchpoint(target, watchpoint); mips_m4k_unset_watchpoint(target, watchpoint);
mips32->num_data_bpoints_avail++; mips32->num_data_bpoints_avail++;
@ -1005,7 +1005,7 @@ static void mips_m4k_enable_watchpoints(struct target *target)
/* set any pending watchpoints */ /* set any pending watchpoints */
while (watchpoint) { while (watchpoint) {
if (watchpoint->set == 0) if (!watchpoint->is_set)
mips_m4k_set_watchpoint(target, watchpoint); mips_m4k_set_watchpoint(target, watchpoint);
watchpoint = watchpoint->next; watchpoint = watchpoint->next;
} }

View File

@ -346,7 +346,7 @@ static int mips_mips64_set_breakpoint(struct target *target,
{ {
int retval; int retval;
if (bp->set) { if (bp->is_set) {
LOG_WARNING("breakpoint already set"); LOG_WARNING("breakpoint already set");
return ERROR_OK; return ERROR_OK;
} }
@ -373,7 +373,7 @@ static int mips_mips64_set_breakpoint(struct target *target,
return retval; return retval;
} }
bp->set = true; bp->is_set = true;
return ERROR_OK; return ERROR_OK;
} }
@ -385,7 +385,7 @@ static int mips_mips64_enable_breakpoints(struct target *target)
/* set any pending breakpoints */ /* set any pending breakpoints */
while (bp) { while (bp) {
if (!bp->set) { if (!bp->is_set) {
retval = mips_mips64_set_breakpoint(target, bp); retval = mips_mips64_set_breakpoint(target, bp);
if (retval != ERROR_OK) if (retval != ERROR_OK)
return retval; 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 int enable = EJTAG_DBCN_NOSB | EJTAG_DBCN_NOLB | EJTAG_DBCN_BE
| (0xff << EJTAG_DBCN_BLM_SHIFT); | (0xff << EJTAG_DBCN_BLM_SHIFT);
if (watchpoint->set) { if (watchpoint->is_set) {
LOG_WARNING("watchpoint already set"); LOG_WARNING("watchpoint already set");
return ERROR_OK; return ERROR_OK;
} }
@ -451,7 +451,7 @@ static int mips_mips64_set_watchpoint(struct target *target,
} }
c = &cl[wp_num]; c = &cl[wp_num];
watchpoint->set = wp_num + 1; watchpoint_set(watchpoint, wp_num);
c->used = true; c->used = true;
c->bp_value = watchpoint->address; c->bp_value = watchpoint->address;
@ -491,7 +491,7 @@ static int mips_mips64_enable_watchpoints(struct target *target)
/* set any pending watchpoints */ /* set any pending watchpoints */
while (watchpoint) { while (watchpoint) {
if (watchpoint->set == 0) { if (!watchpoint->is_set) {
retval = mips_mips64_set_watchpoint(target, watchpoint); retval = mips_mips64_set_watchpoint(target, watchpoint);
if (retval != ERROR_OK) if (retval != ERROR_OK)
return retval; 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_common *mips64 = target->arch_info;
struct mips64_comparator *comparator_list = mips64->inst_break_list; 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 ")", LOG_DEBUG("Invalid FP Comparator number in breakpoint (bpid: %" PRIu32 ")",
bp->unique_id); bp->unique_id);
return ERROR_OK; return ERROR_OK;
@ -568,7 +567,7 @@ static int mips_mips64_unset_breakpoint(struct target *target,
/* get pointers to arch-specific information */ /* get pointers to arch-specific information */
int retval; int retval;
if (!bp->set) { if (!bp->is_set) {
LOG_WARNING("breakpoint not set"); LOG_WARNING("breakpoint not set");
return ERROR_OK; return ERROR_OK;
} }
@ -594,7 +593,7 @@ static int mips_mips64_unset_breakpoint(struct target *target,
return retval; return retval;
} }
bp->set = false; bp->is_set = false;
return ERROR_OK; return ERROR_OK;
} }
@ -815,7 +814,7 @@ static int mips_mips64_remove_breakpoint(struct target *target,
return ERROR_TARGET_NOT_HALTED; return ERROR_TARGET_NOT_HALTED;
} }
if (bp->set) if (bp->is_set)
retval = mips_mips64_unset_breakpoint(target, bp); retval = mips_mips64_unset_breakpoint(target, bp);
if (bp->type == BKPT_HARD) 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_common *mips64 = target->arch_info;
struct mips64_comparator *comparator_list = mips64->data_break_list; struct mips64_comparator *comparator_list = mips64->data_break_list;
if (!watchpoint->set) { if (!watchpoint->is_set) {
LOG_WARNING("watchpoint not set"); LOG_WARNING("watchpoint not set");
return ERROR_OK; return ERROR_OK;
} }
int wp_num = watchpoint->set - 1; int wp_num = watchpoint->number;
if ((wp_num < 0) || (wp_num >= mips64->num_data_bpoints)) { if (wp_num >= mips64->num_data_bpoints) {
LOG_DEBUG("Invalid FP Comparator number in watchpoint"); LOG_DEBUG("Invalid FP Comparator number in watchpoint");
return ERROR_OK; return ERROR_OK;
} }
comparator_list[wp_num].used = false; comparator_list[wp_num].used = false;
comparator_list[wp_num].bp_value = 0; comparator_list[wp_num].bp_value = 0;
target_write_u64(target, comparator_list[wp_num].reg_address + 0x18, 0); target_write_u64(target, comparator_list[wp_num].reg_address + 0x18, 0);
watchpoint->set = 0; watchpoint->is_set = false;
return ERROR_OK; return ERROR_OK;
} }
@ -876,7 +875,7 @@ static int mips_mips64_remove_watchpoint(struct target *target,
return ERROR_TARGET_NOT_HALTED; return ERROR_TARGET_NOT_HALTED;
} }
if (watchpoint->set) if (watchpoint->is_set)
retval = mips_mips64_unset_watchpoint(target, watchpoint); retval = mips_mips64_unset_watchpoint(target, watchpoint);
mips64->num_data_bpoints_avail++; mips64->num_data_bpoints_avail++;

View File

@ -1653,7 +1653,7 @@ int nds32_init_arch_info(struct target *target, struct nds32 *nds32)
nds32->syscall_break.asid = 0; nds32->syscall_break.asid = 0;
nds32->syscall_break.length = 4; 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.orig_instr = NULL;
nds32->syscall_break.next = NULL; nds32->syscall_break.next = NULL;
nds32->syscall_break.unique_id = 0x515CAll + target->target_number; nds32->syscall_break.unique_id = 0x515CAll + target->target_number;

View File

@ -78,12 +78,12 @@ static int nds32_v3_debug_entry(struct nds32 *nds32, bool enable_watchpoint)
struct breakpoint *syscall_break = &(nds32->syscall_break); struct breakpoint *syscall_break = &(nds32->syscall_break);
if (nds32->virtual_hosting) { if (nds32->virtual_hosting) {
if (syscall_break->set) { if (syscall_break->is_set) {
/** disable virtual hosting */ /** disable virtual hosting */
/* remove breakpoint at syscall entry */ /* remove breakpoint at syscall entry */
target_remove_breakpoint(nds32->target, syscall_break); target_remove_breakpoint(nds32->target, syscall_break);
syscall_break->set = 0; syscall_break->is_set = false;
uint32_t value_pc; uint32_t value_pc;
nds32_get_mapped_reg(nds32, PC, &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->address = syscall_address;
syscall_break->type = BKPT_SOFT; syscall_break->type = BKPT_SOFT;
syscall_break->set = 1; syscall_break->is_set = true;
target_add_breakpoint(target, syscall_break); target_add_breakpoint(target, syscall_break);
} }

View File

@ -195,19 +195,22 @@ static int jsp_connection_closed(struct connection *connection)
return ERROR_OK; 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) int jsp_init(struct or1k_jtag *jtag_info, char *banner)
{ {
struct jsp_service *jsp_service = malloc(sizeof(struct jsp_service)); struct jsp_service *jsp_service = malloc(sizeof(struct jsp_service));
jsp_service->banner = banner; jsp_service->banner = banner;
jsp_service->jtag_info = jtag_info; jsp_service->jtag_info = jtag_info;
return add_service("jsp", return add_service(&jsp_service_driver, jsp_port, 1, jsp_service);
jsp_port,
1,
jsp_new_connection,
jsp_input,
jsp_connection_closed,
jsp_service);
} }
COMMAND_HANDLER(handle_jsp_port_command) COMMAND_HANDLER(handle_jsp_port_command)

View File

@ -923,9 +923,9 @@ static int or1k_add_breakpoint(struct target *target,
struct or1k_du *du_core = or1k_to_du(or1k); struct or1k_du *du_core = or1k_to_du(or1k);
uint8_t data; 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->address, breakpoint->length, breakpoint->type,
breakpoint->set, breakpoint->unique_id); breakpoint->unique_id);
/* Only support SW breakpoints for now. */ /* Only support SW breakpoints for now. */
if (breakpoint->type == BKPT_HARD) 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_common *or1k = target_to_or1k(target);
struct or1k_du *du_core = or1k_to_du(or1k); 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->address, breakpoint->length, breakpoint->type,
breakpoint->set, breakpoint->unique_id); breakpoint->unique_id);
/* Only support SW breakpoints for now. */ /* Only support SW breakpoints for now. */
if (breakpoint->type == BKPT_HARD) if (breakpoint->type == BKPT_HARD)

View File

@ -909,7 +909,7 @@ int riscv_add_breakpoint(struct target *target, struct breakpoint *breakpoint)
return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
} }
breakpoint->set = true; breakpoint->is_set = true;
return ERROR_OK; return ERROR_OK;
} }
@ -969,7 +969,7 @@ int riscv_remove_breakpoint(struct target *target,
return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
} }
breakpoint->set = false; breakpoint->is_set = false;
return ERROR_OK; return ERROR_OK;
} }
@ -996,7 +996,7 @@ int riscv_add_watchpoint(struct target *target, struct watchpoint *watchpoint)
int result = add_trigger(target, &trigger); int result = add_trigger(target, &trigger);
if (result != ERROR_OK) if (result != ERROR_OK)
return result; return result;
watchpoint->set = true; watchpoint->is_set = true;
return ERROR_OK; return ERROR_OK;
} }
@ -1012,7 +1012,7 @@ int riscv_remove_watchpoint(struct target *target,
int result = remove_trigger(target, &trigger); int result = remove_trigger(target, &trigger);
if (result != ERROR_OK) if (result != ERROR_OK)
return result; return result;
watchpoint->set = false; watchpoint->is_set = false;
return ERROR_OK; return ERROR_OK;
} }
@ -1381,9 +1381,9 @@ static int disable_triggers(struct target *target, riscv_reg_t *state)
struct watchpoint *watchpoint = target->watchpoints; struct watchpoint *watchpoint = target->watchpoints;
int i = 0; int i = 0;
while (watchpoint) { while (watchpoint) {
LOG_DEBUG("watchpoint %d: set=%d", i, watchpoint->set); LOG_DEBUG("watchpoint %d: set=%d", i, watchpoint->is_set);
state[i] = watchpoint->set; state[i] = watchpoint->is_set;
if (watchpoint->set) { if (watchpoint->is_set) {
if (riscv_remove_watchpoint(target, watchpoint) != ERROR_OK) if (riscv_remove_watchpoint(target, watchpoint) != ERROR_OK)
return ERROR_FAIL; return ERROR_FAIL;
} }

View File

@ -15,6 +15,10 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <stddef.h> #include <stddef.h>
#include <stdint.h> #include <stdint.h>
#include <helper/log.h> #include <helper/log.h>

View File

@ -68,7 +68,7 @@ enum {
}; };
/* GDB remote protocol does not differentiate between text and binary open modes. */ /* 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_RDONLY, TARGET_O_RDONLY,
TARGET_O_RDWR, TARGET_O_RDWR,
@ -83,6 +83,21 @@ static const int open_modeflags[12] = {
TARGET_O_RDWR | TARGET_O_CREAT | TARGET_O_APPEND 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, static int semihosting_common_fileio_info(struct target *target,
struct gdb_fileio_info *fileio_info); struct gdb_fileio_info *fileio_info);
static int semihosting_common_fileio_end(struct target *target, int result, 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->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->is_fileio = false;
semihosting->hit_fileio = false; semihosting->hit_fileio = false;
semihosting->is_resumable = false; semihosting->is_resumable = false;
@ -154,6 +174,147 @@ int semihosting_common_init(struct target *target, void *setup,
return ERROR_OK; 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 * User operation parameter string storage buffer. Contains valid data when the
* TARGET_EVENT_SEMIHOSTING_USER_CMD_xxxxx event callbacks are running. * 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->identifier = "open";
fileio_info->param_1 = addr; fileio_info->param_1 = addr;
fileio_info->param_2 = len; 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; fileio_info->param_4 = 0644;
} }
} else { } else {
@ -756,20 +917,23 @@ int semihosting_common(struct target *target)
* - 4-7 ("w") for stdout, * - 4-7 ("w") for stdout,
* - 8-11 ("a") for stderr */ * - 8-11 ("a") for stderr */
if (mode < 4) { if (mode < 4) {
semihosting->result = dup( int fd = dup(STDIN_FILENO);
STDIN_FILENO); semihosting->result = fd;
semihosting->stdin_fd = fd;
semihosting->sys_errno = errno; semihosting->sys_errno = errno;
LOG_DEBUG("dup(STDIN)=%d", LOG_DEBUG("dup(STDIN)=%d",
(int)semihosting->result); (int)semihosting->result);
} else if (mode < 8) { } else if (mode < 8) {
semihosting->result = dup( int fd = dup(STDOUT_FILENO);
STDOUT_FILENO); semihosting->result = fd;
semihosting->stdout_fd = fd;
semihosting->sys_errno = errno; semihosting->sys_errno = errno;
LOG_DEBUG("dup(STDOUT)=%d", LOG_DEBUG("dup(STDOUT)=%d",
(int)semihosting->result); (int)semihosting->result);
} else { } else {
semihosting->result = dup( int fd = dup(STDERR_FILENO);
STDERR_FILENO); semihosting->result = fd;
semihosting->stderr_fd = fd;
semihosting->sys_errno = errno; semihosting->sys_errno = errno;
LOG_DEBUG("dup(STDERR)=%d", LOG_DEBUG("dup(STDERR)=%d",
(int)semihosting->result); (int)semihosting->result);
@ -779,7 +943,7 @@ int semihosting_common(struct target *target)
* otherwise it will fail to reopen a previously * otherwise it will fail to reopen a previously
* written file */ * written file */
semihosting->result = open((char *)fn, semihosting->result = open((char *)fn,
open_modeflags[mode], open_host_modeflags[mode],
0644); 0644);
semihosting->sys_errno = errno; semihosting->sys_errno = errno;
LOG_DEBUG("open('%s')=%d", fn, LOG_DEBUG("open('%s')=%d", fn,
@ -845,8 +1009,7 @@ int semihosting_common(struct target *target)
semihosting->result = -1; semihosting->result = -1;
semihosting->sys_errno = ENOMEM; semihosting->sys_errno = ENOMEM;
} else { } else {
semihosting->result = read(fd, buf, len); semihosting->result = semihosting_read(semihosting, fd, buf, len);
semihosting->sys_errno = errno;
LOG_DEBUG("read(%d, 0x%" PRIx64 ", %zu)=%d", LOG_DEBUG("read(%d, 0x%" PRIx64 ", %zu)=%d",
fd, fd,
addr, addr,
@ -886,7 +1049,7 @@ int semihosting_common(struct target *target)
LOG_ERROR("SYS_READC not supported by semihosting fileio"); LOG_ERROR("SYS_READC not supported by semihosting fileio");
return ERROR_FAIL; return ERROR_FAIL;
} }
semihosting->result = getchar(); semihosting->result = semihosting_getchar(semihosting, semihosting->stdin_fd);
LOG_DEBUG("getchar()=%d", (int)semihosting->result); LOG_DEBUG("getchar()=%d", (int)semihosting->result);
break; break;
@ -1189,7 +1352,7 @@ int semihosting_common(struct target *target)
free(buf); free(buf);
return retval; return retval;
} }
semihosting->result = write(fd, buf, len); semihosting->result = semihosting_write(semihosting, fd, buf, len);
semihosting->sys_errno = errno; semihosting->sys_errno = errno;
LOG_DEBUG("write(%d, 0x%" PRIx64 ", %zu)=%d", LOG_DEBUG("write(%d, 0x%" PRIx64 ", %zu)=%d",
fd, fd,
@ -1234,7 +1397,7 @@ int semihosting_common(struct target *target)
retval = target_read_memory(target, addr, 1, 1, &c); retval = target_read_memory(target, addr, 1, 1, &c);
if (retval != ERROR_OK) if (retval != ERROR_OK)
return retval; return retval;
putchar(c); semihosting_putchar(semihosting, semihosting->stdout_fd, c);
semihosting->result = 0; semihosting->result = 0;
} }
break; break;
@ -1278,7 +1441,7 @@ int semihosting_common(struct target *target)
return retval; return retval;
if (!c) if (!c)
break; break;
putchar(c); semihosting_putchar(semihosting, semihosting->stdout_fd, c);
} while (1); } while (1);
semihosting->result = 0; 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); 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. */ * Common semihosting commands handlers. */
@ -1602,6 +1829,91 @@ COMMAND_HANDLER(handle_common_semihosting_command)
return ERROR_OK; 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) COMMAND_HANDLER(handle_common_semihosting_fileio_command)
{ {
struct target *target = get_current_target(CMD_CTX); 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[] = { const struct command_registration semihosting_common_handlers[] = {
{ {
"semihosting", .name = "semihosting",
.handler = handle_common_semihosting_command, .handler = handle_common_semihosting_command,
.mode = COMMAND_EXEC, .mode = COMMAND_EXEC,
.usage = "['enable'|'disable']", .usage = "['enable'|'disable']",
.help = "activate support for semihosting operations", .help = "activate support for semihosting operations",
}, },
{ {
"semihosting_cmdline", .name = "semihosting_redirect",
.handler = handle_common_semihosting_redirect_command,
.mode = COMMAND_EXEC,
.usage = "(disable | tcp <port> ['debug'|'stdio'|'all'])",
.help = "redirect semihosting IO",
},
{
.name = "semihosting_cmdline",
.handler = handle_common_semihosting_cmdline, .handler = handle_common_semihosting_cmdline,
.mode = COMMAND_EXEC, .mode = COMMAND_EXEC,
.usage = "arguments", .usage = "arguments",
.help = "command line arguments to be passed to program", .help = "command line arguments to be passed to program",
}, },
{ {
"semihosting_fileio", .name = "semihosting_fileio",
.handler = handle_common_semihosting_fileio_command, .handler = handle_common_semihosting_fileio_command,
.mode = COMMAND_EXEC, .mode = COMMAND_EXEC,
.usage = "['enable'|'disable']", .usage = "['enable'|'disable']",
.help = "activate support for semihosting fileio operations", .help = "activate support for semihosting fileio operations",
}, },
{ {
"semihosting_resexit", .name = "semihosting_resexit",
.handler = handle_common_semihosting_resumable_exit_command, .handler = handle_common_semihosting_resumable_exit_command,
.mode = COMMAND_EXEC, .mode = COMMAND_EXEC,
.usage = "['enable'|'disable']", .usage = "['enable'|'disable']",
.help = "activate support for semihosting resumable exit", .help = "activate support for semihosting resumable exit",
}, },
{ {
"semihosting_read_user_param", .name = "semihosting_read_user_param",
.handler = handle_common_semihosting_read_user_param_command, .handler = handle_common_semihosting_read_user_param_command,
.mode = COMMAND_EXEC, .mode = COMMAND_EXEC,
.usage = "", .usage = "",

View File

@ -26,6 +26,7 @@
#include <stdbool.h> #include <stdbool.h>
#include <time.h> #include <time.h>
#include "helper/replacements.h" #include "helper/replacements.h"
#include <server/server.h>
/* /*
* According to: * According to:
@ -95,6 +96,13 @@ enum semihosting_reported_exceptions {
ADP_STOPPED_RUN_TIME_ERROR = ((2 << 16) + 35), 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; struct target;
/* /*
@ -105,6 +113,15 @@ struct semihosting {
/** A flag reporting whether semihosting is active. */ /** A flag reporting whether semihosting is active. */
bool 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. */ /** A flag reporting whether semihosting fileio is active. */
bool is_fileio; bool is_fileio;

View File

@ -206,6 +206,32 @@ proc init_target_events {} {
proc init_board {} { 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 # smp_on/smp_off were already DEPRECATED in v0.11.0 through http://openocd.zylin.com/4615
lappend _telnet_autocomplete_skip "aarch64 smp_on" lappend _telnet_autocomplete_skip "aarch64 smp_on"
proc "aarch64 smp_on" {args} { proc "aarch64 smp_on" {args} {

View File

@ -1370,7 +1370,7 @@ static void stm8_enable_breakpoints(struct target *target)
/* set any pending breakpoints */ /* set any pending breakpoints */
while (breakpoint) { while (breakpoint) {
if (breakpoint->set == 0) if (!breakpoint->is_set)
stm8_set_breakpoint(target, breakpoint); stm8_set_breakpoint(target, breakpoint);
breakpoint = breakpoint->next; breakpoint = breakpoint->next;
} }
@ -1383,7 +1383,7 @@ static int stm8_set_breakpoint(struct target *target,
struct stm8_comparator *comparator_list = stm8->hw_break_list; struct stm8_comparator *comparator_list = stm8->hw_break_list;
int retval; int retval;
if (breakpoint->set) { if (breakpoint->is_set) {
LOG_WARNING("breakpoint already set"); LOG_WARNING("breakpoint already set");
return ERROR_OK; return ERROR_OK;
} }
@ -1398,7 +1398,7 @@ static int stm8_set_breakpoint(struct target *target,
breakpoint->unique_id); breakpoint->unique_id);
return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; 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].used = true;
comparator_list[bp_num].bp_value = breakpoint->address; comparator_list[bp_num].bp_value = breakpoint->address;
comparator_list[bp_num].type = HWBRK_EXEC; comparator_list[bp_num].type = HWBRK_EXEC;
@ -1435,7 +1435,7 @@ static int stm8_set_breakpoint(struct target *target,
} else { } else {
return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
} }
breakpoint->set = 1; /* Any nice value but 0 */ breakpoint->is_set = true;
} }
return ERROR_OK; return ERROR_OK;
@ -1476,14 +1476,14 @@ static int stm8_unset_breakpoint(struct target *target,
struct stm8_comparator *comparator_list = stm8->hw_break_list; struct stm8_comparator *comparator_list = stm8->hw_break_list;
int retval; int retval;
if (!breakpoint->set) { if (!breakpoint->is_set) {
LOG_WARNING("breakpoint not set"); LOG_WARNING("breakpoint not set");
return ERROR_OK; return ERROR_OK;
} }
if (breakpoint->type == BKPT_HARD) { if (breakpoint->type == BKPT_HARD) {
int bp_num = breakpoint->set - 1; int bp_num = breakpoint->number;
if ((bp_num < 0) || (bp_num >= stm8->num_hw_bpoints)) { if (bp_num >= stm8->num_hw_bpoints) {
LOG_DEBUG("Invalid comparator number in breakpoint (bpid: %" PRIu32 ")", LOG_DEBUG("Invalid comparator number in breakpoint (bpid: %" PRIu32 ")",
breakpoint->unique_id); breakpoint->unique_id);
return ERROR_OK; return ERROR_OK;
@ -1517,7 +1517,7 @@ static int stm8_unset_breakpoint(struct target *target,
} else } else
return ERROR_FAIL; return ERROR_FAIL;
} }
breakpoint->set = 0; breakpoint->is_set = false;
return ERROR_OK; return ERROR_OK;
} }
@ -1533,7 +1533,7 @@ static int stm8_remove_breakpoint(struct target *target,
return ERROR_TARGET_NOT_HALTED; return ERROR_TARGET_NOT_HALTED;
} }
if (breakpoint->set) if (breakpoint->is_set)
stm8_unset_breakpoint(target, breakpoint); stm8_unset_breakpoint(target, breakpoint);
if (breakpoint->type == BKPT_HARD) if (breakpoint->type == BKPT_HARD)
@ -1550,7 +1550,7 @@ static int stm8_set_watchpoint(struct target *target,
int wp_num = 0; int wp_num = 0;
int ret; int ret;
if (watchpoint->set) { if (watchpoint->is_set) {
LOG_WARNING("watchpoint already set"); LOG_WARNING("watchpoint already set");
return ERROR_OK; return ERROR_OK;
} }
@ -1593,7 +1593,7 @@ static int stm8_set_watchpoint(struct target *target,
return ret; return ret;
} }
watchpoint->set = wp_num + 1; watchpoint_set(watchpoint, wp_num);
LOG_DEBUG("wp_num %i bp_value 0x%" PRIx32 "", LOG_DEBUG("wp_num %i bp_value 0x%" PRIx32 "",
wp_num, wp_num,
@ -1627,7 +1627,7 @@ static void stm8_enable_watchpoints(struct target *target)
/* set any pending watchpoints */ /* set any pending watchpoints */
while (watchpoint) { while (watchpoint) {
if (watchpoint->set == 0) if (!watchpoint->is_set)
stm8_set_watchpoint(target, watchpoint); stm8_set_watchpoint(target, watchpoint);
watchpoint = watchpoint->next; 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_common *stm8 = target_to_stm8(target);
struct stm8_comparator *comparator_list = stm8->hw_break_list; struct stm8_comparator *comparator_list = stm8->hw_break_list;
if (!watchpoint->set) { if (!watchpoint->is_set) {
LOG_WARNING("watchpoint not set"); LOG_WARNING("watchpoint not set");
return ERROR_OK; return ERROR_OK;
} }
int wp_num = watchpoint->set - 1; int wp_num = watchpoint->number;
if ((wp_num < 0) || (wp_num >= stm8->num_hw_bpoints)) { if (wp_num >= stm8->num_hw_bpoints) {
LOG_DEBUG("Invalid hw comparator number in watchpoint"); LOG_DEBUG("Invalid hw comparator number in watchpoint");
return ERROR_OK; return ERROR_OK;
} }
comparator_list[wp_num].used = false; comparator_list[wp_num].used = false;
watchpoint->set = 0; watchpoint->is_set = false;
stm8_set_hwbreak(target, comparator_list); stm8_set_hwbreak(target, comparator_list);
@ -1669,7 +1669,7 @@ static int stm8_remove_watchpoint(struct target *target,
return ERROR_TARGET_NOT_HALTED; return ERROR_TARGET_NOT_HALTED;
} }
if (watchpoint->set) if (watchpoint->is_set)
stm8_unset_watchpoint(target, watchpoint); stm8_unset_watchpoint(target, watchpoint);
stm8->num_hw_bpoints_avail++; stm8->num_hw_bpoints_avail++;

View File

@ -3972,26 +3972,26 @@ static int handle_bp_command_list(struct command_invocation *cmd)
if (breakpoint->type == BKPT_SOFT) { if (breakpoint->type == BKPT_SOFT) {
char *buf = buf_to_hex_str(breakpoint->orig_instr, char *buf = buf_to_hex_str(breakpoint->orig_instr,
breakpoint->length); 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->address,
breakpoint->length, breakpoint->length,
breakpoint->set, buf); buf);
free(buf); free(buf);
} else { } else {
if ((breakpoint->address == 0) && (breakpoint->asid != 0)) 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->asid,
breakpoint->length, breakpoint->set); breakpoint->length, breakpoint->number);
else if ((breakpoint->address != 0) && (breakpoint->asid != 0)) { 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->address,
breakpoint->length, breakpoint->set); breakpoint->length, breakpoint->number);
command_print(cmd, "\t|--->linked with ContextID: 0x%8.8" PRIx32, command_print(cmd, "\t|--->linked with ContextID: 0x%8.8" PRIx32,
breakpoint->asid); breakpoint->asid);
} else } 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->address,
breakpoint->length, breakpoint->set); breakpoint->length, breakpoint->number);
} }
breakpoint = breakpoint->next; breakpoint = breakpoint->next;
@ -4436,27 +4436,12 @@ static int new_u64_array_element(Jim_Interp *interp, const char *varname, int id
return result; 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) static int target_mem2array(Jim_Interp *interp, struct target *target, int argc, Jim_Obj *const *argv)
{ {
int e; int e;
LOG_WARNING("DEPRECATED! use 'read_memory' not 'mem2array'");
/* argv[0] = name of array to receive the data /* argv[0] = name of array to receive the data
* argv[1] = desired element width in bits * argv[1] = desired element width in bits
* argv[2] = memory address * argv[2] = memory address
@ -4609,6 +4594,161 @@ static int target_mem2array(Jim_Interp *interp, struct target *target, int argc,
return e; 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) 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); 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; 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, static int target_array2mem(Jim_Interp *interp, struct target *target,
int argc, Jim_Obj *const *argv) int argc, Jim_Obj *const *argv)
{ {
int e; int e;
LOG_WARNING("DEPRECATED! use 'write_memory' not 'array2mem'");
/* argv[0] = name of array from which to read the data /* argv[0] = name of array from which to read the data
* argv[1] = desired element width in bits * argv[1] = desired element width in bits
* argv[2] = memory address * argv[2] = memory address
@ -4819,6 +4944,144 @@ static int target_array2mem(Jim_Interp *interp, struct target *target,
return e; 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 /* FIX? should we propagate errors here rather than printing them
* and continuing? * 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. * 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", "from target memory",
.usage = "arrayname bitwidth address count", .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", .name = "eventlist",
.handler = handle_target_event_list, .handler = handle_target_event_list,
@ -6720,20 +7149,32 @@ static const struct command_registration target_exec_command_handlers[] = {
.usage = "filename [offset [type]]", .usage = "filename [offset [type]]",
}, },
{ {
.name = "mem2array", .name = "get_reg",
.mode = COMMAND_EXEC, .mode = COMMAND_EXEC,
.jim_handler = jim_mem2array, .jim_handler = target_jim_get_reg,
.help = "read 8/16/32 bit memory and return as a TCL array " .help = "Get register values from the target",
"for script processing", .usage = "list",
.usage = "arrayname bitwidth address count",
}, },
{ {
.name = "array2mem", .name = "set_reg",
.mode = COMMAND_EXEC, .mode = COMMAND_EXEC,
.jim_handler = jim_array2mem, .jim_handler = target_jim_set_reg,
.help = "convert a TCL array to memory locations " .help = "Set target register values",
"and write the 8/16/32 bit values", .usage = "dict",
.usage = "arrayname bitwidth address count", },
{
.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", .name = "reset_nag",

View File

@ -862,7 +862,7 @@ int x86_32_common_remove_watchpoint(struct target *t, struct watchpoint *wp)
{ {
if (check_not_halted(t)) if (check_not_halted(t))
return ERROR_TARGET_NOT_HALTED; return ERROR_TARGET_NOT_HALTED;
if (wp->set) if (wp->is_set)
unset_watchpoint(t, wp); unset_watchpoint(t, wp);
return ERROR_OK; 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); LOG_DEBUG("type=%d, addr=" TARGET_ADDR_FMT, bp->type, bp->address);
if (check_not_halted(t)) if (check_not_halted(t))
return ERROR_TARGET_NOT_HALTED; return ERROR_TARGET_NOT_HALTED;
if (bp->set) if (bp->is_set)
unset_breakpoint(t, bp); unset_breakpoint(t, bp);
return ERROR_OK; 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) if (set_debug_regs(t, bp->address, hwbp_num, DR7_BP_EXECUTE, 1) != ERROR_OK)
return ERROR_FAIL; 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].used = 1;
debug_reg_list[hwbp_num].bp_value = bp->address; debug_reg_list[hwbp_num].bp_value = bp->address;
LOG_USER("%s hardware breakpoint %" PRIu32 " set at 0x%08" PRIx32 " (hwreg=%" PRIu8 ")", __func__, 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_common *x86_32 = target_to_x86_32(t);
struct x86_32_dbg_reg *debug_reg_list = x86_32->hw_break_list; 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, LOG_ERROR("%s invalid breakpoint number=%d, bpid=%" PRIu32,
__func__, hwbp_num, bp->unique_id); __func__, hwbp_num, bp->unique_id);
return ERROR_OK; return ERROR_OK;
@ -1055,7 +1055,7 @@ static int set_swbp(struct target *t, struct breakpoint *bp)
__func__, readback, *bp->orig_instr); __func__, readback, *bp->orig_instr);
return ERROR_FAIL; return ERROR_FAIL;
} }
bp->set = SW_BP_OPCODE; /* just non 0 */ bp->is_set = true;
/* add the memory patch */ /* add the memory patch */
struct swbp_mem_patch *new_patch = malloc(sizeof(struct swbp_mem_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; int error = ERROR_OK;
struct x86_32_common *x86_32 = target_to_x86_32(t); struct x86_32_common *x86_32 = target_to_x86_32(t);
LOG_DEBUG("type=%d, addr=" TARGET_ADDR_FMT, bp->type, bp->address); LOG_DEBUG("type=%d, addr=" TARGET_ADDR_FMT, bp->type, bp->address);
if (bp->set) { if (bp->is_set) {
LOG_ERROR("breakpoint already set"); LOG_ERROR("breakpoint already set");
return error; 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) static int unset_breakpoint(struct target *t, struct breakpoint *bp)
{ {
LOG_DEBUG("type=%d, addr=" TARGET_ADDR_FMT, bp->type, bp->address); LOG_DEBUG("type=%d, addr=" TARGET_ADDR_FMT, bp->type, bp->address);
if (!bp->set) { if (!bp->is_set) {
LOG_WARNING("breakpoint not set"); LOG_WARNING("breakpoint not set");
return ERROR_OK; return ERROR_OK;
} }
@ -1182,7 +1182,7 @@ static int unset_breakpoint(struct target *t, struct breakpoint *bp)
return ERROR_FAIL; return ERROR_FAIL;
} }
} }
bp->set = 0; bp->is_set = false;
return ERROR_OK; return ERROR_OK;
} }
@ -1193,7 +1193,7 @@ static int set_watchpoint(struct target *t, struct watchpoint *wp)
int wp_num = 0; int wp_num = 0;
LOG_DEBUG("type=%d, addr=" TARGET_ADDR_FMT, wp->rw, wp->address); 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__); LOG_ERROR("%s watchpoint already set", __func__);
return ERROR_OK; 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__); LOG_ERROR("%s only 'access' or 'write' watchpoints are supported", __func__);
break; break;
} }
wp->set = wp_num + 1; watchpoint_set(wp, wp_num);
debug_reg_list[wp_num].used = 1; debug_reg_list[wp_num].used = 1;
debug_reg_list[wp_num].bp_value = wp->address; debug_reg_list[wp_num].bp_value = wp->address;
LOG_USER("'%s' watchpoint %d set at " TARGET_ADDR_FMT " with length %" PRIu32 " (hwreg=%d)", 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_common *x86_32 = target_to_x86_32(t);
struct x86_32_dbg_reg *debug_reg_list = x86_32->hw_break_list; 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); LOG_DEBUG("type=%d, addr=" TARGET_ADDR_FMT, wp->rw, wp->address);
if (!wp->set) { if (!wp->is_set) {
LOG_WARNING("watchpoint not set"); LOG_WARNING("watchpoint not set");
return ERROR_OK; return ERROR_OK;
} }
int wp_num = wp->set - 1; int wp_num = wp->number;
if ((wp_num < 0) || (wp_num >= x86_32->num_hw_bpoints)) { if (wp_num >= x86_32->num_hw_bpoints) {
LOG_DEBUG("Invalid FP Comparator number in watchpoint"); LOG_DEBUG("Invalid FP Comparator number in watchpoint");
return ERROR_OK; 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].used = 0;
debug_reg_list[wp_num].bp_value = 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)", LOG_USER("'%s' watchpoint %d removed from " TARGET_ADDR_FMT " with length %" PRIu32 " (hwreg=%d)",
wp->rw == WPT_READ ? "read" : wp->rw == WPT_WRITE ? wp->rw == WPT_READ ? "read" : wp->rw == WPT_WRITE ?

View File

@ -1087,7 +1087,7 @@ static void xscale_enable_watchpoints(struct target *target)
struct watchpoint *watchpoint = target->watchpoints; struct watchpoint *watchpoint = target->watchpoints;
while (watchpoint) { while (watchpoint) {
if (watchpoint->set == 0) if (!watchpoint->is_set)
xscale_set_watchpoint(target, watchpoint); xscale_set_watchpoint(target, watchpoint);
watchpoint = watchpoint->next; watchpoint = watchpoint->next;
} }
@ -1099,7 +1099,7 @@ static void xscale_enable_breakpoints(struct target *target)
/* set any pending breakpoints */ /* set any pending breakpoints */
while (breakpoint) { while (breakpoint) {
if (breakpoint->set == 0) if (!breakpoint->is_set)
xscale_set_breakpoint(target, breakpoint); xscale_set_breakpoint(target, breakpoint);
breakpoint = breakpoint->next; breakpoint = breakpoint->next;
} }
@ -1506,7 +1506,7 @@ static int xscale_deassert_reset(struct target *target)
/* mark all hardware breakpoints as unset */ /* mark all hardware breakpoints as unset */
while (breakpoint) { while (breakpoint) {
if (breakpoint->type == BKPT_HARD) if (breakpoint->type == BKPT_HARD)
breakpoint->set = 0; breakpoint->is_set = false;
breakpoint = breakpoint->next; breakpoint = breakpoint->next;
} }
@ -2088,7 +2088,7 @@ static int xscale_set_breakpoint(struct target *target,
return ERROR_TARGET_NOT_HALTED; return ERROR_TARGET_NOT_HALTED;
} }
if (breakpoint->set) { if (breakpoint->is_set) {
LOG_WARNING("breakpoint already set"); LOG_WARNING("breakpoint already set");
return ERROR_OK; return ERROR_OK;
} }
@ -2098,11 +2098,13 @@ static int xscale_set_breakpoint(struct target *target,
if (!xscale->ibcr0_used) { if (!xscale->ibcr0_used) {
xscale_set_reg_u32(&xscale->reg_cache->reg_list[XSCALE_IBCR0], value); xscale_set_reg_u32(&xscale->reg_cache->reg_list[XSCALE_IBCR0], value);
xscale->ibcr0_used = 1; 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) { } else if (!xscale->ibcr1_used) {
xscale_set_reg_u32(&xscale->reg_cache->reg_list[XSCALE_IBCR1], value); xscale_set_reg_u32(&xscale->reg_cache->reg_list[XSCALE_IBCR1], value);
xscale->ibcr1_used = 1; 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() */ } else {/* bug: availability previously verified in xscale_add_breakpoint() */
LOG_ERROR("BUG: no hardware comparator available"); LOG_ERROR("BUG: no hardware comparator available");
return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
@ -2133,7 +2135,7 @@ static int xscale_set_breakpoint(struct target *target,
if (retval != ERROR_OK) if (retval != ERROR_OK)
return retval; return retval;
} }
breakpoint->set = 1; breakpoint->is_set = true;
xscale_send_u32(target, 0x50); /* clean dcache */ xscale_send_u32(target, 0x50); /* clean dcache */
xscale_send_u32(target, xscale->cache_clean_address); 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; return ERROR_TARGET_NOT_HALTED;
} }
if (!breakpoint->set) { if (!breakpoint->is_set) {
LOG_WARNING("breakpoint not set"); LOG_WARNING("breakpoint not set");
return ERROR_OK; return ERROR_OK;
} }
if (breakpoint->type == BKPT_HARD) { 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_set_reg_u32(&xscale->reg_cache->reg_list[XSCALE_IBCR0], 0x0);
xscale->ibcr0_used = 0; 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_set_reg_u32(&xscale->reg_cache->reg_list[XSCALE_IBCR1], 0x0);
xscale->ibcr1_used = 0; xscale->ibcr1_used = 0;
} }
breakpoint->set = 0; breakpoint->is_set = false;
} else { } else {
/* restore original instruction (kept in target endianness) */ /* restore original instruction (kept in target endianness) */
if (breakpoint->length == 4) { if (breakpoint->length == 4) {
@ -2203,7 +2205,7 @@ static int xscale_unset_breakpoint(struct target *target,
if (retval != ERROR_OK) if (retval != ERROR_OK)
return retval; return retval;
} }
breakpoint->set = 0; breakpoint->is_set = false;
xscale_send_u32(target, 0x50); /* clean dcache */ xscale_send_u32(target, 0x50); /* clean dcache */
xscale_send_u32(target, xscale->cache_clean_address); 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; return ERROR_TARGET_NOT_HALTED;
} }
if (breakpoint->set) if (breakpoint->is_set)
xscale_unset_breakpoint(target, breakpoint); xscale_unset_breakpoint(target, breakpoint);
if (breakpoint->type == BKPT_HARD) 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); xscale_set_reg_u32(&xscale->reg_cache->reg_list[XSCALE_DBR0], watchpoint->address);
dbcon_value |= enable; dbcon_value |= enable;
xscale_set_reg_u32(dbcon, dbcon_value); xscale_set_reg_u32(dbcon, dbcon_value);
watchpoint->set = 1; watchpoint_set(watchpoint, 0);
xscale->dbr0_used = 1; xscale->dbr0_used = 1;
} else if (!xscale->dbr1_used) { } else if (!xscale->dbr1_used) {
xscale_set_reg_u32(&xscale->reg_cache->reg_list[XSCALE_DBR1], watchpoint->address); xscale_set_reg_u32(&xscale->reg_cache->reg_list[XSCALE_DBR1], watchpoint->address);
dbcon_value |= enable << 2; dbcon_value |= enable << 2;
xscale_set_reg_u32(dbcon, dbcon_value); xscale_set_reg_u32(dbcon, dbcon_value);
watchpoint->set = 2; watchpoint_set(watchpoint, 1);
xscale->dbr1_used = 1; xscale->dbr1_used = 1;
} else { } else {
LOG_ERROR("BUG: no hardware comparator available"); LOG_ERROR("BUG: no hardware comparator available");
@ -2349,12 +2351,12 @@ static int xscale_unset_watchpoint(struct target *target,
return ERROR_TARGET_NOT_HALTED; return ERROR_TARGET_NOT_HALTED;
} }
if (!watchpoint->set) { if (!watchpoint->is_set) {
LOG_WARNING("breakpoint not set"); LOG_WARNING("breakpoint not set");
return ERROR_OK; return ERROR_OK;
} }
if (watchpoint->set == 1) { if (watchpoint->number == 0) {
if (watchpoint->length > 4) { if (watchpoint->length > 4) {
dbcon_value &= ~0x103; /* clear DBCON[M] as well */ dbcon_value &= ~0x103; /* clear DBCON[M] as well */
xscale->dbr1_used = 0; /* DBR1 was used for mask */ 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_set_reg_u32(dbcon, dbcon_value);
xscale->dbr0_used = 0; xscale->dbr0_used = 0;
} else if (watchpoint->set == 2) { } else if (watchpoint->number == 1) {
dbcon_value &= ~0xc; dbcon_value &= ~0xc;
xscale_set_reg_u32(dbcon, dbcon_value); xscale_set_reg_u32(dbcon, dbcon_value);
xscale->dbr1_used = 0; xscale->dbr1_used = 0;
} }
watchpoint->set = 0; watchpoint->is_set = false;
return ERROR_OK; return ERROR_OK;
} }
@ -2382,7 +2384,7 @@ static int xscale_remove_watchpoint(struct target *target, struct watchpoint *wa
return ERROR_TARGET_NOT_HALTED; return ERROR_TARGET_NOT_HALTED;
} }
if (watchpoint->set) if (watchpoint->is_set)
xscale_unset_watchpoint(target, watchpoint); xscale_unset_watchpoint(target, watchpoint);
if (watchpoint->length > 4) if (watchpoint->length > 4)

View File

@ -32,8 +32,7 @@ $_TARGETNAME configure -event reset-start {
} }
proc peek32 {address} { proc peek32 {address} {
mem2array t 32 $address 1 return [read_memory $address 32 1]
return $t(0)
} }
# Wait for an expression to be true with a timeout # Wait for an expression to be true with a timeout

View File

@ -40,9 +40,7 @@ at91sam9 rdy_busy 0 0xfffff800 13
at91sam9 ce 0 0xfffff800 14 at91sam9 ce 0 0xfffff800 14
proc read_register {register} { proc read_register {register} {
set result "" return [read_memory $register 32 1]
mem2array result 32 $register 1
return $result(0)
} }
proc at91sam9g20_reset_start { } { proc at91sam9g20_reset_start { } {

View File

@ -8,9 +8,7 @@ source [find target/lpc2478.cfg]
# Helper # Helper
# #
proc read_register {register} { proc read_register {register} {
set result "" return [read_memory $register 32 1]
mem2array result 32 $register 1
return $result(0)
} }
proc init_board {} { proc init_board {} {

View File

@ -26,9 +26,7 @@ proc flash_init { } {
} }
proc mread32 {addr} { proc mread32 {addr} {
set value(0) 0 return [read_memory $addr 32 1]
mem2array value 32 $addr 1
return $value(0)
} }
proc init_clocks { } { proc init_clocks { } {

View File

@ -43,9 +43,7 @@ flash bank $_FLASHNAME cfi 0x10000000 0x00800000 2 2 $_TARGETNAME
proc read_register {register} { proc read_register {register} {
set result "" return [read_memory $register 32 1]
mem2array result 32 $register 1
return $result(0)
} }
proc at91sam9g45_start { } { proc at91sam9g45_start { } {

View File

@ -17,7 +17,7 @@ proc core_up { args } {
global _TARGETNAME global _TARGETNAME
# examine remaining cores # examine remaining cores
foreach _core [set args] { foreach _core $args {
${_TARGETNAME}$_core arp_examine ${_TARGETNAME}$_core arp_examine
} }
} }

View File

@ -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]

View File

@ -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

25
tcl/board/ti_am625evm.cfg Normal file
View File

@ -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

View File

@ -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

View File

@ -19,7 +19,7 @@ proc core_up { args } {
global _TARGETNAME global _TARGETNAME
# examine remaining cores # examine remaining cores
foreach _core [set args] { foreach _core $args {
${_TARGETNAME}$_core arp_examine ${_TARGETNAME}$_core arp_examine
} }
} }

View File

@ -54,36 +54,36 @@ proc show_AIC_IMR_helper { NAME ADDR VAL } {
proc show_AIC { } { proc show_AIC { } {
global AIC_SMR 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] error [format "%s (%s)" $msg AIC_SMR]
} }
echo "AIC_SMR: Mode & Type" echo "AIC_SMR: Mode & Type"
global AT91C_ID global AT91C_ID
for { set x 0 } { $x < 32 } { } { for { set x 0 } { $x < 32 } { } {
echo -n " " 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 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 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 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 incr x
} }
global AIC_SVR 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] error [format "%s (%s)" $msg AIC_SVR]
} }
echo "AIC_SVR: Vectors" echo "AIC_SVR: Vectors"
for { set x 0 } { $x < 32 } { } { for { set x 0 } { $x < 32 } { } {
echo -n " " 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 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 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 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 incr x
} }

View File

@ -29,9 +29,8 @@ proc arc_common_reset { {target ""} } {
# vector located at the interrupt vector base address, which is the first # vector located at the interrupt vector base address, which is the first
# entry (offset 0x00) in the vector table. # entry (offset 0x00) in the vector table.
set int_vector_base [arc jtag get-aux-reg 0x25] set int_vector_base [arc jtag get-aux-reg 0x25]
set start_pc "" set start_pc [read_memory $int_vector_base 32 1]
mem2array start_pc 32 $int_vector_base 1 arc jtag set-aux-reg 0x6 $start_pc
arc jtag set-aux-reg 0x6 $start_pc(0)
# It is OK to do uncached writes - register cache will be invalidated by # It is OK to do uncached writes - register cache will be invalidated by
# the reset_assert() function. # the reset_assert() function.

View File

@ -2,9 +2,7 @@
# mrw: "memory read word", returns value of $reg # mrw: "memory read word", returns value of $reg
proc mrw {reg} { proc mrw {reg} {
set value "" return [read_memory $reg 32 1]
mem2array value 32 $reg 1
return $value(0)
} }
add_usage_text mrw "address" 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 # mrh: "memory read halfword", returns value of $reg
proc mrh {reg} { proc mrh {reg} {
set value "" return [read_memory $reg 16 1]
mem2array value 16 $reg 1
return $value(0)
} }
add_usage_text mrh "address" 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 # mrb: "memory read byte", returns value of $reg
proc mrb {reg} { proc mrb {reg} {
set value "" return [read_memory $reg 8 1]
mem2array value 8 $reg 1
return $value(0)
} }
add_usage_text mrb "address" add_usage_text mrb "address"

View File

@ -79,108 +79,96 @@ proc address_info { ADDRESS } {
} }
proc memread32 {ADDR} { proc memread32 {ADDR} {
set foo(0) 0 if ![ catch { set foo [read_memory $ADDR 32 1] } msg ] {
if ![ catch { mem2array foo 32 $ADDR 1 } msg ] { return $foo
return $foo(0)
} else { } else {
error "memread32: $msg" error "memread32: $msg"
} }
} }
proc memread16 {ADDR} { proc memread16 {ADDR} {
set foo(0) 0 if ![ catch { set foo [read_memory $ADDR 16 1] } msg ] {
if ![ catch { mem2array foo 16 $ADDR 1 } msg ] { return $foo
return $foo(0)
} else { } else {
error "memread16: $msg" error "memread16: $msg"
} }
} }
proc memread8 {ADDR} { proc memread8 {ADDR} {
set foo(0) 0 if ![ catch { set foo [read_memory $ADDR 8 1] } msg ] {
if ![ catch { mem2array foo 8 $ADDR 1 } msg ] { return $foo
return $foo(0)
} else { } else {
error "memread8: $msg" error "memread8: $msg"
} }
} }
proc memwrite32 {ADDR DATA} { proc memwrite32 {ADDR DATA} {
set foo(0) $DATA if ![ catch { write_memory $ADDR 32 $DATA } msg ] {
if ![ catch { array2mem foo 32 $ADDR 1 } msg ] { return $DATA
return $foo(0)
} else { } else {
error "memwrite32: $msg" error "memwrite32: $msg"
} }
} }
proc memwrite16 {ADDR DATA} { proc memwrite16 {ADDR DATA} {
set foo(0) $DATA if ![ catch { write_memory $ADDR 16 $DATA } msg ] {
if ![ catch { array2mem foo 16 $ADDR 1 } msg ] { return $DATA
return $foo(0)
} else { } else {
error "memwrite16: $msg" error "memwrite16: $msg"
} }
} }
proc memwrite8 {ADDR DATA} { proc memwrite8 {ADDR DATA} {
set foo(0) $DATA if ![ catch { write_memory $ADDR 8 $DATA } msg ] {
if ![ catch { array2mem foo 8 $ADDR 1 } msg ] { return $DATA
return $foo(0)
} else { } else {
error "memwrite8: $msg" error "memwrite8: $msg"
} }
} }
proc memread32_phys {ADDR} { proc memread32_phys {ADDR} {
set foo(0) 0 if ![ catch { set foo [read_memory $ADDR 32 1 phys] } msg ] {
if ![ catch { mem2array foo 32 $ADDR 1 phys } msg ] { return $foo
return $foo(0)
} else { } else {
error "memread32: $msg" error "memread32: $msg"
} }
} }
proc memread16_phys {ADDR} { proc memread16_phys {ADDR} {
set foo(0) 0 if ![ catch { set foo [read_memory $ADDR 16 1 phys] } msg ] {
if ![ catch { mem2array foo 16 $ADDR 1 phys } msg ] { return $foo
return $foo(0)
} else { } else {
error "memread16: $msg" error "memread16: $msg"
} }
} }
proc memread8_phys {ADDR} { proc memread8_phys {ADDR} {
set foo(0) 0 if ![ catch { set foo [read_memory $ADDR 8 1 phys] } msg ] {
if ![ catch { mem2array foo 8 $ADDR 1 phys } msg ] { return $foo
return $foo(0)
} else { } else {
error "memread8: $msg" error "memread8: $msg"
} }
} }
proc memwrite32_phys {ADDR DATA} { proc memwrite32_phys {ADDR DATA} {
set foo(0) $DATA if ![ catch { write_memory $ADDR 32 $DATA phys } msg ] {
if ![ catch { array2mem foo 32 $ADDR 1 phys } msg ] { return $DATA
return $foo(0)
} else { } else {
error "memwrite32: $msg" error "memwrite32: $msg"
} }
} }
proc memwrite16_phys {ADDR DATA} { proc memwrite16_phys {ADDR DATA} {
set foo(0) $DATA if ![ catch { write_memory $ADDR 16 $DATA phys } msg ] {
if ![ catch { array2mem foo 16 $ADDR 1 phys } msg ] { return $DATA
return $foo(0)
} else { } else {
error "memwrite16: $msg" error "memwrite16: $msg"
} }
} }
proc memwrite8_phys {ADDR DATA} { proc memwrite8_phys {ADDR DATA} {
set foo(0) $DATA if ![ catch { write_memory $ADDR 8 $DATA phys } msg ] {
if ![ catch { array2mem foo 8 $ADDR 1 phys } msg ] { return $DATA
return $foo(0)
} else { } else {
error "memwrite8: $msg" error "memwrite8: $msg"
} }

View File

@ -72,7 +72,7 @@ proc core_up { args } {
global _TARGETNAME global _TARGETNAME
# Examine remaining cores # Examine remaining cores
foreach _core [set args] { foreach _core $args {
${_TARGETNAME}$_core arp_examine ${_TARGETNAME}$_core arp_examine
} }
} }

View File

@ -29,9 +29,7 @@ source [find mem_helper.tcl]
# read a 64-bit register (memory mapped) # read a 64-bit register (memory mapped)
proc mr64bit {reg} { proc mr64bit {reg} {
set value "" return [read_memory $reg 32 2]
mem2array value 32 $reg 2
return $value
} }
@ -117,19 +115,19 @@ proc showAmbaClk {} {
set PLL_CLK_BYPASS [regs PLL_CLK_BYPASS] 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]] 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 # 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] echo [format "PLL bypass bit: %d" $bypass]
if {$bypass == 1} { if {$bypass == 1} {
echo [format "Amba Clk is set to REFCLK: %d (MHz)" [expr {$CFG_REFCLKFREQ/1000000}]] echo [format "Amba Clk is set to REFCLK: %d (MHz)" [expr {$CFG_REFCLKFREQ/1000000}]]
} else { } else {
# nope, extract x,y,w and compute the PLL output freq. # 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] echo [format "x: %d" $x]
set y [expr {($value(0) & 0x00000007F)}] set y [expr {($value & 0x00000007F)}]
echo [format "y: %d" $y] 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 "w: %d" $w]
echo [format "Amba PLL Clk: %d (MHz)" [expr {($CFG_REFCLKFREQ * $y / (($w + 1) * ($x + 1) * 2))/1000000}]] 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] 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]] 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 # 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] echo [format "PLL bypass bit: %d" $bypass]
if {$bypass == 1} { if {$bypass == 1} {
echo [format "Amba Clk is set to REFCLK: %d (MHz)" [expr {$CFG_REFCLKFREQ/1000000}]] echo [format "Amba Clk is set to REFCLK: %d (MHz)" [expr {$CFG_REFCLKFREQ/1000000}]]
} else { } else {
# nope, extract x,y,w and compute the PLL output freq. # 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] echo [format "x: %d" $x]
set y [expr {($value(0) & 0x00000007F)}] set y [expr {($value & 0x00000007F)}]
echo [format "y: %d" $y] 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 "w: %d" $w]
echo [format "Arm PLL Clk: %d (MHz)" [expr {($CFG_REFCLKFREQ * $y / (($w + 1) * ($x + 1) * 2))/1000000}]] echo [format "Arm PLL Clk: %d (MHz)" [expr {($CFG_REFCLKFREQ * $y / (($w + 1) * ($x + 1) * 2))/1000000}]]
} }

View File

@ -26,9 +26,7 @@ set _TARGETNAME $_CHIPNAME.cpu
target create $_TARGETNAME arm926ejs -endian $_ENDIAN -chain-position $_TARGETNAME target create $_TARGETNAME arm926ejs -endian $_ENDIAN -chain-position $_TARGETNAME
proc mread32 {addr} { proc mread32 {addr} {
set value(0) 0 return [read_memory $addr 32 1]
mem2array value 32 $addr 1
return $value(0)
} }
# This function must be called on netX100/500 right after halt # This function must be called on netX100/500 right after halt

56
tcl/target/ls1046a.cfg Normal file
View File

@ -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

View File

@ -74,22 +74,22 @@ if {![using_hla]} {
} }
proc psoc4_get_family_id {} { 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 } { if { $err } {
return 0 return 0
} }
if { [expr {$romtable_pid(0) & 0xffffff00 }] if { [expr {[lindex $romtable_pid 0] & 0xffffff00 }]
|| [expr {$romtable_pid(1) & 0xffffff00 }] || [expr {[lindex $romtable_pid 1] & 0xffffff00 }]
|| [expr {$romtable_pid(2) & 0xffffff00 }] } { || [expr {[lindex $romtable_pid 2] & 0xffffff00 }] } {
echo "Unexpected data in ROMTABLE" echo "Unexpected data in ROMTABLE"
return 0 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 } { if { $designer_id != 0xb4 } {
echo [format "ROMTABLE Designer ID 0x%02x is not Cypress" $designer_id] echo [format "ROMTABLE Designer ID 0x%02x is not Cypress" $designer_id]
return 0 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 return $family_id
} }
@ -193,9 +193,9 @@ proc ocd_process_reset_inner { MODE } {
} }
# Set registers to reset vector values # Set registers to reset vector values
mem2array value 32 0 2 set value [read_memory 0x0 32 2]
reg pc [expr {$value(1) & 0xfffffffe} ] reg pc [expr {[lindex $value 1] & 0xfffffffe}]
reg msp $value(0) reg msp [lindex $value 0]
if { $PSOC4_TEST_MODE_WORKAROUND } { if { $PSOC4_TEST_MODE_WORKAROUND } {
catch { mww $TEST_MODE 0 } catch { mww $TEST_MODE 0 }

View File

@ -232,9 +232,7 @@ if {[set $_CHIPNAME.DUAL_CORE]} {
# like mrw, but with target selection # like mrw, but with target selection
proc stm32h7x_mrw {used_target reg} { proc stm32h7x_mrw {used_target reg} {
set value "" return [$used_target read_memory $reg 32 1]
$used_target mem2array value 32 $reg 1
return $value(0)
} }
# like mmw, but with target selection # like mmw, but with target selection

View File

@ -1,10 +1,8 @@
# SPDX-License-Identifier: GPL-2.0-or-later # SPDX-License-Identifier: GPL-2.0-or-later
# script for stm32l5x family # 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 target/swj-dp.tcl]
source [find mem_helper.tcl] source [find mem_helper.tcl]
@ -14,78 +12,10 @@ if { [info exists CHIPNAME] } {
set _CHIPNAME stm32l5x set _CHIPNAME stm32l5x
} }
set _ENDIAN little source [find target/stm32x5x_common.cfg]
# Work-area is a space in RAM used for flash programming proc stm32l5x_clock_config {} {
# By default use 64kB set offset [expr {[stm32x5x_is_secure] ? 0x10000000 : 0}]
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}]
# MCU clock is MSI (4MHz) after reset, set MCU freq at 110 MHz with PLL # MCU clock is MSI (4MHz) after reset, set MCU freq at 110 MHz with PLL
# RCC_APB1ENR1 = PWREN # RCC_APB1ENR1 = PWREN
mww [expr {0x40021058 + $offset}] 0x10000000 mww [expr {0x40021058 + $offset}] 0x10000000
@ -111,90 +41,8 @@ proc clock_config_110_mhz {} {
while {([mrw [expr {0x40021008 + $offset}]] & 0x0C) != 0x0C} {} 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 { $_TARGETNAME configure -event reset-init {
clock_config_110_mhz stm32l5x_clock_config
# Boost JTAG frequency # Boost JTAG frequency
adapter speed 4000 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
}

View File

@ -109,8 +109,8 @@ proc toggle_cpu0_dbg_claim0 {} {
} }
proc detect_cpu1 {} { proc detect_cpu1 {} {
$::_CHIPNAME.ap1 mem2array cpu1_prsr 32 0xE00D2314 1 set cpu1_prsr [$::_CHIPNAME.ap1 read_memory 0xE00D2314 32 1]
set dual_core [expr {$cpu1_prsr(0) & 1}] set dual_core [expr {$cpu1_prsr & 1}]
if {! $dual_core} {$::_CHIPNAME.cpu1 configure -defer-examine} if {! $dual_core} {$::_CHIPNAME.cpu1 configure -defer-examine}
} }

View File

@ -1,10 +1,8 @@
# SPDX-License-Identifier: GPL-2.0-or-later # SPDX-License-Identifier: GPL-2.0-or-later
# script for stm32u5x family # 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 target/swj-dp.tcl]
source [find mem_helper.tcl] source [find mem_helper.tcl]
@ -14,99 +12,34 @@ if { [info exists CHIPNAME] } {
set _CHIPNAME stm32u5x set _CHIPNAME stm32u5x
} }
set _ENDIAN little source [find target/stm32x5x_common.cfg]
# Work-area is a space in RAM used for flash programming proc stm32u5x_clock_config {} {
# By default use 64kB set offset [expr {[stm32x5x_is_secure] ? 0x10000000 : 0}]
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}]
# MCU clock is at MSI 4MHz after reset, set MCU freq at 160 MHz with PLL # 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 # Enable voltage range 1 for frequency above 100 Mhz
# RCC_AHB3ENR = PWREN # RCC_AHB3ENR = PWREN
mww [expr {0x46020C94 + $offset}] 0x00000004 mww [expr {0x46020C94 + $offset}] 0x00000004
# delay for register clock enable (read back reg) # delay for register clock enable (read back reg)
mrw [expr {0x56020C94 + $offset}] mrw [expr {0x46020C94 + $offset}]
# PWR_VOSR : VOS Range 1 # PWR_VOSR : VOS Range 1
mww [expr {0x4602080C + $offset}] 0x00030000 mmw [expr {0x4602080C + $offset}] 0x00030000 0
# delay for register write (read back reg) # while !(PWR_VOSR & VOSRDY)
mrw [expr {0x4602080C + $offset}] while {!([mrw [expr {0x4602080C + $offset}]] & 0x00008000)} {}
# FLASH_ACR : 4 WS for 160 MHz HCLK # FLASH_ACR : 4 WS for 160 MHz HCLK
mww [expr {0x40022000 + $offset}] 0x00000004 mww [expr {0x40022000 + $offset}] 0x00000004
# RCC_PLL1CFGR => PLL1M=0000=/1, PLL1SRC=MSI 4MHz # RCC_PLL1CFGR => PLL1MBOOST=0, PLL1M=0=/1, PLL1FRACEN=0, PLL1SRC=MSI 4MHz
mww [expr {0x46020C28 + $offset}] 0x00000001 # 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 # RCC_PLL1DIVR => PLL1P=PLL1Q=PLL1R=000001=/2, PLL1N=0x4F=80
# fVCO = 4 x 80 /1 = 320 # fVCO = 4 x 80 /1 = 320
# SYSCLOCK = fVCO/PLL1R = 320/2 = 160 MHz # SYSCLOCK = fVCO/PLL1R = 320/2 = 160 MHz
mmw [expr {0x46020C34 + $offset}] 0x0000004F 0 mww [expr {0x46020C34 + $offset}] 0x0101024F
# RCC_PLL1CFGR => PLL1REN=1
mmw [expr {0x46020C28 + $offset}] 0x00040000 0
# RCC_CR |= PLL1ON # RCC_CR |= PLL1ON
mmw [expr {0x46020C00 + $offset}] 0x01000000 0 mmw [expr {0x46020C00 + $offset}] 0x01000000 0
# while !(RCC_CR & PLL1RDY) # while !(RCC_CR & PLL1RDY)
@ -117,91 +50,8 @@ proc clock_config_160_mhz {} {
while {([mrw [expr {0x46020C1C + $offset}]] & 0x0C) != 0x0C} {} 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 { $_TARGETNAME configure -event reset-init {
clock_config_160_mhz stm32u5x_clock_config
# Boost JTAG frequency # Boost JTAG frequency
adapter speed 4000 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
}

View File

@ -156,9 +156,7 @@ proc stm32wlx_get_chipname {} {
# like mrw, but with target selection # like mrw, but with target selection
proc stm32wlx_mrw {used_target reg} { proc stm32wlx_mrw {used_target reg} {
set value "" return [$used_target read_memory $reg 32 1]
$used_target mem2array value 32 $reg 1
return $value(0)
} }
# like mmw, but with target selection # like mmw, but with target selection

View File

@ -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
}

View File

@ -26,11 +26,11 @@ proc ocd_process_reset_inner { MODE } {
soft_reset_halt soft_reset_halt
# Initialize MSP, PSP, and PC from vector table at flash 0x01000800 # 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 msp [lindex $boot 0]
reg psp $boot(0) reg psp [lindex $boot 0]
reg pc $boot(1) reg pc [lindex $boot 1]
if { 0 == [string compare $MODE run ] } { if { 0 == [string compare $MODE run ] } {
resume resume

View File

@ -27,11 +27,11 @@ if { [info exists V8_SMP_DEBUG] } {
# Common Definitions # 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} set CM3_CTIBASE {0x3C016000}
# M3 power-ap unlock offsets # sysctrl power-ap unlock offsets
set _m3_ap_unlock_offsets {0xf0 0x44} set _sysctrl_ap_unlock_offsets {0xf0 0x44}
# All the ARMV8s are the next processors. # All the ARMV8s are the next processors.
# CL0,CORE0 CL0,CORE1 CL1,CORE0 CL1,CORE1 # 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 # (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_DBGBASE {0x9d010000 0x9d012000 0x9d410000 0x9d412000 0x9d510000 0x9d512000}
set R5_CTIBASE {0x9d018000 0x9d019000 0x9d418000 0x9d419000 0x9d518000 0x9d519000} 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} set CM4_CTIBASE {0x20001000}
# M4 may be present on some very few SoCs # General Purpose MCU (M4) may be present on some very few SoCs
set _mcu_m4_cores 0 set _gp_mcu_cores 0
# M4 power-ap unlock offsets # General Purpose MCU power-ap unlock offsets
set _m4_ap_unlock_offsets {0xf0 0x60} set _gp_mcu_ap_unlock_offsets {0xf0 0x60}
# Set configuration overrides for each SOC # Set configuration overrides for each SOC
switch $_soc { switch $_soc {
@ -63,15 +64,10 @@ switch $_soc {
# AM654 has 1 cluster of 2 R5s cores. # AM654 has 1 cluster of 2 R5s cores.
set _r5_cores 2 set _r5_cores 2
set _mcu_r5_cores 2 set R5_NAMES {mcu_r5.0 mcu_r5.1}
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
# M3 power-ap unlock offsets # Sysctrl power-ap unlock offsets
set _m3_ap_unlock_offsets {0xf0 0x50} set _sysctrl_ap_unlock_offsets {0xf0 0x50}
} }
am642 { am642 {
set _CHIPNAME am642 set _CHIPNAME am642
@ -85,17 +81,37 @@ switch $_soc {
# AM642 has 2 cluster of 2 R5s cores. # AM642 has 2 cluster of 2 R5s cores.
set _r5_cores 4 set _r5_cores 4
set _mcu_r5_cores 0 set R5_NAMES {main0_r5.0 main0_r5.1 main1_r5.0 main1_r5.1}
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_DBGBASE {0x9d410000 0x9d412000 0x9d510000 0x9d512000} set R5_DBGBASE {0x9d410000 0x9d412000 0x9d510000 0x9d512000}
set R5_CTIBASE {0x9d418000 0x9d419000 0x9d518000 0x9d519000} set R5_CTIBASE {0x9d418000 0x9d419000 0x9d518000 0x9d519000}
# M4 processor # 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 { j721e {
set _CHIPNAME j721e set _CHIPNAME j721e
@ -106,12 +122,6 @@ switch $_soc {
# J721E has 3 clusters of 2 R5 cores each. # J721E has 3 clusters of 2 R5 cores each.
set _r5_cores 6 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 { j7200 {
set _CHIPNAME j7200 set _CHIPNAME j7200
@ -123,18 +133,32 @@ switch $_soc {
# J7200 has 2 clusters of 2 R5 cores each. # J7200 has 2 clusters of 2 R5 cores each.
set _r5_cores 4 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_DBGBASE {0x9d010000 0x9d012000 0x9d110000 0x9d112000}
set R5_CTIBASE {0x9d018000 0x9d019000 0x9d118000 0x9d119000} set R5_CTIBASE {0x9d018000 0x9d019000 0x9d118000 0x9d119000}
# M3 CTI base # M3 CTI base
set CM3_CTIBASE {0x20001000} 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 { default {
echo "'$_soc' is invalid!" echo "'$_soc' is invalid!"
} }
@ -147,18 +171,42 @@ set _TARGETNAME $_CHIPNAME.cpu
set _CTINAME $_CHIPNAME.cti set _CTINAME $_CHIPNAME.cti
# M3 is always present # sysctrl is always present
cti create $_CTINAME.m3 -dap $_CHIPNAME.dap -ap-num 7 -baseaddr [lindex $CM3_CTIBASE 0] cti create $_CTINAME.sysctrl -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 target create $_TARGETNAME.sysctrl cortex_m -dap $_CHIPNAME.dap -ap-num 7 -defer-examine
$_TARGETNAME.m3 configure -event reset-assert { } $_TARGETNAME.sysctrl configure -event reset-assert { }
proc m3_up { args } { proc sysctrl_up {} {
# To access M3, we need to enable the JTAG access for the same. # To access sysctrl, we need to enable the JTAG access for the same.
# Ensure Power-AP unlocked # Ensure Power-AP unlocked
$::_CHIPNAME.dap apreg 3 [lindex $::_m3_ap_unlock_offsets 0] 0x00190000 $::_CHIPNAME.dap apreg 3 [lindex $::_sysctrl_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 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 "" 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 -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" 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 # 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 } { if { $_v8_smp_debug == 0 } {
proc $_armv8_up_cmd { args } { proc $_armv8_up_cmd { args } {
foreach { _core } [set args] { foreach _core $args {
$::_TARGETNAME.$::_armv8_cpu_name.$_core arp_examine targets $_core
$::_TARGETNAME.$::_armv8_cpu_name.$_core aarch64 dbginit _cpu_no_smp_up
} }
} }
} else { } else {
proc $_armv8_smp_cmd { args } { proc $_armv8_smp_cmd { args } {
for { set _core 0 } { $_core < $::_armv8_cores } { incr _core } { _armv8_smp_up
$::_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
}
# Declare SMP # Declare SMP
target smp $:::_v8_smp_targets target smp $:::_v8_smp_targets
} }
for { set _core 0 } { $_core < $_r5_cores } { incr _core } { 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] -baseaddr [lindex $R5_CTIBASE $_core]
# inactive core examination will fail - wait till startup of additional 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 -dbgbase [lindex $R5_DBGBASE $_core] -ap-num 1 -defer-examine
}
if { $_mcu_r5_cores != 0 } { $_TARGETNAME.$_r5_name configure -event gdb-attach {
proc mcu_r5_up { args } { _cpu_no_smp_up
foreach { _core } [set args] { # gdb-attach default rule
set _core [expr {$_core + $::_mcu_base_core_id}] halt 1000
$::_TARGETNAME.r5.$_core arp_examine
$::_TARGETNAME.r5.$_core cortex_r4 dbginit
}
} }
} }
if { $_main0_r5_cores != 0 } { proc r5_up { args } {
proc main0_r5_up { args } { foreach _core $args {
foreach { _core } [set args] { targets $_core
set _core [expr {$_core + $::_main0_base_core_id}] _cpu_no_smp_up
$::_TARGETNAME.r5.$_core arp_examine
$::_TARGETNAME.r5.$_core cortex_r4 dbginit
}
} }
} }
if { $_main1_r5_cores != 0 } { if { $_gp_mcu_cores != 0 } {
proc main1_r5_up { args } { cti create $_CTINAME.gp_mcu -dap $_CHIPNAME.dap -ap-num 8 -baseaddr [lindex $CM4_CTIBASE 0]
foreach { _core } [set args] { target create $_TARGETNAME.gp_mcu cortex_m -dap $_CHIPNAME.dap -ap-num 8 -defer-examine
set _core [expr {$_core + $::_main1_base_core_id}] $_TARGETNAME.gp_mcu configure -event reset-assert { }
$::_TARGETNAME.r5.$_core arp_examine
$::_TARGETNAME.r5.$_core cortex_r4 dbginit
}
}
}
if { $_mcu_m4_cores != 0 } { proc gp_mcu_up {} {
cti create $_CTINAME.m4 -dap $_CHIPNAME.dap -ap-num 8 -baseaddr [lindex $CM4_CTIBASE 0] # To access GP MCU, we need to enable the JTAG access for the same.
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.
# Ensure Power-AP unlocked # Ensure Power-AP unlocked
$::_CHIPNAME.dap apreg 3 [lindex $::_m4_ap_unlock_offsets 0] 0x00190000 $::_CHIPNAME.dap apreg 3 [lindex $::_gp_mcu_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 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
} }
} }

View File

@ -99,7 +99,7 @@ targets $_TARGETNAME.0
proc core_up { args } { proc core_up { args } {
global _TARGETNAME global _TARGETNAME
foreach { core } [set args] { foreach core $args {
$_TARGETNAME.$core arp_examine $_TARGETNAME.$core arp_examine
} }
} }

View File

@ -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}]
}

View File

@ -50,7 +50,7 @@ proc load_and_run { name halfwords n_instr } {
echo "# code to trigger $name vector" echo "# code to trigger $name vector"
set addr 0x20000000 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 # compute the resulting $addr ourselves
foreach opcode $halfwords { foreach opcode $halfwords {
mwh $addr $opcode mwh $addr $opcode