Compare commits

...

10 Commits

Author SHA1 Message Date
Marc Schink
6872f7e406 adapter/xds110: Hide '(dis)connected' message
Print a debug message rather than an info message because this
information is not of importance for normal users.

Change-Id: Ie91565df455ffc0bfe976d1782dd4318bfd2d30b
Signed-off-by: Marc Schink <dev@zapb.de>
Reviewed-on: https://review.openocd.org/c/openocd/+/8986
Tested-by: jenkins
Reviewed-by: Antonio Borneo <borneo.antonio@gmail.com>
2025-07-25 16:52:40 +00:00
Antonio Borneo
7e83049c93 tcl: add support for stm32mp2xx targets and boards
Add support for the targets stm32mp21x, stm32mp23x and stm32mp25x.
Add support for the boards stm32mp235f-dk and stm32mp257f-dk.

The board stm32mp215f-dk has no configuration file as it only
provides a generic JTAG/SWD connector for the stm32mp21x SoC.

Change-Id: I0256bebd8a5d5600066d8ae191d83344a35d3d37
Signed-off-by: Antonio Borneo <borneo.antonio@gmail.com>
Reviewed-on: https://review.openocd.org/c/openocd/+/8985
Tested-by: jenkins
Reviewed-by: zapb <dev@zapb.de>
2025-07-25 16:52:12 +00:00
Antonio Borneo
f11b677dec tcl: stm32mp15x: modify handshake to open debug port, add hwthread
Align the target script to the handshake implemented in the latest
version of stm32wrapper4dbg to get access to the debug port.

Use hwthread with the SMP node.

Allow ignoring/masking some CPU from the configuration with the
variables EN_<cpu>.

Change-Id: I7117dd7df20b4f6b6e28f911e3e91ee763bdd200
Signed-off-by: Antonio Borneo <borneo.antonio@gmail.com>
Reviewed-on: https://review.openocd.org/c/openocd/+/8984
Tested-by: jenkins
2025-07-25 16:52:02 +00:00
Antonio Borneo
5d3f53363b tcl: stm32mp13x: modify handshake to open debug port
Align the target script to the handshake implemented in the latest
version of stm32wrapper4dbg to get access to the debug port.

Change-Id: Ia1c7773330fda776abb4385331fddbf431d11c39
Signed-off-by: Antonio Borneo <borneo.antonio@gmail.com>
Reviewed-on: https://review.openocd.org/c/openocd/+/8983
Tested-by: jenkins
2025-07-25 16:51:47 +00:00
Antonio Borneo
9bb6fa67ca tcl: move STM32 MPU files in vendor folder
Move the existing files for STM32MP13x and STM32MP15x in the
folder "st".
Rename the board files using the correct names.
While there, add the missing URL to one of the boards.

Change-Id: If8b92f55e3390ebc75df6a2ea09fcf798ea0b8cf
Signed-off-by: Antonio Borneo <borneo.antonio@gmail.com>
Reviewed-on: https://review.openocd.org/c/openocd/+/8982
Tested-by: jenkins
Reviewed-by: zapb <dev@zapb.de>
2025-07-25 16:51:35 +00:00
Liam Fletcher
1f56ea647d tcl: add microchip's pic64gx curiosity config
Microchip's PIC64GX Curiosity Board has a RISC-V core complex with 4
application processors and one monitor processor. The Curiosity kit also
has an on-board debug interface based around an FTDI 4232H device.

This patch adds basic target, interface and board support for PIC64GX
Curiosity Kit.

Change-Id: I2234d8725744fbae00b3909773b370e5c18debd8
Signed-off-by: Liam Fletcher <liam.fletcher@microchip.com>
Reviewed-on: https://review.openocd.org/c/openocd/+/8878
Reviewed-by: Antonio Borneo <borneo.antonio@gmail.com>
Tested-by: jenkins
2025-07-25 16:42:16 +00:00
Liam Fletcher
6e87864dfc tcl: add embedded flashpro5 config
To support Microchips Embedded Flashpro5

Change-Id: I7861e0772fd4cbf0539725d238c59ae15bbcca41
Signed-off-by: Liam Fletcher <liam.fletcher@microchip.com>
Reviewed-on: https://review.openocd.org/c/openocd/+/8879
Tested-by: jenkins
Reviewed-by: Antonio Borneo <borneo.antonio@gmail.com>
Reviewed-by: Tomas Vanek <vanekt@fbl.cz>
2025-07-25 16:41:58 +00:00
Liam Fletcher
d06ecba2e6 target: add microchip polarfire soc config
Microchip's PolarFire SoC has a RISC-V core complex with four
application processors and one monitor processor. This basic
configuration can be used to attach to all proccessor's or a single
processor, specified by the run-time argument $COREID

It can be used with most FTDI based debug interfaces and has been tested
with interface/ftdi/olimex-arm-usb-tiny-h.cfg.

