From upstream (#684)

* flash/nor/atsame5: add LAN9255 devices

Support Microchip LAN9255 devices with embedded SAME53J MCU.

Signed-off-by: Hans-Erik Floryd <hans-erik.floryd@rt-labs.com>
Change-Id: Ia811c593bf7cf73e588d32873c68eb67c6fafad7
Reviewed-on: https://review.openocd.org/c/openocd/+/6811
Tested-by: jenkins
Reviewed-by: Antonio Borneo <borneo.antonio@gmail.com>
Reviewed-by: Tomas Vanek <vanekt@fbl.cz>

* tcl/board: Add EVB-LAN9255 config

Config for EVB-LAN9255, tested using Atmel-ICE debugger on J10
connector.

Signed-off-by: Hans-Erik Floryd <hans-erik.floryd@rt-labs.com>
Change-Id: I8bcf779e9363499a98aa0b7d10819c53da6a19e7
Reviewed-on: https://review.openocd.org/c/openocd/+/6812
Tested-by: jenkins
Reviewed-by: Antonio Borneo <borneo.antonio@gmail.com>

* aarch64: support for aarch32 ARM_MODE_UND

Fix:
unrecognized psr mode: 0x1b
cannot read system control register in this mode: (UNRECOGNIZED : 0x1b)

Change-Id: I4dc3e72f90d57e52c0fe63cb59a7529a398757b3

Signed-off-by: Julien Massot <julien.massot@iot.bzh>
Change-Id: Ifa5d21ae97492fde9e8c79ee7d99d8a2a871b1b5
Reviewed-on: https://review.openocd.org/c/openocd/+/6808
Tested-by: jenkins
Reviewed-by: Antonio Borneo <borneo.antonio@gmail.com>

* Combine register lists of smp targets.

This is helpful when you want to pretend to gdb that your heterogeneous
multicore system is homogeneous, because gdb cannot handle heterogeneous
systems. This won't always works, but works fine if e.g. one of the
cores has an FPU while the other does not. (Specifically, HiFive
Unleashed has 1 core with no FPU, plus 4 cores with an FPU.)

Signed-off-by: Tim Newsome <tim@sifive.com>
Change-Id: I05ff4c28646778fbc00327bc510be064bfe6c9f0
Reviewed-on: https://review.openocd.org/c/openocd/+/6362
Tested-by: jenkins
Reviewed-by: Antonio Borneo <borneo.antonio@gmail.com>

* semihosting: use open mode flags from GDB, not from sys/stat.h

Values defined in sys/stat.h are not guaranteed to match
the constants defined by the GDB remote protocol, which are defined in
https://sourceware.org/gdb/onlinedocs/gdb/Open-Flags.html#Open-Flags.
On my local system (Manjaro 21.2.1 x86_64), for example, O_TRUNC is
defined as 0x40, whereas GDB requires it to be 0x400,
causing all "w" file open modes to misbehave.

This patch has been tested with STM32F446.

Change-Id: Ifb2c740fd689e71d6f1a4bde1edaecd76fdca910
Signed-off-by: Pavel Kirienko <pavel.kirienko@gmail.com>
Reviewed-on: https://review.openocd.org/c/openocd/+/6804
Tested-by: jenkins
Reviewed-by: Antonio Borneo <borneo.antonio@gmail.com>

* semihosting: User defined operation, Tcl command exec on host

Enabling a portion (0x100 - 0x107) of the user defined semihosting
operation number range (0x100 - 0x1FF) to be processed with the help of
the existing target event mechanism, to implement a general-purpose Tcl
interface for the target available on the host, via semihosting
interface.

Example usage:
- The user configures a Tcl command as a callback for one of the newly
	defined events (semihosting-user-cmd-0x10X) in the configuration
	file.
- The target can make a semihosting call with <opnum>, passing optional
	parameters for the call.

If there is no callback registered to the user defined operation number,
nothing happens.

Example usage: Configure RTT automatically with the exact, linked
control block location from target.

Signed-off-by: Zoltán Dudás <zedudi@gmail.com>
Change-Id: I10e1784b1fecd4e630d78df81cb44bf1aa2fc247
Reviewed-on: https://review.openocd.org/c/openocd/+/6748
Tested-by: jenkins
Reviewed-by: Oleksij Rempel <linux@rempel-privat.de>
Reviewed-by: Antonio Borneo <borneo.antonio@gmail.com>

* target/smp: use a struct list_head to hold the smp targets

Instead of reinventing a simply linked list, reuse the list helper
for the list of targets in a smp cluster.
Using the existing helper, that implements a double linked list,
makes trivial going through the list in reverse order.

Change-Id: Ib36ad2955f15cd2a601b0b9e36ca6d948b12d00f
Signed-off-by: Antonio Borneo <borneo.antonio@gmail.com>
Reviewed-on: https://review.openocd.org/c/openocd/+/6783
Tested-by: jenkins

* helper/list: add list_for_each_entry_direction()

Use a bool flag to specify if the list should be forward or
backward iterated.

Change-Id: Ied19d049f46cdcb7f50137d459cc7c02014526bc
Signed-off-by: Antonio Borneo <borneo.antonio@gmail.com>
Reviewed-on: https://review.openocd.org/c/openocd/+/6784
Tested-by: jenkins

* target/riscv: revive 'riscv resume_order'

This functionality was lost in [1], which was merged as commit
615709d140 ("Upstream a whole host of RISC-V changes.").
Now it works as expected again.

Add convenience macro foreach_smp_target_direction().

Link: [1] https://github.com/riscv/riscv-openocd/pull/567
Change-Id: I1545fa6b45b8a07e27c8ff9dcdcfa2fc4f950cd1
Signed-off-by: Tim Newsome <tim@sifive.com>
Signed-off-by: Antonio Borneo <borneo.antonio@gmail.com>
Reviewed-on: https://review.openocd.org/c/openocd/+/6785
Tested-by: jenkins

* doxygen: fix some function prototype description

Change-Id: I49311a643ea73143839d2f6bde976cfd76f8c67f
Signed-off-by: Antonio Borneo <borneo.antonio@gmail.com>
Reviewed-on: https://review.openocd.org/c/openocd/+/6830
Tested-by: jenkins

* Cadence virtual debug interface (vdebug) integration

Change-Id: I1bc105b3addc3f34161c2356c482ff3011e3f2cc
Signed-off-by: Jacek Wuwer <jacekmw8@gmail.com>
Reviewed-on: https://review.openocd.org/c/openocd/+/6097
Tested-by: jenkins
Reviewed-by: Oleksij Rempel <linux@rempel-privat.de>
Reviewed-by: zapb <dev@zapb.de>
Reviewed-by: Antonio Borneo <borneo.antonio@gmail.com>

* gdb_server: Include thread name as XML attribute

Explicitly providing a thread name in the "thread" element produces
better thread visualizations in downstream tools like IDEs.

Signed-off-by: Ben McMorran <bemcmorr@microsoft.com>
Change-Id: I102c14ddb8b87757fa474de8e3a3f6a1cfe10d98
Reviewed-on: https://review.openocd.org/c/openocd/+/6828
Tested-by: jenkins
Reviewed-by: zapb <dev@zapb.de>
Reviewed-by: Antonio Borneo <borneo.antonio@gmail.com>

* Fix small memory leak.

See https://github.com/riscv/riscv-openocd/pull/672

Change-Id: Ia11ab9bcf860f770ea64ad867102c74b898f6b66
Signed-off-by: Tim Newsome <tim@sifive.com>
Reviewed-on: https://review.openocd.org/c/openocd/+/6831
Tested-by: jenkins
Reviewed-by: zapb <dev@zapb.de>
Reviewed-by: Antonio Borneo <borneo.antonio@gmail.com>

* server: remove remaining crust from dropped eCos code

Commit 39650e2273 ("ecosboard: delete bit-rotted eCos code") has
removed eCos code but has left some empty function that was used
during non-eCos build to replace eCos mutex.

Drop the functions and the file that contain them.

Change-Id: I31bc0237ea699c11bd70921660f960ee406ffa80
Signed-off-by: Antonio Borneo <borneo.antonio@gmail.com>
Reviewed-on: https://review.openocd.org/c/openocd/+/6835
Tested-by: jenkins
Reviewed-by: Tomas Vanek <vanekt@fbl.cz>

* rtos: threadx: Add hla_target support for ThreadX

Tested with an AZ3166 dev board (which uses the STM32F412ZGT6) running
the Azure RTOS ThreadX demonstration system.

Signed-off-by: Ben McMorran <bemcmorr@microsoft.com>
Change-Id: I44c8f7701d9f1aaa872274166321cd7d34fb1855
Reviewed-on: https://review.openocd.org/c/openocd/+/6829
Tested-by: jenkins
Reviewed-by: Antonio Borneo <borneo.antonio@gmail.com>

* .gitmodules: switch away from repo.or.cz

The host repo.or.cz is often offline, creating issues for cloning
and building OpenOCD from scratch.
Already 'jimtcl' developer has dropped repo.or.cz, triggering the
OpenOCD commit 861e75f54e ("jimtcl: switch to github").

Change also the link of the remaining submodules 'git2cl' and
'libjaylink' to their respective main repository.

Change-Id: Ib513237427635359ce36a480a8f2060e2fb12ba4
Signed-off-by: Antonio Borneo <borneo.antonio@gmail.com>
Reviewed-on: https://review.openocd.org/c/openocd/+/6834
Tested-by: jenkins
Reviewed-by: zapb <dev@zapb.de>

* flash/nor/stm32f2x: Fix erase of bank 2 sectors

This commit corrects the erase function for stm32f2x when dealing with
sectors in bank 2, for STM32F42x/43x devices with 1MB flash.

On STM32F42x/43x with 1MB flash in dual bank configuration, the sector
numbering is not consecutive. The last sector in bank 1 is number 7, and
the first sector in bank 2 is number 12.
The sector indices used by openocd, however, _are_ consecutive (0 to 15
in this case). The arguments "first" and "last" to stm32x_erase() are of
this type, and so the logic surrounding sector numbers needed to be
corrected.
Since the two banks in dual bank mode have the same number of sectors, a
sector index in bank 2 is larger than or equal to half the total number
of sectors.

Change-Id: I15260f8a86d9002769a1ae1c40ebdf62142dae18
Signed-off-by: Simon Johansson <ampleyfly@gmail.com>
Reviewed-on: https://review.openocd.org/c/openocd/+/6810
Tested-by: jenkins
Reviewed-by: Tomas Vanek <vanekt@fbl.cz>
Reviewed-by: Tarek BOCHKATI <tarek.bouchkati@gmail.com>

* target/cortex_m: fix target_to_cm() helper

The third parameter of container_of() should point to the same member
as target->arch_info points to, struct arm.

It worked just because struct arm is the first member in
struct armv7m_common.
If you move arm member from the first place, OpenOCD fails heavily.

Change-Id: I0c0a5221490945563e17a0a34d99a603f1d6c2ff
Signed-off-by: Tomas Vanek <vanekt@fbl.cz>
Reviewed-on: https://review.openocd.org/c/openocd/+/6749
Tested-by: jenkins
Reviewed-by: Antonio Borneo <borneo.antonio@gmail.com>

* target/armv7m,cortex_m: introduce checked arch_info cast routines

target_to_armv7m() and target_to_cm() do not match the magic number
so they are not suitable for use outside of target driver code.

Add checked versions of pointer getters. Match the magic number
to ensure the returned value points to struct of the correct type.

Change-Id: If90ef7e969ef04f0f2103e0da29dcbe8e1ac1c0d
Signed-off-by: Tomas Vanek <vanekt@fbl.cz>
Reviewed-on: https://review.openocd.org/c/openocd/+/6750
Tested-by: jenkins
Reviewed-by: Antonio Borneo <borneo.antonio@gmail.com>

* target/cortex_m: add Cortex-M part number getter

The getter checks the magic numbers in arch_info to detect eventual
type mismatch.

Change-Id: I61134b05310a97ae9831517d0516c7b4240d35a5
Signed-off-by: Tomas Vanek <vanekt@fbl.cz>
Reviewed-on: https://review.openocd.org/c/openocd/+/6751
Tested-by: jenkins
Reviewed-by: Antonio Borneo <borneo.antonio@gmail.com>
Reviewed-by: Tarek BOCHKATI <tarek.bouchkati@gmail.com>

* flash/nor/stm32xx: fix segfault accessing Cortex-M part number

Some of STM32 flash drivers read Cortex-M part number from
cortex_m->core_info.
In corner cases the core_info pointer was observed uninitialised
even if target_was_examined() returned true. See also [1]

Use the new and safe helper to get Cortex-M part number.

While on it switch also target_to_cm()/target_to_armv7m() to the safe
versions. This prevents a crash when the flash bank is misconfigured
with non-Cortex-M target.

Add missing checks for target_was_examined() to flash probes.

[1] 6545: fix crash in case cortex_m->core_info is not set
    https://review.openocd.org/c/openocd/+/6545

Change-Id: If2471af74ebfe22f14442f48ae109b2e1bb5fa3b
Signed-off-by: Tomas Vanek <vanekt@fbl.cz>
Fixes: f5898bd93f (flash/stm32fxx.c: do not read CPUID as this info is stored in cortex_m_common)
Reviewed-on: https://review.openocd.org/c/openocd/+/6752
Tested-by: jenkins
Reviewed-by: Antonio Borneo <borneo.antonio@gmail.com>
Reviewed-by: Tarek BOCHKATI <tarek.bouchkati@gmail.com>

* cpld: altera-epm240: Add additional IDCODEs

This adds some additional IDCODEs from the datasheet. It also adds
support for customizing the tap name.

Signed-off-by: Sean Anderson <sean.anderson@seco.com>
Change-Id: I7cda10b92c229b61836c12cd9ca410de358ede2e
Reviewed-on: https://review.openocd.org/c/openocd/+/6846
Tested-by: jenkins
Reviewed-by: Antonio Borneo <borneo.antonio@gmail.com>

* cpld: altera-epm240: Increase adapter speed

According to the datasheet, the minimum clock period with Vccio1 = 1.5V
(the lowest voltage supported) is 143ns, or around 6MHz. Set the default
adapter speed to 5 MHz.

Signed-off-by: Sean Anderson <sean.anderson@seco.com>
Change-Id: I21cad33fa7f1e25e81f43b5d2214d1fa4ec924de
Reviewed-on: https://review.openocd.org/c/openocd/+/6847
Tested-by: jenkins
Reviewed-by: Antonio Borneo <borneo.antonio@gmail.com>

* target: Add support for ls1088a

The LS1088A is an octo-core aarch64 processor from NXP in the layerscape
family. The JTAG is undocumented, but I was able to figure things out
from the output of `dap info`. This is the first in-tree example of
using the hwthread rtos (as far as I know), so hopefully it can serve as
an example to other developers. There are some ETMs, but I was unable to
try them out because I got 'invalid command name "etm"' when trying to
test things out.

Signed-off-by: Sean Anderson <sean.anderson@seco.com>
Change-Id: I9b0791d27d8c41170a413a8d86431107a85feba2
Reviewed-on: https://review.openocd.org/c/openocd/+/6848
Tested-by: jenkins
Reviewed-by: Antonio Borneo <borneo.antonio@gmail.com>

* target: ls1088a: Add service processor

Normally the service processor is not necessary for debugging. However,
if you are using the hard-coded RCW or your boot source is otherwise
corrupt, then the general purpose processors will never be released from
hold-off. This will cause GDB to become confused if it tries to attach,
since they will appear to be running arm32 processors. To deal with
this, we can release the CPUs manually with the BRRL register. This
register cannot be written to from the axi target, so we need to do it
from the service processor target. This involves halting the service
processor, modifying the register, and then resuming it again. We try
and determine what state the service processor was in to avoid resuming
it if it was already halted.

The reset vector for the general purpose processors is determined by the
boot logation pointer registers in the device configuration unit.
Normally these are set using pre-boot initialization commands, but if
they are not set then they default to 0. This will cause the CPU to
almost immediately hit an illegal instruction. This is fine because we
will almost certainly want to attach to the processor and load a program
anyway.

I considered adding this as an event handler for either gdb-attach or
reset-init. However, this command shouldn't be necessary most of the
time, and so I don't think we should run it automatically.

Signed-off-by: Sean Anderson <sean.anderson@seco.com>
Change-Id: I1b725292d8a11274d03af5313dc83678e10e944c
Reviewed-on: https://review.openocd.org/c/openocd/+/6850
Tested-by: jenkins
Reviewed-by: Antonio Borneo <borneo.antonio@gmail.com>

* board: Add NXP LS1088ARDB

This adds a board file for the NXP LS1088ARDB. This only covers the
"primary" JTAG header J55, and not the PCIe header (J91). The only
oddity is that the LS1088A and CPLD are muxed by adding/removing a
jumper from J48. Unfortunately, it doesn't look like OpenOCD supports
this CPLD beyond determining the irlen, so it's not very useful. Those
who are interested in experimenting can define CWTAP to access the CPLD,
but the default is to access the CPU.

Signed-off-by: Sean Anderson <sean.anderson@seco.com>
Change-Id: Ia07436a534f86bd907aa5fe2a78a326a27855a24
Reviewed-on: https://review.openocd.org/c/openocd/+/6849
Tested-by: jenkins
Reviewed-by: Antonio Borneo <borneo.antonio@gmail.com>

* gdb_server: fix double free

Commit 6541233aa7 ("Combine register lists of smp targets.")
unconditionally assigns the output pointers of the function
smp_reg_list_noread(), even if the function fails and returns
error.
This causes a double free from the caller, that has assigned NULL
to the pointers to simplify the error handling.

Use local variables in smp_reg_list_noread() and assign the output
pointers only on success.

Change-Id: Ic0fd2f26520566cf322f0190780e15637c01cfae
Fixes: 6541233aa7 ("Combine register lists of smp targets.")
Reported-by: Michele Bisogno <michele.bisogno.ct@renesas.com>
Signed-off-by: Antonio Borneo <borneo.antonio@gmail.com>
Reviewed-on: https://review.openocd.org/c/openocd/+/6852
Tested-by: jenkins
Reviewed-by: Michele Bisogno <michele.bisogno.ct@renesas.com>
Reviewed-by: Tim Newsome <tim@sifive.com>

* gdb_server: check target examined while combining reg list

Commit 6541233aa7 ("Combine register lists of smp targets.")
assumes that all the targets in the SMP cluster are already
examined and unconditionally call target_get_gdb_reg_list_noread()
that will in turn return error if the target is not examined yet.

Skip targets not examined yet.
Add an additional check in case the register list cannot be built,
e.g. because no target in the SMP cluster is examined. This should
never happen, but it's better to play safe.

Change-Id: I8609815c3d5144790fb05a870cb0c931540aef8a
Fixes: 6541233aa7 ("Combine register lists of smp targets.")
Reported-by: Michele Bisogno <michele.bisogno.ct@renesas.com>
Signed-off-by: Antonio Borneo <borneo.antonio@gmail.com>
Reviewed-on: https://review.openocd.org/c/openocd/+/6853
Tested-by: jenkins
Reviewed-by: Michele Bisogno <michele.bisogno.ct@renesas.com>
Reviewed-by: Tim Newsome <tim@sifive.com>

* flash/stm32l4x: fix maybe-uninitialized compiler error

using gcc (Ubuntu 9.3.0-17ubuntu1~20.04) 9.3.0 we get:
error: ‘retval’ may be used uninitialized in this function

fixes: 13cd75b6ec (flash/nor/stm32xx: fix segfault accessing Cortex-M part number)
Change-Id: I897c40c5d2233f50a5385d251ebfa536023e5cf7
Signed-off-by: Tarek BOCHKATI <tarek.bouchkati@gmail.com>
Reviewed-on: https://review.openocd.org/c/openocd/+/6861
Tested-by: jenkins
Reviewed-by: Tomas Vanek <vanekt@fbl.cz>
Reviewed-by: Antonio Borneo <borneo.antonio@gmail.com>

* Fix build.

Change-Id: Ia60246246dd859d75659a43d1c59588dbb274d46
Signed-off-by: Tim Newsome <tim@sifive.com>

Co-authored-by: Hans-Erik Floryd <hans-erik.floryd@rt-labs.com>
Co-authored-by: Julien Massot <julien.massot@iot.bzh>
Co-authored-by: Pavel Kirienko <pavel.kirienko@gmail.com>
Co-authored-by: Zoltán Dudás <zedudi@gmail.com>
Co-authored-by: Antonio Borneo <borneo.antonio@gmail.com>
Co-authored-by: Jacek Wuwer <jacekmw8@gmail.com>
Co-authored-by: Ben McMorran <bemcmorr@microsoft.com>
Co-authored-by: Simon Johansson <ampleyfly@gmail.com>
Co-authored-by: Tomas Vanek <vanekt@fbl.cz>
Co-authored-by: Sean Anderson <sean.anderson@seco.com>
Co-authored-by: Tarek BOCHKATI <tarek.bouchkati@gmail.com>
This commit is contained in:
Tim Newsome 2022-03-03 10:03:55 -08:00 committed by GitHub
parent 87c0cda00f
commit 9e097d0fc4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
56 changed files with 2046 additions and 322 deletions

View File

@ -275,6 +275,10 @@ AC_ARG_ENABLE([jtag_vpi],
AS_HELP_STRING([--enable-jtag_vpi], [Enable building support for JTAG VPI]),
[build_jtag_vpi=$enableval], [build_jtag_vpi=no])
AC_ARG_ENABLE([vdebug],
AS_HELP_STRING([--enable-vdebug], [Enable building support for Cadence Virtual Debug Interface]),
[build_vdebug=$enableval], [build_vdebug=no])
AC_ARG_ENABLE([jtag_dpi],
AS_HELP_STRING([--enable-jtag_dpi], [Enable building support for JTAG DPI]),
[build_jtag_dpi=$enableval], [build_jtag_dpi=no])
@ -514,6 +518,12 @@ AS_IF([test "x$build_jtag_vpi" = "xyes"], [
AC_DEFINE([BUILD_JTAG_VPI], [0], [0 if you don't want JTAG VPI.])
])
AS_IF([test "x$build_vdebug" = "xyes"], [
AC_DEFINE([BUILD_VDEBUG], [1], [1 if you want Cadence vdebug interface.])
], [
AC_DEFINE([BUILD_VDEBUG], [0], [0 if you don't want Cadence vdebug interface.])
])
AS_IF([test "x$build_jtag_dpi" = "xyes"], [
AC_DEFINE([BUILD_JTAG_DPI], [1], [1 if you want JTAG DPI.])
], [
@ -689,8 +699,9 @@ AM_CONDITIONAL([AT91RM9200], [test "x$build_at91rm9200" = "xyes"])
AM_CONDITIONAL([BCM2835GPIO], [test "x$build_bcm2835gpio" = "xyes"])
AM_CONDITIONAL([IMX_GPIO], [test "x$build_imx_gpio" = "xyes"])
AM_CONDITIONAL([BITBANG], [test "x$build_bitbang" = "xyes"])
AM_CONDITIONAL([JTAG_VPI], [test "x$build_jtag_vpi" = "xyes" -o "x$build_jtag_vpi" = "xyes"])
AM_CONDITIONAL([JTAG_DPI], [test "x$build_jtag_dpi" = "xyes" -o "x$build_jtag_dpi" = "xyes"])
AM_CONDITIONAL([JTAG_VPI], [test "x$build_jtag_vpi" = "xyes"])
AM_CONDITIONAL([VDEBUG], [test "x$build_vdebug" = "xyes"])
AM_CONDITIONAL([JTAG_DPI], [test "x$build_jtag_dpi" = "xyes"])
AM_CONDITIONAL([USB_BLASTER_DRIVER], [test "x$enable_usb_blaster" != "xno" -o "x$enable_usb_blaster_2" != "xno"])
AM_CONDITIONAL([AMTJTAGACCEL], [test "x$build_amtjtagaccel" = "xyes"])
AM_CONDITIONAL([GW16012], [test "x$build_gw16012" = "xyes"])

View File

@ -588,6 +588,12 @@ produced, PDF schematics are easily found and it is easy to make.
@* A JTAG driver acting as a client for the JTAG VPI server interface.
@* Link: @url{http://github.com/fjullien/jtag_vpi}
@item @b{vdebug}
@* A driver for Cadence virtual Debug Interface to emulated or simulated targets.
It implements a client connecting to the vdebug server, which in turn communicates
with the emulated or simulated RTL model through a transactor. The current version
supports only JTAG as a transport, but other virtual transports, like DAP are planned.
@item @b{jtag_dpi}
@* A JTAG driver acting as a client for the SystemVerilog Direct Programming
Interface (DPI) for JTAG devices. DPI allows OpenOCD to connect to the JTAG
@ -3345,6 +3351,41 @@ This value is only used with the standard variant.
@end deffn
@deffn {Interface Driver} {vdebug}
Cadence Virtual Debug Interface driver.
@deffn {Config Command} {vdebug server} host:port
Specifies the host and TCP port number where the vdebug server runs.
@end deffn
@deffn {Config Command} {vdebug batching} value
Specifies the batching method for the vdebug request. Possible values are
0 for no batching
1 or wr to batch write transactions together (default)
2 or rw to batch both read and write transactions
@end deffn
@deffn {Config Command} {vdebug polling} min max
Takes two values, representing the polling interval in ms. Lower values mean faster
debugger responsiveness, but lower emulation performance. The minimum should be
around 10, maximum should not exceed 1000, which is the default gdb and keepalive
timeout value.
@end deffn
@deffn {Config Command} {vdebug bfm_path} path clk_period
Specifies the hierarchical path and input clk period of the vdebug BFM in the design.
The hierarchical path uses Verilog notation top.inst.inst
The clock period must include the unit, for instance 40ns.
@end deffn
@deffn {Config Command} {vdebug mem_path} path base size
Specifies the hierarchical path to the design memory instance for backdoor access.
Up to 4 memories can be specified. The hierarchical path uses Verilog notation.
The base specifies start address in the design address space, size its size in bytes.
Both values can use hexadecimal notation with prefix 0x.
@end deffn
@end deffn
@deffn {Interface Driver} {jtag_dpi}
SystemVerilog Direct Programming Interface (DPI) compatible driver for
JTAG devices in emulation. The driver acts as a client for the SystemVerilog
@ -5185,6 +5226,22 @@ when reset disables PLLs needed to use a fast clock.
@* After single-step has completed
@item @b{trace-config}
@* After target hardware trace configuration was changed
@item @b{semihosting-user-cmd-0x100}
@* The target made a semihosting call with user-defined operation number 0x100
@item @b{semihosting-user-cmd-0x101}
@* The target made a semihosting call with user-defined operation number 0x101
@item @b{semihosting-user-cmd-0x102}
@* The target made a semihosting call with user-defined operation number 0x102
@item @b{semihosting-user-cmd-0x103}
@* The target made a semihosting call with user-defined operation number 0x103
@item @b{semihosting-user-cmd-0x104}
@* The target made a semihosting call with user-defined operation number 0x104
@item @b{semihosting-user-cmd-0x105}
@* The target made a semihosting call with user-defined operation number 0x105
@item @b{semihosting-user-cmd-0x106}
@* The target made a semihosting call with user-defined operation number 0x106
@item @b{semihosting-user-cmd-0x107}
@* The target made a semihosting call with user-defined operation number 0x107
@end itemize
@quotation Note
@ -9241,6 +9298,17 @@ To make the SEMIHOSTING_SYS_EXIT call return normally, enable
this option (default: disabled).
@end deffn
@deffn {Command} {arm semihosting_read_user_param}
@cindex ARM semihosting
Read parameter of the semihosting call from the target. Usable in
semihosting-user-cmd-0x10* event handlers, returning a string.
When the target makes semihosting call with operation number from range 0x100-
0x107, an optional string parameter can be passed to the server. This parameter
is valid during the run of the event handlers and is accessible with this
command.
@end deffn
@section ARMv4 and ARMv5 Architecture
@cindex ARMv4
@cindex ARMv5

View File

@ -146,6 +146,9 @@ static const struct samd_part same53_parts[] = {
{ 0x04, "SAME53J20A", 1024, 256 },
{ 0x05, "SAME53J19A", 512, 192 },
{ 0x06, "SAME53J18A", 256, 128 },
{ 0x55, "LAN9255/ZMX020", 1024, 256 },
{ 0x56, "LAN9255/ZMX019", 512, 192 },
{ 0x57, "LAN9255/ZMX018", 256, 128 },
};
/* Known SAME54 parts. */

View File

@ -622,15 +622,14 @@ cleanup:
static int stm32x_get_device_id(struct flash_bank *bank, uint32_t *device_id)
{
struct target *target = bank->target;
struct cortex_m_common *cortex_m = target_to_cm(target);
uint32_t device_id_register = 0;
if (!target_was_examined(target)) {
LOG_ERROR("Target not examined yet");
return ERROR_FAIL;
return ERROR_TARGET_NOT_EXAMINED;
}
switch (cortex_m->core_info->partno) {
switch (cortex_m_get_partno_safe(target)) {
case CORTEX_M0_PARTNO: /* STM32F0x devices */
device_id_register = 0x40015800;
break;
@ -659,15 +658,14 @@ static int stm32x_get_device_id(struct flash_bank *bank, uint32_t *device_id)
static int stm32x_get_flash_size(struct flash_bank *bank, uint16_t *flash_size_in_kb)
{
struct target *target = bank->target;
struct cortex_m_common *cortex_m = target_to_cm(target);
uint32_t flash_size_reg;
if (!target_was_examined(target)) {
LOG_ERROR("Target not examined yet");
return ERROR_FAIL;
return ERROR_TARGET_NOT_EXAMINED;
}
switch (cortex_m->core_info->partno) {
switch (cortex_m_get_partno_safe(target)) {
case CORTEX_M0_PARTNO: /* STM32F0x devices */
flash_size_reg = 0x1FFFF7CC;
break;

View File

@ -636,8 +636,8 @@ static int stm32x_erase(struct flash_bank *bank, unsigned int first,
for (unsigned int i = first; i <= last; i++) {
unsigned int snb;
if (stm32x_info->has_large_mem && i >= 12)
snb = (i - 12) | 0x10;
if (stm32x_info->has_large_mem && i >= (bank->num_sectors / 2))
snb = (i - (bank->num_sectors / 2)) | 0x10;
else
snb = i;
@ -966,14 +966,14 @@ static int stm32x_get_device_id(struct flash_bank *bank, uint32_t *device_id)
* Only effects Rev A silicon */
struct target *target = bank->target;
struct cortex_m_common *cortex_m = target_to_cm(target);
/* read stm32 device id register */
int retval = target_read_u32(target, 0xE0042000, device_id);
if (retval != ERROR_OK)
return retval;
if ((*device_id & 0xfff) == 0x411 && cortex_m->core_info->partno == CORTEX_M4_PARTNO) {
if ((*device_id & 0xfff) == 0x411
&& cortex_m_get_partno_safe(target) == CORTEX_M4_PARTNO) {
*device_id &= ~((0xFFFF << 16) | 0xfff);
*device_id |= (0x1000 << 16) | 0x413;
LOG_INFO("stm32f4x errata detected - fixing incorrect MCU_IDCODE");
@ -1011,6 +1011,11 @@ static int stm32x_probe(struct flash_bank *bank)
bank->num_prot_blocks = 0;
bank->prot_blocks = NULL;
if (!target_was_examined(target)) {
LOG_ERROR("Target not examined yet");
return ERROR_TARGET_NOT_EXAMINED;
}
/* if explicitly called out as OTP bank, short circuit probe */
if (stm32x_is_otp(bank)) {
if (stm32x_otp_is_f7(bank)) {

View File

@ -759,7 +759,6 @@ static int stm32x_read_id_code(struct flash_bank *bank, uint32_t *id)
static int stm32x_probe(struct flash_bank *bank)
{
struct target *target = bank->target;
struct cortex_m_common *cortex_m = target_to_cm(target);
struct stm32h7x_flash_bank *stm32x_info = bank->driver_priv;
uint16_t flash_size_in_kb;
uint32_t device_id;
@ -767,6 +766,11 @@ static int stm32x_probe(struct flash_bank *bank)
stm32x_info->probed = false;
stm32x_info->part_info = NULL;
if (!target_was_examined(target)) {
LOG_ERROR("Target not examined yet");
return ERROR_TARGET_NOT_EXAMINED;
}
int retval = stm32x_read_id_code(bank, &stm32x_info->idcode);
if (retval != ERROR_OK)
return retval;
@ -800,7 +804,8 @@ static int stm32x_probe(struct flash_bank *bank)
/* get flash size from target */
/* STM32H74x/H75x, the second core (Cortex-M4) cannot read the flash size */
retval = ERROR_FAIL;
if (device_id == DEVID_STM32H74_H75XX && cortex_m->core_info->partno == CORTEX_M4_PARTNO)
if (device_id == DEVID_STM32H74_H75XX
&& cortex_m_get_partno_safe(target) == CORTEX_M4_PARTNO)
LOG_WARNING("%s cannot read the flash size register", target_name(target));
else
retval = target_read_u16(target, stm32x_info->part_info->fsize_addr, &flash_size_in_kb);

View File

@ -1632,13 +1632,14 @@ err_lock:
static int stm32l4_read_idcode(struct flash_bank *bank, uint32_t *id)
{
int retval;
int retval = ERROR_OK;
struct target *target = bank->target;
/* try reading possible IDCODE registers, in the following order */
uint32_t dbgmcu_idcode[] = {DBGMCU_IDCODE_L4_G4, DBGMCU_IDCODE_G0, DBGMCU_IDCODE_L5};
for (unsigned int i = 0; i < ARRAY_SIZE(dbgmcu_idcode); i++) {
retval = target_read_u32(bank->target, dbgmcu_idcode[i], id);
retval = target_read_u32(target, dbgmcu_idcode[i], id);
if ((retval == ERROR_OK) && ((*id & 0xfff) != 0) && ((*id & 0xfff) != 0xfff))
return ERROR_OK;
}
@ -1647,12 +1648,16 @@ static int stm32l4_read_idcode(struct flash_bank *bank, uint32_t *id)
* DBGMCU_IDCODE cannot be read using CPU1 (Cortex-M0+) at AP1,
* to solve this read the UID64 (IEEE 64-bit unique device ID register) */
struct cortex_m_common *cortex_m = target_to_cm(bank->target);
struct armv7m_common *armv7m = target_to_armv7m_safe(target);
if (!armv7m) {
LOG_ERROR("Flash requires Cortex-M target");
return ERROR_TARGET_INVALID;
}
/* CPU2 (Cortex-M0+) is supported only with non-hla adapters because it is on AP1.
* Using HLA adapters armv7m.debug_ap is null, and checking ap_num triggers a segfault */
if (cortex_m->core_info->partno == CORTEX_M0P_PARTNO &&
cortex_m->armv7m.debug_ap && cortex_m->armv7m.debug_ap->ap_num == 1) {
if (cortex_m_get_partno_safe(target) == CORTEX_M0P_PARTNO &&
armv7m->debug_ap && armv7m->debug_ap->ap_num == 1) {
uint32_t uid64_ids;
/* UID64 is contains
@ -1662,7 +1667,7 @@ static int stm32l4_read_idcode(struct flash_bank *bank, uint32_t *id)
*
* read only the fixed values {STID,DEVID} from UID64_IDS to identify the device as STM32WLx
*/
retval = target_read_u32(bank->target, UID64_IDS, &uid64_ids);
retval = target_read_u32(target, UID64_IDS, &uid64_ids);
if (retval == ERROR_OK && uid64_ids == UID64_IDS_STM32WL) {
/* force the DEV_ID to DEVID_STM32WLE_WL5XX and the REV_ID to unknown */
*id = DEVID_STM32WLE_WL5XX;
@ -1700,11 +1705,21 @@ static const char *get_stm32l4_bank_type_str(struct flash_bank *bank)
static int stm32l4_probe(struct flash_bank *bank)
{
struct target *target = bank->target;
struct armv7m_common *armv7m = target_to_armv7m(target);
struct stm32l4_flash_bank *stm32l4_info = bank->driver_priv;
const struct stm32l4_part_info *part_info;
uint16_t flash_size_kb = 0xffff;
if (!target_was_examined(target)) {
LOG_ERROR("Target not examined yet");
return ERROR_TARGET_NOT_EXAMINED;
}
struct armv7m_common *armv7m = target_to_armv7m_safe(target);
if (!armv7m) {
LOG_ERROR("Flash requires Cortex-M target");
return ERROR_TARGET_INVALID;
}
stm32l4_info->probed = false;
/* read stm32 device id registers */

View File

@ -656,6 +656,20 @@ static inline void list_splice_tail_init(struct list_head *list,
!list_entry_is_head(pos, head, member); \
pos = list_prev_entry(pos, member))
/**
* list_for_each_entry_direction - iterate forward/backward over list of given type
* @param forward the iterate direction, true for forward, false for backward.
* @param pos the type * to use as a loop cursor.
* @param head the head for your list.
* @param member the name of the list_head within the struct.
*/
#define list_for_each_entry_direction(forward, pos, head, member) \
for (pos = forward ? list_first_entry(head, typeof(*pos), member) \
: list_last_entry(head, typeof(*pos), member); \
!list_entry_is_head(pos, head, member); \
pos = forward ? list_next_entry(pos, member) \
: list_prev_entry(pos, member))
/**
* list_prepare_entry - prepare a pos entry for use in list_for_each_entry_continue()
* @param pos the type * to use as a start point

View File

@ -75,6 +75,9 @@ endif
if JTAG_VPI
DRIVERFILES += %D%/jtag_vpi.c
endif
if VDEBUG
DRIVERFILES += %D%/vdebug.c
endif
if JTAG_DPI
DRIVERFILES += %D%/jtag_dpi.c
endif

View File

@ -114,8 +114,6 @@ static int jlink_flush(void);
* @param in A pointer to store TDO data to, if NULL the data will be discarded.
* @param in_offset A bit offset for TDO data.
* @param length Amount of bits to transfer out and in.
*
* @retval This function doesn't return any value.
*/
static void jlink_clock_data(const uint8_t *out, unsigned out_offset,
const uint8_t *tms_out, unsigned tms_offset,

View File

@ -604,8 +604,6 @@ static int ulink_get_queue_size(struct ulink *device,
* Clear the OpenULINK command queue.
*
* @param device pointer to struct ulink identifying ULINK driver instance.
* @return on success: ERROR_OK
* @return on failure: ERROR_FAIL
*/
static void ulink_clear_queue(struct ulink *device)
{

1076
src/jtag/drivers/vdebug.c Normal file

File diff suppressed because it is too large Load Diff

View File

@ -57,6 +57,9 @@ extern struct adapter_driver usb_blaster_adapter_driver;
#if BUILD_JTAG_VPI == 1
extern struct adapter_driver jtag_vpi_adapter_driver;
#endif
#if BUILD_VDEBUG == 1
extern struct adapter_driver vdebug_adapter_driver;
#endif
#if BUILD_JTAG_DPI == 1
extern struct adapter_driver jtag_dpi_adapter_driver;
#endif
@ -168,6 +171,9 @@ struct adapter_driver *adapter_drivers[] = {
#if BUILD_JTAG_VPI == 1
&jtag_vpi_adapter_driver,
#endif
#if BUILD_VDEBUG == 1
&vdebug_adapter_driver,
#endif
#if BUILD_JTAG_DPI == 1
&jtag_dpi_adapter_driver,
#endif

View File

@ -546,7 +546,8 @@ int jtag_srst_asserted(int *srst_asserted);
* @param field Pointer to scan field.
* @param value Pointer to scan value.
* @param mask Pointer to scan mask; may be NULL.
* @returns Nothing, but calls jtag_set_error() on any error.
*
* returns Nothing, but calls jtag_set_error() on any error.
*/
void jtag_check_value_mask(struct scan_field *field, uint8_t *value, uint8_t *mask);

View File

@ -175,6 +175,18 @@ static const struct threadx_params threadx_params_list[] = {
get_stacking_info_arm926ejs, /* fn_get_stacking_info */
is_thread_id_valid_arm926ejs, /* fn_is_thread_id_valid */
},
{
"hla_target", /* target_name */
4, /* pointer_width; */
8, /* thread_stack_offset; */
40, /* thread_name_offset; */
48, /* thread_state_offset; */
136, /* thread_next_offset */
&rtos_standard_cortex_m3_stacking, /* stacking_info */
1, /* stacking_info_nb */
NULL, /* fn_get_stacking_info */
NULL, /* fn_is_thread_id_valid */
},
};
enum threadx_symbol_values {

View File

@ -23,6 +23,7 @@
#include "target/target.h"
#include "target/target_type.h"
#include "target/register.h"
#include <target/smp.h>
#include "rtos.h"
#include "helper/log.h"
#include "helper/types.h"
@ -109,7 +110,7 @@ static int hwthread_update_threads(struct rtos *rtos)
/* determine the number of "threads" */
if (target->smp) {
for (head = target->head; head; head = head->next) {
foreach_smp_target(head, target->smp_targets) {
struct target *curr = head->target;
if (!target_was_examined(curr))
@ -130,7 +131,7 @@ static int hwthread_update_threads(struct rtos *rtos)
if (target->smp) {
/* loop over all threads */
for (head = target->head; head; head = head->next) {
foreach_smp_target(head, target->smp_targets) {
struct target *curr = head->target;
if (!target_was_examined(curr))
@ -225,7 +226,8 @@ static struct target *hwthread_find_thread(struct target *target, int64_t thread
if (!target)
return NULL;
if (target->smp) {
for (struct target_list *head = target->head; head; head = head->next) {
struct target_list *head;
foreach_smp_target(head, target->smp_targets) {
if (thread_id == threadid_from_target(head->target))
return head->target;
}

View File

@ -30,6 +30,7 @@
#include "rtos.h"
#include "rtos_standard_stackings.h"
#include <target/register.h>
#include <target/smp.h>
#include "server/gdb_server.h"
#define LINUX_USER_KERNEL_BORDER 0xc0000000
@ -191,16 +192,14 @@ static int linux_os_thread_reg_list(struct rtos *rtos,
/* search target to perform the access */
struct reg **gdb_reg_list;
struct target_list *head;
head = target->head;
found = 0;
do {
foreach_smp_target(head, target->smp_targets) {
if (head->target->coreid == next->core_id) {
target = head->target;
found = 1;
break;
}
head = head->next;
} while (head);
}
if (found == 0) {
LOG_ERROR
@ -397,7 +396,6 @@ static int get_name(struct target *target, struct threads *t)
static int get_current(struct target *target, int create)
{
struct target_list *head;
head = target->head;
uint8_t *buf;
uint32_t val;
uint32_t ti_addr;
@ -413,7 +411,7 @@ static int get_current(struct target *target, int create)
ctt = ctt->next;
}
while (head) {
foreach_smp_target(head, target->smp_targets) {
struct reg **reg_list;
int reg_list_size;
int retval;
@ -474,7 +472,6 @@ static int get_current(struct target *target, int create)
}
free(reg_list);
head = head->next;
}
free(buffer);
@ -1394,9 +1391,8 @@ static int linux_os_smp_init(struct target *target)
struct linux_os *os_linux =
(struct linux_os *)rtos->rtos_specific_params;
struct current_thread *ct;
head = target->head;
while (head) {
foreach_smp_target(head, target->smp_targets) {
if (head->target->rtos != rtos) {
struct linux_os *smp_os_linux =
(struct linux_os *)head->target->rtos->rtos_specific_params;
@ -1413,8 +1409,6 @@ static int linux_os_smp_init(struct target *target)
os_linux->nr_cpus++;
free(smp_os_linux);
}
head = head->next;
}
return ERROR_OK;

View File

@ -801,7 +801,7 @@ struct rtos *rtos_of_target(struct target *target)
if ((target->rtos) && (target->rtos->type))
return target->rtos;
foreach_smp_target(pos, target->head)
foreach_smp_target(pos, target->smp_targets)
if ((pos->target->rtos) && (pos->target->rtos->type))
return pos->target->rtos;

View File

@ -6,7 +6,6 @@ noinst_LTLIBRARIES += %D%/libserver.la
%D%/server.h \
%D%/telnet_server.h \
%D%/gdb_server.h \
%D%/server_stubs.c \
%D%/tcl_server.c \
%D%/tcl_server.h \
%D%/rtt_server.c \

View File

@ -2276,21 +2276,25 @@ static int smp_reg_list_noread(struct target *target,
return target_get_gdb_reg_list_noread(target, combined_list,
combined_list_size, REG_CLASS_ALL);
int combined_allocated = 256;
*combined_list = malloc(combined_allocated * sizeof(struct reg *));
if (*combined_list == NULL) {
LOG_ERROR("malloc(%d) failed", (int) (combined_allocated * sizeof(struct reg *)));
unsigned int combined_allocated = 256;
struct reg **local_list = malloc(combined_allocated * sizeof(struct reg *));
if (!local_list) {
LOG_ERROR("malloc(%zu) failed", combined_allocated * sizeof(struct reg *));
return ERROR_FAIL;
}
*combined_list_size = 0;
unsigned int local_list_size = 0;
struct target_list *head;
foreach_smp_target(head, target->head) {
foreach_smp_target(head, target->smp_targets) {
if (!target_was_examined(head->target))
continue;
struct reg **reg_list = NULL;
int reg_list_size;
int result = target_get_gdb_reg_list_noread(head->target, &reg_list,
&reg_list_size, reg_class);
if (result != ERROR_OK) {
free(*combined_list);
free(local_list);
return result;
}
for (int i = 0; i < reg_list_size; i++) {
@ -2300,8 +2304,8 @@ static int smp_reg_list_noread(struct target *target,
/* Nested loop makes this O(n^2), but this entire function with
* 5 RISC-V targets takes just 2ms on my computer. Fast enough
* for me. */
for (int j = 0; j < *combined_list_size; j++) {
struct reg *b = (*combined_list)[j];
for (unsigned int j = 0; j < local_list_size; j++) {
struct reg *b = local_list[j];
if (!strcmp(a->name, b->name)) {
found = true;
if (a->size != b->size) {
@ -2309,7 +2313,7 @@ static int smp_reg_list_noread(struct target *target,
"target, but %d bits on another target.",
a->name, a->size, b->size);
free(reg_list);
free(*combined_list);
free(local_list);
return ERROR_FAIL;
}
break;
@ -2317,22 +2321,62 @@ static int smp_reg_list_noread(struct target *target,
}
if (!found) {
LOG_DEBUG("[%s] %s not found in combined list", target_name(target), a->name);
if (*combined_list_size >= combined_allocated) {
if (local_list_size >= combined_allocated) {
combined_allocated *= 2;
*combined_list = realloc(*combined_list, combined_allocated * sizeof(struct reg *));
if (*combined_list == NULL) {
LOG_ERROR("realloc(%d) failed", (int) (combined_allocated * sizeof(struct reg *)));
local_list = realloc(local_list, combined_allocated * sizeof(struct reg *));
if (!local_list) {
LOG_ERROR("realloc(%zu) failed", combined_allocated * sizeof(struct reg *));
return ERROR_FAIL;
}
}
(*combined_list)[*combined_list_size] = a;
(*combined_list_size)++;
local_list[local_list_size] = a;
local_list_size++;
}
}
}
free(reg_list);
}
if (local_list_size == 0) {
LOG_ERROR("Unable to get register list");
free(local_list);
return ERROR_FAIL;
}
/* Now warn the user about any registers that weren't found in every target. */
foreach_smp_target(head, target->smp_targets) {
if (!target_was_examined(head->target))
continue;
struct reg **reg_list = NULL;
int reg_list_size;
int result = target_get_gdb_reg_list_noread(head->target, &reg_list,
&reg_list_size, reg_class);
if (result != ERROR_OK) {
free(local_list);
return result;
}
for (unsigned int i = 0; i < local_list_size; i++) {
bool found = false;
struct reg *a = local_list[i];
for (int j = 0; j < reg_list_size; j++) {
struct reg *b = reg_list[j];
if (b->exist && !strcmp(a->name, b->name)) {
found = true;
break;
}
}
if (!found) {
LOG_WARNING("Register %s does not exist in %s, which is part of an SMP group where "
"this register does exist.",
a->name, target_name(head->target));
}
}
free(reg_list);
}
*combined_list = local_list;
*combined_list_size = local_list_size;
return ERROR_OK;
}
@ -2595,8 +2639,14 @@ static int gdb_generate_thread_list(struct target *target, char **thread_list_ou
if (!thread_detail->exists)
continue;
xml_printf(&retval, &thread_list, &pos, &size,
"<thread id=\"%" PRIx64 "\">", thread_detail->threadid);
if (thread_detail->thread_name_str)
xml_printf(&retval, &thread_list, &pos, &size,
"<thread id=\"%" PRIx64 "\" name=\"%s\">",
thread_detail->threadid,
thread_detail->thread_name_str);
else
xml_printf(&retval, &thread_list, &pos, &size,
"<thread id=\"%" PRIx64 "\">", thread_detail->threadid);
if (thread_detail->thread_name_str)
xml_printf(&retval, &thread_list, &pos, &size,
@ -3652,13 +3702,10 @@ static int gdb_target_start(struct target *target, const char *port)
/* initialize all targets gdb service with the same pointer */
{
struct target_list *head;
struct target *curr;
head = target->head;
while (head) {
curr = head->target;
foreach_smp_target(head, target->smp_targets) {
struct target *curr = head->target;
if (curr != target)
curr->gdb_service = gdb_service;
head = head->next;
}
}
return ret;

View File

@ -487,10 +487,8 @@ int server_loop(struct command_context *command_context)
timeout_ms = polling_period;
tv.tv_usec = timeout_ms * 1000;
/* Only while we're sleeping we'll let others run */
openocd_sleep_prelude();
kept_alive();
retval = socket_select(fd_max + 1, &read_fds, NULL, NULL, &tv);
openocd_sleep_postlude();
}
if (retval == -1) {

View File

@ -97,15 +97,6 @@ int server_register_commands(struct command_context *context);
int connection_write(struct connection *connection, const void *data, int len);
int connection_read(struct connection *connection, void *data, int len);
/**
* Used by server_loop(), defined in server_stubs.c
*/
void openocd_sleep_prelude(void);
/**
* Used by server_loop(), defined in server_stubs.c
*/
void openocd_sleep_postlude(void);
/**
* Defines an extended command handler function declaration to enable
* access to (and manipulation of) the server port number.

View File

@ -1,30 +0,0 @@
/***************************************************************************
* Copyright (C) 2009 Zachary T Welch <zw@superlucidity.net> *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
***************************************************************************/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include "server.h"
void openocd_sleep_prelude(void)
{
/* no-op */
}
void openocd_sleep_postlude(void)
{
/* no-op */
}

View File

@ -102,6 +102,7 @@ static int aarch64_restore_system_control_reg(struct target *target)
case ARM_MODE_FIQ:
case ARM_MODE_IRQ:
case ARM_MODE_HYP:
case ARM_MODE_UND:
case ARM_MODE_SYS:
instr = ARMV4_5_MCR(15, 0, 0, 1, 0, 0);
break;
@ -180,6 +181,7 @@ static int aarch64_mmu_modify(struct target *target, int enable)
case ARM_MODE_FIQ:
case ARM_MODE_IRQ:
case ARM_MODE_HYP:
case ARM_MODE_UND:
case ARM_MODE_SYS:
instr = ARMV4_5_MCR(15, 0, 0, 1, 0, 0);
break;
@ -331,15 +333,14 @@ static int aarch64_wait_halt_one(struct target *target)
static int aarch64_prepare_halt_smp(struct target *target, bool exc_target, struct target **p_first)
{
int retval = ERROR_OK;
struct target_list *head = target->head;
struct target_list *head;
struct target *first = NULL;
LOG_DEBUG("target %s exc %i", target_name(target), exc_target);
while (head) {
foreach_smp_target(head, target->smp_targets) {
struct target *curr = head->target;
struct armv8_common *armv8 = target_to_armv8(curr);
head = head->next;
if (exc_target && curr == target)
continue;
@ -428,7 +429,7 @@ static int aarch64_halt_smp(struct target *target, bool exc_target)
struct target_list *head;
struct target *curr;
foreach_smp_target(head, target->head) {
foreach_smp_target(head, target->smp_targets) {
int halted;
curr = head->target;
@ -478,7 +479,7 @@ static int update_halt_gdb(struct target *target, enum target_debug_reason debug
}
/* poll all targets in the group, but skip the target that serves GDB */
foreach_smp_target(head, target->head) {
foreach_smp_target(head, target->smp_targets) {
curr = head->target;
/* skip calling context */
if (curr == target)
@ -743,7 +744,7 @@ static int aarch64_prep_restart_smp(struct target *target, int handle_breakpoint
struct target *first = NULL;
uint64_t address;
foreach_smp_target(head, target->head) {
foreach_smp_target(head, target->smp_targets) {
struct target *curr = head->target;
/* skip calling target */
@ -798,7 +799,7 @@ static int aarch64_step_restart_smp(struct target *target)
struct target *curr = target;
bool all_resumed = true;
foreach_smp_target(head, target->head) {
foreach_smp_target(head, target->smp_targets) {
uint32_t prsr;
int resumed;
@ -886,7 +887,7 @@ static int aarch64_resume(struct target *target, int current,
struct target_list *head;
bool all_resumed = true;
foreach_smp_target(head, target->head) {
foreach_smp_target(head, target->smp_targets) {
uint32_t prsr;
int resumed;
@ -1049,6 +1050,7 @@ static int aarch64_post_debug_entry(struct target *target)
case ARM_MODE_FIQ:
case ARM_MODE_IRQ:
case ARM_MODE_HYP:
case ARM_MODE_UND:
case ARM_MODE_SYS:
instr = ARMV4_5_MRC(15, 0, 0, 1, 0, 0);
break;

View File

@ -367,10 +367,13 @@ int arm_semihosting(struct target *target, int *retval)
}
/* Check for ARM operation numbers. */
if (semihosting->op >= 0 && semihosting->op <= 0x31) {
if ((semihosting->op >= 0 && semihosting->op <= 0x31) ||
(semihosting->op >= 0x100 && semihosting->op <= 0x107)) {
*retval = semihosting_common(target);
if (*retval != ERROR_OK) {
LOG_ERROR("Failed semihosting operation (0x%02X)", semihosting->op);
LOG_ERROR("Failed semihosting operation (0x%02X)",
semihosting->op);
return 0;
}
} else {

View File

@ -38,6 +38,7 @@
#include "arm_opcodes.h"
#include "target.h"
#include "target_type.h"
#include "smp.h"
static void armv7a_show_fault_registers(struct target *target)
{
@ -193,8 +194,7 @@ done:
static int armv7a_l2x_cache_init(struct target *target, uint32_t base, uint32_t way)
{
struct armv7a_l2x_cache *l2x_cache;
struct target_list *head = target->head;
struct target *curr;
struct target_list *head;
struct armv7a_common *armv7a = target_to_armv7a(target);
l2x_cache = calloc(1, sizeof(struct armv7a_l2x_cache));
@ -207,15 +207,14 @@ static int armv7a_l2x_cache_init(struct target *target, uint32_t base, uint32_t
armv7a->armv7a_mmu.armv7a_cache.outer_cache = l2x_cache;
/* initialize all target in this cluster (smp target)
* l2 cache must be configured after smp declaration */
while (head) {
curr = head->target;
foreach_smp_target(head, target->smp_targets) {
struct target *curr = head->target;
if (curr != target) {
armv7a = target_to_armv7a(curr);
if (armv7a->armv7a_mmu.armv7a_cache.outer_cache)
LOG_ERROR("smp target : outer cache already initialized\n");
armv7a->armv7a_mmu.armv7a_cache.outer_cache = l2x_cache;
}
head = head->next;
}
return JIM_OK;
}

View File

@ -26,6 +26,7 @@
#include "armv7a_cache.h"
#include <helper/time_support.h>
#include "arm_opcodes.h"
#include "smp.h"
static int armv7a_l1_d_cache_sanity_check(struct target *target)
{
@ -138,14 +139,10 @@ int armv7a_cache_auto_flush_all_data(struct target *target)
if (target->smp) {
struct target_list *head;
struct target *curr;
head = target->head;
while (head) {
curr = head->target;
foreach_smp_target(head, target->smp_targets) {
struct target *curr = head->target;
if (curr->state == TARGET_HALTED)
retval = armv7a_l1_d_cache_clean_inval_all(curr);
head = head->next;
}
} else
retval = armv7a_l1_d_cache_clean_inval_all(target);

View File

@ -27,6 +27,7 @@
#include <helper/time_support.h>
#include "target.h"
#include "target_type.h"
#include "smp.h"
static int arm7a_l2x_sanity_check(struct target *target)
{
@ -194,8 +195,7 @@ static int arm7a_handle_l2x_cache_info_command(struct command_invocation *cmd,
static int armv7a_l2x_cache_init(struct target *target, uint32_t base, uint32_t way)
{
struct armv7a_l2x_cache *l2x_cache;
struct target_list *head = target->head;
struct target *curr;
struct target_list *head;
struct armv7a_common *armv7a = target_to_armv7a(target);
if (armv7a->armv7a_mmu.armv7a_cache.outer_cache) {
@ -210,8 +210,8 @@ static int armv7a_l2x_cache_init(struct target *target, uint32_t base, uint32_t
/* initialize all targets in this cluster (smp target)
* l2 cache must be configured after smp declaration */
while (head) {
curr = head->target;
foreach_smp_target(head, target->smp_targets) {
struct target *curr = head->target;
if (curr != target) {
armv7a = target_to_armv7a(curr);
if (armv7a->armv7a_mmu.armv7a_cache.outer_cache) {
@ -220,7 +220,6 @@ static int armv7a_l2x_cache_init(struct target *target, uint32_t base, uint32_t
}
armv7a->armv7a_mmu.armv7a_cache.outer_cache = l2x_cache;
}
head = head->next;
}
return ERROR_OK;
}

View File

@ -255,15 +255,48 @@ struct armv7m_common {
void (*pre_restore_context)(struct target *target);
};
static inline bool is_armv7m(const struct armv7m_common *armv7m)
{
return armv7m->common_magic == ARMV7M_COMMON_MAGIC;
}
/**
* @returns the pointer to the target specific struct
* without matching a magic number.
* Use in target specific service routines, where the correct
* type of arch_info is certain.
*/
static inline struct armv7m_common *
target_to_armv7m(struct target *target)
{
return container_of(target->arch_info, struct armv7m_common, arm);
}
static inline bool is_armv7m(const struct armv7m_common *armv7m)
/**
* @returns the pointer to the target specific struct
* or NULL if the magic number does not match.
* Use in a flash driver or any place where mismatch of the arch_info
* type can happen.
*/
static inline struct armv7m_common *
target_to_armv7m_safe(struct target *target)
{
return armv7m->common_magic == ARMV7M_COMMON_MAGIC;
if (!target)
return NULL;
if (!target->arch_info)
return NULL;
/* Check the parent type first to prevent peeking memory too far
* from arch_info pointer */
if (!is_arm(target_to_arm(target)))
return NULL;
struct armv7m_common *armv7m = target_to_armv7m(target);
if (!is_armv7m(armv7m))
return NULL;
return armv7m;
}
struct armv7m_algorithm {

View File

@ -77,6 +77,10 @@ static const struct {
.name = "HYP",
.psr = ARM_MODE_HYP,
},
{
.name = "UND",
.psr = ARM_MODE_UND,
},
{
.name = "SYS",
.psr = ARM_MODE_SYS,

View File

@ -23,6 +23,7 @@
#include "armv8_cache.h"
#include "armv8_dpm.h"
#include "armv8_opcodes.h"
#include "smp.h"
/* CLIDR cache types */
#define CACHE_LEVEL_HAS_UNIFIED_CACHE 0x4
@ -250,15 +251,12 @@ static int armv8_flush_all_data(struct target *target)
/* look if all the other target have been flushed in order to flush level
* 2 */
struct target_list *head;
struct target *curr;
head = target->head;
while (head) {
curr = head->target;
foreach_smp_target(head, target->smp_targets) {
struct target *curr = head->target;
if (curr->state == TARGET_HALTED) {
LOG_INFO("Wait flushing data l1 on core %" PRId32, curr->coreid);
retval = _armv8_flush_all_data(curr);
}
head = head->next;
}
} else
retval = _armv8_flush_all_data(target);

View File

@ -27,6 +27,7 @@
#include <helper/log.h>
#include "breakpoints.h"
#include "rtos/rtos.h"
#include "smp.h"
static const char * const breakpoint_type_strings[] = {
"hardware",
@ -217,24 +218,25 @@ int breakpoint_add(struct target *target,
uint32_t length,
enum breakpoint_type type)
{
int retval = ERROR_OK;
if (target->smp) {
struct target_list *head = target->head;
struct target_list *head;
if (type == BKPT_SOFT) {
head = list_first_entry(target->smp_targets, struct target_list, lh);
struct target *curr = head->target;
if (target->rtos)
curr = rtos_swbp_target(target, address, length, type);
return breakpoint_add_internal(curr, address, length, type);
}
while (head) {
foreach_smp_target(head, target->smp_targets) {
struct target *curr = head->target;
retval = breakpoint_add_internal(curr, address, length, type);
int retval = breakpoint_add_internal(curr, address, length, type);
if (retval != ERROR_OK)
return retval;
head = head->next;
}
return retval;
return ERROR_OK;
} else {
return breakpoint_add_internal(target, address, length, type);
}
@ -245,19 +247,17 @@ int context_breakpoint_add(struct target *target,
uint32_t length,
enum breakpoint_type type)
{
int retval = ERROR_OK;
if (target->smp) {
struct target_list *head;
struct target *curr;
head = target->head;
while (head) {
curr = head->target;
retval = context_breakpoint_add_internal(curr, asid, length, type);
foreach_smp_target(head, target->smp_targets) {
struct target *curr = head->target;
int retval = context_breakpoint_add_internal(curr, asid, length, type);
if (retval != ERROR_OK)
return retval;
head = head->next;
}
return retval;
return ERROR_OK;
} else {
return context_breakpoint_add_internal(target, asid, length, type);
}
@ -269,19 +269,17 @@ int hybrid_breakpoint_add(struct target *target,
uint32_t length,
enum breakpoint_type type)
{
int retval = ERROR_OK;
if (target->smp) {
struct target_list *head;
struct target *curr;
head = target->head;
while (head) {
curr = head->target;
retval = hybrid_breakpoint_add_internal(curr, address, asid, length, type);
foreach_smp_target(head, target->smp_targets) {
struct target *curr = head->target;
int retval = hybrid_breakpoint_add_internal(curr, address, asid, length, type);
if (retval != ERROR_OK)
return retval;
head = head->next;
}
return retval;
return ERROR_OK;
} else
return hybrid_breakpoint_add_internal(target, address, asid, length, type);
}
@ -348,12 +346,10 @@ void breakpoint_remove(struct target *target, target_addr_t address)
if (target->smp) {
unsigned int num_breakpoints = 0;
struct target_list *head;
struct target *curr;
head = target->head;
while (head) {
curr = head->target;
foreach_smp_target(head, target->smp_targets) {
struct target *curr = head->target;
num_breakpoints += breakpoint_remove_internal(curr, address);
head = head->next;
}
if (!num_breakpoints)
LOG_ERROR("no breakpoint at address " TARGET_ADDR_FMT " found", address);
@ -366,12 +362,10 @@ void breakpoint_remove_all(struct target *target)
{
if (target->smp) {
struct target_list *head;
struct target *curr;
head = target->head;
while (head) {
curr = head->target;
foreach_smp_target(head, target->smp_targets) {
struct target *curr = head->target;
breakpoint_remove_all_internal(curr);
head = head->next;
}
} else {
breakpoint_remove_all_internal(target);
@ -390,12 +384,10 @@ void breakpoint_clear_target(struct target *target)
{
if (target->smp) {
struct target_list *head;
struct target *curr;
head = target->head;
while (head) {
curr = head->target;
foreach_smp_target(head, target->smp_targets) {
struct target *curr = head->target;
breakpoint_clear_target_internal(curr);
head = head->next;
}
} else {
breakpoint_clear_target_internal(target);
@ -485,21 +477,17 @@ bye:
int watchpoint_add(struct target *target, target_addr_t address,
uint32_t length, enum watchpoint_rw rw, uint32_t value, uint32_t mask)
{
int retval = ERROR_OK;
if (target->smp) {
struct target_list *head;
struct target *curr;
head = target->head;
while (head != (struct target_list *)NULL) {
curr = head->target;
retval = watchpoint_add_internal(curr, address, length, rw, value,
mask);
foreach_smp_target(head, target->smp_targets) {
struct target *curr = head->target;
int retval = watchpoint_add_internal(curr, address, length, rw, value, mask);
if (retval != ERROR_OK)
return retval;
head = head->next;
}
return retval;
return ERROR_OK;
} else {
return watchpoint_add_internal(target, address, length, rw, value,
mask);
@ -552,12 +540,10 @@ void watchpoint_remove(struct target *target, target_addr_t address)
if (target->smp) {
unsigned int num_watchpoints = 0;
struct target_list *head;
struct target *curr;
head = target->head;
while (head) {
curr = head->target;
foreach_smp_target(head, target->smp_targets) {
struct target *curr = head->target;
num_watchpoints += watchpoint_remove_internal(curr, address);
head = head->next;
}
if (num_watchpoints == 0)
LOG_ERROR("no watchpoint at address " TARGET_ADDR_FMT " num_watchpoints", address);

View File

@ -639,14 +639,11 @@ static int cortex_a_dpm_setup(struct cortex_a_common *a, uint32_t didr)
static struct target *get_cortex_a(struct target *target, int32_t coreid)
{
struct target_list *head;
struct target *curr;
head = target->head;
while (head) {
curr = head->target;
foreach_smp_target(head, target->smp_targets) {
struct target *curr = head->target;
if ((curr->coreid == coreid) && (curr->state == TARGET_HALTED))
return curr;
head = head->next;
}
return target;
}
@ -656,14 +653,12 @@ static int cortex_a_halt_smp(struct target *target)
{
int retval = 0;
struct target_list *head;
struct target *curr;
head = target->head;
while (head) {
curr = head->target;
foreach_smp_target(head, target->smp_targets) {
struct target *curr = head->target;
if ((curr != target) && (curr->state != TARGET_HALTED)
&& target_was_examined(curr))
retval += cortex_a_halt(curr);
head = head->next;
}
return retval;
}
@ -684,7 +679,7 @@ static int update_halt_gdb(struct target *target)
if (target->gdb_service)
gdb_target = target->gdb_service->target;
foreach_smp_target(head, target->head) {
foreach_smp_target(head, target->smp_targets) {
curr = head->target;
/* skip calling context */
if (curr == target)
@ -951,11 +946,10 @@ static int cortex_a_restore_smp(struct target *target, int handle_breakpoints)
{
int retval = 0;
struct target_list *head;
struct target *curr;
target_addr_t address;
head = target->head;
while (head) {
curr = head->target;
foreach_smp_target(head, target->smp_targets) {
struct target *curr = head->target;
if ((curr != target) && (curr->state != TARGET_RUNNING)
&& target_was_examined(curr)) {
/* resume current address , not in step mode */
@ -963,8 +957,6 @@ static int cortex_a_restore_smp(struct target *target, int handle_breakpoints)
handle_breakpoints, 0);
retval += cortex_a_internal_restart(curr);
}
head = head->next;
}
return retval;
}

View File

@ -46,6 +46,7 @@
#define ARM_CPUID_PARTNO_MASK (0xFFF << ARM_CPUID_PARTNO_POS)
enum cortex_m_partno {
CORTEX_M_PARTNO_INVALID,
CORTEX_M0_PARTNO = 0xC20,
CORTEX_M1_PARTNO = 0xC21,
CORTEX_M3_PARTNO = 0xC23,
@ -247,13 +248,6 @@ struct cortex_m_common {
bool maskints_erratum;
};
static inline struct cortex_m_common *
target_to_cm(struct target *target)
{
return container_of(target->arch_info,
struct cortex_m_common, armv7m);
}
static inline bool is_cortex_m_or_hla(const struct cortex_m_common *cortex_m)
{
return cortex_m->common_magic == CORTEX_M_COMMON_MAGIC;
@ -267,6 +261,57 @@ static inline bool is_cortex_m_with_dap_access(const struct cortex_m_common *cor
return !cortex_m->armv7m.is_hla_target;
}
/**
* @returns the pointer to the target specific struct
* without matching a magic number.
* Use in target specific service routines, where the correct
* type of arch_info is certain.
*/
static inline struct cortex_m_common *
target_to_cm(struct target *target)
{
return container_of(target->arch_info,
struct cortex_m_common, armv7m.arm);
}
/**
* @returns the pointer to the target specific struct
* or NULL if the magic number does not match.
* Use in a flash driver or any place where mismatch of the arch_info
* type can happen.
*/
static inline struct cortex_m_common *
target_to_cortex_m_safe(struct target *target)
{
/* Check the parent types first to prevent peeking memory too far
* from arch_info pointer */
if (!target_to_armv7m_safe(target))
return NULL;
struct cortex_m_common *cortex_m = target_to_cm(target);
if (!is_cortex_m_or_hla(cortex_m))
return NULL;
return cortex_m;
}
/**
* @returns cached value of Cortex-M part number
* or CORTEX_M_PARTNO_INVALID if the magic number does not match
* or core_info is not initialised.
*/
static inline enum cortex_m_partno cortex_m_get_partno_safe(struct target *target)
{
struct cortex_m_common *cortex_m = target_to_cortex_m_safe(target);
if (!cortex_m)
return CORTEX_M_PARTNO_INVALID;
if (!cortex_m->core_info)
return CORTEX_M_PARTNO_INVALID;
return cortex_m->core_info->partno;
}
int cortex_m_examine(struct target *target);
int cortex_m_set_breakpoint(struct target *target, struct breakpoint *breakpoint);
int cortex_m_unset_breakpoint(struct target *target, struct breakpoint *breakpoint);

View File

@ -128,14 +128,11 @@ static int mips_m4k_debug_entry(struct target *target)
static struct target *get_mips_m4k(struct target *target, int32_t coreid)
{
struct target_list *head;
struct target *curr;
head = target->head;
while (head) {
curr = head->target;
foreach_smp_target(head, target->smp_targets) {
struct target *curr = head->target;
if ((curr->coreid == coreid) && (curr->state == TARGET_HALTED))
return curr;
head = head->next;
}
return target;
}
@ -144,11 +141,10 @@ static int mips_m4k_halt_smp(struct target *target)
{
int retval = ERROR_OK;
struct target_list *head;
struct target *curr;
head = target->head;
while (head) {
foreach_smp_target(head, target->smp_targets) {
int ret = ERROR_OK;
curr = head->target;
struct target *curr = head->target;
if ((curr != target) && (curr->state != TARGET_HALTED))
ret = mips_m4k_halt(curr);
@ -156,7 +152,6 @@ static int mips_m4k_halt_smp(struct target *target)
LOG_ERROR("halt failed target->coreid: %" PRId32, curr->coreid);
retval = ret;
}
head = head->next;
}
return retval;
}
@ -414,12 +409,10 @@ static int mips_m4k_restore_smp(struct target *target, uint32_t address, int han
{
int retval = ERROR_OK;
struct target_list *head;
struct target *curr;
head = target->head;
while (head) {
foreach_smp_target(head, target->smp_targets) {
int ret = ERROR_OK;
curr = head->target;
struct target *curr = head->target;
if ((curr != target) && (curr->state != TARGET_RUNNING)) {
/* resume current address , not in step mode */
ret = mips_m4k_internal_restore(curr, 1, address,
@ -431,7 +424,6 @@ static int mips_m4k_restore_smp(struct target *target, uint32_t address, int han
retval = ret;
}
}
head = head->next;
}
return retval;
}

View File

@ -2297,7 +2297,7 @@ static int init_target(struct command_context *cmd_ctx,
generic_info->hart_count = &riscv013_hart_count;
generic_info->data_bits = &riscv013_data_bits;
generic_info->print_info = &riscv013_print_info;
if (generic_info->version_specific == NULL) {
if (!generic_info->version_specific) {
generic_info->version_specific = calloc(1, sizeof(riscv013_info_t));
if (!generic_info->version_specific)
return ERROR_FAIL;

View File

@ -13,6 +13,7 @@
#include "target/target.h"
#include "target/algorithm.h"
#include "target/target_type.h"
#include <target/smp.h>
#include "jtag/jtag.h"
#include "target/register.h"
#include "target/breakpoints.h"
@ -1296,13 +1297,14 @@ int riscv_halt(struct target *target)
int result = ERROR_OK;
if (target->smp) {
for (struct target_list *tlist = target->head; tlist; tlist = tlist->next) {
struct target_list *tlist;
foreach_smp_target(tlist, target->smp_targets) {
struct target *t = tlist->target;
if (halt_prep(t) != ERROR_OK)
result = ERROR_FAIL;
}
for (struct target_list *tlist = target->head; tlist; tlist = tlist->next) {
foreach_smp_target(tlist, target->smp_targets) {
struct target *t = tlist->target;
riscv_info_t *i = riscv_info(t);
if (i->prepped) {
@ -1311,7 +1313,7 @@ int riscv_halt(struct target *target)
}
}
for (struct target_list *tlist = target->head; tlist; tlist = tlist->next) {
foreach_smp_target(tlist, target->smp_targets) {
struct target *t = tlist->target;
if (halt_finish(t) != ERROR_OK)
return ERROR_FAIL;
@ -1500,32 +1502,6 @@ static int resume_finish(struct target *target, int debug_execution)
debug_execution ? TARGET_EVENT_DEBUG_RESUMED : TARGET_EVENT_RESUMED);
}
/* Return a newly allocated target list, that contains the same targets as in
* tlist bit in the opposite order. */
static struct target_list *tlist_reverse(struct target_list *tlist)
{
struct target_list *previous = NULL;
struct target_list *reversed = NULL;
for (struct target_list *node = tlist; node; node = node->next) {
reversed = calloc(1, sizeof(struct target_list));
reversed->target = node->target;
reversed->next = previous;
previous = reversed;
}
return reversed;
}
/* Free a target list, but not the targets that are referenced. */
static void tlist_free(struct target_list *tlist)
{
struct target_list *node = tlist;
while (node) {
struct target_list *previous = node;
node = node->next;
free(previous);
}
}
/**
* @par single_hart When true, only resume a single hart even if SMP is
* configured. This is used to run algorithms on just one hart.
@ -1541,21 +1517,17 @@ int riscv_resume(
LOG_DEBUG("handle_breakpoints=%d", handle_breakpoints);
int result = ERROR_OK;
if (target->smp && !single_hart) {
struct target_list *ordered_tlist;
if (resume_order == RO_REVERSED)
ordered_tlist = tlist_reverse(target->head);
else
ordered_tlist = target->head;
for (struct target_list *tlist = ordered_tlist; tlist; tlist = tlist->next) {
struct target_list *tlist;
foreach_smp_target_direction(resume_order == RO_NORMAL,
tlist, target->smp_targets) {
struct target *t = tlist->target;
if (resume_prep(t, current, address, handle_breakpoints,
debug_execution) != ERROR_OK)
result = ERROR_FAIL;
}
for (struct target_list *tlist = ordered_tlist; tlist; tlist = tlist->next) {
foreach_smp_target_direction(resume_order == RO_NORMAL,
tlist, target->smp_targets) {
struct target *t = tlist->target;
riscv_info_t *i = riscv_info(t);
if (i->prepped) {
@ -1565,15 +1537,13 @@ int riscv_resume(
}
}
for (struct target_list *tlist = ordered_tlist; tlist; tlist = tlist->next) {
foreach_smp_target_direction(resume_order == RO_NORMAL,
tlist, target->smp_targets) {
struct target *t = tlist->target;
if (resume_finish(t, debug_execution) != ERROR_OK)
result = ERROR_FAIL;
}
if (resume_order == RO_REVERSED)
tlist_free(ordered_tlist);
} else {
if (resume_prep(target, current, address, handle_breakpoints,
debug_execution) != ERROR_OK)
@ -2230,9 +2200,8 @@ int riscv_openocd_poll(struct target *target)
unsigned halts_discovered = 0;
unsigned should_remain_halted = 0;
unsigned should_resume = 0;
unsigned i = 0;
for (struct target_list *list = target->head; list;
list = list->next, i++) {
struct target_list *list;
foreach_smp_target(list, target->smp_targets) {
struct target *t = list->target;
if (!target_was_examined(t))
continue;
@ -2294,8 +2263,7 @@ int riscv_openocd_poll(struct target *target)
}
/* Sample memory if any target is running. */
for (struct target_list *list = target->head; list;
list = list->next, i++) {
foreach_smp_target(list, target->smp_targets) {
struct target *t = list->target;
if (t->state == TARGET_RUNNING) {
sample_memory(target);

View File

@ -140,7 +140,9 @@ semihosting_result_t riscv_semihosting(struct target *target, int *retval)
semihosting->word_size_bytes = riscv_xlen(target) / 8;
/* Check for ARM operation numbers. */
if (semihosting->op >= 0 && semihosting->op <= 0x31) {
if ((semihosting->op >= 0 && semihosting->op <= 0x31) ||
(semihosting->op >= 0x100 && semihosting->op <= 0x107)) {
*retval = semihosting_common(target);
if (*retval != ERROR_OK) {
LOG_ERROR("Failed semihosting operation (0x%02X)", semihosting->op);

View File

@ -52,19 +52,35 @@
#include <helper/log.h>
#include <sys/stat.h>
/**
* It is not possible to use O_... flags defined in sys/stat.h because they
* are not guaranteed to match the values defined by the GDB Remote Protocol.
* See https://sourceware.org/gdb/onlinedocs/gdb/Open-Flags.html#Open-Flags
*/
enum {
TARGET_O_RDONLY = 0x000,
TARGET_O_WRONLY = 0x001,
TARGET_O_RDWR = 0x002,
TARGET_O_APPEND = 0x008,
TARGET_O_CREAT = 0x200,
TARGET_O_TRUNC = 0x400,
/* O_EXCL=0x800 is not required in this implementation. */
};
/* GDB remote protocol does not differentiate between text and binary open modes. */
static const int open_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
TARGET_O_RDONLY,
TARGET_O_RDONLY,
TARGET_O_RDWR,
TARGET_O_RDWR,
TARGET_O_WRONLY | TARGET_O_CREAT | TARGET_O_TRUNC,
TARGET_O_WRONLY | TARGET_O_CREAT | TARGET_O_TRUNC,
TARGET_O_RDWR | TARGET_O_CREAT | TARGET_O_TRUNC,
TARGET_O_RDWR | TARGET_O_CREAT | TARGET_O_TRUNC,
TARGET_O_WRONLY | TARGET_O_CREAT | TARGET_O_APPEND,
TARGET_O_WRONLY | TARGET_O_CREAT | TARGET_O_APPEND,
TARGET_O_RDWR | TARGET_O_CREAT | TARGET_O_APPEND,
TARGET_O_RDWR | TARGET_O_CREAT | TARGET_O_APPEND
};
static int semihosting_common_fileio_info(struct target *target,
@ -138,6 +154,12 @@ int semihosting_common_init(struct target *target, void *setup,
return ERROR_OK;
}
/**
* 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;
/**
* Portable implementation of ARM semihosting calls.
* Performs the currently pending semihosting operation
@ -167,7 +189,7 @@ int semihosting_common(struct target *target)
/* Enough space to hold 4 long words. */
uint8_t fields[4*8];
LOG_DEBUG("op=0x%x, param=0x%" PRIx64, (int)semihosting->op,
LOG_DEBUG("op=0x%x, param=0x%" PRIx64, semihosting->op,
semihosting->param);
switch (semihosting->op) {
@ -1262,6 +1284,71 @@ int semihosting_common(struct target *target)
}
break;
case SEMIHOSTING_USER_CMD_0x100 ... SEMIHOSTING_USER_CMD_0x107:
/**
* This is a user defined operation (while user cmds 0x100-0x1ff
* are possible, only 0x100-0x107 are currently implemented).
*
* Reads the user operation parameters from target, then fires the
* corresponding target event. When the target callbacks returned,
* cleans up the command parameter buffer.
*
* Entry
* On entry, the PARAMETER REGISTER contains a pointer to a
* two-field data block:
* - field 1 Contains a pointer to the bound command parameter
* string
* - field 2 Contains the command parameter string length
*
* Return
* On exit, the RETURN REGISTER contains the return status.
*/
{
assert(!semihosting_user_op_params);
retval = semihosting_read_fields(target, 2, fields);
if (retval != ERROR_OK) {
LOG_ERROR("Failed to read fields for user defined command"
" op=0x%x", semihosting->op);
return retval;
}
uint64_t addr = semihosting_get_field(target, 0, fields);
size_t len = semihosting_get_field(target, 1, fields);
if (len > SEMIHOSTING_MAX_TCL_COMMAND_FIELD_LENGTH) {
LOG_ERROR("The maximum length for user defined command "
"parameter is %u, received length is %zu (op=0x%x)",
SEMIHOSTING_MAX_TCL_COMMAND_FIELD_LENGTH,
len,
semihosting->op);
return ERROR_FAIL;
}
semihosting_user_op_params = malloc(len + 1);
if (!semihosting_user_op_params)
return ERROR_FAIL;
semihosting_user_op_params[len] = 0;
retval = target_read_buffer(target, addr, len,
(uint8_t *)(semihosting_user_op_params));
if (retval != ERROR_OK) {
LOG_ERROR("Failed to read from target, semihosting op=0x%x",
semihosting->op);
free(semihosting_user_op_params);
semihosting_user_op_params = NULL;
return retval;
}
target_handle_event(target, semihosting->op);
free(semihosting_user_op_params);
semihosting_user_op_params = NULL;
semihosting->result = 0;
break;
}
case SEMIHOSTING_SYS_ELAPSED: /* 0x30 */
/*
* Returns the number of elapsed target ticks since execution
@ -1608,6 +1695,30 @@ COMMAND_HANDLER(handle_common_semihosting_resumable_exit_command)
return ERROR_OK;
}
COMMAND_HANDLER(handle_common_semihosting_read_user_param_command)
{
struct target *target = get_current_target(CMD_CTX);
struct semihosting *semihosting = target->semihosting;
if (CMD_ARGC)
return ERROR_COMMAND_SYNTAX_ERROR;
if (!semihosting->is_active) {
LOG_ERROR("semihosting not yet enabled for current target");
return ERROR_FAIL;
}
if (!semihosting_user_op_params) {
LOG_ERROR("This command is usable only from a registered user "
"semihosting event callback.");
return ERROR_FAIL;
}
command_print_sameline(CMD, "%s", semihosting_user_op_params);
return ERROR_OK;
}
const struct command_registration semihosting_common_handlers[] = {
{
"semihosting",
@ -1637,5 +1748,12 @@ const struct command_registration semihosting_common_handlers[] = {
.usage = "['enable'|'disable']",
.help = "activate support for semihosting resumable exit",
},
{
"semihosting_read_user_param",
.handler = handle_common_semihosting_read_user_param_command,
.mode = COMMAND_EXEC,
.usage = "",
.help = "read parameters in semihosting-user-cmd-0x10X callbacks",
},
COMMAND_REGISTRATION_DONE
};

View File

@ -75,8 +75,14 @@ enum semihosting_operation_numbers {
SEMIHOSTING_SYS_WRITE = 0x05,
SEMIHOSTING_SYS_WRITEC = 0x03,
SEMIHOSTING_SYS_WRITE0 = 0x04,
SEMIHOSTING_USER_CMD_0x100 = 0x100, /* First user cmd op code */
SEMIHOSTING_USER_CMD_0x107 = 0x107, /* Last supported user cmd op code */
SEMIHOSTING_USER_CMD_0x1FF = 0x1FF, /* Last user cmd op code */
};
/** Maximum allowed Tcl command segment length in bytes*/
#define SEMIHOSTING_MAX_TCL_COMMAND_FIELD_LENGTH (1024 * 1024)
/*
* Codes used by SEMIHOSTING_SYS_EXIT (formerly
* SEMIHOSTING_REPORT_EXCEPTION).

View File

@ -111,18 +111,18 @@ COMMAND_HANDLER(default_handle_smp_command)
}
if (!strcmp(CMD_ARGV[0], "on")) {
foreach_smp_target(head, target->head)
foreach_smp_target(head, target->smp_targets)
head->target->smp = 1;
return ERROR_OK;
}
if (!strcmp(CMD_ARGV[0], "off")) {
foreach_smp_target(head, target->head)
foreach_smp_target(head, target->smp_targets)
head->target->smp = 0;
/* fixes the target display to the debugger */
if (target->head)
if (!list_empty(target->smp_targets))
target->gdb_service->target = target;
return ERROR_OK;
@ -135,9 +135,7 @@ COMMAND_HANDLER(handle_smp_gdb_command)
{
struct target *target = get_current_target(CMD_CTX);
int retval = ERROR_OK;
struct target_list *head;
head = target->head;
if (head) {
if (!list_empty(target->smp_targets)) {
if (CMD_ARGC == 1) {
int coreid = 0;
COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], coreid);

View File

@ -19,10 +19,14 @@
#ifndef OPENOCD_TARGET_SMP_H
#define OPENOCD_TARGET_SMP_H
#include <helper/list.h>
#include "server/server.h"
#define foreach_smp_target(pos, head) \
for (pos = head; (pos); pos = pos->next)
list_for_each_entry(pos, head, lh)
#define foreach_smp_target_direction(forward, pos, head) \
list_for_each_entry_direction(forward, pos, head, lh)
extern const struct command_registration smp_command_handlers[];

View File

@ -56,6 +56,7 @@
#include "rtos/rtos.h"
#include "transport/transport.h"
#include "arm_cti.h"
#include "smp.h"
/* default halt wait timeout (ms) */
#define DEFAULT_HALT_TIMEOUT 5000
@ -159,6 +160,7 @@ static int64_t target_timer_next_event_value;
static LIST_HEAD(target_reset_callback_list);
static LIST_HEAD(target_trace_callback_list);
static const int polling_interval = TARGET_DEFAULT_POLLING_INTERVAL;
static LIST_HEAD(empty_smp_targets);
static const struct jim_nvp nvp_assert[] = {
{ .name = "assert", NVP_ASSERT },
@ -236,6 +238,15 @@ static const struct jim_nvp nvp_target_event[] = {
{ .value = TARGET_EVENT_TRACE_CONFIG, .name = "trace-config" },
{ .value = TARGET_EVENT_SEMIHOSTING_USER_CMD_0x100, .name = "semihosting-user-cmd-0x100" },
{ .value = TARGET_EVENT_SEMIHOSTING_USER_CMD_0x101, .name = "semihosting-user-cmd-0x101" },
{ .value = TARGET_EVENT_SEMIHOSTING_USER_CMD_0x102, .name = "semihosting-user-cmd-0x102" },
{ .value = TARGET_EVENT_SEMIHOSTING_USER_CMD_0x103, .name = "semihosting-user-cmd-0x103" },
{ .value = TARGET_EVENT_SEMIHOSTING_USER_CMD_0x104, .name = "semihosting-user-cmd-0x104" },
{ .value = TARGET_EVENT_SEMIHOSTING_USER_CMD_0x105, .name = "semihosting-user-cmd-0x105" },
{ .value = TARGET_EVENT_SEMIHOSTING_USER_CMD_0x106, .name = "semihosting-user-cmd-0x106" },
{ .value = TARGET_EVENT_SEMIHOSTING_USER_CMD_0x107, .name = "semihosting-user-cmd-0x107" },
{ .name = NULL, .value = -1 }
};
@ -2272,13 +2283,15 @@ static void target_destroy(struct target *target)
/* release the targets SMP list */
if (target->smp) {
struct target_list *head = target->head;
while (head) {
struct target_list *pos = head->next;
struct target_list *head, *tmp;
list_for_each_entry_safe(head, tmp, target->smp_targets, lh) {
list_del(&head->lh);
head->target->smp = 0;
free(head);
head = pos;
}
if (target->smp_targets != &empty_smp_targets)
free(target->smp_targets);
target->smp = 0;
}
@ -5782,6 +5795,9 @@ static int target_create(struct jim_getopt_info *goi)
return JIM_ERR;
}
/* set empty smp cluster */
target->smp_targets = &empty_smp_targets;
/* set target number */
target->target_number = new_target_number();
@ -5995,9 +6011,7 @@ static int jim_target_smp(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
int retval, len;
static int smp_group = 1;
struct target *target = NULL;
struct target_list *head, *curr, *new;
curr = NULL;
head = NULL;
struct target_list *head, *new;
retval = 0;
LOG_DEBUG("%d", argc);
@ -6006,6 +6020,13 @@ static int jim_target_smp(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
* argv[3] ...
*/
struct list_head *lh = malloc(sizeof(*lh));
if (!lh) {
LOG_ERROR("Out of memory");
return JIM_ERR;
}
INIT_LIST_HEAD(lh);
for (i = 1; i < argc; i++) {
targetname = Jim_GetString(argv[i], &len);
@ -6014,24 +6035,15 @@ static int jim_target_smp(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
if (target) {
new = malloc(sizeof(struct target_list));
new->target = target;
new->next = NULL;
if (!head) {
head = new;
curr = head;
} else {
curr->next = new;
curr = new;
}
list_add_tail(&new->lh, lh);
}
}
/* now parse the list of cpu and put the target in smp mode*/
curr = head;
while (curr) {
target = curr->target;
foreach_smp_target(head, lh) {
target = head->target;
target->smp = smp_group;
target->head = head;
curr = curr->next;
target->smp = 1;
target->smp_targets = lh;
}
smp_group++;

View File

@ -201,7 +201,9 @@ struct target {
* and must be detected when symbols are offered */
struct backoff_timer backoff;
int smp; /* add some target attributes for smp support */
struct target_list *head;
struct list_head *smp_targets; /* list all targets in this smp group/cluster
* The head of the list is shared between the
* cluster, thus here there is a pointer */
/* the gdb service is there in case of smp, we have only one gdb server
* for all smp target
* the target attached to the gdb is changing dynamically by changing
@ -220,8 +222,8 @@ struct target {
};
struct target_list {
struct list_head lh;
struct target *target;
struct target_list *next;
};
struct gdb_fileio_info {
@ -294,6 +296,15 @@ enum target_event {
TARGET_EVENT_GDB_FLASH_WRITE_END,
TARGET_EVENT_TRACE_CONFIG,
TARGET_EVENT_SEMIHOSTING_USER_CMD_0x100 = 0x100, /* semihosting allows user cmds from 0x100 to 0x1ff */
TARGET_EVENT_SEMIHOSTING_USER_CMD_0x101 = 0x101,
TARGET_EVENT_SEMIHOSTING_USER_CMD_0x102 = 0x102,
TARGET_EVENT_SEMIHOSTING_USER_CMD_0x103 = 0x103,
TARGET_EVENT_SEMIHOSTING_USER_CMD_0x104 = 0x104,
TARGET_EVENT_SEMIHOSTING_USER_CMD_0x105 = 0x105,
TARGET_EVENT_SEMIHOSTING_USER_CMD_0x106 = 0x106,
TARGET_EVENT_SEMIHOSTING_USER_CMD_0x107 = 0x107,
};
struct target_event_action {

11
tcl/board/evb-lan9255.cfg Normal file
View File

@ -0,0 +1,11 @@
# SPDX-License-Identifier: GPL-2.0-or-later
#
# Microchip LAN9255 evaluation board
# https://www.microchip.com/en-us/development-tool/EV25Y25A
#
set CHIPNAME same53
source [find target/atsame5x.cfg]
reset_config srst_only

View File

@ -0,0 +1,14 @@
# SPDX-License-Identifier: GPL-2.0-or-later
# NXP LS1088ARDB (Reference Design Board)
# This is for the "main" JTAG connector J55
transport select jtag
reset_config srst_only
# To access the CPLD, populate J48 and add `-c 'set CWTAP 1'` to your command
# line. At the time of this writing, programming is unsupported.
if { [info exists CWTAP] } {
source [find cpld/altera-epm240.cfg]
} else {
source [find target/ls1088a.cfg]
}

View File

@ -0,0 +1,31 @@
# SPDX-License-Identifier: GPL-2.0-or-later
# Cadence virtual debug interface
# Arm Cortex A53x2 through JTAG
source [find interface/vdebug.cfg]
set _CORES 2
set _CHIPNAME a53
set _MEMSTART 0x00000000
set _MEMSIZE 0x1000000
set _CPUTAPID 0x5ba00477
# vdebug select transport
#transport select jtag
# JTAG reset config, frequency and reset delay
reset_config trst_and_srst
adapter speed 50000
adapter srst delay 5
# BFM hierarchical path and input clk period
vdebug bfm_path tbench.u_vd_jtag_bfm 10ns
# DMA Memories to access backdoor (up to 4)
vdebug mem_path tbench.u_memory.mem_array $_MEMSTART $_MEMSIZE
jtag newtap $_CHIPNAME cpu -irlen 4 -ircapture 0x1 -irmask 0xf -expected-id $_CPUTAPID
jtag arp_init-reset
source [find target/vd_aarch64.cfg]

30
tcl/board/vd_m4_jtag.cfg Normal file
View File

@ -0,0 +1,30 @@
# SPDX-License-Identifier: GPL-2.0-or-later
# Cadence virtual debug interface
# Arm Cortex m4 through JTAG
source [find interface/vdebug.cfg]
set _CHIPNAME m4
set _MEMSTART 0x00000000
set _MEMSIZE 0x10000
set _CPUTAPID 0x4ba00477
# vdebug select transport
#transport select jtag
# JTAG reset config, frequency and reset delay
reset_config trst_and_srst
adapter speed 25000
adapter srst delay 5
# BFM hierarchical path and input clk period
vdebug bfm_path tbench.u_vd_jtag_bfm 20ns
# DMA Memories to access backdoor (up to 4)
vdebug mem_path tbench.u_mcu.u_sys.u_rom.rom $_MEMSTART $_MEMSIZE
jtag newtap $_CHIPNAME cpu -irlen 4 -ircapture 0x1 -irmask 0xf -expected-id $_CPUTAPID
jtag arp_init-reset
source [find target/vd_cortex_m.cfg]

View File

@ -0,0 +1,32 @@
# SPDX-License-Identifier: GPL-2.0-or-later
# Cadence virtual debug interface
# RISCV Ibex core with Pulpissimo through JTAG
source [find interface/vdebug.cfg]
set _CHIPNAME ibex
set _HARTID 0x20
set _CPUTAPID 0x249511c3
# vdebug select transport
#transport select jtag
# JTAG reset config, frequency and reset delay
reset_config trst_and_srst
adapter speed 12500
adapter srst delay 10
# BFM hierarchical path and input clk period
vdebug bfm_path tbench.u_vd_jtag_bfm 40ns
# DMA Memories to access backdoor (up to 4)
vdebug mem_path tbench.soc_domain_i.pulp_soc_i.gen_mem_l2_pri\[0\].sram_i.mem_array 0x1c000000 0x8000
vdebug mem_path tbench.soc_domain_i.pulp_soc_i.gen_mem_l2_pri\[1\].sram_i.mem_array 0x1c008000 0x8000
vdebug mem_path tbench.soc_domain_i.pulp_soc_i.gen_mem_l2\[0\].sram_i.mem_array 0x1c010000 0x80000
# need to explicitly define riscv tap, autoprobing does not work for icapture != 0x01
jtag newtap $_CHIPNAME cpu -irlen 5 -ircapture 0x05 -irmask 0x1f -expected-id $_CPUTAPID
jtag arp_init-reset
source [find target/vd_riscv.cfg]

View File

@ -0,0 +1,32 @@
# SPDX-License-Identifier: GPL-2.0-or-later
# Cadence virtual debug interface
# RISCV swerv core with Swerv through JTAG
source [find interface/vdebug.cfg]
set _CHIPNAME rv32
set _HARTID 0x00
set _CPUTAPID 0x1000008b
set _MEMSTART 0x00000000
set _MEMSIZE 0x10000
# vdebug select transport
#transport select jtag
# JTAG reset config, frequency and reset delay
reset_config trst_and_srst
adapter speed 50000
adapter srst delay 5
# BFM hierarchical path and input clk period
vdebug bfm_path tbench.u_vd_jtag_bfm 10ns
# DMA Memories to access backdoor (up to 4)
vdebug mem_path tbench.i_ahb_ic.mem $_MEMSTART $_MEMSIZE
# need to explicitly define riscv tap, autoprobing does not work for icapture != 0x01
jtag newtap $_CHIPNAME cpu -irlen 5 -ircapture 0x01 -irmask 0x1f -expected-id $_CPUTAPID
jtag arp_init-reset
source [find target/vd_riscv.cfg]

View File

@ -1,6 +1,23 @@
# Altera MAXII EPM240T100C CPLD
if { [info exists CHIPNAME] } {
set _CHIPNAME $CHIPNAME
} else {
set _CHIPNAME epm240
}
# see MAX II Device Handbook
# Table 3-3: 32-Bit MAX II Device IDCODE
# Version Part Number Manuf. ID LSB
# 0000 0010 0000 1010 0001 000 0110 1110 1
jtag newtap epm240 tap -expected-id 0x020a10dd -irlen 10
jtag newtap $_CHIPNAME tap -irlen 10 \
-expected-id 0x020a10dd \
-expected-id 0x020a20dd \
-expected-id 0x020a30dd \
-expected-id 0x020a40dd \
-expected-id 0x020a50dd \
-expected-id 0x020a60dd
# 200ns seems like a good speed
# c.f. Table 5-34: MAX II JTAG Timing Parameters
adapter speed 5000

33
tcl/interface/vdebug.cfg Normal file
View File

@ -0,0 +1,33 @@
# SPDX-License-Identifier: GPL-2.0-or-later
# Cadence virtual debug interface
if { [info exists VDEBUGHOST] } {
set _VDEBUGHOST $VDEBUGHOST
} else {
set _VDEBUGHOST localhost
}
if { [info exists VDEBUGPORT] } {
set _VDEBUGPORT $VDEBUGPORT
} else {
set _VDEBUGPORT 8192
}
adapter driver vdebug
# vdebug server:port
vdebug server $_VDEBUGHOST:$_VDEBUGPORT
# example config debug level and log
#debug_level 3
#log_output vd_ocd.log
# example config listen on all interfaces, disable tcl/telnet server
bindto 0.0.0.0
#gdb_port 3333
#telnet_port disabled
tcl_port disabled
# transaction batching: 0 - no batching, 1 - (default) wr, 2 - rw
vdebug batching 1
# Polling values
vdebug polling 100 1000

74
tcl/target/ls1088a.cfg Normal file
View File

@ -0,0 +1,74 @@
# SPDX-License-Identifier: GPL-2.0-or-later
# NXP LS1088A
if { [info exists CHIPNAME] } {
set _CHIPNAME $CHIPNAME
} else {
set _CHIPNAME ls1088a
}
if { [info exists DAP_TAPID] } {
set _DAP_TAPID $DAP_TAPID
} else {
set _DAP_TAPID 0x5ba00477
}
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 1
set _CPU_BASE 0x81000000
set _CPU_STRIDE 0x100000
set _CPU_DBGOFF 0x10000
set _CPU_CTIOFF 0x20000
set _TARGETS {}
for {set i 0} {$i < 8} {incr i} {
set _BASE [expr {$_CPU_BASE + $_CPU_STRIDE * $i}]
cti create $_CHIPNAME.cti$i -dap $_CHIPNAME.dap -ap-num 0 \
-baseaddr [expr {$_BASE + $_CPU_CTIOFF}]
target create $_CHIPNAME.cpu$i aarch64 -dap $_CHIPNAME.dap \
-cti $_CHIPNAME.cti$i -dbgbase [expr {$_BASE + $_CPU_DBGOFF}] \
{*}[expr {$i ? "-coreid $i" : "-rtos hwthread" }]
lappend _TARGETS $_CHIPNAME.cpu$i
}
target smp {*}$_TARGETS
# Service processor
target create $_CHIPNAME.sp cortex_a -dap $_CHIPNAME.dap -ap-num 0 -dbgbase 0x80138000
# Normally you will not need to call this, but if you are using the hard-coded
# Reset Configuration Word (RCW) you will need to call this manually. The CPU's
# reset vector is 0, and the boot ROM at that location contains ARMv7-A 32-bit
# instructions. This will cause the CPU to almost immediately execute an
# illegal instruction.
#
# This code is idempotent; releasing a released CPU has no effect, although it
# will halt/resume the service processor.
add_help_text release_cpu "Release a cpu which is held off"
proc release_cpu {cpu} {
set RST_BRRL 0x1e60060
set old [target current]
targets $::_CHIPNAME.sp
set not_halted [string compare halted [$::_CHIPNAME.sp curstate]]
if {$not_halted} {
halt
}
# Release the cpu; it will start executing something bogus
mem2array regs 32 $RST_BRRL 1
mww $RST_BRRL [expr {$regs(0) | 1 << $cpu}]
if {$not_halted} {
resume
}
targets $old
}
targets $_CHIPNAME.cpu0
# Seems to work OK in testing
adapter speed 10000

37
tcl/target/vd_aarch64.cfg Normal file
View File

@ -0,0 +1,37 @@
# SPDX-License-Identifier: GPL-2.0-or-later
# Cadence virtual debug interface
# Arm v8 64b Cortex A
if {![info exists _CORES]} {
set _CORES 1
}
if {![info exists _CHIPNAME]} {
set _CHIPNAME aarch64
}
set _TARGETNAME $_CHIPNAME.cpu
set _CTINAME $_CHIPNAME.cti
set DBGBASE {0x80810000 0x80910000}
set CTIBASE {0x80820000 0x80920000}
dap create $_CHIPNAME.dap -chain-position $_TARGETNAME
$_CHIPNAME.dap apsel 1
for { set _core 0 } { $_core < $_CORES } { incr _core } \
{
cti create $_CTINAME.$_core -dap $_CHIPNAME.dap -ap-num 1 -baseaddr [lindex $CTIBASE $_core]
set _command "target create $_TARGETNAME.$_core aarch64 -dap $_CHIPNAME.dap \
-dbgbase [lindex $DBGBASE $_core] -cti $_CTINAME.$_core -coreid $_core"
if { $_core != 0 } {
# non-boot core examination may fail
set _command "$_command -defer-examine"
set _smp_command "$_smp_command $_TARGETNAME.$_core"
} else {
set _smp_command "target smp $_TARGETNAME.$_core"
}
eval $_command
}
eval $_smp_command
# default target is core 0
targets $_TARGETNAME.0

View File

@ -0,0 +1,12 @@
# SPDX-License-Identifier: GPL-2.0-or-later
# Cadence virtual debug interface
# ARM Cortex M
if {![info exists _CHIPNAME]} {
set _CHIPNAME cortex_m
}
set _TARGETNAME $_CHIPNAME.cpu
dap create $_CHIPNAME.dap -chain-position $_TARGETNAME
target create $_TARGETNAME cortex_m -dap $_CHIPNAME.dap

18
tcl/target/vd_riscv.cfg Normal file
View File

@ -0,0 +1,18 @@
# SPDX-License-Identifier: GPL-2.0-or-later
# Cadence virtual debug interface
# RISCV core
if {![info exists _HARTID]} {
set _HARTID 0x00
}
if {![info exists _CHIPNAME]} {
set _CHIPNAME riscv
}
set _TARGETNAME $_CHIPNAME.cpu
target create $_TARGETNAME riscv -chain-position $_TARGETNAME -coreid $_HARTID
riscv set_reset_timeout_sec 120
riscv set_command_timeout_sec 120
# prefer to use sba for system bus access
riscv set_prefer_sba on