Merge branch 'master' into from_upstream

I may have broken memory sampling with this merge.

Conflicts:
	doc/openocd.texi
	src/helper/command.c
	src/jtag/drivers/ftdi.c
	src/rtos/FreeRTOS.c

Change-Id: I2b7e09b2d3b244db546c5212532e6b48fb66dca4
This commit is contained in:
Tim Newsome 2021-05-03 11:01:37 -07:00
commit 927c4db298
65 changed files with 2634 additions and 1445 deletions

View File

@ -45,6 +45,9 @@ AC_SEARCH_LIBS([openpty], [util])
AC_CHECK_HEADERS([sys/socket.h]) AC_CHECK_HEADERS([sys/socket.h])
AC_CHECK_HEADERS([elf.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_HEADERS([dirent.h]) AC_CHECK_HEADERS([dirent.h])
AC_CHECK_HEADERS([fcntl.h]) AC_CHECK_HEADERS([fcntl.h])
AC_CHECK_HEADERS([malloc.h]) AC_CHECK_HEADERS([malloc.h])

View File

@ -154,6 +154,11 @@ ATTRS{idVendor}=="138e", ATTRS{idProduct}=="9000", MODE="660", GROUP="plugdev",
# Debug Board for Neo1973 # Debug Board for Neo1973
ATTRS{idVendor}=="1457", ATTRS{idProduct}=="5118", MODE="660", GROUP="plugdev", TAG+="uaccess" ATTRS{idVendor}=="1457", ATTRS{idProduct}=="5118", 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"
ATTRS{idVendor}=="15a2", ATTRS{idProduct}=="005e", MODE="660", GROUP="plugdev", TAG+="uaccess"
# Olimex ARM-USB-OCD # Olimex ARM-USB-OCD
ATTRS{idVendor}=="15ba", ATTRS{idProduct}=="0003", MODE="660", GROUP="plugdev", TAG+="uaccess" ATTRS{idVendor}=="15ba", ATTRS{idProduct}=="0003", MODE="660", GROUP="plugdev", TAG+="uaccess"

File diff suppressed because it is too large Load Diff

View File

@ -479,8 +479,8 @@ static int nand_init(struct command_context *cmd_ctx)
{ {
if (!nand_devices) if (!nand_devices)
return ERROR_OK; return ERROR_OK;
struct command *parent = command_find_in_context(cmd_ctx, "nand");
return register_commands(cmd_ctx, parent, nand_exec_command_handlers); return register_commands(cmd_ctx, "nand", nand_exec_command_handlers);
} }
COMMAND_HANDLER(handle_nand_init_command) COMMAND_HANDLER(handle_nand_init_command)

View File

@ -52,6 +52,7 @@ NOR_DRIVERS = \
%D%/psoc5lp.c \ %D%/psoc5lp.c \
%D%/psoc6.c \ %D%/psoc6.c \
%D%/renesas_rpchf.c \ %D%/renesas_rpchf.c \
%D%/rp2040.c \
%D%/sfdp.c \ %D%/sfdp.c \
%D%/sh_qspi.c \ %D%/sh_qspi.c \
%D%/sim3x.c \ %D%/sim3x.c \

View File

@ -68,6 +68,7 @@ extern const struct flash_driver psoc5lp_eeprom_flash;
extern const struct flash_driver psoc5lp_nvl_flash; extern const struct flash_driver psoc5lp_nvl_flash;
extern const struct flash_driver psoc6_flash; extern const struct flash_driver psoc6_flash;
extern const struct flash_driver renesas_rpchf_flash; extern const struct flash_driver renesas_rpchf_flash;
extern const struct flash_driver rp2040_flash;
extern const struct flash_driver sh_qspi_flash; extern const struct flash_driver sh_qspi_flash;
extern const struct flash_driver sim3x_flash; extern const struct flash_driver sim3x_flash;
extern const struct flash_driver stellaris_flash; extern const struct flash_driver stellaris_flash;
@ -141,6 +142,7 @@ static const struct flash_driver * const flash_drivers[] = {
&psoc5lp_nvl_flash, &psoc5lp_nvl_flash,
&psoc6_flash, &psoc6_flash,
&renesas_rpchf_flash, &renesas_rpchf_flash,
&rp2040_flash,
&sh_qspi_flash, &sh_qspi_flash,
&sim3x_flash, &sim3x_flash,
&stellaris_flash, &stellaris_flash,

View File

@ -109,7 +109,6 @@ static const struct command_registration esirisc_flash_command_handlers[];
FLASH_BANK_COMMAND_HANDLER(esirisc_flash_bank_command) FLASH_BANK_COMMAND_HANDLER(esirisc_flash_bank_command)
{ {
struct esirisc_flash_bank *esirisc_info; struct esirisc_flash_bank *esirisc_info;
struct command *esirisc_cmd;
if (CMD_ARGC < 9) if (CMD_ARGC < 9)
return ERROR_COMMAND_SYNTAX_ERROR; return ERROR_COMMAND_SYNTAX_ERROR;
@ -123,8 +122,7 @@ FLASH_BANK_COMMAND_HANDLER(esirisc_flash_bank_command)
bank->driver_priv = esirisc_info; bank->driver_priv = esirisc_info;
/* register commands using existing esirisc context */ /* register commands using existing esirisc context */
esirisc_cmd = command_find_in_context(CMD_CTX, "esirisc"); register_commands(CMD_CTX, "esirisc", esirisc_flash_command_handlers);
register_commands(CMD_CTX, esirisc_cmd, esirisc_flash_command_handlers);
return ERROR_OK; return ERROR_OK;
} }

View File

@ -289,7 +289,7 @@ static const struct nrf5_device_package nrf5_packages_table[] = {
const struct flash_driver nrf5_flash, nrf51_flash; const struct flash_driver nrf5_flash, nrf51_flash;
static int nrf5_bank_is_probed(struct flash_bank *bank) static bool nrf5_bank_is_probed(const struct flash_bank *bank)
{ {
struct nrf5_bank *nbank = bank->driver_priv; struct nrf5_bank *nbank = bank->driver_priv;
@ -309,13 +309,10 @@ static int nrf5_get_probed_chip_if_halted(struct flash_bank *bank, struct nrf5_i
struct nrf5_bank *nbank = bank->driver_priv; struct nrf5_bank *nbank = bank->driver_priv;
*chip = nbank->chip; *chip = nbank->chip;
int probed = nrf5_bank_is_probed(bank); if (nrf5_bank_is_probed(bank))
if (probed < 0)
return probed;
else if (!probed)
return nrf5_probe(bank);
else
return ERROR_OK; return ERROR_OK;
return nrf5_probe(bank);
} }
static int nrf5_wait_for_nvmc(struct nrf5_info *chip) static int nrf5_wait_for_nvmc(struct nrf5_info *chip)
@ -871,14 +868,10 @@ static int nrf5_probe(struct flash_bank *bank)
static int nrf5_auto_probe(struct flash_bank *bank) static int nrf5_auto_probe(struct flash_bank *bank)
{ {
int probed = nrf5_bank_is_probed(bank); if (nrf5_bank_is_probed(bank))
if (probed < 0)
return probed;
else if (probed)
return ERROR_OK; return ERROR_OK;
else
return nrf5_probe(bank); return nrf5_probe(bank);
} }
static int nrf5_erase_all(struct nrf5_info *chip) static int nrf5_erase_all(struct nrf5_info *chip)

View File

@ -1132,7 +1132,7 @@ static const struct numicro_cpu_type NuMicroParts[] = {
/* Private bank information for NuMicro. */ /* Private bank information for NuMicro. */
struct numicro_flash_bank { struct numicro_flash_bank {
struct working_area *write_algorithm; struct working_area *write_algorithm;
int probed; bool probed;
const struct numicro_cpu_type *cpu; const struct numicro_cpu_type *cpu;
}; };

453
src/flash/nor/rp2040.c Normal file
View File

@ -0,0 +1,453 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "imp.h"
#include <helper/binarybuffer.h>
#include <target/algorithm.h>
#include <target/armv7m.h>
#include "spi.h"
/* NOTE THAT THIS CODE REQUIRES FLASH ROUTINES in BOOTROM WITH FUNCTION TABLE PTR AT 0x00000010
Your gdbinit should load the bootrom.elf if appropriate */
/* this is 'M' 'u', 1 (version) */
#define BOOTROM_MAGIC 0x01754d
#define BOOTROM_MAGIC_ADDR 0x00000010
/* Call a ROM function via the debug trampoline
Up to four arguments passed in r0...r3 as per ABI
Function address is passed in r7
the trampoline is needed because OpenOCD "algorithm" code insists on sw breakpoints. */
#define MAKE_TAG(a, b) (((b)<<8) | a)
#define FUNC_DEBUG_TRAMPOLINE MAKE_TAG('D', 'T')
#define FUNC_DEBUG_TRAMPOLINE_END MAKE_TAG('D', 'E')
#define FUNC_FLASH_EXIT_XIP MAKE_TAG('E', 'X')
#define FUNC_CONNECT_INTERNAL_FLASH MAKE_TAG('I', 'F')
#define FUNC_FLASH_RANGE_ERASE MAKE_TAG('R', 'E')
#define FUNC_FLASH_RANGE_PROGRAM MAKE_TAG('R', 'P')
#define FUNC_FLASH_FLUSH_CACHE MAKE_TAG('F', 'C')
#define FUNC_FLASH_ENTER_CMD_XIP MAKE_TAG('C', 'X')
struct rp2040_flash_bank {
/* flag indicating successful flash probe */
bool probed;
/* stack used by Boot ROM calls */
struct working_area *stack;
/* function jump table populated by rp2040_flash_probe() */
uint16_t jump_debug_trampoline;
uint16_t jump_debug_trampoline_end;
uint16_t jump_flash_exit_xip;
uint16_t jump_connect_internal_flash;
uint16_t jump_flash_range_erase;
uint16_t jump_flash_range_program;
uint16_t jump_flush_cache;
uint16_t jump_enter_cmd_xip;
/* detected model of SPI flash */
const struct flash_device *dev;
};
static uint32_t rp2040_lookup_symbol(struct target *target, uint32_t tag, uint16_t *symbol)
{
uint32_t magic;
int err = target_read_u32(target, BOOTROM_MAGIC_ADDR, &magic);
if (err != ERROR_OK)
return err;
magic &= 0xffffff; /* ignore bootrom version */
if (magic != BOOTROM_MAGIC) {
if (!((magic ^ BOOTROM_MAGIC)&0xffff))
LOG_ERROR("Incorrect RP2040 BOOT ROM version");
else
LOG_ERROR("RP2040 BOOT ROM not found");
return ERROR_FAIL;
}
/* dereference the table pointer */
uint16_t table_entry;
err = target_read_u16(target, BOOTROM_MAGIC_ADDR + 4, &table_entry);
if (err != ERROR_OK)
return err;
uint16_t entry_tag;
do {
err = target_read_u16(target, table_entry, &entry_tag);
if (err != ERROR_OK)
return err;
if (entry_tag == tag) {
/* 16 bit symbol is next */
return target_read_u16(target, table_entry + 2, symbol);
}
table_entry += 4;
} while (entry_tag);
return ERROR_FAIL;
}
static int rp2040_call_rom_func(struct target *target, struct rp2040_flash_bank *priv,
uint16_t func_offset, uint32_t argdata[], unsigned int n_args)
{
char *regnames[4] = { "r0", "r1", "r2", "r3" };
assert(n_args <= ARRAY_SIZE(regnames)); /* only allow register arguments */
if (!priv->stack) {
LOG_ERROR("no stack for flash programming code");
return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
}
target_addr_t stacktop = priv->stack->address + priv->stack->size;
LOG_DEBUG("Calling ROM func @0x%" PRIx16 " with %d arguments", func_offset, n_args);
LOG_DEBUG("Calling on core \"%s\"", target->cmd_name);
struct reg_param args[ARRAY_SIZE(regnames) + 2];
struct armv7m_algorithm alg_info;
for (unsigned int i = 0; i < n_args; ++i) {
init_reg_param(&args[i], regnames[i], 32, PARAM_OUT);
buf_set_u32(args[i].value, 0, 32, argdata[i]);
}
/* Pass function pointer in r7 */
init_reg_param(&args[n_args], "r7", 32, PARAM_OUT);
buf_set_u32(args[n_args].value, 0, 32, func_offset);
init_reg_param(&args[n_args + 1], "sp", 32, PARAM_OUT);
buf_set_u32(args[n_args + 1].value, 0, 32, stacktop);
for (unsigned int i = 0; i < n_args + 2; ++i)
LOG_DEBUG("Set %s = 0x%" PRIx32, args[i].reg_name, buf_get_u32(args[i].value, 0, 32));
/* Actually call the function */
alg_info.common_magic = ARMV7M_COMMON_MAGIC;
alg_info.core_mode = ARM_MODE_THREAD;
int err = target_run_algorithm(
target,
0, NULL, /* No memory arguments */
n_args + 1, args, /* User arguments + r7 */
priv->jump_debug_trampoline, priv->jump_debug_trampoline_end,
3000, /* 3s timeout */
&alg_info
);
for (unsigned int i = 0; i < n_args + 2; ++i)
destroy_reg_param(&args[i]);
if (err != ERROR_OK)
LOG_ERROR("Failed to invoke ROM function @0x%" PRIx16 "\n", func_offset);
return err;
}
static int stack_grab_and_prep(struct flash_bank *bank)
{
struct rp2040_flash_bank *priv = bank->driver_priv;
/* target_alloc_working_area always allocates multiples of 4 bytes, so no worry about alignment */
const int STACK_SIZE = 256;
int err = target_alloc_working_area(bank->target, STACK_SIZE, &priv->stack);
if (err != ERROR_OK) {
LOG_ERROR("Could not allocate stack for flash programming code");
return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
}
LOG_DEBUG("Connecting internal flash");
err = rp2040_call_rom_func(bank->target, priv, priv->jump_connect_internal_flash, NULL, 0);
if (err != ERROR_OK) {
LOG_ERROR("RP2040 erase: failed to connect internal flash");
return err;
}
LOG_DEBUG("Kicking flash out of XIP mode");
err = rp2040_call_rom_func(bank->target, priv, priv->jump_flash_exit_xip, NULL, 0);
if (err != ERROR_OK) {
LOG_ERROR("RP2040 erase: failed to exit flash XIP mode");
return err;
}
return ERROR_OK;
}
static int rp2040_flash_write(struct flash_bank *bank, const uint8_t *buffer, uint32_t offset, uint32_t count)
{
LOG_DEBUG("Writing %d bytes starting at 0x%" PRIx32, count, offset);
struct rp2040_flash_bank *priv = bank->driver_priv;
struct target *target = bank->target;
struct working_area *bounce;
int err = stack_grab_and_prep(bank);
if (err != ERROR_OK)
return err;
const unsigned int chunk_size = target_get_working_area_avail(target);
if (target_alloc_working_area(target, chunk_size, &bounce) != ERROR_OK) {
LOG_ERROR("Could not allocate bounce buffer for flash programming. Can't continue");
return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
}
LOG_DEBUG("Allocated flash bounce buffer @" TARGET_ADDR_FMT, bounce->address);
while (count > 0) {
uint32_t write_size = count > chunk_size ? chunk_size : count;
LOG_DEBUG("Writing %d bytes to offset 0x%" PRIx32, write_size, offset);
err = target_write_buffer(target, bounce->address, write_size, buffer);
if (err != ERROR_OK) {
LOG_ERROR("Could not load data into target bounce buffer");
break;
}
uint32_t args[3] = {
offset, /* addr */
bounce->address, /* data */
write_size /* count */
};
err = rp2040_call_rom_func(target, priv, priv->jump_flash_range_program, args, ARRAY_SIZE(args));
if (err != ERROR_OK) {
LOG_ERROR("Failed to invoke flash programming code on target");
break;
}
buffer += write_size;
offset += write_size;
count -= write_size;
}
target_free_working_area(target, bounce);
if (err != ERROR_OK)
return err;
/* Flash is successfully programmed. We can now do a bit of poking to make the flash
contents visible to us via memory-mapped (XIP) interface in the 0x1... memory region */
LOG_DEBUG("Flushing flash cache after write behind");
err = rp2040_call_rom_func(bank->target, priv, priv->jump_flush_cache, NULL, 0);
if (err != ERROR_OK) {
LOG_ERROR("RP2040 write: failed to flush flash cache");
return err;
}
LOG_DEBUG("Configuring SSI for execute-in-place");
err = rp2040_call_rom_func(bank->target, priv, priv->jump_enter_cmd_xip, NULL, 0);
if (err != ERROR_OK)
LOG_ERROR("RP2040 write: failed to flush flash cache");
return err;
}
static int rp2040_flash_erase(struct flash_bank *bank, unsigned int first, unsigned int last)
{
struct rp2040_flash_bank *priv = bank->driver_priv;
uint32_t start_addr = bank->sectors[first].offset;
uint32_t length = bank->sectors[last].offset + bank->sectors[last].size - start_addr;
LOG_DEBUG("RP2040 erase %d bytes starting at 0x%" PRIx32, length, start_addr);
int err = stack_grab_and_prep(bank);
if (err != ERROR_OK)
return err;
LOG_DEBUG("Remote call flash_range_erase");
uint32_t args[4] = {
bank->sectors[first].offset, /* addr */
bank->sectors[last].offset + bank->sectors[last].size - bank->sectors[first].offset, /* count */
priv->dev->sectorsize, /* block_size */
priv->dev->erase_cmd /* block_cmd */
};
/*
The RP2040 Boot ROM provides a _flash_range_erase() API call documented in Section 2.8.3.1.3:
https://datasheets.raspberrypi.org/rp2040/rp2040-datasheet.pdf
and the particular source code for said Boot ROM function can be found here:
https://github.com/raspberrypi/pico-bootrom/blob/master/bootrom/program_flash_generic.c
In theory, the function algorithm provides for erasing both a smaller "sector" (4096 bytes) and
an optional larger "block" (size and command provided in args). OpenOCD's spi.c only uses "block" sizes.
*/
err = rp2040_call_rom_func(bank->target, priv, priv->jump_flash_range_erase, args, ARRAY_SIZE(args));
return err;
}
/* -----------------------------------------------------------------------------
Driver probing etc */
static int rp2040_ssel_active(struct target *target, bool active)
{
const target_addr_t qspi_ctrl_addr = 0x4001800c;
const uint32_t qspi_ctrl_outover_low = 2UL << 8;
const uint32_t qspi_ctrl_outover_high = 3UL << 8;
uint32_t state = (active) ? qspi_ctrl_outover_low : qspi_ctrl_outover_high;
uint32_t val;
int err = target_read_u32(target, qspi_ctrl_addr, &val);
if (err != ERROR_OK)
return err;
val = (val & ~qspi_ctrl_outover_high) | state;
err = target_write_u32(target, qspi_ctrl_addr, val);
if (err != ERROR_OK)
return err;
return ERROR_OK;
}
static int rp2040_flash_probe(struct flash_bank *bank)
{
struct rp2040_flash_bank *priv = bank->driver_priv;
struct target *target = bank->target;
int err = rp2040_lookup_symbol(target, FUNC_DEBUG_TRAMPOLINE, &priv->jump_debug_trampoline);
if (err != ERROR_OK) {
LOG_ERROR("Debug trampoline not found in RP2040 ROM.");
return err;
}
priv->jump_debug_trampoline &= ~1u; /* mask off thumb bit */
err = rp2040_lookup_symbol(target, FUNC_DEBUG_TRAMPOLINE_END, &priv->jump_debug_trampoline_end);
if (err != ERROR_OK) {
LOG_ERROR("Debug trampoline end not found in RP2040 ROM.");
return err;
}
priv->jump_debug_trampoline_end &= ~1u; /* mask off thumb bit */
err = rp2040_lookup_symbol(target, FUNC_FLASH_EXIT_XIP, &priv->jump_flash_exit_xip);
if (err != ERROR_OK) {
LOG_ERROR("Function FUNC_FLASH_EXIT_XIP not found in RP2040 ROM.");
return err;
}
err = rp2040_lookup_symbol(target, FUNC_CONNECT_INTERNAL_FLASH, &priv->jump_connect_internal_flash);
if (err != ERROR_OK) {
LOG_ERROR("Function FUNC_CONNECT_INTERNAL_FLASH not found in RP2040 ROM.");
return err;
}
err = rp2040_lookup_symbol(target, FUNC_FLASH_RANGE_ERASE, &priv->jump_flash_range_erase);
if (err != ERROR_OK) {
LOG_ERROR("Function FUNC_FLASH_RANGE_ERASE not found in RP2040 ROM.");
return err;
}
err = rp2040_lookup_symbol(target, FUNC_FLASH_RANGE_PROGRAM, &priv->jump_flash_range_program);
if (err != ERROR_OK) {
LOG_ERROR("Function FUNC_FLASH_RANGE_PROGRAM not found in RP2040 ROM.");
return err;
}
err = rp2040_lookup_symbol(target, FUNC_FLASH_FLUSH_CACHE, &priv->jump_flush_cache);
if (err != ERROR_OK) {
LOG_ERROR("Function FUNC_FLASH_FLUSH_CACHE not found in RP2040 ROM.");
return err;
}
err = rp2040_lookup_symbol(target, FUNC_FLASH_ENTER_CMD_XIP, &priv->jump_enter_cmd_xip);
if (err != ERROR_OK) {
LOG_ERROR("Function FUNC_FLASH_ENTER_CMD_XIP not found in RP2040 ROM.");
return err;
}
err = stack_grab_and_prep(bank);
if (err != ERROR_OK)
return err;
uint32_t device_id = 0;
const target_addr_t ssi_dr0 = 0x18000060;
err = rp2040_ssel_active(target, true);
/* write RDID request into SPI peripheral's FIFO */
for (int count = 0; (count < 4) && (err == ERROR_OK); count++)
err = target_write_u32(target, ssi_dr0, SPIFLASH_READ_ID);
/* by this time, there is a receive FIFO entry for every write */
for (int count = 0; (count < 4) && (err == ERROR_OK); count++) {
uint32_t status;
err = target_read_u32(target, ssi_dr0, &status);
device_id >>= 8;
device_id |= (status & 0xFF) << 24;
}
device_id >>= 8;
err = rp2040_ssel_active(target, false);
if (err != ERROR_OK) {
LOG_ERROR("SSEL inactive failed");
return err;
}
/* search for a SPI flash Device ID match */
priv->dev = NULL;
for (const struct flash_device *p = flash_devices; p->name ; p++)
if (p->device_id == device_id) {
priv->dev = p;
break;
}
if (!priv->dev) {
LOG_ERROR("Unknown flash device (ID 0x%08" PRIx32 ")", device_id);
return ERROR_FAIL;
}
LOG_INFO("Found flash device \'%s\' (ID 0x%08" PRIx32 ")",
priv->dev->name, priv->dev->device_id);
/* the Boot ROM flash_range_program() routine requires page alignment */
bank->write_start_alignment = priv->dev->pagesize;
bank->write_end_alignment = priv->dev->pagesize;
bank->size = priv->dev->size_in_bytes;
bank->num_sectors = bank->size / priv->dev->sectorsize;
LOG_INFO("RP2040 B0 Flash Probe: %d bytes @" TARGET_ADDR_FMT ", in %d sectors\n",
bank->size, bank->base, bank->num_sectors);
bank->sectors = alloc_block_array(0, priv->dev->sectorsize, bank->num_sectors);
if (!bank->sectors)
return ERROR_FAIL;
if (err == ERROR_OK)
priv->probed = true;
return err;
}
static int rp2040_flash_auto_probe(struct flash_bank *bank)
{
struct rp2040_flash_bank *priv = bank->driver_priv;
if (priv->probed)
return ERROR_OK;
return rp2040_flash_probe(bank);
}
static void rp2040_flash_free_driver_priv(struct flash_bank *bank)
{
free(bank->driver_priv);
bank->driver_priv = NULL;
}
/* -----------------------------------------------------------------------------
Driver boilerplate */
FLASH_BANK_COMMAND_HANDLER(rp2040_flash_bank_command)
{
struct rp2040_flash_bank *priv;
priv = malloc(sizeof(struct rp2040_flash_bank));
priv->probed = false;
/* Set up driver_priv */
bank->driver_priv = priv;
return ERROR_OK;
}
struct flash_driver rp2040_flash = {
.name = "rp2040_flash",
.commands = NULL,
.flash_bank_command = rp2040_flash_bank_command,
.erase = rp2040_flash_erase,
.write = rp2040_flash_write,
.read = default_flash_read,
.probe = rp2040_flash_probe,
.auto_probe = rp2040_flash_auto_probe,
.erase_check = default_flash_blank_check,
.free_driver_priv = rp2040_flash_free_driver_priv
};

View File

@ -692,7 +692,7 @@ static int stm32x_probe(struct flash_bank *bank)
struct stm32x_flash_bank *stm32x_info = bank->driver_priv; struct stm32x_flash_bank *stm32x_info = bank->driver_priv;
uint16_t flash_size_in_kb; uint16_t flash_size_in_kb;
uint16_t max_flash_size_in_kb; uint16_t max_flash_size_in_kb;
uint32_t device_id; uint32_t dbgmcu_idcode;
int page_size; int page_size;
uint32_t base_address = 0x08000000; uint32_t base_address = 0x08000000;
@ -705,14 +705,17 @@ static int stm32x_probe(struct flash_bank *bank)
stm32x_info->default_rdp = 0xA5; stm32x_info->default_rdp = 0xA5;
/* read stm32 device id register */ /* read stm32 device id register */
int retval = stm32x_get_device_id(bank, &device_id); int retval = stm32x_get_device_id(bank, &dbgmcu_idcode);
if (retval != ERROR_OK) if (retval != ERROR_OK)
return retval; return retval;
LOG_INFO("device id = 0x%08" PRIx32 "", device_id); LOG_INFO("device id = 0x%08" PRIx32 "", dbgmcu_idcode);
uint16_t device_id = dbgmcu_idcode & 0xfff;
uint16_t rev_id = dbgmcu_idcode >> 16;
/* set page size, protection granularity and max flash size depending on family */ /* set page size, protection granularity and max flash size depending on family */
switch (device_id & 0xfff) { switch (device_id) {
case 0x440: /* stm32f05x */ case 0x440: /* stm32f05x */
page_size = 1024; page_size = 1024;
stm32x_info->ppage_size = 4; stm32x_info->ppage_size = 4;
@ -754,6 +757,25 @@ static int stm32x_probe(struct flash_bank *bank)
page_size = 1024; page_size = 1024;
stm32x_info->ppage_size = 4; stm32x_info->ppage_size = 4;
max_flash_size_in_kb = 128; max_flash_size_in_kb = 128;
/* GigaDevice GD32F1x0 & GD32F3x0 series devices share DEV_ID
with STM32F101/2/3 medium-density line,
however they use a REV_ID different from any STM32 device.
The main difference is another offset of user option bits
(like WDG_SW, nRST_STOP, nRST_STDBY) in option byte register
(FLASH_OBR/FMC_OBSTAT 0x4002201C).
This caused problems e.g. during flash block programming
because of unexpected active hardware watchog. */
switch (rev_id) {
case 0x1303: /* gd32f1x0 */
stm32x_info->user_data_offset = 16;
stm32x_info->option_offset = 6;
max_flash_size_in_kb = 64;
break;
case 0x1704: /* gd32f3x0 */
stm32x_info->user_data_offset = 16;
stm32x_info->option_offset = 6;
break;
}
break; break;
case 0x412: /* stm32f1x low-density */ case 0x412: /* stm32f1x low-density */
page_size = 1024; page_size = 1024;
@ -955,6 +977,14 @@ static int get_stm32x_info(struct flash_bank *bank, char *buf, int buf_size)
rev_str = "A"; rev_str = "A";
break; break;
case 0x1303: /* gd32f1x0 */
device_str = "GD32F1x0";
break;
case 0x1704: /* gd32f3x0 */
device_str = "GD32F3x0";
break;
case 0x2000: case 0x2000:
rev_str = "B"; rev_str = "B";
break; break;

View File

@ -1249,8 +1249,7 @@ static int flash_init_drivers(struct command_context *cmd_ctx)
if (!flash_bank_list()) if (!flash_bank_list())
return ERROR_OK; return ERROR_OK;
struct command *parent = command_find_in_context(cmd_ctx, "flash"); return register_commands(cmd_ctx, "flash", flash_exec_command_handlers);
return register_commands(cmd_ctx, parent, flash_exec_command_handlers);
} }
COMMAND_HANDLER(handle_flash_bank_command) COMMAND_HANDLER(handle_flash_bank_command)

File diff suppressed because it is too large Load Diff

View File

@ -26,6 +26,7 @@
#include <stdbool.h> #include <stdbool.h>
#include <jim-nvp.h> #include <jim-nvp.h>
#include <helper/list.h>
#include <helper/types.h> #include <helper/types.h>
/* To achieve C99 printf compatibility in MinGW, gnu_printf should be /* To achieve C99 printf compatibility in MinGW, gnu_printf should be
@ -41,6 +42,7 @@ enum command_mode {
COMMAND_EXEC, COMMAND_EXEC,
COMMAND_CONFIG, COMMAND_CONFIG,
COMMAND_ANY, COMMAND_ANY,
COMMAND_UNKNOWN = -1, /* error condition */
}; };
struct command_context; struct command_context;
@ -52,7 +54,6 @@ typedef int (*command_output_handler_t)(struct command_context *context,
struct command_context { struct command_context {
Jim_Interp *interp; Jim_Interp *interp;
enum command_mode mode; enum command_mode mode;
struct command *commands;
struct target *current_target; struct target *current_target;
/* The target set by 'targets xx' command or the latest created */ /* The target set by 'targets xx' command or the latest created */
struct target *current_target_override; struct target *current_target_override;
@ -64,6 +65,7 @@ struct command_context {
*/ */
command_output_handler_t output_handler; command_output_handler_t output_handler;
void *output_handler_priv; void *output_handler_priv;
struct list_head *help_list;
}; };
struct command; struct command;
@ -179,22 +181,24 @@ typedef __COMMAND_HANDLER((*command_handler_t));
struct command { struct command {
char *name; char *name;
char *help;
char *usage;
struct command *parent;
struct command *children;
command_handler_t handler; command_handler_t handler;
Jim_CmdProc *jim_handler; Jim_CmdProc *jim_handler;
void *jim_handler_data; void *jim_handler_data;
/* Currently used only for target of target-prefixed cmd. /* Command handlers can use it for any handler specific data */
* Native OpenOCD commands use jim_handler_data exclusively struct target *jim_override_target;
* as a target override. /* Used only for target of target-prefixed cmd */
* Jim handlers outside of target cmd tree can use
* jim_handler_data for any handler specific data */
enum command_mode mode; enum command_mode mode;
struct command *next;
}; };
/*
* Return the struct command pointer kept in private data
* Used to enforce check on data type
*/
static inline struct command *jim_to_command(Jim_Interp *interp)
{
return Jim_CmdPrivData(interp);
}
/* /*
* Commands should be registered by filling in one or more of these * Commands should be registered by filling in one or more of these
* structures and passing them to [un]register_commands(). * structures and passing them to [un]register_commands().
@ -233,6 +237,10 @@ struct command_registration {
/** Use this as the last entry in an array of command_registration records. */ /** Use this as the last entry in an array of command_registration records. */
#define COMMAND_REGISTRATION_DONE { .name = NULL, .chain = NULL } #define COMMAND_REGISTRATION_DONE { .name = NULL, .chain = NULL }
int __register_commands(struct command_context *cmd_ctx, const char *cmd_prefix,
const struct command_registration *cmds, void *data,
struct target *override_target);
/** /**
* Register one or more commands in the specified context, as children * Register one or more commands in the specified context, as children
* of @c parent (or top-level commends, if NULL). In a registration's * of @c parent (or top-level commends, if NULL). In a registration's
@ -241,37 +249,77 @@ struct command_registration {
* Otherwise, the chained commands are added as children of the command. * Otherwise, the chained commands are added as children of the command.
* *
* @param cmd_ctx The command_context in which to register the command. * @param cmd_ctx The command_context in which to register the command.
* @param parent Register this command as a child of this, or NULL to * @param cmd_prefix Register this command as a child of this, or NULL to
* register a top-level command. * register a top-level command.
* @param cmds Pointer to an array of command_registration records that * @param cmds Pointer to an array of command_registration records that
* contains the desired command parameters. The last record must have * contains the desired command parameters. The last record must have
* NULL for all fields. * NULL for all fields.
* @returns ERROR_OK on success; ERROR_FAIL if any registration fails. * @returns ERROR_OK on success; ERROR_FAIL if any registration fails.
*/ */
int register_commands(struct command_context *cmd_ctx, struct command *parent, static inline int register_commands(struct command_context *cmd_ctx, const char *cmd_prefix,
const struct command_registration *cmds); const struct command_registration *cmds)
{
return __register_commands(cmd_ctx, cmd_prefix, cmds, NULL, NULL);
}
/**
* Register one or more commands, as register_commands(), plus specify
* that command should override the current target
*
* @param cmd_ctx The command_context in which to register the command.
* @param cmd_prefix Register this command as a child of this, or NULL to
* register a top-level command.
* @param cmds Pointer to an array of command_registration records that
* contains the desired command parameters. The last record must have
* NULL for all fields.
* @param target The target that has to override current target.
* @returns ERROR_OK on success; ERROR_FAIL if any registration fails.
*/
static inline int register_commands_override_target(struct command_context *cmd_ctx,
const char *cmd_prefix, const struct command_registration *cmds,
struct target *target)
{
return __register_commands(cmd_ctx, cmd_prefix, cmds, NULL, target);
}
/**
* Register one or more commands, as register_commands(), plus specify
* a pointer to command private data that would be accessible through
* the macro CMD_DATA. The private data will not be freed when command
* is unregistered.
*
* @param cmd_ctx The command_context in which to register the command.
* @param cmd_prefix Register this command as a child of this, or NULL to
* register a top-level command.
* @param cmds Pointer to an array of command_registration records that
* contains the desired command parameters. The last record must have
* NULL for all fields.
* @param data The command private data.
* @returns ERROR_OK on success; ERROR_FAIL if any registration fails.
*/
static inline int register_commands_with_data(struct command_context *cmd_ctx,
const char *cmd_prefix, const struct command_registration *cmds,
void *data)
{
return __register_commands(cmd_ctx, cmd_prefix, cmds, data, NULL);
}
/** /**
* Unregisters all commands from the specified context. * Unregisters all commands from the specified context.
* @param cmd_ctx The context that will be cleared of registered commands. * @param cmd_ctx The context that will be cleared of registered commands.
* @param parent If given, only clear commands from under this one command. * @param cmd_prefix If given, only clear commands from under this one command.
* @returns ERROR_OK on success, or an error code. * @returns ERROR_OK on success, or an error code.
*/ */
int unregister_all_commands(struct command_context *cmd_ctx, int unregister_all_commands(struct command_context *cmd_ctx,
struct command *parent); const char *cmd_prefix);
struct command *command_find_in_context(struct command_context *cmd_ctx,
const char *name);
/** /**
* Update the private command data field for a command and all descendents. * Unregisters the help for all commands. Used at exit to remove the help
* This is used when creating a new hierarchy of commands that depends * added through the commands 'add_help_text' and 'add_usage_text'.
* on obtaining a dynamically created context. The value will be available * @param cmd_ctx The context that will be cleared of registered helps.
* in command handlers by using the CMD_DATA macro. * @returns ERROR_OK on success, or an error code.
* @param c The command (group) whose data pointer(s) will be updated.
* @param p The new data pointer to use for the command or its descendents.
*/ */
void command_set_handler_data(struct command *c, void *p); int help_del_all_commands(struct command_context *cmd_ctx);
void command_set_output_handler(struct command_context *context, void command_set_output_handler(struct command_context *context,
command_output_handler_t output_handler, void *priv); command_output_handler_t output_handler, void *priv);
@ -408,6 +456,4 @@ COMMAND_HELPER(handle_command_parse_bool, bool *out, const char *label);
#define COMMAND_PARSE_ENABLE(in, out) \ #define COMMAND_PARSE_ENABLE(in, out) \
COMMAND_PARSE_BOOL(in, out, "enable", "disable") COMMAND_PARSE_BOOL(in, out, "enable", "disable")
void script_debug(Jim_Interp *interp, unsigned int argc, Jim_Obj * const *argv);
#endif /* OPENOCD_HELPER_COMMAND_H */ #endif /* OPENOCD_HELPER_COMMAND_H */

View File

@ -333,9 +333,3 @@ const char *Jim_Debug_ArgvString(Jim_Interp *interp, int argc, Jim_Obj *const *a
return Jim_String(debug_string_obj); return Jim_String(debug_string_obj);
} }
int Jim_nvpInit(Jim_Interp *interp)
{
/* This is really a helper library, not an extension, but this is the easy way */
return JIM_OK;
}

View File

@ -242,13 +242,13 @@ static inline int socket_select(int max_fd,
typedef uint32_t Elf32_Addr; typedef uint32_t Elf32_Addr;
typedef uint16_t Elf32_Half; typedef uint16_t Elf32_Half;
typedef uint32_t Elf32_Off; typedef uint32_t Elf32_Off;
typedef int32_t Elf32_Sword;
typedef uint32_t Elf32_Word; typedef uint32_t Elf32_Word;
typedef uint32_t Elf32_Size; typedef uint32_t Elf32_Size;
typedef Elf32_Off Elf32_Hashelt;
#define EI_NIDENT 16
typedef struct { typedef struct {
unsigned char e_ident[16]; /* Magic number and other info */ unsigned char e_ident[EI_NIDENT]; /* Magic number and other info */
Elf32_Half e_type; /* Object file type */ Elf32_Half e_type; /* Object file type */
Elf32_Half e_machine; /* Architecture */ Elf32_Half e_machine; /* Architecture */
Elf32_Word e_version; /* Object file version */ Elf32_Word e_version; /* Object file version */
@ -290,6 +290,44 @@ typedef struct {
#endif /* HAVE_ELF_H */ #endif /* HAVE_ELF_H */
#ifndef HAVE_ELF64
typedef uint64_t Elf64_Addr;
typedef uint16_t Elf64_Half;
typedef uint64_t Elf64_Off;
typedef uint32_t Elf64_Word;
typedef uint64_t Elf64_Xword;
typedef struct {
unsigned char e_ident[EI_NIDENT]; /* Magic number and other info */
Elf64_Half e_type; /* Object file type */
Elf64_Half e_machine; /* Architecture */
Elf64_Word e_version; /* Object file version */
Elf64_Addr e_entry; /* Entry point virtual address */
Elf64_Off e_phoff; /* Program header table file offset */
Elf64_Off e_shoff; /* Section header table file offset */
Elf64_Word e_flags; /* Processor-specific flags */
Elf64_Half e_ehsize; /* ELF header size in bytes */
Elf64_Half e_phentsize; /* Program header table entry size */
Elf64_Half e_phnum; /* Program header table entry count */
Elf64_Half e_shentsize; /* Section header table entry size */
Elf64_Half e_shnum; /* Section header table entry count */
Elf64_Half e_shstrndx; /* Section header string table index */
} Elf64_Ehdr;
typedef struct {
Elf64_Word p_type; /* Segment type */
Elf64_Word p_flags; /* Segment flags */
Elf64_Off p_offset; /* Segment file offset */
Elf64_Addr p_vaddr; /* Segment virtual address */
Elf64_Addr p_paddr; /* Segment physical address */
Elf64_Xword p_filesz; /* Segment size in file */
Elf64_Xword p_memsz; /* Segment size in memory */
Elf64_Xword p_align; /* Segment alignment */
} Elf64_Phdr;
#endif /* HAVE_ELF64 */
#if defined HAVE_LIBUSB1 && !defined HAVE_LIBUSB_ERROR_NAME #if defined HAVE_LIBUSB1 && !defined HAVE_LIBUSB_ERROR_NAME
const char *libusb_error_name(int error_code); const char *libusb_error_name(int error_code);
#endif /* defined HAVE_LIBUSB1 && !defined HAVE_LIBUSB_ERROR_NAME */ #endif /* defined HAVE_LIBUSB1 && !defined HAVE_LIBUSB_ERROR_NAME */

View File

@ -21,6 +21,15 @@
#ifndef OPENOCD_HELPER_SYSTEM_H #ifndef OPENOCD_HELPER_SYSTEM_H
#define OPENOCD_HELPER_SYSTEM_H #define OPENOCD_HELPER_SYSTEM_H
/* +++ platform specific headers +++ */
#ifdef _WIN32
#include <winsock2.h>
#include <ws2tcpip.h>
#include <sys/types.h>
#include <sys/stat.h>
#endif
/* --- platform specific headers --- */
/* standard C library header files */ /* standard C library header files */
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
@ -34,15 +43,6 @@
#include <sys/time.h> #include <sys/time.h>
#endif #endif
/* +++ platform specific headers +++ */
#ifdef _WIN32
#include <winsock2.h>
#include <ws2tcpip.h>
#include <sys/types.h>
#include <sys/stat.h>
#endif
/* --- platform specific headers --- */
#ifdef HAVE_SYS_SOCKET_H #ifdef HAVE_SYS_SOCKET_H
#include <sys/socket.h> #include <sys/socket.h>
#endif #endif

View File

@ -47,16 +47,10 @@
#ifndef __cplusplus #ifndef __cplusplus
#define false 0 #define false 0
#define true 1 #define true 1
typedef int _Bool;
#else
typedef bool _Bool;
#endif /* __cplusplus */ #endif /* __cplusplus */
#endif /* HAVE__BOOL */ #endif /* HAVE__BOOL */
#define bool _Bool
#endif /* HAVE_STDBOOL_H */ #endif /* HAVE_STDBOOL_H */
/// turns a macro argument into a string constant /// turns a macro argument into a string constant

View File

@ -19,6 +19,8 @@
#include "config.h" #include "config.h"
#endif #endif
#include <helper/system.h>
#ifdef _WIN32 #ifdef _WIN32
#include <windows.h> #include <windows.h>
#else #else

View File

@ -256,9 +256,8 @@ static int jim_aice_arp_init_reset(Jim_Interp *interp, int argc, Jim_Obj * const
e = aice_init_reset(context); e = aice_init_reset(context);
if (e != ERROR_OK) { if (e != ERROR_OK) {
Jim_Obj *eObj = Jim_NewIntObj(goi.interp, e); Jim_Obj *obj = Jim_NewIntObj(goi.interp, e);
Jim_SetResultFormatted(goi.interp, "error: %#s", eObj); Jim_SetResultFormatted(goi.interp, "error: %#s", obj);
Jim_FreeNewObj(goi.interp, eObj);
return JIM_ERR; return JIM_ERR;
} }
return JIM_OK; return JIM_OK;

View File

@ -19,6 +19,7 @@
#include "config.h" #include "config.h"
#endif #endif
#include <helper/system.h>
#include <jtag/drivers/libusb_helper.h> #include <jtag/drivers/libusb_helper.h>
#include <helper/log.h> #include <helper/log.h>
#include <helper/time_support.h> #include <helper/time_support.h>
@ -350,8 +351,8 @@ static void aice_unpack_dthmb(uint8_t *cmd_ack_code, uint8_t *target_id,
/* calls the given usb_bulk_* function, allowing for the data to /* calls the given usb_bulk_* function, allowing for the data to
* trickle in with some timeouts */ * trickle in with some timeouts */
static int usb_bulk_with_retries( static int usb_bulk_with_retries(
int (*f)(libusb_device_handle *, int, char *, int, int, int *), int (*f)(struct libusb_device_handle *, int, char *, int, int, int *),
libusb_device_handle *dev, int ep, struct libusb_device_handle *dev, int ep,
char *bytes, int size, int timeout, int *transferred) char *bytes, int size, int timeout, int *transferred)
{ {
int tries = 3, count = 0; int tries = 3, count = 0;
@ -370,7 +371,7 @@ static int usb_bulk_with_retries(
return ERROR_OK; return ERROR_OK;
} }
static int wrap_usb_bulk_write(libusb_device_handle *dev, int ep, static int wrap_usb_bulk_write(struct libusb_device_handle *dev, int ep,
char *buff, int size, int timeout, int *transferred) char *buff, int size, int timeout, int *transferred)
{ {
@ -380,7 +381,7 @@ static int wrap_usb_bulk_write(libusb_device_handle *dev, int ep,
return 0; return 0;
} }
static inline int usb_bulk_write_ex(libusb_device_handle *dev, int ep, static inline int usb_bulk_write_ex(struct libusb_device_handle *dev, int ep,
char *bytes, int size, int timeout) char *bytes, int size, int timeout)
{ {
int tr = 0; int tr = 0;

View File

@ -137,6 +137,7 @@ static bool swd_mode;
/* CMSIS-DAP SWD Commands */ /* CMSIS-DAP SWD Commands */
#define CMD_DAP_SWD_CONFIGURE 0x13 #define CMD_DAP_SWD_CONFIGURE 0x13
#define CMD_DAP_SWD_SEQUENCE 0x1D
/* CMSIS-DAP JTAG Commands */ /* CMSIS-DAP JTAG Commands */
#define CMD_DAP_JTAG_SEQ 0x14 #define CMD_DAP_JTAG_SEQ 0x14
@ -222,6 +223,8 @@ static uint8_t output_pins = SWJ_PIN_SRST | SWJ_PIN_TRST;
static struct cmsis_dap *cmsis_dap_handle; static struct cmsis_dap *cmsis_dap_handle;
static int cmsis_dap_quit(void);
static int cmsis_dap_open(void) static int cmsis_dap_open(void)
{ {
const struct cmsis_dap_backend *backend = NULL; const struct cmsis_dap_backend *backend = NULL;
@ -280,6 +283,21 @@ static void cmsis_dap_close(struct cmsis_dap *dap)
} }
} }
static void cmsis_dap_flush_read(struct cmsis_dap *dap)
{
unsigned int i;
/* Some CMSIS-DAP adapters keep buffered packets over
* USB close/open so we need to flush up to 64 old packets
* to be sure all buffers are empty */
for (i = 0; i < 64; i++) {
int retval = dap->backend->read(dap, 10);
if (retval == ERROR_TIMEOUT_REACHED)
break;
}
if (i)
LOG_DEBUG("Flushed %u packets", i);
}
/* Send a message and receive the reply */ /* Send a message and receive the reply */
static int cmsis_dap_xfer(struct cmsis_dap *dap, int txlen) static int cmsis_dap_xfer(struct cmsis_dap *dap, int txlen)
{ {
@ -293,6 +311,7 @@ static int cmsis_dap_xfer(struct cmsis_dap *dap, int txlen)
pending_fifo_get_idx = 0; pending_fifo_get_idx = 0;
} }
uint8_t current_cmd = cmsis_dap_handle->command[0];
int retval = dap->backend->write(dap, txlen, USB_TIMEOUT); int retval = dap->backend->write(dap, txlen, USB_TIMEOUT);
if (retval < 0) if (retval < 0)
return retval; return retval;
@ -302,6 +321,20 @@ static int cmsis_dap_xfer(struct cmsis_dap *dap, int txlen)
if (retval < 0) if (retval < 0)
return retval; return retval;
uint8_t *resp = cmsis_dap_handle->response;
if (resp[0] == DAP_ERROR) {
LOG_ERROR("CMSIS-DAP command 0x%" PRIx8 " not implemented", current_cmd);
return ERROR_NOT_IMPLEMENTED;
}
if (resp[0] != current_cmd) {
LOG_ERROR("CMSIS-DAP command mismatch. Sent 0x%" PRIx8
" received 0x%" PRIx8, current_cmd, resp[0]);
cmsis_dap_flush_read(dap);
return ERROR_FAIL;
}
return ERROR_OK; return ERROR_OK;
} }
@ -511,6 +544,45 @@ static int cmsis_dap_cmd_DAP_Delay(uint16_t delay_us)
} }
#endif #endif
static int cmsis_dap_metacmd_targetsel(uint32_t instance_id)
{
int retval;
uint8_t *command = cmsis_dap_handle->command;
const uint32_t SEQ_RD = 0x80, SEQ_WR = 0x00;
/* SWD multi-drop requires a transfer ala CMD_DAP_TFER,
but with no expectation of an SWD ACK response. In
CMSIS-DAP v1.20 and v2.00, CMD_DAP_SWD_SEQUENCE was
added to allow this special sequence to be generated.
The purpose of this operation is to select the target
corresponding to the instance_id that is written */
size_t idx = 0;
command[idx++] = CMD_DAP_SWD_SEQUENCE;
command[idx++] = 3; /* sequence count */
/* sequence 0: packet request for TARGETSEL */
command[idx++] = SEQ_WR | 8;
command[idx++] = SWD_CMD_START | swd_cmd(false, false, DP_TARGETSEL) | SWD_CMD_STOP | SWD_CMD_PARK;
/* sequence 1: read Trn ACK Trn, no expectation for target to ACK */
command[idx++] = SEQ_RD | 5;
/* sequence 2: WDATA plus parity */
command[idx++] = SEQ_WR | (32 + 1);
h_u32_to_le(command + idx, instance_id);
idx += 4;
command[idx++] = parity_u32(instance_id);
retval = cmsis_dap_xfer(cmsis_dap_handle, idx);
if (retval != ERROR_OK || cmsis_dap_handle->response[1] != DAP_OK) {
LOG_ERROR("CMSIS-DAP command SWD_Sequence failed.");
return ERROR_JTAG_DEVICE_ERROR;
}
return ERROR_OK;
}
static void cmsis_dap_swd_write_from_queue(struct cmsis_dap *dap) static void cmsis_dap_swd_write_from_queue(struct cmsis_dap *dap)
{ {
uint8_t *command = cmsis_dap_handle->command; uint8_t *command = cmsis_dap_handle->command;
@ -606,6 +678,13 @@ static void cmsis_dap_swd_read_process(struct cmsis_dap *dap, int timeout_ms)
} }
uint8_t *resp = dap->response; uint8_t *resp = dap->response;
if (resp[0] != CMD_DAP_TFER) {
LOG_ERROR("CMSIS-DAP command mismatch. Expected 0x%" PRIx8
" received 0x%" PRIx8, CMD_DAP_TFER, resp[0]);
queued_retval = ERROR_FAIL;
goto skip;
}
uint8_t transfer_count = resp[1]; uint8_t transfer_count = resp[1];
uint8_t ack = resp[2] & 0x07; uint8_t ack = resp[2] & 0x07;
if (resp[2] & 0x08) { if (resp[2] & 0x08) {
@ -617,6 +696,7 @@ static void cmsis_dap_swd_read_process(struct cmsis_dap *dap, int timeout_ms)
LOG_DEBUG("SWD ack not OK @ %d %s", transfer_count, LOG_DEBUG("SWD ack not OK @ %d %s", transfer_count,
ack == SWD_ACK_WAIT ? "WAIT" : ack == SWD_ACK_FAULT ? "FAULT" : "JUNK"); ack == SWD_ACK_WAIT ? "WAIT" : ack == SWD_ACK_FAULT ? "FAULT" : "JUNK");
queued_retval = ack == SWD_ACK_WAIT ? ERROR_WAIT : ERROR_FAIL; queued_retval = ack == SWD_ACK_WAIT ? ERROR_WAIT : ERROR_FAIL;
/* TODO: use results of transfers completed before the error occurred? */
goto skip; goto skip;
} }
@ -676,7 +756,10 @@ static int cmsis_dap_swd_run_queue(void)
static void cmsis_dap_swd_queue_cmd(uint8_t cmd, uint32_t *dst, uint32_t data) static void cmsis_dap_swd_queue_cmd(uint8_t cmd, uint32_t *dst, uint32_t data)
{ {
if (pending_fifo[pending_fifo_put_idx].transfer_count == pending_queue_len) { bool targetsel_cmd = swd_cmd(false, false, DP_TARGETSEL) == cmd;
if (pending_fifo[pending_fifo_put_idx].transfer_count == pending_queue_len
|| targetsel_cmd) {
if (pending_fifo_block_count) if (pending_fifo_block_count)
cmsis_dap_swd_read_process(cmsis_dap_handle, 0); cmsis_dap_swd_read_process(cmsis_dap_handle, 0);
@ -690,6 +773,11 @@ static void cmsis_dap_swd_queue_cmd(uint8_t cmd, uint32_t *dst, uint32_t data)
if (queued_retval != ERROR_OK) if (queued_retval != ERROR_OK)
return; return;
if (targetsel_cmd) {
cmsis_dap_metacmd_targetsel(data);
return;
}
struct pending_request_block *block = &pending_fifo[pending_fifo_put_idx]; struct pending_request_block *block = &pending_fifo[pending_fifo_put_idx];
struct pending_transfer_result *transfer = &(block->transfers[block->transfer_count]); struct pending_transfer_result *transfer = &(block->transfers[block->transfer_count]);
transfer->data = data; transfer->data = data;
@ -807,7 +895,7 @@ static int cmsis_dap_swd_switch_seq(enum swd_special_seq seq)
switch (seq) { switch (seq) {
case LINE_RESET: case LINE_RESET:
LOG_DEBUG("SWD line reset"); LOG_DEBUG_IO("SWD line reset");
s = swd_seq_line_reset; s = swd_seq_line_reset;
s_len = swd_seq_line_reset_len; s_len = swd_seq_line_reset_len;
break; break;
@ -816,11 +904,26 @@ static int cmsis_dap_swd_switch_seq(enum swd_special_seq seq)
s = swd_seq_jtag_to_swd; s = swd_seq_jtag_to_swd;
s_len = swd_seq_jtag_to_swd_len; s_len = swd_seq_jtag_to_swd_len;
break; break;
case JTAG_TO_DORMANT:
LOG_DEBUG("JTAG-to-DORMANT");
s = swd_seq_jtag_to_dormant;
s_len = swd_seq_jtag_to_dormant_len;
break;
case SWD_TO_JTAG: case SWD_TO_JTAG:
LOG_DEBUG("SWD-to-JTAG"); LOG_DEBUG("SWD-to-JTAG");
s = swd_seq_swd_to_jtag; s = swd_seq_swd_to_jtag;
s_len = swd_seq_swd_to_jtag_len; s_len = swd_seq_swd_to_jtag_len;
break; break;
case SWD_TO_DORMANT:
LOG_DEBUG("SWD-to-DORMANT");
s = swd_seq_swd_to_dormant;
s_len = swd_seq_swd_to_dormant_len;
break;
case DORMANT_TO_SWD:
LOG_DEBUG("DORMANT-to-SWD");
s = swd_seq_dormant_to_swd;
s_len = swd_seq_dormant_to_swd_len;
break;
default: default:
LOG_ERROR("Sequence %d not supported", seq); LOG_ERROR("Sequence %d not supported", seq);
return ERROR_FAIL; return ERROR_FAIL;
@ -863,6 +966,8 @@ static int cmsis_dap_init(void)
if (retval != ERROR_OK) if (retval != ERROR_OK)
return retval; return retval;
cmsis_dap_flush_read(cmsis_dap_handle);
retval = cmsis_dap_get_caps_info(); retval = cmsis_dap_get_caps_info();
if (retval != ERROR_OK) if (retval != ERROR_OK)
return retval; return retval;
@ -901,7 +1006,7 @@ static int cmsis_dap_init(void)
/* INFO_ID_PKT_SZ - short */ /* INFO_ID_PKT_SZ - short */
retval = cmsis_dap_cmd_DAP_Info(INFO_ID_PKT_SZ, &data); retval = cmsis_dap_cmd_DAP_Info(INFO_ID_PKT_SZ, &data);
if (retval != ERROR_OK) if (retval != ERROR_OK)
return retval; goto init_err;
if (data[0] == 2) { /* short */ if (data[0] == 2) { /* short */
uint16_t pkt_sz = data[1] + (data[2] << 8); uint16_t pkt_sz = data[1] + (data[2] << 8);
@ -915,7 +1020,7 @@ static int cmsis_dap_init(void)
free(cmsis_dap_handle->packet_buffer); free(cmsis_dap_handle->packet_buffer);
retval = cmsis_dap_handle->backend->packet_buffer_alloc(cmsis_dap_handle, pkt_sz); retval = cmsis_dap_handle->backend->packet_buffer_alloc(cmsis_dap_handle, pkt_sz);
if (retval != ERROR_OK) if (retval != ERROR_OK)
return retval; goto init_err;
LOG_DEBUG("CMSIS-DAP: Packet Size = %" PRIu16, pkt_sz); LOG_DEBUG("CMSIS-DAP: Packet Size = %" PRIu16, pkt_sz);
} }
@ -924,7 +1029,7 @@ static int cmsis_dap_init(void)
/* INFO_ID_PKT_CNT - byte */ /* INFO_ID_PKT_CNT - byte */
retval = cmsis_dap_cmd_DAP_Info(INFO_ID_PKT_CNT, &data); retval = cmsis_dap_cmd_DAP_Info(INFO_ID_PKT_CNT, &data);
if (retval != ERROR_OK) if (retval != ERROR_OK)
return retval; goto init_err;
if (data[0] == 1) { /* byte */ if (data[0] == 1) { /* byte */
int pkt_cnt = data[1]; int pkt_cnt = data[1];
@ -939,43 +1044,40 @@ static int cmsis_dap_init(void)
pending_fifo[i].transfers = malloc(pending_queue_len * sizeof(struct pending_transfer_result)); pending_fifo[i].transfers = malloc(pending_queue_len * sizeof(struct pending_transfer_result));
if (!pending_fifo[i].transfers) { if (!pending_fifo[i].transfers) {
LOG_ERROR("Unable to allocate memory for CMSIS-DAP queue"); LOG_ERROR("Unable to allocate memory for CMSIS-DAP queue");
return ERROR_FAIL; retval = ERROR_FAIL;
goto init_err;
} }
} }
/* Intentionally not checked for error, just logs an info message
retval = cmsis_dap_get_status(); * not vital for further debugging */
if (retval != ERROR_OK) (void)cmsis_dap_get_status();
return ERROR_FAIL;
/* Now try to connect to the target /* Now try to connect to the target
* TODO: This is all SWD only @ present */ * TODO: This is all SWD only @ present */
retval = cmsis_dap_cmd_DAP_SWJ_Clock(jtag_get_speed_khz()); retval = cmsis_dap_cmd_DAP_SWJ_Clock(jtag_get_speed_khz());
if (retval != ERROR_OK) if (retval != ERROR_OK)
return ERROR_FAIL; goto init_err;
/* Ask CMSIS-DAP to automatically retry on receiving WAIT for /* Ask CMSIS-DAP to automatically retry on receiving WAIT for
* up to 64 times. This must be changed to 0 if sticky * up to 64 times. This must be changed to 0 if sticky
* overrun detection is enabled. */ * overrun detection is enabled. */
retval = cmsis_dap_cmd_DAP_TFER_Configure(0, 64, 0); retval = cmsis_dap_cmd_DAP_TFER_Configure(0, 64, 0);
if (retval != ERROR_OK) if (retval != ERROR_OK)
return ERROR_FAIL; goto init_err;
if (swd_mode) { if (swd_mode) {
/* Data Phase (bit 2) must be set to 1 if sticky overrun /* Data Phase (bit 2) must be set to 1 if sticky overrun
* detection is enabled */ * detection is enabled */
retval = cmsis_dap_cmd_DAP_SWD_Configure(0); /* 1 TRN, no Data Phase */ retval = cmsis_dap_cmd_DAP_SWD_Configure(0); /* 1 TRN, no Data Phase */
if (retval != ERROR_OK) if (retval != ERROR_OK)
return ERROR_FAIL; goto init_err;
} }
/* Both LEDs on */ /* Both LEDs on */
retval = cmsis_dap_cmd_DAP_LED(LED_ID_CONNECT, LED_ON); /* Intentionally not checked for error, debugging will work
if (retval != ERROR_OK) * without LEDs */
return ERROR_FAIL; (void)cmsis_dap_cmd_DAP_LED(LED_ID_CONNECT, LED_ON);
(void)cmsis_dap_cmd_DAP_LED(LED_ID_RUN, LED_ON);
retval = cmsis_dap_cmd_DAP_LED(LED_ID_RUN, LED_ON);
if (retval != ERROR_OK)
return ERROR_FAIL;
/* support connecting with srst asserted */ /* support connecting with srst asserted */
enum reset_types jtag_reset_config = jtag_get_reset_config(); enum reset_types jtag_reset_config = jtag_get_reset_config();
@ -984,13 +1086,16 @@ static int cmsis_dap_init(void)
if (jtag_reset_config & RESET_SRST_NO_GATING) { if (jtag_reset_config & RESET_SRST_NO_GATING) {
retval = cmsis_dap_cmd_DAP_SWJ_Pins(0, SWJ_PIN_SRST, 0, NULL); retval = cmsis_dap_cmd_DAP_SWJ_Pins(0, SWJ_PIN_SRST, 0, NULL);
if (retval != ERROR_OK) if (retval != ERROR_OK)
return ERROR_FAIL; goto init_err;
LOG_INFO("Connecting under reset"); LOG_INFO("Connecting under reset");
} }
} }
LOG_INFO("CMSIS-DAP: Interface ready"); LOG_INFO("CMSIS-DAP: Interface ready");
return ERROR_OK; return ERROR_OK;
init_err:
cmsis_dap_quit();
return retval;
} }
static int cmsis_dap_swd_init(void) static int cmsis_dap_swd_init(void)

View File

@ -35,6 +35,7 @@
#include "config.h" #include "config.h"
#endif #endif
#include <helper/system.h>
#include <libusb.h> #include <libusb.h>
#include <helper/log.h> #include <helper/log.h>
#include <helper/replacements.h> #include <helper/replacements.h>
@ -42,8 +43,8 @@
#include "cmsis_dap.h" #include "cmsis_dap.h"
struct cmsis_dap_backend_data { struct cmsis_dap_backend_data {
libusb_context *usb_ctx; struct libusb_context *usb_ctx;
libusb_device_handle *dev_handle; struct libusb_device_handle *dev_handle;
unsigned int ep_out; unsigned int ep_out;
unsigned int ep_in; unsigned int ep_in;
int interface; int interface;
@ -57,8 +58,8 @@ static int cmsis_dap_usb_alloc(struct cmsis_dap *dap, unsigned int pkt_sz);
static int cmsis_dap_usb_open(struct cmsis_dap *dap, uint16_t vids[], uint16_t pids[], char *serial) static int cmsis_dap_usb_open(struct cmsis_dap *dap, uint16_t vids[], uint16_t pids[], char *serial)
{ {
int err; int err;
libusb_context *ctx; struct libusb_context *ctx;
libusb_device **device_list; struct libusb_device **device_list;
err = libusb_init(&ctx); err = libusb_init(&ctx);
if (err) { if (err) {
@ -74,7 +75,7 @@ static int cmsis_dap_usb_open(struct cmsis_dap *dap, uint16_t vids[], uint16_t p
} }
for (int i = 0; i < num_devices; i++) { for (int i = 0; i < num_devices; i++) {
libusb_device *dev = device_list[i]; struct libusb_device *dev = device_list[i];
struct libusb_device_descriptor dev_desc; struct libusb_device_descriptor dev_desc;
err = libusb_get_device_descriptor(dev, &dev_desc); err = libusb_get_device_descriptor(dev, &dev_desc);
@ -102,7 +103,7 @@ static int cmsis_dap_usb_open(struct cmsis_dap *dap, uint16_t vids[], uint16_t p
if (dev_desc.iSerialNumber == 0 && serial && serial[0]) if (dev_desc.iSerialNumber == 0 && serial && serial[0])
continue; continue;
libusb_device_handle *dev_handle = NULL; struct libusb_device_handle *dev_handle = NULL;
err = libusb_open(dev, &dev_handle); err = libusb_open(dev, &dev_handle);
if (err) { if (err) {
/* It's to be expected that most USB devices can't be opened /* It's to be expected that most USB devices can't be opened

View File

@ -35,6 +35,7 @@
#include "config.h" #include "config.h"
#endif #endif
#include <string.h>
#include <hidapi.h> #include <hidapi.h>
#include <helper/log.h> #include <helper/log.h>

View File

@ -547,7 +547,7 @@ static void ftdi_execute_scan(struct jtag_command *cmd)
uint8_t last_bit = 0; uint8_t last_bit = 0;
if (field->out_value) if (field->out_value)
bit_copy(&last_bit, 0, field->out_value, field->num_bits - 1, 1); bit_copy(&last_bit, 0, field->out_value, field->num_bits - 1, 1);
uint8_t tms_bits = 0x01; uint8_t tms_bits = 0x03;
DO_CLOCK_TMS_CS(mpsse_ctx, DO_CLOCK_TMS_CS(mpsse_ctx,
&tms_bits, &tms_bits,
0, 0,
@ -557,13 +557,24 @@ static void ftdi_execute_scan(struct jtag_command *cmd)
last_bit, last_bit,
ftdi_jtag_mode); ftdi_jtag_mode);
tap_set_state(tap_state_transition(tap_get_state(), 1)); tap_set_state(tap_state_transition(tap_get_state(), 1));
DO_CLOCK_TMS_CS_OUT(mpsse_ctx, if (tap_get_end_state() == TAP_IDLE) {
&tms_bits, DO_CLOCK_TMS_CS_OUT(mpsse_ctx,
1, &tms_bits,
1, 1,
last_bit, 2,
ftdi_jtag_mode); last_bit,
tap_set_state(tap_state_transition(tap_get_state(), 0)); ftdi_jtag_mode);
tap_set_state(tap_state_transition(tap_get_state(), 1));
tap_set_state(tap_state_transition(tap_get_state(), 0));
} else {
DO_CLOCK_TMS_CS_OUT(mpsse_ctx,
&tms_bits,
2,
1,
last_bit,
ftdi_jtag_mode);
tap_set_state(tap_state_transition(tap_get_state(), 0));
}
} else } else
DO_CLOCK_DATA(mpsse_ctx, DO_CLOCK_DATA(mpsse_ctx,
field->out_value, field->out_value,

View File

@ -31,7 +31,7 @@
#define MAX_USB_PORTS 7 #define MAX_USB_PORTS 7
static struct libusb_context *jtag_libusb_context; /**< Libusb context **/ static struct libusb_context *jtag_libusb_context; /**< Libusb context **/
static libusb_device **devs; /**< The usb device list **/ static struct libusb_device **devs; /**< The usb device list **/
static int jtag_libusb_error(int err) static int jtag_libusb_error(int err)
{ {
@ -71,7 +71,7 @@ static bool jtag_libusb_match_ids(struct libusb_device_descriptor *dev_desc,
} }
#ifdef HAVE_LIBUSB_GET_PORT_NUMBERS #ifdef HAVE_LIBUSB_GET_PORT_NUMBERS
static bool jtag_libusb_location_equal(libusb_device *device) static bool jtag_libusb_location_equal(struct libusb_device *device)
{ {
uint8_t port_path[MAX_USB_PORTS]; uint8_t port_path[MAX_USB_PORTS];
uint8_t dev_bus; uint8_t dev_bus;
@ -88,7 +88,7 @@ static bool jtag_libusb_location_equal(libusb_device *device)
return jtag_usb_location_equal(dev_bus, port_path, path_len); return jtag_usb_location_equal(dev_bus, port_path, path_len);
} }
#else /* HAVE_LIBUSB_GET_PORT_NUMBERS */ #else /* HAVE_LIBUSB_GET_PORT_NUMBERS */
static bool jtag_libusb_location_equal(libusb_device *device) static bool jtag_libusb_location_equal(struct libusb_device *device)
{ {
return true; return true;
} }
@ -96,7 +96,7 @@ static bool jtag_libusb_location_equal(libusb_device *device)
/* Returns true if the string descriptor indexed by str_index in device matches string */ /* Returns true if the string descriptor indexed by str_index in device matches string */
static bool string_descriptor_equal(libusb_device_handle *device, uint8_t str_index, static bool string_descriptor_equal(struct libusb_device_handle *device, uint8_t str_index,
const char *string) const char *string)
{ {
int retval; int retval;
@ -123,7 +123,7 @@ static bool string_descriptor_equal(libusb_device_handle *device, uint8_t str_in
return matched; return matched;
} }
static bool jtag_libusb_match_serial(libusb_device_handle *device, static bool jtag_libusb_match_serial(struct libusb_device_handle *device,
struct libusb_device_descriptor *dev_desc, const char *serial, struct libusb_device_descriptor *dev_desc, const char *serial,
adapter_get_alternate_serial_fn adapter_get_alternate_serial) adapter_get_alternate_serial_fn adapter_get_alternate_serial)
{ {

View File

@ -24,7 +24,7 @@
/* this callback should return a non NULL value only when the serial could not /* this callback should return a non NULL value only when the serial could not
* be retrieved by the standard 'libusb_get_string_descriptor_ascii' */ * be retrieved by the standard 'libusb_get_string_descriptor_ascii' */
typedef char * (*adapter_get_alternate_serial_fn)(libusb_device_handle *device, typedef char * (*adapter_get_alternate_serial_fn)(struct libusb_device_handle *device,
struct libusb_device_descriptor *dev_desc); struct libusb_device_descriptor *dev_desc);
int jtag_libusb_open(const uint16_t vids[], const uint16_t pids[], int jtag_libusb_open(const uint16_t vids[], const uint16_t pids[],

View File

@ -63,8 +63,8 @@
#define SIO_RESET_PURGE_TX 2 #define SIO_RESET_PURGE_TX 2
struct mpsse_ctx { struct mpsse_ctx {
libusb_context *usb_ctx; struct libusb_context *usb_ctx;
libusb_device_handle *usb_dev; struct libusb_device_handle *usb_dev;
unsigned int usb_write_timeout; unsigned int usb_write_timeout;
unsigned int usb_read_timeout; unsigned int usb_read_timeout;
uint8_t in_ep; uint8_t in_ep;
@ -86,7 +86,7 @@ struct mpsse_ctx {
}; };
/* Returns true if the string descriptor indexed by str_index in device matches string */ /* Returns true if the string descriptor indexed by str_index in device matches string */
static bool string_descriptor_equal(libusb_device_handle *device, uint8_t str_index, static bool string_descriptor_equal(struct libusb_device_handle *device, uint8_t str_index,
const char *string) const char *string)
{ {
int retval; int retval;
@ -100,7 +100,7 @@ static bool string_descriptor_equal(libusb_device_handle *device, uint8_t str_in
return strncmp(string, desc_string, sizeof(desc_string)) == 0; return strncmp(string, desc_string, sizeof(desc_string)) == 0;
} }
static bool device_location_equal(libusb_device *device, const char *location) static bool device_location_equal(struct libusb_device *device, const char *location)
{ {
bool result = false; bool result = false;
#ifdef HAVE_LIBUSB_GET_PORT_NUMBERS #ifdef HAVE_LIBUSB_GET_PORT_NUMBERS
@ -162,7 +162,7 @@ static bool device_location_equal(libusb_device *device, const char *location)
static bool open_matching_device(struct mpsse_ctx *ctx, const uint16_t *vid, const uint16_t *pid, static bool open_matching_device(struct mpsse_ctx *ctx, const uint16_t *vid, const uint16_t *pid,
const char *product, const char *serial, const char *location) const char *product, const char *serial, const char *location)
{ {
libusb_device **list; struct libusb_device **list;
struct libusb_device_descriptor desc; struct libusb_device_descriptor desc;
struct libusb_config_descriptor *config0; struct libusb_config_descriptor *config0;
int err; int err;
@ -172,7 +172,7 @@ static bool open_matching_device(struct mpsse_ctx *ctx, const uint16_t *vid, con
LOG_ERROR("libusb_get_device_list() failed with %s", libusb_error_name(cnt)); LOG_ERROR("libusb_get_device_list() failed with %s", libusb_error_name(cnt));
for (ssize_t i = 0; i < cnt; i++) { for (ssize_t i = 0; i < cnt; i++) {
libusb_device *device = list[i]; struct libusb_device *device = list[i];
err = libusb_get_device_descriptor(device, &desc); err = libusb_get_device_descriptor(device, &desc);
if (err != LIBUSB_SUCCESS) { if (err != LIBUSB_SUCCESS) {

View File

@ -35,7 +35,6 @@
static char *remote_bitbang_host; static char *remote_bitbang_host;
static char *remote_bitbang_port; static char *remote_bitbang_port;
static FILE *remote_bitbang_file;
static int remote_bitbang_fd; static int remote_bitbang_fd;
/* Circular buffer. When start == end, the buffer is empty. */ /* Circular buffer. When start == end, the buffer is empty. */
@ -65,7 +64,7 @@ static int remote_bitbang_fill_buf(void)
contiguous_available_space = remote_bitbang_start - contiguous_available_space = remote_bitbang_start -
remote_bitbang_end - 1; remote_bitbang_end - 1;
} }
ssize_t count = read(remote_bitbang_fd, ssize_t count = read_socket(remote_bitbang_fd,
remote_bitbang_buf + remote_bitbang_end, remote_bitbang_buf + remote_bitbang_end,
contiguous_available_space); contiguous_available_space);
if (count > 0) { if (count > 0) {
@ -75,11 +74,14 @@ static int remote_bitbang_fill_buf(void)
} else if (count == 0) { } else if (count == 0) {
return ERROR_OK; return ERROR_OK;
} else if (count < 0) { } else if (count < 0) {
#ifdef _WIN32
if (WSAGetLastError() == WSAEWOULDBLOCK) {
#else
if (errno == EAGAIN) { if (errno == EAGAIN) {
#endif
return ERROR_OK; return ERROR_OK;
} else { } else {
LOG_ERROR("remote_bitbang_fill_buf: %s (%d)", log_socket_error("remote_bitbang_fill_buf");
strerror(errno), errno);
return ERROR_FAIL; return ERROR_FAIL;
} }
} }
@ -90,8 +92,10 @@ static int remote_bitbang_fill_buf(void)
static int remote_bitbang_putc(int c) static int remote_bitbang_putc(int c)
{ {
if (EOF == fputc(c, remote_bitbang_file)) { char buf = c;
LOG_ERROR("remote_bitbang_putc: %s", strerror(errno)); ssize_t count = write_socket(remote_bitbang_fd, &buf, sizeof(buf));
if (count < 0) {
log_socket_error("remote_bitbang_putc");
return ERROR_FAIL; return ERROR_FAIL;
} }
return ERROR_OK; return ERROR_OK;
@ -99,20 +103,11 @@ static int remote_bitbang_putc(int c)
static int remote_bitbang_quit(void) static int remote_bitbang_quit(void)
{ {
if (EOF == fputc('Q', remote_bitbang_file)) { if (remote_bitbang_putc('Q') == ERROR_FAIL)
LOG_ERROR("fputs: %s", strerror(errno));
return ERROR_FAIL; return ERROR_FAIL;
}
if (EOF == fflush(remote_bitbang_file)) { if (close_socket(remote_bitbang_fd) != 0) {
LOG_ERROR("fflush: %s", strerror(errno)); log_socket_error("close_socket");
return ERROR_FAIL;
}
/* We only need to close one of the FILE*s, because they both use the same */
/* underlying file descriptor. */
if (EOF == fclose(remote_bitbang_file)) {
LOG_ERROR("fclose: %s", strerror(errno));
return ERROR_FAIL; return ERROR_FAIL;
} }
@ -140,21 +135,16 @@ static bb_value_t char_to_int(int c)
/* Get the next read response. */ /* Get the next read response. */
static bb_value_t remote_bitbang_rread(void) static bb_value_t remote_bitbang_rread(void)
{ {
if (EOF == fflush(remote_bitbang_file)) {
remote_bitbang_quit();
LOG_ERROR("fflush: %s", strerror(errno));
return BB_ERROR;
}
/* Enable blocking access. */ /* Enable blocking access. */
socket_block(remote_bitbang_fd); socket_block(remote_bitbang_fd);
char c; char c;
ssize_t count = read(remote_bitbang_fd, &c, 1); ssize_t count = read_socket(remote_bitbang_fd, &c, 1);
if (count == 1) { if (count == 1) {
return char_to_int(c); return char_to_int(c);
} else { } else {
remote_bitbang_quit(); remote_bitbang_quit();
LOG_ERROR("read: count=%d, error=%s", (int) count, strerror(errno)); LOG_ERROR("read_socket: count=%d", (int) count);
log_socket_error("read_socket");
return BB_ERROR; return BB_ERROR;
} }
} }
@ -240,7 +230,7 @@ static int remote_bitbang_init_tcp(void)
freeaddrinfo(result); /* No longer needed */ freeaddrinfo(result); /* No longer needed */
if (rp == NULL) { /* No address succeeded */ if (rp == NULL) { /* No address succeeded */
LOG_ERROR("Failed to connect: %s", strerror(errno)); log_socket_error("Failed to connect");
return ERROR_FAIL; return ERROR_FAIL;
} }
@ -257,7 +247,7 @@ static int remote_bitbang_init_unix(void)
LOG_INFO("Connecting to unix socket %s", remote_bitbang_host); LOG_INFO("Connecting to unix socket %s", remote_bitbang_host);
int fd = socket(PF_UNIX, SOCK_STREAM, 0); int fd = socket(PF_UNIX, SOCK_STREAM, 0);
if (fd < 0) { if (fd < 0) {
LOG_ERROR("socket: %s", strerror(errno)); log_socket_error("socket");
return ERROR_FAIL; return ERROR_FAIL;
} }
@ -267,7 +257,7 @@ static int remote_bitbang_init_unix(void)
addr.sun_path[sizeof(addr.sun_path)-1] = '\0'; addr.sun_path[sizeof(addr.sun_path)-1] = '\0';
if (connect(fd, (struct sockaddr *)&addr, sizeof(struct sockaddr_un)) < 0) { if (connect(fd, (struct sockaddr *)&addr, sizeof(struct sockaddr_un)) < 0) {
LOG_ERROR("connect: %s", strerror(errno)); log_socket_error("connect");
return ERROR_FAIL; return ERROR_FAIL;
} }
@ -290,13 +280,6 @@ static int remote_bitbang_init(void)
if (remote_bitbang_fd < 0) if (remote_bitbang_fd < 0)
return remote_bitbang_fd; return remote_bitbang_fd;
remote_bitbang_file = fdopen(remote_bitbang_fd, "w+");
if (remote_bitbang_file == NULL) {
LOG_ERROR("fdopen: failed to open write stream");
close(remote_bitbang_fd);
return ERROR_FAIL;
}
LOG_INFO("remote_bitbang driver initialized"); LOG_INFO("remote_bitbang driver initialized");
return ERROR_OK; return ERROR_OK;
} }

View File

@ -97,14 +97,14 @@
#define ST7_PC_TDO ST7_PC_IO9 #define ST7_PC_TDO ST7_PC_IO9
#define ST7_PA_DBGACK ST7_PA_IO10 #define ST7_PA_DBGACK ST7_PA_IO10
static libusb_device_handle *pHDev; static struct libusb_device_handle *pHDev;
/* /*
* ep1 commands are up to USB_EP1OUT_SIZE bytes in length. * ep1 commands are up to USB_EP1OUT_SIZE bytes in length.
* This function takes care of zeroing the unused bytes before sending the packet. * This function takes care of zeroing the unused bytes before sending the packet.
* Any reply packet is not handled by this function. * Any reply packet is not handled by this function.
*/ */
static int ep1_generic_commandl(libusb_device_handle *pHDev_param, size_t length, ...) static int ep1_generic_commandl(struct libusb_device_handle *pHDev_param, size_t length, ...)
{ {
uint8_t usb_buffer[USB_EP1OUT_SIZE]; uint8_t usb_buffer[USB_EP1OUT_SIZE];
uint8_t *usb_buffer_p; uint8_t *usb_buffer_p;
@ -144,7 +144,7 @@ static int ep1_generic_commandl(libusb_device_handle *pHDev_param, size_t length
#if 0 #if 0
static ssize_t ep1_memory_read( static ssize_t ep1_memory_read(
libusb_device_handle *pHDev_param, uint16_t addr, struct libusb_device_handle *pHDev_param, uint16_t addr,
size_t length, uint8_t *buffer) size_t length, uint8_t *buffer)
{ {
uint8_t usb_buffer[USB_EP1OUT_SIZE]; uint8_t usb_buffer[USB_EP1OUT_SIZE];
@ -203,7 +203,7 @@ static ssize_t ep1_memory_read(
} }
#endif #endif
static ssize_t ep1_memory_write(libusb_device_handle *pHDev_param, uint16_t addr, static ssize_t ep1_memory_write(struct libusb_device_handle *pHDev_param, uint16_t addr,
size_t length, uint8_t const *buffer) size_t length, uint8_t const *buffer)
{ {
uint8_t usb_buffer[USB_EP1OUT_SIZE]; uint8_t usb_buffer[USB_EP1OUT_SIZE];
@ -259,7 +259,7 @@ static ssize_t ep1_memory_write(libusb_device_handle *pHDev_param, uint16_t addr
#if 0 #if 0
static ssize_t ep1_memory_writel(libusb_device_handle *pHDev_param, uint16_t addr, static ssize_t ep1_memory_writel(struct libusb_device_handle *pHDev_param, uint16_t addr,
size_t length, ...) size_t length, ...)
{ {
uint8_t buffer[USB_EP1OUT_SIZE - 4]; uint8_t buffer[USB_EP1OUT_SIZE - 4];
@ -296,7 +296,7 @@ static ssize_t ep1_memory_writel(libusb_device_handle *pHDev_param, uint16_t add
static uint8_t dtc_entry_download; static uint8_t dtc_entry_download;
/* The buffer is specially formatted to represent a valid image to load into the DTC. */ /* The buffer is specially formatted to represent a valid image to load into the DTC. */
static int dtc_load_from_buffer(libusb_device_handle *pHDev_param, const uint8_t *buffer, static int dtc_load_from_buffer(struct libusb_device_handle *pHDev_param, const uint8_t *buffer,
size_t length) size_t length)
{ {
struct header_s { struct header_s {
@ -470,7 +470,7 @@ static int dtc_start_download(void)
} }
static int dtc_run_download( static int dtc_run_download(
libusb_device_handle *pHDev_param, struct libusb_device_handle *pHDev_param,
uint8_t *command_buffer, uint8_t *command_buffer,
int command_buffer_size, int command_buffer_size,
uint8_t *reply_buffer, uint8_t *reply_buffer,

View File

@ -3017,7 +3017,7 @@ static int stlink_close(void *handle)
* based on the length (0x1a = 26) we could easily decide if we have to fixup the serial * based on the length (0x1a = 26) we could easily decide if we have to fixup the serial
* and then we have just to convert the raw data into printable characters using sprintf * and then we have just to convert the raw data into printable characters using sprintf
*/ */
static char *stlink_usb_get_alternate_serial(libusb_device_handle *device, static char *stlink_usb_get_alternate_serial(struct libusb_device_handle *device,
struct libusb_device_descriptor *dev_desc) struct libusb_device_descriptor *dev_desc)
{ {
int usb_retval; int usb_retval;

View File

@ -267,7 +267,7 @@ static int ulink_usb_open(struct ulink **device)
{ {
ssize_t num_devices, i; ssize_t num_devices, i;
bool found; bool found;
libusb_device **usb_devices; struct libusb_device **usb_devices;
struct libusb_device_descriptor usb_desc; struct libusb_device_descriptor usb_desc;
struct libusb_device_handle *usb_device_handle; struct libusb_device_handle *usb_device_handle;

View File

@ -19,11 +19,12 @@
#include "config.h" #include "config.h"
#endif #endif
#include "versaloon_include.h"
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include <libusb.h> #include <libusb.h>
#include "versaloon_include.h"
#include "versaloon.h" #include "versaloon.h"
#include "versaloon_internal.h" #include "versaloon_internal.h"
#include "usbtoxxx/usbtoxxx.h" #include "usbtoxxx/usbtoxxx.h"
@ -35,7 +36,7 @@ uint16_t versaloon_buf_size;
struct versaloon_pending_t versaloon_pending[VERSALOON_MAX_PENDING_NUMBER]; struct versaloon_pending_t versaloon_pending[VERSALOON_MAX_PENDING_NUMBER];
uint16_t versaloon_pending_idx; uint16_t versaloon_pending_idx;
libusb_device_handle *versaloon_usb_device_handle; struct libusb_device_handle *versaloon_usb_device_handle;
static uint32_t versaloon_usb_to = VERSALOON_TIMEOUT; static uint32_t versaloon_usb_to = VERSALOON_TIMEOUT;
static RESULT versaloon_init(void); static RESULT versaloon_init(void);

View File

@ -107,6 +107,6 @@ struct versaloon_interface_t {
}; };
extern struct versaloon_interface_t versaloon_interface; extern struct versaloon_interface_t versaloon_interface;
extern libusb_device_handle *versaloon_usb_device_handle; extern struct libusb_device_handle *versaloon_usb_device_handle;
#endif /* OPENOCD_JTAG_DRIVERS_VERSALOON_VERSALOON_H */ #endif /* OPENOCD_JTAG_DRIVERS_VERSALOON_VERSALOON_H */

View File

@ -18,6 +18,7 @@
#ifndef OPENOCD_JTAG_DRIVERS_VERSALOON_VERSALOON_INCLUDE_H #ifndef OPENOCD_JTAG_DRIVERS_VERSALOON_VERSALOON_INCLUDE_H
#define OPENOCD_JTAG_DRIVERS_VERSALOON_VERSALOON_INCLUDE_H #define OPENOCD_JTAG_DRIVERS_VERSALOON_VERSALOON_INCLUDE_H
#include "helper/system.h"
/* This file is used to include different header and macros */ /* This file is used to include different header and macros */
/* according to different platform */ /* according to different platform */
#include <jtag/interface.h> #include <jtag/interface.h>

View File

@ -812,7 +812,7 @@ static int vsllink_check_usb_strings(
static int vsllink_usb_open(struct vsllink *vsllink) static int vsllink_usb_open(struct vsllink *vsllink)
{ {
ssize_t num_devices, i; ssize_t num_devices, i;
libusb_device **usb_devices; struct libusb_device **usb_devices;
struct libusb_device_descriptor usb_desc; struct libusb_device_descriptor usb_desc;
struct libusb_device_handle *usb_device_handle; struct libusb_device_handle *usb_device_handle;
int retval; int retval;
@ -823,7 +823,7 @@ static int vsllink_usb_open(struct vsllink *vsllink)
return ERROR_FAIL; return ERROR_FAIL;
for (i = 0; i < num_devices; i++) { for (i = 0; i < num_devices; i++) {
libusb_device *device = usb_devices[i]; struct libusb_device *device = usb_devices[i];
retval = libusb_get_device_descriptor(device, &usb_desc); retval = libusb_get_device_descriptor(device, &usb_desc);
if (retval != 0) if (retval != 0)

View File

@ -213,8 +213,8 @@ struct scan_result {
struct xds110_info { struct xds110_info {
/* USB connection handles and data buffers */ /* USB connection handles and data buffers */
libusb_context *ctx; struct libusb_context *ctx;
libusb_device_handle *dev; struct libusb_device_handle *dev;
unsigned char read_payload[USB_PAYLOAD_SIZE]; unsigned char read_payload[USB_PAYLOAD_SIZE];
unsigned char write_packet[3]; unsigned char write_packet[3];
unsigned char write_payload[USB_PAYLOAD_SIZE]; unsigned char write_payload[USB_PAYLOAD_SIZE];
@ -317,9 +317,9 @@ static inline uint16_t xds110_get_u16(uint8_t *buffer)
static bool usb_connect(void) static bool usb_connect(void)
{ {
libusb_context *ctx = NULL; struct libusb_context *ctx = NULL;
libusb_device **list = NULL; struct libusb_device **list = NULL;
libusb_device_handle *dev = NULL; struct libusb_device_handle *dev = NULL;
struct libusb_device_descriptor desc; struct libusb_device_descriptor desc;

View File

@ -108,8 +108,6 @@ static int Jim_Command_drscan(Jim_Interp *interp, int argc, Jim_Obj *const *args
endstate = TAP_IDLE; endstate = TAP_IDLE;
script_debug(interp, argc, args);
/* validate arguments as numbers */ /* validate arguments as numbers */
e = JIM_OK; e = JIM_OK;
for (i = 2; i < argc; i += 2) { for (i = 2; i < argc; i += 2) {
@ -234,8 +232,6 @@ static int Jim_Command_pathmove(Jim_Interp *interp, int argc, Jim_Obj *const *ar
return JIM_ERR; return JIM_ERR;
} }
script_debug(interp, argc, args);
int i; int i;
for (i = 0; i < argc-1; i++) { for (i = 0; i < argc-1; i++) {
const char *cp; const char *cp;
@ -266,8 +262,6 @@ static int Jim_Command_pathmove(Jim_Interp *interp, int argc, Jim_Obj *const *ar
static int Jim_Command_flush_count(Jim_Interp *interp, int argc, Jim_Obj *const *args) static int Jim_Command_flush_count(Jim_Interp *interp, int argc, Jim_Obj *const *args)
{ {
script_debug(interp, argc, args);
Jim_SetResult(interp, Jim_NewIntObj(interp, jtag_get_flush_queue_count())); Jim_SetResult(interp, Jim_NewIntObj(interp, jtag_get_flush_queue_count()));
return JIM_OK; return JIM_OK;
@ -693,10 +687,8 @@ static int jim_jtag_arp_init(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
struct command_context *context = current_command_context(interp); struct command_context *context = current_command_context(interp);
int e = jtag_init_inner(context); int e = jtag_init_inner(context);
if (e != ERROR_OK) { if (e != ERROR_OK) {
Jim_Obj *eObj = Jim_NewIntObj(goi.interp, e); Jim_Obj *obj = Jim_NewIntObj(goi.interp, e);
Jim_IncrRefCount(eObj); Jim_SetResultFormatted(goi.interp, "error: %#s", obj);
Jim_SetResultFormatted(goi.interp, "error: %#s", eObj);
Jim_DecrRefCount(goi.interp, eObj);
return JIM_ERR; return JIM_ERR;
} }
return JIM_OK; return JIM_OK;
@ -718,10 +710,8 @@ static int jim_jtag_arp_init_reset(Jim_Interp *interp, int argc, Jim_Obj *const
e = swd_init_reset(context); e = swd_init_reset(context);
if (e != ERROR_OK) { if (e != ERROR_OK) {
Jim_Obj *eObj = Jim_NewIntObj(goi.interp, e); Jim_Obj *obj = Jim_NewIntObj(goi.interp, e);
Jim_IncrRefCount(eObj); Jim_SetResultFormatted(goi.interp, "error: %#s", obj);
Jim_SetResultFormatted(goi.interp, "error: %#s", eObj);
Jim_DecrRefCount(goi.interp, eObj);
return JIM_ERR; return JIM_ERR;
} }
return JIM_OK; return JIM_OK;
@ -767,7 +757,8 @@ static bool jtag_tap_disable(struct jtag_tap *t)
int jim_jtag_tap_enabler(Jim_Interp *interp, int argc, Jim_Obj *const *argv) int jim_jtag_tap_enabler(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{ {
const char *cmd_name = Jim_GetString(argv[0], NULL); struct command *c = jim_to_command(interp);
const char *cmd_name = c->name;
Jim_GetOptInfo goi; Jim_GetOptInfo goi;
Jim_GetOpt_Setup(&goi, interp, argc-1, argv + 1); Jim_GetOpt_Setup(&goi, interp, argc-1, argv + 1);
if (goi.argc != 1) { if (goi.argc != 1) {
@ -804,7 +795,8 @@ int jim_jtag_tap_enabler(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
int jim_jtag_configure(Jim_Interp *interp, int argc, Jim_Obj *const *argv) int jim_jtag_configure(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{ {
const char *cmd_name = Jim_GetString(argv[0], NULL); struct command *c = jim_to_command(interp);
const char *cmd_name = c->name;
Jim_GetOptInfo goi; Jim_GetOptInfo goi;
Jim_GetOpt_Setup(&goi, interp, argc-1, argv + 1); Jim_GetOpt_Setup(&goi, interp, argc-1, argv + 1);
goi.isconfigure = !strcmp(cmd_name, "configure"); goi.isconfigure = !strcmp(cmd_name, "configure");

View File

@ -361,6 +361,7 @@ int openocd_main(int argc, char *argv[])
server_free(); server_free();
unregister_all_commands(cmd_ctx, NULL); unregister_all_commands(cmd_ctx, NULL);
help_del_all_commands(cmd_ctx);
/* free all DAP and CTI objects */ /* free all DAP and CTI objects */
dap_cleanup_all(); dap_cleanup_all();

View File

@ -188,8 +188,7 @@ static int pld_init(struct command_context *cmd_ctx)
if (!pld_devices) if (!pld_devices)
return ERROR_OK; return ERROR_OK;
struct command *parent = command_find_in_context(cmd_ctx, "pld"); return register_commands(cmd_ctx, "pld", pld_exec_command_handlers);
return register_commands(cmd_ctx, parent, pld_exec_command_handlers);
} }
COMMAND_HANDLER(handle_pld_init_command) COMMAND_HANDLER(handle_pld_init_command)

View File

@ -81,7 +81,7 @@ static int cortex_m_stacking(struct rtos *rtos, const struct rtos_register_stack
int cm4_fpu_enabled = 0; int cm4_fpu_enabled = 0;
struct armv7m_common *armv7m_target = target_to_armv7m(rtos->target); struct armv7m_common *armv7m_target = target_to_armv7m(rtos->target);
if (is_armv7m(armv7m_target)) { if (is_armv7m(armv7m_target)) {
if (armv7m_target->fp_feature == FPv4_SP) { if (armv7m_target->fp_feature == FPV4_SP) {
/* Found ARM v7m target which includes a FPU */ /* Found ARM v7m target which includes a FPU */
uint32_t cpacr; uint32_t cpacr;

View File

@ -350,7 +350,7 @@ static int nuttx_get_thread_reg_list(struct rtos *rtos, int64_t thread_id,
bool cm4_fpu_enabled = false; bool cm4_fpu_enabled = false;
struct armv7m_common *armv7m_target = target_to_armv7m(rtos->target); struct armv7m_common *armv7m_target = target_to_armv7m(rtos->target);
if (is_armv7m(armv7m_target)) { if (is_armv7m(armv7m_target)) {
if (armv7m_target->fp_feature == FPv4_SP) { if (armv7m_target->fp_feature == FPV4_SP) {
/* Found ARM v7m target which includes a FPU */ /* Found ARM v7m target which includes a FPU */
uint32_t cpacr; uint32_t cpacr;

View File

@ -29,6 +29,7 @@
#include "telnet_server.h" #include "telnet_server.h"
#include <target/target_request.h> #include <target/target_request.h>
#include <helper/configuration.h> #include <helper/configuration.h>
#include <helper/list.h>
static char *telnet_port; static char *telnet_port;
@ -58,6 +59,13 @@ static int telnet_write(struct connection *connection, const void *data,
return ERROR_SERVER_REMOTE_CLOSED; return ERROR_SERVER_REMOTE_CLOSED;
} }
/* output an audible bell */
static int telnet_bell(struct connection *connection)
{
/* ("\a" does not work, at least on windows) */
return telnet_write(connection, "\x07", 1);
}
static int telnet_prompt(struct connection *connection) static int telnet_prompt(struct connection *connection)
{ {
struct telnet_connection *t_con = connection->priv; struct telnet_connection *t_con = connection->priv;
@ -366,6 +374,217 @@ static void telnet_move_cursor(struct connection *connection, size_t pos)
tc->line_cursor = pos; tc->line_cursor = pos;
} }
/* check buffer size leaving one spare character for string null termination */
static inline bool telnet_can_insert(struct connection *connection, size_t len)
{
struct telnet_connection *t_con = connection->priv;
return t_con->line_size + len < TELNET_LINE_MAX_SIZE;
}
/* write to telnet console, and update the telnet_connection members
* this function is capable of inserting in the middle of a line
* please ensure that data does not contain special characters (\n, \r, \t, \b ...)
*
* returns false when it fails to insert the requested data
*/
static bool telnet_insert(struct connection *connection, const void *data, size_t len)
{
struct telnet_connection *t_con = connection->priv;
if (!telnet_can_insert(connection, len)) {
telnet_bell(connection);
return false;
}
if (t_con->line_cursor < t_con->line_size) {
/* we have some content after the cursor */
memmove(t_con->line + t_con->line_cursor + len,
t_con->line + t_con->line_cursor,
t_con->line_size - t_con->line_cursor);
}
strncpy(t_con->line + t_con->line_cursor, data, len);
telnet_write(connection,
t_con->line + t_con->line_cursor,
t_con->line_size + len - t_con->line_cursor);
t_con->line_size += len;
t_con->line_cursor += len;
for (size_t i = t_con->line_cursor; i < t_con->line_size; i++)
telnet_write(connection, "\b", 1);
return true;
}
static void telnet_auto_complete(struct connection *connection)
{
struct telnet_connection *t_con = connection->priv;
struct command_context *command_context = connection->cmd_ctx;
struct cmd_match {
char *cmd;
struct list_head lh;
};
LIST_HEAD(matches);
/* user command sequence, either at line beginning
* or we start over after these characters ';', '[', '{' */
size_t seq_start = (t_con->line_cursor == 0) ? 0 : (t_con->line_cursor - 1);
while (seq_start > 0) {
char c = t_con->line[seq_start];
if (c == ';' || c == '[' || c == '{') {
seq_start++;
break;
}
seq_start--;
}
/* user command position in the line, ignore leading spaces */
size_t usr_cmd_pos = seq_start;
while ((usr_cmd_pos < t_con->line_cursor) && isspace(t_con->line[usr_cmd_pos]))
usr_cmd_pos++;
/* user command length */
size_t usr_cmd_len = t_con->line_cursor - usr_cmd_pos;
/* optimize multiple spaces in the user command,
* because info commands does not tolerate multiple spaces */
size_t optimized_spaces = 0;
char query[usr_cmd_len + 1];
for (size_t i = 0; i < usr_cmd_len; i++) {
if ((i < usr_cmd_len - 1) && isspace(t_con->line[usr_cmd_pos + i])
&& isspace(t_con->line[usr_cmd_pos + i + 1])) {
optimized_spaces++;
continue;
}
query[i - optimized_spaces] = t_con->line[usr_cmd_pos + i];
}
usr_cmd_len -= optimized_spaces;
query[usr_cmd_len] = '\0';
/* filter commands */
char *query_cmd = alloc_printf("lsort [info commands {%s*}]", query);
if (!query_cmd) {
LOG_ERROR("Out of memory");
return;
}
int retval = Jim_EvalSource(command_context->interp, __FILE__, __LINE__, query_cmd);
free(query_cmd);
if (retval != JIM_OK)
return;
Jim_Obj *list = Jim_GetResult(command_context->interp);
Jim_IncrRefCount(list);
/* common prefix length of the matched commands */
size_t common_len = 0;
char *first_match = NULL; /* used to compute the common prefix length */
int len = Jim_ListLength(command_context->interp, list);
for (int i = 0; i < len; i++) {
Jim_Obj *elem = Jim_ListGetIndex(command_context->interp, list, i);
Jim_IncrRefCount(elem);
char *name = (char *)Jim_GetString(elem, NULL);
/* validate the command */
bool ignore_cmd = false;
Jim_Cmd *jim_cmd = Jim_GetCommand(command_context->interp, elem, JIM_NONE);
if (!jim_cmd)
ignore_cmd = true;
else {
if (!jim_cmd->isproc) {
/* ignore commands without handler
* and those with COMMAND_CONFIG mode */
/* FIXME it's better to use jimcmd_is_ocd_command(jim_cmd)
* or command_find_from_name(command_context->interp, name) */
struct command *cmd = jim_cmd->u.native.privData;
if (!cmd)
ignore_cmd = true;
/* make Valgrind happy by checking that cmd is not NULL */
else if (cmd != NULL && !cmd->handler && !cmd->jim_handler)
ignore_cmd = true;
else if (cmd != NULL && cmd->mode == COMMAND_CONFIG)
ignore_cmd = true;
}
}
/* save the command in the prediction list */
if (!ignore_cmd) {
struct cmd_match *match = calloc(1, sizeof(struct cmd_match));
if (!match) {
LOG_ERROR("Out of memory");
Jim_DecrRefCount(command_context->interp, elem);
break; /* break the for loop */
}
if (list_empty(&matches)) {
common_len = strlen(name);
first_match = name;
} else {
size_t new_common_len = usr_cmd_len; /* save some loops */
while (new_common_len < common_len && first_match[new_common_len] == name[new_common_len])
new_common_len++;
common_len = new_common_len;
}
match->cmd = name;
list_add_tail(&match->lh, &matches);
}
Jim_DecrRefCount(command_context->interp, elem);
}
/* end of command filtering */
/* proceed with auto-completion */
if (list_empty(&matches))
telnet_bell(connection);
else if (common_len == usr_cmd_len && list_is_singular(&matches) && t_con->line_cursor == t_con->line_size)
telnet_insert(connection, " ", 1);
else if (common_len > usr_cmd_len) {
int completion_size = common_len - usr_cmd_len;
if (telnet_insert(connection, first_match + usr_cmd_len, completion_size)) {
/* in bash this extra space is only added when the cursor in at the end of line */
if (list_is_singular(&matches) && t_con->line_cursor == t_con->line_size)
telnet_insert(connection, " ", 1);
}
} else if (!list_is_singular(&matches)) {
telnet_write(connection, "\n\r", 2);
struct cmd_match *match;
list_for_each_entry(match, &matches, lh) {
telnet_write(connection, match->cmd, strlen(match->cmd));
telnet_write(connection, "\n\r", 2);
}
telnet_prompt(connection);
telnet_write(connection, t_con->line, t_con->line_size);
/* restore the terminal visible cursor location */
for (size_t i = t_con->line_cursor; i < t_con->line_size; i++)
telnet_write(connection, "\b", 1);
}
/* destroy the command_list */
struct cmd_match *tmp, *match;
list_for_each_entry_safe(match, tmp, &matches, lh)
free(match);
Jim_DecrRefCount(command_context->interp, list);
}
static int telnet_input(struct connection *connection) static int telnet_input(struct connection *connection)
{ {
int bytes_read; int bytes_read;
@ -391,30 +610,7 @@ static int telnet_input(struct connection *connection)
t_con->state = TELNET_STATE_IAC; t_con->state = TELNET_STATE_IAC;
else { else {
if (isprint(*buf_p)) { /* printable character */ if (isprint(*buf_p)) { /* printable character */
/* watch buffer size leaving one spare character for telnet_insert(connection, buf_p, 1);
* string null termination */
if (t_con->line_size == TELNET_LINE_MAX_SIZE-1) {
/* output audible bell if buffer is full
* "\a" does not work, at least on windows */
telnet_write(connection, "\x07", 1);
} else if (t_con->line_cursor == t_con->line_size) {
telnet_write(connection, buf_p, 1);
t_con->line[t_con->line_size++] = *buf_p;
t_con->line_cursor++;
} else {
size_t i;
memmove(t_con->line + t_con->line_cursor + 1,
t_con->line + t_con->line_cursor,
t_con->line_size - t_con->line_cursor);
t_con->line[t_con->line_cursor] = *buf_p;
t_con->line_size++;
telnet_write(connection,
t_con->line + t_con->line_cursor,
t_con->line_size - t_con->line_cursor);
t_con->line_cursor++;
for (i = t_con->line_cursor; i < t_con->line_size; i++)
telnet_write(connection, "\b", 1);
}
} else { /* non-printable */ } else { /* non-printable */
if (*buf_p == 0x1b) { /* escape */ if (*buf_p == 0x1b) { /* escape */
t_con->state = TELNET_STATE_ESCAPE; t_con->state = TELNET_STATE_ESCAPE;
@ -548,7 +744,9 @@ static int telnet_input(struct connection *connection)
t_con->line[t_con->line_cursor] = '\0'; t_con->line[t_con->line_cursor] = '\0';
t_con->line_size = t_con->line_cursor; t_con->line_size = t_con->line_cursor;
} }
} else } else if (*buf_p == '\t')
telnet_auto_complete(connection);
else
LOG_DEBUG("unhandled nonprintable: %2.2x", *buf_p); LOG_DEBUG("unhandled nonprintable: %2.2x", *buf_p);
} }
} }

View File

@ -133,6 +133,7 @@ static int aarch64_mmu_modify(struct target *target, int enable)
struct aarch64_common *aarch64 = target_to_aarch64(target); struct aarch64_common *aarch64 = target_to_aarch64(target);
struct armv8_common *armv8 = &aarch64->armv8_common; struct armv8_common *armv8 = &aarch64->armv8_common;
int retval = ERROR_OK; int retval = ERROR_OK;
enum arm_mode target_mode = ARM_MODE_ANY;
uint32_t instr = 0; uint32_t instr = 0;
if (enable) { if (enable) {
@ -158,6 +159,8 @@ static int aarch64_mmu_modify(struct target *target, int enable)
switch (armv8->arm.core_mode) { switch (armv8->arm.core_mode) {
case ARMV8_64_EL0T: case ARMV8_64_EL0T:
target_mode = ARMV8_64_EL1H;
/* fall through */
case ARMV8_64_EL1T: case ARMV8_64_EL1T:
case ARMV8_64_EL1H: case ARMV8_64_EL1H:
instr = ARMV8_MSR_GP(SYSTEM_SCTLR_EL1, 0); instr = ARMV8_MSR_GP(SYSTEM_SCTLR_EL1, 0);
@ -184,9 +187,15 @@ static int aarch64_mmu_modify(struct target *target, int enable)
LOG_DEBUG("unknown cpu state 0x%x", armv8->arm.core_mode); LOG_DEBUG("unknown cpu state 0x%x", armv8->arm.core_mode);
break; break;
} }
if (target_mode != ARM_MODE_ANY)
armv8_dpm_modeswitch(&armv8->dpm, target_mode);
retval = armv8->dpm.instr_write_data_r0(&armv8->dpm, instr, retval = armv8->dpm.instr_write_data_r0(&armv8->dpm, instr,
aarch64->system_control_reg_curr); aarch64->system_control_reg_curr);
if (target_mode != ARM_MODE_ANY)
armv8_dpm_modeswitch(&armv8->dpm, ARM_MODE_ANY);
return retval; return retval;
} }
@ -2957,6 +2966,7 @@ COMMAND_HANDLER(aarch64_mask_interrupts_command)
static int jim_mcrmrc(Jim_Interp *interp, int argc, Jim_Obj * const *argv) static int jim_mcrmrc(Jim_Interp *interp, int argc, Jim_Obj * const *argv)
{ {
struct command *c = jim_to_command(interp);
struct command_context *context; struct command_context *context;
struct target *target; struct target *target;
struct arm *arm; struct arm *arm;
@ -2964,7 +2974,7 @@ static int jim_mcrmrc(Jim_Interp *interp, int argc, Jim_Obj * const *argv)
bool is_mcr = false; bool is_mcr = false;
int arg_cnt = 0; int arg_cnt = 0;
if (Jim_CompareStringImmediate(interp, argv[0], "mcr")) { if (!strcmp(c->name, "mcr")) {
is_mcr = true; is_mcr = true;
arg_cnt = 7; arg_cnt = 7;
} else { } else {

View File

@ -74,7 +74,7 @@ static void swd_clear_sticky_errors(struct adiv5_dap *dap)
const struct swd_driver *swd = adiv5_dap_swd_driver(dap); const struct swd_driver *swd = adiv5_dap_swd_driver(dap);
assert(swd); assert(swd);
swd->write_reg(swd_cmd(false, false, DP_ABORT), swd->write_reg(swd_cmd(false, false, DP_ABORT),
STKCMPCLR | STKERRCLR | WDERRCLR | ORUNERRCLR, 0); STKCMPCLR | STKERRCLR | WDERRCLR | ORUNERRCLR, 0);
} }
@ -174,7 +174,7 @@ static int swd_connect(struct adiv5_dap *dap)
dap->do_reconnect = false; dap->do_reconnect = false;
swd->write_reg(swd_cmd(false, false, DP_ABORT), swd->write_reg(swd_cmd(false, false, DP_ABORT),
DAPABORT | STKCMPCLR | STKERRCLR | WDERRCLR | ORUNERRCLR, 0); DAPABORT | STKCMPCLR | STKERRCLR | WDERRCLR | ORUNERRCLR, 0);
status = swd_run_inner(dap); status = swd_run_inner(dap);
} }
@ -325,7 +325,7 @@ static int swd_queue_ap_read(struct adiv5_ap *ap, unsigned reg,
if (retval != ERROR_OK) if (retval != ERROR_OK)
return retval; return retval;
swd->read_reg(swd_cmd(true, true, reg), dap->last_read, ap->memaccess_tck); swd->read_reg(swd_cmd(true, true, reg), dap->last_read, ap->memaccess_tck);
dap->last_read = data; dap->last_read = data;
return check_sync(dap); return check_sync(dap);
@ -347,7 +347,7 @@ static int swd_queue_ap_write(struct adiv5_ap *ap, unsigned reg,
if (retval != ERROR_OK) if (retval != ERROR_OK)
return retval; return retval;
swd->write_reg(swd_cmd(false, true, reg), data, ap->memaccess_tck); swd->write_reg(swd_cmd(false, true, reg), data, ap->memaccess_tck);
return check_sync(dap); return check_sync(dap);
} }

View File

@ -85,6 +85,15 @@
#define CSYSPWRUPREQ (1UL << 30) #define CSYSPWRUPREQ (1UL << 30)
#define CSYSPWRUPACK (1UL << 31) #define CSYSPWRUPACK (1UL << 31)
#define DP_SELECT_APSEL 0xFF000000
#define DP_SELECT_APBANK 0x000000F0
#define DP_SELECT_DPBANK 0x0000000F
#define DP_SELECT_INVALID 0x00FFFF00 /* Reserved bits one */
#define DP_APSEL_MAX (255)
#define DP_APSEL_INVALID (-1)
/* MEM-AP register addresses */ /* MEM-AP register addresses */
#define MEM_AP_REG_CSW 0x00 #define MEM_AP_REG_CSW 0x00
#define MEM_AP_REG_TAR 0x04 #define MEM_AP_REG_TAR 0x04
@ -150,18 +159,11 @@
#define IDR_JEP106_ARM 0x04760000 #define IDR_JEP106_ARM 0x04760000
#define DP_SELECT_APSEL 0xFF000000
#define DP_SELECT_APBANK 0x000000F0
#define DP_SELECT_DPBANK 0x0000000F
#define DP_SELECT_INVALID 0x00FFFF00 /* Reserved bits one */
#define DP_APSEL_MAX (255)
#define DP_APSEL_INVALID (-1)
/* FIXME: not SWD specific; should be renamed, e.g. adiv5_special_seq */ /* FIXME: not SWD specific; should be renamed, e.g. adiv5_special_seq */
enum swd_special_seq { enum swd_special_seq {
LINE_RESET, LINE_RESET,
JTAG_TO_SWD, JTAG_TO_SWD,
JTAG_TO_DORMANT,
SWD_TO_JTAG, SWD_TO_JTAG,
SWD_TO_DORMANT, SWD_TO_DORMANT,
DORMANT_TO_SWD, DORMANT_TO_SWD,

View File

@ -507,17 +507,13 @@ static int cti_create(Jim_GetOptInfo *goi)
}, },
COMMAND_REGISTRATION_DONE COMMAND_REGISTRATION_DONE
}; };
e = register_commands(cmd_ctx, NULL, cti_commands); e = register_commands_with_data(cmd_ctx, NULL, cti_commands, cti);
if (ERROR_OK != e) if (ERROR_OK != e)
return JIM_ERR; return JIM_ERR;
struct command *c = command_find_in_context(cmd_ctx, cp);
assert(c);
command_set_handler_data(c, cti);
list_add_tail(&cti->lh, &all_cti); list_add_tail(&cti->lh, &all_cti);
return (ERROR_OK == e) ? JIM_OK : JIM_ERR; return JIM_OK;
} }
static int jim_cti_create(Jim_Interp *interp, int argc, Jim_Obj *const *argv) static int jim_cti_create(Jim_Interp *interp, int argc, Jim_Obj *const *argv)

View File

@ -265,17 +265,13 @@ static int dap_create(Jim_GetOptInfo *goi)
if (transport_is_hla()) if (transport_is_hla())
dap_commands[0].chain = NULL; dap_commands[0].chain = NULL;
e = register_commands(cmd_ctx, NULL, dap_commands); e = register_commands_with_data(cmd_ctx, NULL, dap_commands, dap);
if (ERROR_OK != e) if (ERROR_OK != e)
return JIM_ERR; return JIM_ERR;
struct command *c = command_find_in_context(cmd_ctx, cp);
assert(c);
command_set_handler_data(c, dap);
list_add_tail(&dap->lh, &all_dap); list_add_tail(&dap->lh, &all_dap);
return (ERROR_OK == e) ? JIM_OK : JIM_ERR; return JIM_OK;
} }
static int jim_dap_create(Jim_Interp *interp, int argc, Jim_Obj *const *argv) static int jim_dap_create(Jim_Interp *interp, int argc, Jim_Obj *const *argv)

View File

@ -550,16 +550,17 @@ err_no_params:
static int jim_arm_tpiu_swo_configure(Jim_Interp *interp, int argc, Jim_Obj * const *argv) static int jim_arm_tpiu_swo_configure(Jim_Interp *interp, int argc, Jim_Obj * const *argv)
{ {
struct command *c = jim_to_command(interp);
Jim_GetOptInfo goi; Jim_GetOptInfo goi;
Jim_GetOpt_Setup(&goi, interp, argc - 1, argv + 1); Jim_GetOpt_Setup(&goi, interp, argc - 1, argv + 1);
goi.isconfigure = !strcmp(Jim_GetString(argv[0], NULL), "configure"); goi.isconfigure = !strcmp(c->name, "configure");
if (goi.argc < 1) { if (goi.argc < 1) {
Jim_WrongNumArgs(goi.interp, goi.argc, goi.argv, Jim_WrongNumArgs(goi.interp, goi.argc, goi.argv,
"missing: -option ..."); "missing: -option ...");
return JIM_ERR; return JIM_ERR;
} }
struct arm_tpiu_swo_object *obj = Jim_CmdPrivData(interp); struct arm_tpiu_swo_object *obj = c->jim_handler_data;
return arm_tpiu_swo_configure(&goi, obj); return arm_tpiu_swo_configure(&goi, obj);
} }
@ -583,7 +584,8 @@ static int wrap_read_u32(struct target *target, struct adiv5_ap *tpiu_ap,
static int jim_arm_tpiu_swo_enable(Jim_Interp *interp, int argc, Jim_Obj *const *argv) static int jim_arm_tpiu_swo_enable(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{ {
struct arm_tpiu_swo_object *obj = Jim_CmdPrivData(interp); struct command *c = jim_to_command(interp);
struct arm_tpiu_swo_object *obj = c->jim_handler_data;
struct command_context *cmd_ctx = current_command_context(interp); struct command_context *cmd_ctx = current_command_context(interp);
struct adiv5_ap *tpiu_ap = dap_ap(obj->spot.dap, obj->spot.ap_num); struct adiv5_ap *tpiu_ap = dap_ap(obj->spot.dap, obj->spot.ap_num);
uint32_t value; uint32_t value;
@ -786,7 +788,8 @@ error_exit:
static int jim_arm_tpiu_swo_disable(Jim_Interp *interp, int argc, Jim_Obj *const *argv) static int jim_arm_tpiu_swo_disable(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{ {
struct arm_tpiu_swo_object *obj = Jim_CmdPrivData(interp); struct command *c = jim_to_command(interp);
struct arm_tpiu_swo_object *obj = c->jim_handler_data;
if (argc != 1) { if (argc != 1) {
Jim_WrongNumArgs(interp, 1, argv, "Too many parameters"); Jim_WrongNumArgs(interp, 1, argv, "Too many parameters");
@ -883,14 +886,10 @@ static int arm_tpiu_swo_create(Jim_Interp *interp, struct arm_tpiu_swo_object *o
}, },
COMMAND_REGISTRATION_DONE COMMAND_REGISTRATION_DONE
}; };
e = register_commands(cmd_ctx, NULL, obj_commands); e = register_commands_with_data(cmd_ctx, NULL, obj_commands, obj);
if (ERROR_OK != e) if (ERROR_OK != e)
return JIM_ERR; return JIM_ERR;
struct command *c = command_find_in_context(cmd_ctx, obj->name);
assert(c);
command_set_handler_data(c, obj);
list_add_tail(&obj->lh, &all_tpiu_swo); list_add_tail(&obj->lh, &all_tpiu_swo);
return JIM_OK; return JIM_OK;

View File

@ -164,18 +164,22 @@ enum {
/* Floating-point status register */ /* Floating-point status register */
ARMV7M_FPSCR, ARMV7M_FPSCR,
/* for convenience add registers' block delimiters */
ARMV7M_LAST_REG, 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,
}; };
enum { enum {
FP_NONE = 0, FP_NONE = 0,
FPv4_SP, FPV4_SP,
FPv5_SP, FPV5_SP,
FPv5_DP, FPV5_DP,
}; };
#define ARMV7M_NUM_CORE_REGS (ARMV7M_xPSR + 1) #define ARMV7M_NUM_CORE_REGS (ARMV7M_CORE_LAST_REG - ARMV7M_CORE_FIRST_REG + 1)
#define ARMV7M_NUM_CORE_REGS_NOFP (ARMV7M_CONTROL + 1)
#define ARMV7M_COMMON_MAGIC 0x2A452A45 #define ARMV7M_COMMON_MAGIC 0x2A452A45

View File

@ -1596,6 +1596,35 @@ int cortex_m_remove_watchpoint(struct target *target, struct watchpoint *watchpo
return ERROR_OK; return ERROR_OK;
} }
int cortex_m_hit_watchpoint(struct target *target, struct watchpoint **hit_watchpoint)
{
if (target->debug_reason != DBG_REASON_WATCHPOINT)
return ERROR_FAIL;
struct cortex_m_common *cortex_m = target_to_cm(target);
for (struct watchpoint *wp = target->watchpoints; wp; wp = wp->next) {
if (!wp->set)
continue;
unsigned int dwt_num = wp->set - 1;
struct cortex_m_dwt_comparator *comparator = cortex_m->dwt_comparator_list + dwt_num;
uint32_t dwt_function;
int retval = target_read_u32(target, comparator->dwt_comparator_address + 8, &dwt_function);
if (retval != ERROR_OK)
return ERROR_FAIL;
/* check the MATCHED bit */
if (dwt_function & BIT(24)) {
*hit_watchpoint = wp;
return ERROR_OK;
}
}
return ERROR_FAIL;
}
void cortex_m_enable_watchpoints(struct target *target) void cortex_m_enable_watchpoints(struct target *target)
{ {
struct watchpoint *watchpoint = target->watchpoints; struct watchpoint *watchpoint = target->watchpoints;
@ -2019,7 +2048,7 @@ int cortex_m_examine(struct target *target)
/* test for floating point feature on Cortex-M4 */ /* test for floating point feature on Cortex-M4 */
if ((mvfr0 == MVFR0_DEFAULT_M4) && (mvfr1 == MVFR1_DEFAULT_M4)) { if ((mvfr0 == MVFR0_DEFAULT_M4) && (mvfr1 == MVFR1_DEFAULT_M4)) {
LOG_DEBUG("Cortex-M%d floating point feature FPv4_SP found", i); LOG_DEBUG("Cortex-M%d floating point feature FPv4_SP found", i);
armv7m->fp_feature = FPv4_SP; armv7m->fp_feature = FPV4_SP;
} }
} else if (i == 7 || i == 33 || i == 35 || i == 55) { } else if (i == 7 || i == 33 || i == 35 || i == 55) {
target_read_u32(target, MVFR0, &mvfr0); target_read_u32(target, MVFR0, &mvfr0);
@ -2028,29 +2057,21 @@ int cortex_m_examine(struct target *target)
/* test for floating point features on Cortex-M7 */ /* test for floating point features on Cortex-M7 */
if ((mvfr0 == MVFR0_DEFAULT_M7_SP) && (mvfr1 == MVFR1_DEFAULT_M7_SP)) { if ((mvfr0 == MVFR0_DEFAULT_M7_SP) && (mvfr1 == MVFR1_DEFAULT_M7_SP)) {
LOG_DEBUG("Cortex-M%d floating point feature FPv5_SP found", i); LOG_DEBUG("Cortex-M%d floating point feature FPv5_SP found", i);
armv7m->fp_feature = FPv5_SP; armv7m->fp_feature = FPV5_SP;
} else if ((mvfr0 == MVFR0_DEFAULT_M7_DP) && (mvfr1 == MVFR1_DEFAULT_M7_DP)) { } else if ((mvfr0 == MVFR0_DEFAULT_M7_DP) && (mvfr1 == MVFR1_DEFAULT_M7_DP)) {
LOG_DEBUG("Cortex-M%d floating point feature FPv5_DP found", i); LOG_DEBUG("Cortex-M%d floating point feature FPv5_DP found", i);
armv7m->fp_feature = FPv5_DP; armv7m->fp_feature = FPV5_DP;
} }
} else if (i == 0) { } else if (i == 0) {
/* Cortex-M0 does not support unaligned memory access */ /* Cortex-M0 does not support unaligned memory access */
armv7m->arm.is_armv6m = true; armv7m->arm.is_armv6m = true;
} }
if (armv7m->fp_feature == FP_NONE && /* Check for FPU, otherwise mark FPU register as non-existent */
armv7m->arm.core_cache->num_regs > ARMV7M_NUM_CORE_REGS_NOFP) { if (armv7m->fp_feature == FP_NONE)
/* free unavailable FPU registers */ for (size_t idx = ARMV7M_FPU_FIRST_REG; idx <= ARMV7M_FPU_LAST_REG; idx++)
size_t idx; armv7m->arm.core_cache->reg_list[idx].exist = false;
for (idx = ARMV7M_NUM_CORE_REGS_NOFP;
idx < armv7m->arm.core_cache->num_regs;
idx++) {
free(armv7m->arm.core_cache->reg_list[idx].feature);
free(armv7m->arm.core_cache->reg_list[idx].reg_data_type);
}
armv7m->arm.core_cache->num_regs = ARMV7M_NUM_CORE_REGS_NOFP;
}
if (!armv7m->stlink) { if (!armv7m->stlink) {
if (i == 3 || i == 4) if (i == 3 || i == 4)
@ -2531,6 +2552,7 @@ struct target_type cortexm_target = {
.remove_breakpoint = cortex_m_remove_breakpoint, .remove_breakpoint = cortex_m_remove_breakpoint,
.add_watchpoint = cortex_m_add_watchpoint, .add_watchpoint = cortex_m_add_watchpoint,
.remove_watchpoint = cortex_m_remove_watchpoint, .remove_watchpoint = cortex_m_remove_watchpoint,
.hit_watchpoint = cortex_m_hit_watchpoint,
.commands = cortex_m_command_handlers, .commands = cortex_m_command_handlers,
.target_create = cortex_m_target_create, .target_create = cortex_m_target_create,

View File

@ -2107,6 +2107,5 @@ static const struct command_registration etm_exec_command_handlers[] = {
static int etm_register_user_commands(struct command_context *cmd_ctx) static int etm_register_user_commands(struct command_context *cmd_ctx)
{ {
struct command *etm_cmd = command_find_in_context(cmd_ctx, "etm"); return register_commands(cmd_ctx, "etm", etm_exec_command_handlers);
return register_commands(cmd_ctx, etm_cmd, etm_exec_command_handlers);
} }

View File

@ -11,6 +11,9 @@
* Copyright (C) 2009 by Franck Hereson * * Copyright (C) 2009 by Franck Hereson *
* franck.hereson@secad.fr * * franck.hereson@secad.fr *
* * * *
* Copyright (C) 2018 by Advantest *
* florian.meister@advantest.com *
* *
* This program is free software; you can redistribute it and/or modify * * This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by * * it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or * * the Free Software Foundation; either version 2 of the License, or *
@ -42,6 +45,10 @@
((elf->endianness == ELFDATA2LSB) ? \ ((elf->endianness == ELFDATA2LSB) ? \
le_to_h_u32((uint8_t *)&field) : be_to_h_u32((uint8_t *)&field)) le_to_h_u32((uint8_t *)&field) : be_to_h_u32((uint8_t *)&field))
#define field64(elf, field) \
((elf->endianness == ELFDATA2LSB) ? \
le_to_h_u64((uint8_t *)&field) : be_to_h_u64((uint8_t *)&field))
static int autodetect_image_type(struct image *image, const char *url) static int autodetect_image_type(struct image *image, const char *url)
{ {
int retval; int retval;
@ -49,7 +56,7 @@ static int autodetect_image_type(struct image *image, const char *url)
size_t read_bytes; size_t read_bytes;
uint8_t buffer[9]; uint8_t buffer[9];
/* read the first 4 bytes of image */ /* read the first 9 bytes of image */
retval = fileio_open(&fileio, url, FILEIO_READ, FILEIO_BINARY); retval = fileio_open(&fileio, url, FILEIO_READ, FILEIO_BINARY);
if (retval != ERROR_OK) if (retval != ERROR_OK)
return retval; return retval;
@ -350,22 +357,29 @@ static int image_ihex_buffer_complete(struct image *image)
return retval; return retval;
} }
static int image_elf_read_headers(struct image *image) static int image_elf32_read_headers(struct image *image)
{ {
struct image_elf *elf = image->type_private; struct image_elf *elf = image->type_private;
size_t read_bytes; size_t read_bytes;
uint32_t i, j; uint32_t i, j;
int retval; int retval;
uint32_t nload, load_to_vaddr = 0; uint32_t nload;
bool load_to_vaddr = false;
elf->header = malloc(sizeof(Elf32_Ehdr)); retval = fileio_seek(elf->fileio, 0);
if (retval != ERROR_OK) {
LOG_ERROR("cannot seek to ELF file header, read failed");
return retval;
}
if (elf->header == NULL) { elf->header32 = malloc(sizeof(Elf32_Ehdr));
LOG_ERROR("insufficient memory to perform operation ");
if (elf->header32 == NULL) {
LOG_ERROR("insufficient memory to perform operation");
return ERROR_FILEIO_OPERATION_FAILED; return ERROR_FILEIO_OPERATION_FAILED;
} }
retval = fileio_read(elf->fileio, sizeof(Elf32_Ehdr), (uint8_t *)elf->header, &read_bytes); retval = fileio_read(elf->fileio, sizeof(Elf32_Ehdr), (uint8_t *)elf->header32, &read_bytes);
if (retval != ERROR_OK) { if (retval != ERROR_OK) {
LOG_ERROR("cannot read ELF file header, read failed"); LOG_ERROR("cannot read ELF file header, read failed");
return ERROR_FILEIO_OPERATION_FAILED; return ERROR_FILEIO_OPERATION_FAILED;
@ -375,42 +389,26 @@ static int image_elf_read_headers(struct image *image)
return ERROR_FILEIO_OPERATION_FAILED; return ERROR_FILEIO_OPERATION_FAILED;
} }
if (strncmp((char *)elf->header->e_ident, ELFMAG, SELFMAG) != 0) { elf->segment_count = field16(elf, elf->header32->e_phnum);
LOG_ERROR("invalid ELF file, bad magic number");
return ERROR_IMAGE_FORMAT_ERROR;
}
if (elf->header->e_ident[EI_CLASS] != ELFCLASS32) {
LOG_ERROR("invalid ELF file, only 32bits files are supported");
return ERROR_IMAGE_FORMAT_ERROR;
}
elf->endianness = elf->header->e_ident[EI_DATA];
if ((elf->endianness != ELFDATA2LSB)
&& (elf->endianness != ELFDATA2MSB)) {
LOG_ERROR("invalid ELF file, unknown endianness setting");
return ERROR_IMAGE_FORMAT_ERROR;
}
elf->segment_count = field16(elf, elf->header->e_phnum);
if (elf->segment_count == 0) { if (elf->segment_count == 0) {
LOG_ERROR("invalid ELF file, no program headers"); LOG_ERROR("invalid ELF file, no program headers");
return ERROR_IMAGE_FORMAT_ERROR; return ERROR_IMAGE_FORMAT_ERROR;
} }
retval = fileio_seek(elf->fileio, field32(elf, elf->header->e_phoff)); retval = fileio_seek(elf->fileio, field32(elf, elf->header32->e_phoff));
if (retval != ERROR_OK) { if (retval != ERROR_OK) {
LOG_ERROR("cannot seek to ELF program header table, read failed"); LOG_ERROR("cannot seek to ELF program header table, read failed");
return retval; return retval;
} }
elf->segments = malloc(elf->segment_count*sizeof(Elf32_Phdr)); elf->segments32 = malloc(elf->segment_count*sizeof(Elf32_Phdr));
if (elf->segments == NULL) { if (elf->segments32 == NULL) {
LOG_ERROR("insufficient memory to perform operation "); LOG_ERROR("insufficient memory to perform operation");
return ERROR_FILEIO_OPERATION_FAILED; return ERROR_FILEIO_OPERATION_FAILED;
} }
retval = fileio_read(elf->fileio, elf->segment_count*sizeof(Elf32_Phdr), retval = fileio_read(elf->fileio, elf->segment_count*sizeof(Elf32_Phdr),
(uint8_t *)elf->segments, &read_bytes); (uint8_t *)elf->segments32, &read_bytes);
if (retval != ERROR_OK) { if (retval != ERROR_OK) {
LOG_ERROR("cannot read ELF segment headers, read failed"); LOG_ERROR("cannot read ELF segment headers, read failed");
return retval; return retval;
@ -424,11 +422,14 @@ static int image_elf_read_headers(struct image *image)
image->num_sections = 0; image->num_sections = 0;
for (i = 0; i < elf->segment_count; i++) for (i = 0; i < elf->segment_count; i++)
if ((field32(elf, if ((field32(elf,
elf->segments[i].p_type) == PT_LOAD) && elf->segments32[i].p_type) == PT_LOAD) &&
(field32(elf, elf->segments[i].p_filesz) != 0)) (field32(elf, elf->segments32[i].p_filesz) != 0))
image->num_sections++; image->num_sections++;
assert(image->num_sections > 0); if (image->num_sections == 0) {
LOG_ERROR("invalid ELF file, no loadable segments");
return ERROR_IMAGE_FORMAT_ERROR;
}
/** /**
* some ELF linkers produce binaries with *all* the program header * some ELF linkers produce binaries with *all* the program header
@ -441,44 +442,220 @@ static int image_elf_read_headers(struct image *image)
* when obtaining lma - look at elf.c of BDF) * when obtaining lma - look at elf.c of BDF)
*/ */
for (nload = 0, i = 0; i < elf->segment_count; i++) for (nload = 0, i = 0; i < elf->segment_count; i++)
if (elf->segments[i].p_paddr != 0) if (elf->segments32[i].p_paddr != 0)
break; break;
else if ((field32(elf, else if ((field32(elf,
elf->segments[i].p_type) == PT_LOAD) && elf->segments32[i].p_type) == PT_LOAD) &&
(field32(elf, elf->segments[i].p_memsz) != 0)) (field32(elf, elf->segments32[i].p_memsz) != 0))
++nload; ++nload;
if (i >= elf->segment_count && nload > 1) if (i >= elf->segment_count && nload > 1)
load_to_vaddr = 1; load_to_vaddr = true;
/* alloc and fill sections array with loadable segments */ /* alloc and fill sections array with loadable segments */
image->sections = malloc(image->num_sections * sizeof(struct imagesection)); image->sections = malloc(image->num_sections * sizeof(struct imagesection));
if (image->sections == NULL) {
LOG_ERROR("insufficient memory to perform operation");
return ERROR_FILEIO_OPERATION_FAILED;
}
for (i = 0, j = 0; i < elf->segment_count; i++) { for (i = 0, j = 0; i < elf->segment_count; i++) {
if ((field32(elf, if ((field32(elf,
elf->segments[i].p_type) == PT_LOAD) && elf->segments32[i].p_type) == PT_LOAD) &&
(field32(elf, elf->segments[i].p_filesz) != 0)) { (field32(elf, elf->segments32[i].p_filesz) != 0)) {
image->sections[j].size = field32(elf, elf->segments[i].p_filesz); image->sections[j].size = field32(elf, elf->segments32[i].p_filesz);
if (load_to_vaddr) if (load_to_vaddr)
image->sections[j].base_address = field32(elf, image->sections[j].base_address = field32(elf,
elf->segments[i].p_vaddr); elf->segments32[i].p_vaddr);
else else
image->sections[j].base_address = field32(elf, image->sections[j].base_address = field32(elf,
elf->segments[i].p_paddr); elf->segments32[i].p_paddr);
image->sections[j].private = &elf->segments[i]; image->sections[j].private = &elf->segments32[i];
image->sections[j].flags = field32(elf, elf->segments[i].p_flags); image->sections[j].flags = field32(elf, elf->segments32[i].p_flags);
j++; j++;
} }
} }
image->start_address_set = true; image->start_address_set = true;
image->start_address = field32(elf, elf->header->e_entry); image->start_address = field32(elf, elf->header32->e_entry);
return ERROR_OK; return ERROR_OK;
} }
static int image_elf_read_section(struct image *image, static int image_elf64_read_headers(struct image *image)
{
struct image_elf *elf = image->type_private;
size_t read_bytes;
uint32_t i, j;
int retval;
uint32_t nload;
bool load_to_vaddr = false;
retval = fileio_seek(elf->fileio, 0);
if (retval != ERROR_OK) {
LOG_ERROR("cannot seek to ELF file header, read failed");
return retval;
}
elf->header64 = malloc(sizeof(Elf64_Ehdr));
if (elf->header64 == NULL) {
LOG_ERROR("insufficient memory to perform operation");
return ERROR_FILEIO_OPERATION_FAILED;
}
retval = fileio_read(elf->fileio, sizeof(Elf64_Ehdr), (uint8_t *)elf->header64, &read_bytes);
if (retval != ERROR_OK) {
LOG_ERROR("cannot read ELF file header, read failed");
return ERROR_FILEIO_OPERATION_FAILED;
}
if (read_bytes != sizeof(Elf64_Ehdr)) {
LOG_ERROR("cannot read ELF file header, only partially read");
return ERROR_FILEIO_OPERATION_FAILED;
}
elf->segment_count = field16(elf, elf->header64->e_phnum);
if (elf->segment_count == 0) {
LOG_ERROR("invalid ELF file, no program headers");
return ERROR_IMAGE_FORMAT_ERROR;
}
retval = fileio_seek(elf->fileio, field64(elf, elf->header64->e_phoff));
if (retval != ERROR_OK) {
LOG_ERROR("cannot seek to ELF program header table, read failed");
return retval;
}
elf->segments64 = malloc(elf->segment_count*sizeof(Elf64_Phdr));
if (elf->segments64 == NULL) {
LOG_ERROR("insufficient memory to perform operation");
return ERROR_FILEIO_OPERATION_FAILED;
}
retval = fileio_read(elf->fileio, elf->segment_count*sizeof(Elf64_Phdr),
(uint8_t *)elf->segments64, &read_bytes);
if (retval != ERROR_OK) {
LOG_ERROR("cannot read ELF segment headers, read failed");
return retval;
}
if (read_bytes != elf->segment_count*sizeof(Elf64_Phdr)) {
LOG_ERROR("cannot read ELF segment headers, only partially read");
return ERROR_FILEIO_OPERATION_FAILED;
}
/* count useful segments (loadable), ignore BSS section */
image->num_sections = 0;
for (i = 0; i < elf->segment_count; i++)
if ((field32(elf,
elf->segments64[i].p_type) == PT_LOAD) &&
(field64(elf, elf->segments64[i].p_filesz) != 0))
image->num_sections++;
if (image->num_sections == 0) {
LOG_ERROR("invalid ELF file, no loadable segments");
return ERROR_IMAGE_FORMAT_ERROR;
}
/**
* some ELF linkers produce binaries with *all* the program header
* p_paddr fields zero (there can be however one loadable segment
* that has valid physical address 0x0).
* If we have such a binary with more than
* one PT_LOAD header, then use p_vaddr instead of p_paddr
* (ARM ELF standard demands p_paddr = 0 anyway, and BFD
* library uses this approach to workaround zero-initialized p_paddrs
* when obtaining lma - look at elf.c of BDF)
*/
for (nload = 0, i = 0; i < elf->segment_count; i++)
if (elf->segments64[i].p_paddr != 0)
break;
else if ((field32(elf,
elf->segments64[i].p_type) == PT_LOAD) &&
(field64(elf, elf->segments64[i].p_memsz) != 0))
++nload;
if (i >= elf->segment_count && nload > 1)
load_to_vaddr = true;
/* alloc and fill sections array with loadable segments */
image->sections = malloc(image->num_sections * sizeof(struct imagesection));
if (image->sections == NULL) {
LOG_ERROR("insufficient memory to perform operation");
return ERROR_FILEIO_OPERATION_FAILED;
}
for (i = 0, j = 0; i < elf->segment_count; i++) {
if ((field32(elf,
elf->segments64[i].p_type) == PT_LOAD) &&
(field64(elf, elf->segments64[i].p_filesz) != 0)) {
image->sections[j].size = field64(elf, elf->segments64[i].p_filesz);
if (load_to_vaddr)
image->sections[j].base_address = field64(elf,
elf->segments64[i].p_vaddr);
else
image->sections[j].base_address = field64(elf,
elf->segments64[i].p_paddr);
image->sections[j].private = &elf->segments64[i];
image->sections[j].flags = field32(elf, elf->segments64[i].p_flags);
j++;
}
}
image->start_address_set = true;
image->start_address = field64(elf, elf->header64->e_entry);
return ERROR_OK;
}
static int image_elf_read_headers(struct image *image)
{
struct image_elf *elf = image->type_private;
size_t read_bytes;
unsigned char e_ident[EI_NIDENT];
int retval;
retval = fileio_read(elf->fileio, EI_NIDENT, e_ident, &read_bytes);
if (retval != ERROR_OK) {
LOG_ERROR("cannot read ELF file header, read failed");
return ERROR_FILEIO_OPERATION_FAILED;
}
if (read_bytes != EI_NIDENT) {
LOG_ERROR("cannot read ELF file header, only partially read");
return ERROR_FILEIO_OPERATION_FAILED;
}
if (strncmp((char *)e_ident, ELFMAG, SELFMAG) != 0) {
LOG_ERROR("invalid ELF file, bad magic number");
return ERROR_IMAGE_FORMAT_ERROR;
}
elf->endianness = e_ident[EI_DATA];
if ((elf->endianness != ELFDATA2LSB)
&& (elf->endianness != ELFDATA2MSB)) {
LOG_ERROR("invalid ELF file, unknown endianness setting");
return ERROR_IMAGE_FORMAT_ERROR;
}
switch (e_ident[EI_CLASS]) {
case ELFCLASS32:
LOG_DEBUG("ELF32 image detected.");
elf->is_64_bit = false;
return image_elf32_read_headers(image);
case ELFCLASS64:
LOG_DEBUG("ELF64 image detected.");
elf->is_64_bit = true;
return image_elf64_read_headers(image);
default:
LOG_ERROR("invalid ELF file, only 32/64 bit ELF files are supported");
return ERROR_IMAGE_FORMAT_ERROR;
}
}
static int image_elf32_read_section(struct image *image,
int section, int section,
uint32_t offset, target_addr_t offset,
uint32_t size, uint32_t size,
uint8_t *buffer, uint8_t *buffer,
size_t *size_read) size_t *size_read)
@ -490,13 +667,13 @@ static int image_elf_read_section(struct image *image,
*size_read = 0; *size_read = 0;
LOG_DEBUG("load segment %d at 0x%" PRIx32 " (sz = 0x%" PRIx32 ")", section, offset, size); LOG_DEBUG("load segment %d at 0x%" TARGET_PRIxADDR " (sz = 0x%" PRIx32 ")", section, offset, size);
/* read initialized data in current segment if any */ /* read initialized data in current segment if any */
if (offset < field32(elf, segment->p_filesz)) { if (offset < field32(elf, segment->p_filesz)) {
/* maximal size present in file for the current segment */ /* maximal size present in file for the current segment */
read_size = MIN(size, field32(elf, segment->p_filesz) - offset); read_size = MIN(size, field32(elf, segment->p_filesz) - offset);
LOG_DEBUG("read elf: size = 0x%zx at 0x%" PRIx32 "", read_size, LOG_DEBUG("read elf: size = 0x%zx at 0x%" TARGET_PRIxADDR "", read_size,
field32(elf, segment->p_offset) + offset); field32(elf, segment->p_offset) + offset);
/* read initialized area of the segment */ /* read initialized area of the segment */
retval = fileio_seek(elf->fileio, field32(elf, segment->p_offset) + offset); retval = fileio_seek(elf->fileio, field32(elf, segment->p_offset) + offset);
@ -519,6 +696,64 @@ static int image_elf_read_section(struct image *image,
return ERROR_OK; return ERROR_OK;
} }
static int image_elf64_read_section(struct image *image,
int section,
target_addr_t offset,
uint32_t size,
uint8_t *buffer,
size_t *size_read)
{
struct image_elf *elf = image->type_private;
Elf64_Phdr *segment = (Elf64_Phdr *)image->sections[section].private;
size_t read_size, really_read;
int retval;
*size_read = 0;
LOG_DEBUG("load segment %d at 0x%" TARGET_PRIxADDR " (sz = 0x%" PRIx32 ")", section, offset, size);
/* read initialized data in current segment if any */
if (offset < field64(elf, segment->p_filesz)) {
/* maximal size present in file for the current segment */
read_size = MIN(size, field64(elf, segment->p_filesz) - offset);
LOG_DEBUG("read elf: size = 0x%zx at 0x%" TARGET_PRIxADDR "", read_size,
field64(elf, segment->p_offset) + offset);
/* read initialized area of the segment */
retval = fileio_seek(elf->fileio, field64(elf, segment->p_offset) + offset);
if (retval != ERROR_OK) {
LOG_ERROR("cannot find ELF segment content, seek failed");
return retval;
}
retval = fileio_read(elf->fileio, read_size, buffer, &really_read);
if (retval != ERROR_OK) {
LOG_ERROR("cannot read ELF segment content, read failed");
return retval;
}
size -= read_size;
*size_read += read_size;
/* need more data ? */
if (!size)
return ERROR_OK;
}
return ERROR_OK;
}
static int image_elf_read_section(struct image *image,
int section,
target_addr_t offset,
uint32_t size,
uint8_t *buffer,
size_t *size_read)
{
struct image_elf *elf = image->type_private;
if (elf->is_64_bit)
return image_elf64_read_section(image, section, offset, size, buffer, size_read);
else
return image_elf32_read_section(image, section, offset, size, buffer, size_read);
}
static int image_mot_buffer_complete_inner(struct image *image, static int image_mot_buffer_complete_inner(struct image *image,
char *lpszLine, char *lpszLine,
struct imagesection *section) struct imagesection *section)
@ -840,7 +1075,7 @@ int image_open(struct image *image, const char *url, const char *type_string)
int image_read_section(struct image *image, int image_read_section(struct image *image,
int section, int section,
uint32_t offset, target_addr_t offset,
uint32_t size, uint32_t size,
uint8_t *buffer, uint8_t *buffer,
size_t *size_read) size_t *size_read)
@ -850,7 +1085,7 @@ int image_read_section(struct image *image,
/* don't read past the end of a section */ /* don't read past the end of a section */
if (offset + size > image->sections[section].size) { if (offset + size > image->sections[section].size) {
LOG_DEBUG( LOG_DEBUG(
"read past end of section: 0x%8.8" PRIx32 " + 0x%8.8" PRIx32 " > 0x%8.8" PRIx32 "", "read past end of section: 0x%8.8" TARGET_PRIxADDR " + 0x%8.8" PRIx32 " > 0x%8.8" PRIx32 "",
offset, offset,
size, size,
image->sections[section].size); image->sections[section].size);
@ -878,9 +1113,9 @@ int image_read_section(struct image *image,
*size_read = size; *size_read = size;
return ERROR_OK; return ERROR_OK;
} else if (image->type == IMAGE_ELF) } else if (image->type == IMAGE_ELF) {
return image_elf_read_section(image, section, offset, size, buffer, size_read); return image_elf_read_section(image, section, offset, size, buffer, size_read);
else if (image->type == IMAGE_MEMORY) { } else if (image->type == IMAGE_MEMORY) {
struct image_memory *image_memory = image->type_private; struct image_memory *image_memory = image->type_private;
uint32_t address = image->sections[section].base_address + offset; uint32_t address = image->sections[section].base_address + offset;
@ -933,7 +1168,7 @@ int image_read_section(struct image *image,
return ERROR_OK; return ERROR_OK;
} }
int image_add_section(struct image *image, uint32_t base, uint32_t size, int flags, uint8_t const *data) int image_add_section(struct image *image, target_addr_t base, uint32_t size, int flags, uint8_t const *data)
{ {
struct imagesection *section; struct imagesection *section;
@ -988,11 +1223,19 @@ void image_close(struct image *image)
fileio_close(image_elf->fileio); fileio_close(image_elf->fileio);
free(image_elf->header); if (image_elf->is_64_bit) {
image_elf->header = NULL; free(image_elf->header64);
image_elf->header64 = NULL;
free(image_elf->segments); free(image_elf->segments64);
image_elf->segments = NULL; image_elf->segments64 = NULL;
} else {
free(image_elf->header32);
image_elf->header32 = NULL;
free(image_elf->segments32);
image_elf->segments32 = NULL;
}
} else if (image->type == IMAGE_MEMORY) { } else if (image->type == IMAGE_MEMORY) {
struct image_memory *image_memory = image->type_private; struct image_memory *image_memory = image->type_private;

View File

@ -8,6 +8,9 @@
* Copyright (C) 2008 by Spencer Oliver * * Copyright (C) 2008 by Spencer Oliver *
* spen@spen-soft.co.uk * * spen@spen-soft.co.uk *
* * * *
* Copyright (C) 2018 by Advantest *
* florian.meister@advantest.com *
* *
* This program is free software; you can redistribute it and/or modify * * This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by * * it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or * * the Free Software Foundation; either version 2 of the License, or *
@ -81,8 +84,15 @@ struct image_memory {
struct image_elf { struct image_elf {
struct fileio *fileio; struct fileio *fileio;
Elf32_Ehdr *header; bool is_64_bit;
Elf32_Phdr *segments; union {
Elf32_Ehdr *header32;
Elf64_Ehdr *header64;
};
union {
Elf32_Phdr *segments32;
Elf64_Phdr *segments64;
};
uint32_t segment_count; uint32_t segment_count;
uint8_t endianness; uint8_t endianness;
}; };
@ -93,11 +103,11 @@ struct image_mot {
}; };
int image_open(struct image *image, const char *url, const char *type_string); int image_open(struct image *image, const char *url, const char *type_string);
int image_read_section(struct image *image, int section, uint32_t offset, int image_read_section(struct image *image, int section, target_addr_t offset,
uint32_t size, uint8_t *buffer, size_t *size_read); uint32_t size, uint8_t *buffer, size_t *size_read);
void image_close(struct image *image); void image_close(struct image *image);
int image_add_section(struct image *image, uint32_t base, uint32_t size, int image_add_section(struct image *image, target_addr_t base, uint32_t size,
int flags, uint8_t const *data); int flags, uint8_t const *data);
int image_calculate_checksum(const uint8_t *buffer, uint32_t nbytes, int image_calculate_checksum(const uint8_t *buffer, uint32_t nbytes,

View File

@ -722,7 +722,9 @@ static int jim_nds32_bulk_write(Jim_Interp *interp, int argc, Jim_Obj * const *a
return JIM_ERR; return JIM_ERR;
} }
struct target *target = Jim_CmdPrivData(goi.interp); struct command_context *cmd_ctx = current_command_context(interp);
assert(cmd_ctx);
struct target *target = get_current_target(cmd_ctx);
int result; int result;
result = target_write_buffer(target, address, count * 4, (const uint8_t *)data); result = target_write_buffer(target, address, count * 4, (const uint8_t *)data);
@ -751,7 +753,9 @@ static int jim_nds32_multi_write(Jim_Interp *interp, int argc, Jim_Obj * const *
if (e != JIM_OK) if (e != JIM_OK)
return e; return e;
struct target *target = Jim_CmdPrivData(goi.interp); struct command_context *cmd_ctx = current_command_context(interp);
assert(cmd_ctx);
struct target *target = get_current_target(cmd_ctx);
struct aice_port_s *aice = target_to_aice(target); struct aice_port_s *aice = target_to_aice(target);
int result; int result;
uint32_t address; uint32_t address;
@ -812,7 +816,9 @@ static int jim_nds32_bulk_read(Jim_Interp *interp, int argc, Jim_Obj * const *ar
if (goi.argc != 0) if (goi.argc != 0)
return JIM_ERR; return JIM_ERR;
struct target *target = Jim_CmdPrivData(goi.interp); struct command_context *cmd_ctx = current_command_context(interp);
assert(cmd_ctx);
struct target *target = get_current_target(cmd_ctx);
uint32_t *data = malloc(count * sizeof(uint32_t)); uint32_t *data = malloc(count * sizeof(uint32_t));
int result; int result;
result = target_read_buffer(target, address, count * 4, (uint8_t *)data); result = target_read_buffer(target, address, count * 4, (uint8_t *)data);
@ -863,7 +869,9 @@ static int jim_nds32_read_edm_sr(Jim_Interp *interp, int argc, Jim_Obj * const *
else else
return ERROR_FAIL; return ERROR_FAIL;
struct target *target = Jim_CmdPrivData(goi.interp); struct command_context *cmd_ctx = current_command_context(interp);
assert(cmd_ctx);
struct target *target = get_current_target(cmd_ctx);
struct aice_port_s *aice = target_to_aice(target); struct aice_port_s *aice = target_to_aice(target);
char data_str[11]; char data_str[11];
@ -911,7 +919,9 @@ static int jim_nds32_write_edm_sr(Jim_Interp *interp, int argc, Jim_Obj * const
else else
return ERROR_FAIL; return ERROR_FAIL;
struct target *target = Jim_CmdPrivData(goi.interp); struct command_context *cmd_ctx = current_command_context(interp);
assert(cmd_ctx);
struct target *target = get_current_target(cmd_ctx);
struct aice_port_s *aice = target_to_aice(target); struct aice_port_s *aice = target_to_aice(target);
aice_write_debug_reg(aice, edm_sr_number, value); aice_write_debug_reg(aice, edm_sr_number, value);

View File

@ -131,26 +131,6 @@ COMMAND_HANDLER(default_handle_smp_command)
return ERROR_COMMAND_SYNTAX_ERROR; return ERROR_COMMAND_SYNTAX_ERROR;
} }
COMMAND_HANDLER(deprecated_handle_smp_on_command)
{
const char *argv[] = {"on", NULL};
LOG_WARNING("\'smp_on\' is deprecated, please use \'smp on\' instead.");
CMD_ARGC = 1;
CMD_ARGV = argv;
return CALL_COMMAND_HANDLER(default_handle_smp_command);
}
COMMAND_HANDLER(deprecated_handle_smp_off_command)
{
const char *argv[] = {"off", NULL};
LOG_WARNING("\'smp_off\' is deprecated, please use \'smp off\' instead.");
CMD_ARGC = 1;
CMD_ARGV = argv;
return CALL_COMMAND_HANDLER(default_handle_smp_command);
}
COMMAND_HANDLER(handle_smp_gdb_command) COMMAND_HANDLER(handle_smp_gdb_command)
{ {
struct target *target = get_current_target(CMD_CTX); struct target *target = get_current_target(CMD_CTX);
@ -180,20 +160,6 @@ const struct command_registration smp_command_handlers[] = {
.help = "smp handling", .help = "smp handling",
.usage = "[on|off]", .usage = "[on|off]",
}, },
{
.name = "smp_on",
.handler = deprecated_handle_smp_on_command,
.mode = COMMAND_EXEC,
.help = "Restart smp handling",
.usage = "",
},
{
.name = "smp_off",
.handler = deprecated_handle_smp_off_command,
.mode = COMMAND_EXEC,
.help = "Stop smp handling",
.usage = "",
},
{ {
.name = "smp_gdb", .name = "smp_gdb",
.handler = handle_smp_gdb_command, .handler = handle_smp_gdb_command,

View File

@ -206,3 +206,34 @@ proc init_target_events {} {
# Additionally board config scripts can define a procedure init_board that will be executed after init and init_targets # Additionally board config scripts can define a procedure init_board that will be executed after init and init_targets
proc init_board {} { proc init_board {} {
} }
# smp_on/smp_off were already DEPRECATED in v0.11.0 through http://openocd.zylin.com/4615
proc "aarch64 smp_on" {args} {
echo "DEPRECATED! use 'aarch64 smp on' not 'aarch64 smp_on'"
eval aarch64 smp on $args
}
proc "aarch64 smp_off" {args} {
echo "DEPRECATED! use 'aarch64 smp off' not 'aarch64 smp_off'"
eval aarch64 smp off $args
}
proc "cortex_a smp_on" {args} {
echo "DEPRECATED! use 'cortex_a smp on' not 'cortex_a smp_on'"
eval cortex_a smp on $args
}
proc "cortex_a smp_off" {args} {
echo "DEPRECATED! use 'cortex_a smp off' not 'cortex_a smp_off'"
eval cortex_a smp off $args
}
proc "mips_m4k smp_on" {args} {
echo "DEPRECATED! use 'mips_m4k smp on' not 'mips_m4k smp_on'"
eval mips_m4k smp on $args
}
proc "mips_m4k smp_off" {args} {
echo "DEPRECATED! use 'mips_m4k smp off' not 'mips_m4k smp_off'"
eval mips_m4k smp off $args
}

View File

@ -5229,30 +5229,37 @@ no_params:
static int jim_target_configure(Jim_Interp *interp, int argc, Jim_Obj * const *argv) static int jim_target_configure(Jim_Interp *interp, int argc, Jim_Obj * const *argv)
{ {
struct command *c = jim_to_command(interp);
Jim_GetOptInfo goi; Jim_GetOptInfo goi;
Jim_GetOpt_Setup(&goi, interp, argc - 1, argv + 1); Jim_GetOpt_Setup(&goi, interp, argc - 1, argv + 1);
goi.isconfigure = !strcmp(Jim_GetString(argv[0], NULL), "configure"); goi.isconfigure = !strcmp(c->name, "configure");
if (goi.argc < 1) { if (goi.argc < 1) {
Jim_WrongNumArgs(goi.interp, goi.argc, goi.argv, Jim_WrongNumArgs(goi.interp, goi.argc, goi.argv,
"missing: -option ..."); "missing: -option ...");
return JIM_ERR; return JIM_ERR;
} }
struct target *target = Jim_CmdPrivData(goi.interp); struct command_context *cmd_ctx = current_command_context(interp);
assert(cmd_ctx);
struct target *target = get_current_target(cmd_ctx);
return target_configure(&goi, target); return target_configure(&goi, target);
} }
static int jim_target_mem2array(Jim_Interp *interp, static int jim_target_mem2array(Jim_Interp *interp,
int argc, Jim_Obj *const *argv) int argc, Jim_Obj *const *argv)
{ {
struct target *target = Jim_CmdPrivData(interp); struct command_context *cmd_ctx = current_command_context(interp);
assert(cmd_ctx);
struct target *target = get_current_target(cmd_ctx);
return target_mem2array(interp, target, argc - 1, argv + 1); return target_mem2array(interp, target, argc - 1, argv + 1);
} }
static int jim_target_array2mem(Jim_Interp *interp, static int jim_target_array2mem(Jim_Interp *interp,
int argc, Jim_Obj *const *argv) int argc, Jim_Obj *const *argv)
{ {
struct target *target = Jim_CmdPrivData(interp); struct command_context *cmd_ctx = current_command_context(interp);
assert(cmd_ctx);
struct target *target = get_current_target(cmd_ctx);
return target_array2mem(interp, target, argc - 1, argv + 1); return target_array2mem(interp, target, argc - 1, argv + 1);
} }
@ -5284,7 +5291,9 @@ static int jim_target_examine(Jim_Interp *interp, int argc, Jim_Obj *const *argv
allow_defer = true; allow_defer = true;
} }
struct target *target = Jim_CmdPrivData(interp); struct command_context *cmd_ctx = current_command_context(interp);
assert(cmd_ctx);
struct target *target = get_current_target(cmd_ctx);
if (!target->tap->enabled) if (!target->tap->enabled)
return jim_target_tap_disabled(interp); return jim_target_tap_disabled(interp);
@ -5302,7 +5311,9 @@ static int jim_target_examine(Jim_Interp *interp, int argc, Jim_Obj *const *argv
static int jim_target_was_examined(Jim_Interp *interp, int argc, Jim_Obj * const *argv) static int jim_target_was_examined(Jim_Interp *interp, int argc, Jim_Obj * const *argv)
{ {
struct target *target = Jim_CmdPrivData(interp); struct command_context *cmd_ctx = current_command_context(interp);
assert(cmd_ctx);
struct target *target = get_current_target(cmd_ctx);
Jim_SetResultBool(interp, target_was_examined(target)); Jim_SetResultBool(interp, target_was_examined(target));
return JIM_OK; return JIM_OK;
@ -5310,7 +5321,9 @@ static int jim_target_was_examined(Jim_Interp *interp, int argc, Jim_Obj * const
static int jim_target_examine_deferred(Jim_Interp *interp, int argc, Jim_Obj * const *argv) static int jim_target_examine_deferred(Jim_Interp *interp, int argc, Jim_Obj * const *argv)
{ {
struct target *target = Jim_CmdPrivData(interp); struct command_context *cmd_ctx = current_command_context(interp);
assert(cmd_ctx);
struct target *target = get_current_target(cmd_ctx);
Jim_SetResultBool(interp, target->defer_examine); Jim_SetResultBool(interp, target->defer_examine);
return JIM_OK; return JIM_OK;
@ -5322,7 +5335,9 @@ static int jim_target_halt_gdb(Jim_Interp *interp, int argc, Jim_Obj *const *arg
Jim_WrongNumArgs(interp, 1, argv, "[no parameters]"); Jim_WrongNumArgs(interp, 1, argv, "[no parameters]");
return JIM_ERR; return JIM_ERR;
} }
struct target *target = Jim_CmdPrivData(interp); struct command_context *cmd_ctx = current_command_context(interp);
assert(cmd_ctx);
struct target *target = get_current_target(cmd_ctx);
if (target_call_event_callbacks(target, TARGET_EVENT_GDB_HALT) != ERROR_OK) if (target_call_event_callbacks(target, TARGET_EVENT_GDB_HALT) != ERROR_OK)
return JIM_ERR; return JIM_ERR;
@ -5336,7 +5351,9 @@ static int jim_target_poll(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
Jim_WrongNumArgs(interp, 1, argv, "[no parameters]"); Jim_WrongNumArgs(interp, 1, argv, "[no parameters]");
return JIM_ERR; return JIM_ERR;
} }
struct target *target = Jim_CmdPrivData(interp); struct command_context *cmd_ctx = current_command_context(interp);
assert(cmd_ctx);
struct target *target = get_current_target(cmd_ctx);
if (!target->tap->enabled) if (!target->tap->enabled)
return jim_target_tap_disabled(interp); return jim_target_tap_disabled(interp);
@ -5373,7 +5390,9 @@ static int jim_target_reset(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
if (e != JIM_OK) if (e != JIM_OK)
return e; return e;
struct target *target = Jim_CmdPrivData(goi.interp); struct command_context *cmd_ctx = current_command_context(interp);
assert(cmd_ctx);
struct target *target = get_current_target(cmd_ctx);
if (!target->tap->enabled) if (!target->tap->enabled)
return jim_target_tap_disabled(interp); return jim_target_tap_disabled(interp);
@ -5406,7 +5425,9 @@ static int jim_target_halt(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
Jim_WrongNumArgs(interp, 1, argv, "[no parameters]"); Jim_WrongNumArgs(interp, 1, argv, "[no parameters]");
return JIM_ERR; return JIM_ERR;
} }
struct target *target = Jim_CmdPrivData(interp); struct command_context *cmd_ctx = current_command_context(interp);
assert(cmd_ctx);
struct target *target = get_current_target(cmd_ctx);
if (!target->tap->enabled) if (!target->tap->enabled)
return jim_target_tap_disabled(interp); return jim_target_tap_disabled(interp);
int e = target->type->halt(target); int e = target->type->halt(target);
@ -5436,7 +5457,9 @@ static int jim_target_wait_state(Jim_Interp *interp, int argc, Jim_Obj *const *a
e = Jim_GetOpt_Wide(&goi, &a); e = Jim_GetOpt_Wide(&goi, &a);
if (e != JIM_OK) if (e != JIM_OK)
return e; return e;
struct target *target = Jim_CmdPrivData(interp); struct command_context *cmd_ctx = current_command_context(interp);
assert(cmd_ctx);
struct target *target = get_current_target(cmd_ctx);
if (!target->tap->enabled) if (!target->tap->enabled)
return jim_target_tap_disabled(interp); return jim_target_tap_disabled(interp);
@ -5480,7 +5503,9 @@ static int jim_target_current_state(Jim_Interp *interp, int argc, Jim_Obj *const
Jim_WrongNumArgs(interp, 1, argv, "[no parameters]"); Jim_WrongNumArgs(interp, 1, argv, "[no parameters]");
return JIM_ERR; return JIM_ERR;
} }
struct target *target = Jim_CmdPrivData(interp); struct command_context *cmd_ctx = current_command_context(interp);
assert(cmd_ctx);
struct target *target = get_current_target(cmd_ctx);
Jim_SetResultString(interp, target_state_name(target), -1); Jim_SetResultString(interp, target_state_name(target), -1);
return JIM_OK; return JIM_OK;
} }
@ -5499,7 +5524,9 @@ static int jim_target_invoke_event(Jim_Interp *interp, int argc, Jim_Obj *const
Jim_GetOpt_NvpUnknown(&goi, nvp_target_event, 1); Jim_GetOpt_NvpUnknown(&goi, nvp_target_event, 1);
return e; return e;
} }
struct target *target = Jim_CmdPrivData(interp); struct command_context *cmd_ctx = current_command_context(interp);
assert(cmd_ctx);
struct target *target = get_current_target(cmd_ctx);
target_handle_event(target, n->value); target_handle_event(target, n->value);
return JIM_OK; return JIM_OK;
} }
@ -5877,7 +5904,7 @@ static int target_create(Jim_GetOptInfo *goi)
}, },
COMMAND_REGISTRATION_DONE COMMAND_REGISTRATION_DONE
}; };
e = register_commands(cmd_ctx, NULL, target_commands); e = register_commands_override_target(cmd_ctx, NULL, target_commands, target);
if (e != ERROR_OK) { if (e != ERROR_OK) {
if (target->type->deinit_target) if (target->type->deinit_target)
target->type->deinit_target(target); target->type->deinit_target(target);
@ -5890,10 +5917,6 @@ static int target_create(Jim_GetOptInfo *goi)
return JIM_ERR; return JIM_ERR;
} }
struct command *c = command_find_in_context(cmd_ctx, cp);
assert(c);
command_set_handler_data(c, target);
/* append to end of list */ /* append to end of list */
append_to_list_all_targets(target); append_to_list_all_targets(target);

View File

@ -79,7 +79,7 @@ proc init_l2cc { } {
; #orr r0, r0, #(1 << 22) /* disable write allocate */ ; #orr r0, r0, #(1 << 22) /* disable write allocate */
; #mcr 15, 1, r0, c9, c0, 2 ; #mcr 15, 1, r0, c9, c0, 2
arm mcr 15 1 9 0 2 [expr 0xC4 | (1<<24) | (1<<23) | (1<22)] arm mcr 15 1 9 0 2 [expr 0xC4 | (1<<24) | (1<<23) | (1<<22)]
} }

View File

@ -75,7 +75,7 @@ proc init_l2cc { } {
; #orr r0, r0, #(1 << 22) /* disable write allocate */ ; #orr r0, r0, #(1 << 22) /* disable write allocate */
; #mcr 15, 1, r0, c9, c0, 2 ; #mcr 15, 1, r0, c9, c0, 2
arm mcr 15 1 9 0 2 [expr 0xC4 | (1<<24) | (1<<23) | (1<22)] arm mcr 15 1 9 0 2 [expr 0xC4 | (1<<24) | (1<<23) | (1<<22)]
} }

View File

@ -80,7 +80,7 @@ proc init_l2cc { } {
; #orr r0, r0, #(1 << 22) /* disable write allocate */ ; #orr r0, r0, #(1 << 22) /* disable write allocate */
; #mcr 15, 1, r0, c9, c0, 2 ; #mcr 15, 1, r0, c9, c0, 2
arm mcr 15 1 9 0 2 [expr 0xC4 | (1<<24) | (1<<23) | (1<22)] arm mcr 15 1 9 0 2 [expr 0xC4 | (1<<24) | (1<<23) | (1<<22)]
} }

11
tcl/board/pico-debug.cfg Normal file
View File

@ -0,0 +1,11 @@
# SPDX-License-Identifier: GPL-2.0-or-later
# pico-debug is a virtual CMSIS-DAP debug adapter
# it runs on the very same RP2040 target being debugged without additional hardware
# https://github.com/majbthrd/pico-debug
source [find interface/cmsis-dap.cfg]
adapter speed 4000
set CHIPNAME rp2040
source [find target/rp2040-core0.cfg]

View File

@ -26,30 +26,30 @@
# tdf_cycles # tdf_cycles
proc sam9_smc_config { cs smc_config } { proc sam9_smc_config { cs smc_config } {
;# Setup Register for CS n ;# Setup Register for CS n
set AT91_SMC_SETUP [expr ($::AT91_SMC + 0x00 + ((cs)*0x10))] set AT91_SMC_SETUP [expr {$::AT91_SMC + 0x00 + $cs * 0x10}]
set val [expr ($smc_config(nwe_setup) << 0)] set val [expr {$smc_config(nwe_setup) << 0}]
set val [expr ($val | $smc_config(ncs_write_setup) << 8] set val [expr {$val | $smc_config(ncs_write_setup) << 8}]
set val [expr ($val | $smc_config(nrd_setup)) << 16] set val [expr {$val | $smc_config(nrd_setup)) << 16}]
set val [expr ($val | $smc_config(ncs_read_setup) << 24] set val [expr {$val | $smc_config(ncs_read_setup) << 24}]
mww $AT91_SMC_SETUP $val mww $AT91_SMC_SETUP $val
;# Pulse Register for CS n ;# Pulse Register for CS n
set AT91_SMC_PULSE [expr ($::AT91_SMC + 0x04 + ((cs)*0x10))] set AT91_SMC_PULSE [expr {$::AT91_SMC + 0x04 + $cs * 0x10}]
set val [expr ($smc_config(nwe_pulse) << 0)] set val [expr {$smc_config(nwe_pulse) << 0}]
set val [expr ($val | $smc_config(ncs_write_pulse) << 8] set val [expr {$val | $smc_config(ncs_write_pulse) << 8}]
set val [expr ($val | $smc_config(nrd_pulse) << 16] set val [expr {$val | $smc_config(nrd_pulse) << 16}]
set val [expr ($val | $smc_config(ncs_read_pulse) << 24] set val [expr {$val | $smc_config(ncs_read_pulse) << 24}]
mww $AT91_SMC_PULSE $val mww $AT91_SMC_PULSE $val
;# Cycle Register for CS n ;# Cycle Register for CS n
set AT91_SMC_CYCLE [expr ($::AT91_SMC + 0x08 + ((cs)*0x10))] set AT91_SMC_CYCLE [expr {$::AT91_SMC + 0x08 + $cs * 0x10}]
set val [expr ($smc_config(write_cycle) << 0)] set val [expr {$smc_config(write_cycle) << 0}]
set val [expr ($val | $smc_config(read_cycle) << 16] set val [expr {$val | $smc_config(read_cycle) << 16}]
mww $AT91_SMC_CYCLE $val mww $AT91_SMC_CYCLE $val
;# Mode Register for CS n ;# Mode Register for CS n
set AT91_SMC_MODE [expr ($::AT91_SMC + 0x0c + ((cs)*0x10))] set AT91_SMC_MODE [expr {$::AT91_SMC + 0x0c + $cs * 0x10}]
set val [expr ($smc_config(mode) << 0)] set val [expr {$smc_config(mode) << 0}]
set val [expr ($val | $smc_config(tdf_cycles) << 16] set val [expr {$val | $smc_config(tdf_cycles) << 16}]
mww $AT91_SMC_MODE $val mww $AT91_SMC_MODE $val
} }

89
tcl/target/imx8qm.cfg Normal file
View File

@ -0,0 +1,89 @@
#
# NXP i.MX8QuadMax
#
if { [info exists CHIPNAME] } {
set _CHIPNAME $CHIPNAME
} else {
set _CHIPNAME imx8qm
}
# CoreSight Debug Access Port (DAP)
if { [info exists DAP_TAPID] } {
set _DAP_TAPID $DAP_TAPID
} else {
# TAPID is from FreeScale!
set _DAP_TAPID 0x1890101d
}
jtag newtap $_CHIPNAME cpu -irlen 4 -ircapture 0x01 -irmask 0x0f \
-expected-id $_DAP_TAPID
dap create $_CHIPNAME.dap -chain-position $_CHIPNAME.cpu
# AXI: Main SOC bus on AP #0
target create ${_CHIPNAME}.axi mem_ap -dap ${_CHIPNAME}.dap -ap-num 0
# 4x Cortex-A53 on AP #6
set _A53_DBGBASE {0x80410000 0x80510000 0x80610000 0x80710000}
set _A53_CTIBASE {0x80420000 0x80520000 0x80620000 0x80720000}
cti create $_CHIPNAME.a53_cti.0 -dap $_CHIPNAME.dap \
-ap-num 6 -baseaddr [lindex $_A53_CTIBASE 0]
cti create $_CHIPNAME.a53_cti.1 -dap $_CHIPNAME.dap \
-ap-num 6 -baseaddr [lindex $_A53_CTIBASE 1]
cti create $_CHIPNAME.a53_cti.2 -dap $_CHIPNAME.dap \
-ap-num 6 -baseaddr [lindex $_A53_CTIBASE 2]
cti create $_CHIPNAME.a53_cti.3 -dap $_CHIPNAME.dap \
-ap-num 6 -baseaddr [lindex $_A53_CTIBASE 3]
target create $_CHIPNAME.a53.0 aarch64 -dap $_CHIPNAME.dap \
-cti $_CHIPNAME.a53_cti.0 -dbgbase [lindex $_A53_DBGBASE 0]
target create $_CHIPNAME.a53.1 aarch64 -dap $_CHIPNAME.dap \
-cti $_CHIPNAME.a53_cti.1 -dbgbase [lindex $_A53_DBGBASE 1] -defer-examine
target create $_CHIPNAME.a53.2 aarch64 -dap $_CHIPNAME.dap \
-cti $_CHIPNAME.a53_cti.2 -dbgbase [lindex $_A53_DBGBASE 2] -defer-examine
target create $_CHIPNAME.a53.3 aarch64 -dap $_CHIPNAME.dap \
-cti $_CHIPNAME.a53_cti.3 -dbgbase [lindex $_A53_DBGBASE 3] -defer-examine
# 2x Cortex-A72 on AP #6
set _A72_DBGBASE {0x80210000 0x80310000}
set _A72_CTIBASE {0x80220000 0x80220000}
cti create $_CHIPNAME.a72_cti.0 -dap $_CHIPNAME.dap \
-ap-num 6 -baseaddr [lindex $_A72_CTIBASE 0]
cti create $_CHIPNAME.a72_cti.1 -dap $_CHIPNAME.dap \
-ap-num 6 -baseaddr [lindex $_A72_CTIBASE 1]
target create $_CHIPNAME.a72.0 aarch64 -dap $_CHIPNAME.dap \
-cti $_CHIPNAME.a72_cti.0 -dbgbase [lindex $_A72_DBGBASE 0] -defer-examine
target create $_CHIPNAME.a72.1 aarch64 -dap $_CHIPNAME.dap \
-cti $_CHIPNAME.a72_cti.1 -dbgbase [lindex $_A72_DBGBASE 1] -defer-examine
# All Cortex-A in SMP
target smp \
$_CHIPNAME.a53.0 \
$_CHIPNAME.a53.1 \
$_CHIPNAME.a53.2 \
$_CHIPNAME.a53.3 \
$_CHIPNAME.a72.0 \
$_CHIPNAME.a72.1
# SCU: Cortex-M4 core
# always running imx SC firmware
target create ${_CHIPNAME}.scu cortex_m -dap ${_CHIPNAME}.dap -ap-num 1
# AHB from SCU perspective
target create ${_CHIPNAME}.scu_ahb mem_ap -dap ${_CHIPNAME}.dap -ap-num 4
# Cortex-M4 M4_0 core on AP #2 (default off)
target create ${_CHIPNAME}.m4_0 cortex_m -dap ${_CHIPNAME}.dap -ap-num 2 \
-defer-examine
# Cortex-M4 M4_1 core on AP #3 (default off)
target create ${_CHIPNAME}.m4_1 cortex_m -dap ${_CHIPNAME}.dap -ap-num 3 \
-defer-examine
# Debug APB bus
target create ${_CHIPNAME}.apb mem_ap -dap ${_CHIPNAME}.dap -ap-num 6
# Default target is boot core a53.0
targets $_CHIPNAME.a53.0

View File

@ -0,0 +1,38 @@
# SPDX-License-Identifier: GPL-2.0-or-later
transport select swd
source [find target/swj-dp.tcl]
if { [info exists CHIPNAME] } {
set _CHIPNAME $CHIPNAME
} else {
set _CHIPNAME rp2040
}
if { [info exists WORKAREASIZE] } {
set _WORKAREASIZE $WORKAREASIZE
} else {
set _WORKAREASIZE 0x10000
}
if { [info exists CPUTAPID] } {
set _CPUTAPID $CPUTAPID
} else {
set _CPUTAPID 0x01002927
}
swj_newdap $_CHIPNAME cpu -expected-id $_CPUTAPID
dap create $_CHIPNAME.dap -chain-position $_CHIPNAME.cpu
set _TARGETNAME $_CHIPNAME.cpu
target create $_TARGETNAME cortex_m -dap $_CHIPNAME.dap
$_TARGETNAME configure -work-area-phys 0x20010000 -work-area-size $_WORKAREASIZE
set _FLASHNAME $_CHIPNAME.flash
set _FLASHSIZE 0x200000
set _FLASHBASE 0x10000000
flash bank $_FLASHNAME rp2040_flash $_FLASHBASE $_FLASHSIZE 1 32 $_TARGETNAME
# srst does not exist; use SYSRESETREQ to perform a soft reset
cortex_m reset_config sysresetreq