Change-Id: I75dd965f1ce550807706d00fe17de887d36f0b02
Signed-off-by: Liam Fletcher <liam.fletcher@microchip.com>
Reviewed-on: https://review.openocd.org/c/openocd/+/8877
Reviewed-by: Tomas Vanek <vanekt@fbl.cz>
Tested-by: jenkins
Reviewed-by: Antonio Borneo <borneo.antonio@gmail.com>
2025-07-25 16:41:22 +00:00
Nicolas Derumigny
a192949095 jtag: drivers: xlnx-axi-xvc: Add support for Xilinx XVC over direct bus interface (AXI)
This change allow to use direct mapping of the JTAG interface using
Xilinx Virtual Cable (XVC) over AXI. This merges the existing XVC PCIe
code and the patch proposed by Jeremy Garff
(https://review.openocd.org/c/openocd/+/6594).

This is useful when using on a Zynq/ZynqMP/uBlaze host with direct
access to the debug bridge over AXI.  You can then use the debug bridge
Xilinx IP (AXIXVC) to debug a remote device.

Signed-off-by: Nicolas Derumigny <nicolas.derumigny@inria.fr>
Change-Id: I934591b489e30b400b87772b1437e6030440904c
Reviewed-on: https://review.openocd.org/c/openocd/+/8595
Tested-by: jenkins
Reviewed-by: Antonio Borneo <borneo.antonio@gmail.com>
2025-07-25 16:38:41 +00:00
Nicolas Derumigny
8cdf8cb995 driver: jtag: rename xlnx-pcie-xvc to xlnx-xvc
Rename xlnx-pcie-xvc.c to xlnx-xvc.c in provision for AXI support

Signed-off-by: Nicolas Derumigny <nicolas.derumigny@inria.fr>
Change-Id: I287fdcb8edf97f48c6f8614ac4c456f8ba197011
Reviewed-on: https://review.openocd.org/c/openocd/+/8980
Reviewed-by: Antonio Borneo <borneo.antonio@gmail.com>
Tested-by: jenkins
2025-07-25 16:38:28 +00:00
23 changed files with 1526 additions and 158 deletions

View File

@@ -177,8 +177,8 @@ m4_define([REMOTE_BITBANG_ADAPTER],
m4_define([LIBJAYLINK_ADAPTERS],
[[[jlink], [SEGGER J-Link Programmer], [JLINK]]])
m4_define([PCIE_ADAPTERS],
[[[xlnx_pcie_xvc], [Xilinx XVC/PCIe], [XLNX_PCIE_XVC]]])
m4_define([XVC_ADAPTERS],
[[[xlnx_xvc], [Xilinx XVC PCIe and AXI drives], [XLNX_XVC]]])
m4_define([SERIAL_PORT_ADAPTERS],
[[[buspirate], [Bus Pirate], [BUS_PIRATE]]])
@@ -335,7 +335,7 @@ AC_ARG_ADAPTERS([
JTAG_DPI_ADAPTER,
JTAG_VPI_ADAPTER,
RSHIM_ADAPTER,
PCIE_ADAPTERS,
XVC_ADAPTERS,
LIBJAYLINK_ADAPTERS
],[auto])
@@ -644,7 +644,7 @@ PROCESS_ADAPTERS([DMEM_ADAPTER], ["x$is_linux" = "xyes"], [Linux /dev/mem])
PROCESS_ADAPTERS([SYSFSGPIO_ADAPTER], ["x$is_linux" = "xyes"], [Linux sysfs])
PROCESS_ADAPTERS([REMOTE_BITBANG_ADAPTER], [true], [unused])
PROCESS_ADAPTERS([LIBJAYLINK_ADAPTERS], ["x$use_internal_libjaylink" = "xyes" -o "x$use_libjaylink" = "xyes"], [libjaylink-0.2])
PROCESS_ADAPTERS([PCIE_ADAPTERS], ["x$is_linux" = "xyes" -a "x$ac_cv_header_linux_pci_h" = "xyes"], [Linux build])
PROCESS_ADAPTERS([XVC_ADAPTERS], ["x$is_linux" = "xyes" -a "x$ac_cv_header_linux_pci_h" = "xyes"], [Linux build])
PROCESS_ADAPTERS([SERIAL_PORT_ADAPTERS], ["x$can_build_buspirate" = "xyes"],
[internal error: validation should happen beforehand])
PROCESS_ADAPTERS([LINUXSPIDEV_ADAPTER], ["x$is_linux" = "xyes" -a "x$ac_cv_header_linux_spi_spidev_h" = "xyes"],
@@ -840,7 +840,8 @@ m4_foreach([adapterTuple], [USB1_ADAPTERS,
DMEM_ADAPTER,
SYSFSGPIO_ADAPTER,
REMOTE_BITBANG_ADAPTER,
LIBJAYLINK_ADAPTERS, PCIE_ADAPTERS, SERIAL_PORT_ADAPTERS,
LIBJAYLINK_ADAPTERS, XVC_ADAPTERS,
SERIAL_PORT_ADAPTERS,
LINUXSPIDEV_ADAPTER,
VDEBUG_ADAPTER,
JTAG_DPI_ADAPTER,

View File

@@ -190,6 +190,10 @@ ATTRS{idVendor}=="138e", ATTRS{idProduct}=="9000", MODE="660", GROUP="plugdev",
# Debug Board for Neo1973
ATTRS{idVendor}=="1457", ATTRS{idProduct}=="5118", MODE="660", GROUP="plugdev", TAG+="uaccess"
# Microchip RISC-V Debug
ATTRS{idVendor}=="1514", ATTRS{idProduct}=="2008", MODE="660", GROUP="plugdev", TAG+="uaccess"
ATTRS{idVendor}=="1514", ATTRS{idProduct}=="200a", MODE="660", GROUP="plugdev", TAG+="uaccess"
# OSBDM
ATTRS{idVendor}=="15a2", ATTRS{idProduct}=="0042", MODE="660", GROUP="plugdev", TAG+="uaccess"
ATTRS{idVendor}=="15a2", ATTRS{idProduct}=="0058", MODE="660", GROUP="plugdev", TAG+="uaccess"

View File

@@ -613,6 +613,12 @@ emulation model of target hardware.
@item @b{xlnx_pcie_xvc}
@* A JTAG driver exposing Xilinx Virtual Cable over PCI Express to OpenOCD as JTAG/SWD interface.
@* Link: @url{https://www.xilinx.com/products/intellectual-property/debug-bridge.html}
@item @b{xlnx_axi_xvc}
@* A JTAG driver exposing JTAG to OpenOCD over AXI-mapped registers.
@* Link: @url{https://docs.amd.com/r/en-US/pg437-axi-jtag/Introduction}
@* Link: @url{https://china.xilinx.com/support/documentation/application_notes/xapp1251-xvc-zynq-petalinux.pdf}
@item @b{linuxspidev}
@* A SPI based SWD driver using Linux SPI devices.
@@ -3352,6 +3358,21 @@ The string will be of the format "DDDD:BB:SS.F" such as "0000:65:00.1".
@end deffn
@end deffn
@deffn {Interface Driver} {xlnx_axi_xvc}
This driver supports the Xilinx JTAG mapping over AXI using the AXI to JTAG
Converter or the AXI-to-JTAG mode of the debug bridge.
It is commonly found in Xilinx MPSoC based designs. It allows debugging
fabric based JTAG/SWD devices such as Cortex-M1/M3 or RISC-V softcores. Access to this
is exposed via extended capability registers in the AXI-mapped configuration space.
@deffn {Config Command} {xlnx_axi_xvc dev_addr} addr
Specifies the address of the AXI-mapped registers via parameter @var{addr}.
The correct value for @var{addr} is specified in the "Address Editor" tab
in Vivado.
@end deffn
@end deffn
@deffn {Interface Driver} {bcm2835gpio}
This GPIO interface is present in Raspberry Pi 0-4 which is a cheap
single-board computer exposing some GPIOs on its expansion header.

View File

@@ -179,8 +179,8 @@ endif
if LINUXSPIDEV
DRIVERFILES += %D%/linuxspidev.c
endif
if XLNX_PCIE_XVC
DRIVERFILES += %D%/xlnx-pcie-xvc.c
if XLNX_XVC
DRIVERFILES += %D%/xlnx-xvc.c
endif
if BCM2835GPIO
DRIVERFILES += %D%/bcm2835gpio.c

View File

@@ -428,7 +428,7 @@ static bool usb_connect(void)
/* Log the results */
if (result == 0)
LOG_INFO("XDS110: connected");
LOG_DEBUG("XDS110: connected");
else
LOG_ERROR("XDS110: failed to connect");
@@ -448,7 +448,7 @@ static void usb_disconnect(void)
xds110.ctx = NULL;
}
LOG_INFO("XDS110: disconnected");
LOG_DEBUG("XDS110: disconnected");
}
static bool usb_read(unsigned char *buffer, int size, int *bytes_read,

View File

@@ -1,8 +1,14 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (c) 2019 Google, LLC.
* Author: Moritz Fischer <moritzf@google.com>
* Copyright (C) 2019 Google, LLC.
* Moritz Fischer <moritzf@google.com>
*
* Copyright (C) 2021 Western Digital Corporation or its affiliates
* Jeremy Garff <jeremy.garff@wdc.com>
*
* Copyright (C) 2024 Inria
* Nicolas Derumigny <nicolas.derumigny@inria.fr>
*/
#ifdef HAVE_CONFIG_H
@@ -11,13 +17,14 @@
#include <stdint.h>
#include <stdlib.h>
#include <math.h>
#include <unistd.h>
#include <linux/pci.h>
#include <sys/mman.h>
#include <jtag/interface.h>
#include <jtag/swd.h>
#include <jtag/commands.h>
#include <jtag/interface.h>
#include <jtag/swd.h>
#include <helper/replacements.h>
#include <helper/bits.h>
@@ -28,14 +35,24 @@
#define PCIE_EXT_CAP_LST 0x100
#define XLNX_XVC_EXT_CAP 0x00
#define XLNX_XVC_VSEC_HDR 0x04
#define XLNX_XVC_LEN_REG 0x0C
#define XLNX_XVC_TMS_REG 0x10
#define XLNX_XVC_TDX_REG 0x14
#define XLNX_PCIE_XVC_EXT_CAP 0x00
#define XLNX_PCIE_XVC_VSEC_HDR 0x04
#define XLNX_PCIE_XVC_LEN_REG 0x0C
#define XLNX_PCIE_XVC_TMS_REG 0x10
#define XLNX_PCIE_XVC_TDX_REG 0x14
#define XLNX_PCIE_XVC_CAP_SIZE 0x20
#define XLNX_PCIE_XVC_VSEC_ID 0x8
#define XLNX_AXI_XVC_LEN_REG 0x00
#define XLNX_AXI_XVC_TMS_REG 0x04
#define XLNX_AXI_XVC_TDI_REG 0x08
#define XLNX_AXI_XVC_TDO_REG 0x0c
#define XLNX_AXI_XVC_CTRL_REG 0x10
#define XLNX_AXI_XVC_MAX_REG 0x18
#define XLNX_AXI_XVC_CTRL_REG_ENABLE_MASK 0x01
#define XLNX_XVC_CAP_SIZE 0x20
#define XLNX_XVC_VSEC_ID 0x8
#define XLNX_XVC_MAX_BITS 0x20
#define MASK_ACK(x) (((x) >> 9) & 0x7)
@@ -47,8 +64,23 @@ struct xlnx_pcie_xvc {
char *device;
};
struct xlnx_axi_xvc {
int fd;
uint32_t *base;
char *device_addr;
// Defaults to `/dev/mem` if NULL
char *device_file;
};
enum xlnx_xvc_type_t {
PCIE,
AXI
};
static struct xlnx_pcie_xvc xlnx_pcie_xvc_state;
static struct xlnx_pcie_xvc *xlnx_pcie_xvc = &xlnx_pcie_xvc_state;
static struct xlnx_axi_xvc xlnx_axi_xvc_state;
static struct xlnx_axi_xvc *xlnx_axi_xvc = &xlnx_axi_xvc_state;
static int xlnx_pcie_xvc_read_reg(const int offset, uint32_t *val)
{
@@ -60,9 +92,9 @@ static int xlnx_pcie_xvc_read_reg(const int offset, uint32_t *val)
* space accessor functions
*/
err = pread(xlnx_pcie_xvc->fd, &res, sizeof(res),
xlnx_pcie_xvc->offset + offset);
xlnx_pcie_xvc->offset + offset);
if (err != sizeof(res)) {
LOG_ERROR("Failed to read offset %x", offset);
LOG_ERROR("Failed to read offset 0x%x", offset);
return ERROR_JTAG_DEVICE_ERROR;
}
@@ -72,6 +104,19 @@ static int xlnx_pcie_xvc_read_reg(const int offset, uint32_t *val)
return ERROR_OK;
}
static int xlnx_axi_xvc_read_reg(const int offset, uint32_t *val)
{
uintptr_t b = ((uintptr_t)xlnx_axi_xvc->base) + offset;
volatile uint32_t *w = (uint32_t *)b;
if (val) {
__atomic_thread_fence(__ATOMIC_SEQ_CST);
*val = *w;
}
return ERROR_OK;
}
static int xlnx_pcie_xvc_write_reg(const int offset, const uint32_t val)
{
int err;
@@ -81,9 +126,9 @@ static int xlnx_pcie_xvc_write_reg(const int offset, const uint32_t val)
* space accessor functions
*/
err = pwrite(xlnx_pcie_xvc->fd, &val, sizeof(val),
xlnx_pcie_xvc->offset + offset);
xlnx_pcie_xvc->offset + offset);
if (err != sizeof(val)) {
LOG_ERROR("Failed to write offset: %x with value: %" PRIx32,
LOG_ERROR("Failed to write offset: 0x%x with value: %" PRIx32,
offset, val);
return ERROR_JTAG_DEVICE_ERROR;
}
@@ -91,37 +136,117 @@ static int xlnx_pcie_xvc_write_reg(const int offset, const uint32_t val)
return ERROR_OK;
}
static int xlnx_axi_xvc_write_reg(const int offset, const uint32_t val)
{
uintptr_t b = ((uintptr_t)xlnx_axi_xvc->base) + offset;
volatile uint32_t *w = (uint32_t *)b;
*w = val;
__atomic_thread_fence(__ATOMIC_SEQ_CST);
return ERROR_OK;
}
static int xlnx_pcie_xvc_transact(size_t num_bits, uint32_t tms, uint32_t tdi,
uint32_t *tdo)
{
int err;
err = xlnx_pcie_xvc_write_reg(XLNX_XVC_LEN_REG, num_bits);
err = xlnx_pcie_xvc_write_reg(XLNX_PCIE_XVC_LEN_REG, num_bits);
if (err != ERROR_OK)
return err;
err = xlnx_pcie_xvc_write_reg(XLNX_XVC_TMS_REG, tms);
err = xlnx_pcie_xvc_write_reg(XLNX_PCIE_XVC_TMS_REG, tms);
if (err != ERROR_OK)
return err;
err = xlnx_pcie_xvc_write_reg(XLNX_XVC_TDX_REG, tdi);
err = xlnx_pcie_xvc_write_reg(XLNX_PCIE_XVC_TDX_REG, tdi);
if (err != ERROR_OK)
return err;
err = xlnx_pcie_xvc_read_reg(XLNX_XVC_TDX_REG, tdo);
err = xlnx_pcie_xvc_read_reg(XLNX_PCIE_XVC_TDX_REG, tdo);
if (err != ERROR_OK)
return err;
if (tdo)
LOG_DEBUG_IO("Transact num_bits: %zu, tms: %" PRIx32 ", tdi: %" PRIx32 ", tdo: %" PRIx32,
num_bits, tms, tdi, *tdo);
num_bits, tms, tdi, *tdo);
else
LOG_DEBUG_IO("Transact num_bits: %zu, tms: %" PRIx32 ", tdi: %" PRIx32 ", tdo: <null>",
num_bits, tms, tdi);
num_bits, tms, tdi);
return ERROR_OK;
}
static int xlnx_pcie_xvc_execute_stableclocks(struct jtag_command *cmd)
static int xlnx_axi_xvc_transact(size_t num_bits, uint32_t tms, uint32_t tdi,
uint32_t *tdo)
{
uint32_t ctrl;
int done = 0;
int err;
err = xlnx_axi_xvc_write_reg(XLNX_AXI_XVC_LEN_REG, num_bits);
if (err != ERROR_OK)
return err;
err = xlnx_axi_xvc_write_reg(XLNX_AXI_XVC_TMS_REG, tms);
if (err != ERROR_OK)
return err;
err = xlnx_axi_xvc_write_reg(XLNX_AXI_XVC_TDI_REG, tdi);
if (err != ERROR_OK)
return err;
err = xlnx_axi_xvc_write_reg(XLNX_AXI_XVC_CTRL_REG, XLNX_AXI_XVC_CTRL_REG_ENABLE_MASK);
if (err != ERROR_OK)
return err;
while (!done) {
err = xlnx_axi_xvc_read_reg(XLNX_AXI_XVC_CTRL_REG, &ctrl);
if (err != ERROR_OK)
return err;
if (!(ctrl & XLNX_AXI_XVC_CTRL_REG_ENABLE_MASK))
done = 1;
/*
There is no delay here intentionally. The usleep()
function doesn't block and burns CPU cycles anyway.
The turnaround time is fast enough at high JTAG rates
that adding the call can slow down the overall
throughput. So we'll just sacrifice the CPU to get
best performance.
Additionally there is no timeout. The underlying
hardware is guaranteed to unset the enable bit within
32 JTAG clock cycles. There is no hardware condition
that will keep it set forever. Essentially, the hardware
is also our timeout mechanism.
*/
}
err = xlnx_axi_xvc_read_reg(XLNX_AXI_XVC_TDO_REG, tdo);
if (err != ERROR_OK)
return err;
if (tdo)
LOG_DEBUG_IO("Transact num_bits: %zu, tms: 0x%x, tdi: 0x%x, tdo: 0x%x",
num_bits, tms, tdi, *tdo);
else
LOG_DEBUG_IO("Transact num_bits: %zu, tms: 0x%x, tdi: 0x%x, tdo: <null>",
num_bits, tms, tdi);
return ERROR_OK;
}
static int xlnx_xvc_transact(size_t num_bits, uint32_t tms, uint32_t tdi,
uint32_t *tdo, enum xlnx_xvc_type_t xvc_type)
{
if (xvc_type == PCIE)
return xlnx_pcie_xvc_transact(num_bits, tms, tdi, tdo);
assert(xvc_type == AXI);
return xlnx_axi_xvc_transact(num_bits, tms, tdi, tdo);
}
static int xlnx_xvc_execute_stableclocks(struct jtag_command *cmd, enum xlnx_xvc_type_t xvc_type)
{
int tms = tap_get_state() == TAP_RESET ? 1 : 0;
size_t left = cmd->cmd.stableclocks->num_cycles;
@@ -132,7 +257,7 @@ static int xlnx_pcie_xvc_execute_stableclocks(struct jtag_command *cmd)
while (left) {
write = MIN(XLNX_XVC_MAX_BITS, left);
err = xlnx_pcie_xvc_transact(write, tms, 0, NULL);
err = xlnx_xvc_transact(write, tms, 0, NULL, xvc_type);
if (err != ERROR_OK)
return err;
left -= write;
@@ -141,12 +266,12 @@ static int xlnx_pcie_xvc_execute_stableclocks(struct jtag_command *cmd)
return ERROR_OK;
}
static int xlnx_pcie_xvc_execute_statemove(size_t skip)
static int xlnx_xvc_execute_statemove(size_t skip, enum xlnx_xvc_type_t xvc_type)
{
uint8_t tms_scan = tap_get_tms_path(tap_get_state(),
tap_get_end_state());
tap_get_end_state());
int tms_count = tap_get_tms_path_len(tap_get_state(),
tap_get_end_state());
tap_get_end_state());
int err;
LOG_DEBUG("statemove starting at (skip: %zu) %s end in %s", skip,
@@ -154,7 +279,7 @@ static int xlnx_pcie_xvc_execute_statemove(size_t skip)
tap_state_name(tap_get_end_state()));
err = xlnx_pcie_xvc_transact(tms_count - skip, tms_scan >> skip, 0, NULL);
err = xlnx_xvc_transact(tms_count - skip, tms_scan >> skip, 0, NULL, xvc_type);
if (err != ERROR_OK)
return err;
@@ -163,7 +288,8 @@ static int xlnx_pcie_xvc_execute_statemove(size_t skip)
return ERROR_OK;
}
static int xlnx_pcie_xvc_execute_runtest(struct jtag_command *cmd)
static int xlnx_xvc_execute_runtest(struct jtag_command *cmd,
enum xlnx_xvc_type_t xvc_type)
{
int err = ERROR_OK;
@@ -175,7 +301,7 @@ static int xlnx_pcie_xvc_execute_runtest(struct jtag_command *cmd)
if (tap_get_state() != TAP_IDLE) {
tap_set_end_state(TAP_IDLE);
err = xlnx_pcie_xvc_execute_statemove(0);
err = xlnx_xvc_execute_statemove(0, xvc_type);
if (err != ERROR_OK)
return err;
};
@@ -185,7 +311,7 @@ static int xlnx_pcie_xvc_execute_runtest(struct jtag_command *cmd)
while (left) {
write = MIN(XLNX_XVC_MAX_BITS, left);
err = xlnx_pcie_xvc_transact(write, 0, 0, NULL);
err = xlnx_xvc_transact(write, 0, 0, NULL, xvc_type);
if (err != ERROR_OK)
return err;
left -= write;
@@ -193,12 +319,13 @@ static int xlnx_pcie_xvc_execute_runtest(struct jtag_command *cmd)
tap_set_end_state(tmp_state);
if (tap_get_state() != tap_get_end_state())
err = xlnx_pcie_xvc_execute_statemove(0);
err = xlnx_xvc_execute_statemove(0, xvc_type);
return err;
}
static int xlnx_pcie_xvc_execute_pathmove(struct jtag_command *cmd)
static int xlnx_xvc_execute_pathmove(struct jtag_command *cmd,
enum xlnx_xvc_type_t xvc_type)
{
unsigned int num_states = cmd->cmd.pathmove->num_states;
enum tap_state *path = cmd->cmd.pathmove->path;
@@ -210,9 +337,9 @@ static int xlnx_pcie_xvc_execute_pathmove(struct jtag_command *cmd)
for (unsigned int i = 0; i < num_states; i++) {
if (path[i] == tap_state_transition(tap_get_state(), false)) {
err = xlnx_pcie_xvc_transact(1, 0, 0, NULL);
err = xlnx_xvc_transact(1, 0, 0, NULL, xvc_type);
} else if (path[i] == tap_state_transition(tap_get_state(), true)) {
err = xlnx_pcie_xvc_transact(1, 1, 0, NULL);
err = xlnx_xvc_transact(1, 1, 0, NULL, xvc_type);
} else {
LOG_ERROR("BUG: %s -> %s isn't a valid TAP transition.",
tap_state_name(tap_get_state()),
@@ -229,7 +356,8 @@ static int xlnx_pcie_xvc_execute_pathmove(struct jtag_command *cmd)
return ERROR_OK;
}
static int xlnx_pcie_xvc_execute_scan(struct jtag_command *cmd)
static int xlnx_xvc_execute_scan(struct jtag_command *cmd,
enum xlnx_xvc_type_t xvc_type)
{
enum scan_type type = jtag_scan_type(cmd->cmd.scan);
enum tap_state saved_end_state = cmd->cmd.scan->end_state;
@@ -253,13 +381,13 @@ static int xlnx_pcie_xvc_execute_scan(struct jtag_command *cmd)
*/
if (ir_scan && tap_get_state() != TAP_IRSHIFT) {
tap_set_end_state(TAP_IRSHIFT);
err = xlnx_pcie_xvc_execute_statemove(0);
err = xlnx_xvc_execute_statemove(0, xvc_type);
if (err != ERROR_OK)
goto out_err;
tap_set_end_state(saved_end_state);
} else if (!ir_scan && (tap_get_state() != TAP_DRSHIFT)) {
tap_set_end_state(TAP_DRSHIFT);
err = xlnx_pcie_xvc_execute_statemove(0);
err = xlnx_xvc_execute_statemove(0, xvc_type);
if (err != ERROR_OK)
goto out_err;
tap_set_end_state(saved_end_state);
@@ -271,8 +399,8 @@ static int xlnx_pcie_xvc_execute_scan(struct jtag_command *cmd)
/* the last TMS should be a 1, to leave the state */
tms = left <= XLNX_XVC_MAX_BITS ? BIT(write - 1) : 0;
tdi = (type != SCAN_IN) ? buf_get_u32(rd_ptr, 0, write) : 0;
err = xlnx_pcie_xvc_transact(write, tms, tdi, type != SCAN_OUT ?
&tdo : NULL);
err = xlnx_xvc_transact(write, tms, tdi, type != SCAN_OUT ?
&tdo : NULL, xvc_type);
if (err != ERROR_OK)
goto out_err;
left -= write;
@@ -285,7 +413,7 @@ static int xlnx_pcie_xvc_execute_scan(struct jtag_command *cmd)
free(buf);
if (tap_get_state() != tap_get_end_state())
err = xlnx_pcie_xvc_execute_statemove(1);
err = xlnx_xvc_execute_statemove(1, xvc_type);
return err;
@@ -294,19 +422,14 @@ out_err:
return err;
}
static void xlnx_pcie_xvc_execute_reset(struct jtag_command *cmd)
{
LOG_DEBUG("reset trst: %i srst: %i", cmd->cmd.reset->trst,
cmd->cmd.reset->srst);
}
static void xlnx_pcie_xvc_execute_sleep(struct jtag_command *cmd)
static void xlnx_xvc_execute_sleep(struct jtag_command *cmd)
{
LOG_DEBUG("sleep %" PRIu32 "", cmd->cmd.sleep->us);
usleep(cmd->cmd.sleep->us);
}
static int xlnx_pcie_xvc_execute_tms(struct jtag_command *cmd)
static int xlnx_xvc_execute_tms(struct jtag_command *cmd,
enum xlnx_xvc_type_t xvc_type)
{
const size_t num_bits = cmd->cmd.tms->num_bits;
const uint8_t *bits = cmd->cmd.tms->bits;
@@ -320,7 +443,7 @@ static int xlnx_pcie_xvc_execute_tms(struct jtag_command *cmd)
while (left) {
write = MIN(XLNX_XVC_MAX_BITS, left);
tms = buf_get_u32(bits, 0, write);
err = xlnx_pcie_xvc_transact(write, tms, 0, NULL);
err = xlnx_xvc_transact(write, tms, 0, NULL, xvc_type);
if (err != ERROR_OK)
return err;
left -= write;
@@ -330,29 +453,30 @@ static int xlnx_pcie_xvc_execute_tms(struct jtag_command *cmd)
return ERROR_OK;
}
static int xlnx_pcie_xvc_execute_command(struct jtag_command *cmd)
static int xlnx_xvc_execute_command(struct jtag_command *cmd,
enum xlnx_xvc_type_t xvc_type)
{
LOG_DEBUG("%s: cmd->type: %u", __func__, cmd->type);
switch (cmd->type) {
case JTAG_STABLECLOCKS:
return xlnx_pcie_xvc_execute_stableclocks(cmd);
return xlnx_xvc_execute_stableclocks(cmd, xvc_type);
case JTAG_RUNTEST:
return xlnx_pcie_xvc_execute_runtest(cmd);
return xlnx_xvc_execute_runtest(cmd, xvc_type);
case JTAG_TLR_RESET:
tap_set_end_state(cmd->cmd.statemove->end_state);
return xlnx_pcie_xvc_execute_statemove(0);
return xlnx_xvc_execute_statemove(0, xvc_type);
case JTAG_PATHMOVE:
return xlnx_pcie_xvc_execute_pathmove(cmd);
return xlnx_xvc_execute_pathmove(cmd, xvc_type);
case JTAG_SCAN:
return xlnx_pcie_xvc_execute_scan(cmd);
return xlnx_xvc_execute_scan(cmd, xvc_type);
case JTAG_RESET:
xlnx_pcie_xvc_execute_reset(cmd);
LOG_INFO("WARN: XVC driver has no reset.");
break;
case JTAG_SLEEP:
xlnx_pcie_xvc_execute_sleep(cmd);
xlnx_xvc_execute_sleep(cmd);
break;
case JTAG_TMS:
return xlnx_pcie_xvc_execute_tms(cmd);
return xlnx_xvc_execute_tms(cmd, xvc_type);
default:
LOG_ERROR("BUG: Unknown JTAG command type encountered.");
return ERROR_JTAG_QUEUE_FAILED;
@@ -361,13 +485,14 @@ static int xlnx_pcie_xvc_execute_command(struct jtag_command *cmd)
return ERROR_OK;
}
static int xlnx_pcie_xvc_execute_queue(struct jtag_command *cmd_queue)
static int xlnx_xvc_execute_queue(struct jtag_command *cmd_queue,
enum xlnx_xvc_type_t xvc_type)
{
struct jtag_command *cmd = cmd_queue;
int ret;
while (cmd) {
ret = xlnx_pcie_xvc_execute_command(cmd);
ret = xlnx_xvc_execute_command(cmd, xvc_type);
if (ret != ERROR_OK)
return ret;
@@ -378,6 +503,15 @@ static int xlnx_pcie_xvc_execute_queue(struct jtag_command *cmd_queue)
return ERROR_OK;
}
static int xlnx_pcie_xvc_execute_queue(struct jtag_command *cmd_queue)
{
return xlnx_xvc_execute_queue(cmd_queue, PCIE);
}
static int xlnx_axi_xvc_execute_queue(struct jtag_command *cmd_queue)
{
return xlnx_xvc_execute_queue(cmd_queue, AXI);
}
static int xlnx_pcie_xvc_init(void)
{
@@ -399,8 +533,8 @@ static int xlnx_pcie_xvc_init(void)
* vendor specific header */
xlnx_pcie_xvc->offset = PCIE_EXT_CAP_LST;
while (xlnx_pcie_xvc->offset <= PCI_CFG_SPACE_EXP_SIZE - sizeof(cap) &&
xlnx_pcie_xvc->offset >= PCIE_EXT_CAP_LST) {
err = xlnx_pcie_xvc_read_reg(XLNX_XVC_EXT_CAP, &cap);
xlnx_pcie_xvc->offset >= PCIE_EXT_CAP_LST) {
err = xlnx_pcie_xvc_read_reg(XLNX_PCIE_XVC_EXT_CAP, &cap);
if (err != ERROR_OK)
return err;
LOG_DEBUG("Checking capability at 0x%x; id=0x%04" PRIx32 " version=0x%" PRIx32 " next=0x%" PRIx32,
@@ -409,7 +543,7 @@ static int xlnx_pcie_xvc_init(void)
PCI_EXT_CAP_VER(cap),
PCI_EXT_CAP_NEXT(cap));
if (PCI_EXT_CAP_ID(cap) == PCI_EXT_CAP_ID_VNDR) {
err = xlnx_pcie_xvc_read_reg(XLNX_XVC_VSEC_HDR, &vh);
err = xlnx_pcie_xvc_read_reg(XLNX_PCIE_XVC_VSEC_HDR, &vh);
if (err != ERROR_OK)
return err;
LOG_DEBUG("Checking possible match at 0x%x; id: 0x%" PRIx32 "; rev: 0x%" PRIx32 "; length: 0x%" PRIx32,
@@ -417,14 +551,14 @@ static int xlnx_pcie_xvc_init(void)
PCI_VNDR_HEADER_ID(vh),
PCI_VNDR_HEADER_REV(vh),
PCI_VNDR_HEADER_LEN(vh));
if ((PCI_VNDR_HEADER_ID(vh) == XLNX_XVC_VSEC_ID) &&
(PCI_VNDR_HEADER_LEN(vh) == XLNX_XVC_CAP_SIZE))
if ((PCI_VNDR_HEADER_ID(vh) == XLNX_PCIE_XVC_VSEC_ID) &&
(PCI_VNDR_HEADER_LEN(vh) == XLNX_PCIE_XVC_CAP_SIZE))
break;
}
xlnx_pcie_xvc->offset = PCI_EXT_CAP_NEXT(cap);
}
if ((xlnx_pcie_xvc->offset > PCI_CFG_SPACE_EXP_SIZE - XLNX_XVC_CAP_SIZE) ||
xlnx_pcie_xvc->offset < PCIE_EXT_CAP_LST) {
if ((xlnx_pcie_xvc->offset > PCI_CFG_SPACE_EXP_SIZE - XLNX_PCIE_XVC_CAP_SIZE) ||
xlnx_pcie_xvc->offset < PCIE_EXT_CAP_LST) {
close(xlnx_pcie_xvc->fd);
return ERROR_JTAG_INIT_FAILED;
}
@@ -434,6 +568,44 @@ static int xlnx_pcie_xvc_init(void)
return ERROR_OK;
}
static int xlnx_axi_xvc_init(void)
{
uint64_t baseaddr;
if (xlnx_axi_xvc->device_addr) {
baseaddr = strtoul(xlnx_axi_xvc->device_addr, NULL, 0);
} else {
LOG_ERROR("Please set device addr.");
return ERROR_JTAG_INIT_FAILED;
}
if (xlnx_axi_xvc->device_file) {
LOG_INFO("Opening %s for AXI communication", xlnx_axi_xvc->device_file);
xlnx_axi_xvc->fd = open(xlnx_axi_xvc->device_file, O_RDWR | O_SYNC);
} else {
LOG_INFO("Opening /dev/mem for AXI communication");
xlnx_axi_xvc->fd = open("/dev/mem", O_RDWR | O_SYNC);
}
if (xlnx_axi_xvc->fd < 0) {
LOG_ERROR("Failed to open device file, check permissions.");
return ERROR_JTAG_INIT_FAILED;
}
xlnx_axi_xvc->base = mmap(0, XLNX_AXI_XVC_MAX_REG, PROT_READ | PROT_WRITE,
MAP_SHARED, xlnx_axi_xvc->fd, baseaddr);
if (xlnx_axi_xvc->base == MAP_FAILED) {
LOG_ERROR("mmap() failed, check permissions.");
close(xlnx_axi_xvc->fd);
return ERROR_JTAG_INIT_FAILED;
}
LOG_INFO("Mapped Xilinx XVC/AXI vaddr %p paddr 0x%" PRIx64,
xlnx_axi_xvc->base, baseaddr);
return ERROR_OK;
}
static int xlnx_pcie_xvc_quit(void)
{
int err;
@@ -445,21 +617,55 @@ static int xlnx_pcie_xvc_quit(void)
return ERROR_OK;
}
static int xlnx_axi_xvc_quit(void)
{
int err;
munmap(xlnx_axi_xvc->base, XLNX_AXI_XVC_MAX_REG);
free(xlnx_pcie_xvc->device);
free(xlnx_axi_xvc->device_file);
free(xlnx_axi_xvc->device_addr);
err = close(xlnx_axi_xvc->fd);
if (err)
return err;
return ERROR_OK;
}
COMMAND_HANDLER(xlnx_pcie_xvc_handle_config_command)
{
if (CMD_ARGC < 1)
if (CMD_ARGC != 1)
return ERROR_COMMAND_SYNTAX_ERROR;
/* we can't really free this in a safe manner, so at least
* limit the memory we're leaking by freeing the old one first
* before allocating a new one ...
*/
free(xlnx_pcie_xvc->device);
xlnx_pcie_xvc->device = strdup(CMD_ARGV[0]);
return ERROR_OK;
}
COMMAND_HANDLER(xlnx_axi_xvc_handle_dev_addr_command)
{
if (CMD_ARGC != 1)
return ERROR_COMMAND_SYNTAX_ERROR;
free(xlnx_axi_xvc->device_addr);
xlnx_axi_xvc->device_addr = strdup(CMD_ARGV[0]);
return ERROR_OK;
}
COMMAND_HANDLER(xlnx_axi_xvc_handle_dev_file_command)
{
if (CMD_ARGC != 1)
return ERROR_COMMAND_SYNTAX_ERROR;
free(xlnx_axi_xvc->device_file);
xlnx_axi_xvc->device_file = strdup(CMD_ARGV[0]);
return ERROR_OK;
}
static const struct command_registration xlnx_pcie_xvc_subcommand_handlers[] = {
{
.name = "config",
@@ -482,11 +688,45 @@ static const struct command_registration xlnx_pcie_xvc_command_handlers[] = {
COMMAND_REGISTRATION_DONE
};
static const struct command_registration xlnx_axi_xvc_subcommand_handlers[] = {
{
.name = "dev_addr",
.handler = xlnx_axi_xvc_handle_dev_addr_command,
.mode = COMMAND_CONFIG,
.help = "Configure XVC/AXI JTAG device memory address",
.usage = "addr",
},
{
.name = "dev_file",
.handler = xlnx_axi_xvc_handle_dev_file_command,
.mode = COMMAND_CONFIG,
.help = "Configure XVC/AXI JTAG device file location",
.usage = "addr",
},
COMMAND_REGISTRATION_DONE
};
static const struct command_registration xlnx_axi_xvc_command_handlers[] = {
{
.name = "xlnx_axi_xvc",
.mode = COMMAND_ANY,
.help = "perform xlnx_axi_xvc management",
.chain = xlnx_axi_xvc_subcommand_handlers,
.usage = "",
},
COMMAND_REGISTRATION_DONE
};
static struct jtag_interface xlnx_pcie_xvc_jtag_ops = {
.execute_queue = &xlnx_pcie_xvc_execute_queue,
};
static int xlnx_pcie_xvc_swd_sequence(const uint8_t *seq, size_t length)
static struct jtag_interface xlnx_axi_xvc_jtag_ops = {
.execute_queue = &xlnx_axi_xvc_execute_queue,
};
static int xlnx_xvc_swd_sequence(const uint8_t *seq, size_t length,
enum xlnx_xvc_type_t xvc_type)
{
size_t left, write;
uint32_t send;
@@ -496,7 +736,7 @@ static int xlnx_pcie_xvc_swd_sequence(const uint8_t *seq, size_t length)
while (left) {
write = MIN(XLNX_XVC_MAX_BITS, left);
send = buf_get_u32(seq, 0, write);
err = xlnx_pcie_xvc_transact(write, send, 0, NULL);
err = xlnx_xvc_transact(write, send, 0, NULL, xvc_type);
if (err != ERROR_OK)
return err;
left -= write;
@@ -506,21 +746,22 @@ static int xlnx_pcie_xvc_swd_sequence(const uint8_t *seq, size_t length)
return ERROR_OK;
}
static int xlnx_pcie_xvc_swd_switch_seq(enum swd_special_seq seq)
static int xlnx_xvc_swd_switch_seq(enum swd_special_seq seq,
enum xlnx_xvc_type_t xvc_type)
{
switch (seq) {
case LINE_RESET:
LOG_DEBUG("SWD line reset");
return xlnx_pcie_xvc_swd_sequence(swd_seq_line_reset,
swd_seq_line_reset_len);
return xlnx_xvc_swd_sequence(swd_seq_line_reset,
swd_seq_line_reset_len, xvc_type);
case JTAG_TO_SWD:
LOG_DEBUG("JTAG-to-SWD");
return xlnx_pcie_xvc_swd_sequence(swd_seq_jtag_to_swd,
swd_seq_jtag_to_swd_len);
return xlnx_xvc_swd_sequence(swd_seq_jtag_to_swd,
swd_seq_jtag_to_swd_len, xvc_type);
case SWD_TO_JTAG:
LOG_DEBUG("SWD-to-JTAG");
return xlnx_pcie_xvc_swd_sequence(swd_seq_swd_to_jtag,
swd_seq_swd_to_jtag_len);
return xlnx_xvc_swd_sequence(swd_seq_swd_to_jtag,
swd_seq_swd_to_jtag_len, xvc_type);
default:
LOG_ERROR("Sequence %d not supported", seq);
return ERROR_FAIL;
@@ -529,19 +770,31 @@ static int xlnx_pcie_xvc_swd_switch_seq(enum swd_special_seq seq)
return ERROR_OK;
}
static int queued_retval;
static void xlnx_pcie_xvc_swd_write_reg(uint8_t cmd, uint32_t value,
uint32_t ap_delay_clk);
static void swd_clear_sticky_errors(void)
static int xlnx_pcie_xvc_swd_switch_seq(enum swd_special_seq seq)
{
xlnx_pcie_xvc_swd_write_reg(swd_cmd(false, false, DP_ABORT),
STKCMPCLR | STKERRCLR | WDERRCLR | ORUNERRCLR, 0);
return xlnx_xvc_swd_switch_seq(seq, PCIE);
}
static void xlnx_pcie_xvc_swd_read_reg(uint8_t cmd, uint32_t *value,
uint32_t ap_delay_clk)
static int xlnx_axi_xvc_swd_switch_seq(enum swd_special_seq seq)
{
return xlnx_xvc_swd_switch_seq(seq, AXI);
}
static int queued_retval;
static void xlnx_xvc_swd_write_reg(uint8_t cmd, uint32_t value,
uint32_t ap_delay_clk,
enum xlnx_xvc_type_t xvc_type);
static void swd_clear_sticky_errors(enum xlnx_xvc_type_t xvc_type)
{
xlnx_xvc_swd_write_reg(swd_cmd(false, false, DP_ABORT),
STKCMPCLR | STKERRCLR | WDERRCLR | ORUNERRCLR, 0, xvc_type);
}
static void xlnx_xvc_swd_read_reg(uint8_t cmd, uint32_t *value,
uint32_t ap_delay_clk,
enum xlnx_xvc_type_t xvc_type)
{
uint32_t res, ack, rpar;
int err;
@@ -550,23 +803,23 @@ static void xlnx_pcie_xvc_swd_read_reg(uint8_t cmd, uint32_t *value,
cmd |= SWD_CMD_START | SWD_CMD_PARK;
/* cmd + ack */
err = xlnx_pcie_xvc_transact(12, cmd, 0, &res);
err = xlnx_xvc_transact(12, cmd, 0, &res, xvc_type);
if (err != ERROR_OK)
goto err_out;
ack = MASK_ACK(res);
/* read data */
err = xlnx_pcie_xvc_transact(32, 0, 0, &res);
err = xlnx_xvc_transact(32, 0, 0, &res, xvc_type);
if (err != ERROR_OK)
goto err_out;
/* parity + trn */
err = xlnx_pcie_xvc_transact(2, 0, 0, &rpar);
err = xlnx_xvc_transact(2, 0, 0, &rpar, xvc_type);
if (err != ERROR_OK)
goto err_out;
LOG_DEBUG("%s %s %s reg %X = %08"PRIx32,
LOG_DEBUG("%s %s %s reg %X = %08" PRIx32,
ack == SWD_ACK_OK ? "OK" : ack == SWD_ACK_WAIT ?
"WAIT" : ack == SWD_ACK_FAULT ? "FAULT" : "JUNK",
cmd & SWD_CMD_APNDP ? "AP" : "DP",
@@ -583,19 +836,19 @@ static void xlnx_pcie_xvc_swd_read_reg(uint8_t cmd, uint32_t *value,
if (value)
*value = res;
if (cmd & SWD_CMD_APNDP)
err = xlnx_pcie_xvc_transact(ap_delay_clk, 0, 0, NULL);
err = xlnx_xvc_transact(ap_delay_clk, 0, 0, NULL, xvc_type);
queued_retval = err;
return;
case SWD_ACK_WAIT:
LOG_DEBUG_IO("SWD_ACK_WAIT");
swd_clear_sticky_errors();
swd_clear_sticky_errors(xvc_type);
return;
case SWD_ACK_FAULT:
LOG_DEBUG_IO("SWD_ACK_FAULT");
queued_retval = ack;
return;
default:
LOG_DEBUG_IO("No valid acknowledge: ack=%02"PRIx32, ack);
LOG_DEBUG_IO("No valid acknowledge: ack=%02" PRIx32, ack);
queued_retval = ack;
return;
}
@@ -603,8 +856,21 @@ err_out:
queued_retval = err;
}
static void xlnx_pcie_xvc_swd_write_reg(uint8_t cmd, uint32_t value,
static void xlnx_pcie_xvc_swd_read_reg(uint8_t cmd, uint32_t *value,
uint32_t ap_delay_clk)
{
xlnx_xvc_swd_read_reg(cmd, value, ap_delay_clk, PCIE);
}
static void xlnx_axi_xvc_swd_read_reg(uint8_t cmd, uint32_t *value,
uint32_t ap_delay_clk)
{
xlnx_xvc_swd_read_reg(cmd, value, ap_delay_clk, AXI);
}
static void xlnx_xvc_swd_write_reg(uint8_t cmd, uint32_t value,
uint32_t ap_delay_clk,
enum xlnx_xvc_type_t xvc_type)
{
uint32_t res, ack;
int err;
@@ -613,23 +879,23 @@ static void xlnx_pcie_xvc_swd_write_reg(uint8_t cmd, uint32_t value,
cmd |= SWD_CMD_START | SWD_CMD_PARK;
/* cmd + trn + ack */
err = xlnx_pcie_xvc_transact(13, cmd, 0, &res);
err = xlnx_xvc_transact(13, cmd, 0, &res, xvc_type);
if (err != ERROR_OK)
goto err_out;
ack = MASK_ACK(res);
/* write data */
err = xlnx_pcie_xvc_transact(32, value, 0, NULL);
err = xlnx_xvc_transact(32, value, 0, NULL, xvc_type);
if (err != ERROR_OK)
goto err_out;
/* parity + trn */
err = xlnx_pcie_xvc_transact(2, parity_u32(value), 0, NULL);
err = xlnx_xvc_transact(2, parity_u32(value), 0, NULL, xvc_type);
if (err != ERROR_OK)
goto err_out;
LOG_DEBUG("%s %s %s reg %X = %08"PRIx32,
LOG_DEBUG("%s %s %s reg %X = %08" PRIx32,
ack == SWD_ACK_OK ? "OK" : ack == SWD_ACK_WAIT ?
"WAIT" : ack == SWD_ACK_FAULT ? "FAULT" : "JUNK",
cmd & SWD_CMD_APNDP ? "AP" : "DP",
@@ -640,19 +906,19 @@ static void xlnx_pcie_xvc_swd_write_reg(uint8_t cmd, uint32_t value,
switch (ack) {
case SWD_ACK_OK:
if (cmd & SWD_CMD_APNDP)
err = xlnx_pcie_xvc_transact(ap_delay_clk, 0, 0, NULL);
err = xlnx_xvc_transact(ap_delay_clk, 0, 0, NULL, xvc_type);
queued_retval = err;
return;
case SWD_ACK_WAIT:
LOG_DEBUG_IO("SWD_ACK_WAIT");
swd_clear_sticky_errors();
swd_clear_sticky_errors(xvc_type);
return;
case SWD_ACK_FAULT:
LOG_DEBUG_IO("SWD_ACK_FAULT");
queued_retval = ack;
return;
default:
LOG_DEBUG_IO("No valid acknowledge: ack=%02"PRIx32, ack);
LOG_DEBUG_IO("No valid acknowledge: ack=%02" PRIx32, ack);
queued_retval = ack;
return;
}
@@ -661,12 +927,24 @@ err_out:
queued_retval = err;
}
static int xlnx_pcie_xvc_swd_run_queue(void)
static void xlnx_pcie_xvc_swd_write_reg(uint8_t cmd, uint32_t value,
uint32_t ap_delay_clk)
{
xlnx_xvc_swd_write_reg(cmd, value, ap_delay_clk, PCIE);
}
static void xlnx_axi_xvc_swd_write_reg(uint8_t cmd, uint32_t value,
uint32_t ap_delay_clk)
{
xlnx_xvc_swd_write_reg(cmd, value, ap_delay_clk, AXI);
}
static int xlnx_xvc_swd_run_queue(enum xlnx_xvc_type_t xvc_type)
{
int err;
/* we want at least 8 idle cycles between each transaction */
err = xlnx_pcie_xvc_transact(8, 0, 0, NULL);
err = xlnx_xvc_transact(8, 0, 0, NULL, xvc_type);
if (err != ERROR_OK)
return err;
@@ -677,19 +955,37 @@ static int xlnx_pcie_xvc_swd_run_queue(void)
return err;
}
static int xlnx_pcie_xvc_swd_init(void)
static int xlnx_pcie_xvc_swd_run_queue(void)
{
return xlnx_xvc_swd_run_queue(PCIE);
}
static int xlnx_axi_xvc_swd_run_queue(void)
{
return xlnx_xvc_swd_run_queue(AXI);
}
static int xlnx_xvc_swd_init(void)
{
return ERROR_OK;
}
static const struct swd_driver xlnx_pcie_xvc_swd_ops = {
.init = xlnx_pcie_xvc_swd_init,
.init = xlnx_xvc_swd_init,
.switch_seq = xlnx_pcie_xvc_swd_switch_seq,
.read_reg = xlnx_pcie_xvc_swd_read_reg,
.write_reg = xlnx_pcie_xvc_swd_write_reg,
.run = xlnx_pcie_xvc_swd_run_queue,
};
static const struct swd_driver xlnx_axi_xvc_swd_ops = {
.init = xlnx_xvc_swd_init,
.switch_seq = xlnx_axi_xvc_swd_switch_seq,
.read_reg = xlnx_axi_xvc_swd_read_reg,
.write_reg = xlnx_axi_xvc_swd_write_reg,
.run = xlnx_axi_xvc_swd_run_queue,
};
struct adapter_driver xlnx_pcie_xvc_adapter_driver = {
.name = "xlnx_pcie_xvc",
.transport_ids = TRANSPORT_JTAG | TRANSPORT_SWD,
@@ -702,3 +998,16 @@ struct adapter_driver xlnx_pcie_xvc_adapter_driver = {
.jtag_ops = &xlnx_pcie_xvc_jtag_ops,
.swd_ops = &xlnx_pcie_xvc_swd_ops,
};
struct adapter_driver xlnx_axi_xvc_adapter_driver = {
.name = "xlnx_axi_xvc",
.transport_ids = TRANSPORT_JTAG | TRANSPORT_SWD,
.transport_preferred_id = TRANSPORT_JTAG,
.commands = xlnx_axi_xvc_command_handlers,
.init = &xlnx_axi_xvc_init,
.quit = &xlnx_axi_xvc_quit,
.jtag_ops = &xlnx_axi_xvc_jtag_ops,
.swd_ops = &xlnx_axi_xvc_swd_ops,
};

View File

@@ -411,6 +411,7 @@ extern struct adapter_driver usbprog_adapter_driver;
extern struct adapter_driver vdebug_adapter_driver;
extern struct adapter_driver vsllink_adapter_driver;
extern struct adapter_driver xds110_adapter_driver;
extern struct adapter_driver xlnx_axi_xvc_adapter_driver;
extern struct adapter_driver xlnx_pcie_xvc_adapter_driver;
#endif /* OPENOCD_JTAG_INTERFACE_H */

View File

@@ -155,8 +155,9 @@ struct adapter_driver *adapter_drivers[] = {
#if BUILD_XDS110 == 1
&xds110_adapter_driver,
#endif
#if BUILD_XLNX_PCIE_XVC == 1
&xlnx_pcie_xvc_adapter_driver,
#if BUILD_XLNX_XVC == 1
&xlnx_pcie_xvc_adapter_driver,
&xlnx_axi_xvc_adapter_driver,
#endif
NULL,

View File

@@ -413,6 +413,12 @@ proc xlnx_pcie_xvc_config args {
eval xlnx_pcie_xvc config $args
}
lappend _telnet_autocomplete_skip xlnx_axi_xvc_config
proc xlnx_axi_xvc_config args {
echo "DEPRECATED! use 'xlnx_axi_xvc config' not 'xlnx_axi_xvc_config'"
eval xlnx_axi_xvc config $args
}
lappend _telnet_autocomplete_skip ulink_download_firmware
proc ulink_download_firmware args {
echo "DEPRECATED! use 'ulink download_firmware' not 'ulink_download_firmware'"

View File

@@ -0,0 +1,10 @@
# SPDX-License-Identifier: GPL-2.0-or-later
#
# Microchip RISC-V board
#
# https://www.microchip.com/en-us/products/microprocessors/64-bit-mpus/pic64gx
#
adapter speed 6000
source [find interface/microchip/embedded_flashpro5.cfg]
source [find target/microchip/pic64gx.cfg]

View File

@@ -7,6 +7,6 @@ source [find interface/stlink.cfg]
transport select swd
source [find target/stm32mp13x.cfg]
source [find target/st/stm32mp13x.cfg]
reset_config srst_only

View File

@@ -3,11 +3,12 @@
# board MB1272B
# http://www.st.com/en/evaluation-tools/stm32mp157a-dk1.html
# http://www.st.com/en/evaluation-tools/stm32mp157c-dk2.html
# http://www.st.com/en/evaluation-tools/stm32mp157f-dk2.html
source [find interface/stlink.cfg]
transport select swd
source [find target/stm32mp15x.cfg]
source [find target/st/stm32mp15x.cfg]
reset_config srst_only

View File

@@ -0,0 +1,12 @@
# SPDX-License-Identifier: GPL-2.0-or-later
# MB1605 with stm32mp23x
# https://www.st.com/en/evaluation-tools/stm32mp257f-dk.html
source [find interface/stlink.cfg]
transport select swd
source [find target/st/stm32mp23x.cfg]
reset_config srst_only

View File

@@ -0,0 +1,12 @@
# SPDX-License-Identifier: GPL-2.0-or-later
# MB1605
# https://www.st.com/en/evaluation-tools/stm32mp257f-dk.html
source [find interface/stlink.cfg]
transport select swd
source [find target/st/stm32mp25x.cfg]
reset_config srst_only

View File

@@ -17,6 +17,8 @@ set _file_renaming {
board/nordic_nrf51822_mkit.cfg board/nordic/nrf51822-mkit.cfg
board/nordic_nrf51_dk.cfg board/nordic/nrf51-dk.cfg
board/nordic_nrf52_dk.cfg board/nordic/nrf52-dk.cfg
board/stm32mp13x_dk.cfg board/st/stm32mp135f-dk.cfg
board/stm32mp15x_dk2.cfg board/st/stm32mp157f-dk2.cfg
target/nrf51.cfg target/nordic/nrf51.cfg
target/nrf52.cfg target/nordic/nrf52.cfg
target/nrf53.cfg target/nordic/nrf53.cfg

View File

@@ -0,0 +1,40 @@
# SPDX-License-Identifier: GPL-2.0-or-later
#
# Embedded FlashPro5
#
# https://www.microchip.com/en-us/development-tool/flashpro5
#
adapter driver ftdi
# vidpid 1514:2008 = embedded flashpro5
# vidpid 1514:200a = pic64gx
ftdi vid_pid 0x1514 0x2008 0x1514 0x200a
# That FTDI has 4 channels (channel 0 and 1 are MPSSE-capable, 2 and 3 are bitbang
ftdi channel 0
# Initial Layout - data[0..15] direction[0..15]
ftdi layout_init 0x0018 0xfdfb
# Signal Data Direction Notes
# AD0 TCK 0 1 (out) Port A TCK
# AD1 TDI 0 1 (out) Port A TDI
# AD2 TDO 0 0 (in) PORT A TDO
# AD3 TMS 1 1 (out) Port A TMS
# AD4 GPIOL0 1 1 (out) Port A TRST
# AD5 GPIOL1 0 1 (out) (unused)
# AD6 GPIOL2 0 1 (out) (unused)
# AD7 GPIOL3 0 1 (out) (unused)
# BD0 TCK 0 1 (out) FTDI_UART_B_TXD
# BD1 TDI 0 0 (in) FTDI_UART_B_RXD
# BD2 TDO 0 1 (out) (unused)
# BD3 TMS 0 1 (out) (unused)
# BD4 GPIOL0 0 1 (out) (unused)
# BD5 GPIOL1 0 1 (out) (unused)
# BD6 GPIOL2 0 1 (out) (unused)
# BD7 GPIOL2 0 1 (out) (unused)
# Signals definition
ftdi layout_signal nTRST -data 0x0010 -oe 0x0010

View File

@@ -0,0 +1,75 @@
# SPDX-License-Identifier: GPL-2.0-or-later
#
# Target: MPFS PolarFire SoC-series processors by Microchip Technologies
#
# https://www.microchip.com/en-us/products/fpgas-and-plds/system-on-chip-fpgas/polarfire-soc-fpgas
#
if { [info exists CHIPNAME] } {
set _CHIPNAME $CHIPNAME
} else {
set _CHIPNAME mpfs
}
# Process COREID variable
if { ![exists COREID] } {
set COREID -1
}
transport select jtag
# PolarFire SoC (MPFS) hart id to name lookup table
array set hart_names {
0 e51
1 u54_1
2 u54_2
3 u54_3
4 u54_4
}
# MPFS devices table
set mpfs_cpu_tap_info {
MPFS025 0x0f8531cf
MPFS095 0x0f8181cf
MPFS160 0x0f8191cf
MPFS250 0x0f81a1cf
MPFS460 0x0f81b1cf
RTPFS160 0x0f8991cf
RTPFS460 0x0f89b1cf
}
proc expected_ids {tap_list} {
set str ""
dict for {key value} $tap_list {
append str "-expected-id" " " $value " "
}
return $str
}
set irlen 8
set expected_ids [expected_ids $mpfs_cpu_tap_info]
eval jtag newtap $_CHIPNAME cpu -irlen $irlen $expected_ids -ignore-version
if {$COREID == -1} {
# Single debug connection to all HART's
set _TARGETNAME_0 $_CHIPNAME.$hart_names(0)
set _TARGETNAME_1 $_CHIPNAME.$hart_names(1)
set _TARGETNAME_2 $_CHIPNAME.$hart_names(2)
set _TARGETNAME_3 $_CHIPNAME.$hart_names(3)
set _TARGETNAME_4 $_CHIPNAME.$hart_names(4)
target create $_TARGETNAME_0 riscv -chain-position $_CHIPNAME.cpu -coreid 0 -rtos hwthread
target create $_TARGETNAME_1 riscv -chain-position $_CHIPNAME.cpu -coreid 1 -rtos hwthread
target create $_TARGETNAME_2 riscv -chain-position $_CHIPNAME.cpu -coreid 2 -rtos hwthread
target create $_TARGETNAME_3 riscv -chain-position $_CHIPNAME.cpu -coreid 3 -rtos hwthread
target create $_TARGETNAME_4 riscv -chain-position $_CHIPNAME.cpu -coreid 4 -rtos hwthread
target smp $_TARGETNAME_0 $_TARGETNAME_1 $_TARGETNAME_2 $_TARGETNAME_3 $_TARGETNAME_4
} else {
# Debug connection to a specific hart
set _TARGETNAME_0 $_CHIPNAME.$hart_names($COREID)
target create $_TARGETNAME_0 riscv -chain-position $_CHIPNAME.cpu -coreid $COREID
}
# Only TRSTn supported
reset_config trst_only

View File

@@ -0,0 +1,69 @@
# SPDX-License-Identifier: GPL-2.0-or-later
#
# Target: Pic64gx processor by Microchip Technologies
#
# https://www.microchip.com/en-us/products/microprocessors/64-bit-mpus/pic64gx
#
if { [info exists CHIPNAME] } {
set _CHIPNAME $CHIPNAME
} else {
set _CHIPNAME pic64gx
}
# Process COREID variable
if {![exists COREID]} {
set COREID -1
}
transport select jtag
# PIC64GX hart id to name lookup table
array set hart_names {
0 e51
1 u54_1
2 u54_2
3 u54_3
4 u54_4
}
# PIC64GX table
set pic64gx_tap_info {
PIC64GX1000 0x0f8531cf
}
proc expected_ids {tap_list} {
set str ""
dict for {key value} $tap_list {
append str "-expected-id" " " $value " "
}
return $str
}
set irlen 8
set expected_ids [expected_ids $pic64gx_tap_info]
eval jtag newtap $_CHIPNAME cpu -irlen $irlen $expected_ids -ignore-version
if {$COREID == -1} {
# Single debug connection to all harts
set _TARGETNAME_0 $_CHIPNAME.$hart_names(0)
set _TARGETNAME_1 $_CHIPNAME.$hart_names(1)
set _TARGETNAME_2 $_CHIPNAME.$hart_names(2)
set _TARGETNAME_3 $_CHIPNAME.$hart_names(3)
set _TARGETNAME_4 $_CHIPNAME.$hart_names(4)
target create $_TARGETNAME_0 riscv -chain-position $_CHIPNAME.cpu -coreid 0 -rtos hwthread
target create $_TARGETNAME_1 riscv -chain-position $_CHIPNAME.cpu -coreid 1 -rtos hwthread
target create $_TARGETNAME_2 riscv -chain-position $_CHIPNAME.cpu -coreid 2 -rtos hwthread
target create $_TARGETNAME_3 riscv -chain-position $_CHIPNAME.cpu -coreid 3 -rtos hwthread
target create $_TARGETNAME_4 riscv -chain-position $_CHIPNAME.cpu -coreid 4 -rtos hwthread
target smp $_TARGETNAME_0 $_TARGETNAME_1 $_TARGETNAME_2 $_TARGETNAME_3 $_TARGETNAME_4
} else {
# Debug connection to a specific hart
set _TARGETNAME_0 $_CHIPNAME.$hart_names($COREID)
target create $_TARGETNAME_0 riscv -chain-position $_CHIPNAME.cpu -coreid $COREID
}
# Only TRSTn supported
reset_config trst_only

View File

@@ -46,7 +46,7 @@ dap create $_CHIPNAME.dap -chain-position $_CHIPNAME.tap -ignore-syspwrupack
# NOTE: do not change the order of target create
target create $_CHIPNAME.ap1 mem_ap -dap $_CHIPNAME.dap -ap-num 1
target create $_CHIPNAME.axi mem_ap -dap $_CHIPNAME.dap -ap-num 0
target create $_CHIPNAME.cpu cortex_a -dap $_CHIPNAME.dap -ap-num 1 -coreid 0 -dbgbase 0xE00D0000
target create $_CHIPNAME.cpu cortex_a -dap $_CHIPNAME.dap -ap-num 1 -coreid 0 -dbgbase 0xE00D0000 -defer-examine
$_CHIPNAME.cpu cortex_a maskisr on
$_CHIPNAME.cpu cortex_a dacrfixup on
@@ -76,27 +76,59 @@ proc axi_nsecure {} {
axi_secure
proc dbgmcu_enable_debug {} {
# mmw with target selection
proc target_mmw {target reg setbits clearbits} {
set val [eval $target read_memory $reg 32 1]
set val [expr {($val & ~$clearbits) | $setbits}]
eval $target mww $reg $val
}
lappend _telnet_autocomplete_skip _enable_debug
# Uses AP1
proc _enable_debug {} {
# keep clock enabled in low-power
## catch {$::_CHIPNAME.ap1 mww 0xe0081004 0x00000004}
catch {$::_CHIPNAME.ap1 mww 0xe0081004 0x00000004}
# freeze watchdog 1 and 2 on core halted
catch {$::_CHIPNAME.ap1 mww 0xe008102c 0x00000004}
catch {$::_CHIPNAME.ap1 mww 0xe008104c 0x00000008}
}
proc toggle_cpu_dbg_claim0 {} {
# toggle CPU0 DBG_CLAIM[0]
$::_CHIPNAME.ap1 mww 0xe00d0fa0 1
$::_CHIPNAME.ap1 mww 0xe00d0fa4 1
lappend _telnet_autocomplete_skip _handshake_with_wrapper
# Uses AP1
proc _handshake_with_wrapper { halt } {
set dbgmcu_cr 0
catch {set dbgmcu_cr [eval $::_CHIPNAME.ap1 read_memory 0xe0081004 32 1]}
if {[expr {($dbgmcu_cr & 0x07) == 0x00}]} {
echo "\nWARNING: FSBL wrapper not detected. Board in dev boot mode?\n"
return
}
if { $halt } {
$::_CHIPNAME.ap1 arp_halt
$::_CHIPNAME.ap1 mww 0xe00d0300 0
target_mmw $::_CHIPNAME.ap1 0xe00d0088 0x00004000 0
}
$::_CHIPNAME.ap1 mww 0xe0081004 0x7
}
# FIXME: most of handlers below will be removed once reset framework get merged
$_CHIPNAME.ap1 configure -event reset-assert-post {
adapter assert srst
}
$_CHIPNAME.ap1 configure -event reset-deassert-pre {
adapter deassert srst deassert trst
catch {dap init}
catch {$::_CHIPNAME.dap apid 1}
$::_CHIPNAME.ap1 arp_examine
_handshake_with_wrapper $halt
_enable_debug
$::_CHIPNAME.cpu arp_examine
if { $halt } {
$::_CHIPNAME.cpu arp_halt
}
}
$_CHIPNAME.ap1 configure -event examine-end {
_enable_debug
$::_CHIPNAME.cpu arp_examine
}
$_CHIPNAME.cpu configure -event reset-deassert-pre {$::_CHIPNAME.cpu arp_examine}
$_CHIPNAME.cpu configure -event reset-deassert-post {toggle_cpu_dbg_claim0; dbgmcu_enable_debug}
$_CHIPNAME.ap1 configure -event examine-start {dap init}
$_CHIPNAME.ap1 configure -event examine-end {dbgmcu_enable_debug}

View File

@@ -18,6 +18,17 @@ if { [info exists CHIPNAME] } {
set _CHIPNAME stm32mp15x
}
# Set to 0 to prevent CPU examine. Default examine them
if { ! [info exists EN_CA7_0] } {
set EN_CA7_0 1
}
if { ! [info exists EN_CA7_1] } {
set EN_CA7_1 1
}
if { ! [info exists EN_CM4] } {
set EN_CM4 1
}
if { [info exists CPUTAPID] } {
set _CPUTAPID $CPUTAPID
} else {
@@ -42,20 +53,21 @@ if { [using_jtag] } {
dap create $_CHIPNAME.dap -chain-position $_CHIPNAME.tap -ignore-syspwrupack
# FIXME: Cortex-M code requires target accessible during reset, but this is not possible in STM32MP1
# so defer-examine it until the reset framework get merged
# NOTE: keep ap-num and dbgbase to speed-up examine after reset
# NOTE: do not change the order of target create
target create $_CHIPNAME.ap1 mem_ap -dap $_CHIPNAME.dap -ap-num 1
target create $_CHIPNAME.ap2 mem_ap -dap $_CHIPNAME.dap -ap-num 2
target create $_CHIPNAME.axi mem_ap -dap $_CHIPNAME.dap -ap-num 0
target create $_CHIPNAME.cpu0 cortex_a -dap $_CHIPNAME.dap -ap-num 1 -coreid 0 -dbgbase 0xE00D0000
target create $_CHIPNAME.cpu1 cortex_a -dap $_CHIPNAME.dap -ap-num 1 -coreid 1 -dbgbase 0xE00D2000
target create $_CHIPNAME.cpu0 cortex_a -dap $_CHIPNAME.dap -ap-num 1 -coreid 0 -dbgbase 0xE00D0000 -defer-examine
target create $_CHIPNAME.cpu1 cortex_a -dap $_CHIPNAME.dap -ap-num 1 -coreid 1 -dbgbase 0xE00D2000 -defer-examine
target create $_CHIPNAME.cm4 cortex_m -dap $_CHIPNAME.dap -ap-num 2 -defer-examine
targets $_CHIPNAME.cpu0
target smp $_CHIPNAME.cpu0 $_CHIPNAME.cpu1
$_CHIPNAME.cpu0 configure -rtos hwthread
$_CHIPNAME.cpu1 configure -rtos hwthread
$_CHIPNAME.cpu0 cortex_a maskisr on
$_CHIPNAME.cpu1 cortex_a maskisr on
$_CHIPNAME.cpu0 cortex_a dacrfixup on
@@ -96,7 +108,16 @@ proc axi_nsecure {} {
axi_secure
proc dbgmcu_enable_debug {} {
# mmw with target selection
proc target_mmw {target reg setbits clearbits} {
set val [eval $target read_memory $reg 32 1]
set val [expr {($val & ~$clearbits) | $setbits}]
eval $target mww $reg $val
}
lappend _telnet_autocomplete_skip _enable_debug
# Uses AP1
proc _enable_debug {} {
# set debug enable bits in DBGMCU_CR to get ap2 and cm4 visible
catch {$::_CHIPNAME.ap1 mww 0xe0081004 0x00000007}
# freeze watchdog 1 and 2 on cores halted
@@ -104,30 +125,97 @@ proc dbgmcu_enable_debug {} {
catch {$::_CHIPNAME.ap1 mww 0xe008104c 0x00000008}
}
proc toggle_cpu0_dbg_claim0 {} {
# toggle CPU0 DBG_CLAIM[0]
$::_CHIPNAME.ap1 mww 0xe00d0fa0 1
$::_CHIPNAME.ap1 mww 0xe00d0fa4 1
lappend _telnet_autocomplete_skip _handshake_with_wrapper
# Uses AP1
proc _handshake_with_wrapper { halt } {
set dbgmcu_cr 0
catch {set dbgmcu_cr [eval $::_CHIPNAME.ap1 read_memory 0xe0081004 32 1]}
if {[expr {($dbgmcu_cr & 0x07) == 0x00}]} {
echo "\nWARNING: FSBL wrapper not detected. Board in dev boot mode?\n"
return
}
if { $halt } {
$::_CHIPNAME.ap1 arp_halt
if { $::EN_CA7_0 } {
$::_CHIPNAME.ap1 arp_halt
$::_CHIPNAME.ap1 mww 0xe00d0300 0
target_mmw $::_CHIPNAME.ap1 0xe00d0088 0x00004000 0
}
}
$::_CHIPNAME.ap1 mww 0xe0081004 0x7
}
proc detect_cpu1 {} {
lappend _telnet_autocomplete_skip _detect_cpu1
# Uses AP1
proc _detect_cpu1 {} {
if { !$::EN_CA7_1 } {
return
}
set cpu1_prsr [$::_CHIPNAME.ap1 read_memory 0xE00D2314 32 1]
set dual_core [expr {$cpu1_prsr & 1}]
if {! $dual_core} {$::_CHIPNAME.cpu1 configure -defer-examine}
if { !$dual_core } {
set ::EN_CA7_1 0
}
}
proc rcc_enable_traceclk {} {
lappend _telnet_autocomplete_skip _rcc_enable_traceclk
proc _rcc_enable_traceclk {} {
$::_CHIPNAME.ap2 mww 0x5000080c 0x301
}
# FIXME: most of handler below will be removed once reset framework get merged
$_CHIPNAME.ap1 configure -event reset-deassert-pre {adapter deassert srst deassert trst;catch {dap init};catch {$::_CHIPNAME.dap apid 1}}
$_CHIPNAME.ap2 configure -event reset-deassert-pre {dbgmcu_enable_debug;rcc_enable_traceclk}
$_CHIPNAME.cpu0 configure -event reset-deassert-pre {$::_CHIPNAME.cpu0 arp_examine}
$_CHIPNAME.cpu1 configure -event reset-deassert-pre {$::_CHIPNAME.cpu1 arp_examine allow-defer}
$_CHIPNAME.cpu0 configure -event reset-deassert-post {toggle_cpu0_dbg_claim0}
$_CHIPNAME.cm4 configure -event reset-deassert-post {$::_CHIPNAME.cm4 arp_examine;if {[$::_CHIPNAME.ap2 curstate] == "halted"} {$::_CHIPNAME.cm4 arp_poll;$::_CHIPNAME.cm4 arp_poll;$::_CHIPNAME.cm4 arp_halt}}
$_CHIPNAME.ap1 configure -event examine-start {dap init}
$_CHIPNAME.ap2 configure -event examine-start {dbgmcu_enable_debug}
$_CHIPNAME.cpu0 configure -event examine-end {detect_cpu1}
$_CHIPNAME.ap2 configure -event examine-end {rcc_enable_traceclk;$::_CHIPNAME.cm4 arp_examine}
$_CHIPNAME.cm4 configure -event reset-assert { }
$_CHIPNAME.ap1 configure -event reset-assert-post {
adapter assert srst
}
$_CHIPNAME.ap1 configure -event reset-deassert-pre {
adapter deassert srst deassert trst
$::_CHIPNAME.ap1 arp_examine
_handshake_with_wrapper $halt
if { $::EN_CA7_0 } {
$::_CHIPNAME.cpu0 arp_examine
if { $halt } {
$::_CHIPNAME.cpu0 arp_halt
}
}
if { $::EN_CA7_1 } {
$::_CHIPNAME.cpu1 arp_examine
if { $halt } {
$::_CHIPNAME.cpu1 arp_halt
}
}
_enable_debug
}
$_CHIPNAME.ap2 configure -event reset-deassert-pre {
_rcc_enable_traceclk
if { $::EN_CM4 } {
$::_CHIPNAME.cm4 arp_examine
if { $halt } {
$::_CHIPNAME.cm4 arp_halt
}
}
}
$_CHIPNAME.ap1 configure -event examine-end {
_enable_debug
_detect_cpu1
if { $::EN_CA7_0 } {
$::_CHIPNAME.cpu0 arp_examine
}
if { $::EN_CA7_1 } {
$::_CHIPNAME.cpu1 arp_examine
}
}
$_CHIPNAME.ap2 configure -event examine-end {
_rcc_enable_traceclk
if { $::EN_CM4 } {
$::_CHIPNAME.cm4 arp_examine
}
}

View File

@@ -0,0 +1,222 @@
# SPDX-License-Identifier: GPL-2.0-or-later
# STMicroelectronics STM32MP21x
# STM32MP21x devices support both JTAG and SWD transports.
# HLA does not support multi-cores nor custom CSW nor AP other than 0
if { [using_hla] } {
echo "ERROR: HLA transport cannot work with this target."
shutdown
}
source [find target/swj-dp.tcl]
source [find mem_helper.tcl]
if { [info exists CHIPNAME] } {
set _CHIPNAME $CHIPNAME
} else {
set _CHIPNAME stm32mp21x
}
# Set to 0 to prevent CPU examine. Default examine them
if { ! [info exists EN_CA35] } {
set EN_CA35 1
}
if { ! [info exists EN_CM33] } {
set EN_CM33 1
}
set _ENDIAN little
# jtag scan chain
if { [info exists CPUTAPID] } {
set _CPUTAPID $CPUTAPID
} else {
if { [using_jtag] } {
set _CPUTAPID 0x6ba00477
} {
set _CPUTAPID 0x6ba02477
}
}
# Chip Level TAP Controller, only in jtag mode
if { [info exists CLCTAPID] } {
set _CLCTAPID $CLCTAPID
} else {
set _CLCTAPID 0x16503041
}
swj_newdap $_CHIPNAME tap -expected-id $_CPUTAPID -irlen 4 -ircapture 0x01 -irmask 0x0f
if { [using_jtag] } {
swj_newdap $_CHIPNAME.clc tap -expected-id $_CLCTAPID -irlen 5
}
dap create $_CHIPNAME.dap -chain-position $_CHIPNAME.tap
# define AXI & APB Memory Access Ports
# NOTE: do not change the order of target create
target create $_CHIPNAME.ap0 mem_ap -dap $_CHIPNAME.dap -ap-num 0
target create $_CHIPNAME.ap1 mem_ap -dap $_CHIPNAME.dap -ap-num 1
target create $_CHIPNAME.axi mem_ap -dap $_CHIPNAME.dap -ap-num 2
target create $_CHIPNAME.ap3 mem_ap -dap $_CHIPNAME.dap -ap-num 3 -defer-examine
# define the Cortex-A35
cti create $_CHIPNAME.cti.a35 -dap $_CHIPNAME.dap -ap-num 1 -baseaddr 0x80220000
target create $_CHIPNAME.a35 aarch64 -dap $_CHIPNAME.dap -ap-num 1 -dbgbase 0x80210000 \
-cti $_CHIPNAME.cti.a35 -defer-examine
# define the Cortex-M33
target create $_CHIPNAME.m33 cortex_m -dap $_CHIPNAME.dap -ap-num 3 -defer-examine
cti create $_CHIPNAME.cti.m33 -dap $_CHIPNAME.dap -ap-num 3 -baseaddr 0xe0042000
# define the system CTIs
cti create $_CHIPNAME.cti.sys0 -dap $_CHIPNAME.dap -ap-num 1 -baseaddr 0x80080000
cti create $_CHIPNAME.cti.sys1 -dap $_CHIPNAME.dap -ap-num 1 -baseaddr 0x80090000
swo create $_CHIPNAME.swo -dap $_CHIPNAME.dap -ap-num 1 -baseaddr 0x800A0000
tpiu create $_CHIPNAME.tpiu -dap $_CHIPNAME.dap -ap-num 1 -baseaddr 0x80040000
targets $_CHIPNAME.a35
reset_config srst_pulls_trst
adapter speed 5000
adapter srst pulse_width 200
# wait 1 seconds for bootrom
adapter srst delay 1000
# set CSW for AXI
$_CHIPNAME.dap apsel 2
$_CHIPNAME.dap apcsw 0x12800000
# mmw with target selection
proc target_mmw {target reg setbits clearbits} {
set val [eval $target read_memory $reg 32 1]
set val [expr {($val & ~$clearbits) | $setbits}]
eval $target mww $reg $val
}
lappend _telnet_autocomplete_skip _enable_debug
# Uses AP0 and AXI
proc _enable_debug {} {
# Enable DBGMCU clock in RC
$::_CHIPNAME.axi mww 0x44200520 0x500
# set debug enable bits in DBGMCU_CR to get ap3/cm33 visible
$::_CHIPNAME.ap0 mww 0x80001004 0x7
# Freeze watchdogs on CPU halt
$::_CHIPNAME.axi mww 0x440a003c 0x00000026
$::_CHIPNAME.axi mww 0x440a0040 0x00000038
}
lappend _telnet_autocomplete_skip _rcc_enable_traceclk
# Uses AXI
proc _rcc_enable_traceclk {} {
# set bit TRACEEN in RCC_DBGCFGR to clock TPIU
target_mmw $::_CHIPNAME.axi 0x44200520 0x200 0
}
lappend _telnet_autocomplete_skip _handshake_with_wrapper
# Uses AP0, AP1 and AP3
proc _handshake_with_wrapper { halt } {
set dbgmcu_cr 0
catch {set dbgmcu_cr [eval $::_CHIPNAME.ap0 read_memory 0x80001004 32 1]}
if {[expr {($dbgmcu_cr & 0x07) == 0x00}]} {
echo "\nWARNING: FSBL wrapper not detected. Board in dev boot mode?\n"
return
}
if { $halt } {
if { $::EN_CA35 } {
$::_CHIPNAME.ap1 arp_examine
$::_CHIPNAME.ap1 arp_halt
$::_CHIPNAME.ap1 mww 0x80210300 0
target_mmw $::_CHIPNAME.ap1 0x80210088 0x00004000 0
}
if { $::EN_CM33 } {
$::_CHIPNAME.ap3 arp_examine
$::_CHIPNAME.ap3 arp_halt
$::_CHIPNAME.ap3 mww 0xe000edf0 0xa05f0001
}
}
# alert wrapper that debugger is ready
$::_CHIPNAME.ap0 mww 0x80001004 0x07
}
lappend _telnet_autocomplete_skip _enable_dbgmcu_on_devboot
# In DEV BOOT the BootROM does not completes the sequence to enable the
# visibility of DBGMCU on AP0.
# Write a value in DBGMCU_DBG_AUTH_DEV from CID1.
# Returns 1 if DEV BOOT is detected
# Uses AP2 (AXI bus)
proc _enable_dbgmcu_on_devboot {} {
$::_CHIPNAME.axi mww 0x44230004 0
set boot_pins [expr {[$::_CHIPNAME.axi read_memory 0x44230000 32 1] & 0xf}]
if {$boot_pins != 0x3 && $boot_pins != 0xc} {
return 0
}
set rifsc_rimc_cr [$::_CHIPNAME.axi read_memory 0x42080c00 32 1]
if {$rifsc_rimc_cr != 0x00008710} {
echo "RIFSC_RIMC_CR modified, skip activation of DBGMCU"
return 1
}
# Enable DBGMCU clock in RC
$::_CHIPNAME.axi mww 0x44200520 0x500
# Change DAP (AXI) CID, write in DBGMCU, set back DAP CID
$::_CHIPNAME.axi mww 0x42080c00 0x00008110
$::_CHIPNAME.axi mww 0x440A0104 1
$::_CHIPNAME.axi mww 0x42080c00 0x00008710
return 1
}
$_CHIPNAME.m33 configure -event reset-assert { }
$_CHIPNAME.axi configure -event reset-assert-post {
adapter assert srst
}
$_CHIPNAME.axi configure -event reset-deassert-pre {
adapter deassert srst deassert trst
$::_CHIPNAME.axi arp_examine
set is_dev_boot [_enable_dbgmcu_on_devboot]
if { !$is_dev_boot } {
_handshake_with_wrapper $halt
}
_enable_debug
_rcc_enable_traceclk
if { $::EN_CA35 } {
$::_CHIPNAME.a35 arp_examine
if { $halt } {
$::_CHIPNAME.a35 arp_halt
}
}
if { $::EN_CM33 } {
$::_CHIPNAME.ap3 arp_examine
$::_CHIPNAME.m33 arp_examine
if { $halt } {
$::_CHIPNAME.ap3 arp_halt
$::_CHIPNAME.m33 arp_halt
}
}
}
$_CHIPNAME.axi configure -event examine-end {
set is_dev_boot [_enable_dbgmcu_on_devboot]
if { $is_dev_boot } {
echo "Dev boot detected"
}
_enable_debug
_rcc_enable_traceclk
if { $::EN_CA35 } {
$::_CHIPNAME.a35 arp_examine
}
if { $::EN_CM33 } {
$::_CHIPNAME.ap3 arp_examine
$::_CHIPNAME.m33 arp_examine
}
}

View File

@@ -0,0 +1,215 @@
# SPDX-License-Identifier: GPL-2.0-or-later
# STMicroelectronics STM32MP23x
# STM32MP23x devices support both JTAG and SWD transports.
# HLA does not support multi-cores nor custom CSW nor AP other than 0
if { [using_hla] } {
echo "ERROR: HLA transport cannot work with this target."
shutdown
}
source [find target/swj-dp.tcl]
source [find mem_helper.tcl]
if { [info exists CHIPNAME] } {
set _CHIPNAME $CHIPNAME
} else {
set _CHIPNAME stm32mp23x
}
# Set to 0 to prevent CPU examine. Default examine them
if { ! [info exists EN_CA35_0] } {
set EN_CA35_0 1
}
if { ! [info exists EN_CA35_1] } {
set EN_CA35_1 1
}
if { ! [info exists EN_CM33] } {
set EN_CM33 1
}
set _ENDIAN little
# jtag scan chain
if { [info exists CPUTAPID] } {
set _CPUTAPID $CPUTAPID
} else {
if { [using_jtag] } {
set _CPUTAPID 0x6ba00477
} {
set _CPUTAPID 0x6ba02477
}
}
# Chip Level TAP Controller, only in jtag mode
if { [info exists CLCTAPID] } {
set _CLCTAPID $CLCTAPID
} else {
set _CLCTAPID 0x16505041
}
swj_newdap $_CHIPNAME tap -expected-id $_CPUTAPID -irlen 4 -ircapture 0x01 -irmask 0x0f
if { [using_jtag] } {
swj_newdap $_CHIPNAME.clc tap -expected-id $_CLCTAPID -irlen 5
}
dap create $_CHIPNAME.dap -chain-position $_CHIPNAME.tap
# define AXI & APB Memory Access Ports
# NOTE: do not change the order of target create
target create $_CHIPNAME.ap0 mem_ap -dap $_CHIPNAME.dap -ap-num 0
target create $_CHIPNAME.axi mem_ap -dap $_CHIPNAME.dap -ap-num 4
target create $_CHIPNAME.ap8 mem_ap -dap $_CHIPNAME.dap -ap-num 8 -defer-examine
# define the first Cortex-A35
cti create $_CHIPNAME.cti.a35_0 -dap $_CHIPNAME.dap -ap-num 0 -baseaddr 0x80220000
target create $_CHIPNAME.a35_0 aarch64 -dap $_CHIPNAME.dap -ap-num 0 -dbgbase 0x80210000 \
-cti $_CHIPNAME.cti.a35_0 -defer-examine
# define the second Cortex-A35
cti create $_CHIPNAME.cti.a35_1 -dap $_CHIPNAME.dap -ap-num 0 -baseaddr 0x80320000
target create $_CHIPNAME.a35_1 aarch64 -dap $_CHIPNAME.dap -ap-num 0 -dbgbase 0x80310000 \
-cti $_CHIPNAME.cti.a35_1 -defer-examine
# define the Cortex-M33
target create $_CHIPNAME.m33 cortex_m -dap $_CHIPNAME.dap -ap-num 8 -defer-examine
cti create $_CHIPNAME.cti.m33 -dap $_CHIPNAME.dap -ap-num 8 -baseaddr 0xe0042000
# define the system CTIs
cti create $_CHIPNAME.cti.sys0 -dap $_CHIPNAME.dap -ap-num 0 -baseaddr 0x80090000
cti create $_CHIPNAME.cti.sys1 -dap $_CHIPNAME.dap -ap-num 0 -baseaddr 0x800a0000
swo create $_CHIPNAME.swo -dap $_CHIPNAME.dap -ap-num 0 -baseaddr 0x800b0000
tpiu create $_CHIPNAME.tpiu -dap $_CHIPNAME.dap -ap-num 0 -baseaddr 0x80050000
targets $_CHIPNAME.a35_0
target smp $_CHIPNAME.a35_0 $_CHIPNAME.a35_1
$_CHIPNAME.a35_0 configure -rtos hwthread
$_CHIPNAME.a35_1 configure -rtos hwthread
reset_config srst_gates_jtag srst_pulls_trst
adapter speed 5000
adapter srst pulse_width 200
# wait 1 seconds for bootrom
adapter srst delay 1000
# set CSW for AXI
$_CHIPNAME.dap apsel 4
$_CHIPNAME.dap apcsw 0x12800000
# mmw with target selection
proc target_mmw {target reg setbits clearbits} {
set val [eval $target read_memory $reg 32 1]
set val [expr {($val & ~$clearbits) | $setbits}]
eval $target mww $reg $val
}
lappend _telnet_autocomplete_skip _enable_debug
# Uses AP0 and AXI
proc _enable_debug {} {
# set debug enable bits in DBGMCU_CR to get ap8/cm33 visible
$::_CHIPNAME.ap0 mww 0x80010004 0x17
# Freeze watchdogs on CPU halt
$::_CHIPNAME.axi mww 0x4a010008 0x00000000
$::_CHIPNAME.axi mww 0x4a01003c 0x00000026
$::_CHIPNAME.axi mww 0x4a010040 0x00000038
$::_CHIPNAME.axi mww 0x4a010044 0x00000400
$::_CHIPNAME.axi mww 0x4a010048 0x00000400
$::_CHIPNAME.axi mww 0x4a01004c 0x00000600
}
lappend _telnet_autocomplete_skip _rcc_enable_traceclk
# Uses AXI
proc _rcc_enable_traceclk {} {
# set bit TRACEEN in RCC_DBGCFGR to clock TPIU
target_mmw $::_CHIPNAME.axi 0x44200520 0x200 0
}
lappend _telnet_autocomplete_skip _handshake_with_wrapper
# Uses AP0
proc _handshake_with_wrapper { halt } {
set dbgmcu_cr 0
catch {set dbgmcu_cr [eval $::_CHIPNAME.ap0 read_memory 0x80010004 32 1]}
if {[expr {($dbgmcu_cr & 0x07) == 0x00}]} {
echo "\nWARNING: FSBL wrapper not detected. Board in dev boot mode?\n"
return;
}
if { $halt } {
if { $::EN_CA35_0 || $::EN_CA35_1 } {
$::_CHIPNAME.ap0 arp_examine
$::_CHIPNAME.ap0 arp_halt
}
if { $::EN_CA35_0 } {
$::_CHIPNAME.ap0 mww 0x80210300 0
target_mmw $::_CHIPNAME.ap0 0x80210088 0x00004000 0
}
if { $::EN_CA35_1 } {
$::_CHIPNAME.ap0 mww 0x80310300 0
target_mmw $::_CHIPNAME.ap0 0x80310088 0x00004000 0
}
if { $::EN_CM33 } {
$::_CHIPNAME.ap8 arp_examine
$::_CHIPNAME.ap8 arp_halt
$::_CHIPNAME.ap8 mww 0xe000edf0 0xa05f0001
}
}
# alert wrapper that debugger is ready
$::_CHIPNAME.ap0 mww 0x80010004 0x17
}
$_CHIPNAME.m33 configure -event reset-assert { }
$_CHIPNAME.axi configure -event reset-assert-post {
adapter assert srst
}
$_CHIPNAME.axi configure -event reset-deassert-pre {
adapter deassert srst deassert trst
$::_CHIPNAME.ap0 arp_examine
_handshake_with_wrapper $halt
$::_CHIPNAME.axi arp_examine
_enable_debug
_rcc_enable_traceclk
if { $::EN_CA35_0 } {
$::_CHIPNAME.a35_0 arp_examine
if { $halt } {
$::_CHIPNAME.a35_0 arp_halt
}
}
if { $::EN_CA35_1 } {
$::_CHIPNAME.a35_1 arp_examine
if { $halt } {
$::_CHIPNAME.a35_1 arp_halt
}
}
if { $::EN_CM33 } {
$::_CHIPNAME.ap8 arp_examine
$::_CHIPNAME.m33 arp_examine
if { $halt } {
$::_CHIPNAME.m33 arp_halt
}
}
}
$_CHIPNAME.axi configure -event examine-end {
_enable_debug
_rcc_enable_traceclk
if { $::EN_CA35_0 } {
$::_CHIPNAME.a35_0 arp_examine
}
if { $::EN_CA35_1 } {
$::_CHIPNAME.a35_1 arp_examine
}
if { $::EN_CM33 } {
$::_CHIPNAME.ap8 arp_examine
$::_CHIPNAME.m33 arp_examine
}
}

View File

@@ -0,0 +1,247 @@
# SPDX-License-Identifier: GPL-2.0-or-later
# STMicroelectronics STM32MP25x
# STM32MP25x devices support both JTAG and SWD transports.
# HLA does not support multi-cores nor custom CSW nor AP other than 0
if { [using_hla] } {
echo "ERROR: HLA transport cannot work with this target."
shutdown
}
source [find target/swj-dp.tcl]
source [find mem_helper.tcl]
if { [info exists CHIPNAME] } {
set _CHIPNAME $CHIPNAME
} else {
set _CHIPNAME stm32mp25x
}
# Set to 0 to prevent CPU examine. Default examine them
if { ! [info exists EN_CA35_0] } {
set EN_CA35_0 1
}
if { ! [info exists EN_CA35_1] } {
set EN_CA35_1 1
}
if { ! [info exists EN_CM33] } {
set EN_CM33 1
}
if { ! [info exists EN_CM0P] } {
set EN_CM0P 1
}
set _ENDIAN little
# jtag scan chain
if { [info exists CPUTAPID] } {
set _CPUTAPID $CPUTAPID
} else {
if { [using_jtag] } {
set _CPUTAPID 0x6ba00477
} {
set _CPUTAPID 0x6ba02477
}
}
# Chip Level TAP Controller, only in jtag mode
if { [info exists CLCTAPID] } {
set _CLCTAPID $CLCTAPID
} else {
set _CLCTAPID 0x16505041
}
swj_newdap $_CHIPNAME tap -expected-id $_CPUTAPID -irlen 4 -ircapture 0x01 -irmask 0x0f
if { [using_jtag] } {
swj_newdap $_CHIPNAME.clc tap -expected-id $_CLCTAPID -irlen 5
}
dap create $_CHIPNAME.dap -chain-position $_CHIPNAME.tap
# define AXI & APB Memory Access Ports
# NOTE: do not change the order of target create
target create $_CHIPNAME.ap0 mem_ap -dap $_CHIPNAME.dap -ap-num 0
target create $_CHIPNAME.axi mem_ap -dap $_CHIPNAME.dap -ap-num 4
target create $_CHIPNAME.ap2 mem_ap -dap $_CHIPNAME.dap -ap-num 2 -defer-examine
target create $_CHIPNAME.ap8 mem_ap -dap $_CHIPNAME.dap -ap-num 8 -defer-examine
# define the first Cortex-A35
cti create $_CHIPNAME.cti.a35_0 -dap $_CHIPNAME.dap -ap-num 0 -baseaddr 0x80220000
target create $_CHIPNAME.a35_0 aarch64 -dap $_CHIPNAME.dap -ap-num 0 -dbgbase 0x80210000 \
-cti $_CHIPNAME.cti.a35_0 -defer-examine
# define the second Cortex-A35
cti create $_CHIPNAME.cti.a35_1 -dap $_CHIPNAME.dap -ap-num 0 -baseaddr 0x80320000
target create $_CHIPNAME.a35_1 aarch64 -dap $_CHIPNAME.dap -ap-num 0 -dbgbase 0x80310000 \
-cti $_CHIPNAME.cti.a35_1 -defer-examine
# define the Cortex-M33
target create $_CHIPNAME.m33 cortex_m -dap $_CHIPNAME.dap -ap-num 8 -defer-examine
cti create $_CHIPNAME.cti.m33 -dap $_CHIPNAME.dap -ap-num 8 -baseaddr 0xe0042000
# define the Cortex-M0+
target create $_CHIPNAME.m0p cortex_m -dap $_CHIPNAME.dap -ap-num 2 -defer-examine
cti create $_CHIPNAME.cti.m0p -dap $_CHIPNAME.dap -ap-num 2 -baseaddr 0xf0000000
# define the system CTIs
cti create $_CHIPNAME.cti.sys0 -dap $_CHIPNAME.dap -ap-num 0 -baseaddr 0x80090000
cti create $_CHIPNAME.cti.sys1 -dap $_CHIPNAME.dap -ap-num 0 -baseaddr 0x800a0000
swo create $_CHIPNAME.swo -dap $_CHIPNAME.dap -ap-num 0 -baseaddr 0x800b0000
tpiu create $_CHIPNAME.tpiu -dap $_CHIPNAME.dap -ap-num 0 -baseaddr 0x80050000
targets $_CHIPNAME.a35_0
target smp $_CHIPNAME.a35_0 $_CHIPNAME.a35_1
$_CHIPNAME.a35_0 configure -rtos hwthread
$_CHIPNAME.a35_1 configure -rtos hwthread
reset_config srst_gates_jtag srst_pulls_trst
adapter speed 5000
adapter srst pulse_width 200
# wait 1 seconds for bootrom
adapter srst delay 1000
# set CSW for AXI
$_CHIPNAME.dap apsel 4
$_CHIPNAME.dap apcsw 0x12800000
# mmw with target selection
proc target_mmw {target reg setbits clearbits} {
set val [eval $target read_memory $reg 32 1]
set val [expr {($val & ~$clearbits) | $setbits}]
eval $target mww $reg $val
}
lappend _telnet_autocomplete_skip _enable_ap2_cm0p
proc _enable_ap2_cm0p {} {
# set bits C3LPEN and C3EN in RCC_C3CFGR to enable AP2 and CM0+ clock
target_mmw $::_CHIPNAME.axi 0x54200490 6 0
}
lappend _telnet_autocomplete_skip _enable_debug
# Uses AP0 and AXI
proc _enable_debug {} {
# set debug enable bits in DBGMCU_CR to get ap2/cm0+ and ap8/cm33 visible
# set DBG_SWD_SEL_N bit in DBGMCU_CR to get ap2/cm0+ on main debug interface
$::_CHIPNAME.ap0 mww 0x80010004 0x17
if { $::EN_CM0P } {
_enable_ap2_cm0p
}
# Freeze watchdogs on CPU halt
$::_CHIPNAME.axi mww 0x4a010008 0x00000000
$::_CHIPNAME.axi mww 0x4a01003c 0x00000026
$::_CHIPNAME.axi mww 0x4a010040 0x00000038
$::_CHIPNAME.axi mww 0x4a010044 0x00000400
$::_CHIPNAME.axi mww 0x4a010048 0x00000400
$::_CHIPNAME.axi mww 0x4a01004c 0x00000600
}
lappend _telnet_autocomplete_skip _rcc_enable_traceclk
# Uses AXI
proc _rcc_enable_traceclk {} {
# set bit TRACEEN in RCC_DBGCFGR to clock TPIU
target_mmw $::_CHIPNAME.axi 0x44200520 0x200 0
}
lappend _telnet_autocomplete_skip _handshake_with_wrapper
# Uses AP0
proc _handshake_with_wrapper { halt } {
set dbgmcu_cr 0
catch {set dbgmcu_cr [eval $::_CHIPNAME.ap0 read_memory 0x80010004 32 1]}
if {[expr {($dbgmcu_cr & 0x07) == 0x00}]} {
echo "\nWARNING: FSBL wrapper not detected. Board in dev boot mode?\n"
return;
}
if { $halt } {
if { $::EN_CA35_0 || $::EN_CA35_1 } {
$::_CHIPNAME.ap0 arp_examine
$::_CHIPNAME.ap0 arp_halt
}
if { $::EN_CA35_0 } {
$::_CHIPNAME.ap0 mww 0x80210300 0
target_mmw $::_CHIPNAME.ap0 0x80210088 0x00004000 0
}
if { $::EN_CA35_1 } {
$::_CHIPNAME.ap0 mww 0x80310300 0
target_mmw $::_CHIPNAME.ap0 0x80310088 0x00004000 0
}
if { $::EN_CM33 } {
$::_CHIPNAME.ap8 arp_examine
$::_CHIPNAME.ap8 arp_halt
$::_CHIPNAME.ap8 mww 0xe000edf0 0xa05f0001
}
}
# alert wrapper that debugger is ready
$::_CHIPNAME.ap0 mww 0x80010004 0x17
}
$_CHIPNAME.m33 configure -event reset-assert { }
$_CHIPNAME.m0p configure -event reset-assert { }
$_CHIPNAME.axi configure -event reset-assert-post {
adapter assert srst
}
$_CHIPNAME.axi configure -event reset-deassert-pre {
adapter deassert srst deassert trst
$::_CHIPNAME.ap0 arp_examine
_handshake_with_wrapper $halt
$::_CHIPNAME.axi arp_examine
_enable_debug
_rcc_enable_traceclk
if { $::EN_CA35_0 } {
$::_CHIPNAME.a35_0 arp_examine
if { $halt } {
$::_CHIPNAME.a35_0 arp_halt
}
}
if { $::EN_CA35_1 } {
$::_CHIPNAME.a35_1 arp_examine
if { $halt } {
$::_CHIPNAME.a35_1 arp_halt
}
}
if { $::EN_CM0P } {
$::_CHIPNAME.ap2 arp_examine
$::_CHIPNAME.m0p arp_examine
}
if { $::EN_CM33 } {
$::_CHIPNAME.ap8 arp_examine
$::_CHIPNAME.m33 arp_examine
if { $halt } {
$::_CHIPNAME.m33 arp_halt
}
}
}
$_CHIPNAME.m0p configure -event examine-start {
_enable_ap2_cm0p
}
$_CHIPNAME.axi configure -event examine-end {
_enable_debug
_rcc_enable_traceclk
if { $::EN_CA35_0 } {
$::_CHIPNAME.a35_0 arp_examine
}
if { $::EN_CA35_1 } {
$::_CHIPNAME.a35_1 arp_examine
}
if { $::EN_CM33 } {
$::_CHIPNAME.ap8 arp_examine
$::_CHIPNAME.m33 arp_examine
}
if { $::EN_CM0P } {
$::_CHIPNAME.ap2 arp_examine
$::_CHIPNAME.m0p arp_examine
}
}