Merge up to a510d51a78 from upstream

Changed `.github/workflows` due to internall `jimtcl` deprecation.

Change-Id: I628922a843a7116955cd6b48c48b0cd104bcaf20
Signed-off-by: Evgeniy Naydanov <evgeniy.naydanov@syntacore.com>
This commit is contained in:
Evgeniy Naydanov 2025-01-27 14:04:41 +03:00
commit 309c25f5e2
33 changed files with 976 additions and 174 deletions

View File

@ -9,13 +9,34 @@ jobs:
env:
CFLAGS: -m32
CC: clang
PKG_CONFIG_PATH: /opt/libjim32/lib/pkgconfig
steps:
- name: Checkout Code
uses: actions/checkout@v4
- name: Install required packages (apt-get)
run: |
sudo apt-get update
sudo apt-get install clang gcc-multilib
- name: Get 32-bit JIM TCL from cache
id: cache-libjim32
uses: actions/cache@v4
with:
path: /opt/libjim32
key: libjim32
- if: ${{ steps.cache-libjim32.outputs.cache-hit != 'true' }}
name: Checkout JIM TCL
uses: actions/checkout@v4
with:
repository: msteveb/jimtcl
ref: 0.83
path: jimtcl
- if: ${{ steps.cache-libjim32.outputs.cache-hit != 'true' }}
name: Build 32-bit JIM TCL from source
run: |
cd jimtcl
./configure --prefix=/opt/libjim32 --with-ext=json --minimal --disable-ssl
make -j`nproc`
make install
- name: Checkout Code
uses: actions/checkout@v4
- run: ./bootstrap
- run: ./configure --enable-remote-bitbang --enable-jtag_vpi --disable-target64
- run: make -j`nproc`
@ -39,7 +60,7 @@ jobs:
- name: Install required packages (apt-get)
run: |
sudo apt-get update
sudo apt-get install libusb-1.0-0 libusb-1.0-0-dev
sudo apt-get install libusb-1.0-0 libusb-1.0-0-dev libjim-dev
- run: ./bootstrap
- run: ./configure --enable-remote-bitbang --enable-jtag_vpi --enable-ftdi-cjtag --prefix /tmp/${{ env.NAME }}
- run: make -j`nproc`

View File

@ -33,7 +33,7 @@ jobs:
- name: Install packages
run: |
sudo apt-get update
sudo apt-get install -y device-tree-compiler build-essential
sudo apt-get install -y device-tree-compiler build-essential libjim-dev
- name: Get revisions of dependencies
run: |

View File

@ -15,19 +15,21 @@ else
exit 1
fi
SKIP_SUBMODULE=0
WITH_SUBMODULES=0
case "$#" in
0) ;;
1) if [ "$1" = "nosubmodule" ]; then
SKIP_SUBMODULE=1
else
1) if [ "$1" = "with-submodules" ]; then
WITH_SUBMODULES=1
elif [ "$1" = "nosubmodule" ]; then
WITH_SUBMODULES=0
elif [ -n "$1" ]; then
echo "$0: Illegal argument $1" >&2
echo "USAGE: $0 [nosubmodule]" >&2
echo "USAGE: $0 [with-submodules]" >&2
exit 1
fi;;
*) echo "$0: Wrong number of command-line arguments." >&2
echo "USAGE: $0 [nosubmodule]" >&2
echo "USAGE: $0 [with-submodules]" >&2
exit 1;;
esac
@ -42,12 +44,12 @@ autoheader --warnings=all
automake --warnings=all --gnu --add-missing --copy
)
if [ "$SKIP_SUBMODULE" -ne 0 ]; then
echo "Skipping submodule setup"
else
if [ "$WITH_SUBMODULES" -ne 0 ]; then
echo "Setting up submodules"
git submodule sync
git submodule update --init
else
echo "Skipping submodule setup"
fi
if [ -x src/jtag/drivers/libjaylink/autogen.sh ]; then

View File

