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:
commit
00d7c7994a
|
@ -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"
|
||||||
])
|
])
|
||||||
])
|
])
|
||||||
|
|
11
configure.ac
11
configure.ac
|
@ -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.])
|
||||||
])
|
])
|
||||||
|
|
|
@ -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ве1т") # better to clear the array before
|
|
||||||
self.send("array set 1986ве1т { %s }" % array)
|
|
||||||
self.send("array2mem 1986ве1т 0x%x %s %d" % (wordLen, address, n))
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
|
||||||
|
|
184
doc/openocd.texi
184
doc/openocd.texi
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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>
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
@ -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++) {
|
||||||
|
|
|
@ -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 "$"
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -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>
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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++;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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++;
|
||||||
|
|
|
@ -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 */
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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, ®_value);
|
retval = target_read_u32(target, DWT_PCSR, ®_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;
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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++;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -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 = "",
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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} {
|
||||||
|
|
|
@ -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++;
|
||||||
|
|
|
@ -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",
|
||||||
|
|
|
@ -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 ?
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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 { } {
|
||||||
|
|
|
@ -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 {} {
|
||||||
|
|
|
@ -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 { } {
|
||||||
|
|
|
@ -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 { } {
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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]
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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"
|
||||||
|
|
|
@ -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"
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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}]]
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
|
@ -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 }
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
|
||||||
}
|
|
||||||
|
|
|
@ -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}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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
|
|
||||||
}
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
}
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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}]
|
||||||
|
}
|
|
@ -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
|
||||||
|
|
Loading…
Reference in New Issue