aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorEvgeniy Naydanov <109669442+en-sc@users.noreply.github.com>2025-09-12 12:57:16 +0300
committerGitHub <noreply@github.com>2025-09-12 12:57:16 +0300
commit48483a84a064ee5487aa3e8a2c2494722a3c3849 (patch)
treec257d9a9f54558064219ed565088000ee0883ce4 /src
parent39d4c50950817d0622aa468a675091ea9a0b23c2 (diff)
parent517c40ba8d2da7dfdbcccd04dd3fba59da633213 (diff)
downloadriscv-openocd-riscv.zip
riscv-openocd-riscv.tar.gz
riscv-openocd-riscv.tar.bz2
Merge pull request #1267 from en-sc/en-sc/from_upstreamHEADlatestriscv
Merge up to afbd01b0a46f3a81fe6076c002ad66973dcfb64c from upstream
Diffstat (limited to 'src')
-rw-r--r--src/flash/nor/Makefile.am2
-rw-r--r--src/flash/nor/driver.h2
-rw-r--r--src/flash/nor/drivers.c2
-rw-r--r--src/flash/nor/rp2040.c533
-rw-r--r--src/flash/nor/rp2xxx.c1442
-rw-r--r--src/flash/nor/stellaris.c2
-rw-r--r--src/flash/nor/stm32l4x.c34
-rw-r--r--src/flash/nor/stm32l4x.h2
-rw-r--r--src/helper/command.c145
-rw-r--r--src/helper/list.h4
-rw-r--r--src/jtag/adapter.c37
-rw-r--r--src/jtag/core.c10
-rw-r--r--src/jtag/drivers/am335xgpio.c5
-rw-r--r--src/jtag/drivers/amt_jtagaccel.c3
-rw-r--r--src/jtag/drivers/angie.c3
-rw-r--r--src/jtag/drivers/arm-jtag-ew.c3
-rw-r--r--src/jtag/drivers/at91rm9200.c3
-rw-r--r--src/jtag/drivers/bcm2835gpio.c5
-rw-r--r--src/jtag/drivers/buspirate.c5
-rw-r--r--src/jtag/drivers/cmsis_dap.c5
-rw-r--r--src/jtag/drivers/dmem.c5
-rw-r--r--src/jtag/drivers/dummy.c3
-rw-r--r--src/jtag/drivers/ep93xx.c3
-rw-r--r--src/jtag/drivers/esp_usb_jtag.c3
-rw-r--r--src/jtag/drivers/ft232r.c3
-rw-r--r--src/jtag/drivers/ftdi.c5
-rw-r--r--src/jtag/drivers/gw16012.c3
-rw-r--r--src/jtag/drivers/imx_gpio.c5
-rw-r--r--src/jtag/drivers/jlink.c5
-rw-r--r--src/jtag/drivers/jtag_dpi.c3
-rw-r--r--src/jtag/drivers/jtag_vpi.c3
-rw-r--r--src/jtag/drivers/kitprog.c5
-rw-r--r--src/jtag/drivers/linuxgpiod.c5
-rw-r--r--src/jtag/drivers/linuxspidev.c6
-rw-r--r--src/jtag/drivers/opendous.c3
-rw-r--r--src/jtag/drivers/openjtag.c3
-rw-r--r--src/jtag/drivers/osbdm.c3
-rw-r--r--src/jtag/drivers/parport.c3
-rw-r--r--src/jtag/drivers/presto.c3
-rw-r--r--src/jtag/drivers/remote_bitbang.c5
-rw-r--r--src/jtag/drivers/rlink.c3
-rw-r--r--src/jtag/drivers/rshim.c5
-rw-r--r--src/jtag/drivers/stlink_usb.c12
-rw-r--r--src/jtag/drivers/sysfsgpio.c5
-rw-r--r--src/jtag/drivers/ulink.c3
-rw-r--r--src/jtag/drivers/usb_blaster/usb_blaster.c3
-rw-r--r--src/jtag/drivers/usbprog.c3
-rw-r--r--src/jtag/drivers/vdebug.c5
-rw-r--r--src/jtag/drivers/vsllink.c5
-rw-r--r--src/jtag/drivers/xds110.c5
-rw-r--r--src/jtag/drivers/xlnx-pcie-xvc.c5
-rw-r--r--src/jtag/hla/hla_interface.c3
-rw-r--r--src/jtag/hla/hla_interface.h2
-rw-r--r--src/jtag/hla/hla_transport.c21
-rw-r--r--src/jtag/interface.h15
-rw-r--r--src/jtag/swim.c2
-rw-r--r--src/target/Makefile.am1
-rw-r--r--src/target/aarch64.c4
-rw-r--r--src/target/adi_v5_dapdirect.c4
-rw-r--r--src/target/adi_v5_swd.c2
-rw-r--r--src/target/arc.c2
-rw-r--r--src/target/arm11.c2
-rw-r--r--src/target/arm720t.c2
-rw-r--r--src/target/arm7tdmi.c2
-rw-r--r--src/target/arm920t.c2
-rw-r--r--src/target/arm926ejs.c2
-rw-r--r--src/target/arm946e.c2
-rw-r--r--src/target/arm966e.c2
-rw-r--r--src/target/arm9tdmi.c2
-rw-r--r--src/target/avr32_ap7k.c2
-rw-r--r--src/target/avrt.c4
-rw-r--r--src/target/cortex_a.c4
-rw-r--r--src/target/cortex_m.c2
-rw-r--r--src/target/dsp563xx.c2
-rw-r--r--src/target/dsp5680xx.c2
-rw-r--r--src/target/esirisc.c2
-rw-r--r--src/target/espressif/esp32.c2
-rw-r--r--src/target/espressif/esp32s2.c2
-rw-r--r--src/target/espressif/esp32s3.c2
-rw-r--r--src/target/fa526.c2
-rw-r--r--src/target/feroceon.c4
-rw-r--r--src/target/hla_target.c3
-rw-r--r--src/target/ls1_sap.c2
-rw-r--r--src/target/mem_ap.c2
-rw-r--r--src/target/mips_m4k.c2
-rw-r--r--src/target/mips_mips64.c2
-rw-r--r--src/target/openrisc/or1k.c2
-rw-r--r--src/target/quark_d20xx.c2
-rw-r--r--src/target/quark_x10xx.c2
-rw-r--r--src/target/riscv/riscv.c2
-rw-r--r--src/target/stm8.c52
-rw-r--r--src/target/stm8.h63
-rw-r--r--src/target/target.c600
-rw-r--r--src/target/target_type.h2
-rw-r--r--src/target/xscale.c2
-rw-r--r--src/target/xtensa/xtensa_chip.c2
-rw-r--r--src/transport/transport.c231
-rw-r--r--src/transport/transport.h38
98 files changed, 2274 insertions, 1215 deletions
diff --git a/src/flash/nor/Makefile.am b/src/flash/nor/Makefile.am
index 147807f..7a81b28 100644
--- a/src/flash/nor/Makefile.am
+++ b/src/flash/nor/Makefile.am
@@ -59,7 +59,7 @@ NOR_DRIVERS = \
%D%/psoc6.c \
%D%/qn908x.c \
%D%/renesas_rpchf.c \
- %D%/rp2040.c \
+ %D%/rp2xxx.c \
%D%/rsl10.c \
%D%/sfdp.c \
%D%/sh_qspi.c \
diff --git a/src/flash/nor/driver.h b/src/flash/nor/driver.h
index 794566f..3b57ef9 100644
--- a/src/flash/nor/driver.h
+++ b/src/flash/nor/driver.h
@@ -289,7 +289,7 @@ extern const struct flash_driver psoc5lp_nvl_flash;
extern const struct flash_driver psoc6_flash;
extern const struct flash_driver qn908x_flash;
extern const struct flash_driver renesas_rpchf_flash;
-extern const struct flash_driver rp2040_flash;
+extern const struct flash_driver rp2xxx_flash;
extern const struct flash_driver rsl10_flash;
extern const struct flash_driver sh_qspi_flash;
extern const struct flash_driver sim3x_flash;
diff --git a/src/flash/nor/drivers.c b/src/flash/nor/drivers.c
index 67d8624..3770bfb 100644
--- a/src/flash/nor/drivers.c
+++ b/src/flash/nor/drivers.c
@@ -66,7 +66,7 @@ static const struct flash_driver * const flash_drivers[] = {
&psoc6_flash,
&qn908x_flash,
&renesas_rpchf_flash,
- &rp2040_flash,
+ &rp2xxx_flash,
&sh_qspi_flash,
&sim3x_flash,
&stellaris_flash,
diff --git a/src/flash/nor/rp2040.c b/src/flash/nor/rp2040.c
deleted file mode 100644
index b2ebd9c..0000000
--- a/src/flash/nor/rp2040.c
+++ /dev/null
@@ -1,533 +0,0 @@
-// 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;
-};
-
-/* guessed SPI flash description if autodetection disabled (same as win w25q16jv) */
-static const struct flash_device rp2040_default_spi_device =
- FLASH_ID("autodetect disabled", 0x03, 0x00, 0x02, 0xd8, 0xc7, 0, 0x100, 0x10000, 0);
-
-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, unsigned int timeout_ms)
-{
- 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_TARGET_DEBUG(target, "Calling ROM func @0x%" PRIx16 " with %u arguments", func_offset, n_args);
-
- 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);
- /* Setup stack */
- init_reg_param(&args[n_args + 1], "sp", 32, PARAM_OUT);
- buf_set_u32(args[n_args + 1].value, 0, 32, stacktop);
- unsigned int n_reg_params = n_args + 2; /* User arguments + r7 + sp */
-
- for (unsigned int i = 0; i < n_reg_params; ++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_reg_params, args, /* User arguments + r7 + sp */
- priv->jump_debug_trampoline, priv->jump_debug_trampoline_end,
- timeout_ms,
- &alg_info
- );
-
- for (unsigned int i = 0; i < n_reg_params; ++i)
- destroy_reg_param(&args[i]);
-
- if (err != ERROR_OK)
- LOG_ERROR("Failed to invoke ROM function @0x%" PRIx16, func_offset);
-
- return err;
-}
-
-/* Finalize flash write/erase/read ID
- * - flush cache
- * - enters memory-mapped (XIP) mode to make flash data visible
- * - deallocates target ROM func stack if previously allocated
- */
-static int rp2040_finalize_stack_free(struct flash_bank *bank)
-{
- struct rp2040_flash_bank *priv = bank->driver_priv;
- struct target *target = bank->target;
-
- /* Always flush before returning to execute-in-place, to invalidate stale
- * cache contents. The flush call also restores regular hardware-controlled
- * chip select following a rp2040_flash_exit_xip().
- */
- LOG_DEBUG("Flushing flash cache after write behind");
- int err = rp2040_call_rom_func(target, priv, priv->jump_flush_cache, NULL, 0, 1000);
- if (err != ERROR_OK) {
- LOG_ERROR("Failed to flush flash cache");
- /* Intentionally continue after error and try to setup xip anyway */
- }
-
- LOG_DEBUG("Configuring SSI for execute-in-place");
- err = rp2040_call_rom_func(target, priv, priv->jump_enter_cmd_xip, NULL, 0, 1000);
- if (err != ERROR_OK)
- LOG_ERROR("Failed to set SSI to XIP mode");
-
- target_free_working_area(target, priv->stack);
- priv->stack = NULL;
- return err;
-}
-
-/* Prepare flash write/erase/read ID
- * - allocates a stack for target ROM func
- * - switches the SPI interface from memory-mapped mode to direct command mode
- * Always pair with a call of rp2040_finalize_stack_free()
- * after flash operation finishes or fails.
- */
-static int rp2040_stack_grab_and_prep(struct flash_bank *bank)
-{
- struct rp2040_flash_bank *priv = bank->driver_priv;
- struct target *target = bank->target;
-
- /* 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(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(target, priv, priv->jump_connect_internal_flash, NULL, 0, 1000);
- if (err != ERROR_OK) {
- LOG_ERROR("Failed to connect internal flash");
- return err;
- }
-
- LOG_DEBUG("Kicking flash out of XIP mode");
- err = rp2040_call_rom_func(target, priv, priv->jump_flash_exit_xip, NULL, 0, 1000);
- if (err != ERROR_OK) {
- LOG_ERROR("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;
-
- if (target->state != TARGET_HALTED) {
- LOG_ERROR("Target not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- struct working_area *bounce = NULL;
-
- int err = rp2040_stack_grab_and_prep(bank);
- if (err != ERROR_OK)
- goto cleanup;
-
- unsigned int avail_pages = target_get_working_area_avail(target) / priv->dev->pagesize;
- /* We try to allocate working area rounded down to device page size,
- * al least 1 page, at most the write data size
- */
- unsigned int chunk_size = MIN(MAX(avail_pages, 1) * priv->dev->pagesize, count);
- err = target_alloc_working_area(target, chunk_size, &bounce);
- if (err != ERROR_OK) {
- LOG_ERROR("Could not allocate bounce buffer for flash programming. Can't continue");
- goto cleanup;
- }
-
- 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), 3000);
- if (err != ERROR_OK) {
- LOG_ERROR("Failed to invoke flash programming code on target");
- break;
- }
-
- buffer += write_size;
- offset += write_size;
- count -= write_size;
- }
-
-cleanup:
- target_free_working_area(target, bounce);
-
- rp2040_finalize_stack_free(bank);
-
- 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;
- struct target *target = bank->target;
-
- if (target->state != TARGET_HALTED) {
- LOG_ERROR("Target not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- 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 = rp2040_stack_grab_and_prep(bank);
- if (err != ERROR_OK)
- goto cleanup;
-
- 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).
- */
-
- unsigned int timeout_ms = 2000 * (last - first) + 1000;
- err = rp2040_call_rom_func(target, priv, priv->jump_flash_range_erase,
- args, ARRAY_SIZE(args), timeout_ms);
-
-cleanup:
- rp2040_finalize_stack_free(bank);
-
- 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_spi_read_flash_id(struct target *target, uint32_t *devid)
-{
- uint32_t device_id = 0;
- const target_addr_t ssi_dr0 = 0x18000060;
-
- int 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;
- }
-
- if (err == ERROR_OK)
- *devid = device_id >> 8;
-
- int err2 = rp2040_ssel_active(target, false);
- if (err2 != ERROR_OK)
- LOG_ERROR("SSEL inactive failed");
-
- return err;
-}
-
-static int rp2040_flash_probe(struct flash_bank *bank)
-{
- struct rp2040_flash_bank *priv = bank->driver_priv;
- struct target *target = bank->target;
-
- if (target->state != TARGET_HALTED) {
- LOG_ERROR("Target not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- 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;
- }
-
- if (bank->size) {
- /* size overridden, suppress reading SPI flash ID */
- priv->dev = &rp2040_default_spi_device;
- LOG_DEBUG("SPI flash autodetection disabled, using configured size");
-
- } else {
- /* zero bank size in cfg, read SPI flash ID and autodetect */
- err = rp2040_stack_grab_and_prep(bank);
-
- uint32_t device_id = 0;
- if (err == ERROR_OK)
- err = rp2040_spi_read_flash_id(target, &device_id);
-
- rp2040_finalize_stack_free(bank);
-
- if (err != ERROR_OK)
- 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);
-
- bank->size = priv->dev->size_in_bytes;
- }
-
- /* 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->num_sectors = bank->size / priv->dev->sectorsize;
- LOG_INFO("RP2040 B0 Flash Probe: %" PRIu32 " bytes @" TARGET_ADDR_FMT ", in %u 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;
-}
-
-const struct flash_driver rp2040_flash = {
- .name = "rp2040_flash",
- .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
-};
diff --git a/src/flash/nor/rp2xxx.c b/src/flash/nor/rp2xxx.c
new file mode 100644
index 0000000..85c5911
--- /dev/null
+++ b/src/flash/nor/rp2xxx.c
@@ -0,0 +1,1442 @@
+// 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"
+#include "sfdp.h"
+#include <target/cortex_m.h>
+
+/* this is 'M' 'u', 1 (version) */
+#define BOOTROM_RP2040_MAGIC 0x01754d
+/* this is 'M' 'u', 2 (version) */
+#define BOOTROM_RP2350_MAGIC 0x02754d
+#define BOOTROM_MAGIC_MASK 0xffffff
+#define BOOTROM_MAGIC_ADDR 0x00000010
+
+#define MAKE_TAG(a, b) (((b)<<8) | a)
+#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')
+#define FUNC_BOOTROM_STATE_RESET MAKE_TAG('S', 'R')
+#define FUNC_BOOTROM_SET_STACK MAKE_TAG('S', 'S')
+#define FUNC_FLASH_RESET_ADDRESS_TRANS MAKE_TAG('R', 'A')
+
+/* ROM table flags for RP2350 A1 ROM onwards */
+#define RT_FLAG_FUNC_RISCV 0x01
+#define RT_FLAG_FUNC_ARM_SEC 0x04
+#define RT_FLAG_FUNC_ARM_NONSEC 0x10
+#define RT_FLAG_DATA 0x40
+
+// these form a bit set
+#define BOOTROM_STATE_RESET_CURRENT_CORE 0x01
+#define BOOTROM_STATE_RESET_OTHER_CORE 0x02
+#define BOOTROM_STATE_RESET_GLOBAL_STATE 0x04
+
+#define ACCESSCTRL_LOCK_OFFSET 0x40060000u
+#define ACCESSCTRL_LOCK_DEBUG_BITS 0x00000008u
+#define ACCESSCTRL_CFGRESET_OFFSET 0x40060008u
+#define ACCESSCTRL_WRITE_PASSWORD 0xacce0000u
+
+#define RP2040_SSI_DR0 0x18000060
+#define RP2040_QSPI_CTRL 0x4001800c
+
+#define RP2040_QSPI_CTRL_OUTOVER_MASK (3ul << 8)
+#define RP2040_QSPI_CTRL_OUTOVER_LOW (2ul << 8)
+#define RP2040_QSPI_CTRL_OUTOVER_HIGH (3ul << 8)
+
+#define RP2350_QMI_DIRECT_CSR 0x400d0000
+#define RP2350_QMI_DIRECT_TX 0x400d0004
+#define RP2350_QMI_DIRECT_RX 0x400d0008
+
+#define RP2350_QMI_DIRECT_CSR_EN BIT(0)
+#define RP2350_QMI_DIRECT_CSR_ASSERT_CS0N BIT(2)
+#define RP2350_QMI_DIRECT_TX_NOPUSH BIT(20)
+#define RP2350_QMI_DIRECT_TX_OE BIT(19)
+
+#define RP2XXX_SYSINFO_CHIP_ID 0x40000000
+#define RP2XXX_CHIP_ID_PART_MANUFACTURER(id) ((id) & 0x0fffffff)
+#define RP2XXX_CHIP_ID_MANUFACTURER 0x493
+#define RP2XXX_MK_PART(part) (((part) << 12) | (RP2XXX_CHIP_ID_MANUFACTURER << 1) | 1)
+#define RP2040_CHIP_ID_PART 0x0002
+#define IS_RP2040(id) (RP2XXX_CHIP_ID_PART_MANUFACTURER(id) == RP2XXX_MK_PART(RP2040_CHIP_ID_PART))
+#define RP2350_CHIP_ID_PART 0x0004
+#define IS_RP2350(id) (RP2XXX_CHIP_ID_PART_MANUFACTURER(id) == RP2XXX_MK_PART(RP2350_CHIP_ID_PART))
+#define RP2XXX_CHIP_ID_REVISION(id) ((id) >> 28)
+
+#define RP2XXX_MAX_ALGO_STACK_USAGE 1024
+#define RP2XXX_MAX_RAM_ALGO_SIZE 1024
+
+#define RP2XXX_ROM_API_FIXED_FLASH_PAGE 256
+#define RP2XXX_ROM_API_FIXED_FLASH_SECTOR 4096
+
+// Calling bootrom functions on Arm RP2350 requires the redundancy
+// coprocessor (RCP) to be initialised. Usually this is done first thing by
+// the bootrom, but the debugger may skip this, e.g. by resetting the cores
+// and then running a NO_FLASH binary, or by reset-halting the cores before
+// flash programming.
+//
+// The first case can be handled by a stub in the binary itself to initialise
+// the RCP with dummy values if the bootrom has not already initialised it.
+// (Note this case is only reachable via the debugger.) The second case
+// requires the debugger itself to initialise the RCP, using this stub code:
+
+static const int rcp_init_code_bkpt_offset = 24;
+static const uint8_t rcp_init_code[] = {
+ // Just enable the RCP which is fine if it already was (we assume no other
+ // co-processors are enabled at this point to save space)
+ 0x06, 0x48, // ldr r0, = PPB_BASE + M33_CPACR_OFFSET
+ 0x5f, 0xf4, 0x40, 0x41, // movs r1, #M33_CPACR_CP7_BITS
+ 0x01, 0x60, // str r1, [r0]
+ // Only initialize canary seeds if they haven't been (as to do so twice is a fault)
+ 0x30, 0xee, 0x10, 0xf7, // mrc p7, #1, r15, c0, c0, #0
+ 0x04, 0xd4, // bmi 1f
+ // Todo should we use something random here and pass it into the algorithm?
+ 0x40, 0xec, 0x80, 0x07, // mcrr p7, #8, r0, r0, c0
+ 0x40, 0xec, 0x81, 0x07, // mcrr p7, #8, r0, r0, c1
+ // Let other core know
+ 0x40, 0xbf, // sev
+ // 1:
+ 0x00, 0xbe, // bkpt (end of algorithm)
+ 0x00, 0x00, // pad
+ 0x88, 0xed, 0x00, 0xe0 // PPB_BASE + M33_CPACR_OFFSET
+};
+
+// An algorithm stub that can be concatenated with a null-terminated list of
+// (PC, SP, r0-r3) records to perform a batch of ROM calls under a single
+// OpenOCD algorithm call, to save on algorithm overhead:
+#define ROM_CALL_BATCH_ALGO_SIZE_BYTES 32
+static const int rp2xxx_rom_call_batch_algo_bkpt_offset = ROM_CALL_BATCH_ALGO_SIZE_BYTES - 2;
+static const uint8_t rp2xxx_rom_call_batch_algo_armv6m[ROM_CALL_BATCH_ALGO_SIZE_BYTES] = {
+// <_start>:
+ 0x07, 0xa7, // add r7, pc, #28 ; (adr r7, 20 <_args>)
+// <_do_next>:
+ 0x10, 0xcf, // ldmia r7!, {r4}
+ 0x00, 0x2c, // cmp r4, #0
+ 0x0a, 0xd0, // beq.n 1e <_done>
+ 0x20, 0xcf, // ldmia r7!, {r5}
+ 0xad, 0x46, // mov sp, r5
+ 0x0f, 0xcf, // ldmia r7!, {r0, r1, r2, r3}
+ 0xa0, 0x47, // blx r4
+ 0xf7, 0xe7, // b.n 2 <_do_next>
+ 0xc0, 0x46, // nop
+ 0xc0, 0x46, // nop
+ 0xc0, 0x46, // nop
+ 0xc0, 0x46, // nop
+ 0xc0, 0x46, // nop
+ 0xc0, 0x46, // nop
+// <_done>:
+ 0x00, 0xbe, // bkpt 0x0000
+// <_args>:
+};
+
+// The same as rom_call_batch_algo_armv6m, but clearing stack limits before setting stack:
+static const uint8_t rp2xxx_rom_call_batch_algo_armv8m[ROM_CALL_BATCH_ALGO_SIZE_BYTES] = {
+// <_start>:
+ 0x07, 0xa7, // add r7, pc, #28 ; (adr r7, 20 <_args>)
+ 0x00, 0x20, // movs r0, #0
+ 0x80, 0xf3, 0x0a, 0x88, // msr MSPLIM, r0
+ 0x80, 0xf3, 0x0b, 0x88, // msr PSPLIM, r0
+// <_do_next>:
+ 0x10, 0xcf, // ldmia r7!, {r4}
+ 0x00, 0x2c, // cmp r4, #0
+ 0x05, 0xd0, // beq.n 1e <_done>
+ 0x20, 0xcf, // ldmia r7!, {r5}
+ 0xad, 0x46, // mov sp, r5
+ 0x0f, 0xcf, // ldmia r7!, {r0, r1, r2, r3}
+ 0xa0, 0x47, // blx r4
+ 0xf7, 0xe7, // b.n c <_do_next>
+ 0xc0, 0x46, // nop
+// <_done>:
+ 0x00, 0xbe, // bkpt 0x0000
+// <_args>:
+};
+
+// The same as rom_call_batch_algo_armv6m, but placing arguments in a0-a3 on RISC-V:
+static const uint8_t rp2xxx_rom_call_batch_algo_riscv[ROM_CALL_BATCH_ALGO_SIZE_BYTES] = {
+// <_start>:
+ 0x97, 0x04, 0x00, 0x00, // auipc s1,0
+ 0x93, 0x84, 0x04, 0x02, // add s1,s1,32 # 20 <_args>
+// <_do_next>:
+ 0x98, 0x40, // lw a4,0(s1)
+ 0x11, 0xcb, // beqz a4,1e <_done>
+ 0x03, 0xa1, 0x44, 0x00, // lw sp,4(s1)
+ 0x88, 0x44, // lw a0,8(s1)
+ 0xcc, 0x44, // lw a1,12(s1)
+ 0x90, 0x48, // lw a2,16(s1)
+ 0xd4, 0x48, // lw a3,20(s1)
+ 0xe1, 0x04, // add s1,s1,24
+ 0x02, 0x97, // jalr a4
+ 0xf5, 0xb7, // j 8 <_do_next>
+// <_done>:
+ 0x02, 0x90, // ebreak
+// <_args>:
+};
+
+struct rp2xxx_rom_call_batch_record {
+ uint32_t pc;
+ uint32_t sp;
+ uint32_t args[4];
+};
+
+struct rp2xxx_flash_bank {
+ bool probed; /* flag indicating successful flash probe */
+ uint32_t id; /* cached SYSINFO CHIP_ID */
+ struct working_area *stack; /* stack used by Boot ROM calls */
+ /* static code scratchpad used for RAM algorithms -- allocated in advance
+ so that higher-level calls can just grab all remaining workarea: */
+ struct working_area *ram_algo_space;
+ /* function jump table populated by rp2xxx_flash_probe() */
+ 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_flash_reset_address_trans;
+ uint16_t jump_enter_cmd_xip;
+ uint16_t jump_bootrom_reset_state;
+ uint16_t jump_bootrom_set_varm_stack;
+
+ char dev_name[20];
+ bool size_override;
+ struct flash_device spi_dev; /* detected model of SPI flash */
+ unsigned int sfdp_dummy, sfdp_dummy_detect;
+};
+
+#ifndef LOG_ROM_SYMBOL_DEBUG
+#define LOG_ROM_SYMBOL_DEBUG LOG_DEBUG
+#endif
+
+static int rp2040_lookup_rom_symbol(struct target *target, uint16_t tag, uint16_t flags, uint16_t *symbol_out)
+{
+ LOG_ROM_SYMBOL_DEBUG("Looking up ROM symbol '%c%c' in RP2040 table", tag & 0xff, (tag >> 8) & 0xff);
+ if (flags != RT_FLAG_FUNC_ARM_SEC && flags != RT_FLAG_DATA) {
+ /* Note RT flags do not exist on RP2040, so just sanity check that we
+ are asked for a type of thing that actually exists in the ROM table */
+ LOG_ERROR("Only data and Secure Arm functions can be looked up in RP2040 ROM table");
+ return ERROR_FAIL;
+ }
+
+ uint16_t ptr_to_entry;
+ unsigned int offset_magic_to_table_ptr = flags == RT_FLAG_DATA ? 6 : 4;
+ int err = target_read_u16(target, BOOTROM_MAGIC_ADDR + offset_magic_to_table_ptr, &ptr_to_entry);
+ if (err != ERROR_OK)
+ return err;
+
+ uint16_t entry_tag;
+ do {
+ err = target_read_u16(target, ptr_to_entry, &entry_tag);
+ if (err != ERROR_OK)
+ return err;
+
+ if (entry_tag == tag) {
+ /* 16 bit symbol is next */
+ err = target_read_u16(target, ptr_to_entry + 2, symbol_out);
+ if (err != ERROR_OK)
+ return err;
+
+ LOG_ROM_SYMBOL_DEBUG(" -> found: 0x%04" PRIx16, *symbol_out);
+ return ERROR_OK;
+ }
+ ptr_to_entry += 4;
+ } while (entry_tag);
+ *symbol_out = 0;
+ return ERROR_FAIL;
+}
+
+static int rp2350_a0_lookup_symbol(struct target *target, uint16_t tag, uint16_t flags, uint16_t *symbol_out)
+{
+ LOG_ROM_SYMBOL_DEBUG("Looking up ROM symbol '%c%c' in RP2350 A0 table", tag & 0xff, (tag >> 8) & 0xff);
+
+ /* RP2350 A0 table format is the same as RP2040 except with 16 bits of
+ flags after each 16-bit pointer. We ignore the flags, as each symbol
+ only has one datum associated with it. */
+
+ uint32_t magic_ptr = BOOTROM_MAGIC_ADDR;
+ if (flags == RT_FLAG_FUNC_RISCV) {
+ /* RP2350 A0 used split function tables for Arm/RISC-V -- not used on
+ any other device or any other version of this device. There is a
+ well-known RISC-V table at the top of ROM, matching the well-known
+ Arm table at the bottom of ROM. */
+ magic_ptr = 0x7decu;
+ } else if (flags != RT_FLAG_FUNC_ARM_SEC) {
+ LOG_WARNING("Ignoring non-default flags for RP2350 A0 lookup, hope you like Secure Arm functions");
+ }
+
+ uint16_t ptr_to_entry;
+ const unsigned int offset_magic_to_table_ptr = 4;
+ int err = target_read_u16(target, magic_ptr + offset_magic_to_table_ptr, &ptr_to_entry);
+ if (err != ERROR_OK)
+ return err;
+
+ uint16_t entry_tag;
+ do {
+ err = target_read_u16(target, ptr_to_entry, &entry_tag);
+ if (err != ERROR_OK)
+ return err;
+
+ if (entry_tag == tag) {
+ err = target_read_u16(target, ptr_to_entry + 2, symbol_out);
+ if (err != ERROR_OK)
+ return err;
+
+ LOG_ROM_SYMBOL_DEBUG(" -> found: 0x%04" PRIx16, *symbol_out);
+ return ERROR_OK;
+ }
+ ptr_to_entry += 6;
+ } while (entry_tag);
+ *symbol_out = 0;
+ return ERROR_FAIL;
+}
+
+static int rp2350_lookup_rom_symbol(struct target *target, uint32_t ptr_to_entry,
+ uint16_t tag, uint16_t flags, uint16_t *symbol_out)
+{
+ LOG_ROM_SYMBOL_DEBUG("Looking up ROM symbol '%c%c' in RP2350 A1 table", tag & 0xff, (tag >> 8) & 0xff);
+
+ /* On RP2350 A1, Each entry has a flag bitmap identifying the type of its
+ contents. The entry contains one halfword of data for each set flag
+ bit. There may be both Arm and RISC-V entries under the same tag, or
+ separate Arm Secure/NonSecure entries (or all three, why not). */
+
+ while (true) {
+ uint16_t entry_tag, entry_flags;
+
+ int err = target_read_u16(target, ptr_to_entry, &entry_tag);
+ if (err != ERROR_OK)
+ return err;
+
+ if (entry_tag == 0) {
+ *symbol_out = 0;
+ return ERROR_FAIL;
+ }
+ ptr_to_entry += 2;
+
+ err = target_read_u16(target, ptr_to_entry, &entry_flags);
+ if (err != ERROR_OK)
+ return err;
+
+ ptr_to_entry += 2;
+
+ uint16_t matching_flags = flags & entry_flags;
+
+ if (tag == entry_tag && matching_flags != 0) {
+ /* This is our entry, seek to the correct data item and return it. */
+ bool is_riscv_func = matching_flags & RT_FLAG_FUNC_RISCV;
+ while (!(matching_flags & 1)) {
+ if (entry_flags & 1)
+ ptr_to_entry += 2;
+
+ matching_flags >>= 1;
+ entry_flags >>= 1;
+ }
+ if (is_riscv_func) {
+ /* For RISC-V, the table entry itself is the entry point -- trick
+ to make shared function implementations smaller */
+ *symbol_out = ptr_to_entry;
+ return ERROR_OK;
+ }
+ err = target_read_u16(target, ptr_to_entry, symbol_out);
+ if (err != ERROR_OK)
+ return err;
+
+ LOG_ROM_SYMBOL_DEBUG(" -> found: 0x%04" PRIx16, *symbol_out);
+ return ERROR_OK;
+ }
+ /* Skip past this entry */
+ while (entry_flags) {
+ if (entry_flags & 1)
+ ptr_to_entry += 2;
+
+ entry_flags >>= 1;
+ }
+ }
+}
+
+static int rp2xxx_lookup_rom_symbol(struct target *target, uint16_t tag, uint16_t flags, uint16_t *symbol_out)
+{
+ uint32_t magic;
+ int err = target_read_u32(target, BOOTROM_MAGIC_ADDR, &magic);
+ if (err != ERROR_OK)
+ return err;
+
+ /* Ignore version */
+ magic &= BOOTROM_MAGIC_MASK;
+
+ if (magic == BOOTROM_RP2350_MAGIC) {
+ /* Distinguish old-style RP2350 ROM table (A0, and earlier A1 builds)
+ based on position of table -- a high address means it is shared with
+ RISC-V, i.e. new-style. */
+ uint16_t table_ptr;
+ err = target_read_u16(target, BOOTROM_MAGIC_ADDR + 4, &table_ptr);
+ if (err != ERROR_OK)
+ return err;
+ if (table_ptr < 0x7c00)
+ return rp2350_a0_lookup_symbol(target, tag, flags, symbol_out);
+ else
+ return rp2350_lookup_rom_symbol(target, table_ptr, tag, flags, symbol_out);
+
+ } else if (magic == BOOTROM_RP2040_MAGIC) {
+ return rp2040_lookup_rom_symbol(target, tag, flags, symbol_out);
+ }
+ LOG_ERROR("RP2040/RP2350 BOOT ROM not found");
+ return ERROR_FAIL;
+}
+
+static int rp2xxx_populate_rom_pointer_cache(struct target *target, struct rp2xxx_flash_bank *priv)
+{
+ uint16_t symtype_func = is_arm(target_to_arm(target))
+ ? RT_FLAG_FUNC_ARM_SEC : RT_FLAG_FUNC_RISCV;
+ int err;
+ err = rp2xxx_lookup_rom_symbol(target, FUNC_FLASH_EXIT_XIP,
+ symtype_func, &priv->jump_flash_exit_xip);
+ if (err != ERROR_OK) {
+ LOG_ERROR("Function FUNC_FLASH_EXIT_XIP not found in RP2xxx ROM");
+ return err;
+ }
+
+ err = rp2xxx_lookup_rom_symbol(target, FUNC_CONNECT_INTERNAL_FLASH,
+ symtype_func, &priv->jump_connect_internal_flash);
+ if (err != ERROR_OK) {
+ LOG_ERROR("Function FUNC_CONNECT_INTERNAL_FLASH not found in RP2xxx ROM");
+ return err;
+ }
+
+ err = rp2xxx_lookup_rom_symbol(target, FUNC_FLASH_RANGE_ERASE, symtype_func, &priv->jump_flash_range_erase);
+ if (err != ERROR_OK) {
+ LOG_ERROR("Function FUNC_FLASH_RANGE_ERASE not found in RP2xxx ROM");
+ return err;
+ }
+
+ err = rp2xxx_lookup_rom_symbol(target, FUNC_FLASH_RANGE_PROGRAM, symtype_func, &priv->jump_flash_range_program);
+ if (err != ERROR_OK) {
+ LOG_ERROR("Function FUNC_FLASH_RANGE_PROGRAM not found in RP2xxx ROM");
+ return err;
+ }
+
+ err = rp2xxx_lookup_rom_symbol(target, FUNC_FLASH_FLUSH_CACHE, symtype_func, &priv->jump_flush_cache);
+ if (err != ERROR_OK) {
+ LOG_ERROR("Function FUNC_FLASH_FLUSH_CACHE not found in RP2xxx ROM");
+ return err;
+ }
+
+ err = rp2xxx_lookup_rom_symbol(target, FUNC_FLASH_ENTER_CMD_XIP, symtype_func, &priv->jump_enter_cmd_xip);
+ if (err != ERROR_OK) {
+ LOG_ERROR("Function FUNC_FLASH_ENTER_CMD_XIP not found in RP2xxx ROM");
+ return err;
+ }
+
+ // From this point are optional functions which do not exist on e.g. RP2040
+ // or pre-production RP2350 ROM versions:
+ if (IS_RP2040(priv->id)) {
+ priv->jump_bootrom_reset_state = 0;
+ priv->jump_flash_reset_address_trans = 0;
+ return ERROR_OK;
+ }
+
+ err = rp2xxx_lookup_rom_symbol(target, FUNC_BOOTROM_STATE_RESET, symtype_func, &priv->jump_bootrom_reset_state);
+ if (err != ERROR_OK) {
+ priv->jump_bootrom_reset_state = 0;
+ LOG_WARNING("Function FUNC_BOOTROM_STATE_RESET not found in RP2xxx ROM. (probably an RP2350 A0)");
+ }
+
+ if (!is_arm(target_to_arm(target))) {
+ err = rp2xxx_lookup_rom_symbol(target, FUNC_BOOTROM_SET_STACK, symtype_func,
+ &priv->jump_bootrom_set_varm_stack);
+ if (err != ERROR_OK) {
+ priv->jump_bootrom_set_varm_stack = 0;
+ LOG_WARNING("Function FUNC_BOOTROM_SET_STACK not found in RP2xxx ROM. (probably an RP2350 A0)");
+ }
+ }
+
+ err = rp2xxx_lookup_rom_symbol(target, FUNC_FLASH_RESET_ADDRESS_TRANS,
+ symtype_func, &priv->jump_flash_reset_address_trans);
+ if (err != ERROR_OK) {
+ priv->jump_flash_reset_address_trans = 0;
+ LOG_WARNING("Function FUNC_FLASH_RESET_ADDRESS_TRANS not found in RP2xxx ROM. (probably an RP2350 A0)");
+ }
+ return ERROR_OK;
+}
+
+// Call a list of PC + SP + r0-r3 function call tuples with a single OpenOCD
+// algorithm invocation, to amortise the algorithm overhead over multiple calls:
+static int rp2xxx_call_rom_func_batch(struct target *target, struct rp2xxx_flash_bank *priv,
+ struct rp2xxx_rom_call_batch_record *calls, unsigned int n_calls)
+{
+ // Note + sizeof(uint32_t) is for the null terminator
+ unsigned int batch_size = ROM_CALL_BATCH_ALGO_SIZE_BYTES
+ + n_calls * sizeof(struct rp2xxx_rom_call_batch_record)
+ + sizeof(uint32_t);
+
+ if (!priv->ram_algo_space) {
+ LOG_ERROR("No RAM code space allocated for ROM call");
+ return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
+ }
+ if (priv->ram_algo_space->size < batch_size) {
+ LOG_ERROR("RAM code space too small for call batch size of %u", n_calls);
+ return ERROR_BUF_TOO_SMALL;
+ }
+
+ LOG_TARGET_DEBUG(target, "Calling batch of %u ROM functions:", n_calls);
+ for (unsigned int i = 0; i < n_calls; ++i) {
+ LOG_DEBUG(" func @ %" PRIx32, calls[i].pc);
+ LOG_DEBUG(" sp = %" PRIx32, calls[i].sp);
+ for (unsigned int j = 0; j < 4; ++j)
+ LOG_DEBUG(" a%u = %" PRIx32, j, calls[i].args[j]);
+ }
+
+ if (n_calls <= 0) {
+ LOG_DEBUG("Returning early from call of 0 ROM functions");
+ return ERROR_OK;
+ }
+
+ const uint8_t *algo_code;
+ if (is_arm(target_to_arm(target))) {
+ if (target_to_arm(target)->arch == ARM_ARCH_V8M) {
+ LOG_DEBUG("Using algo: rp2xxx_rom_call_batch_algo_armv8m");
+ algo_code = rp2xxx_rom_call_batch_algo_armv8m;
+ } else {
+ LOG_DEBUG("Using algo: rp2xxx_rom_call_batch_algo_armv6m");
+ algo_code = rp2xxx_rom_call_batch_algo_armv6m;
+ }
+ } else {
+ LOG_DEBUG("Using algo: rp2xxx_rom_call_batch_algo_riscv");
+ algo_code = rp2xxx_rom_call_batch_algo_riscv;
+ }
+
+ uint8_t *batch_bf = malloc(batch_size);
+ if (!batch_bf) {
+ LOG_ERROR("No memory for batch buffer");
+ return ERROR_FAIL;
+ }
+ memcpy(batch_bf, algo_code, ROM_CALL_BATCH_ALGO_SIZE_BYTES);
+ unsigned int words = n_calls * sizeof(struct rp2xxx_rom_call_batch_record)
+ / sizeof(uint32_t);
+ target_buffer_set_u32_array(target,
+ &batch_bf[ROM_CALL_BATCH_ALGO_SIZE_BYTES], words,
+ (const uint32_t *)calls);
+ /* Null terminator */
+ target_buffer_set_u32(target, &batch_bf[batch_size - sizeof(uint32_t)], 0);
+
+ int err = target_write_buffer(target,
+ priv->ram_algo_space->address,
+ batch_size,
+ batch_bf
+ );
+ free(batch_bf);
+
+ if (err != ERROR_OK) {
+ LOG_ERROR("Failed to write ROM batch algorithm to RAM code space");
+ return err;
+ }
+
+ // Call into the ROM batch algorithm -- this will in turn call each ROM
+ // call specified by the batch records.
+ target_addr_t algo_start_addr = priv->ram_algo_space->address;
+ target_addr_t algo_end_addr = priv->ram_algo_space->address + rp2xxx_rom_call_batch_algo_bkpt_offset;
+ unsigned int algo_timeout_ms = 3000;
+ if (is_arm(target_to_arm(target))) {
+ struct armv7m_algorithm alg_info;
+ alg_info.common_magic = ARMV7M_COMMON_MAGIC;
+ alg_info.core_mode = ARM_MODE_THREAD;
+ err = target_run_algorithm(target,
+ 0, NULL, /* No memory arguments */
+ 0, NULL, /* No register arguments */
+ algo_start_addr, algo_end_addr,
+ algo_timeout_ms,
+ &alg_info
+ );
+ } else {
+ // Presumed RISC-V -- there is no RISCV_COMMON_MAGIC on older OpenOCD
+ err = target_run_algorithm(target,
+ 0, NULL, /* No memory arguments */
+ 0, NULL, /* No register arguments */
+ algo_start_addr, algo_end_addr,
+ algo_timeout_ms,
+ NULL /* Currently no RISC-V-specific algorithm info */
+ );
+ }
+ if (err != ERROR_OK) {
+ LOG_ERROR("Failed to call ROM function batch");
+ /* This case is hit when loading new ROM images on FPGA, but can also be hit on real
+ hardware if you swap two devices with different ROM versions without restarting OpenOCD: */
+ LOG_ROM_SYMBOL_DEBUG("Repopulating ROM address cache after failed ROM call");
+ /* We ignore the error on this next call because we have already failed, this is just
+ recovery for the next attempt. */
+ (void)rp2xxx_populate_rom_pointer_cache(target, priv);
+ return err;
+ }
+ return ERROR_OK;
+}
+
+// Call a single ROM function, using the default algorithm stack.
+static int rp2xxx_call_rom_func(struct target *target, struct rp2xxx_flash_bank *priv,
+ uint16_t func_offset, uint32_t argdata[], unsigned int n_args)
+{
+ assert(n_args <= 4); /* only allow register arguments -- capped at just 4 on Arm */
+
+ 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;
+
+ struct rp2xxx_rom_call_batch_record call = {
+ .pc = func_offset,
+ .sp = stacktop
+ };
+ for (unsigned int i = 0; i < n_args; ++i)
+ call.args[i] = argdata[i];
+
+ return rp2xxx_call_rom_func_batch(target, priv, &call, 1);
+}
+
+static int rp2350_init_accessctrl(struct target *target)
+{
+ // Attempt to reset ACCESSCTRL, in case Secure access to SRAM has been
+ // blocked, which will stop us from loading/running algorithms such as RCP
+ // init. (Also ROM, QMI regs are needed later)
+ uint32_t accessctrl_lock_reg;
+ if (target_read_u32(target, ACCESSCTRL_LOCK_OFFSET, &accessctrl_lock_reg) != ERROR_OK) {
+ LOG_ERROR("Failed to read ACCESSCTRL lock register");
+ // Failed to read an APB register which should always be readable from
+ // any security/privilege level. Something fundamental is wrong. E.g.:
+ //
+ // - The debugger is attempting to perform Secure bus accesses on a
+ // system where Secure debug has been disabled
+ // - clk_sys or busfabric clock are stopped (try doing a rescue reset)
+ return ERROR_FAIL;
+ }
+ if (accessctrl_lock_reg & ACCESSCTRL_LOCK_DEBUG_BITS) {
+ LOG_ERROR("ACCESSCTRL is locked, so can't reset permissions. Following steps might fail");
+ } else {
+ LOG_DEBUG("Reset ACCESSCTRL permissions via CFGRESET");
+ return target_write_u32(target, ACCESSCTRL_CFGRESET_OFFSET, ACCESSCTRL_WRITE_PASSWORD | 1u);
+ }
+ return ERROR_OK;
+}
+
+static int rp2350_init_arm_core0(struct target *target, struct rp2xxx_flash_bank *priv)
+{
+ // Flash algorithms (and the RCP init stub called by this function) must
+ // run in the Secure state, so flip the state now before attempting to
+ // execute any code on the core.
+ int retval;
+ uint32_t dscsr;
+ retval = target_read_u32(target, DCB_DSCSR, &dscsr);
+ if (retval != ERROR_OK) {
+ LOG_ERROR("RP2350 init ARM core: DSCSR read failed");
+ return retval;
+ }
+
+ LOG_DEBUG("DSCSR: 0x%08" PRIx32, dscsr);
+ if (!(dscsr & DSCSR_CDS)) {
+ LOG_DEBUG("Setting Current Domain Secure in DSCSR");
+ retval = target_write_u32(target, DCB_DSCSR, (dscsr & ~DSCSR_CDSKEY) | DSCSR_CDS);
+ if (retval != ERROR_OK) {
+ LOG_ERROR("RP2350 init ARM core: DSCSR read failed");
+ return retval;
+ }
+ }
+
+ if (!priv->stack) {
+ LOG_ERROR("No stack for flash programming code");
+ return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
+ }
+
+ if (!priv->ram_algo_space || priv->ram_algo_space->size < sizeof(rcp_init_code)) {
+ LOG_ERROR("No algorithm space for rcp_init code");
+ return ERROR_BUF_TOO_SMALL;
+ }
+
+ int err = target_write_memory(target,
+ priv->ram_algo_space->address,
+ 1,
+ sizeof(rcp_init_code),
+ rcp_init_code
+ );
+ if (err != ERROR_OK) {
+ LOG_ERROR("Failed to load rcp_init algorithm into RAM");
+ return ERROR_FAIL;
+ }
+
+ LOG_TARGET_DEBUG(target, "Calling rcp_init, code at " TARGET_ADDR_FMT,
+ priv->ram_algo_space->address);
+
+ /* Actually call the function */
+ struct armv7m_algorithm alg_info;
+ alg_info.common_magic = ARMV7M_COMMON_MAGIC;
+ alg_info.core_mode = ARM_MODE_THREAD;
+ err = target_run_algorithm(target,
+ 0, NULL, /* No memory arguments */
+ 0, NULL, /* No register arguments */
+ priv->ram_algo_space->address,
+ priv->ram_algo_space->address + rcp_init_code_bkpt_offset,
+ 1000, /* 1s timeout */
+ &alg_info
+ );
+ if (err != ERROR_OK) {
+ LOG_ERROR("Failed to invoke rcp_init");
+ return err;
+ }
+
+ return err;
+}
+
+static int setup_for_raw_flash_cmd(struct target *target, struct rp2xxx_flash_bank *priv)
+{
+ int err = ERROR_OK;
+
+ if (!priv->stack) {
+ /* target_alloc_working_area always allocates multiples of 4 bytes, so no worry about alignment */
+ err = target_alloc_working_area(target, RP2XXX_MAX_ALGO_STACK_USAGE, &priv->stack);
+ if (err != ERROR_OK) {
+ LOG_ERROR("Could not allocate stack for flash programming code -- insufficient space");
+ return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
+ }
+ }
+
+ if (!priv->ram_algo_space) {
+ err = target_alloc_working_area(target, RP2XXX_MAX_RAM_ALGO_SIZE, &priv->ram_algo_space);
+ if (err != ERROR_OK) {
+ LOG_ERROR("Could not allocate RAM code space for ROM calls -- insufficient space");
+ return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
+ }
+ }
+
+ if (IS_RP2350(priv->id)) {
+ err = rp2350_init_accessctrl(target);
+ if (err != ERROR_OK) {
+ LOG_ERROR("Failed to init ACCESSCTRL before ROM call");
+ return err;
+ }
+ if (is_arm(target_to_arm(target))) {
+ err = rp2350_init_arm_core0(target, priv);
+ if (err != ERROR_OK) {
+ LOG_ERROR("Failed to init Arm core 0 before ROM call");
+ return err;
+ }
+ }
+ uint32_t reset_args[1] = {
+ BOOTROM_STATE_RESET_CURRENT_CORE
+ };
+ if (!priv->jump_bootrom_reset_state) {
+ LOG_WARNING("RP2350 flash: no bootrom_reset_method");
+ } else {
+ /* This is mainly required to clear varmulet_enclosing_cpu pointers on RISC-V, in case
+ an Arm -> RISC-V call has been interrupted (these pointers are used to handle
+ reentrant calls to the ROM emulator) */
+ LOG_DEBUG("Clearing core 0 ROM state");
+ err = rp2xxx_call_rom_func(target, priv, priv->jump_bootrom_reset_state,
+ reset_args, ARRAY_SIZE(reset_args));
+ if (err != ERROR_OK) {
+ LOG_ERROR("RP2350 flash: failed to call reset core state");
+ return err;
+ }
+ }
+ if (!is_arm(target_to_arm(target)) && priv->jump_bootrom_set_varm_stack) {
+ /* Pass {0, 0} to set_varmulet_user_stack() to enable automatic emulation of Arm APIs
+ using the ROM's default stacks. Usually the bootrom does this before exiting to user
+ code, but it needs to be done manually when the USB bootloader has been interrupted. */
+ LOG_DEBUG("Enabling default Arm emulator stacks for RISC-V ROM calls");
+ struct working_area *set_stack_mem_args;
+ err = target_alloc_working_area(target, 2 * sizeof(uint32_t), &set_stack_mem_args);
+ if (err != ERROR_OK) {
+ LOG_ERROR("Failed to allocate memory for arguments to set_varmulet_user_stack()");
+ return err;
+ }
+
+ err = target_write_u32(target, set_stack_mem_args->address, 0);
+ if (err == ERROR_OK)
+ err = target_write_u32(target, set_stack_mem_args->address + 4, 0);
+
+ if (err != ERROR_OK) {
+ LOG_ERROR("Failed to initialise memory arguments for set_varmulet_user_stack()");
+ target_free_working_area(target, set_stack_mem_args);
+ return err;
+ }
+
+ uint32_t set_stack_register_args[1] = {
+ set_stack_mem_args->address
+ };
+ err = rp2xxx_call_rom_func(target, priv, priv->jump_bootrom_set_varm_stack,
+ set_stack_register_args, ARRAY_SIZE(set_stack_register_args));
+ target_free_working_area(target, set_stack_mem_args);
+ if (err != ERROR_OK) {
+ LOG_ERROR("Failed to initialise Arm emulation stacks for RISC-V");
+ return err;
+ }
+ }
+ }
+
+ LOG_DEBUG("Connecting flash IOs and issuing XIP exit sequence to flash");
+ struct rp2xxx_rom_call_batch_record calls[2] = {
+ {
+ .pc = priv->jump_connect_internal_flash,
+ .sp = priv->stack->address + priv->stack->size
+ },
+ {
+ .pc = priv->jump_flash_exit_xip,
+ .sp = priv->stack->address + priv->stack->size
+ }
+ };
+ err = rp2xxx_call_rom_func_batch(target, priv, calls, 2);
+ if (err != ERROR_OK) {
+ LOG_ERROR("RP2xxx flash: failed to exit flash XIP mode");
+ return err;
+ }
+
+ return ERROR_OK;
+}
+
+static int rp2xxx_invalidate_cache_restore_xip(struct target *target, struct rp2xxx_flash_bank *priv)
+{
+ // Flash content has changed. We can now do a bit of poking to make
+ // the new flash contents visible to us via memory-mapped (XIP) interface
+ // in the 0x1... memory region.
+
+ LOG_DEBUG("Flushing flash cache after write behind");
+
+ struct rp2xxx_rom_call_batch_record finishing_calls[2] = {
+ {
+ .pc = priv->jump_flush_cache,
+ .sp = priv->stack->address + priv->stack->size
+ },
+ {
+ .sp = priv->stack->address + priv->stack->size
+ },
+ };
+
+ int num_finishing_calls = 1;
+ // Note on RP2350 it's not *required* to call flash_enter_cmd_xip, since
+ // the ROM leaves flash XIPable by default in between direct-mode
+ // accesses
+ if (IS_RP2040(priv->id)) {
+ finishing_calls[num_finishing_calls++].pc = priv->jump_enter_cmd_xip;
+ } else if (priv->jump_flash_reset_address_trans) {
+ // Note flash_reset_address_trans function does not exist on older devices
+ finishing_calls[num_finishing_calls++].pc = priv->jump_flash_reset_address_trans;
+ }
+
+ int retval = rp2xxx_call_rom_func_batch(target, priv, finishing_calls, num_finishing_calls);
+ if (retval != ERROR_OK)
+ LOG_ERROR("RP2xxx: failed to flush flash cache/restore XIP");
+
+ return retval;
+}
+
+static void cleanup_after_raw_flash_cmd(struct target *target, struct rp2xxx_flash_bank *priv)
+{
+ /* OpenOCD is prone to trashing work-area allocations on target state
+ transitions, which leaves us with stale work area pointers in our
+ driver state. Best to clean up our allocations manually after
+ completing each flash call, so we know to make fresh ones next time. */
+ LOG_DEBUG("Cleaning up after flash operations");
+ if (priv->stack) {
+ target_free_working_area(target, priv->stack);
+ priv->stack = 0;
+ }
+ if (priv->ram_algo_space) {
+ target_free_working_area(target, priv->ram_algo_space);
+ priv->ram_algo_space = 0;
+ }
+}
+
+static int rp2xxx_flash_write(struct flash_bank *bank, const uint8_t *buffer, uint32_t offset, uint32_t count)
+{
+ LOG_DEBUG("Writing %" PRIu32 " bytes starting at 0x%" PRIx32, count, offset);
+
+ struct rp2xxx_flash_bank *priv = bank->driver_priv;
+ struct target *target = bank->target;
+
+ if (target->state != TARGET_HALTED) {
+ LOG_ERROR("Target not halted");
+ return ERROR_TARGET_NOT_HALTED;
+ }
+
+ struct working_area *bounce = NULL;
+
+ int err = setup_for_raw_flash_cmd(target, priv);
+ if (err != ERROR_OK)
+ goto cleanup_and_return;
+
+ unsigned int avail_pages = target_get_working_area_avail(target) / RP2XXX_ROM_API_FIXED_FLASH_PAGE;
+ /* We try to allocate working area rounded down to device page size,
+ * al least 1 page, at most the write data size */
+ unsigned int chunk_size = MIN(MAX(avail_pages, 1) * RP2XXX_ROM_API_FIXED_FLASH_PAGE, count);
+ err = target_alloc_working_area(target, chunk_size, &bounce);
+ if (err != ERROR_OK) {
+ LOG_ERROR("Could not allocate bounce buffer for flash programming. Can't continue");
+ goto cleanup_and_return;
+ }
+
+ 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 %" PRIu32 " 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 = rp2xxx_call_rom_func(target, priv, priv->jump_flash_range_program,
+ args, ARRAY_SIZE(args));
+ keep_alive();
+ if (err != ERROR_OK) {
+ LOG_ERROR("Failed to invoke flash programming code on target");
+ break;
+ }
+
+ buffer += write_size;
+ offset += write_size;
+ count -= write_size;
+ }
+
+cleanup_and_return:
+ target_free_working_area(target, bounce);
+
+ /* Don't propagate error or user gets fooled the flash write failed */
+ (void)rp2xxx_invalidate_cache_restore_xip(target, priv);
+
+ cleanup_after_raw_flash_cmd(target, priv);
+ return err;
+}
+
+static int rp2xxx_flash_erase(struct flash_bank *bank, unsigned int first, unsigned int last)
+{
+ struct rp2xxx_flash_bank *priv = bank->driver_priv;
+ struct target *target = bank->target;
+
+ if (target->state != TARGET_HALTED) {
+ LOG_ERROR("Target not halted");
+ return ERROR_TARGET_NOT_HALTED;
+ }
+
+ uint32_t offset_start = bank->sectors[first].offset;
+ uint32_t offset_last = bank->sectors[last].offset + bank->sectors[last].size;
+ uint32_t length = offset_last - offset_start;
+ LOG_DEBUG("erase %" PRIu32 " bytes starting at 0x%" PRIx32,
+ length, offset_start);
+
+ int err = setup_for_raw_flash_cmd(target, priv);
+ if (err != ERROR_OK)
+ goto cleanup_and_return;
+
+ uint32_t offset_next = offset_start;
+
+ /* Break erase into multiple calls to avoid timeout on large erase. Choose 128k chunk which has
+ fairly low ROM call overhead and empirically seems to avoid the default keep_alive() limit
+ as well as our ROM call timeout. */
+ const uint32_t erase_chunk_size = 128 * 1024;
+
+ /* Promote log level for long erases to provide feedback */
+ bool requires_loud_prints = offset_last - offset_next >= 2 * erase_chunk_size;
+ enum log_levels chunk_log_level = requires_loud_prints ? LOG_LVL_INFO : LOG_LVL_DEBUG;
+
+ while (offset_next < offset_last) {
+ uint32_t remaining = offset_last - offset_next;
+ uint32_t call_size = remaining < erase_chunk_size ? remaining : erase_chunk_size;
+ /* Shorten the first call of a large erase if necessary to align subsequent calls */
+ if (offset_next % erase_chunk_size != 0 && call_size == erase_chunk_size)
+ call_size = erase_chunk_size - offset_next % erase_chunk_size;
+
+ LOG_CUSTOM_LEVEL(chunk_log_level,
+ " Erase chunk: 0x%08" PRIx32 " -> 0x%08" PRIx32,
+ offset_next,
+ offset_next + call_size - 1
+ );
+
+ /* This ROM function uses the optimal mixture of 4k 20h and 64k D8h erases, without
+ over-erase. This is why we force the flash_bank sector size attribute to 4k even if
+ OpenOCD prefers to give the block size instead. */
+ uint32_t args[4] = {
+ offset_next,
+ call_size,
+ 65536, /* block_size */
+ 0xd8 /* block_cmd */
+ };
+
+ err = rp2xxx_call_rom_func(target, priv, priv->jump_flash_range_erase, args, ARRAY_SIZE(args));
+ keep_alive();
+
+ if (err != ERROR_OK)
+ break;
+
+ offset_next += call_size;
+ }
+
+
+cleanup_and_return:
+ /* Don't propagate error or user gets fooled the flash erase failed */
+ (void)rp2xxx_invalidate_cache_restore_xip(target, priv);
+
+ cleanup_after_raw_flash_cmd(target, priv);
+ return err;
+}
+
+/* -----------------------------------------------------------------------------
+ Driver probing etc */
+
+
+static int rp2040_ssel_active(struct target *target, bool active)
+{
+ uint32_t state = active ? RP2040_QSPI_CTRL_OUTOVER_LOW : RP2040_QSPI_CTRL_OUTOVER_HIGH;
+ uint32_t val;
+
+ int err = target_read_u32(target, RP2040_QSPI_CTRL, &val);
+ if (err != ERROR_OK)
+ return err;
+
+ val = (val & ~RP2040_QSPI_CTRL_OUTOVER_MASK) | state;
+
+ err = target_write_u32(target, RP2040_QSPI_CTRL, val);
+ if (err != ERROR_OK)
+ return err;
+
+ return ERROR_OK;
+}
+
+static int rp2040_spi_tx_rx(struct target *target,
+ const uint8_t *tx, unsigned int tx_len,
+ unsigned int dummy_len,
+ uint8_t *rx, unsigned int rx_len)
+{
+ int retval, retval2;
+
+ retval = rp2040_ssel_active(target, true);
+ if (retval != ERROR_OK) {
+ LOG_ERROR("QSPI select failed");
+ goto deselect;
+ }
+
+ unsigned int tx_cnt = 0;
+ unsigned int rx_cnt = 0;
+ unsigned int xfer_len = tx_len + dummy_len + rx_len;
+ while (rx_cnt < xfer_len) {
+ int in_flight = tx_cnt - rx_cnt;
+ if (tx_cnt < xfer_len && in_flight < 14) {
+ uint32_t dr = tx_cnt < tx_len ? tx[tx_cnt] : 0;
+ retval = target_write_u32(target, RP2040_SSI_DR0, dr);
+ if (retval != ERROR_OK)
+ break;
+
+ tx_cnt++;
+ continue;
+ }
+ uint32_t dr;
+ retval = target_read_u32(target, RP2040_SSI_DR0, &dr);
+ if (retval != ERROR_OK)
+ break;
+
+ if (rx_cnt >= tx_len + dummy_len)
+ rx[rx_cnt - tx_len - dummy_len] = (uint8_t)dr;
+
+ rx_cnt++;
+ }
+
+deselect:
+ retval2 = rp2040_ssel_active(target, false);
+
+ if (retval != ERROR_OK) {
+ LOG_ERROR("QSPI Tx/Rx failed");
+ return retval;
+ }
+ if (retval2 != ERROR_OK)
+ LOG_ERROR("QSPI deselect failed");
+
+ return retval2;
+}
+
+static int rp2350_spi_tx_rx(struct target *target,
+ const uint8_t *tx, unsigned int tx_len,
+ unsigned int dummy_len,
+ uint8_t *rx, unsigned int rx_len)
+{
+ uint32_t direct_csr;
+ int retval = target_read_u32(target, RP2350_QMI_DIRECT_CSR, &direct_csr);
+ if (retval != ERROR_OK) {
+ LOG_ERROR("QMI DIRECT_CSR read failed");
+ return retval;
+ }
+ direct_csr |= RP2350_QMI_DIRECT_CSR_EN | RP2350_QMI_DIRECT_CSR_ASSERT_CS0N;
+ retval = target_write_u32(target, RP2350_QMI_DIRECT_CSR, direct_csr);
+ if (retval != ERROR_OK) {
+ LOG_ERROR("QMI DIRECT mode enable failed");
+ goto deselect;
+ }
+
+ unsigned int tx_cnt = 0;
+ unsigned int rx_cnt = 0;
+ unsigned int xfer_len = tx_len + dummy_len + rx_len;
+ while (tx_cnt < xfer_len || rx_cnt < rx_len) {
+ int in_flight = tx_cnt - tx_len - dummy_len - rx_cnt;
+ if (tx_cnt < xfer_len && in_flight < 4) {
+ uint32_t tx_cmd;
+ if (tx_cnt < tx_len)
+ tx_cmd = tx[tx_cnt] | RP2350_QMI_DIRECT_TX_NOPUSH | RP2350_QMI_DIRECT_TX_OE;
+ else if (tx_cnt < tx_len + dummy_len)
+ tx_cmd = RP2350_QMI_DIRECT_TX_NOPUSH;
+ else
+ tx_cmd = 0;
+
+ retval = target_write_u32(target, RP2350_QMI_DIRECT_TX, tx_cmd);
+ if (retval != ERROR_OK)
+ break;
+
+ tx_cnt++;
+ continue;
+ }
+ if (rx_cnt < rx_len) {
+ uint32_t dr;
+ retval = target_read_u32(target, RP2350_QMI_DIRECT_RX, &dr);
+ if (retval != ERROR_OK)
+ break;
+
+ rx[rx_cnt] = (uint8_t)dr;
+ rx_cnt++;
+ }
+ }
+
+deselect:
+ direct_csr &= ~(RP2350_QMI_DIRECT_CSR_EN | RP2350_QMI_DIRECT_CSR_ASSERT_CS0N);
+ int retval2 = target_write_u32(target, RP2350_QMI_DIRECT_CSR, direct_csr);
+
+ if (retval != ERROR_OK) {
+ LOG_ERROR("QSPI Tx/Rx failed");
+ return retval;
+ }
+ if (retval2 != ERROR_OK)
+ LOG_ERROR("QMI DIRECT mode disable failed");
+
+ return retval2;
+}
+
+static int rp2xxx_spi_tx_rx(struct flash_bank *bank,
+ const uint8_t *tx, unsigned int tx_len,
+ unsigned int dummy_len,
+ uint8_t *rx, unsigned int rx_len)
+{
+ struct rp2xxx_flash_bank *priv = bank->driver_priv;
+ struct target *target = bank->target;
+
+ if (IS_RP2040(priv->id))
+ return rp2040_spi_tx_rx(target, tx, tx_len, dummy_len, rx, rx_len);
+ else if (IS_RP2350(priv->id))
+ return rp2350_spi_tx_rx(target, tx, tx_len, dummy_len, rx, rx_len);
+ else
+ return ERROR_FAIL;
+}
+
+static int rp2xxx_read_sfdp_block(struct flash_bank *bank, uint32_t addr,
+ unsigned int words, uint32_t *buffer)
+{
+ struct rp2xxx_flash_bank *priv = bank->driver_priv;
+
+ uint8_t cmd[4] = { SPIFLASH_READ_SFDP };
+ uint8_t data[4 * words + priv->sfdp_dummy_detect];
+
+ h_u24_to_be(&cmd[1], addr);
+
+ int retval = rp2xxx_spi_tx_rx(bank, cmd, sizeof(cmd), priv->sfdp_dummy,
+ data, 4 * words + priv->sfdp_dummy_detect);
+ if (retval != ERROR_OK)
+ return retval;
+
+ if (priv->sfdp_dummy_detect) {
+ for (unsigned int i = 0; i < priv->sfdp_dummy_detect; i++)
+ if (le_to_h_u32(&data[i]) == SFDP_MAGIC) {
+ priv->sfdp_dummy_detect = 0;
+ priv->sfdp_dummy = i;
+ break;
+ }
+ for (unsigned int i = 0; i < words; i++)
+ buffer[i] = le_to_h_u32(&data[4 * i + priv->sfdp_dummy]);
+ } else {
+ for (unsigned int i = 0; i < words; i++)
+ buffer[i] = le_to_h_u32(&data[4 * i]);
+ }
+ return retval;
+}
+
+static int rp2xxx_flash_probe(struct flash_bank *bank)
+{
+ struct rp2xxx_flash_bank *priv = bank->driver_priv;
+ struct target *target = bank->target;
+
+ int retval = target_read_u32(target, RP2XXX_SYSINFO_CHIP_ID, &priv->id);
+ if (retval != ERROR_OK) {
+ LOG_ERROR("SYSINFO CHIP_ID read failed");
+ return retval;
+ }
+ if (!IS_RP2040(priv->id) && !IS_RP2350(priv->id)) {
+ LOG_ERROR("Unknown SYSINFO CHIP_ID 0x%08" PRIx32, priv->id);
+ return ERROR_FLASH_BANK_INVALID;
+ }
+
+ retval = rp2xxx_populate_rom_pointer_cache(target, priv);
+ if (retval != ERROR_OK)
+ return retval;
+
+ /* the Boot ROM flash_range_program() routine requires page alignment */
+ bank->write_start_alignment = RP2XXX_ROM_API_FIXED_FLASH_PAGE;
+ bank->write_end_alignment = RP2XXX_ROM_API_FIXED_FLASH_PAGE;
+
+ uint32_t flash_id = 0;
+ if (priv->size_override) {
+ priv->spi_dev.name = "size override";
+ LOG_DEBUG("SPI flash autodetection disabled, using configured size");
+ } else {
+ if (target->state != TARGET_HALTED) {
+ LOG_ERROR("Target not halted");
+ return ERROR_TARGET_NOT_HALTED;
+ }
+
+ bank->size = 0;
+
+ (void)setup_for_raw_flash_cmd(target, priv);
+ /* ignore error, flash size detection could work anyway */
+
+ const uint8_t cmd[] = { SPIFLASH_READ_ID };
+ uint8_t data[3];
+ retval = rp2xxx_spi_tx_rx(bank, cmd, sizeof(cmd), 0, data, sizeof(data));
+ if (retval == ERROR_OK) {
+ flash_id = le_to_h_u24(data);
+
+ /* search for a SPI flash Device ID match */
+ for (const struct flash_device *p = flash_devices; p->name ; p++) {
+ if (p->device_id == flash_id) {
+ priv->spi_dev = *p;
+ bank->size = p->size_in_bytes;
+ break;
+ }
+ }
+ }
+
+ if (bank->size == 0) {
+ priv->sfdp_dummy_detect = 8;
+ priv->sfdp_dummy = 0;
+ retval = spi_sfdp(bank, &priv->spi_dev, &rp2xxx_read_sfdp_block);
+ if (retval == ERROR_OK)
+ bank->size = priv->spi_dev.size_in_bytes;
+ }
+
+ cleanup_after_raw_flash_cmd(target, priv);
+ }
+
+ snprintf(priv->dev_name, sizeof(priv->dev_name), "%s rev %u",
+ IS_RP2350(priv->id) ? "RP2350" : "RP2040",
+ RP2XXX_CHIP_ID_REVISION(priv->id));
+
+ if (bank->size == 0) {
+ LOG_ERROR("%s, QSPI Flash id = 0x%06" PRIx32 " not recognised",
+ priv->dev_name, flash_id);
+ return ERROR_FLASH_BANK_INVALID;
+ }
+
+ bank->num_sectors = bank->size / RP2XXX_ROM_API_FIXED_FLASH_SECTOR;
+
+ if (priv->size_override) {
+ LOG_INFO("%s, QSPI Flash size override = %u KiB in %u sectors",
+ priv->dev_name, bank->size / 1024, bank->num_sectors);
+ } else {
+ LOG_INFO("%s, QSPI Flash %s id = 0x%06" PRIx32 " size = %u KiB in %u sectors",
+ priv->dev_name, priv->spi_dev.name, flash_id,
+ bank->size / 1024, bank->num_sectors);
+ }
+
+ free(bank->sectors);
+ bank->sectors = alloc_block_array(0, RP2XXX_ROM_API_FIXED_FLASH_SECTOR, bank->num_sectors);
+ if (!bank->sectors)
+ return ERROR_FAIL;
+
+ priv->probed = true;
+
+ return ERROR_OK;
+}
+
+static int rp2xxx_flash_auto_probe(struct flash_bank *bank)
+{
+ struct rp2xxx_flash_bank *priv = bank->driver_priv;
+
+ if (priv->probed)
+ return ERROR_OK;
+
+ return rp2xxx_flash_probe(bank);
+}
+
+/* -----------------------------------------------------------------------------
+ Driver boilerplate */
+
+FLASH_BANK_COMMAND_HANDLER(rp2xxx_flash_bank_command)
+{
+ struct rp2xxx_flash_bank *priv;
+ priv = calloc(1, sizeof(struct rp2xxx_flash_bank));
+ priv->size_override = bank->size != 0;
+
+ /* Set up driver_priv */
+ bank->driver_priv = priv;
+
+ return ERROR_OK;
+}
+
+
+COMMAND_HANDLER(rp2xxx_rom_api_call_handler)
+{
+ if (CMD_ARGC < 1)
+ return ERROR_COMMAND_SYNTAX_ERROR;
+
+ struct target *target = get_current_target(CMD->ctx);
+
+ struct flash_bank *bank;
+ for (bank = flash_bank_list(); bank; bank = bank->next) {
+ if (bank->driver != &rp2xxx_flash)
+ continue;
+
+ if (bank->target == target)
+ break;
+ }
+
+ if (!bank) {
+ command_print(CMD, "[%s] No associated RP2xxx flash bank found",
+ target_name(target));
+ return ERROR_FAIL;
+ }
+
+ int retval = rp2xxx_flash_auto_probe(bank);
+ if (retval != ERROR_OK) {
+ command_print(CMD, "auto_probe failed");
+ return retval;
+ }
+
+ uint16_t tag = MAKE_TAG(CMD_ARGV[0][0], CMD_ARGV[0][1]);
+
+ uint32_t args[4] = { 0 };
+ for (unsigned int i = 0; i + 1 < CMD_ARGC && i < ARRAY_SIZE(args); i++)
+ COMMAND_PARSE_NUMBER(u32, CMD_ARGV[i + 1], args[i]);
+
+ if (target->state != TARGET_HALTED) {
+ command_print(CMD, "Target not halted");
+ return ERROR_TARGET_NOT_HALTED;
+ }
+
+ struct rp2xxx_flash_bank *priv = bank->driver_priv;
+ retval = setup_for_raw_flash_cmd(target, priv);
+ if (retval != ERROR_OK)
+ goto cleanup_and_return;
+
+ uint16_t symtype_func = is_arm(target_to_arm(target))
+ ? RT_FLAG_FUNC_ARM_SEC : RT_FLAG_FUNC_RISCV;
+
+ uint16_t fc;
+ retval = rp2xxx_lookup_rom_symbol(target, tag, symtype_func, &fc);
+ if (retval != ERROR_OK) {
+ command_print(CMD, "Function %.2s not found in RP2xxx ROM",
+ CMD_ARGV[0]);
+ goto cleanup_and_return;
+ }
+
+ /* command_print() output gets lost if the command is called
+ * in an event handler, use LOG_INFO instead */
+ LOG_INFO("RP2xxx ROM API function %.2s @ %04" PRIx16, CMD_ARGV[0], fc);
+
+ retval = rp2xxx_call_rom_func(target, priv, fc, args, ARRAY_SIZE(args));
+ if (retval != ERROR_OK)
+ command_print(CMD, "RP2xxx ROM API call failed");
+
+cleanup_and_return:
+ cleanup_after_raw_flash_cmd(target, priv);
+ return retval;
+}
+
+COMMAND_HANDLER(rp2xxx_switch_target_handler)
+{
+ if (CMD_ARGC != 2)
+ return ERROR_COMMAND_SYNTAX_ERROR;
+
+ struct target *old_target = get_target(CMD_ARGV[0]);
+ if (!old_target) {
+ command_print(CMD, "Unrecognised old target %s", CMD_ARGV[0]);
+ return ERROR_COMMAND_ARGUMENT_INVALID;
+ }
+
+ struct target *new_target = get_target(CMD_ARGV[1]);
+ if (!new_target) {
+ command_print(CMD, "Unrecognised new target %s", CMD_ARGV[1]);
+ return ERROR_COMMAND_ARGUMENT_INVALID;
+ }
+
+ struct flash_bank *bank;
+ for (bank = flash_bank_list(); bank; bank = bank->next) {
+ if (bank->driver == &rp2xxx_flash) {
+ if (bank->target == old_target) {
+ bank->target = new_target;
+ struct rp2xxx_flash_bank *priv = bank->driver_priv;
+ priv->probed = false;
+ return ERROR_OK;
+ } else if (bank->target == new_target) {
+ return ERROR_OK;
+ }
+ }
+ }
+
+ command_print(CMD, "Neither old nor new target %s found in flash bank list",
+ CMD_ARGV[0]);
+ return ERROR_FAIL;
+}
+
+static const struct command_registration rp2xxx_exec_command_handlers[] = {
+ {
+ .name = "rom_api_call",
+ .mode = COMMAND_EXEC,
+ .help = "arbitrary ROM API call",
+ .usage = "fc [p0 [p1 [p2 [p3]]]]",
+ .handler = rp2xxx_rom_api_call_handler,
+ },
+ {
+ .name = "_switch_target",
+ .mode = COMMAND_EXEC,
+ .help = "internal use",
+ .usage = "old_target new_target",
+ .handler = rp2xxx_switch_target_handler,
+ },
+ COMMAND_REGISTRATION_DONE
+};
+
+static const struct command_registration rp2xxx_command_handler[] = {
+ {
+ .name = "rp2xxx",
+ .mode = COMMAND_ANY,
+ .help = "rp2xxx flash controller commands",
+ .usage = "",
+ .chain = rp2xxx_exec_command_handlers,
+ },
+ COMMAND_REGISTRATION_DONE
+};
+
+const struct flash_driver rp2xxx_flash = {
+ .name = "rp2xxx",
+ .commands = rp2xxx_command_handler,
+ .flash_bank_command = rp2xxx_flash_bank_command,
+ .erase = rp2xxx_flash_erase,
+ .write = rp2xxx_flash_write,
+ .read = default_flash_read,
+ .probe = rp2xxx_flash_probe,
+ .auto_probe = rp2xxx_flash_auto_probe,
+ .erase_check = default_flash_blank_check,
+ .free_driver_priv = default_flash_free_driver_priv
+};
diff --git a/src/flash/nor/stellaris.c b/src/flash/nor/stellaris.c
index 1f53b2f..f7dcc6f 100644
--- a/src/flash/nor/stellaris.c
+++ b/src/flash/nor/stellaris.c
@@ -1342,7 +1342,7 @@ COMMAND_HANDLER(stellaris_handle_recover_command)
* cycle to recover.
*/
- Jim_Eval_Named(CMD_CTX->interp, "catch { hla_command \"debug unlock\" }", NULL, 0);
+ Jim_Eval_Named(CMD_CTX->interp, "catch { hla command \"debug unlock\" }", NULL, 0);
if (!strcmp(Jim_GetString(Jim_GetResult(CMD_CTX->interp), NULL), "0")) {
retval = ERROR_OK;
goto user_action;
diff --git a/src/flash/nor/stm32l4x.c b/src/flash/nor/stm32l4x.c
index fa57db8..f163332 100644
--- a/src/flash/nor/stm32l4x.c
+++ b/src/flash/nor/stm32l4x.c
@@ -303,10 +303,18 @@ static const struct stm32l4_rev stm32c03xx_revs[] = {
{ 0x1000, "A" }, { 0x1001, "Z" },
};
+static const struct stm32l4_rev stm32c05xx_revs[] = {
+ { 0x1000, "A" },
+};
+
static const struct stm32l4_rev stm32c071xx_revs[] = {
{ 0x1001, "Z" },
};
+static const struct stm32l4_rev stm32c09xx_revs[] = {
+ { 0x1000, "A" },
+};
+
static const struct stm32l4_rev stm32g05_g06xx_revs[] = {
{ 0x1000, "A" },
};
@@ -451,6 +459,18 @@ static const struct stm32l4_part_info stm32l4_parts[] = {
.otp_size = 1024,
},
{
+ .id = DEVID_STM32C05XX,
+ .revs = stm32c05xx_revs,
+ .num_revs = ARRAY_SIZE(stm32c05xx_revs),
+ .device_str = "STM32C05xx",
+ .max_flash_size_kb = 64,
+ .flags = F_NONE,
+ .flash_regs_base = 0x40022000,
+ .fsize_addr = 0x1FFF75A0,
+ .otp_base = 0x1FFF7000,
+ .otp_size = 1024,
+ },
+ {
.id = DEVID_STM32C071XX,
.revs = stm32c071xx_revs,
.num_revs = ARRAY_SIZE(stm32c071xx_revs),
@@ -463,6 +483,18 @@ static const struct stm32l4_part_info stm32l4_parts[] = {
.otp_size = 1024,
},
{
+ .id = DEVID_STM32C09XX,
+ .revs = stm32c09xx_revs,
+ .num_revs = ARRAY_SIZE(stm32c09xx_revs),
+ .device_str = "STM32C09xx",
+ .max_flash_size_kb = 256,
+ .flags = F_NONE,
+ .flash_regs_base = 0x40022000,
+ .fsize_addr = 0x1FFF75A0,
+ .otp_base = 0x1FFF7000,
+ .otp_size = 1024,
+ },
+ {
.id = DEVID_STM32U53_U54XX,
.revs = stm32u53_u54xx_revs,
.num_revs = ARRAY_SIZE(stm32u53_u54xx_revs),
@@ -2021,7 +2053,9 @@ static int stm32l4_probe(struct flash_bank *bank)
case DEVID_STM32L43_L44XX:
case DEVID_STM32C01XX:
case DEVID_STM32C03XX:
+ case DEVID_STM32C05XX:
case DEVID_STM32C071XX:
+ case DEVID_STM32C09XX:
case DEVID_STM32G05_G06XX:
case DEVID_STM32G07_G08XX:
case DEVID_STM32U031XX:
diff --git a/src/flash/nor/stm32l4x.h b/src/flash/nor/stm32l4x.h
index 3199d4f..07b3615 100644
--- a/src/flash/nor/stm32l4x.h
+++ b/src/flash/nor/stm32l4x.h
@@ -88,6 +88,8 @@
#define DEVID_STM32L47_L48XX 0x415
#define DEVID_STM32L43_L44XX 0x435
#define DEVID_STM32C01XX 0x443
+#define DEVID_STM32C05XX 0x44C
+#define DEVID_STM32C09XX 0x44D
#define DEVID_STM32C03XX 0x453
#define DEVID_STM32U53_U54XX 0x455
#define DEVID_STM32G05_G06XX 0x456
diff --git a/src/helper/command.c b/src/helper/command.c
index 3d4379d..218f058 100644
--- a/src/helper/command.c
+++ b/src/helper/command.c
@@ -31,8 +31,7 @@
#define __THIS__FILE__ "command.c"
struct log_capture_state {
- Jim_Interp *interp;
- Jim_Obj *output;
+ char *output;
};
static int unregister_command(struct command_context *context,
@@ -59,73 +58,6 @@ void *jimcmd_privdata(Jim_Cmd *cmd)
return cmd->isproc ? NULL : cmd->u.native.privData;
}
-static void tcl_output(void *privData, const char *file, unsigned int line,
- const char *function, const char *string)
-{
- struct log_capture_state *state = privData;
- Jim_AppendString(state->interp, state->output, string, strlen(string));
-}
-
-static struct log_capture_state *command_log_capture_start(Jim_Interp *interp)
-{
- /* capture log output and return it. A garbage collect can
- * happen, so we need a reference count to this object */
- Jim_Obj *jim_output = Jim_NewStringObj(interp, "", 0);
- if (!jim_output)
- return NULL;
-
- Jim_IncrRefCount(jim_output);
-
- struct log_capture_state *state = malloc(sizeof(*state));
- if (!state) {
- LOG_ERROR("Out of memory");
- Jim_DecrRefCount(interp, jim_output);
- return NULL;
- }
-
- state->interp = interp;
- state->output = jim_output;
-
- log_add_callback(tcl_output, state);
-
- return state;
-}
-
-/* Classic openocd commands provide progress output which we
- * will capture and return as a Tcl return value.
- *
- * However, if a non-openocd command has been invoked, then it
- * makes sense to return the tcl return value from that command.
- *
- * The tcl return value is empty for openocd commands that provide
- * progress output.
- *
- * For other commands, we prepend the logs to the tcl return value.
- */
-static void command_log_capture_finish(struct log_capture_state *state)
-{
- if (!state)
- return;
-
- log_remove_callback(tcl_output, state);
-
- int loglen;
- const char *log_result = Jim_GetString(state->output, &loglen);
- int reslen;
- const char *cmd_result = Jim_GetString(Jim_GetResult(state->interp), &reslen);
-
- // Just in case the log doesn't end with a newline, we add it
- if (loglen != 0 && reslen != 0 && log_result[loglen - 1] != '\n')
- Jim_AppendString(state->interp, state->output, "\n", 1);
-
- Jim_AppendString(state->interp, state->output, cmd_result, reslen);
-
- Jim_SetResult(state->interp, state->output);
- Jim_DecrRefCount(state->interp, state->output);
-
- free(state);
-}
-
static int command_retval_set(Jim_Interp *interp, int retval)
{
int *return_retval = Jim_GetAssocData(interp, "retval");
@@ -680,15 +612,28 @@ COMMAND_HANDLER(handle_echo)
return ERROR_OK;
}
-/* Return both the progress output (LOG_INFO and higher)
+static void tcl_output(void *privData, const char *file, unsigned int line,
+ const char *function, const char *string)
+{
+ struct log_capture_state *state = privData;
+ char *old = state->output;
+
+ state->output = alloc_printf("%s%s", old ? old : "", string);
+ free(old);
+ if (!state->output)
+ LOG_ERROR("Out of memory");
+}
+
+/*
+ * Return both the progress output (LOG_INFO and higher)
* and the tcl return value of a command.
*/
-static int jim_capture(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+COMMAND_HANDLER(handle_command_capture)
{
- if (argc != 2)
- return JIM_ERR;
+ struct log_capture_state state = {NULL};
- struct log_capture_state *state = command_log_capture_start(interp);
+ if (CMD_ARGC != 1)
+ return ERROR_COMMAND_SYNTAX_ERROR;
/* disable polling during capture. This avoids capturing output
* from polling.
@@ -698,14 +643,24 @@ static int jim_capture(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
*/
bool save_poll_mask = jtag_poll_mask();
- const char *str = Jim_GetString(argv[1], NULL);
- int retcode = Jim_Eval_Named(interp, str, __THIS__FILE__, __LINE__);
+ log_add_callback(tcl_output, &state);
+
+ int jimretval = Jim_EvalObj(CMD_CTX->interp, CMD_JIMTCL_ARGV[0]);
+ const char *cmd_result = Jim_GetString(Jim_GetResult(CMD_CTX->interp), NULL);
+
+ log_remove_callback(tcl_output, &state);
jtag_poll_unmask(save_poll_mask);
- command_log_capture_finish(state);
+ if (state.output && *state.output)
+ command_print(CMD, "%s", state.output);
+
+ if (cmd_result && *cmd_result)
+ command_print(CMD, "%s", cmd_result);
- return retcode;
+ free(state.output);
+
+ return (jimretval == JIM_OK) ? ERROR_OK : ERROR_FAIL;
}
struct help_entry {
@@ -843,22 +798,19 @@ COMMAND_HANDLER(handle_help_command)
return retval;
}
-static char *alloc_concatenate_strings(int argc, Jim_Obj * const *argv)
+static char *alloc_concatenate_strings(int argc, const char **argv)
{
- char *prev, *all;
- int i;
-
assert(argc >= 1);
- all = strdup(Jim_GetString(argv[0], NULL));
+ char *all = strdup(argv[0]);
if (!all) {
LOG_ERROR("Out of memory");
return NULL;
}
- for (i = 1; i < argc; ++i) {
- prev = all;
- all = alloc_printf("%s %s", all, Jim_GetString(argv[i], NULL));
+ for (int i = 1; i < argc; ++i) {
+ char *prev = all;
+ all = alloc_printf("%s %s", all, argv[i]);
free(prev);
if (!all) {
LOG_ERROR("Out of memory");
@@ -944,17 +896,16 @@ static enum command_mode get_command_mode(Jim_Interp *interp, const char *cmd_na
return c->mode;
}
-static int jim_command_mode(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+COMMAND_HANDLER(handle_command_mode)
{
- struct command_context *cmd_ctx = current_command_context(interp);
- enum command_mode mode = cmd_ctx->mode;
+ enum command_mode mode = CMD_CTX->mode;
- if (argc > 1) {
- char *full_name = alloc_concatenate_strings(argc - 1, argv + 1);
+ if (CMD_ARGC) {
+ char *full_name = alloc_concatenate_strings(CMD_ARGC, CMD_ARGV);
if (!full_name)
- return JIM_ERR;
+ return ERROR_FAIL;
- mode = get_command_mode(interp, full_name);
+ mode = get_command_mode(CMD_CTX->interp, full_name);
free(full_name);
}
@@ -975,8 +926,8 @@ static int jim_command_mode(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
mode_str = "unknown";
break;
}
- Jim_SetResultString(interp, mode_str, -1);
- return JIM_OK;
+ command_print(CMD, "%s", mode_str);
+ return ERROR_OK;
}
int help_del_all_commands(struct command_context *cmd_ctx)
@@ -1115,7 +1066,7 @@ static const struct command_registration command_subcommand_handlers[] = {
{
.name = "mode",
.mode = COMMAND_ANY,
- .jim_handler = jim_command_mode,
+ .handler = handle_command_mode,
.usage = "[command_name ...]",
.help = "Returns the command modes allowed by a command: "
"'any', 'config', or 'exec'. If no command is "
@@ -1137,7 +1088,7 @@ static const struct command_registration command_builtin_handlers[] = {
{
.name = "capture",
.mode = COMMAND_ANY,
- .jim_handler = jim_capture,
+ .handler = handle_command_capture,
.help = "Capture progress output and return as tcl return value. If the "
"progress output was empty, return tcl return value.",
.usage = "command",
diff --git a/src/helper/list.h b/src/helper/list.h
index ba07f15..89b8468 100644
--- a/src/helper/list.h
+++ b/src/helper/list.h
@@ -35,6 +35,7 @@
/* begin OpenOCD changes */
+#include <assert.h>
#include <stddef.h>
struct list_head {
@@ -109,6 +110,9 @@ static inline void
linux_list_add(struct list_head *new, struct list_head *prev,
struct list_head *next)
{
+ assert(next);
+ assert(prev);
+
next->prev = new;
new->next = next;
new->prev = prev;
diff --git a/src/jtag/adapter.c b/src/jtag/adapter.c
index 2fcbd60..6785a74 100644
--- a/src/jtag/adapter.c
+++ b/src/jtag/adapter.c
@@ -16,6 +16,7 @@
#include "minidriver.h"
#include "interface.h"
#include "interfaces.h"
+#include <helper/bits.h>
#include <transport/transport.h>
/**
@@ -24,7 +25,6 @@
*/
struct adapter_driver *adapter_driver;
-const char * const jtag_only[] = { "jtag", NULL };
enum adapter_clk_mode {
CLOCK_MODE_UNSELECTED = 0,
@@ -187,7 +187,6 @@ int adapter_init(struct command_context *cmd_ctx)
int adapter_quit(void)
{
if (is_adapter_initialized() && adapter_driver->quit) {
- /* close the JTAG interface */
int result = adapter_driver->quit();
if (result != ERROR_OK)
LOG_ERROR("failed: %d", result);
@@ -380,7 +379,7 @@ done:
COMMAND_HANDLER(handle_adapter_name)
{
- /* return the name of the interface */
+ /* return the name of the adapter driver */
/* TCL code might need to know the exact type... */
/* FUTURE: we allow this as a means to "set" the interface. */
@@ -394,9 +393,22 @@ COMMAND_HANDLER(handle_adapter_name)
COMMAND_HANDLER(dump_adapter_driver_list)
{
+ int max_len = 0;
+ for (unsigned int i = 0; adapter_drivers[i]; i++) {
+ int len = strlen(adapter_drivers[i]->name);
+ if (max_len < len)
+ max_len = len;
+ }
+
for (unsigned int i = 0; adapter_drivers[i]; i++) {
const char *name = adapter_drivers[i]->name;
- command_print(CMD, "%u: %s", i + 1, name);
+ unsigned int transport_ids = adapter_drivers[i]->transport_ids;
+
+ command_print_sameline(CMD, "%-*s {", max_len, name);
+ for (unsigned int j = BIT(0); j & TRANSPORT_VALID_MASK; j <<= 1)
+ if (j & transport_ids)
+ command_print_sameline(CMD, " %s", transport_name(j));
+ command_print(CMD, " }");
}
return ERROR_OK;
@@ -414,14 +426,14 @@ COMMAND_HANDLER(handle_adapter_driver_command)
{
int retval;
- /* check whether the interface is already configured */
+ /* check whether the adapter driver is already configured */
if (adapter_driver) {
- LOG_WARNING("Interface already configured, ignoring");
+ LOG_WARNING("Adapter driver already configured, ignoring");
return ERROR_OK;
}
- /* interface name is a mandatory argument */
- if (CMD_ARGC != 1 || CMD_ARGV[0][0] == '\0')
+ /* adapter driver name is a mandatory argument */
+ if (CMD_ARGC != 1)
return ERROR_COMMAND_SYNTAX_ERROR;
for (unsigned int i = 0; adapter_drivers[i]; i++) {
@@ -436,13 +448,14 @@ COMMAND_HANDLER(handle_adapter_driver_command)
adapter_driver = adapter_drivers[i];
- return allow_transports(CMD_CTX, adapter_driver->transports);
+ return allow_transports(CMD_CTX, adapter_driver->transport_ids,
+ adapter_driver->transport_preferred_id);
}
- /* no valid interface was found (i.e. the configuration option,
- * didn't match one of the compiled-in interfaces
+ /* no valid adapter driver was found (i.e. the configuration option,
+ * didn't match one of the compiled-in drivers
*/
- LOG_ERROR("The specified debug interface was not found (%s)",
+ LOG_ERROR("The specified adapter driver was not found (%s)",
CMD_ARGV[0]);
command_print(CMD, "The following adapter drivers are available:");
CALL_COMMAND_HANDLER(dump_adapter_driver_list);
diff --git a/src/jtag/core.c b/src/jtag/core.c
index 030c173..6dd2144 100644
--- a/src/jtag/core.c
+++ b/src/jtag/core.c
@@ -1823,7 +1823,7 @@ static int jtag_select(struct command_context *ctx)
}
static struct transport jtag_transport = {
- .name = "jtag",
+ .id = TRANSPORT_JTAG,
.select = jtag_select,
.init = jtag_init,
};
@@ -1868,7 +1868,7 @@ int adapter_resets(int trst, int srst)
transport_is_swim()) {
if (trst == TRST_ASSERT) {
LOG_ERROR("transport %s has no trst signal",
- get_current_transport()->name);
+ get_current_transport_name());
return ERROR_FAIL;
}
@@ -1884,7 +1884,7 @@ int adapter_resets(int trst, int srst)
return ERROR_OK;
LOG_ERROR("reset is not supported on transport %s",
- get_current_transport()->name);
+ get_current_transport_name());
return ERROR_FAIL;
}
@@ -1903,7 +1903,7 @@ int adapter_assert_reset(void)
return adapter_system_reset(1);
else if (get_current_transport())
LOG_ERROR("reset is not supported on %s",
- get_current_transport()->name);
+ get_current_transport_name());
else
LOG_ERROR("transport is not selected");
return ERROR_FAIL;
@@ -1920,7 +1920,7 @@ int adapter_deassert_reset(void)
return adapter_system_reset(0);
else if (get_current_transport())
LOG_ERROR("reset is not supported on %s",
- get_current_transport()->name);
+ get_current_transport_name());
else
LOG_ERROR("transport is not selected");
return ERROR_FAIL;
diff --git a/src/jtag/drivers/am335xgpio.c b/src/jtag/drivers/am335xgpio.c
index cacf4e7..a4727cc 100644
--- a/src/jtag/drivers/am335xgpio.c
+++ b/src/jtag/drivers/am335xgpio.c
@@ -350,8 +350,6 @@ static const struct command_registration am335xgpio_command_handlers[] = {
COMMAND_REGISTRATION_DONE
};
-static const char * const am335xgpio_transports[] = { "jtag", "swd", NULL };
-
static struct jtag_interface am335xgpio_interface = {
.supported = DEBUG_CAP_TMS_SEQ,
.execute_queue = bitbang_execute_queue,
@@ -494,7 +492,8 @@ static int am335xgpio_quit(void)
struct adapter_driver am335xgpio_adapter_driver = {
.name = "am335xgpio",
- .transports = am335xgpio_transports,
+ .transport_ids = TRANSPORT_JTAG | TRANSPORT_SWD,
+ .transport_preferred_id = TRANSPORT_JTAG,
.commands = am335xgpio_command_handlers,
.init = am335xgpio_init,
diff --git a/src/jtag/drivers/amt_jtagaccel.c b/src/jtag/drivers/amt_jtagaccel.c
index 80254ff..633c204 100644
--- a/src/jtag/drivers/amt_jtagaccel.c
+++ b/src/jtag/drivers/amt_jtagaccel.c
@@ -579,7 +579,8 @@ static struct jtag_interface amt_jtagaccel_interface = {
struct adapter_driver amt_jtagaccel_adapter_driver = {
.name = "amt_jtagaccel",
- .transports = jtag_only,
+ .transport_ids = TRANSPORT_JTAG,
+ .transport_preferred_id = TRANSPORT_JTAG,
.commands = amtjtagaccel_command_handlers,
.init = amt_jtagaccel_init,
diff --git a/src/jtag/drivers/angie.c b/src/jtag/drivers/angie.c
index 46a4c82..56a118e 100644
--- a/src/jtag/drivers/angie.c
+++ b/src/jtag/drivers/angie.c
@@ -2388,7 +2388,8 @@ static struct jtag_interface angie_interface = {
struct adapter_driver angie_adapter_driver = {
.name = "angie",
- .transports = jtag_only,
+ .transport_ids = TRANSPORT_JTAG,
+ .transport_preferred_id = TRANSPORT_JTAG,
.init = angie_init,
.quit = angie_quit,
diff --git a/src/jtag/drivers/arm-jtag-ew.c b/src/jtag/drivers/arm-jtag-ew.c
index 45e0384..9d8c592 100644
--- a/src/jtag/drivers/arm-jtag-ew.c
+++ b/src/jtag/drivers/arm-jtag-ew.c
@@ -486,7 +486,8 @@ static struct jtag_interface armjtagew_interface = {
struct adapter_driver armjtagew_adapter_driver = {
.name = "arm-jtag-ew",
- .transports = jtag_only,
+ .transport_ids = TRANSPORT_JTAG,
+ .transport_preferred_id = TRANSPORT_JTAG,
.commands = armjtagew_command_handlers,
.init = armjtagew_init,
diff --git a/src/jtag/drivers/at91rm9200.c b/src/jtag/drivers/at91rm9200.c
index a77e29a..ddcf857 100644
--- a/src/jtag/drivers/at91rm9200.c
+++ b/src/jtag/drivers/at91rm9200.c
@@ -186,7 +186,8 @@ static struct jtag_interface at91rm9200_interface = {
struct adapter_driver at91rm9200_adapter_driver = {
.name = "at91rm9200",
- .transports = jtag_only,
+ .transport_ids = TRANSPORT_JTAG,
+ .transport_preferred_id = TRANSPORT_JTAG,
.commands = at91rm9200_command_handlers,
.init = at91rm9200_init,
diff --git a/src/jtag/drivers/bcm2835gpio.c b/src/jtag/drivers/bcm2835gpio.c
index e8689aa..1a105aa 100644
--- a/src/jtag/drivers/bcm2835gpio.c
+++ b/src/jtag/drivers/bcm2835gpio.c
@@ -590,15 +590,14 @@ static int bcm2835gpio_quit(void)
}
-static const char * const bcm2835_transports[] = { "jtag", "swd", NULL };
-
static struct jtag_interface bcm2835gpio_interface = {
.supported = DEBUG_CAP_TMS_SEQ,
.execute_queue = bitbang_execute_queue,
};
struct adapter_driver bcm2835gpio_adapter_driver = {
.name = "bcm2835gpio",
- .transports = bcm2835_transports,
+ .transport_ids = TRANSPORT_JTAG | TRANSPORT_SWD,
+ .transport_preferred_id = TRANSPORT_JTAG,
.commands = bcm2835gpio_command_handlers,
.init = bcm2835gpio_init,
diff --git a/src/jtag/drivers/buspirate.c b/src/jtag/drivers/buspirate.c
index 93f0ba3..4283616 100644
--- a/src/jtag/drivers/buspirate.c
+++ b/src/jtag/drivers/buspirate.c
@@ -534,15 +534,14 @@ static const struct swd_driver buspirate_swd = {
.run = buspirate_swd_run_queue,
};
-static const char * const buspirate_transports[] = { "jtag", "swd", NULL };
-
static struct jtag_interface buspirate_interface = {
.execute_queue = buspirate_execute_queue,
};
struct adapter_driver buspirate_adapter_driver = {
.name = "buspirate",
- .transports = buspirate_transports,
+ .transport_ids = TRANSPORT_JTAG | TRANSPORT_SWD,
+ .transport_preferred_id = TRANSPORT_JTAG,
.commands = buspirate_command_handlers,
.init = buspirate_init,
diff --git a/src/jtag/drivers/cmsis_dap.c b/src/jtag/drivers/cmsis_dap.c
index be9ebae..2bfcfcc 100644
--- a/src/jtag/drivers/cmsis_dap.c
+++ b/src/jtag/drivers/cmsis_dap.c
@@ -2314,8 +2314,6 @@ static const struct swd_driver cmsis_dap_swd_driver = {
.run = cmsis_dap_swd_run_queue,
};
-static const char * const cmsis_dap_transport[] = { "swd", "jtag", NULL };
-
static struct jtag_interface cmsis_dap_interface = {
.supported = DEBUG_CAP_TMS_SEQ,
.execute_queue = cmsis_dap_execute_queue,
@@ -2323,7 +2321,8 @@ static struct jtag_interface cmsis_dap_interface = {
struct adapter_driver cmsis_dap_adapter_driver = {
.name = "cmsis-dap",
- .transports = cmsis_dap_transport,
+ .transport_ids = TRANSPORT_SWD | TRANSPORT_JTAG,
+ .transport_preferred_id = TRANSPORT_SWD,
.commands = cmsis_dap_command_handlers,
.init = cmsis_dap_init,
diff --git a/src/jtag/drivers/dmem.c b/src/jtag/drivers/dmem.c
index 4dc5821..e50e84a 100644
--- a/src/jtag/drivers/dmem.c
+++ b/src/jtag/drivers/dmem.c
@@ -604,11 +604,10 @@ static const struct dap_ops dmem_dap_ops = {
.run = dmem_dp_run,
};
-static const char *const dmem_dap_transport[] = { "dapdirect_swd", NULL };
-
struct adapter_driver dmem_dap_adapter_driver = {
.name = "dmem",
- .transports = dmem_dap_transport,
+ .transport_ids = TRANSPORT_DAPDIRECT_SWD,
+ .transport_preferred_id = TRANSPORT_DAPDIRECT_SWD,
.commands = dmem_dap_command_handlers,
.init = dmem_dap_init,
diff --git a/src/jtag/drivers/dummy.c b/src/jtag/drivers/dummy.c
index 79b29fb..471668c 100644
--- a/src/jtag/drivers/dummy.c
+++ b/src/jtag/drivers/dummy.c
@@ -140,7 +140,8 @@ static struct jtag_interface dummy_interface = {
struct adapter_driver dummy_adapter_driver = {
.name = "dummy",
- .transports = jtag_only,
+ .transport_ids = TRANSPORT_JTAG,
+ .transport_preferred_id = TRANSPORT_JTAG,
.commands = dummy_command_handlers,
.init = &dummy_init,
diff --git a/src/jtag/drivers/ep93xx.c b/src/jtag/drivers/ep93xx.c
index ea9faf1..f3e1676 100644
--- a/src/jtag/drivers/ep93xx.c
+++ b/src/jtag/drivers/ep93xx.c
@@ -46,7 +46,8 @@ static struct jtag_interface ep93xx_interface = {
struct adapter_driver ep93xx_adapter_driver = {
.name = "ep93xx",
- .transports = jtag_only,
+ .transport_ids = TRANSPORT_JTAG,
+ .transport_preferred_id = TRANSPORT_JTAG,
.init = ep93xx_init,
.quit = ep93xx_quit,
diff --git a/src/jtag/drivers/esp_usb_jtag.c b/src/jtag/drivers/esp_usb_jtag.c
index 9504059..a133035 100644
--- a/src/jtag/drivers/esp_usb_jtag.c
+++ b/src/jtag/drivers/esp_usb_jtag.c
@@ -784,7 +784,8 @@ static struct jtag_interface esp_usb_jtag_interface = {
struct adapter_driver esp_usb_adapter_driver = {
.name = "esp_usb_jtag",
- .transports = jtag_only,
+ .transport_ids = TRANSPORT_JTAG,
+ .transport_preferred_id = TRANSPORT_JTAG,
.commands = esp_usb_jtag_commands,
.init = esp_usb_jtag_init,
diff --git a/src/jtag/drivers/ft232r.c b/src/jtag/drivers/ft232r.c
index f4e5af4..f88e4b9 100644
--- a/src/jtag/drivers/ft232r.c
+++ b/src/jtag/drivers/ft232r.c
@@ -900,7 +900,8 @@ static struct jtag_interface ft232r_interface = {
struct adapter_driver ft232r_adapter_driver = {
.name = "ft232r",
- .transports = jtag_only,
+ .transport_ids = TRANSPORT_JTAG,
+ .transport_preferred_id = TRANSPORT_JTAG,
.commands = ft232r_command_handlers,
.init = ft232r_init,
diff --git a/src/jtag/drivers/ftdi.c b/src/jtag/drivers/ftdi.c
index f56a517..2c3339e 100644
--- a/src/jtag/drivers/ftdi.c
+++ b/src/jtag/drivers/ftdi.c
@@ -1665,8 +1665,6 @@ static const struct swd_driver ftdi_swd = {
.run = ftdi_swd_run_queue,
};
-static const char * const ftdi_transports[] = { "jtag", "swd", NULL };
-
static struct jtag_interface ftdi_interface = {
.supported = DEBUG_CAP_TMS_SEQ,
.execute_queue = ftdi_execute_queue,
@@ -1674,7 +1672,8 @@ static struct jtag_interface ftdi_interface = {
struct adapter_driver ftdi_adapter_driver = {
.name = "ftdi",
- .transports = ftdi_transports,
+ .transport_ids = TRANSPORT_JTAG | TRANSPORT_SWD,
+ .transport_preferred_id = TRANSPORT_JTAG,
.commands = ftdi_command_handlers,
.init = ftdi_initialize,
diff --git a/src/jtag/drivers/gw16012.c b/src/jtag/drivers/gw16012.c
index 7200e75..805065f 100644
--- a/src/jtag/drivers/gw16012.c
+++ b/src/jtag/drivers/gw16012.c
@@ -514,7 +514,8 @@ static struct jtag_interface gw16012_interface = {
struct adapter_driver gw16012_adapter_driver = {
.name = "gw16012",
- .transports = jtag_only,
+ .transport_ids = TRANSPORT_JTAG,
+ .transport_preferred_id = TRANSPORT_JTAG,
.commands = gw16012_command_handlers,
.init = gw16012_init,
diff --git a/src/jtag/drivers/imx_gpio.c b/src/jtag/drivers/imx_gpio.c
index 18dc2dd..a4a76ca 100644
--- a/src/jtag/drivers/imx_gpio.c
+++ b/src/jtag/drivers/imx_gpio.c
@@ -417,8 +417,6 @@ static const struct command_registration imx_gpio_command_handlers[] = {
COMMAND_REGISTRATION_DONE
};
-static const char * const imx_gpio_transports[] = { "jtag", "swd", NULL };
-
static struct jtag_interface imx_gpio_interface = {
.supported = DEBUG_CAP_TMS_SEQ,
.execute_queue = bitbang_execute_queue,
@@ -426,7 +424,8 @@ static struct jtag_interface imx_gpio_interface = {
struct adapter_driver imx_gpio_adapter_driver = {
.name = "imx_gpio",
- .transports = imx_gpio_transports,
+ .transport_ids = TRANSPORT_JTAG | TRANSPORT_SWD,
+ .transport_preferred_id = TRANSPORT_JTAG,
.commands = imx_gpio_command_handlers,
.init = imx_gpio_init,
diff --git a/src/jtag/drivers/jlink.c b/src/jtag/drivers/jlink.c
index 4d15cf5..9caf37f 100644
--- a/src/jtag/drivers/jlink.c
+++ b/src/jtag/drivers/jlink.c
@@ -2264,15 +2264,14 @@ static const struct swd_driver jlink_swd = {
.run = &jlink_swd_run_queue,
};
-static const char * const jlink_transports[] = { "jtag", "swd", NULL };
-
static struct jtag_interface jlink_interface = {
.execute_queue = &jlink_execute_queue,
};
struct adapter_driver jlink_adapter_driver = {
.name = "jlink",
- .transports = jlink_transports,
+ .transport_ids = TRANSPORT_JTAG | TRANSPORT_SWD,
+ .transport_preferred_id = TRANSPORT_JTAG,
.commands = jlink_command_handlers,
.init = &jlink_init,
diff --git a/src/jtag/drivers/jtag_dpi.c b/src/jtag/drivers/jtag_dpi.c
index 046186a..d6418d3 100644
--- a/src/jtag/drivers/jtag_dpi.c
+++ b/src/jtag/drivers/jtag_dpi.c
@@ -398,7 +398,8 @@ static struct jtag_interface jtag_dpi_interface = {
struct adapter_driver jtag_dpi_adapter_driver = {
.name = "jtag_dpi",
- .transports = jtag_only,
+ .transport_ids = TRANSPORT_JTAG,
+ .transport_preferred_id = TRANSPORT_JTAG,
.commands = jtag_dpi_command_handlers,
.init = jtag_dpi_init,
.quit = jtag_dpi_quit,
diff --git a/src/jtag/drivers/jtag_vpi.c b/src/jtag/drivers/jtag_vpi.c
index f6cb3de..fac27b3 100644
--- a/src/jtag/drivers/jtag_vpi.c
+++ b/src/jtag/drivers/jtag_vpi.c
@@ -666,7 +666,8 @@ static struct jtag_interface jtag_vpi_interface = {
struct adapter_driver jtag_vpi_adapter_driver = {
.name = "jtag_vpi",
- .transports = jtag_only,
+ .transport_ids = TRANSPORT_JTAG,
+ .transport_preferred_id = TRANSPORT_JTAG,
.commands = jtag_vpi_command_handlers,
.init = jtag_vpi_init,
diff --git a/src/jtag/drivers/kitprog.c b/src/jtag/drivers/kitprog.c
index 98b0d16..88e301c 100644
--- a/src/jtag/drivers/kitprog.c
+++ b/src/jtag/drivers/kitprog.c
@@ -908,11 +908,10 @@ static const struct swd_driver kitprog_swd = {
.run = kitprog_swd_run_queue,
};
-static const char * const kitprog_transports[] = { "swd", NULL };
-
struct adapter_driver kitprog_adapter_driver = {
.name = "kitprog",
- .transports = kitprog_transports,
+ .transport_ids = TRANSPORT_SWD,
+ .transport_preferred_id = TRANSPORT_SWD,
.commands = kitprog_command_handlers,
.init = kitprog_init,
diff --git a/src/jtag/drivers/linuxgpiod.c b/src/jtag/drivers/linuxgpiod.c
index eda7b1a..36c7e04 100644
--- a/src/jtag/drivers/linuxgpiod.c
+++ b/src/jtag/drivers/linuxgpiod.c
@@ -425,8 +425,6 @@ out_error:
return ERROR_JTAG_INIT_FAILED;
}
-static const char *const linuxgpiod_transport[] = { "swd", "jtag", NULL };
-
static struct jtag_interface linuxgpiod_interface = {
.supported = DEBUG_CAP_TMS_SEQ,
.execute_queue = bitbang_execute_queue,
@@ -434,7 +432,8 @@ static struct jtag_interface linuxgpiod_interface = {
struct adapter_driver linuxgpiod_adapter_driver = {
.name = "linuxgpiod",
- .transports = linuxgpiod_transport,
+ .transport_ids = TRANSPORT_SWD | TRANSPORT_JTAG,
+ .transport_preferred_id = TRANSPORT_SWD,
.init = linuxgpiod_init,
.quit = linuxgpiod_quit,
diff --git a/src/jtag/drivers/linuxspidev.c b/src/jtag/drivers/linuxspidev.c
index 18abdc7..396f1a1 100644
--- a/src/jtag/drivers/linuxspidev.c
+++ b/src/jtag/drivers/linuxspidev.c
@@ -616,12 +616,10 @@ static const struct command_registration spidev_command_handlers[] = {
COMMAND_REGISTRATION_DONE
};
-// Only SWD transport supported
-static const char *const spidev_transports[] = { "swd", NULL };
-
struct adapter_driver linuxspidev_adapter_driver = {
.name = "linuxspidev",
- .transports = spidev_transports,
+ .transport_ids = TRANSPORT_SWD,
+ .transport_preferred_id = TRANSPORT_SWD,
.commands = spidev_command_handlers,
.init = spidev_init,
diff --git a/src/jtag/drivers/opendous.c b/src/jtag/drivers/opendous.c
index 999afb3..04626cb 100644
--- a/src/jtag/drivers/opendous.c
+++ b/src/jtag/drivers/opendous.c
@@ -229,7 +229,8 @@ static struct jtag_interface opendous_interface = {
struct adapter_driver opendous_adapter_driver = {
.name = "opendous",
- .transports = jtag_only,
+ .transport_ids = TRANSPORT_JTAG,
+ .transport_preferred_id = TRANSPORT_JTAG,
.commands = opendous_command_handlers,
.init = opendous_init,
diff --git a/src/jtag/drivers/openjtag.c b/src/jtag/drivers/openjtag.c
index 14bcc17..943ad85 100644
--- a/src/jtag/drivers/openjtag.c
+++ b/src/jtag/drivers/openjtag.c
@@ -931,7 +931,8 @@ static struct jtag_interface openjtag_interface = {
struct adapter_driver openjtag_adapter_driver = {
.name = "openjtag",
- .transports = jtag_only,
+ .transport_ids = TRANSPORT_JTAG,
+ .transport_preferred_id = TRANSPORT_JTAG,
.commands = openjtag_command_handlers,
.init = openjtag_init,
diff --git a/src/jtag/drivers/osbdm.c b/src/jtag/drivers/osbdm.c
index 80f66d1..de2e1f8 100644
--- a/src/jtag/drivers/osbdm.c
+++ b/src/jtag/drivers/osbdm.c
@@ -684,7 +684,8 @@ static struct jtag_interface osbdm_interface = {
struct adapter_driver osbdm_adapter_driver = {
.name = "osbdm",
- .transports = jtag_only,
+ .transport_ids = TRANSPORT_JTAG,
+ .transport_preferred_id = TRANSPORT_JTAG,
.init = osbdm_init,
.quit = osbdm_quit,
diff --git a/src/jtag/drivers/parport.c b/src/jtag/drivers/parport.c
index 3b20fe2..143f3bd 100644
--- a/src/jtag/drivers/parport.c
+++ b/src/jtag/drivers/parport.c
@@ -533,7 +533,8 @@ static struct jtag_interface parport_interface = {
struct adapter_driver parport_adapter_driver = {
.name = "parport",
- .transports = jtag_only,
+ .transport_ids = TRANSPORT_JTAG,
+ .transport_preferred_id = TRANSPORT_JTAG,
.commands = parport_command_handlers,
.init = parport_init,
diff --git a/src/jtag/drivers/presto.c b/src/jtag/drivers/presto.c
index f6e13f7..84b881c 100644
--- a/src/jtag/drivers/presto.c
+++ b/src/jtag/drivers/presto.c
@@ -528,7 +528,8 @@ static struct jtag_interface presto_interface = {
struct adapter_driver presto_adapter_driver = {
.name = "presto",
- .transports = jtag_only,
+ .transport_ids = TRANSPORT_JTAG,
+ .transport_preferred_id = TRANSPORT_JTAG,
.init = presto_jtag_init,
.quit = presto_jtag_quit,
diff --git a/src/jtag/drivers/remote_bitbang.c b/src/jtag/drivers/remote_bitbang.c
index bb608ba..449c616 100644
--- a/src/jtag/drivers/remote_bitbang.c
+++ b/src/jtag/drivers/remote_bitbang.c
@@ -412,8 +412,6 @@ COMMAND_HANDLER(remote_bitbang_handle_remote_bitbang_host_command)
return ERROR_COMMAND_SYNTAX_ERROR;
}
-static const char * const remote_bitbang_transports[] = { "jtag", "swd", NULL };
-
COMMAND_HANDLER(remote_bitbang_handle_remote_bitbang_use_remote_sleep_command)
{
if (CMD_ARGC != 1)
@@ -484,7 +482,8 @@ static struct jtag_interface remote_bitbang_interface = {
struct adapter_driver remote_bitbang_adapter_driver = {
.name = "remote_bitbang",
- .transports = remote_bitbang_transports,
+ .transport_ids = TRANSPORT_JTAG | TRANSPORT_SWD,
+ .transport_preferred_id = TRANSPORT_JTAG,
.commands = remote_bitbang_command_handlers,
.init = &remote_bitbang_init,
diff --git a/src/jtag/drivers/rlink.c b/src/jtag/drivers/rlink.c
index 6ea3729..a818996 100644
--- a/src/jtag/drivers/rlink.c
+++ b/src/jtag/drivers/rlink.c
@@ -1675,7 +1675,8 @@ static struct jtag_interface rlink_interface = {
struct adapter_driver rlink_adapter_driver = {
.name = "rlink",
- .transports = jtag_only,
+ .transport_ids = TRANSPORT_JTAG,
+ .transport_preferred_id = TRANSPORT_JTAG,
.init = rlink_init,
.quit = rlink_quit,
diff --git a/src/jtag/drivers/rshim.c b/src/jtag/drivers/rshim.c
index b37fe8c..89bdadd 100644
--- a/src/jtag/drivers/rshim.c
+++ b/src/jtag/drivers/rshim.c
@@ -508,11 +508,10 @@ static const struct dap_ops rshim_dap_ops = {
.quit = rshim_disconnect,
};
-static const char *const rshim_dap_transport[] = { "dapdirect_swd", NULL };
-
struct adapter_driver rshim_dap_adapter_driver = {
.name = "rshim",
- .transports = rshim_dap_transport,
+ .transport_ids = TRANSPORT_DAPDIRECT_SWD,
+ .transport_preferred_id = TRANSPORT_DAPDIRECT_SWD,
.commands = rshim_dap_command_handlers,
.init = rshim_dap_init,
diff --git a/src/jtag/drivers/stlink_usb.c b/src/jtag/drivers/stlink_usb.c
index d77f28b..5ee1f85 100644
--- a/src/jtag/drivers/stlink_usb.c
+++ b/src/jtag/drivers/stlink_usb.c
@@ -5143,7 +5143,12 @@ static int stlink_dap_init(void)
if ((mode != STLINK_MODE_DEBUG_SWIM) &&
!(stlink_dap_handle->version.flags & STLINK_F_HAS_DAP_REG)) {
- LOG_ERROR("ST-Link version does not support DAP direct transport");
+ LOG_ERROR("The firmware in the ST-Link adapter only supports deprecated HLA.");
+ LOG_ERROR("Please consider updating the ST-Link firmware with a version");
+ LOG_ERROR("newer that V2J24 (2015), available for downloading on ST website:");
+ LOG_ERROR(" https://www.st.com/en/development-tools/stsw-link007.html");
+ LOG_ERROR("In mean time, you can re-run OpenOCD for ST-Link HLA as:");
+ LOG_ERROR(" openocd -f interface/stlink-hla.cfg ...");
return ERROR_FAIL;
}
return ERROR_OK;
@@ -5217,11 +5222,10 @@ static const struct swim_driver stlink_swim_ops = {
.reconnect = stlink_swim_op_reconnect,
};
-static const char *const stlink_dap_transport[] = { "dapdirect_swd", "dapdirect_jtag", "swim", NULL };
-
struct adapter_driver stlink_dap_adapter_driver = {
.name = "st-link",
- .transports = stlink_dap_transport,
+ .transport_ids = TRANSPORT_DAPDIRECT_SWD | TRANSPORT_DAPDIRECT_JTAG | TRANSPORT_SWIM,
+ .transport_preferred_id = TRANSPORT_DAPDIRECT_SWD,
.commands = stlink_dap_command_handlers,
.init = stlink_dap_init,
diff --git a/src/jtag/drivers/sysfsgpio.c b/src/jtag/drivers/sysfsgpio.c
index ccd3974..279b353 100644
--- a/src/jtag/drivers/sysfsgpio.c
+++ b/src/jtag/drivers/sysfsgpio.c
@@ -545,8 +545,6 @@ static const struct command_registration sysfsgpio_command_handlers[] = {
static int sysfsgpio_init(void);
static int sysfsgpio_quit(void);
-static const char * const sysfsgpio_transports[] = { "jtag", "swd", NULL };
-
static struct jtag_interface sysfsgpio_interface = {
.supported = DEBUG_CAP_TMS_SEQ,
.execute_queue = bitbang_execute_queue,
@@ -554,7 +552,8 @@ static struct jtag_interface sysfsgpio_interface = {
struct adapter_driver sysfsgpio_adapter_driver = {
.name = "sysfsgpio",
- .transports = sysfsgpio_transports,
+ .transport_ids = TRANSPORT_JTAG | TRANSPORT_SWD,
+ .transport_preferred_id = TRANSPORT_JTAG,
.commands = sysfsgpio_command_handlers,
.init = sysfsgpio_init,
diff --git a/src/jtag/drivers/ulink.c b/src/jtag/drivers/ulink.c
index 0a13bf6..417d560 100644
--- a/src/jtag/drivers/ulink.c
+++ b/src/jtag/drivers/ulink.c
@@ -2271,7 +2271,8 @@ static struct jtag_interface ulink_interface = {
struct adapter_driver ulink_adapter_driver = {
.name = "ulink",
- .transports = jtag_only,
+ .transport_ids = TRANSPORT_JTAG,
+ .transport_preferred_id = TRANSPORT_JTAG,
.commands = ulink_command_handlers,
.init = ulink_init,
diff --git a/src/jtag/drivers/usb_blaster/usb_blaster.c b/src/jtag/drivers/usb_blaster/usb_blaster.c
index 1782cc4..8134466 100644
--- a/src/jtag/drivers/usb_blaster/usb_blaster.c
+++ b/src/jtag/drivers/usb_blaster/usb_blaster.c
@@ -1057,7 +1057,8 @@ static struct jtag_interface usb_blaster_interface = {
struct adapter_driver usb_blaster_adapter_driver = {
.name = "usb_blaster",
- .transports = jtag_only,
+ .transport_ids = TRANSPORT_JTAG,
+ .transport_preferred_id = TRANSPORT_JTAG,
.commands = ublast_command_handlers,
.init = ublast_init,
diff --git a/src/jtag/drivers/usbprog.c b/src/jtag/drivers/usbprog.c
index 24407f0..264b45f 100644
--- a/src/jtag/drivers/usbprog.c
+++ b/src/jtag/drivers/usbprog.c
@@ -590,7 +590,8 @@ static struct jtag_interface usbprog_interface = {
struct adapter_driver usbprog_adapter_driver = {
.name = "usbprog",
- .transports = jtag_only,
+ .transport_ids = TRANSPORT_JTAG,
+ .transport_preferred_id = TRANSPORT_JTAG,
.init = usbprog_init,
.quit = usbprog_quit,
diff --git a/src/jtag/drivers/vdebug.c b/src/jtag/drivers/vdebug.c
index fd1e6a7..3868595 100644
--- a/src/jtag/drivers/vdebug.c
+++ b/src/jtag/drivers/vdebug.c
@@ -1342,11 +1342,10 @@ static const struct dap_ops vdebug_dap_ops = {
.quit = NULL, /* optional */
};
-static const char *const vdebug_transports[] = { "jtag", "dapdirect_swd", NULL };
-
struct adapter_driver vdebug_adapter_driver = {
.name = "vdebug",
- .transports = vdebug_transports,
+ .transport_ids = TRANSPORT_JTAG | TRANSPORT_DAPDIRECT_SWD,
+ .transport_preferred_id = TRANSPORT_JTAG,
.speed = vdebug_jtag_speed,
.khz = vdebug_jtag_khz,
.speed_div = vdebug_jtag_div,
diff --git a/src/jtag/drivers/vsllink.c b/src/jtag/drivers/vsllink.c
index c10ed13..145f068 100644
--- a/src/jtag/drivers/vsllink.c
+++ b/src/jtag/drivers/vsllink.c
@@ -913,8 +913,6 @@ static const struct command_registration vsllink_command_handlers[] = {
COMMAND_REGISTRATION_DONE
};
-static const char * const vsllink_transports[] = {"jtag", "swd", NULL};
-
static const struct swd_driver vsllink_swd_driver = {
.init = vsllink_swd_init,
.switch_seq = vsllink_swd_switch_seq,
@@ -930,7 +928,8 @@ static struct jtag_interface vsllink_interface = {
struct adapter_driver vsllink_adapter_driver = {
.name = "vsllink",
- .transports = vsllink_transports,
+ .transport_ids = TRANSPORT_JTAG | TRANSPORT_SWD,
+ .transport_preferred_id = TRANSPORT_JTAG,
.commands = vsllink_command_handlers,
.init = vsllink_init,
diff --git a/src/jtag/drivers/xds110.c b/src/jtag/drivers/xds110.c
index c843710..d1bb705 100644
--- a/src/jtag/drivers/xds110.c
+++ b/src/jtag/drivers/xds110.c
@@ -2058,15 +2058,14 @@ static const struct swd_driver xds110_swd_driver = {
.run = xds110_swd_run_queue,
};
-static const char * const xds110_transport[] = { "swd", "jtag", NULL };
-
static struct jtag_interface xds110_interface = {
.execute_queue = xds110_execute_queue,
};
struct adapter_driver xds110_adapter_driver = {
.name = "xds110",
- .transports = xds110_transport,
+ .transport_ids = TRANSPORT_SWD | TRANSPORT_JTAG,
+ .transport_preferred_id = TRANSPORT_SWD,
.commands = xds110_command_handlers,
.init = xds110_init,
diff --git a/src/jtag/drivers/xlnx-pcie-xvc.c b/src/jtag/drivers/xlnx-pcie-xvc.c
index 37c6777..3baa183 100644
--- a/src/jtag/drivers/xlnx-pcie-xvc.c
+++ b/src/jtag/drivers/xlnx-pcie-xvc.c
@@ -690,11 +690,10 @@ static const struct swd_driver xlnx_pcie_xvc_swd_ops = {
.run = xlnx_pcie_xvc_swd_run_queue,
};
-static const char * const xlnx_pcie_xvc_transports[] = { "jtag", "swd", NULL };
-
struct adapter_driver xlnx_pcie_xvc_adapter_driver = {
.name = "xlnx_pcie_xvc",
- .transports = xlnx_pcie_xvc_transports,
+ .transport_ids = TRANSPORT_JTAG | TRANSPORT_SWD,
+ .transport_preferred_id = TRANSPORT_JTAG,
.commands = xlnx_pcie_xvc_command_handlers,
.init = &xlnx_pcie_xvc_init,
diff --git a/src/jtag/hla/hla_interface.c b/src/jtag/hla/hla_interface.c
index 96862b0..a9d196c 100644
--- a/src/jtag/hla/hla_interface.c
+++ b/src/jtag/hla/hla_interface.c
@@ -367,7 +367,8 @@ static const struct command_registration hl_interface_command_handlers[] = {
struct adapter_driver hl_adapter_driver = {
.name = "hla",
- .transports = hl_transports,
+ .transport_ids = TRANSPORT_HLA_SWD | TRANSPORT_HLA_JTAG,
+ .transport_preferred_id = TRANSPORT_HLA_SWD,
.commands = hl_interface_command_handlers,
.init = hl_interface_init,
diff --git a/src/jtag/hla/hla_interface.h b/src/jtag/hla/hla_interface.h
index f1550d9..c0ee054 100644
--- a/src/jtag/hla/hla_interface.h
+++ b/src/jtag/hla/hla_interface.h
@@ -15,8 +15,6 @@
struct target;
/** */
enum e_hl_transports;
-/** */
-extern const char *hl_transports[];
#define HLA_MAX_USB_IDS 16
diff --git a/src/jtag/hla/hla_transport.c b/src/jtag/hla/hla_transport.c
index b826eb0..d8ece07 100644
--- a/src/jtag/hla/hla_transport.c
+++ b/src/jtag/hla/hla_transport.c
@@ -177,15 +177,20 @@ static int hl_transport_init(struct command_context *cmd_ctx)
return ERROR_FAIL;
}
- LOG_DEBUG("current transport %s", transport->name);
+ LOG_DEBUG("current transport %s", get_current_transport_name());
/* get selected transport as enum */
- tr = HL_TRANSPORT_UNKNOWN;
-
- if (strcmp(transport->name, "hla_swd") == 0)
+ switch (transport->id) {
+ case TRANSPORT_HLA_SWD:
tr = HL_TRANSPORT_SWD;
- else if (strcmp(transport->name, "hla_jtag") == 0)
+ break;
+ case TRANSPORT_HLA_JTAG:
tr = HL_TRANSPORT_JTAG;
+ break;
+ default:
+ tr = HL_TRANSPORT_UNKNOWN;
+ break;
+ }
int retval = hl_interface_open(tr);
@@ -213,21 +218,19 @@ static int hl_swd_transport_select(struct command_context *cmd_ctx)
}
static struct transport hl_swd_transport = {
- .name = "hla_swd",
+ .id = TRANSPORT_HLA_SWD,
.select = hl_swd_transport_select,
.init = hl_transport_init,
.override_target = hl_interface_override_target,
};
static struct transport hl_jtag_transport = {
- .name = "hla_jtag",
+ .id = TRANSPORT_HLA_JTAG,
.select = hl_jtag_transport_select,
.init = hl_transport_init,
.override_target = hl_interface_override_target,
};
-const char *hl_transports[] = { "hla_swd", "hla_jtag", NULL };
-
static void hl_constructor(void) __attribute__ ((constructor));
static void hl_constructor(void)
{
diff --git a/src/jtag/interface.h b/src/jtag/interface.h
index b2d7123..475dbed 100644
--- a/src/jtag/interface.h
+++ b/src/jtag/interface.h
@@ -17,6 +17,7 @@
#include <jtag/jtag.h>
#include <jtag/swim.h>
#include <target/arm_tpiu_swo.h>
+#include <transport/transport.h>
/* @file
* The "Cable Helper API" is what the cable drivers can use to help
@@ -208,8 +209,16 @@ struct adapter_driver {
/** The name of the interface driver. */
const char * const name;
- /** transports supported in C code (NULL terminated vector) */
- const char * const *transports;
+ /**
+ * Bitmask of transport IDs supported in C code.
+ */
+ unsigned int transport_ids;
+
+ /**
+ * ID of transport that gets auto-selected when not specified by the user.
+ * The auto-selection of transport is DEPRECATED.
+ */
+ unsigned int transport_preferred_id;
/**
* The interface driver may register additional commands to expose
@@ -354,8 +363,6 @@ struct adapter_driver {
const struct swim_driver *swim_ops;
};
-extern const char * const jtag_only[];
-
int adapter_resets(int assert_trst, int assert_srst);
int adapter_assert_reset(void);
int adapter_deassert_reset(void);
diff --git a/src/jtag/swim.c b/src/jtag/swim.c
index de3e106..004a9fd 100644
--- a/src/jtag/swim.c
+++ b/src/jtag/swim.c
@@ -136,7 +136,7 @@ static int swim_transport_init(struct command_context *cmd_ctx)
}
static struct transport swim_transport = {
- .name = "swim",
+ .id = TRANSPORT_SWIM,
.select = swim_transport_select,
.init = swim_transport_init,
};
diff --git a/src/target/Makefile.am b/src/target/Makefile.am
index 1fc7d2a..1a76864 100644
--- a/src/target/Makefile.am
+++ b/src/target/Makefile.am
@@ -224,7 +224,6 @@ ARC_SRC = \
%D%/avr32_mem.h \
%D%/avr32_regs.h \
%D%/semihosting_common.h \
- %D%/stm8.h \
%D%/lakemont.h \
%D%/x86_32_common.h \
%D%/arm_cti.h \
diff --git a/src/target/aarch64.c b/src/target/aarch64.c
index ce7808e..101cb14 100644
--- a/src/target/aarch64.c
+++ b/src/target/aarch64.c
@@ -2814,7 +2814,7 @@ static int aarch64_init_arch_info(struct target *target,
return ERROR_OK;
}
-static int armv8r_target_create(struct target *target, Jim_Interp *interp)
+static int armv8r_target_create(struct target *target)
{
struct aarch64_private_config *pc = target->private_config;
struct aarch64_common *aarch64;
@@ -2833,7 +2833,7 @@ static int armv8r_target_create(struct target *target, Jim_Interp *interp)
return aarch64_init_arch_info(target, aarch64, pc->adiv5_config.dap);
}
-static int aarch64_target_create(struct target *target, Jim_Interp *interp)
+static int aarch64_target_create(struct target *target)
{
struct aarch64_private_config *pc = target->private_config;
struct aarch64_common *aarch64;
diff --git a/src/target/adi_v5_dapdirect.c b/src/target/adi_v5_dapdirect.c
index d198dac..07ea313 100644
--- a/src/target/adi_v5_dapdirect.c
+++ b/src/target/adi_v5_dapdirect.c
@@ -207,13 +207,13 @@ static int dapdirect_init(struct command_context *ctx)
}
static struct transport dapdirect_jtag_transport = {
- .name = "dapdirect_jtag",
+ .id = TRANSPORT_DAPDIRECT_JTAG,
.select = dapdirect_jtag_select,
.init = dapdirect_init,
};
static struct transport dapdirect_swd_transport = {
- .name = "dapdirect_swd",
+ .id = TRANSPORT_DAPDIRECT_SWD,
.select = dapdirect_swd_select,
.init = dapdirect_init,
};
diff --git a/src/target/adi_v5_swd.c b/src/target/adi_v5_swd.c
index e50f8f1..2d28613 100644
--- a/src/target/adi_v5_swd.c
+++ b/src/target/adi_v5_swd.c
@@ -756,7 +756,7 @@ static int swd_init(struct command_context *ctx)
}
static struct transport swd_transport = {
- .name = "swd",
+ .id = TRANSPORT_SWD,
.select = swd_select,
.init = swd_init,
};
diff --git a/src/target/arc.c b/src/target/arc.c
index 8757caf..f2482c2 100644
--- a/src/target/arc.c
+++ b/src/target/arc.c
@@ -1424,7 +1424,7 @@ static void arc_deinit_target(struct target *target)
}
-static int arc_target_create(struct target *target, Jim_Interp *interp)
+static int arc_target_create(struct target *target)
{
struct arc_common *arc = calloc(1, sizeof(*arc));
diff --git a/src/target/arm11.c b/src/target/arm11.c
index 756b36b..583830f 100644
--- a/src/target/arm11.c
+++ b/src/target/arm11.c
@@ -1079,7 +1079,7 @@ static int arm11_remove_breakpoint(struct target *target,
return ERROR_OK;
}
-static int arm11_target_create(struct target *target, Jim_Interp *interp)
+static int arm11_target_create(struct target *target)
{
struct arm11_common *arm11;
diff --git a/src/target/arm720t.c b/src/target/arm720t.c
index beab632..d1433dd 100644
--- a/src/target/arm720t.c
+++ b/src/target/arm720t.c
@@ -412,7 +412,7 @@ static int arm720t_init_arch_info(struct target *target,
return ERROR_OK;
}
-static int arm720t_target_create(struct target *target, Jim_Interp *interp)
+static int arm720t_target_create(struct target *target)
{
struct arm720t_common *arm720t = calloc(1, sizeof(*arm720t));
diff --git a/src/target/arm7tdmi.c b/src/target/arm7tdmi.c
index 393d3b4..2f59254 100644
--- a/src/target/arm7tdmi.c
+++ b/src/target/arm7tdmi.c
@@ -669,7 +669,7 @@ int arm7tdmi_init_arch_info(struct target *target,
return ERROR_OK;
}
-static int arm7tdmi_target_create(struct target *target, Jim_Interp *interp)
+static int arm7tdmi_target_create(struct target *target)
{
struct arm7_9_common *arm7_9;
diff --git a/src/target/arm920t.c b/src/target/arm920t.c
index 53b4d9d..95cfd7c 100644
--- a/src/target/arm920t.c
+++ b/src/target/arm920t.c
@@ -833,7 +833,7 @@ static int arm920t_init_arch_info(struct target *target,
return ERROR_OK;
}
-static int arm920t_target_create(struct target *target, Jim_Interp *interp)
+static int arm920t_target_create(struct target *target)
{
struct arm920t_common *arm920t;
diff --git a/src/target/arm926ejs.c b/src/target/arm926ejs.c
index add90c9..0531106 100644
--- a/src/target/arm926ejs.c
+++ b/src/target/arm926ejs.c
@@ -702,7 +702,7 @@ int arm926ejs_init_arch_info(struct target *target, struct arm926ejs_common *arm
return ERROR_OK;
}
-static int arm926ejs_target_create(struct target *target, Jim_Interp *interp)
+static int arm926ejs_target_create(struct target *target)
{
struct arm926ejs_common *arm926ejs = calloc(1, sizeof(struct arm926ejs_common));
diff --git a/src/target/arm946e.c b/src/target/arm946e.c
index 03f7e44..828e70f 100644
--- a/src/target/arm946e.c
+++ b/src/target/arm946e.c
@@ -79,7 +79,7 @@ static int arm946e_init_arch_info(struct target *target,
return ERROR_OK;
}
-static int arm946e_target_create(struct target *target, Jim_Interp *interp)
+static int arm946e_target_create(struct target *target)
{
struct arm946e_common *arm946e = calloc(1, sizeof(struct arm946e_common));
diff --git a/src/target/arm966e.c b/src/target/arm966e.c
index 8598d29..b6bcc8b 100644
--- a/src/target/arm966e.c
+++ b/src/target/arm966e.c
@@ -38,7 +38,7 @@ int arm966e_init_arch_info(struct target *target, struct arm966e_common *arm966e
return ERROR_OK;
}
-static int arm966e_target_create(struct target *target, Jim_Interp *interp)
+static int arm966e_target_create(struct target *target)
{
struct arm966e_common *arm966e = calloc(1, sizeof(struct arm966e_common));
diff --git a/src/target/arm9tdmi.c b/src/target/arm9tdmi.c
index 7e31306..8ab12de 100644
--- a/src/target/arm9tdmi.c
+++ b/src/target/arm9tdmi.c
@@ -765,7 +765,7 @@ int arm9tdmi_init_arch_info(struct target *target,
return ERROR_OK;
}
-static int arm9tdmi_target_create(struct target *target, Jim_Interp *interp)
+static int arm9tdmi_target_create(struct target *target)
{
struct arm7_9_common *arm7_9 = calloc(1, sizeof(struct arm7_9_common));
diff --git a/src/target/avr32_ap7k.c b/src/target/avr32_ap7k.c
index 1b051dc..94962c2 100644
--- a/src/target/avr32_ap7k.c
+++ b/src/target/avr32_ap7k.c
@@ -510,7 +510,7 @@ static int avr32_ap7k_init_target(struct command_context *cmd_ctx,
return ERROR_OK;
}
-static int avr32_ap7k_target_create(struct target *target, Jim_Interp *interp)
+static int avr32_ap7k_target_create(struct target *target)
{
struct avr32_ap7k_common *ap7k = calloc(1, sizeof(struct
avr32_ap7k_common));
diff --git a/src/target/avrt.c b/src/target/avrt.c
index 3afe320..e25718b 100644
--- a/src/target/avrt.c
+++ b/src/target/avrt.c
@@ -16,7 +16,7 @@
#define AVR_JTAG_INS_LEN 4
/* forward declarations */
-static int avr_target_create(struct target *target, Jim_Interp *interp);
+static int avr_target_create(struct target *target);
static int avr_init_target(struct command_context *cmd_ctx, struct target *target);
static int avr_arch_state(struct target *target);
@@ -68,7 +68,7 @@ struct target_type avr_target = {
.init_target = avr_init_target,
};
-static int avr_target_create(struct target *target, Jim_Interp *interp)
+static int avr_target_create(struct target *target)
{
struct avr_common *avr = calloc(1, sizeof(struct avr_common));
diff --git a/src/target/cortex_a.c b/src/target/cortex_a.c
index 9c60645..ee27e1b 100644
--- a/src/target/cortex_a.c
+++ b/src/target/cortex_a.c
@@ -3126,7 +3126,7 @@ static int cortex_a_init_arch_info(struct target *target,
return ERROR_OK;
}
-static int cortex_a_target_create(struct target *target, Jim_Interp *interp)
+static int cortex_a_target_create(struct target *target)
{
struct cortex_a_common *cortex_a;
struct adiv5_private_config *pc;
@@ -3148,7 +3148,7 @@ static int cortex_a_target_create(struct target *target, Jim_Interp *interp)
return cortex_a_init_arch_info(target, cortex_a, pc->dap);
}
-static int cortex_r4_target_create(struct target *target, Jim_Interp *interp)
+static int cortex_r4_target_create(struct target *target)
{
struct cortex_a_common *cortex_a;
struct adiv5_private_config *pc;
diff --git a/src/target/cortex_m.c b/src/target/cortex_m.c
index e17f23c..ba9d83d 100644
--- a/src/target/cortex_m.c
+++ b/src/target/cortex_m.c
@@ -2916,7 +2916,7 @@ static int cortex_m_init_arch_info(struct target *target,
return ERROR_OK;
}
-static int cortex_m_target_create(struct target *target, Jim_Interp *interp)
+static int cortex_m_target_create(struct target *target)
{
struct adiv5_private_config *pc;
diff --git a/src/target/dsp563xx.c b/src/target/dsp563xx.c
index 629056f..8198438 100644
--- a/src/target/dsp563xx.c
+++ b/src/target/dsp563xx.c
@@ -880,7 +880,7 @@ static void dsp563xx_invalidate_x_context(struct target *target,
}
}
-static int dsp563xx_target_create(struct target *target, Jim_Interp *interp)
+static int dsp563xx_target_create(struct target *target)
{
struct dsp563xx_common *dsp563xx = calloc(1, sizeof(struct dsp563xx_common));
diff --git a/src/target/dsp5680xx.c b/src/target/dsp5680xx.c
index 3f9a674..65efbae 100644
--- a/src/target/dsp5680xx.c
+++ b/src/target/dsp5680xx.c
@@ -855,7 +855,7 @@ static int eonce_pc_store(struct target *target)
return ERROR_OK;
}
-static int dsp5680xx_target_create(struct target *target, Jim_Interp *interp)
+static int dsp5680xx_target_create(struct target *target)
{
struct dsp5680xx_common *dsp5680xx =
calloc(1, sizeof(struct dsp5680xx_common));
diff --git a/src/target/esirisc.c b/src/target/esirisc.c
index da40928..fac5dc7 100644
--- a/src/target/esirisc.c
+++ b/src/target/esirisc.c
@@ -1575,7 +1575,7 @@ static int esirisc_identify(struct target *target)
return ERROR_OK;
}
-static int esirisc_target_create(struct target *target, Jim_Interp *interp)
+static int esirisc_target_create(struct target *target)
{
struct jtag_tap *tap = target->tap;
struct esirisc_common *esirisc;
diff --git a/src/target/espressif/esp32.c b/src/target/espressif/esp32.c
index 4deb5e0..399ba8e 100644
--- a/src/target/espressif/esp32.c
+++ b/src/target/espressif/esp32.c
@@ -326,7 +326,7 @@ static const struct esp_semihost_ops esp32_semihost_ops = {
.prepare = esp32_disable_wdts
};
-static int esp32_target_create(struct target *target, Jim_Interp *interp)
+static int esp32_target_create(struct target *target)
{
struct xtensa_debug_module_config esp32_dm_cfg = {
.dbg_ops = &esp32_dbg_ops,
diff --git a/src/target/espressif/esp32s2.c b/src/target/espressif/esp32s2.c
index 4f3914f..b86e43e 100644
--- a/src/target/espressif/esp32s2.c
+++ b/src/target/espressif/esp32s2.c
@@ -445,7 +445,7 @@ static const struct esp_semihost_ops esp32s2_semihost_ops = {
.prepare = esp32s2_disable_wdts
};
-static int esp32s2_target_create(struct target *target, Jim_Interp *interp)
+static int esp32s2_target_create(struct target *target)
{
struct xtensa_debug_module_config esp32s2_dm_cfg = {
.dbg_ops = &esp32s2_dbg_ops,
diff --git a/src/target/espressif/esp32s3.c b/src/target/espressif/esp32s3.c
index 7507c11..82413f7 100644
--- a/src/target/espressif/esp32s3.c
+++ b/src/target/espressif/esp32s3.c
@@ -320,7 +320,7 @@ static const struct esp_semihost_ops esp32s3_semihost_ops = {
.prepare = esp32s3_disable_wdts
};
-static int esp32s3_target_create(struct target *target, Jim_Interp *interp)
+static int esp32s3_target_create(struct target *target)
{
struct xtensa_debug_module_config esp32s3_dm_cfg = {
.dbg_ops = &esp32s3_dbg_ops,
diff --git a/src/target/fa526.c b/src/target/fa526.c
index 38b7ab2..d832d3e 100644
--- a/src/target/fa526.c
+++ b/src/target/fa526.c
@@ -329,7 +329,7 @@ static int fa526_init_arch_info(struct target *target,
return ERROR_OK;
}
-static int fa526_target_create(struct target *target, Jim_Interp *interp)
+static int fa526_target_create(struct target *target)
{
struct arm920t_common *arm920t = calloc(1, sizeof(struct arm920t_common));
diff --git a/src/target/feroceon.c b/src/target/feroceon.c
index 840ca1b..cf2c838 100644
--- a/src/target/feroceon.c
+++ b/src/target/feroceon.c
@@ -622,7 +622,7 @@ static void feroceon_common_setup(struct target *target)
arm7_9->wp1_used_default = -1;
}
-static int feroceon_target_create(struct target *target, Jim_Interp *interp)
+static int feroceon_target_create(struct target *target)
{
struct arm926ejs_common *arm926ejs = calloc(1, sizeof(struct arm926ejs_common));
@@ -640,7 +640,7 @@ static int feroceon_target_create(struct target *target, Jim_Interp *interp)
return ERROR_OK;
}
-static int dragonite_target_create(struct target *target, Jim_Interp *interp)
+static int dragonite_target_create(struct target *target)
{
struct arm966e_common *arm966e = calloc(1, sizeof(struct arm966e_common));
diff --git a/src/target/hla_target.c b/src/target/hla_target.c
index ef05df2..983cd87 100644
--- a/src/target/hla_target.c
+++ b/src/target/hla_target.c
@@ -187,8 +187,7 @@ static int adapter_init_target(struct command_context *cmd_ctx,
return ERROR_OK;
}
-static int adapter_target_create(struct target *target,
- Jim_Interp *interp)
+static int adapter_target_create(struct target *target)
{
LOG_DEBUG("%s", __func__);
struct adiv5_private_config *pc = target->private_config;
diff --git a/src/target/ls1_sap.c b/src/target/ls1_sap.c
index 692f4cc..49335a8 100644
--- a/src/target/ls1_sap.c
+++ b/src/target/ls1_sap.c
@@ -17,7 +17,7 @@ struct ls1_sap {
struct jtag_tap *tap;
};
-static int ls1_sap_target_create(struct target *target, Jim_Interp *interp)
+static int ls1_sap_target_create(struct target *target)
{
struct ls1_sap *ls1_sap = calloc(1, sizeof(struct ls1_sap));
diff --git a/src/target/mem_ap.c b/src/target/mem_ap.c
index fdc52c3..c5618c9 100644
--- a/src/target/mem_ap.c
+++ b/src/target/mem_ap.c
@@ -24,7 +24,7 @@ struct mem_ap {
uint64_t ap_num;
};
-static int mem_ap_target_create(struct target *target, Jim_Interp *interp)
+static int mem_ap_target_create(struct target *target)
{
struct mem_ap *mem_ap;
struct adiv5_private_config *pc;
diff --git a/src/target/mips_m4k.c b/src/target/mips_m4k.c
index dc74501..4e27914 100644
--- a/src/target/mips_m4k.c
+++ b/src/target/mips_m4k.c
@@ -1158,7 +1158,7 @@ static int mips_m4k_init_arch_info(struct target *target,
return ERROR_OK;
}
-static int mips_m4k_target_create(struct target *target, Jim_Interp *interp)
+static int mips_m4k_target_create(struct target *target)
{
struct mips_m4k_common *mips_m4k = calloc(1, sizeof(struct mips_m4k_common));
diff --git a/src/target/mips_mips64.c b/src/target/mips_mips64.c
index 85e3779..a181a15 100644
--- a/src/target/mips_mips64.c
+++ b/src/target/mips_mips64.c
@@ -1082,7 +1082,7 @@ static int mips_mips64_init_target(struct command_context *cmd_ctx,
return mips64_build_reg_cache(target);
}
-static int mips_mips64_target_create(struct target *target, Jim_Interp *interp)
+static int mips_mips64_target_create(struct target *target)
{
struct mips_mips64_common *mips_mips64;
struct mips64_common *mips64;
diff --git a/src/target/openrisc/or1k.c b/src/target/openrisc/or1k.c
index 4b9d3bc..4aa2bd7 100644
--- a/src/target/openrisc/or1k.c
+++ b/src/target/openrisc/or1k.c
@@ -1097,7 +1097,7 @@ static int or1k_init_target(struct command_context *cmd_ctx,
return ERROR_OK;
}
-static int or1k_target_create(struct target *target, Jim_Interp *interp)
+static int or1k_target_create(struct target *target)
{
if (!target->tap)
return ERROR_FAIL;
diff --git a/src/target/quark_d20xx.c b/src/target/quark_d20xx.c
index 90cf667..931f0da 100644
--- a/src/target/quark_d20xx.c
+++ b/src/target/quark_d20xx.c
@@ -32,7 +32,7 @@
#include "lakemont.h"
#include "x86_32_common.h"
-static int quark_d20xx_target_create(struct target *t, Jim_Interp *interp)
+static int quark_d20xx_target_create(struct target *t)
{
struct x86_32_common *x86_32 = calloc(1, sizeof(struct x86_32_common));
if (!x86_32) {
diff --git a/src/target/quark_x10xx.c b/src/target/quark_x10xx.c
index 0daa642..2abc32a 100644
--- a/src/target/quark_x10xx.c
+++ b/src/target/quark_x10xx.c
@@ -40,7 +40,7 @@
#include "lakemont.h"
#include "x86_32_common.h"
-static int quark_x10xx_target_create(struct target *t, Jim_Interp *interp)
+static int quark_x10xx_target_create(struct target *t)
{
struct x86_32_common *x86_32 = calloc(1, sizeof(*x86_32));
diff --git a/src/target/riscv/riscv.c b/src/target/riscv/riscv.c
index 2e475a5..ce0af2a 100644
--- a/src/target/riscv/riscv.c
+++ b/src/target/riscv/riscv.c
@@ -489,7 +489,7 @@ static struct riscv_private_config *alloc_default_riscv_private_config(void)
return config;
}
-static int riscv_create_target(struct target *target, Jim_Interp *interp)
+static int riscv_create_target(struct target *target)
{
LOG_TARGET_DEBUG(target, "riscv_create_target()");
struct riscv_private_config *config = target->private_config;
diff --git a/src/target/stm8.c b/src/target/stm8.c
index 76482e8..81c41f2 100644
--- a/src/target/stm8.c
+++ b/src/target/stm8.c
@@ -13,14 +13,12 @@
#include <helper/log.h>
#include "target.h"
#include "target_type.h"
-#include "hello.h"
#include "jtag/interface.h"
#include "jtag/jtag.h"
#include "jtag/swim.h"
#include "register.h"
#include "breakpoints.h"
#include "algorithm.h"
-#include "stm8.h"
static struct reg_cache *stm8_build_reg_cache(struct target *target);
static int stm8_read_core_reg(struct target *target, unsigned int num);
@@ -54,6 +52,8 @@ static const struct {
{ 5, "cc", 8, REG_TYPE_UINT8, "general", "org.gnu.gdb.stm8.core", 0 },
};
+#define STM8_COMMON_MAGIC 0x53544D38U
+
#define STM8_NUM_REGS ARRAY_SIZE(stm8_regs)
#define STM8_PC 0
#define STM8_A 1
@@ -168,6 +168,51 @@ struct stm8_comparator {
enum hw_break_type type;
};
+struct stm8_common {
+ unsigned int common_magic;
+
+ void *arch_info;
+ struct reg_cache *core_cache;
+ uint32_t core_regs[STM8_NUM_REGS];
+
+ /* working area for fastdata access */
+ struct working_area *fast_data_area;
+
+ bool swim_configured;
+ bool bp_scanned;
+ uint8_t num_hw_bpoints;
+ uint8_t num_hw_bpoints_avail;
+ struct stm8_comparator *hw_break_list;
+ uint32_t blocksize;
+ uint32_t flashstart;
+ uint32_t flashend;
+ uint32_t eepromstart;
+ uint32_t eepromend;
+ uint32_t optionstart;
+ uint32_t optionend;
+ bool enable_step_irq;
+
+ bool enable_stm8l;
+ uint32_t flash_cr2;
+ uint32_t flash_ncr2;
+ uint32_t flash_iapsr;
+ uint32_t flash_dukr;
+ uint32_t flash_pukr;
+
+ /* cc value used for interrupt flags restore */
+ uint32_t cc;
+ bool cc_valid;
+
+ /* register cache to processor synchronization */
+ int (*read_core_reg)(struct target *target, unsigned int num);
+ int (*write_core_reg)(struct target *target, unsigned int num);
+};
+
+static struct stm8_common *target_to_stm8(struct target *target)
+{
+ return target->arch_info;
+}
+
static int stm8_adapter_read_memory(struct target *target,
uint32_t addr, int size, int count, void *buf)
{
@@ -1106,8 +1151,7 @@ static int stm8_init_arch_info(struct target *target,
return ERROR_OK;
}
-static int stm8_target_create(struct target *target,
- Jim_Interp *interp)
+static int stm8_target_create(struct target *target)
{
struct stm8_common *stm8 = calloc(1, sizeof(struct stm8_common));
diff --git a/src/target/stm8.h b/src/target/stm8.h
deleted file mode 100644
index 55e1071..0000000
--- a/src/target/stm8.h
+++ /dev/null
@@ -1,63 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-or-later */
-
-/*
-* OpenOCD STM8 target driver
-* Copyright (C) 2017 Ake Rehnman
-* ake.rehnman(at)gmail.com
-*/
-
-#ifndef OPENOCD_TARGET_STM8_H
-#define OPENOCD_TARGET_STM8_H
-
-struct target;
-
-#define STM8_COMMON_MAGIC 0x53544D38U
-#define STM8_NUM_CORE_REGS 6
-
-struct stm8_common {
- unsigned int common_magic;
-
- void *arch_info;
- struct reg_cache *core_cache;
- uint32_t core_regs[STM8_NUM_CORE_REGS];
-
- /* working area for fastdata access */
- struct working_area *fast_data_area;
-
- bool swim_configured;
- bool bp_scanned;
- uint8_t num_hw_bpoints;
- uint8_t num_hw_bpoints_avail;
- struct stm8_comparator *hw_break_list;
- uint32_t blocksize;
- uint32_t flashstart;
- uint32_t flashend;
- uint32_t eepromstart;
- uint32_t eepromend;
- uint32_t optionstart;
- uint32_t optionend;
- bool enable_step_irq;
-
- bool enable_stm8l;
- uint32_t flash_cr2;
- uint32_t flash_ncr2;
- uint32_t flash_iapsr;
- uint32_t flash_dukr;
- uint32_t flash_pukr;
-
- /* cc value used for interrupt flags restore */
- uint32_t cc;
- bool cc_valid;
-
- /* register cache to processor synchronization */
- int (*read_core_reg)(struct target *target, unsigned int num);
- int (*write_core_reg)(struct target *target, unsigned int num);
-};
-
-static inline struct stm8_common *
-target_to_stm8(struct target *target)
-{
- return target->arch_info;
-}
-
-#endif /* OPENOCD_TARGET_STM8_H */
diff --git a/src/target/target.c b/src/target/target.c
index 442e8be..1125252 100644
--- a/src/target/target.c
+++ b/src/target/target.c
@@ -162,7 +162,7 @@ static const char *target_strerror_safe(int err)
return n->name;
}
-static const struct jim_nvp nvp_target_event[] = {
+static const struct nvp nvp_target_event[] = {
{ .value = TARGET_EVENT_GDB_HALT, .name = "gdb-halt" },
{ .value = TARGET_EVENT_HALTED, .name = "halted" },
@@ -237,7 +237,7 @@ static const struct nvp nvp_target_debug_reason[] = {
{ .name = NULL, .value = -1 },
};
-static const struct jim_nvp nvp_target_endian[] = {
+static const struct nvp nvp_target_endian[] = {
{ .name = "big", .value = TARGET_BIG_ENDIAN },
{ .name = "little", .value = TARGET_LITTLE_ENDIAN },
{ .name = "be", .value = TARGET_BIG_ENDIAN },
@@ -284,7 +284,7 @@ const char *target_state_name(const struct target *t)
const char *target_event_name(enum target_event event)
{
const char *cp;
- cp = jim_nvp_value2name_simple(nvp_target_event, event)->name;
+ cp = nvp_value2name(nvp_target_event, event)->name;
if (!cp) {
LOG_ERROR("Invalid target event: %d", (int)(event));
cp = "(*BUG*unknown*BUG*)";
@@ -2848,8 +2848,7 @@ COMMAND_HANDLER(handle_targets_command)
marker,
target_name(target),
target_type_name(target),
- jim_nvp_value2name_simple(nvp_target_endian,
- target->endianness)->name,
+ nvp_value2name(nvp_target_endian, target->endianness)->name,
target->tap->dotted_name,
state);
}
@@ -4841,7 +4840,7 @@ enum target_cfg_param {
TCFG_GDB_MAX_CONNECTIONS,
};
-static struct jim_nvp nvp_config_opts[] = {
+static struct nvp nvp_config_opts[] = {
{ .name = "-type", .value = TCFG_TYPE },
{ .name = "-event", .value = TCFG_EVENT },
{ .name = "-work-area-virt", .value = TCFG_WORK_AREA_VIRT },
@@ -4859,78 +4858,71 @@ static struct jim_nvp nvp_config_opts[] = {
{ .name = NULL, .value = -1 }
};
-static int target_configure(struct jim_getopt_info *goi, struct target *target)
+static COMMAND_HELPER(target_configure, struct target *target, unsigned int index, bool is_configure)
{
- struct jim_nvp *n;
- Jim_Obj *o;
- jim_wide w;
- int e;
+ const struct nvp *n;
+ int retval;
/* parse config or cget options ... */
- while (goi->argc > 0) {
- Jim_SetEmptyResult(goi->interp);
- /* jim_getopt_debug(goi); */
-
+ while (index < CMD_ARGC) {
if (target->type->target_jim_configure) {
/* target defines a configure function */
/* target gets first dibs on parameters */
- e = (*(target->type->target_jim_configure))(target, goi);
+ struct jim_getopt_info goi;
+ jim_getopt_setup(&goi, CMD_CTX->interp, CMD_ARGC - index, CMD_JIMTCL_ARGV + index);
+ goi.is_configure = is_configure;
+ int e = (*target->type->target_jim_configure)(target, &goi);
+ index = CMD_ARGC - goi.argc;
if (e == JIM_OK) {
/* more? */
continue;
}
if (e == JIM_ERR) {
/* An error */
- return e;
+ int reslen;
+ const char *result = Jim_GetString(Jim_GetResult(CMD_CTX->interp), &reslen);
+ if (reslen > 0)
+ command_print(CMD, "%s", result);
+ return ERROR_FAIL;
}
/* otherwise we 'continue' below */
}
- e = jim_getopt_nvp(goi, nvp_config_opts, &n);
- if (e != JIM_OK) {
- jim_getopt_nvp_unknown(goi, nvp_config_opts, 0);
- return e;
+ n = nvp_name2value(nvp_config_opts, CMD_ARGV[index]);
+ if (!n->name) {
+ nvp_unknown_command_print(CMD, nvp_config_opts, NULL, CMD_ARGV[index]);
+ return ERROR_COMMAND_ARGUMENT_INVALID;
}
+ index++;
switch (n->value) {
case TCFG_TYPE:
/* not settable */
- if (goi->is_configure) {
- Jim_SetResultFormatted(goi->interp,
- "not settable: %s", n->name);
- return JIM_ERR;
- } else {
-no_params:
- if (goi->argc != 0) {
- Jim_WrongNumArgs(goi->interp,
- goi->argc, goi->argv,
- "NO PARAMS");
- return JIM_ERR;
- }
+ if (is_configure) {
+ command_print(CMD, "not settable: %s", n->name);
+ return ERROR_COMMAND_ARGUMENT_INVALID;
}
- Jim_SetResultString(goi->interp,
- target_type_name(target), -1);
+ if (index != CMD_ARGC)
+ return ERROR_COMMAND_SYNTAX_ERROR;
+ command_print(CMD, "%s", target_type_name(target));
/* loop for more */
break;
+
case TCFG_EVENT:
- if (goi->argc == 0) {
- Jim_WrongNumArgs(goi->interp, goi->argc, goi->argv, "-event ?event-name? ...");
- return JIM_ERR;
+ if (index == CMD_ARGC) {
+ command_print(CMD, "missing event-name");
+ return ERROR_COMMAND_ARGUMENT_INVALID;
}
- e = jim_getopt_nvp(goi, nvp_target_event, &n);
- if (e != JIM_OK) {
- jim_getopt_nvp_unknown(goi, nvp_target_event, 1);
- return e;
+ n = nvp_name2value(nvp_target_event, CMD_ARGV[index]);
+ if (!n->name) {
+ nvp_unknown_command_print(CMD, nvp_target_event, CMD_ARGV[index - 1], CMD_ARGV[index]);
+ return ERROR_COMMAND_ARGUMENT_INVALID;
}
+ index++;
- if (goi->is_configure) {
- if (goi->argc != 1) {
- Jim_WrongNumArgs(goi->interp, goi->argc, goi->argv, "-event ?event-name? ?EVENT-BODY?");
- return JIM_ERR;
- }
- } else {
- if (goi->argc != 0) {
- Jim_WrongNumArgs(goi->interp, goi->argc, goi->argv, "-event ?event-name?");
- return JIM_ERR;
+ if (is_configure) {
+ if (index == CMD_ARGC) {
+ command_print(CMD, "missing event-body");
+ return ERROR_COMMAND_ARGUMENT_INVALID;
}
}
@@ -4946,20 +4938,20 @@ no_params:
if (&teap->list == &target->events_action)
teap = NULL;
- if (goi->is_configure) {
+ if (is_configure) {
/* START_DEPRECATED_TPIU */
if (n->value == TARGET_EVENT_TRACE_CONFIG)
LOG_INFO("DEPRECATED target event %s; use TPIU events {pre,post}-{enable,disable}", n->name);
/* END_DEPRECATED_TPIU */
- jim_getopt_obj(goi, &o);
- if (Jim_Length(o) == 0) {
+ if (strlen(CMD_ARGV[index]) == 0) {
/* empty action, drop existing one */
if (teap) {
list_del(&teap->list);
Jim_DecrRefCount(teap->interp, teap->body);
free(teap);
}
+ index++;
break;
}
@@ -4970,10 +4962,12 @@ no_params:
replace = false;
}
teap->event = n->value;
- teap->interp = goi->interp;
+ teap->interp = CMD_CTX->interp;
if (teap->body)
Jim_DecrRefCount(teap->interp, teap->body);
- teap->body = Jim_DuplicateObj(goi->interp, o);
+ /* use jim object to keep its reference on tcl file and line */
+ /* TODO: need duplicate? isn't IncrRefCount enough? */
+ teap->body = Jim_DuplicateObj(teap->interp, CMD_JIMTCL_ARGV[index++]);
/*
* FIXME:
* Tcl/TK - "tk events" have a nice feature.
@@ -4990,238 +4984,278 @@ no_params:
/* add to head of event list */
list_add(&teap->list, &target->events_action);
}
- Jim_SetEmptyResult(goi->interp);
} else {
- /* get */
- if (!teap)
- Jim_SetEmptyResult(goi->interp);
- else
- Jim_SetResult(goi->interp, Jim_DuplicateObj(goi->interp, teap->body));
+ /* cget */
+ if (index != CMD_ARGC)
+ return ERROR_COMMAND_SYNTAX_ERROR;
+
+ if (teap)
+ command_print(CMD, "%s", Jim_GetString(teap->body, NULL));
}
}
/* loop for more */
break;
case TCFG_WORK_AREA_VIRT:
- if (goi->is_configure) {
- target_free_all_working_areas(target);
- e = jim_getopt_wide(goi, &w);
- if (e != JIM_OK)
- return e;
- target->working_area_virt = w;
+ if (is_configure) {
+ if (index == CMD_ARGC) {
+ command_print(CMD, "missing argument to %s", CMD_ARGV[index - 1]);
+ return ERROR_COMMAND_ARGUMENT_INVALID;
+ }
+ COMMAND_PARSE_NUMBER(u64, CMD_ARGV[index], target->working_area_virt);
+ index++;
target->working_area_virt_spec = true;
+ target_free_all_working_areas(target);
} else {
- if (goi->argc != 0)
- goto no_params;
+ if (index != CMD_ARGC)
+ return ERROR_COMMAND_SYNTAX_ERROR;
+ command_print(CMD, TARGET_ADDR_FMT, target->working_area_virt);
}
- Jim_SetResult(goi->interp, Jim_NewIntObj(goi->interp, target->working_area_virt));
/* loop for more */
break;
case TCFG_WORK_AREA_PHYS:
- if (goi->is_configure) {
- target_free_all_working_areas(target);
- e = jim_getopt_wide(goi, &w);
- if (e != JIM_OK)
- return e;
- target->working_area_phys = w;
+ if (is_configure) {
+ if (index == CMD_ARGC) {
+ command_print(CMD, "missing argument to %s", CMD_ARGV[index - 1]);
+ return ERROR_COMMAND_ARGUMENT_INVALID;
+ }
+ COMMAND_PARSE_NUMBER(u64, CMD_ARGV[index], target->working_area_phys);
+ index++;
target->working_area_phys_spec = true;
+ target_free_all_working_areas(target);
} else {
- if (goi->argc != 0)
- goto no_params;
+ if (index != CMD_ARGC)
+ return ERROR_COMMAND_SYNTAX_ERROR;
+ command_print(CMD, TARGET_ADDR_FMT, target->working_area_phys);
}
- Jim_SetResult(goi->interp, Jim_NewIntObj(goi->interp, target->working_area_phys));
/* loop for more */
break;
case TCFG_WORK_AREA_SIZE:
- if (goi->is_configure) {
+ if (is_configure) {
+ if (index == CMD_ARGC) {
+ command_print(CMD, "missing argument to %s", CMD_ARGV[index - 1]);
+ return ERROR_COMMAND_ARGUMENT_INVALID;
+ }
+ COMMAND_PARSE_NUMBER(u32, CMD_ARGV[index], target->working_area_size);
+ index++;
target_free_all_working_areas(target);
- e = jim_getopt_wide(goi, &w);
- if (e != JIM_OK)
- return e;
- target->working_area_size = w;
} else {
- if (goi->argc != 0)
- goto no_params;
+ if (index != CMD_ARGC)
+ return ERROR_COMMAND_SYNTAX_ERROR;
+ command_print(CMD, "0x%08" PRIx32, target->working_area_size);
}
- Jim_SetResult(goi->interp, Jim_NewIntObj(goi->interp, target->working_area_size));
/* loop for more */
break;
case TCFG_WORK_AREA_BACKUP:
- if (goi->is_configure) {
+ if (is_configure) {
+ if (index == CMD_ARGC) {
+ command_print(CMD, "missing argument to %s", CMD_ARGV[index - 1]);
+ return ERROR_COMMAND_ARGUMENT_INVALID;
+ }
+ retval = command_parse_bool_arg(CMD_ARGV[index], &target->backup_working_area);
+ if (retval != ERROR_OK)
+ return retval;
+ index++;
target_free_all_working_areas(target);
- e = jim_getopt_wide(goi, &w);
- if (e != JIM_OK)
- return e;
- /* make this boolean */
- target->backup_working_area = (w != 0);
} else {
- if (goi->argc != 0)
- goto no_params;
+ if (index != CMD_ARGC)
+ return ERROR_COMMAND_SYNTAX_ERROR;
+ command_print(CMD, target->backup_working_area ? "1" : "0");
}
- Jim_SetResult(goi->interp, Jim_NewIntObj(goi->interp, target->backup_working_area ? 1 : 0));
- /* loop for more e*/
+ /* loop for more */
break;
-
case TCFG_ENDIAN:
- if (goi->is_configure) {
- e = jim_getopt_nvp(goi, nvp_target_endian, &n);
- if (e != JIM_OK) {
- jim_getopt_nvp_unknown(goi, nvp_target_endian, 1);
- return e;
+ if (is_configure) {
+ if (index == CMD_ARGC) {
+ command_print(CMD, "missing argument to %s", CMD_ARGV[index - 1]);
+ return ERROR_COMMAND_ARGUMENT_INVALID;
+ }
+ n = nvp_name2value(nvp_target_endian, CMD_ARGV[index]);
+ if (!n->name) {
+ nvp_unknown_command_print(CMD, nvp_target_endian, CMD_ARGV[index - 1], CMD_ARGV[index]);
+ return ERROR_COMMAND_ARGUMENT_INVALID;
}
+ index++;
target->endianness = n->value;
} else {
- if (goi->argc != 0)
- goto no_params;
- }
- n = jim_nvp_value2name_simple(nvp_target_endian, target->endianness);
- if (!n->name) {
- target->endianness = TARGET_LITTLE_ENDIAN;
- n = jim_nvp_value2name_simple(nvp_target_endian, target->endianness);
+ if (index != CMD_ARGC)
+ return ERROR_COMMAND_SYNTAX_ERROR;
+ n = nvp_value2name(nvp_target_endian, target->endianness);
+ if (!n->name) {
+ target->endianness = TARGET_LITTLE_ENDIAN;
+ n = nvp_value2name(nvp_target_endian, target->endianness);
+ }
+ command_print(CMD, "%s", n->name);
}
- Jim_SetResultString(goi->interp, n->name, -1);
/* loop for more */
break;
case TCFG_COREID:
- if (goi->is_configure) {
- e = jim_getopt_wide(goi, &w);
- if (e != JIM_OK)
- return e;
- target->coreid = (int32_t)w;
+ if (is_configure) {
+ if (index == CMD_ARGC) {
+ command_print(CMD, "missing argument to %s", CMD_ARGV[index - 1]);
+ return ERROR_COMMAND_ARGUMENT_INVALID;
+ }
+ COMMAND_PARSE_NUMBER(s32, CMD_ARGV[index], target->coreid);
+ index++;
} else {
- if (goi->argc != 0)
- goto no_params;
+ if (index != CMD_ARGC)
+ return ERROR_COMMAND_SYNTAX_ERROR;
+ command_print(CMD, "%" PRIi32, target->coreid);
}
- Jim_SetResult(goi->interp, Jim_NewIntObj(goi->interp, target->coreid));
/* loop for more */
break;
case TCFG_CHAIN_POSITION:
- if (goi->is_configure) {
- Jim_Obj *o_t;
- struct jtag_tap *tap;
-
+ if (is_configure) {
if (target->has_dap) {
- Jim_SetResultString(goi->interp,
- "target requires -dap parameter instead of -chain-position!", -1);
- return JIM_ERR;
+ command_print(CMD, "target requires -dap parameter instead of -chain-position!");
+ return ERROR_COMMAND_ARGUMENT_INVALID;
}
- target_free_all_working_areas(target);
- e = jim_getopt_obj(goi, &o_t);
- if (e != JIM_OK)
- return e;
- tap = jtag_tap_by_jim_obj(goi->interp, o_t);
- if (!tap)
- return JIM_ERR;
+ if (index == CMD_ARGC) {
+ command_print(CMD, "missing argument to %s", CMD_ARGV[index - 1]);
+ return ERROR_COMMAND_ARGUMENT_INVALID;
+ }
+ struct jtag_tap *tap = jtag_tap_by_string(CMD_ARGV[index]);
+ if (!tap) {
+ command_print(CMD, "Tap '%s' could not be found", CMD_ARGV[index]);
+ return ERROR_COMMAND_ARGUMENT_INVALID;
+ }
+ index++;
target->tap = tap;
target->tap_configured = true;
} else {
- if (goi->argc != 0)
- goto no_params;
+ if (index != CMD_ARGC)
+ return ERROR_COMMAND_SYNTAX_ERROR;
+ command_print(CMD, "%s", target->tap->dotted_name);
}
- Jim_SetResultString(goi->interp, target->tap->dotted_name, -1);
- /* loop for more e*/
+ /* loop for more */
break;
+
case TCFG_DBGBASE:
- if (goi->is_configure) {
- e = jim_getopt_wide(goi, &w);
- if (e != JIM_OK)
- return e;
- target->dbgbase = (uint32_t)w;
+ if (is_configure) {
+ if (index == CMD_ARGC) {
+ command_print(CMD, "missing argument to %s", CMD_ARGV[index - 1]);
+ return ERROR_COMMAND_ARGUMENT_INVALID;
+ }
+ COMMAND_PARSE_NUMBER(u32, CMD_ARGV[index], target->dbgbase);
+ index++;
target->dbgbase_set = true;
} else {
- if (goi->argc != 0)
- goto no_params;
+ if (index != CMD_ARGC)
+ return ERROR_COMMAND_SYNTAX_ERROR;
+ command_print(CMD, "0x%08" PRIx32, target->dbgbase);
}
- Jim_SetResult(goi->interp, Jim_NewIntObj(goi->interp, target->dbgbase));
/* loop for more */
break;
+
case TCFG_RTOS:
- /* RTOS */
- {
- int result = rtos_create(goi, target);
- if (result != JIM_OK)
- return result;
+ if (is_configure) {
+ if (index == CMD_ARGC) {
+ command_print(CMD, "missing argument to %s", CMD_ARGV[index - 1]);
+ return ERROR_COMMAND_ARGUMENT_INVALID;
+ }
+ struct jim_getopt_info goi;
+ jim_getopt_setup(&goi, CMD_CTX->interp, CMD_ARGC - index, CMD_JIMTCL_ARGV + index);
+ index++;
+ goi.is_configure = true;
+ int resval = rtos_create(&goi, target);
+ int reslen;
+ const char *result = Jim_GetString(Jim_GetResult(CMD_CTX->interp), &reslen);
+ if (reslen > 0)
+ command_print(CMD, "%s", result);
+ if (resval != JIM_OK)
+ return ERROR_FAIL;
+ } else {
+ if (index != CMD_ARGC)
+ return ERROR_COMMAND_SYNTAX_ERROR;
+ if (target->rtos)
+ command_print(CMD, "%s", target->rtos->type->name);
}
/* loop for more */
break;
case TCFG_DEFER_EXAMINE:
- /* DEFER_EXAMINE */
- target->defer_examine = true;
+ if (is_configure)
+ target->defer_examine = true;
+ else
+ command_print(CMD, "%s", target->defer_examine ? "true" : "false");
/* loop for more */
break;
case TCFG_GDB_PORT:
- if (goi->is_configure) {
- struct command_context *cmd_ctx = current_command_context(goi->interp);
- if (cmd_ctx->mode != COMMAND_CONFIG) {
- Jim_SetResultString(goi->interp, "-gdb-port must be configured before 'init'", -1);
- return JIM_ERR;
+ if (is_configure) {
+ if (index == CMD_ARGC) {
+ command_print(CMD, "missing argument to %s", CMD_ARGV[index - 1]);
+ return ERROR_COMMAND_ARGUMENT_INVALID;
}
- const char *s;
- e = jim_getopt_string(goi, &s, NULL);
- if (e != JIM_OK)
- return e;
+ /* TODO: generalize test of COMMAND_CONFIG */
+ if (CMD_CTX->mode != COMMAND_CONFIG) {
+ command_print(CMD, "-gdb-port must be configured before 'init'");
+ return ERROR_COMMAND_ARGUMENT_INVALID;
+ }
+
+ char *s = strdup(CMD_ARGV[index]);
+ if (!s) {
+ LOG_ERROR("Out of memory");
+ return ERROR_FAIL;
+ }
free(target->gdb_port_override);
- target->gdb_port_override = strdup(s);
+ target->gdb_port_override = s;
+ index++;
} else {
- if (goi->argc != 0)
- goto no_params;
+ if (index != CMD_ARGC)
+ return ERROR_COMMAND_SYNTAX_ERROR;
+ command_print(CMD, "%s", target->gdb_port_override ? target->gdb_port_override : "undefined");
}
- Jim_SetResultString(goi->interp, target->gdb_port_override ? target->gdb_port_override : "undefined", -1);
/* loop for more */
break;
case TCFG_GDB_MAX_CONNECTIONS:
- if (goi->is_configure) {
- struct command_context *cmd_ctx = current_command_context(goi->interp);
- if (cmd_ctx->mode != COMMAND_CONFIG) {
- Jim_SetResultString(goi->interp, "-gdb-max-connections must be configured before 'init'", -1);
- return JIM_ERR;
+ if (is_configure) {
+ if (index == CMD_ARGC) {
+ command_print(CMD, "missing argument to %s", CMD_ARGV[index - 1]);
+ return ERROR_COMMAND_ARGUMENT_INVALID;
}
- e = jim_getopt_wide(goi, &w);
- if (e != JIM_OK)
- return e;
- target->gdb_max_connections = (w < 0) ? CONNECTION_LIMIT_UNLIMITED : (int)w;
+ if (CMD_CTX->mode != COMMAND_CONFIG) {
+ command_print(CMD, "-gdb-max-connections must be configured before 'init'");
+ return ERROR_COMMAND_ARGUMENT_INVALID;
+ }
+
+ COMMAND_PARSE_NUMBER(int, CMD_ARGV[index], target->gdb_max_connections);
+ index++;
+ if (target->gdb_max_connections < 0)
+ target->gdb_max_connections = CONNECTION_LIMIT_UNLIMITED;
} else {
- if (goi->argc != 0)
- goto no_params;
+ if (index != CMD_ARGC)
+ return ERROR_COMMAND_SYNTAX_ERROR;
+ command_print(CMD, "%d", target->gdb_max_connections);
}
- Jim_SetResult(goi->interp, Jim_NewIntObj(goi->interp, target->gdb_max_connections));
+ /* loop for more */
break;
}
- } /* while (goi->argc) */
-
+ }
- /* done - we return */
- return JIM_OK;
+ return ERROR_OK;
}
-static int jim_target_configure(Jim_Interp *interp, int argc, Jim_Obj * const *argv)
+COMMAND_HANDLER(handle_target_configure)
{
- struct command *c = jim_to_command(interp);
- struct jim_getopt_info goi;
+ if (!CMD_ARGC)
+ return ERROR_COMMAND_SYNTAX_ERROR;
- jim_getopt_setup(&goi, interp, argc - 1, argv + 1);
- goi.is_configure = !strcmp(c->name, "configure");
- if (goi.argc < 1) {
- Jim_WrongNumArgs(goi.interp, goi.argc, goi.argv,
- "missing: -option ...");
- return JIM_ERR;
- }
- 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);
+ bool is_configure = !strcmp(CMD_NAME, "configure");
+
+ struct target *target = get_current_target(CMD_CTX);
+
+ return CALL_COMMAND_HANDLER(target_configure, target, 0, is_configure);
}
COMMAND_HANDLER(handle_target_examine)
@@ -5454,40 +5488,34 @@ COMMAND_HANDLER(handle_target_debug_reason)
return ERROR_OK;
}
-static int jim_target_invoke_event(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+COMMAND_HANDLER(handle_target_invoke_event)
{
- struct jim_getopt_info goi;
- jim_getopt_setup(&goi, interp, argc - 1, argv + 1);
- if (goi.argc != 1) {
- const char *cmd_name = Jim_GetString(argv[0], NULL);
- Jim_SetResultFormatted(goi.interp, "%s <eventname>", cmd_name);
- return JIM_ERR;
- }
- struct jim_nvp *n;
- int e = jim_getopt_nvp(&goi, nvp_target_event, &n);
- if (e != JIM_OK) {
- jim_getopt_nvp_unknown(&goi, nvp_target_event, 1);
- return e;
+ if (CMD_ARGC != 1)
+ return ERROR_COMMAND_SYNTAX_ERROR;
+
+ const struct nvp *n = nvp_name2value(nvp_target_event, CMD_ARGV[0]);
+ if (!n->name) {
+ nvp_unknown_command_print(CMD, nvp_target_event, NULL, CMD_ARGV[0]);
+ return ERROR_COMMAND_ARGUMENT_INVALID;
}
- struct command_context *cmd_ctx = current_command_context(interp);
- assert(cmd_ctx);
- struct target *target = get_current_target(cmd_ctx);
+
+ struct target *target = get_current_target(CMD_CTX);
target_handle_event(target, n->value);
- return JIM_OK;
+ return ERROR_OK;
}
static const struct command_registration target_instance_command_handlers[] = {
{
.name = "configure",
.mode = COMMAND_ANY,
- .jim_handler = jim_target_configure,
+ .handler = handle_target_configure,
.help = "configure a new target for use",
.usage = "[target_attribute ...]",
},
{
.name = "cget",
.mode = COMMAND_ANY,
- .jim_handler = jim_target_configure,
+ .handler = handle_target_configure,
.help = "returns the specified target attribute",
.usage = "target_attribute",
},
@@ -5655,51 +5683,36 @@ static const struct command_registration target_instance_command_handlers[] = {
{
.name = "invoke-event",
.mode = COMMAND_EXEC,
- .jim_handler = jim_target_invoke_event,
+ .handler = handle_target_invoke_event,
.help = "invoke handler for specified event",
.usage = "event_name",
},
COMMAND_REGISTRATION_DONE
};
-static int target_create(struct jim_getopt_info *goi)
+COMMAND_HANDLER(handle_target_create)
{
- Jim_Obj *new_cmd;
- Jim_Cmd *cmd;
- const char *cp;
- int e;
+ int retval = ERROR_OK;
int x;
- struct target *target;
- struct command_context *cmd_ctx;
-
- cmd_ctx = current_command_context(goi->interp);
- assert(cmd_ctx);
- if (goi->argc < 3) {
- Jim_WrongNumArgs(goi->interp, 1, goi->argv, "?name? ?type? ..options...");
- return JIM_ERR;
- }
+ if (CMD_ARGC < 4)
+ return ERROR_COMMAND_SYNTAX_ERROR;
- /* COMMAND */
- jim_getopt_obj(goi, &new_cmd);
- /* does this command exist? */
- cmd = Jim_GetCommand(goi->interp, new_cmd, JIM_NONE);
- if (cmd) {
- cp = Jim_GetString(new_cmd, NULL);
- Jim_SetResultFormatted(goi->interp, "Command/target: %s Exists", cp);
- return JIM_ERR;
+ /* check if the target name clashes with an existing command name */
+ Jim_Cmd *jimcmd = Jim_GetCommand(CMD_CTX->interp, CMD_JIMTCL_ARGV[0], JIM_NONE);
+ if (jimcmd) {
+ command_print(CMD, "Command/target: %s Exists", CMD_ARGV[0]);
+ return ERROR_FAIL;
}
/* TYPE */
- e = jim_getopt_string(goi, &cp, NULL);
- if (e != JIM_OK)
- return e;
+ const char *cp = CMD_ARGV[1];
struct transport *tr = get_current_transport();
if (tr && tr->override_target) {
- e = tr->override_target(&cp);
- if (e != ERROR_OK) {
- LOG_ERROR("The selected transport doesn't support this target");
- return JIM_ERR;
+ retval = tr->override_target(&cp);
+ if (retval != ERROR_OK) {
+ command_print(CMD, "The selected transport doesn't support this target");
+ return retval;
}
LOG_INFO("The selected transport took over low-level target control. The results might differ compared to plain JTAG/SWD");
}
@@ -5711,28 +5724,29 @@ static int target_create(struct jim_getopt_info *goi)
}
}
if (!target_types[x]) {
- Jim_SetResultFormatted(goi->interp, "Unknown target type %s, try one of ", cp);
+ char *all = NULL;
for (x = 0 ; target_types[x] ; x++) {
- if (target_types[x + 1]) {
- Jim_AppendStrings(goi->interp,
- Jim_GetResult(goi->interp),
- target_types[x]->name,
- ", ", NULL);
- } else {
- Jim_AppendStrings(goi->interp,
- Jim_GetResult(goi->interp),
- " or ",
- target_types[x]->name, NULL);
+ char *prev = all;
+ if (all)
+ all = alloc_printf("%s, %s", all, target_types[x]->name);
+ else
+ all = alloc_printf("%s", target_types[x]->name);
+ free(prev);
+ if (!all) {
+ LOG_ERROR("Out of memory");
+ return ERROR_FAIL;
}
}
- return JIM_ERR;
+ command_print(CMD, "Unknown target type %s, try one of %s", cp, all);
+ free(all);
+ return ERROR_FAIL;
}
/* Create it */
- target = calloc(1, sizeof(struct target));
+ struct target *target = calloc(1, sizeof(struct target));
if (!target) {
LOG_ERROR("Out of memory");
- return JIM_ERR;
+ return ERROR_FAIL;
}
/* set empty smp cluster */
@@ -5743,7 +5757,7 @@ static int target_create(struct jim_getopt_info *goi)
if (!target->type) {
LOG_ERROR("Out of memory");
free(target);
- return JIM_ERR;
+ return ERROR_FAIL;
}
memcpy(target->type, target_types[x], sizeof(struct target_type));
@@ -5776,7 +5790,7 @@ static int target_create(struct jim_getopt_info *goi)
LOG_ERROR("Out of memory");
free(target->type);
free(target);
- return JIM_ERR;
+ return ERROR_FAIL;
}
target->dbgmsg = NULL;
@@ -5790,45 +5804,43 @@ static int target_create(struct jim_getopt_info *goi)
target->gdb_port_override = NULL;
target->gdb_max_connections = 1;
- cp = Jim_GetString(new_cmd, NULL);
- target->cmd_name = strdup(cp);
+ target->cmd_name = strdup(CMD_ARGV[0]);
if (!target->cmd_name) {
LOG_ERROR("Out of memory");
free(target->trace_info);
free(target->type);
free(target);
- return JIM_ERR;
+ return ERROR_FAIL;
}
/* Do the rest as "configure" options */
- goi->is_configure = true;
- e = target_configure(goi, target);
-
- if (e == JIM_OK) {
+ bool is_configure = true;
+ retval = CALL_COMMAND_HANDLER(target_configure, target, 2, is_configure);
+ if (retval == ERROR_OK) {
if (target->has_dap) {
if (!target->dap_configured) {
- Jim_SetResultString(goi->interp, "-dap ?name? required when creating target", -1);
- e = JIM_ERR;
+ command_print(CMD, "-dap ?name? required when creating target");
+ retval = ERROR_COMMAND_ARGUMENT_INVALID;
}
} else {
if (!target->tap_configured) {
- Jim_SetResultString(goi->interp, "-chain-position ?name? required when creating target", -1);
- e = JIM_ERR;
+ command_print(CMD, "-chain-position ?name? required when creating target");
+ retval = ERROR_COMMAND_ARGUMENT_INVALID;
}
}
/* tap must be set after target was configured */
if (!target->tap)
- e = JIM_ERR;
+ retval = ERROR_COMMAND_ARGUMENT_INVALID;
}
- if (e != JIM_OK) {
+ if (retval != ERROR_OK) {
rtos_destroy(target);
free(target->gdb_port_override);
free(target->trace_info);
free(target->type);
free(target->private_config);
free(target);
- return e;
+ return retval;
}
if (target->endianness == TARGET_ENDIAN_UNKNOWN) {
@@ -5837,8 +5849,8 @@ static int target_create(struct jim_getopt_info *goi)
}
if (target->type->target_create) {
- e = (*(target->type->target_create))(target, goi->interp);
- if (e != ERROR_OK) {
+ retval = (*target->type->target_create)(target);
+ if (retval != ERROR_OK) {
LOG_DEBUG("target_create failed");
free(target->cmd_name);
rtos_destroy(target);
@@ -5847,15 +5859,15 @@ static int target_create(struct jim_getopt_info *goi)
free(target->type);
free(target->private_config);
free(target);
- return JIM_ERR;
+ return retval;
}
}
/* create the target specific commands */
if (target->type->commands) {
- e = register_commands(cmd_ctx, NULL, target->type->commands);
- if (e != ERROR_OK)
- LOG_ERROR("unable to register '%s' commands", cp);
+ retval = register_commands(CMD_CTX, NULL, target->type->commands);
+ if (retval != ERROR_OK)
+ LOG_ERROR("unable to register '%s' commands", CMD_ARGV[0]);
}
/* now - create the new target name command */
@@ -5870,7 +5882,7 @@ static int target_create(struct jim_getopt_info *goi)
};
const struct command_registration target_commands[] = {
{
- .name = cp,
+ .name = CMD_ARGV[0],
.mode = COMMAND_ANY,
.help = "target command group",
.usage = "",
@@ -5878,8 +5890,8 @@ static int target_create(struct jim_getopt_info *goi)
},
COMMAND_REGISTRATION_DONE
};
- e = register_commands_override_target(cmd_ctx, NULL, target_commands, target);
- if (e != ERROR_OK) {
+ retval = register_commands_override_target(CMD_CTX, NULL, target_commands, target);
+ if (retval != ERROR_OK) {
if (target->type->deinit_target)
target->type->deinit_target(target);
free(target->cmd_name);
@@ -5888,14 +5900,14 @@ static int target_create(struct jim_getopt_info *goi)
free(target->trace_info);
free(target->type);
free(target);
- return JIM_ERR;
+ return retval;
}
/* append to end of list */
append_to_list_all_targets(target);
- cmd_ctx->current_target = target;
- return JIM_OK;
+ CMD_CTX->current_target = target;
+ return ERROR_OK;
}
COMMAND_HANDLER(handle_target_current)
@@ -6016,18 +6028,6 @@ COMMAND_HANDLER(handle_target_smp)
return retval;
}
-static int jim_target_create(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
-{
- struct jim_getopt_info goi;
- jim_getopt_setup(&goi, interp, argc - 1, argv + 1);
- if (goi.argc < 3) {
- Jim_WrongNumArgs(goi.interp, goi.argc, goi.argv,
- "<name> <target_type> [<target_options> ...]");
- return JIM_ERR;
- }
- return target_create(&goi);
-}
-
static const struct command_registration target_subcommand_handlers[] = {
{
.name = "init",
@@ -6039,7 +6039,7 @@ static const struct command_registration target_subcommand_handlers[] = {
{
.name = "create",
.mode = COMMAND_CONFIG,
- .jim_handler = jim_target_create,
+ .handler = handle_target_create,
.usage = "name type '-chain-position' name [options ...]",
.help = "Creates and selects a new target",
},
diff --git a/src/target/target_type.h b/src/target/target_type.h
index ce98cba..eddedbf 100644
--- a/src/target/target_type.h
+++ b/src/target/target_type.h
@@ -194,7 +194,7 @@ struct target_type {
const struct command_registration *commands;
/* called when target is created */
- int (*target_create)(struct target *target, Jim_Interp *interp);
+ int (*target_create)(struct target *target);
/* called for various config parameters */
/* returns JIM_CONTINUE - if option not understood */
diff --git a/src/target/xscale.c b/src/target/xscale.c
index 5cc790a..84318a9 100644
--- a/src/target/xscale.c
+++ b/src/target/xscale.c
@@ -3012,7 +3012,7 @@ static int xscale_init_arch_info(struct target *target,
return ERROR_OK;
}
-static int xscale_target_create(struct target *target, Jim_Interp *interp)
+static int xscale_target_create(struct target *target)
{
struct xscale_common *xscale;
diff --git a/src/target/xtensa/xtensa_chip.c b/src/target/xtensa/xtensa_chip.c
index ce6d35c..aab7ee3 100644
--- a/src/target/xtensa/xtensa_chip.c
+++ b/src/target/xtensa/xtensa_chip.c
@@ -81,7 +81,7 @@ static const struct xtensa_power_ops xtensa_chip_dm_pwr_ops = {
.queue_reg_write = xtensa_dm_queue_pwr_reg_write
};
-static int xtensa_chip_target_create(struct target *target, Jim_Interp *interp)
+static int xtensa_chip_target_create(struct target *target)
{
struct xtensa_debug_module_config xtensa_chip_dm_cfg = {
.dbg_ops = &xtensa_chip_dm_dbg_ops,
diff --git a/src/transport/transport.c b/src/transport/transport.c
index 0af1360..ab5be49 100644
--- a/src/transport/transport.c
+++ b/src/transport/transport.c
@@ -30,6 +30,9 @@
* messaging and error handling.
*/
+#include <helper/align.h>
+#include <helper/bits.h>
+#include <helper/list.h>
#include <helper/log.h>
#include <helper/replacements.h>
#include <transport/transport.h>
@@ -43,24 +46,82 @@ extern struct command_context *global_cmd_ctx;
*/
/** List of transports known to OpenOCD. */
-static struct transport *transport_list;
+static const struct {
+ unsigned int id;
+ const char *name;
+ const char *full_name;
+ const char *deprecated_name;
+} transport_names[] = {
+ { TRANSPORT_JTAG, "jtag", "jtag", NULL, },
+ { TRANSPORT_SWD, "swd", "swd", NULL, },
+ { TRANSPORT_HLA_JTAG, "jtag", "jtag (hla)", "hla_jtag", },
+ { TRANSPORT_HLA_SWD, "swd", "swd (hla)", "hla_swd", },
+ { TRANSPORT_DAPDIRECT_JTAG, "jtag", "jtag (dapdirect)", "dapdirect_jtag", },
+ { TRANSPORT_DAPDIRECT_SWD, "swd", "swd (dapdirect)", "dapdirect_swd", },
+ { TRANSPORT_SWIM, "swim", "swim", NULL, },
+};
+
+/** List of transports registered in OpenOCD, alphabetically sorted per name. */
+static OOCD_LIST_HEAD(transport_list);
+
+/**
+ * Bitmask of transport IDs which the currently selected debug adapter supports.
+ * This is declared by the time that adapter is fully set up.
+ */
+static unsigned int allowed_transports;
+
+/**
+ * Transport ID auto-selected when not specified by the user.
+ */
+static unsigned int preferred_transport;
/**
- * NULL-terminated Vector of names of transports which the
- * currently selected debug adapter supports. This is declared
- * by the time that adapter is fully set up.
+ * Adapter supports a single transport; it has been auto-selected
*/
-static const char * const *allowed_transports;
+static bool transport_single_is_autoselected;
/** * The transport being used for the current OpenOCD session. */
static struct transport *session;
-static int transport_select(struct command_context *ctx, const char *name)
+const char *transport_name(unsigned int id)
+{
+ for (unsigned int i = 0; i < ARRAY_SIZE(transport_names); i++)
+ if (id == transport_names[i].id)
+ return transport_names[i].name;
+
+ return NULL;
+}
+
+static const char *transport_full_name(unsigned int id)
+{
+ for (unsigned int i = 0; i < ARRAY_SIZE(transport_names); i++)
+ if (id == transport_names[i].id)
+ return transport_names[i].full_name;
+
+ return NULL;
+}
+
+static const char *transport_deprecated_name(unsigned int id)
+{
+ for (unsigned int i = 0; i < ARRAY_SIZE(transport_names); i++)
+ if (id == transport_names[i].id)
+ return transport_names[i].deprecated_name;
+
+ return NULL;
+}
+
+static bool is_transport_id_valid(unsigned int id)
+{
+ return (id != 0) && ((id & ~TRANSPORT_VALID_MASK) == 0) && IS_PWR_OF_2(id);
+}
+
+static int transport_select(struct command_context *ctx, unsigned int transport_id)
{
/* name may only identify a known transport;
* caller guarantees session's transport isn't yet set.*/
- for (struct transport *t = transport_list; t; t = t->next) {
- if (strcmp(t->name, name) == 0) {
+ struct transport *t;
+ list_for_each_entry(t, &transport_list, lh) {
+ if (t->id == transport_id) {
int retval = t->select(ctx);
/* select() registers commands specific to this
* transport, and may also reset the link, e.g.
@@ -69,12 +130,14 @@ static int transport_select(struct command_context *ctx, const char *name)
if (retval == ERROR_OK)
session = t;
else
- LOG_ERROR("Error selecting '%s' as transport", t->name);
+ LOG_ERROR("Error selecting '%s' as transport",
+ transport_full_name(transport_id));
return retval;
}
}
- LOG_ERROR("No transport named '%s' is available.", name);
+ LOG_ERROR("No transport named '%s' is available.",
+ transport_full_name(transport_id));
return ERROR_FAIL;
}
@@ -83,29 +146,48 @@ static int transport_select(struct command_context *ctx, const char *name)
* to declare the set of transports supported by an adapter. When
* there is only one member of that set, it is automatically selected.
*/
-int allow_transports(struct command_context *ctx, const char * const *vector)
+int allow_transports(struct command_context *ctx, unsigned int transport_ids,
+ unsigned int transport_preferred_id)
{
- /* NOTE: caller is required to provide only a list
- * of *valid* transport names
- *
- * REVISIT should we validate that? and insist there's
- * at least one non-NULL element in that list?
- *
- * ... allow removals, e.g. external strapping prevents use
- * of one transport; C code should be definitive about what
- * can be used when all goes well.
- */
if (allowed_transports || session) {
LOG_ERROR("Can't modify the set of allowed transports.");
return ERROR_FAIL;
}
- allowed_transports = vector;
+ /* validate the values in transport_ids and transport_preferred_id */
+ if (transport_ids == 0 || (transport_ids & ~TRANSPORT_VALID_MASK) != 0) {
+ LOG_ERROR("BUG: Unknown transport IDs %lu", transport_ids & ~TRANSPORT_VALID_MASK);
+ return ERROR_FAIL;
+ }
+
+ if ((transport_ids & transport_preferred_id) == 0
+ || !IS_PWR_OF_2(transport_preferred_id)) {
+ LOG_ERROR("BUG: Invalid adapter transport_preferred_id");
+ return ERROR_FAIL;
+ }
+
+ unsigned int mask = transport_ids &
+ (TRANSPORT_JTAG | TRANSPORT_HLA_JTAG | TRANSPORT_DAPDIRECT_JTAG);
+ if (mask && !IS_PWR_OF_2(mask)) {
+ LOG_ERROR("BUG: Multiple JTAG transports");
+ return ERROR_FAIL;
+ }
+
+ mask = transport_ids &
+ (TRANSPORT_SWD | TRANSPORT_HLA_SWD | TRANSPORT_DAPDIRECT_SWD);
+ if (mask && !IS_PWR_OF_2(mask)) {
+ LOG_ERROR("BUG: Multiple SWD transports");
+ return ERROR_FAIL;
+ }
+
+ allowed_transports = transport_ids;
+ preferred_transport = transport_preferred_id;
/* autoselect if there's no choice ... */
- if (!vector[1]) {
- LOG_INFO("only one transport option; autoselecting '%s'", vector[0]);
- return transport_select(ctx, vector[0]);
+ if (IS_PWR_OF_2(transport_ids)) {
+ LOG_DEBUG("only one transport option; autoselecting '%s'", transport_name(transport_ids));
+ transport_single_is_autoselected = true;
+ return transport_select(ctx, transport_ids);
}
return ERROR_OK;
@@ -130,20 +212,33 @@ int transport_register(struct transport *new_transport)
{
struct transport *t;
- for (t = transport_list; t; t = t->next) {
- if (strcmp(t->name, new_transport->name) == 0) {
- LOG_ERROR("transport name already used");
+ if (!is_transport_id_valid(new_transport->id)) {
+ LOG_ERROR("invalid transport ID 0x%x", new_transport->id);
+ return ERROR_FAIL;
+ }
+
+ list_for_each_entry(t, &transport_list, lh) {
+ if (t->id == new_transport->id) {
+ LOG_ERROR("transport '%s' already registered",
+ transport_name(t->id));
return ERROR_FAIL;
}
}
if (!new_transport->select || !new_transport->init)
- LOG_ERROR("invalid transport %s", new_transport->name);
+ LOG_ERROR("invalid transport %s",
+ transport_full_name(new_transport->id));
+
+ /* splice this into the list, sorted in alphabetic order */
+ list_for_each_entry(t, &transport_list, lh) {
+ if (strcmp(transport_name(t->id),
+ transport_name(new_transport->id)) >= 0)
+ break;
+ }
+ list_add_tail(&new_transport->lh, &t->lh);
- /* splice this into the list */
- new_transport->next = transport_list;
- transport_list = new_transport;
- LOG_DEBUG("register '%s'", new_transport->name);
+ LOG_DEBUG("register '%s' (ID %d)",
+ transport_full_name(new_transport->id), new_transport->id);
return ERROR_OK;
}
@@ -160,6 +255,14 @@ struct transport *get_current_transport(void)
return session;
}
+const char *get_current_transport_name(void)
+{
+ if (!session || !is_transport_id_valid(session->id))
+ NULL;
+
+ return transport_full_name(session->id);
+}
+
/*-----------------------------------------------------------------------*/
/*
@@ -174,14 +277,18 @@ COMMAND_HANDLER(handle_transport_init)
/* no session transport configured, print transports then fail */
LOG_ERROR("Transports available:");
- const char * const *vector = allowed_transports;
- while (*vector) {
- LOG_ERROR("%s", *vector);
- vector++;
+ for (unsigned int i = BIT(0); i & TRANSPORT_VALID_MASK; i <<= 1) {
+ if (i & allowed_transports)
+ LOG_ERROR("%s", transport_full_name(i));
}
return ERROR_FAIL;
}
+ if (transport_single_is_autoselected)
+ LOG_WARNING("DEPRECATED: auto-selecting transport \"%s\". "
+ "Use 'transport select %s' to suppress this message.",
+ transport_full_name(session->id), transport_name(session->id));
+
return session->init(CMD_CTX);
}
@@ -192,8 +299,15 @@ COMMAND_HANDLER(handle_transport_list)
command_print(CMD, "The following transports are available:");
- for (struct transport *t = transport_list; t; t = t->next)
- command_print(CMD, "\t%s", t->name);
+ struct transport *t;
+ const char *prev_name = NULL;
+ /* list is sorted, don't print duplicated transport names */
+ list_for_each_entry(t, &transport_list, lh) {
+ const char *name = transport_name(t->id);
+ if (!prev_name || strcmp(prev_name, name))
+ command_print(CMD, "\t%s", name);
+ prev_name = name;
+ }
return ERROR_OK;
}
@@ -216,20 +330,29 @@ COMMAND_HANDLER(handle_transport_select)
command_print(CMD, "Debug adapter does not support any transports? Check config file order.");
return ERROR_FAIL;
}
- LOG_INFO("auto-selecting first available session transport \"%s\". "
- "To override use 'transport select <transport>'.", allowed_transports[0]);
- int retval = transport_select(CMD_CTX, allowed_transports[0]);
+ LOG_WARNING("DEPRECATED: auto-selecting transport \"%s\". "
+ "Use 'transport select %s' to suppress this message.",
+ transport_full_name(preferred_transport),
+ transport_name(preferred_transport));
+ int retval = transport_select(CMD_CTX, preferred_transport);
if (retval != ERROR_OK)
return retval;
}
- command_print(CMD, "%s", session->name);
+ command_print(CMD, "%s", transport_full_name(session->id));
return ERROR_OK;
}
/* assign transport */
if (session) {
- if (!strcmp(session->name, CMD_ARGV[0])) {
- LOG_WARNING("Transport \"%s\" was already selected", session->name);
+ if (!strcmp(transport_name(session->id), CMD_ARGV[0])
+ || (transport_deprecated_name(session->id)
+ && !strcmp(transport_deprecated_name(session->id), CMD_ARGV[0]))) {
+ if (transport_single_is_autoselected) {
+ /* Nothing to do, but also nothing to complain */
+ transport_single_is_autoselected = false;
+ return ERROR_OK;
+ }
+ LOG_WARNING("Transport \"%s\" was already selected", CMD_ARGV[0]);
return ERROR_OK;
}
command_print(CMD, "Can't change session's transport after the initial selection was made");
@@ -247,12 +370,18 @@ COMMAND_HANDLER(handle_transport_select)
return ERROR_FAIL;
}
- for (unsigned int i = 0; allowed_transports[i]; i++) {
- if (!strcmp(allowed_transports[i], CMD_ARGV[0])) {
- int retval = transport_select(CMD_CTX, CMD_ARGV[0]);
- if (retval != ERROR_OK)
- return retval;
- return ERROR_OK;
+ for (unsigned int i = BIT(0); i & TRANSPORT_VALID_MASK; i <<= 1) {
+ if (!(i & allowed_transports))
+ continue;
+
+ if (!strcmp(transport_name(i), CMD_ARGV[0]))
+ return transport_select(CMD_CTX, i);
+
+ if (transport_deprecated_name(i)
+ && !strcmp(transport_deprecated_name(i), CMD_ARGV[0])) {
+ LOG_WARNING("DEPRECATED! use 'transport select %s', not 'transport select %s'",
+ transport_name(i), transport_deprecated_name(i));
+ return transport_select(CMD_CTX, i);
}
}
diff --git a/src/transport/transport.h b/src/transport/transport.h
index 2e3dcc6..5445bcf 100644
--- a/src/transport/transport.h
+++ b/src/transport/transport.h
@@ -12,7 +12,27 @@
#include "config.h"
#endif
+#include "helper/bits.h"
#include "helper/command.h"
+#include "helper/list.h"
+
+#define TRANSPORT_JTAG BIT(0)
+#define TRANSPORT_SWD BIT(1)
+#define TRANSPORT_HLA_JTAG BIT(2)
+#define TRANSPORT_HLA_SWD BIT(3)
+#define TRANSPORT_DAPDIRECT_JTAG BIT(4)
+#define TRANSPORT_DAPDIRECT_SWD BIT(5)
+#define TRANSPORT_SWIM BIT(6)
+
+/* mask for valid ID */
+#define TRANSPORT_VALID_MASK \
+ (TRANSPORT_JTAG | \
+ TRANSPORT_SWD | \
+ TRANSPORT_HLA_JTAG | \
+ TRANSPORT_HLA_SWD | \
+ TRANSPORT_DAPDIRECT_JTAG | \
+ TRANSPORT_DAPDIRECT_SWD | \
+ TRANSPORT_SWIM)
/**
* Wrapper for transport lifecycle operations.
@@ -34,11 +54,10 @@
*/
struct transport {
/**
- * Each transport has a unique name, used to select it
- * from among the alternatives. Examples might include
- * "jtag", * "swd", "AVR_ISP" and more.
+ * Each transport has a unique ID, used to select it
+ * from among the alternatives.
*/
- const char *name;
+ unsigned int id;
/**
* When a transport is selected, this method registers
@@ -66,18 +85,23 @@ struct transport {
int (*override_target)(const char **targetname);
/**
- * Transports are stored in a singly linked list.
+ * Transports are stored in a linked list.
*/
- struct transport *next;
+ struct list_head lh;
};
int transport_register(struct transport *new_transport);
struct transport *get_current_transport(void);
+const char *get_current_transport_name(void);
+
+const char *transport_name(unsigned int id);
+
int transport_register_commands(struct command_context *ctx);
-int allow_transports(struct command_context *ctx, const char * const *vector);
+int allow_transports(struct command_context *ctx, unsigned int transport_ids,
+ unsigned int transport_preferred_id);
bool transport_is_jtag(void);
bool transport_is_swd(void);