@ -52,9 +52,16 @@ AC_SEARCH_LIBS([openpty], [util])
AC_CHECK_HEADERS([sys/socket.h])
AC_CHECK_HEADERS([elf.h])
AC_EGREP_HEADER(Elf64_Ehdr, [elf.h], [
AC_DEFINE([HAVE_ELF64], [1], [Define to 1 if the system has the type `Elf64_Ehdr'.])
])
AC_CHECK_TYPE([Elf64_Ehdr],
AC_DEFINE([HAVE_ELF64], [1], [Define to 1 if the system has the type 'Elf64_Ehdr'.]),
[], [[#include <elf.h>]])
AC_MSG_CHECKING([for glibc])
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <features.h>]], [[int v = __GLIBC__;return 0;]])],
[have_glibc=yes], [have_glibc=no])
AC_MSG_RESULT($have_glibc)
AC_CHECK_HEADERS([fcntl.h])
AC_CHECK_HEADERS([malloc.h])
AC_CHECK_HEADERS([netdb.h])
@ -164,6 +171,9 @@ m4_define([PCIE_ADAPTERS],
m4_define([SERIAL_PORT_ADAPTERS],
[[[buspirate], [Bus Pirate], [BUS_PIRATE]]])
m4_define([LINUXSPIDEV_ADAPTER],
[[[linuxspidev], [Linux spidev driver], [LINUXSPIDEV]]])
# The word 'Adapter' in "Dummy Adapter" below must begin with a capital letter
# because there is an M4 macro called 'adapter'.
m4_define([DUMMY_ADAPTER],
@ -258,7 +268,7 @@ AC_ARG_ENABLE([malloc_logging],
AC_MSG_CHECKING([whether to enable malloc free space logging]);
AC_MSG_RESULT([$debug_malloc])
AS_IF([test "x$debug_malloc" = "xyes"], [
AS_IF([test "x$debug_malloc" = "xyes" -a "x$have_glibc" = "xyes"], [
AC_DEFINE([_DEBUG_FREE_SPACE_],[1], [Include malloc free space in logging])
])
@ -290,6 +300,7 @@ AC_ARG_ADAPTERS([
LIBFTDI_ADAPTERS,
LIBFTDI_USB1_ADAPTERS,
LIBGPIOD_ADAPTERS,
LINUXSPIDEV_ADAPTER,
SERIAL_PORT_ADAPTERS,
DUMMY_ADAPTER,
PCIE_ADAPTERS,
@ -389,8 +400,8 @@ AS_CASE([$host_os],
])
AC_ARG_ENABLE([internal-jimtcl],
AS_HELP_STRING([--disable-internal-jimtcl], [Disable building internal jimtcl]),
[use_internal_jimtcl=$enableval], [use_internal_jimtcl=yes])
AS_HELP_STRING([--enable-internal-jimtcl], [Enable building internal jimtcl (deprecated)]),
[use_internal_jimtcl=$enableval], [use_internal_jimtcl=no])
AC_ARG_ENABLE([jimtcl-maintainer],
AS_HELP_STRING([--enable-jimtcl-maintainer], [Enable maintainer mode when building internal jimtcl]),
@ -727,6 +738,7 @@ PROCESS_ADAPTERS([LIBJAYLINK_ADAPTERS], ["x$use_internal_libjaylink" = "xyes" -o
PROCESS_ADAPTERS([PCIE_ADAPTERS], ["x$is_linux" = "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"], [Linux spidev])
PROCESS_ADAPTERS([DUMMY_ADAPTER], [true], [unused])
AS_IF([test "x$enable_linuxgpiod" != "xno"], [
@ -867,6 +879,10 @@ AS_IF([test "x$enable_jlink" != "xno"], [
]])
)
AS_IF([test "x$use_internal_jimtcl" = "xyes"], [
AC_MSG_WARN([Using the internal jimtcl is deprecated and will not be possible in the future.])
])
echo
echo
echo OpenOCD configuration summary
@ -876,6 +892,7 @@ m4_foreach([adapter], [USB1_ADAPTERS,
LIBFTDI_USB1_ADAPTERS,
LIBGPIOD_ADAPTERS,
LIBJAYLINK_ADAPTERS, PCIE_ADAPTERS, SERIAL_PORT_ADAPTERS,
LINUXSPIDEV_ADAPTER,
DUMMY_ADAPTER,
OPTIONAL_LIBRARIES,
COVERAGE],

View File

@ -614,6 +614,9 @@ 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.
@item @b{linuxspidev}
@* A SPI based SWD driver using Linux SPI devices.
@item @b{linuxgpiod}
@* A bitbang JTAG driver using Linux GPIO through library libgpiod.
@ -3430,6 +3433,70 @@ See @file{interface/beaglebone-swd-native.cfg} for a sample configuration file.
@end deffn
@deffn {Interface Driver} {linuxspidev}
Linux provides userspace access to SPI through spidev. Full duplex SPI
transactions are used to simultaneously read and write to/from the target to
emulate the SWD transport.
@deffn {Config Command} {spidev path} path
Specifies the path to the spidev device.
@end deffn
@deffn {Config Command} {spidev mode} value
Set the mode of the spi port with optional bit flags (default=3).
See /usr/include/linux/spi/spidev.h for all of the SPI mode options.
@end deffn
@deffn {Config Command} {spidev queue_entries} value
Set the maximum number of queued transactions per spi exchange (default=64).
More queued transactions may offer greater performance when the target doesn't
need to wait. On the contrary higher numbers will reduce performance when the
target requests a wait as all queued transactions will need to be exchanged
before spidev can see the wait request.
@end deffn
See @file{tcl/interface/spidev_example.cfg} for a sample configuration file.
Electrical connections:
@example
+--------------+ +--------------+
| | 1K | |
| MOSI|---/\/\/\---+ | |
| Host | | | Target |
| MISO|------------+---|SWDIO |
| | | |
| SCK|----------------|SWDCLK |
| | | |
+--------------+ +--------------+
@end example
The 1K resistor works well with most MCUs up to 3 MHz. A lower resistance
could be used to achieve higher speeds granted that the target SWDIO pin has
enough drive strength to pull the signal high while being pulled low by this
resistor.
If you are having trouble here are some tips:
@itemize @bullet
@item @b{Make sure MISO and MOSI are tied together with a 1K resistor.}
MISO should be attached to the target.
@item @b{Make sure that your host and target are using the same I/O voltage}
(for example both are using 3.3 volts).
@item @b{Your host's SPI port may not idle low.}
This will lead to an additional clock edge being sent to the target, causing
the host and target being 1 clock off from each other. Try setting
SPI_MOSI_IDLE_LOW in spi_mode. Try using a different spi_mode (0 - 3).
@item @b{Your target may pull SWDIO and/or SWDCLK high.}
This will create an extra edge when the host releases control of the SPI port
at the end of a transaction. You'll need to confirm this with a scope or meter.
Try installing 10K resistors on SWDIO and SWDCLK to ground to stop this.
@end itemize
@end deffn
@deffn {Interface Driver} {linuxgpiod}
Linux provides userspace access to GPIO through libgpiod since Linux kernel

View File

@ -751,9 +751,9 @@ static int fespi_probe(struct flash_bank *bank)
target_device->name, bank->base);
} else {
LOG_DEBUG("Assuming FESPI as specified at address " TARGET_ADDR_FMT
" with ctrl at " TARGET_ADDR_FMT, fespi_info->ctrl_base,
bank->base);
LOG_DEBUG("Assuming FESPI as specified at address " TARGET_ADDR_FMT
" with ctrl at " TARGET_ADDR_FMT, fespi_info->ctrl_base,
bank->base);
}
/* read and decode flash ID; returns in SW mode */

View File

@ -1489,7 +1489,22 @@ static int kinetis_fill_fcf(struct flash_bank *bank, uint8_t *fcf)
kinetis_auto_probe(bank_iter);
assert(bank_iter->prot_blocks);
if (bank_iter->num_prot_blocks == 0) {
if (k_bank->flash_class == FC_PFLASH) {
LOG_ERROR("BUG: PFLASH bank %u has no protection blocks",
bank_idx);
} else {
LOG_DEBUG("skipping FLEX_NVM bank %u with no prot blocks (EE bkp only)",
bank_idx);
}
continue;
}
if (!bank_iter->prot_blocks) {
LOG_ERROR("BUG: bank %u has NULL protection blocks array",
bank_idx);
continue;
}
if (k_bank->flash_class == FC_PFLASH) {
for (unsigned int i = 0; i < bank_iter->num_prot_blocks; i++) {

View File

@ -1005,7 +1005,7 @@ static int kinetis_ke_write(struct flash_bank *bank, const uint8_t *buffer,
result = kinetis_ke_stop_watchdog(bank->target);
if (result != ERROR_OK)
return result;
return result;
result = kinetis_ke_prepare_flash(bank);
if (result != ERROR_OK)

View File

@ -311,7 +311,7 @@ static int niietcm4_uflash_page_erase(struct flash_bank *bank, int page_num, int
/* status check */
retval = niietcm4_uopstatus_check(bank);
if (retval != ERROR_OK)
return retval;
return retval;
return retval;
}
@ -394,7 +394,7 @@ COMMAND_HANDLER(niietcm4_handle_uflash_read_byte_command)
uint32_t uflash_data;
if (strcmp("info", CMD_ARGV[0]) == 0)
uflash_cmd = UFMC_MAGIC_KEY | UFMC_READ_IFB;
uflash_cmd = UFMC_MAGIC_KEY | UFMC_READ_IFB;
else if (strcmp("main", CMD_ARGV[0]) == 0)
uflash_cmd = UFMC_MAGIC_KEY | UFMC_READ;
else
@ -539,7 +539,7 @@ COMMAND_HANDLER(niietcm4_handle_uflash_erase_command)
int mem_type;
if (strcmp("info", CMD_ARGV[0]) == 0)
mem_type = 1;
mem_type = 1;
else if (strcmp("main", CMD_ARGV[0]) == 0)
mem_type = 0;
else

View File

@ -384,15 +384,15 @@ static int psoc4_get_silicon_id(struct flash_bank *bank, uint32_t *silicon_id, u
* bit 7..0 family ID (lowest 8 bits)
*/
if (silicon_id)
*silicon_id = ((part0 & 0x0000ffff) << 16)
| ((part0 & 0x00ff0000) >> 8)
| (part1 & 0x000000ff);
*silicon_id = ((part0 & 0x0000ffff) << 16)
| ((part0 & 0x00ff0000) >> 8)
| (part1 & 0x000000ff);
if (family_id)
*family_id = part1 & 0x0fff;
*family_id = part1 & 0x0fff;
if (protection)
*protection = (part1 >> 12) & 0x0f;
*protection = (part1 >> 12) & 0x0f;
return ERROR_OK;
}

View File

@ -30,6 +30,18 @@
#else
#error "malloc.h is required to use --enable-malloc-logging"
#endif
#ifdef __GLIBC__
#if __GLIBC_PREREQ(2, 33)
#define FORDBLKS_FORMAT " %zu"
#else
/* glibc older than 2.33 (2021-02-01) use mallinfo(). Overwrite it */
#define mallinfo2 mallinfo
#define FORDBLKS_FORMAT " %d"
#endif
#else
#error "GNU glibc is required to use --enable-malloc-logging"
#endif
#endif
int debug_level = LOG_LVL_INFO;
@ -105,12 +117,11 @@ static void log_puts(enum log_levels level,
/* print with count and time information */
int64_t t = timeval_ms() - start;
#ifdef _DEBUG_FREE_SPACE_
struct mallinfo info;
info = mallinfo();
struct mallinfo2 info = mallinfo2();
#endif
fprintf(log_output, "%s%d %" PRId64 " %s:%d %s()"
#ifdef _DEBUG_FREE_SPACE_
" %d"
FORDBLKS_FORMAT
#endif
": %s", log_strings[level + 1], count, t, file, line, function,
#ifdef _DEBUG_FREE_SPACE_
@ -272,10 +283,10 @@ void log_init(void)
if (debug_env) {
int value;
int retval = parse_int(debug_env, &value);
if (retval == ERROR_OK &&
debug_level >= LOG_LVL_SILENT &&
debug_level <= LOG_LVL_DEBUG_IO)
debug_level = value;
if (retval == ERROR_OK
&& debug_level >= LOG_LVL_SILENT
&& debug_level <= LOG_LVL_DEBUG_IO)
debug_level = value;
}
if (!log_output)

View File

@ -303,12 +303,14 @@ int parse_cmdline_args(struct command_context *cmd_ctx, int argc, char *argv[])
break;
}
case 'l': /* --log_output | -l */
if (optarg)
command_run_linef(cmd_ctx, "log_output %s", optarg);
{
int retval = command_run_linef(cmd_ctx, "log_output %s", optarg);
if (retval != ERROR_OK)
return retval;
break;
}
case 'c': /* --command | -c */
if (optarg)
add_config_command(optarg);
add_config_command(optarg);
break;
default: /* '?' */
/* getopt will emit an error message, all we have to do is bail. */

View File

@ -176,6 +176,9 @@ endif
if SYSFSGPIO
DRIVERFILES += %D%/sysfsgpio.c
endif
if LINUXSPIDEV
DRIVERFILES += %D%/linuxspidev.c
endif
if XLNX_PCIE_XVC
DRIVERFILES += %D%/xlnx-pcie-xvc.c
endif

View File

@ -0,0 +1,622 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/* Copyright (C) 2020 by Lup Yuen Lee <luppy@appkaki.com>
* Copyright (C) 2024 by Richard Pasek <rpasek@google.com>
*/
/**
* @file
* Implementation of SWD protocol with a Linux SPI device.
*/
/* Uncomment to log SPI exchanges (very verbose, slows things down a lot)
*
* A quick note on interpreting SPI exchange messages:
*
* This implementation works by performing SPI exchanges with MOSI and MISO
* tied together with a 1K resistor. This combined signal becomes SWDIO.
*
* Since we are performing SPI exchanges, (reading and writing at the same
* time) this means when the target isn't driving SWDIO, what is written by
* the host should also be read by the host.
*
* On SWD writes:
* The TX and RX data should match except for the ACK bits from the target
* swd write reg exchange: len=6
* tx_buf=C5 02 40 00 02 2C
* rx_buf=C5 42 40 00 02 2C
* ^
* |
* ACK from target
*
* On SWD reads:
* Only the command byte should match
* swd read reg exchange: len=6
* tx_buf=B1 00 00 00 00 00
* rx_buf=B1 40 20 00 00 F8
* ^^
* ||
* Command packet from host
*
*/
// #define LOG_SPI_EXCHANGE
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <stdint.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <linux/spi/spidev.h>
#include <jtag/adapter.h>
#include <jtag/swd.h>
#include <jtag/interface.h>
#include <jtag/commands.h>
// Number of bits per SPI exchange
#define SPI_BITS 8
// Time in uS after the last bit of transfer before deselecting the device
#define SPI_DESELECT_DELAY 0
// Maximum number of SWD transactions to queue together in a SPI exchange
#define MAX_QUEUE_ENTRIES 64
#define CMD_BITS 8
#define TURN_BITS 1
#define ACK_BITS 3
#define DATA_BITS 32
#define PARITY_BITS 1
#define SWD_WR_BITS (CMD_BITS + TURN_BITS + ACK_BITS + TURN_BITS + DATA_BITS + PARITY_BITS)
#define SWD_RD_BITS (CMD_BITS + TURN_BITS + ACK_BITS + DATA_BITS + PARITY_BITS + TURN_BITS)
#define SWD_OP_BITS (MAX(SWD_WR_BITS, SWD_RD_BITS))
#define SWD_OP_BYTES (DIV_ROUND_UP(SWD_OP_BITS, SPI_BITS))
#define AP_DELAY_CLOCKS 8
#define AP_DELAY_BYTES (DIV_ROUND_UP(AP_DELAY_CLOCKS, SPI_BITS))
#define END_IDLE_CLOCKS 8
#define END_IDLE_BYTES (DIV_ROUND_UP(END_IDLE_CLOCKS, SPI_BITS))
// File descriptor for SPI device
static int spi_fd = -1;
// SPI Configuration
static char *spi_path;
static uint32_t spi_mode = SPI_MODE_3; // Note: SPI in LSB mode is not often supported. We'll flip LSB to MSB ourselves.
static uint32_t spi_speed;
struct queue_info {
unsigned int buf_idx;
uint32_t *rx_ptr;
};
static int queue_retval;
static unsigned int max_queue_entries;
static unsigned int queue_fill;
static unsigned int queue_buf_fill;
static unsigned int queue_buf_size;
static struct queue_info *queue_infos;
static uint8_t *queue_tx_buf;
static uint8_t *queue_rx_buf;
static uint8_t *tx_flip_buf;
static int spidev_swd_switch_seq(enum swd_special_seq seq);
static void spidev_swd_write_reg(uint8_t cmd, uint32_t value, uint32_t ap_delay_clk);
static void spi_exchange(const uint8_t *tx_data, uint8_t *rx_data, unsigned int len)
{
#ifdef LOG_SPI_EXCHANGE
LOG_OUTPUT("exchange: len=%u\n", len);
#endif // LOG_SPI_EXCHANGE
if (len == 0) {
LOG_DEBUG("exchange with no length");
return;
}
if (!tx_data && !rx_data) {
LOG_DEBUG("exchange with no valid tx or rx pointers");
return;
}
if (len > queue_buf_size) {
LOG_ERROR("exchange too large len=%u ", len);
return;
}
if (tx_data) {
// Reverse LSB to MSB
for (unsigned int i = 0; i < len; i++)
tx_flip_buf[i] = flip_u32(tx_data[i], 8);
#ifdef LOG_SPI_EXCHANGE
if (len != 0) {
LOG_OUTPUT(" tx_buf=");
for (unsigned int i = 0; i < len; i++)
LOG_OUTPUT("%.2" PRIx8 " ", tx_flip_buf[i]);
}
LOG_OUTPUT("\n");
#endif // LOG_SPI_EXCHANGE
}
// Transmit the MSB buffer to SPI device.
struct spi_ioc_transfer tr = {
/* The following must be cast to unsigned long to compile correctly on
* 32 and 64 bit machines (as is done in the spidev examples in Linux
* kernel code in tools/spi/).
*/
.tx_buf = (unsigned long)(tx_data ? tx_flip_buf : NULL),
.rx_buf = (unsigned long)rx_data,
.len = len,
.delay_usecs = SPI_DESELECT_DELAY,
.speed_hz = spi_speed,
.bits_per_word = SPI_BITS,
};
int ret = ioctl(spi_fd, SPI_IOC_MESSAGE(1), &tr);
if (ret < 1) {
LOG_ERROR("exchange failed");
return;
}
if (rx_data) {
#ifdef LOG_SPI_EXCHANGE
if (len != 0) {
LOG_OUTPUT(" rx_buf=");
for (unsigned int i = 0; i < len; i++)
LOG_OUTPUT("%.2" PRIx8 " ", rx_data[i]);
}
LOG_OUTPUT("\n");
#endif // LOG_SPI_EXCHANGE
// Reverse MSB to LSB
for (unsigned int i = 0; i < len; i++)
rx_data[i] = flip_u32(rx_data[i], 8);
}
}
static int spidev_speed(int speed)
{
uint32_t tmp_speed = speed;
int ret = ioctl(spi_fd, SPI_IOC_WR_MAX_SPEED_HZ, &tmp_speed);
if (ret == -1) {
LOG_ERROR("Failed to set SPI %d speed", speed);
return ERROR_FAIL;
}
spi_speed = speed;
return ERROR_OK;
}
static int spidev_speed_div(int speed, int *khz)
{
*khz = speed / 1000;
return ERROR_OK;
}
static int spidev_khz(int khz, int *jtag_speed)
{
if (khz == 0) {
LOG_DEBUG("RCLK not supported");
return ERROR_FAIL;
}
*jtag_speed = khz * 1000;
return ERROR_OK;
}
static void spidev_free_queue(void)
{
max_queue_entries = 0;
queue_buf_size = 0;
free(queue_infos);
queue_infos = NULL;
free(queue_tx_buf);
queue_tx_buf = NULL;
free(queue_rx_buf);
queue_rx_buf = NULL;
free(tx_flip_buf);
tx_flip_buf = NULL;
}
static int spidev_alloc_queue(unsigned int new_queue_entries)
{
if (queue_fill || queue_buf_fill) {
LOG_ERROR("Can't realloc allocate queue when queue is in use");
return ERROR_FAIL;
}
unsigned int new_queue_buf_size =
(new_queue_entries * (SWD_OP_BYTES + AP_DELAY_BYTES)) + END_IDLE_BYTES;
queue_infos = realloc(queue_infos, sizeof(struct queue_info) * new_queue_entries);
if (!queue_infos)
goto realloc_fail;
queue_tx_buf = realloc(queue_tx_buf, new_queue_buf_size);
if (!queue_tx_buf)
goto realloc_fail;
queue_rx_buf = realloc(queue_rx_buf, new_queue_buf_size);
if (!queue_rx_buf)
goto realloc_fail;
tx_flip_buf = realloc(tx_flip_buf, new_queue_buf_size);
if (!tx_flip_buf)
goto realloc_fail;
max_queue_entries = new_queue_entries;
queue_buf_size = new_queue_buf_size;
LOG_DEBUG("Set queue entries to %u (buffers %u bytes)", max_queue_entries, queue_buf_size);
return ERROR_OK;
realloc_fail:
spidev_free_queue();
LOG_ERROR("Couldn't allocate queue. Out of memory.");
return ERROR_FAIL;
}
static int spidev_init(void)
{
LOG_INFO("SPI SWD driver");
if (spi_fd >= 0)
return ERROR_OK;
if (!spi_path) {
LOG_ERROR("Path to spidev not set");
return ERROR_JTAG_INIT_FAILED;
}
// Open SPI device.
spi_fd = open(spi_path, O_RDWR);
if (spi_fd < 0) {
LOG_ERROR("Failed to open SPI port at %s", spi_path);
return ERROR_JTAG_INIT_FAILED;
}
// Set SPI mode.
int ret = ioctl(spi_fd, SPI_IOC_WR_MODE32, &spi_mode);
if (ret == -1) {
LOG_ERROR("Failed to set SPI mode 0x%" PRIx32, spi_mode);
return ERROR_JTAG_INIT_FAILED;
}
// Set SPI bits per word.
uint32_t spi_bits = SPI_BITS;
ret = ioctl(spi_fd, SPI_IOC_WR_BITS_PER_WORD, &spi_bits);
if (ret == -1) {
LOG_ERROR("Failed to set SPI %" PRIu8 " bits per transfer", spi_bits);
return ERROR_JTAG_INIT_FAILED;
}
LOG_INFO("Opened SPI device at %s in mode 0x%" PRIx32 " with %" PRIu8 " bits ",
spi_path, spi_mode, spi_bits);
// Set SPI read and write max speed.
int speed;
ret = adapter_get_speed(&speed);
if (ret != ERROR_OK) {
LOG_ERROR("Failed to get adapter speed");
return ERROR_JTAG_INIT_FAILED;
}
ret = spidev_speed(speed);
if (ret != ERROR_OK)
return ERROR_JTAG_INIT_FAILED;
if (max_queue_entries == 0) {
ret = spidev_alloc_queue(MAX_QUEUE_ENTRIES);
if (ret != ERROR_OK)
return ERROR_JTAG_INIT_FAILED;
}
return ERROR_OK;
}
static int spidev_quit(void)
{
spidev_free_queue();
if (spi_fd < 0)
return ERROR_OK;
close(spi_fd);
spi_fd = -1;
return ERROR_OK;
}
static int spidev_swd_init(void)
{
LOG_DEBUG("spidev_swd_init");
return ERROR_OK;
}
static int spidev_swd_execute_queue(unsigned int end_idle_bytes)
{
LOG_DEBUG_IO("Executing %u queued transactions", queue_fill);
if (queue_retval != ERROR_OK) {
LOG_DEBUG_IO("Skipping due to previous errors: %d", queue_retval);
goto skip;
}
/* A transaction must be followed by another transaction or at least 8 idle
* cycles to ensure that data is clocked through the AP. Since the tx
* buffer is zeroed after each queue run, every byte added to the buffer
* fill will add on an additional 8 idle cycles.
*/
queue_buf_fill += end_idle_bytes;
spi_exchange(queue_tx_buf, queue_rx_buf, queue_buf_fill);
for (unsigned int queue_idx = 0; queue_idx < queue_fill; queue_idx++) {
unsigned int buf_idx = queue_infos[queue_idx].buf_idx;
uint8_t *tx_ptr = &queue_tx_buf[buf_idx];
uint8_t *rx_ptr = &queue_rx_buf[buf_idx];
uint8_t cmd = buf_get_u32(tx_ptr, 0, CMD_BITS);
bool read = cmd & SWD_CMD_RNW ? true : false;
int ack = buf_get_u32(rx_ptr, CMD_BITS + TURN_BITS, ACK_BITS);
uint32_t data = read ?
buf_get_u32(rx_ptr, CMD_BITS + TURN_BITS + ACK_BITS, DATA_BITS) :
buf_get_u32(tx_ptr, CMD_BITS + TURN_BITS + ACK_BITS + TURN_BITS, DATA_BITS);
// Devices do not reply to DP_TARGETSEL write cmd, ignore received ack
bool check_ack = swd_cmd_returns_ack(cmd);
LOG_CUSTOM_LEVEL((check_ack && ack != SWD_ACK_OK) ? LOG_LVL_DEBUG : LOG_LVL_DEBUG_IO,
"%s%s %s %s reg %X = %08" PRIx32,
check_ack ? "" : "ack ignored ",
ack == SWD_ACK_OK ? "OK" :
ack == SWD_ACK_WAIT ? "WAIT" :
ack == SWD_ACK_FAULT ? "FAULT" : "JUNK",
cmd & SWD_CMD_APNDP ? "AP" : "DP",
read ? "read" : "write",
(cmd & SWD_CMD_A32) >> 1,
data);
if (ack != SWD_ACK_OK && check_ack) {
queue_retval = swd_ack_to_error_code(ack);
goto skip;
} else if (read) {
int parity = buf_get_u32(rx_ptr, CMD_BITS + TURN_BITS + ACK_BITS + DATA_BITS, PARITY_BITS);
if (parity != parity_u32(data)) {
LOG_ERROR("SWD Read data parity mismatch");
queue_retval = ERROR_FAIL;
goto skip;
}
if (queue_infos[queue_idx].rx_ptr)
*queue_infos[queue_idx].rx_ptr = data;
}
}
skip:
// Clear everything in the queue
queue_fill = 0;
queue_buf_fill = 0;
memset(queue_infos, 0, sizeof(queue_infos[0]) * max_queue_entries);
memset(queue_tx_buf, 0, queue_buf_size);
memset(queue_rx_buf, 0, queue_buf_size);
int retval = queue_retval;
queue_retval = ERROR_OK;
return retval;
}
static int spidev_swd_run_queue(void)
{
/* Since we are unsure if another SWD transaction will follow the
* transactions we are just about to execute, we need to add on 8 idle
* cycles.
*/
return spidev_swd_execute_queue(END_IDLE_BYTES);
}
static void spidev_swd_queue_cmd(uint8_t cmd, uint32_t *dst, uint32_t data, uint32_t ap_delay_clk)
{
unsigned int swd_op_bytes = DIV_ROUND_UP(SWD_OP_BITS + ap_delay_clk, SPI_BITS);
if (queue_fill >= max_queue_entries ||
queue_buf_fill + swd_op_bytes + END_IDLE_BYTES > queue_buf_size) {
/* Not enough room in the queue. Run the queue. No idle bytes are
* needed because we are going to execute transactions right after
* the queue is emptied.
*/
queue_retval = spidev_swd_execute_queue(0);
}
if (queue_retval != ERROR_OK)
return;
uint8_t *tx_ptr = &queue_tx_buf[queue_buf_fill];
cmd |= SWD_CMD_START | SWD_CMD_PARK;
buf_set_u32(tx_ptr, 0, CMD_BITS, cmd);
if (cmd & SWD_CMD_RNW) {
// Queue a read transaction
queue_infos[queue_fill].rx_ptr = dst;
} else {
// Queue a write transaction
buf_set_u32(tx_ptr,
CMD_BITS + TURN_BITS + ACK_BITS + TURN_BITS, DATA_BITS, data);
buf_set_u32(tx_ptr,
CMD_BITS + TURN_BITS + ACK_BITS + TURN_BITS + DATA_BITS, PARITY_BITS, parity_u32(data));
}
queue_infos[queue_fill].buf_idx = queue_buf_fill;
/* Add idle cycles after AP accesses to avoid WAIT. Buffer is already
* zeroed so we just need to advance the pointer to add idle cycles.
*/
queue_buf_fill += swd_op_bytes;
queue_fill++;
}
static void spidev_swd_read_reg(uint8_t cmd, uint32_t *value, uint32_t ap_delay_clk)
{
assert(cmd & SWD_CMD_RNW);
spidev_swd_queue_cmd(cmd, value, 0, ap_delay_clk);
}
static void spidev_swd_write_reg(uint8_t cmd, uint32_t value, uint32_t ap_delay_clk)
{
assert(!(cmd & SWD_CMD_RNW));
spidev_swd_queue_cmd(cmd, NULL, value, ap_delay_clk);
}
static int spidev_swd_switch_seq(enum swd_special_seq seq)
{
switch (seq) {
case LINE_RESET:
LOG_DEBUG_IO("SWD line reset");
spi_exchange(swd_seq_line_reset, NULL, swd_seq_line_reset_len / SPI_BITS);
break;
case JTAG_TO_SWD:
LOG_DEBUG("JTAG-to-SWD");
spi_exchange(swd_seq_jtag_to_swd, NULL, swd_seq_jtag_to_swd_len / SPI_BITS);
break;
case JTAG_TO_DORMANT:
LOG_DEBUG("JTAG-to-DORMANT");
spi_exchange(swd_seq_jtag_to_dormant, NULL, swd_seq_jtag_to_dormant_len / SPI_BITS);
break;
case SWD_TO_JTAG:
LOG_DEBUG("SWD-to-JTAG");
spi_exchange(swd_seq_swd_to_jtag, NULL, swd_seq_swd_to_jtag_len / SPI_BITS);
break;
case SWD_TO_DORMANT:
LOG_DEBUG("SWD-to-DORMANT");
spi_exchange(swd_seq_swd_to_dormant, NULL, swd_seq_swd_to_dormant_len / SPI_BITS);
break;
case DORMANT_TO_SWD:
LOG_DEBUG("DORMANT-to-SWD");
spi_exchange(swd_seq_dormant_to_swd, NULL, swd_seq_dormant_to_swd_len / SPI_BITS);
break;
case DORMANT_TO_JTAG:
LOG_DEBUG("DORMANT-to-JTAG");
spi_exchange(swd_seq_dormant_to_jtag, NULL, swd_seq_dormant_to_jtag_len / SPI_BITS);
break;
default:
LOG_ERROR("Sequence %d not supported", seq);
return ERROR_FAIL;
}
return ERROR_OK;
}
COMMAND_HANDLER(spidev_handle_path_command)
{
if (CMD_ARGC != 1)
return ERROR_COMMAND_SYNTAX_ERROR;
free(spi_path);
spi_path = strdup(CMD_ARGV[0]);
if (!spi_path) {
LOG_ERROR("Out of memory");
return ERROR_FAIL;
}
return ERROR_OK;
}
COMMAND_HANDLER(spidev_handle_mode_command)
{
if (CMD_ARGC != 1)
return ERROR_COMMAND_SYNTAX_ERROR;
COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], spi_mode);
return ERROR_OK;
}
COMMAND_HANDLER(spidev_handle_queue_entries_command)
{
uint32_t new_queue_entries;
if (CMD_ARGC != 1)
return ERROR_COMMAND_SYNTAX_ERROR;
COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], new_queue_entries);
return spidev_alloc_queue(new_queue_entries);
}
const struct swd_driver spidev_swd = {
.init = spidev_swd_init,
.switch_seq = spidev_swd_switch_seq,
.read_reg = spidev_swd_read_reg,
.write_reg = spidev_swd_write_reg,
.run = spidev_swd_run_queue,
};
static const struct command_registration spidev_subcommand_handlers[] = {
{
.name = "path",
.handler = &spidev_handle_path_command,
.mode = COMMAND_CONFIG,
.help = "set the path to the spidev device",
.usage = "path_to_spidev",
},
{
.name = "mode",
.handler = &spidev_handle_mode_command,
.mode = COMMAND_CONFIG,
.help = "set the mode of the spi port with optional bit flags (default=3)",
.usage = "mode",
},
{
.name = "queue_entries",
.handler = &spidev_handle_queue_entries_command,
.mode = COMMAND_CONFIG,
.help = "set the queue entry size (default=64)",
.usage = "queue_entries",
},
COMMAND_REGISTRATION_DONE
};
static const struct command_registration spidev_command_handlers[] = {
{
.name = "spidev",
.mode = COMMAND_ANY,
.help = "perform spidev management",
.chain = spidev_subcommand_handlers,
.usage = "",
},
COMMAND_REGISTRATION_DONE
};
// Only SWD transport supported
static const char *const spidev_transports[] = { "swd", NULL };
struct adapter_driver linuxspidev_adapter_driver = {
.name = "linuxspidev",
.transports = spidev_transports,
.commands = spidev_command_handlers,
.init = spidev_init,
.quit = spidev_quit,
.speed = spidev_speed,
.khz = spidev_khz,
.speed_div = spidev_speed_div,
.swd_ops = &spidev_swd,
};

View File

@ -252,7 +252,7 @@ static int vdebug_socket_open(char *server_addr, uint32_t port)
#ifdef _WIN32
hsock = socket(AF_INET, SOCK_STREAM, IPPROTO_IP);
if (hsock == INVALID_SOCKET)
if (hsock < 0)
rc = vdebug_socket_error();
#elif defined __CYGWIN__
/* SO_RCVLOWAT unsupported on CYGWIN */

View File

@ -386,6 +386,7 @@ extern struct adapter_driver jtag_dpi_adapter_driver;
extern struct adapter_driver jtag_vpi_adapter_driver;
extern struct adapter_driver kitprog_adapter_driver;
extern struct adapter_driver linuxgpiod_adapter_driver;
extern struct adapter_driver linuxspidev_adapter_driver;
extern struct adapter_driver opendous_adapter_driver;
extern struct adapter_driver openjtag_adapter_driver;
extern struct adapter_driver osbdm_adapter_driver;

View File

@ -123,6 +123,9 @@ struct adapter_driver *adapter_drivers[] = {
#if BUILD_LINUXGPIOD == 1
&linuxgpiod_adapter_driver,
#endif
#if BUILD_LINUXSPIDEV == 1
&linuxspidev_adapter_driver,
#endif
#if BUILD_XLNX_PCIE_XVC == 1
&xlnx_pcie_xvc_adapter_driver,
#endif

View File

@ -161,9 +161,8 @@ static int hwthread_update_threads(struct rtos *rtos)
if (curr->debug_reason == DBG_REASON_SINGLESTEP) {
current_reason = curr->debug_reason;
current_thread = tid;
} else
/* multiple breakpoints, prefer gdbs' threadid */
if (curr->debug_reason == DBG_REASON_BREAKPOINT) {
} else if (curr->debug_reason == DBG_REASON_BREAKPOINT) {
/* multiple breakpoints, prefer gdbs' threadid */
if (tid == rtos->current_threadid)
current_thread = tid;
}
@ -183,8 +182,7 @@ static int hwthread_update_threads(struct rtos *rtos)
curr->debug_reason == DBG_REASON_BREAKPOINT) {
current_reason = curr->debug_reason;
current_thread = tid;
} else
if (curr->debug_reason == DBG_REASON_DBGRQ) {
} else if (curr->debug_reason == DBG_REASON_DBGRQ) {
if (tid == rtos->current_threadid)
current_thread = tid;
}

View File

@ -624,7 +624,7 @@ static struct threads *liste_add_task(struct threads *task_list, struct threads
{
t->next = NULL;
if (!*last)
if (!*last) {
if (!task_list) {
task_list = t;
return task_list;
@ -637,7 +637,8 @@ static struct threads *liste_add_task(struct threads *task_list, struct threads
temp->next = t;
*last = t;
return task_list;
} else {
}
} else {
(*last)->next = t;
*last = t;
return task_list;

View File

@ -2908,9 +2908,9 @@ static int aarch64_jim_configure(struct target *target, struct jim_getopt_info *
pc = (struct aarch64_private_config *)target->private_config;
if (!pc) {
pc = calloc(1, sizeof(struct aarch64_private_config));
pc->adiv5_config.ap_num = DP_APSEL_INVALID;
target->private_config = pc;
pc = calloc(1, sizeof(struct aarch64_private_config));
pc->adiv5_config.ap_num = DP_APSEL_INVALID;
target->private_config = pc;
}
/*

View File

@ -388,7 +388,7 @@ static int arc_build_reg_cache(struct target *target)
}
list_for_each_entry(reg_desc, &arc->aux_reg_descriptions, list) {
CHECK_RETVAL(arc_init_reg(target, &reg_list[i], reg_desc, i));
CHECK_RETVAL(arc_init_reg(target, &reg_list[i], reg_desc, i));
LOG_TARGET_DEBUG(target, "reg n=%3li name=%3s group=%s feature=%s", i,
reg_list[i].name, reg_list[i].group,
@ -464,7 +464,7 @@ static int arc_build_bcr_reg_cache(struct target *target)
}
list_for_each_entry(reg_desc, &arc->bcr_reg_descriptions, list) {
CHECK_RETVAL(arc_init_reg(target, &reg_list[i], reg_desc, gdb_regnum));
CHECK_RETVAL(arc_init_reg(target, &reg_list[i], reg_desc, gdb_regnum));
/* BCRs always semantically, they are just read-as-zero, if there is
* not real register. */
reg_list[i].exist = true;
@ -719,14 +719,14 @@ static int arc_configure(struct target *target)
LOG_TARGET_DEBUG(target, "Configuring ARC ICCM and DCCM");
/* Configuring DCCM if DCCM_BUILD and AUX_DCCM are known registers. */
if (arc_reg_get_by_name(target->reg_cache, "dccm_build", true) &&
arc_reg_get_by_name(target->reg_cache, "aux_dccm", true))
CHECK_RETVAL(arc_configure_dccm(target));
if (arc_reg_get_by_name(target->reg_cache, "dccm_build", true)
&& arc_reg_get_by_name(target->reg_cache, "aux_dccm", true))
CHECK_RETVAL(arc_configure_dccm(target));
/* Configuring ICCM if ICCM_BUILD and AUX_ICCM are known registers. */
if (arc_reg_get_by_name(target->reg_cache, "iccm_build", true) &&
arc_reg_get_by_name(target->reg_cache, "aux_iccm", true))
CHECK_RETVAL(arc_configure_iccm(target));
if (arc_reg_get_by_name(target->reg_cache, "iccm_build", true)
&& arc_reg_get_by_name(target->reg_cache, "aux_iccm", true))
CHECK_RETVAL(arc_configure_iccm(target));
return ERROR_OK;
}
@ -1067,9 +1067,7 @@ static int arc_poll(struct target *target)
LOG_TARGET_DEBUG(target, "Discrepancy of STATUS32[0] HALT bit and ARC_JTAG_STAT_RU, "
"target is still running");
}
} else if (target->state == TARGET_DEBUG_RUNNING) {
target->state = TARGET_HALTED;
LOG_TARGET_DEBUG(target, "ARC core is in debug running mode");

View File

@ -1301,11 +1301,11 @@ int arm_get_gdb_reg_list(struct target *target,
*reg_list = malloc(sizeof(struct reg *) * (*reg_list_size));
for (i = 0; i < 16; i++)
(*reg_list)[i] = arm_reg_current(arm, i);
(*reg_list)[i] = arm_reg_current(arm, i);
/* For GDB compatibility, take FPA registers size into account and zero-fill it*/
for (i = 16; i < 24; i++)
(*reg_list)[i] = &arm_gdb_dummy_fp_reg;
(*reg_list)[i] = &arm_gdb_dummy_fp_reg;
(*reg_list)[24] = &arm_gdb_dummy_fps_reg;
(*reg_list)[25] = arm->cpsr;
@ -1330,25 +1330,25 @@ int arm_get_gdb_reg_list(struct target *target,
*reg_list = malloc(sizeof(struct reg *) * (*reg_list_size));
for (i = 0; i < 16; i++)
(*reg_list)[i] = arm_reg_current(arm, i);
(*reg_list)[i] = arm_reg_current(arm, i);
for (i = 13; i < ARRAY_SIZE(arm_core_regs); i++) {
int reg_index = arm->core_cache->reg_list[i].number;
int reg_index = arm->core_cache->reg_list[i].number;
if (arm_core_regs[i].mode == ARM_MODE_MON
if (arm_core_regs[i].mode == ARM_MODE_MON
&& arm->core_type != ARM_CORE_TYPE_SEC_EXT
&& arm->core_type != ARM_CORE_TYPE_VIRT_EXT)
continue;
if (arm_core_regs[i].mode == ARM_MODE_HYP
continue;
if (arm_core_regs[i].mode == ARM_MODE_HYP
&& arm->core_type != ARM_CORE_TYPE_VIRT_EXT)
continue;
(*reg_list)[reg_index] = &(arm->core_cache->reg_list[i]);
continue;
(*reg_list)[reg_index] = &arm->core_cache->reg_list[i];
}
/* When we supply the target description, there is no need for fake FPA */
for (i = 16; i < 24; i++) {
(*reg_list)[i] = &arm_gdb_dummy_fp_reg;
(*reg_list)[i]->size = 0;
(*reg_list)[i] = &arm_gdb_dummy_fp_reg;
(*reg_list)[i]->size = 0;
}
(*reg_list)[24] = &arm_gdb_dummy_fps_reg;
(*reg_list)[24]->size = 0;

View File

@ -260,8 +260,7 @@ COMMAND_HANDLER(armv7a_mmu_dump_table)
/* skip empty entries in the first level table */
if ((first_lvl_descriptor & 3) == 0) {
pt_idx++;
} else
if ((first_lvl_descriptor & 0x40002) == 2) {
} else if ((first_lvl_descriptor & 0x40002) == 2) {
/* section descriptor */
uint32_t va_range = 1024*1024-1; /* 1MB range */
uint32_t va_start = pt_idx << 20;
@ -273,8 +272,7 @@ COMMAND_HANDLER(armv7a_mmu_dump_table)
LOG_USER("SECT: VA[%8.8"PRIx32" -- %8.8"PRIx32"]: PA[%8.8"PRIx32" -- %8.8"PRIx32"] %s",
va_start, va_end, pa_start, pa_end, l1_desc_bits_to_string(first_lvl_descriptor, afe));
pt_idx++;
} else
if ((first_lvl_descriptor & 0x40002) == 0x40002) {
} else if ((first_lvl_descriptor & 0x40002) == 0x40002) {
/* supersection descriptor */
uint32_t va_range = 16*1024*1024-1; /* 16MB range */
uint32_t va_start = pt_idx << 20;
@ -310,8 +308,7 @@ COMMAND_HANDLER(armv7a_mmu_dump_table)
if ((second_lvl_descriptor & 3) == 0) {
/* skip entry */
pt2_idx++;
} else
if ((second_lvl_descriptor & 3) == 1) {
} else if ((second_lvl_descriptor & 3) == 1) {
/* large page */
uint32_t va_range = 64*1024-1; /* 64KB range */
uint32_t va_start = (pt_idx << 20) + (pt2_idx << 12);

View File

@ -65,6 +65,28 @@ const int armv7m_msp_reg_map[ARMV7M_NUM_CORE_REGS] = {
ARMV7M_XPSR,
};
static struct reg_data_type_bitfield armv8m_vpr_bits[] = {
{ 0, 15, REG_TYPE_UINT },
{ 16, 19, REG_TYPE_UINT },
{ 20, 23, REG_TYPE_UINT },
};
static struct reg_data_type_flags_field armv8m_vpr_fields[] = {
{ "P0", armv8m_vpr_bits + 0, armv8m_vpr_fields + 1, },
{ "MASK01", armv8m_vpr_bits + 1, armv8m_vpr_fields + 2, },
{ "MASK23", armv8m_vpr_bits + 2, NULL },
};
static struct reg_data_type_flags armv8m_vpr_flags[] = {
{ 4, armv8m_vpr_fields },
};
static struct reg_data_type armv8m_flags_vpr[] = {
{ REG_TYPE_ARCH_DEFINED, "vpr_reg", REG_TYPE_CLASS_FLAGS,
{ .reg_type_flags = armv8m_vpr_flags },
},
};
/*
* These registers are not memory-mapped. The ARMv7-M profile includes
* memory mapped registers too, such as for the NVIC (interrupt controller)
@ -80,30 +102,31 @@ static const struct {
enum reg_type type;
const char *group;
const char *feature;
struct reg_data_type *data_type;
} armv7m_regs[] = {
{ ARMV7M_R0, "r0", 32, REG_TYPE_INT, "general", "org.gnu.gdb.arm.m-profile" },
{ ARMV7M_R1, "r1", 32, REG_TYPE_INT, "general", "org.gnu.gdb.arm.m-profile" },
{ ARMV7M_R2, "r2", 32, REG_TYPE_INT, "general", "org.gnu.gdb.arm.m-profile" },
{ ARMV7M_R3, "r3", 32, REG_TYPE_INT, "general", "org.gnu.gdb.arm.m-profile" },
{ ARMV7M_R4, "r4", 32, REG_TYPE_INT, "general", "org.gnu.gdb.arm.m-profile" },
{ ARMV7M_R5, "r5", 32, REG_TYPE_INT, "general", "org.gnu.gdb.arm.m-profile" },
{ ARMV7M_R6, "r6", 32, REG_TYPE_INT, "general", "org.gnu.gdb.arm.m-profile" },
{ ARMV7M_R7, "r7", 32, REG_TYPE_INT, "general", "org.gnu.gdb.arm.m-profile" },
{ ARMV7M_R8, "r8", 32, REG_TYPE_INT, "general", "org.gnu.gdb.arm.m-profile" },
{ ARMV7M_R9, "r9", 32, REG_TYPE_INT, "general", "org.gnu.gdb.arm.m-profile" },
{ ARMV7M_R10, "r10", 32, REG_TYPE_INT, "general", "org.gnu.gdb.arm.m-profile" },
{ ARMV7M_R11, "r11", 32, REG_TYPE_INT, "general", "org.gnu.gdb.arm.m-profile" },
{ ARMV7M_R12, "r12", 32, REG_TYPE_INT, "general", "org.gnu.gdb.arm.m-profile" },
{ ARMV7M_R13, "sp", 32, REG_TYPE_DATA_PTR, "general", "org.gnu.gdb.arm.m-profile" },
{ ARMV7M_R14, "lr", 32, REG_TYPE_INT, "general", "org.gnu.gdb.arm.m-profile" },
{ ARMV7M_PC, "pc", 32, REG_TYPE_CODE_PTR, "general", "org.gnu.gdb.arm.m-profile" },
{ ARMV7M_XPSR, "xpsr", 32, REG_TYPE_INT, "general", "org.gnu.gdb.arm.m-profile" },
{ ARMV7M_R0, "r0", 32, REG_TYPE_INT, "general", "org.gnu.gdb.arm.m-profile", NULL, },
{ ARMV7M_R1, "r1", 32, REG_TYPE_INT, "general", "org.gnu.gdb.arm.m-profile", NULL, },
{ ARMV7M_R2, "r2", 32, REG_TYPE_INT, "general", "org.gnu.gdb.arm.m-profile", NULL, },
{ ARMV7M_R3, "r3", 32, REG_TYPE_INT, "general", "org.gnu.gdb.arm.m-profile", NULL, },
{ ARMV7M_R4, "r4", 32, REG_TYPE_INT, "general", "org.gnu.gdb.arm.m-profile", NULL, },
{ ARMV7M_R5, "r5", 32, REG_TYPE_INT, "general", "org.gnu.gdb.arm.m-profile", NULL, },
{ ARMV7M_R6, "r6", 32, REG_TYPE_INT, "general", "org.gnu.gdb.arm.m-profile", NULL, },
{ ARMV7M_R7, "r7", 32, REG_TYPE_INT, "general", "org.gnu.gdb.arm.m-profile", NULL, },
{ ARMV7M_R8, "r8", 32, REG_TYPE_INT, "general", "org.gnu.gdb.arm.m-profile", NULL, },
{ ARMV7M_R9, "r9", 32, REG_TYPE_INT, "general", "org.gnu.gdb.arm.m-profile", NULL, },
{ ARMV7M_R10, "r10", 32, REG_TYPE_INT, "general", "org.gnu.gdb.arm.m-profile", NULL, },
{ ARMV7M_R11, "r11", 32, REG_TYPE_INT, "general", "org.gnu.gdb.arm.m-profile", NULL, },
{ ARMV7M_R12, "r12", 32, REG_TYPE_INT, "general", "org.gnu.gdb.arm.m-profile", NULL, },
{ ARMV7M_R13, "sp", 32, REG_TYPE_DATA_PTR, "general", "org.gnu.gdb.arm.m-profile", NULL, },
{ ARMV7M_R14, "lr", 32, REG_TYPE_INT, "general", "org.gnu.gdb.arm.m-profile", NULL, },
{ ARMV7M_PC, "pc", 32, REG_TYPE_CODE_PTR, "general", "org.gnu.gdb.arm.m-profile", NULL, },
{ ARMV7M_XPSR, "xpsr", 32, REG_TYPE_INT, "general", "org.gnu.gdb.arm.m-profile", NULL, },
{ ARMV7M_MSP, "msp", 32, REG_TYPE_DATA_PTR, "system", "org.gnu.gdb.arm.m-system" },
{ ARMV7M_PSP, "psp", 32, REG_TYPE_DATA_PTR, "system", "org.gnu.gdb.arm.m-system" },
{ ARMV7M_MSP, "msp", 32, REG_TYPE_DATA_PTR, "system", "org.gnu.gdb.arm.m-system", NULL, },
{ ARMV7M_PSP, "psp", 32, REG_TYPE_DATA_PTR, "system", "org.gnu.gdb.arm.m-system", NULL, },
/* A working register for packing/unpacking special regs, hidden from gdb */
{ ARMV7M_PMSK_BPRI_FLTMSK_CTRL, "pmsk_bpri_fltmsk_ctrl", 32, REG_TYPE_INT, NULL, NULL },
{ ARMV7M_PMSK_BPRI_FLTMSK_CTRL, "pmsk_bpri_fltmsk_ctrl", 32, REG_TYPE_INT, NULL, NULL, NULL },
/* WARNING: If you use armv7m_write_core_reg() on one of 4 following
* special registers, the new data go to ARMV7M_PMSK_BPRI_FLTMSK_CTRL
@ -111,52 +134,54 @@ static const struct {
* To trigger write to CPU HW register, add
* armv7m_write_core_reg(,,ARMV7M_PMSK_BPRI_FLTMSK_CTRL,);
*/
{ ARMV7M_PRIMASK, "primask", 1, REG_TYPE_INT8, "system", "org.gnu.gdb.arm.m-system" },
{ ARMV7M_BASEPRI, "basepri", 8, REG_TYPE_INT8, "system", "org.gnu.gdb.arm.m-system" },
{ ARMV7M_FAULTMASK, "faultmask", 1, REG_TYPE_INT8, "system", "org.gnu.gdb.arm.m-system" },
{ ARMV7M_CONTROL, "control", 3, REG_TYPE_INT8, "system", "org.gnu.gdb.arm.m-system" },
{ ARMV7M_PRIMASK, "primask", 1, REG_TYPE_INT8, "system", "org.gnu.gdb.arm.m-system", NULL, },
{ ARMV7M_BASEPRI, "basepri", 8, REG_TYPE_INT8, "system", "org.gnu.gdb.arm.m-system", NULL, },
{ ARMV7M_FAULTMASK, "faultmask", 1, REG_TYPE_INT8, "system", "org.gnu.gdb.arm.m-system", NULL, },
{ ARMV7M_CONTROL, "control", 3, REG_TYPE_INT8, "system", "org.gnu.gdb.arm.m-system", NULL, },
/* ARMv8-M security extension (TrustZone) specific registers */
{ ARMV8M_MSP_NS, "msp_ns", 32, REG_TYPE_DATA_PTR, "stack", "org.gnu.gdb.arm.secext" },
{ ARMV8M_PSP_NS, "psp_ns", 32, REG_TYPE_DATA_PTR, "stack", "org.gnu.gdb.arm.secext" },
{ ARMV8M_MSP_S, "msp_s", 32, REG_TYPE_DATA_PTR, "stack", "org.gnu.gdb.arm.secext" },
{ ARMV8M_PSP_S, "psp_s", 32, REG_TYPE_DATA_PTR, "stack", "org.gnu.gdb.arm.secext" },
{ ARMV8M_MSPLIM_S, "msplim_s", 32, REG_TYPE_DATA_PTR, "stack", "org.gnu.gdb.arm.secext" },
{ ARMV8M_PSPLIM_S, "psplim_s", 32, REG_TYPE_DATA_PTR, "stack", "org.gnu.gdb.arm.secext" },
{ ARMV8M_MSPLIM_NS, "msplim_ns", 32, REG_TYPE_DATA_PTR, "stack", "org.gnu.gdb.arm.secext" },
{ ARMV8M_PSPLIM_NS, "psplim_ns", 32, REG_TYPE_DATA_PTR, "stack", "org.gnu.gdb.arm.secext" },
{ ARMV8M_MSP_NS, "msp_ns", 32, REG_TYPE_DATA_PTR, "stack", "org.gnu.gdb.arm.secext", NULL, },
{ ARMV8M_PSP_NS, "psp_ns", 32, REG_TYPE_DATA_PTR, "stack", "org.gnu.gdb.arm.secext", NULL, },
{ ARMV8M_MSP_S, "msp_s", 32, REG_TYPE_DATA_PTR, "stack", "org.gnu.gdb.arm.secext", NULL, },
{ ARMV8M_PSP_S, "psp_s", 32, REG_TYPE_DATA_PTR, "stack", "org.gnu.gdb.arm.secext", NULL, },
{ ARMV8M_MSPLIM_S, "msplim_s", 32, REG_TYPE_DATA_PTR, "stack", "org.gnu.gdb.arm.secext", NULL, },
{ ARMV8M_PSPLIM_S, "psplim_s", 32, REG_TYPE_DATA_PTR, "stack", "org.gnu.gdb.arm.secext", NULL, },
{ ARMV8M_MSPLIM_NS, "msplim_ns", 32, REG_TYPE_DATA_PTR, "stack", "org.gnu.gdb.arm.secext", NULL, },
{ ARMV8M_PSPLIM_NS, "psplim_ns", 32, REG_TYPE_DATA_PTR, "stack", "org.gnu.gdb.arm.secext", NULL, },
{ ARMV8M_PMSK_BPRI_FLTMSK_CTRL_S, "pmsk_bpri_fltmsk_ctrl_s", 32, REG_TYPE_INT, NULL, NULL },
{ ARMV8M_PRIMASK_S, "primask_s", 1, REG_TYPE_INT8, "system", "org.gnu.gdb.arm.secext" },
{ ARMV8M_BASEPRI_S, "basepri_s", 8, REG_TYPE_INT8, "system", "org.gnu.gdb.arm.secext" },
{ ARMV8M_FAULTMASK_S, "faultmask_s", 1, REG_TYPE_INT8, "system", "org.gnu.gdb.arm.secext" },
{ ARMV8M_CONTROL_S, "control_s", 3, REG_TYPE_INT8, "system", "org.gnu.gdb.arm.secext" },
{ ARMV8M_PMSK_BPRI_FLTMSK_CTRL_S, "pmsk_bpri_fltmsk_ctrl_s", 32, REG_TYPE_INT, NULL, NULL, NULL, },
{ ARMV8M_PRIMASK_S, "primask_s", 1, REG_TYPE_INT8, "system", "org.gnu.gdb.arm.secext", NULL, },
{ ARMV8M_BASEPRI_S, "basepri_s", 8, REG_TYPE_INT8, "system", "org.gnu.gdb.arm.secext", NULL, },
{ ARMV8M_FAULTMASK_S, "faultmask_s", 1, REG_TYPE_INT8, "system", "org.gnu.gdb.arm.secext", NULL, },
{ ARMV8M_CONTROL_S, "control_s", 3, REG_TYPE_INT8, "system", "org.gnu.gdb.arm.secext", NULL, },
{ ARMV8M_PMSK_BPRI_FLTMSK_CTRL_NS, "pmsk_bpri_fltmsk_ctrl_ns", 32, REG_TYPE_INT, NULL, NULL },
{ ARMV8M_PRIMASK_NS, "primask_ns", 1, REG_TYPE_INT8, "system", "org.gnu.gdb.arm.secext" },
{ ARMV8M_BASEPRI_NS, "basepri_ns", 8, REG_TYPE_INT8, "system", "org.gnu.gdb.arm.secext" },
{ ARMV8M_FAULTMASK_NS, "faultmask_ns", 1, REG_TYPE_INT8, "system", "org.gnu.gdb.arm.secext" },
{ ARMV8M_CONTROL_NS, "control_ns", 3, REG_TYPE_INT8, "system", "org.gnu.gdb.arm.secext" },
{ ARMV8M_PMSK_BPRI_FLTMSK_CTRL_NS, "pmsk_bpri_fltmsk_ctrl_ns", 32, REG_TYPE_INT, NULL, NULL, NULL, },
{ ARMV8M_PRIMASK_NS, "primask_ns", 1, REG_TYPE_INT8, "system", "org.gnu.gdb.arm.secext", NULL, },
{ ARMV8M_BASEPRI_NS, "basepri_ns", 8, REG_TYPE_INT8, "system", "org.gnu.gdb.arm.secext", NULL, },
{ ARMV8M_FAULTMASK_NS, "faultmask_ns", 1, REG_TYPE_INT8, "system", "org.gnu.gdb.arm.secext", NULL, },
{ ARMV8M_CONTROL_NS, "control_ns", 3, REG_TYPE_INT8, "system", "org.gnu.gdb.arm.secext", NULL, },
/* FPU registers */
{ ARMV7M_D0, "d0", 64, REG_TYPE_IEEE_DOUBLE, "float", "org.gnu.gdb.arm.vfp" },
{ ARMV7M_D1, "d1", 64, REG_TYPE_IEEE_DOUBLE, "float", "org.gnu.gdb.arm.vfp" },
{ ARMV7M_D2, "d2", 64, REG_TYPE_IEEE_DOUBLE, "float", "org.gnu.gdb.arm.vfp" },
{ ARMV7M_D3, "d3", 64, REG_TYPE_IEEE_DOUBLE, "float", "org.gnu.gdb.arm.vfp" },
{ ARMV7M_D4, "d4", 64, REG_TYPE_IEEE_DOUBLE, "float", "org.gnu.gdb.arm.vfp" },
{ ARMV7M_D5, "d5", 64, REG_TYPE_IEEE_DOUBLE, "float", "org.gnu.gdb.arm.vfp" },
{ ARMV7M_D6, "d6", 64, REG_TYPE_IEEE_DOUBLE, "float", "org.gnu.gdb.arm.vfp" },
{ ARMV7M_D7, "d7", 64, REG_TYPE_IEEE_DOUBLE, "float", "org.gnu.gdb.arm.vfp" },
{ ARMV7M_D8, "d8", 64, REG_TYPE_IEEE_DOUBLE, "float", "org.gnu.gdb.arm.vfp" },
{ ARMV7M_D9, "d9", 64, REG_TYPE_IEEE_DOUBLE, "float", "org.gnu.gdb.arm.vfp" },
{ ARMV7M_D10, "d10", 64, REG_TYPE_IEEE_DOUBLE, "float", "org.gnu.gdb.arm.vfp" },
{ ARMV7M_D11, "d11", 64, REG_TYPE_IEEE_DOUBLE, "float", "org.gnu.gdb.arm.vfp" },
{ ARMV7M_D12, "d12", 64, REG_TYPE_IEEE_DOUBLE, "float", "org.gnu.gdb.arm.vfp" },
{ ARMV7M_D13, "d13", 64, REG_TYPE_IEEE_DOUBLE, "float", "org.gnu.gdb.arm.vfp" },
{ ARMV7M_D14, "d14", 64, REG_TYPE_IEEE_DOUBLE, "float", "org.gnu.gdb.arm.vfp" },
{ ARMV7M_D15, "d15", 64, REG_TYPE_IEEE_DOUBLE, "float", "org.gnu.gdb.arm.vfp" },
{ ARMV7M_D0, "d0", 64, REG_TYPE_IEEE_DOUBLE, "float", "org.gnu.gdb.arm.vfp", NULL, },
{ ARMV7M_D1, "d1", 64, REG_TYPE_IEEE_DOUBLE, "float", "org.gnu.gdb.arm.vfp", NULL, },
{ ARMV7M_D2, "d2", 64, REG_TYPE_IEEE_DOUBLE, "float", "org.gnu.gdb.arm.vfp", NULL, },
{ ARMV7M_D3, "d3", 64, REG_TYPE_IEEE_DOUBLE, "float", "org.gnu.gdb.arm.vfp", NULL, },
{ ARMV7M_D4, "d4", 64, REG_TYPE_IEEE_DOUBLE, "float", "org.gnu.gdb.arm.vfp", NULL, },
{ ARMV7M_D5, "d5", 64, REG_TYPE_IEEE_DOUBLE, "float", "org.gnu.gdb.arm.vfp", NULL, },
{ ARMV7M_D6, "d6", 64, REG_TYPE_IEEE_DOUBLE, "float", "org.gnu.gdb.arm.vfp", NULL, },
{ ARMV7M_D7, "d7", 64, REG_TYPE_IEEE_DOUBLE, "float", "org.gnu.gdb.arm.vfp", NULL, },
{ ARMV7M_D8, "d8", 64, REG_TYPE_IEEE_DOUBLE, "float", "org.gnu.gdb.arm.vfp", NULL, },
{ ARMV7M_D9, "d9", 64, REG_TYPE_IEEE_DOUBLE, "float", "org.gnu.gdb.arm.vfp", NULL, },
{ ARMV7M_D10, "d10", 64, REG_TYPE_IEEE_DOUBLE, "float", "org.gnu.gdb.arm.vfp", NULL, },
{ ARMV7M_D11, "d11", 64, REG_TYPE_IEEE_DOUBLE, "float", "org.gnu.gdb.arm.vfp", NULL, },
{ ARMV7M_D12, "d12", 64, REG_TYPE_IEEE_DOUBLE, "float", "org.gnu.gdb.arm.vfp", NULL, },
{ ARMV7M_D13, "d13", 64, REG_TYPE_IEEE_DOUBLE, "float", "org.gnu.gdb.arm.vfp", NULL, },
{ ARMV7M_D14, "d14", 64, REG_TYPE_IEEE_DOUBLE, "float", "org.gnu.gdb.arm.vfp", NULL, },
{ ARMV7M_D15, "d15", 64, REG_TYPE_IEEE_DOUBLE, "float", "org.gnu.gdb.arm.vfp", NULL, },
{ ARMV7M_FPSCR, "fpscr", 32, REG_TYPE_INT, "float", "org.gnu.gdb.arm.vfp" },
{ ARMV7M_FPSCR, "fpscr", 32, REG_TYPE_INT, "float", "org.gnu.gdb.arm.vfp", NULL, },
{ ARMV8M_VPR, "vpr", 32, REG_TYPE_INT, "float", "org.gnu.gdb.arm.m-profile-mve", armv8m_flags_vpr, },
};
#define ARMV7M_NUM_REGS ARRAY_SIZE(armv7m_regs)
@ -272,6 +297,9 @@ uint32_t armv7m_map_id_to_regsel(unsigned int arm_reg_id)
case ARMV7M_FPSCR:
return ARMV7M_REGSEL_FPSCR;
case ARMV8M_VPR:
return ARMV8M_REGSEL_VPR;
case ARMV7M_D0 ... ARMV7M_D15:
return ARMV7M_REGSEL_S0 + 2 * (arm_reg_id - ARMV7M_D0);
@ -811,10 +839,14 @@ struct reg_cache *armv7m_build_reg_cache(struct target *target)
LOG_TARGET_ERROR(target, "unable to allocate feature list");
reg_list[i].reg_data_type = calloc(1, sizeof(struct reg_data_type));
if (reg_list[i].reg_data_type)
reg_list[i].reg_data_type->type = armv7m_regs[i].type;
else
if (reg_list[i].reg_data_type) {
if (armv7m_regs[i].data_type)
*reg_list[i].reg_data_type = *armv7m_regs[i].data_type;
else
reg_list[i].reg_data_type->type = armv7m_regs[i].type;
} else {
LOG_TARGET_ERROR(target, "unable to allocate reg type list");
}
}
arm->cpsr = reg_list + ARMV7M_XPSR;

View File

@ -62,6 +62,7 @@ enum {
ARMV7M_REGSEL_PMSK_BPRI_FLTMSK_CTRL = 0x14,
ARMV8M_REGSEL_PMSK_BPRI_FLTMSK_CTRL_S = 0x22,
ARMV8M_REGSEL_PMSK_BPRI_FLTMSK_CTRL_NS = 0x23,
ARMV8M_REGSEL_VPR = 0x24,
ARMV7M_REGSEL_FPSCR = 0x21,
/* 32bit Floating-point registers */
@ -196,12 +197,15 @@ enum {
/* Floating-point status register */
ARMV7M_FPSCR,
/* Vector Predication Status and Control Register */
ARMV8M_VPR,
/* for convenience add registers' block delimiters */
ARMV7M_LAST_REG,
ARMV7M_CORE_FIRST_REG = ARMV7M_R0,
ARMV7M_CORE_LAST_REG = ARMV7M_XPSR,
ARMV7M_FPU_FIRST_REG = ARMV7M_D0,
ARMV7M_FPU_LAST_REG = ARMV7M_FPSCR,
ARMV7M_FPU_LAST_REG = ARMV8M_VPR,
ARMV8M_FIRST_REG = ARMV8M_MSP_NS,
ARMV8M_LAST_REG = ARMV8M_CONTROL_NS,
};

View File

@ -1966,7 +1966,7 @@ int armv8_get_gdb_reg_list(struct target *target,
*reg_list = malloc(sizeof(struct reg *) * (*reg_list_size));
for (i = 0; i < *reg_list_size; i++)
(*reg_list)[i] = armv8_reg_current(arm, i);
(*reg_list)[i] = armv8_reg_current(arm, i);
return ERROR_OK;
case REG_CLASS_ALL:
@ -1974,7 +1974,7 @@ int armv8_get_gdb_reg_list(struct target *target,
*reg_list = malloc(sizeof(struct reg *) * (*reg_list_size));
for (i = 0; i < *reg_list_size; i++)
(*reg_list)[i] = armv8_reg_current(arm, i);
(*reg_list)[i] = armv8_reg_current(arm, i);
return ERROR_OK;

View File

@ -1324,21 +1324,21 @@ static int cortex_a_set_breakpoint(struct target *target,
brp_list[brp_i].value);
} else if (breakpoint->type == BKPT_SOFT) {
uint8_t code[4];
/* length == 2: Thumb breakpoint */
if (breakpoint->length == 2)
if (breakpoint->length == 2) {
/* length == 2: Thumb breakpoint */
buf_set_u32(code, 0, 32, ARMV5_T_BKPT(0x11));
else
/* length == 3: Thumb-2 breakpoint, actual encoding is
* a regular Thumb BKPT instruction but we replace a
* 32bit Thumb-2 instruction, so fix-up the breakpoint
* length
*/
if (breakpoint->length == 3) {
} else if (breakpoint->length == 3) {
/* length == 3: Thumb-2 breakpoint, actual encoding is
* a regular Thumb BKPT instruction but we replace a
* 32bit Thumb-2 instruction, so fix-up the breakpoint
* length
*/
buf_set_u32(code, 0, 32, ARMV5_T_BKPT(0x11));
breakpoint->length = 4;
} else
} else {
/* length == 4, normal ARM breakpoint */
buf_set_u32(code, 0, 32, ARMV5_BKPT(0x11));
}
retval = target_read_memory(target,
breakpoint->address & 0xFFFFFFFE,
@ -1348,8 +1348,7 @@ static int cortex_a_set_breakpoint(struct target *target,
return retval;
/* make sure data cache is cleaned & invalidated down to PoC */
armv7a_cache_flush_virt(target, breakpoint->address,
breakpoint->length);
armv7a_cache_flush_virt(target, breakpoint->address, breakpoint->length);
retval = target_write_memory(target,
breakpoint->address & 0xFFFFFFFE,
@ -1358,10 +1357,8 @@ static int cortex_a_set_breakpoint(struct target *target,
return retval;
/* update i-cache at breakpoint location */
armv7a_l1_d_cache_inval_virt(target, breakpoint->address,
breakpoint->length);
armv7a_l1_i_cache_inval_virt(target, breakpoint->address,
breakpoint->length);
armv7a_l1_d_cache_inval_virt(target, breakpoint->address, breakpoint->length);
armv7a_l1_i_cache_inval_virt(target, breakpoint->address, breakpoint->length);
breakpoint->is_set = true;
}

View File

@ -2708,6 +2708,10 @@ int cortex_m_examine(struct target *target)
for (size_t idx = ARMV7M_FPU_FIRST_REG; idx <= ARMV7M_FPU_LAST_REG; idx++)
armv7m->arm.core_cache->reg_list[idx].exist = false;
/* TODO: MVE can be present without floating points. Revisit this test */
if (armv7m->fp_feature != FPV5_MVE_F && armv7m->fp_feature != FPV5_MVE_I)
armv7m->arm.core_cache->reg_list[ARMV8M_VPR].exist = false;
if (!cortex_m_has_tz(target))
for (size_t idx = ARMV8M_FIRST_REG; idx <= ARMV8M_LAST_REG; idx++)
armv7m->arm.core_cache->reg_list[idx].exist = false;

View File

@ -2357,7 +2357,7 @@ COMMAND_HANDLER(mips32_handle_scan_delay_command)
if (CMD_ARGC == 1)
COMMAND_PARSE_NUMBER(uint, CMD_ARGV[0], ejtag_info->scan_delay);
else if (CMD_ARGC > 1)
return ERROR_COMMAND_SYNTAX_ERROR;
return ERROR_COMMAND_SYNTAX_ERROR;
command_print(CMD, "scan delay: %d nsec", ejtag_info->scan_delay);
if (ejtag_info->scan_delay >= MIPS32_SCAN_DELAY_LEGACY_MODE) {

View File

@ -1397,7 +1397,7 @@ COMMAND_HANDLER(mips_m4k_handle_scan_delay_command)
if (CMD_ARGC == 1)
COMMAND_PARSE_NUMBER(uint, CMD_ARGV[0], ejtag_info->scan_delay);
else if (CMD_ARGC > 1)
return ERROR_COMMAND_SYNTAX_ERROR;
return ERROR_COMMAND_SYNTAX_ERROR;
command_print(CMD, "scan delay: %d nsec", ejtag_info->scan_delay);
if (ejtag_info->scan_delay >= MIPS32_SCAN_DELAY_LEGACY_MODE) {

View File

@ -689,15 +689,13 @@ static int stm8_write_flash(struct target *target, enum mem_type type,
if (stm8->flash_ncr2)
stm8_write_u8(target, stm8->flash_ncr2, ~(PRG + opt));
blocksize = blocksize_param;
} else
if ((bytecnt >= 4) && ((address & 0x3) == 0)) {
} else if ((bytecnt >= 4) && ((address & 0x3) == 0)) {
if (stm8->flash_cr2)
stm8_write_u8(target, stm8->flash_cr2, WPRG + opt);
if (stm8->flash_ncr2)
stm8_write_u8(target, stm8->flash_ncr2, ~(WPRG + opt));
blocksize = 4;
} else
if (blocksize != 1) {
} else if (blocksize != 1) {
if (stm8->flash_cr2)
stm8_write_u8(target, stm8->flash_cr2, opt);
if (stm8->flash_ncr2)
@ -1552,8 +1550,8 @@ static int stm8_set_watchpoint(struct target *target,
}
if (watchpoint->length != 1) {
LOG_ERROR("Only watchpoints of length 1 are supported");
return ERROR_TARGET_UNALIGNED_ACCESS;
LOG_ERROR("Only watchpoints of length 1 are supported");
return ERROR_TARGET_UNALIGNED_ACCESS;
}
enum hw_break_type enable = 0;

View File

@ -749,10 +749,10 @@ COMMAND_HANDLER(handle_xsvf_command)
int delay;
if (read(xsvf_fd, &wait_local, 1) < 0
|| read(xsvf_fd, &end, 1) < 0
|| read(xsvf_fd, delay_buf, 4) < 0) {
do_abort = 1;
break;
|| read(xsvf_fd, &end, 1) < 0
|| read(xsvf_fd, delay_buf, 4) < 0) {
do_abort = 1;
break;
}
wait_state = xsvf_to_tap(wait_local);

View File

@ -0,0 +1,9 @@
# SPDX-License-Identifier: GPL-2.0-or-later
# Example config for using Linux spidev as a SWD adapter.
adapter driver linuxspidev
adapter speed 3000
spidev path "/dev/spidev0.0"
spidev mode 3
spidev queue_entries 64