aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Makefile.am4
-rw-r--r--src/flash/nor/atsame5.c30
-rw-r--r--src/flash/nor/em357.c2
-rw-r--r--src/flash/nor/kinetis.c1
-rw-r--r--src/flash/nor/nrf5.c126
-rw-r--r--src/flash/nor/psoc6.c7
-rw-r--r--src/flash/nor/sfdp.c3
-rw-r--r--src/flash/nor/sfdp.h4
-rw-r--r--src/flash/nor/stm32l4x.c58
-rw-r--r--src/flash/nor/stm32l4x.h2
-rw-r--r--src/flash/nor/stmqspi.c4
-rw-r--r--src/flash/startup.tcl6
-rw-r--r--src/helper/binarybuffer.c194
-rw-r--r--src/helper/binarybuffer.h24
-rw-r--r--src/helper/command.c21
-rw-r--r--src/helper/command.h9
-rw-r--r--src/helper/jep106.inc37
-rw-r--r--src/jtag/commands.c30
-rw-r--r--src/jtag/commands.h12
-rw-r--r--src/jtag/core.c110
-rw-r--r--src/jtag/drivers/amt_jtagaccel.c2
-rw-r--r--src/jtag/drivers/angie.c11
-rw-r--r--src/jtag/drivers/arm-jtag-ew.c20
-rw-r--r--src/jtag/drivers/bitbang.c21
-rw-r--r--src/jtag/drivers/bitq.c28
-rw-r--r--src/jtag/drivers/buspirate.c29
-rw-r--r--src/jtag/drivers/cmsis_dap.c20
-rw-r--r--src/jtag/drivers/cmsis_dap_usb_hid.c8
-rw-r--r--src/jtag/drivers/driver.c8
-rw-r--r--src/jtag/drivers/ft232r.c18
-rw-r--r--src/jtag/drivers/ftdi.c25
-rw-r--r--src/jtag/drivers/gw16012.c7
-rw-r--r--src/jtag/drivers/jlink.c138
-rw-r--r--src/jtag/drivers/jtag_dpi.c10
-rw-r--r--src/jtag/drivers/jtag_vpi.c14
-rw-r--r--src/jtag/drivers/mpsse.c3
-rw-r--r--src/jtag/drivers/mpsse.h1
-rw-r--r--src/jtag/drivers/opendous.c20
-rw-r--r--src/jtag/drivers/openjtag.c10
-rw-r--r--src/jtag/drivers/osbdm.c12
-rw-r--r--src/jtag/drivers/rlink.c10
-rw-r--r--src/jtag/drivers/ulink.c11
-rw-r--r--src/jtag/drivers/usb_blaster/usb_blaster.c18
-rw-r--r--src/jtag/drivers/usbprog.c14
-rw-r--r--src/jtag/drivers/vdebug.c22
-rw-r--r--src/jtag/drivers/vsllink.c20
-rw-r--r--src/jtag/drivers/xds110.c12
-rw-r--r--src/jtag/drivers/xlnx-pcie-xvc.c11
-rw-r--r--src/jtag/hla/hla_interface.c23
-rw-r--r--src/jtag/jtag.h39
-rw-r--r--src/jtag/minidriver.h6
-rw-r--r--src/jtag/startup.tcl30
-rw-r--r--src/jtag/tcl.c21
-rw-r--r--src/rtos/hwthread.c51
-rw-r--r--src/rtos/nuttx.c54
-rw-r--r--src/rtos/rtos_nuttx_stackings.c134
-rw-r--r--src/rtos/rtos_nuttx_stackings.h9
-rw-r--r--src/rtos/rtos_standard_stackings.c4
-rw-r--r--src/rtt/tcl.c12
-rw-r--r--src/server/gdb_server.c74
-rw-r--r--src/server/startup.tcl78
-rw-r--r--src/server/tcl_server.c21
-rw-r--r--src/server/telnet_server.c26
-rw-r--r--src/svf/svf.c2
-rw-r--r--src/target/aarch64.c49
-rw-r--r--src/target/arm.h11
-rw-r--r--src/target/arm_adi_v5.c19
-rw-r--r--src/target/arm_cti.c76
-rw-r--r--src/target/arm_cti.h1
-rw-r--r--src/target/armv8.h2
-rw-r--r--src/target/avrt.c26
-rw-r--r--src/target/breakpoints.c18
-rw-r--r--src/target/breakpoints.h13
-rw-r--r--src/target/cortex_m.c96
-rw-r--r--src/target/cortex_m.h44
-rw-r--r--src/target/esirisc.c2
-rw-r--r--src/target/esirisc_jtag.c5
-rw-r--r--src/target/espressif/esp32s3.c1
-rw-r--r--src/target/espressif/esp_xtensa.c72
-rw-r--r--src/target/espressif/esp_xtensa.h3
-rw-r--r--src/target/lakemont.c4
-rw-r--r--src/target/riscv/batch.c158
-rw-r--r--src/target/riscv/batch.h28
-rw-r--r--src/target/riscv/opcodes.h16
-rw-r--r--src/target/riscv/program.c6
-rw-r--r--src/target/riscv/riscv-011.c80
-rw-r--r--src/target/riscv/riscv-011_reg.c4
-rw-r--r--src/target/riscv/riscv-013.c1372
-rw-r--r--src/target/riscv/riscv-013.h4
-rw-r--r--src/target/riscv/riscv-013_reg.c280
-rw-r--r--src/target/riscv/riscv-013_reg.h7
-rw-r--r--src/target/riscv/riscv.c444
-rw-r--r--src/target/riscv/riscv.h72
-rw-r--r--src/target/riscv/riscv_reg.c53
-rw-r--r--src/target/riscv/riscv_reg_impl.h16
-rw-r--r--src/target/target.c75
-rw-r--r--src/target/target.h3
-rw-r--r--src/target/target_request.c4
-rw-r--r--src/target/xtensa/xtensa.c8
-rw-r--r--src/target/xtensa/xtensa_chip.c2
-rw-r--r--src/target/xtensa/xtensa_debug_module.h2
-rw-r--r--src/transport/transport.c2
102 files changed, 2767 insertions, 2102 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index 6d79cd6..4d1c1a2 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -17,8 +17,12 @@ bin_PROGRAMS += %D%/openocd
if INTERNAL_JIMTCL
%C%_openocd_LDADD += $(top_builddir)/jimtcl/libjim.a
else
+if HAVE_JIMTCL_PKG_CONFIG
+%C%_openocd_LDADD += $(JIMTCL_LIBS)
+else
%C%_openocd_LDADD += -ljim
endif
+endif
%C%_libopenocd_la_CPPFLAGS =
diff --git a/src/flash/nor/atsame5.c b/src/flash/nor/atsame5.c
index c590081..a6ac906 100644
--- a/src/flash/nor/atsame5.c
+++ b/src/flash/nor/atsame5.c
@@ -85,6 +85,9 @@
#define SAME_SERIES_51 0x01
#define SAME_SERIES_53 0x03
#define SAME_SERIES_54 0x04
+#define PIC32CXSG_SERIES_41 0x07
+#define PIC32CXSG_SERIES_60 0x00
+#define PIC32CXSG_SERIES_61 0x02
/* Device ID macros */
#define SAMD_GET_PROCESSOR(id) (id >> 28)
@@ -148,6 +151,27 @@ static const struct samd_part same54_parts[] = {
{ 0x03, "SAME54N19A", 512, 192 },
};
+/* See PIC32CX SG41/SG60/SG61 Family Silicon Errata and Datasheet Clarifications
+ * DS80000985G */
+/* Known PIC32CX-SG41 parts. */
+static const struct samd_part pic32cxsg41_parts[] = {
+ { 0x00, "PIC32CX1025SG41128", 1024, 256 },
+ { 0x01, "PIC32CX1025SG41100", 1024, 256 },
+ { 0x02, "PIC32CX1025SG41064", 1024, 256 },
+};
+
+/* Known PIC32CX-SG60 parts. */
+static const struct samd_part pic32cxsg60_parts[] = {
+ { 0x00, "PIC32CX1025SG60128", 1024, 256 },
+ { 0x01, "PIC32CX1025SG60100", 1024, 256 },
+};
+
+/* Known PIC32CX-SG61 parts. */
+static const struct samd_part pic32cxsg61_parts[] = {
+ { 0x00, "PIC32CX1025SG61128", 1024, 256 },
+ { 0x01, "PIC32CX1025SG61100", 1024, 256 },
+};
+
/* Each family of parts contains a parts table in the DEVSEL field of DID. The
* processor ID, family ID, and series ID are used to determine which exact
* family this is and then we can use the corresponding table. */
@@ -169,6 +193,12 @@ static const struct samd_family samd_families[] = {
same53_parts, ARRAY_SIZE(same53_parts) },
{ SAMD_PROCESSOR_M4, SAMD_FAMILY_E, SAME_SERIES_54,
same54_parts, ARRAY_SIZE(same54_parts) },
+ { SAMD_PROCESSOR_M4, SAMD_FAMILY_E, PIC32CXSG_SERIES_41,
+ pic32cxsg41_parts, ARRAY_SIZE(pic32cxsg41_parts) },
+ { SAMD_PROCESSOR_M4, SAMD_FAMILY_E, PIC32CXSG_SERIES_60,
+ pic32cxsg60_parts, ARRAY_SIZE(pic32cxsg60_parts) },
+ { SAMD_PROCESSOR_M4, SAMD_FAMILY_E, PIC32CXSG_SERIES_61,
+ pic32cxsg61_parts, ARRAY_SIZE(pic32cxsg61_parts) },
};
struct samd_info {
diff --git a/src/flash/nor/em357.c b/src/flash/nor/em357.c
index 043494c..207346f 100644
--- a/src/flash/nor/em357.c
+++ b/src/flash/nor/em357.c
@@ -709,7 +709,7 @@ static int em357_probe(struct flash_bank *bank)
em357_info->ppage_size = 4;
- LOG_INFO("flash size = %d KiB", num_pages*page_size/1024);
+ LOG_INFO("flash size = %d KiB", num_pages * page_size / 1024);
free(bank->sectors);
diff --git a/src/flash/nor/kinetis.c b/src/flash/nor/kinetis.c
index fee3644..2d0a753 100644
--- a/src/flash/nor/kinetis.c
+++ b/src/flash/nor/kinetis.c
@@ -1038,6 +1038,7 @@ static int kinetis_create_missing_banks(struct kinetis_chip *k_chip)
bank->target = k_chip->target;
bank->driver = &kinetis_flash;
bank->default_padded_value = bank->erased_value = 0xff;
+ bank->minimal_write_gap = FLASH_WRITE_GAP_SECTOR;
snprintf(name, sizeof(name), "%s.%s%s",
base_name, class, num);
diff --git a/src/flash/nor/nrf5.c b/src/flash/nor/nrf5.c
index f07433e..5cb552a 100644
--- a/src/flash/nor/nrf5.c
+++ b/src/flash/nor/nrf5.c
@@ -117,20 +117,24 @@ struct nrf5_map {
struct nrf5_info {
unsigned int refcount;
+ bool chip_probed;
struct nrf5_bank {
struct nrf5_info *chip;
bool probed;
} bank[2];
+
struct target *target;
- /* chip identification stored in nrf5_probe() for use in nrf5_info() */
+ /* chip identification stored in nrf5_probe_chip()
+ * for use in nrf5_info() and nrf5_setup_bank() */
bool ficr_info_valid;
struct nrf52_ficr_info ficr_info;
const struct nrf5_device_spec *spec;
uint16_t hwid;
enum nrf5_features features;
- unsigned int flash_size_kb;
+ uint32_t flash_page_size;
+ uint32_t flash_num_sectors;
unsigned int ram_size_kb;
const struct nrf5_map *map;
@@ -341,16 +345,19 @@ const struct flash_driver nrf5_flash, nrf51_flash;
static bool nrf5_bank_is_probed(const struct flash_bank *bank)
{
struct nrf5_bank *nbank = bank->driver_priv;
- assert(nbank);
-
return nbank->probed;
}
-static bool nrf5_bank_is_uicr(const struct nrf5_bank *nbank)
+static bool nrf5_chip_is_probed(const struct flash_bank *bank)
{
+ struct nrf5_bank *nbank = bank->driver_priv;
struct nrf5_info *chip = nbank->chip;
- assert(chip);
+ return chip->chip_probed;
+}
+static bool nrf5_bank_is_uicr(const struct nrf5_bank *nbank)
+{
+ struct nrf5_info *chip = nbank->chip;
return nbank == &chip->bank[1];
}
@@ -470,9 +477,7 @@ static int nrf51_protect_check_clenr0(struct flash_bank *bank)
uint32_t clenr0;
struct nrf5_bank *nbank = bank->driver_priv;
- assert(nbank);
struct nrf5_info *chip = nbank->chip;
- assert(chip);
res = target_read_u32(chip->target, NRF51_FICR_CLENR0,
&clenr0);
@@ -501,9 +506,7 @@ static int nrf51_protect_check_clenr0(struct flash_bank *bank)
static int nrf52_protect_check_bprot(struct flash_bank *bank)
{
struct nrf5_bank *nbank = bank->driver_priv;
- assert(nbank);
struct nrf5_info *chip = nbank->chip;
- assert(chip);
static uint32_t nrf5_bprot_offsets[4] = { 0x600, 0x604, 0x610, 0x614 };
uint32_t bprot_reg = 0;
@@ -528,9 +531,7 @@ static int nrf52_protect_check_bprot(struct flash_bank *bank)
static int nrf5_protect_check(struct flash_bank *bank)
{
struct nrf5_bank *nbank = bank->driver_priv;
- assert(nbank);
struct nrf5_info *chip = nbank->chip;
- assert(chip);
/* UICR cannot be write protected so just return early */
if (nrf5_bank_is_uicr(nbank))
@@ -554,9 +555,7 @@ static int nrf51_protect_clenr0(struct flash_bank *bank, int set, unsigned int f
uint32_t clenr0, ppfc;
struct nrf5_bank *nbank = bank->driver_priv;
- assert(nbank);
struct nrf5_info *chip = nbank->chip;
- assert(chip);
if (first != 0) {
LOG_ERROR("Code region 0 must start at the beginning of the bank");
@@ -614,9 +613,7 @@ static int nrf5_protect(struct flash_bank *bank, int set, unsigned int first,
unsigned int last)
{
struct nrf5_bank *nbank = bank->driver_priv;
- assert(nbank);
struct nrf5_info *chip = nbank->chip;
- assert(chip);
/* UICR cannot be write protected so just bail out early */
if (nrf5_bank_is_uicr(nbank)) {
@@ -701,16 +698,15 @@ static int nrf5_get_chip_type_str(const struct nrf5_info *chip, char *buf, unsig
static int nrf5_info(struct flash_bank *bank, struct command_invocation *cmd)
{
struct nrf5_bank *nbank = bank->driver_priv;
- assert(nbank);
struct nrf5_info *chip = nbank->chip;
- assert(chip);
char chip_type_str[256];
if (nrf5_get_chip_type_str(chip, chip_type_str, sizeof(chip_type_str)) != ERROR_OK)
return ERROR_FAIL;
+ unsigned int flash_size_kb = chip->flash_num_sectors * chip->flash_page_size / 1024;
command_print_sameline(cmd, "%s %ukB Flash, %ukB RAM",
- chip_type_str, chip->flash_size_kb, chip->ram_size_kb);
+ chip_type_str, flash_size_kb, chip->ram_size_kb);
return ERROR_OK;
}
@@ -838,14 +834,12 @@ static int nrf51_get_ram_size(struct target *target, uint32_t *ram_size)
return res;
}
-static int nrf5_probe(struct flash_bank *bank)
+static int nrf5_probe_chip(struct flash_bank *bank)
{
int res = ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
struct nrf5_bank *nbank = bank->driver_priv;
- assert(nbank);
struct nrf5_info *chip = nbank->chip;
- assert(chip);
struct target *target = chip->target;
chip->spec = NULL;
@@ -968,9 +962,8 @@ static int nrf5_probe(struct flash_bank *bank)
}
/* The value stored in FICR CODEPAGESIZE is the number of bytes in one page of FLASH. */
- uint32_t flash_page_size;
res = target_read_u32(chip->target, ficr_base + ficr_offsets->codepagesize,
- &flash_page_size);
+ &chip->flash_page_size);
if (res != ERROR_OK) {
LOG_ERROR("Couldn't read code page size");
return res;
@@ -978,69 +971,93 @@ static int nrf5_probe(struct flash_bank *bank)
/* Note the register name is misleading,
* FICR CODESIZE is the number of pages in flash memory, not the number of bytes! */
- uint32_t num_sectors;
res = target_read_u32(chip->target, ficr_base + ficr_offsets->codesize,
- &num_sectors);
+ &chip->flash_num_sectors);
if (res != ERROR_OK) {
LOG_ERROR("Couldn't read code memory size");
return res;
}
- chip->flash_size_kb = num_sectors * flash_page_size / 1024;
+ char chip_type_str[256];
+ if (nrf5_get_chip_type_str(chip, chip_type_str, sizeof(chip_type_str)) != ERROR_OK)
+ return ERROR_FAIL;
- if (!chip->bank[0].probed && !chip->bank[1].probed) {
- char chip_type_str[256];
- if (nrf5_get_chip_type_str(chip, chip_type_str, sizeof(chip_type_str)) != ERROR_OK)
- return ERROR_FAIL;
- const bool device_is_unknown = (!chip->spec && !chip->ficr_info_valid);
- LOG_INFO("%s%s %ukB Flash, %ukB RAM",
- device_is_unknown ? "Unknown device: " : "",
- chip_type_str,
- chip->flash_size_kb,
- chip->ram_size_kb);
- }
+ unsigned int flash_size_kb = chip->flash_num_sectors * chip->flash_page_size / 1024;
+ const bool device_is_unknown = (!chip->spec && !chip->ficr_info_valid);
+ LOG_INFO("%s%s %ukB Flash, %ukB RAM",
+ device_is_unknown ? "Unknown device: " : "",
+ chip_type_str,
+ flash_size_kb,
+ chip->ram_size_kb);
- free(bank->sectors);
+ chip->chip_probed = true;
+ return ERROR_OK;
+}
+
+static int nrf5_setup_bank(struct flash_bank *bank)
+{
+ struct nrf5_bank *nbank = bank->driver_priv;
+ struct nrf5_info *chip = nbank->chip;
if (bank->base == chip->map->flash_base) {
+ unsigned int flash_size_kb = chip->flash_num_sectors * chip->flash_page_size / 1024;
/* Sanity check */
- if (chip->spec && chip->flash_size_kb != chip->spec->flash_size_kb)
+ if (chip->spec && flash_size_kb != chip->spec->flash_size_kb)
LOG_WARNING("Chip's reported Flash capacity does not match expected one");
- if (chip->ficr_info_valid && chip->flash_size_kb != chip->ficr_info.flash)
+ if (chip->ficr_info_valid && flash_size_kb != chip->ficr_info.flash)
LOG_WARNING("Chip's reported Flash capacity does not match FICR INFO.FLASH");
- bank->num_sectors = num_sectors;
- bank->size = num_sectors * flash_page_size;
+ bank->num_sectors = chip->flash_num_sectors;
+ bank->size = chip->flash_num_sectors * chip->flash_page_size;
- bank->sectors = alloc_block_array(0, flash_page_size, num_sectors);
+ bank->sectors = alloc_block_array(0, chip->flash_page_size, bank->num_sectors);
if (!bank->sectors)
return ERROR_FAIL;
chip->bank[0].probed = true;
- } else {
+ } else if (bank->base == chip->map->uicr_base) {
/* UICR bank */
bank->num_sectors = 1;
- bank->size = flash_page_size;
+ bank->size = chip->flash_page_size;
- bank->sectors = alloc_block_array(0, flash_page_size, num_sectors);
+ bank->sectors = alloc_block_array(0, chip->flash_page_size, bank->num_sectors);
if (!bank->sectors)
return ERROR_FAIL;
bank->sectors[0].is_protected = 0;
chip->bank[1].probed = true;
+ } else {
+ LOG_ERROR("Invalid nRF bank address " TARGET_ADDR_FMT, bank->base);
+ return ERROR_FLASH_BANK_INVALID;
}
return ERROR_OK;
}
+static int nrf5_probe(struct flash_bank *bank)
+{
+ /* probe always reads actual info from the device */
+ int res = nrf5_probe_chip(bank);
+ if (res != ERROR_OK)
+ return res;
+
+ return nrf5_setup_bank(bank);
+}
+
static int nrf5_auto_probe(struct flash_bank *bank)
{
if (nrf5_bank_is_probed(bank))
return ERROR_OK;
- return nrf5_probe(bank);
+ if (!nrf5_chip_is_probed(bank)) {
+ int res = nrf5_probe_chip(bank);
+ if (res != ERROR_OK)
+ return res;
+ }
+
+ return nrf5_setup_bank(bank);
}
@@ -1214,9 +1231,7 @@ static int nrf5_write(struct flash_bank *bank, const uint8_t *buffer,
}
struct nrf5_bank *nbank = bank->driver_priv;
- assert(nbank);
struct nrf5_info *chip = nbank->chip;
- assert(chip);
assert(offset % 4 == 0);
assert(count % 4 == 0);
@@ -1276,9 +1291,7 @@ static int nrf5_erase(struct flash_bank *bank, unsigned int first,
}
struct nrf5_bank *nbank = bank->driver_priv;
- assert(nbank);
struct nrf5_info *chip = nbank->chip;
- assert(chip);
/* UICR CLENR0 based protection used on nRF51 prevents erase
* absolutely silently. NVMC has no flag to indicate the protection
@@ -1322,7 +1335,6 @@ error:
static void nrf5_free_driver_priv(struct flash_bank *bank)
{
struct nrf5_bank *nbank = bank->driver_priv;
- assert(nbank);
struct nrf5_info *chip = nbank->chip;
if (!chip)
return;
@@ -1372,8 +1384,8 @@ FLASH_BANK_COMMAND_HANDLER(nrf5_flash_bank_command)
case NRF53NET_UICR_BASE:
break;
default:
- LOG_ERROR("Invalid bank address " TARGET_ADDR_FMT, bank->base);
- return ERROR_FAIL;
+ LOG_ERROR("Invalid nRF bank address " TARGET_ADDR_FMT, bank->base);
+ return ERROR_FLASH_BANK_INVALID;
}
chip = nrf5_get_chip(bank->target);
@@ -1418,17 +1430,13 @@ COMMAND_HANDLER(nrf5_handle_mass_erase_command)
if (res != ERROR_OK)
return res;
- assert(bank);
-
if (target->state != TARGET_HALTED) {
LOG_ERROR("Target not halted");
return ERROR_TARGET_NOT_HALTED;
}
struct nrf5_bank *nbank = bank->driver_priv;
- assert(nbank);
struct nrf5_info *chip = nbank->chip;
- assert(chip);
if (chip->features & NRF5_FEATURE_SERIES_51) {
uint32_t ppfc;
diff --git a/src/flash/nor/psoc6.c b/src/flash/nor/psoc6.c
index 859b3e9..47f3ac6 100644
--- a/src/flash/nor/psoc6.c
+++ b/src/flash/nor/psoc6.c
@@ -223,6 +223,8 @@ static int ipc_poll_lock_stat(struct target *target, uint32_t ipc_id, bool lock_
{
int hr;
uint32_t reg_val;
+ struct armv7m_common *armv7m = target_to_armv7m(target);
+ bool is_cm0 = (armv7m->arm.arch == ARM_ARCH_V6M);
struct timeout to;
timeout_init(&to, IPC_TIMEOUT_MS);
@@ -244,7 +246,7 @@ static int ipc_poll_lock_stat(struct target *target, uint32_t ipc_id, bool lock_
return ERROR_OK;
}
- if (target->coreid) {
+ if (!is_cm0) {
LOG_WARNING("SROM API calls via CM4 target are supported on single-core PSoC6 devices only. "
"Please perform all Flash-related operations via CM0+ target on dual-core devices.");
}
@@ -886,7 +888,8 @@ static int handle_reset_halt(struct target *target)
{
int hr;
uint32_t reset_addr;
- bool is_cm0 = (target->coreid == 0);
+ struct armv7m_common *armv7m = target_to_armv7m(target);
+ bool is_cm0 = (armv7m->arm.arch == ARM_ARCH_V6M);
/* Halt target device */
if (target->state != TARGET_HALTED) {
diff --git a/src/flash/nor/sfdp.c b/src/flash/nor/sfdp.c
index 5bfb541..917f162 100644
--- a/src/flash/nor/sfdp.c
+++ b/src/flash/nor/sfdp.c
@@ -12,7 +12,6 @@
#include "spi.h"
#include "sfdp.h"
-#define SFDP_MAGIC 0x50444653
#define SFDP_ACCESS_PROT 0xFF
#define SFDP_BASIC_FLASH 0xFF00
#define SFDP_4BYTE_ADDR 0xFF84
@@ -100,7 +99,7 @@ int spi_sfdp(struct flash_bank *bank, struct flash_device *dev,
goto err;
for (k = 0; k < nph; k++) {
- uint8_t words = (pheaders[k].revision >> 24) & 0xFF;
+ unsigned int words = (pheaders[k].revision >> 24) & 0xFF;
uint16_t id = (((pheaders[k].ptr) >> 16) & 0xFF00) | (pheaders[k].revision & 0xFF);
uint32_t ptr = pheaders[k].ptr & 0xFFFFFF;
diff --git a/src/flash/nor/sfdp.h b/src/flash/nor/sfdp.h
index 1c9af32..0d43519 100644
--- a/src/flash/nor/sfdp.h
+++ b/src/flash/nor/sfdp.h
@@ -7,6 +7,8 @@
#ifndef OPENOCD_FLASH_NOR_SFDP_H
#define OPENOCD_FLASH_NOR_SFDP_H
+#define SFDP_MAGIC 0x50444653
+
/* per JESD216D 'addr' is *byte* based but must be word aligned,
* 'buffer' is word based, word aligned and always little-endian encoded,
* in the flash, 'addr_len' is 3 or 4, 'dummy' ***usually*** 8
@@ -16,7 +18,7 @@
*
* buffer contents is supposed to be returned in ***host*** endianness */
typedef int (*read_sfdp_block_t)(struct flash_bank *bank, uint32_t addr,
- uint32_t words, uint32_t *buffer);
+ unsigned int words, uint32_t *buffer);
extern int spi_sfdp(struct flash_bank *bank, struct flash_device *dev,
read_sfdp_block_t read_sfdp_block);
diff --git a/src/flash/nor/stm32l4x.c b/src/flash/nor/stm32l4x.c
index 0399385..9235dd7 100644
--- a/src/flash/nor/stm32l4x.c
+++ b/src/flash/nor/stm32l4x.c
@@ -120,6 +120,12 @@
* http://www.st.com/resource/en/reference_manual/dm00346336.pdf
*/
+/* STM32U5xxx series for reference.
+ *
+ * RM0456 (STM32U5xx)
+ * http://www.st.com/resource/en/reference_manual/dm00477635.pdf
+ */
+
/* Erase time can be as high as 25ms, 10x this and assume it's toast... */
#define FLASH_ERASE_TIMEOUT 250
@@ -344,9 +350,17 @@ static const struct stm32l4_rev stm32g49_g4axx_revs[] = {
{ 0x1000, "A" },
};
+static const struct stm32l4_rev stm32u53_u54xx_revs[] = {
+ { 0x1000, "A" }, { 0x1001, "Z" },
+};
+
static const struct stm32l4_rev stm32u57_u58xx_revs[] = {
{ 0x1000, "A" }, { 0x1001, "Z" }, { 0x1003, "Y" }, { 0x2000, "B" },
- { 0x2001, "X" }, { 0x3000, "C" },
+ { 0x2001, "X" }, { 0x3000, "C" }, { 0x3001, "W" },
+};
+
+static const struct stm32l4_rev stm32u59_u5axx_revs[] = {
+ { 0x3001, "X" },
};
static const struct stm32l4_rev stm32wba5x_revs[] = {
@@ -419,6 +433,18 @@ static const struct stm32l4_part_info stm32l4_parts[] = {
.otp_size = 1024,
},
{
+ .id = DEVID_STM32U53_U54XX,
+ .revs = stm32u53_u54xx_revs,
+ .num_revs = ARRAY_SIZE(stm32u53_u54xx_revs),
+ .device_str = "STM32U535/U545",
+ .max_flash_size_kb = 512,
+ .flags = F_HAS_DUAL_BANK | F_QUAD_WORD_PROG | F_HAS_TZ | F_HAS_L5_FLASH_REGS,
+ .flash_regs_base = 0x40022000,
+ .fsize_addr = 0x0BFA07A0,
+ .otp_base = 0x0BFA0000,
+ .otp_size = 512,
+ },
+ {
.id = DEVID_STM32G05_G06XX,
.revs = stm32g05_g06xx_revs,
.num_revs = ARRAY_SIZE(stm32g05_g06xx_revs),
@@ -575,6 +601,18 @@ static const struct stm32l4_part_info stm32l4_parts[] = {
.otp_size = 1024,
},
{
+ .id = DEVID_STM32U59_U5AXX,
+ .revs = stm32u59_u5axx_revs,
+ .num_revs = ARRAY_SIZE(stm32u59_u5axx_revs),
+ .device_str = "STM32U59/U5Axx",
+ .max_flash_size_kb = 4096,
+ .flags = F_HAS_DUAL_BANK | F_QUAD_WORD_PROG | F_HAS_TZ | F_HAS_L5_FLASH_REGS,
+ .flash_regs_base = 0x40022000,
+ .fsize_addr = 0x0BFA07A0,
+ .otp_base = 0x0BFA0000,
+ .otp_size = 512,
+ },
+ {
.id = DEVID_STM32U57_U58XX,
.revs = stm32u57_u58xx_revs,
.num_revs = ARRAY_SIZE(stm32u57_u58xx_revs),
@@ -2000,10 +2038,22 @@ static int stm32l4_probe(struct flash_bank *bank)
stm32l4_info->bank1_sectors = num_pages / 2;
}
break;
+ case DEVID_STM32U53_U54XX:
case DEVID_STM32U57_U58XX:
- /* if flash size is max (2M) the device is always dual bank
- * otherwise check DUALBANK
+ case DEVID_STM32U59_U5AXX:
+ /* according to RM0456 Rev 4, Chapter 7.3.1 and 7.9.13
+ * U53x/U54x have 512K max flash size:
+ * 512K variants are always in DUAL BANK mode
+ * 256K and 128K variants can be in DUAL BANK mode if FLASH_OPTR:DUALBANK is set
+ * U57x/U58x have 2M max flash size:
+ * 2M variants are always in DUAL BANK mode
+ * 1M variants can be in DUAL BANK mode if FLASH_OPTR:DUALBANK is set
+ * U59x/U5Ax have 4M max flash size:
+ * 4M variants are always in DUAL BANK mode
+ * 2M variants can be in DUAL BANK mode if FLASH_OPTR:DUALBANK is set
+ * Note: flash banks are always contiguous
*/
+
page_size_kb = 8;
num_pages = flash_size_kb / page_size_kb;
stm32l4_info->bank1_sectors = num_pages;
@@ -2572,7 +2622,7 @@ static const struct command_registration stm32l4_exec_command_handlers[] = {
.name = "option_write",
.handler = stm32l4_handle_option_write_command,
.mode = COMMAND_EXEC,
- .usage = "bank_id reg_offset value mask",
+ .usage = "bank_id reg_offset value [mask]",
.help = "Write device option bit fields with provided value.",
},
{
diff --git a/src/flash/nor/stm32l4x.h b/src/flash/nor/stm32l4x.h
index 3dc0909..5f3bc26 100644
--- a/src/flash/nor/stm32l4x.h
+++ b/src/flash/nor/stm32l4x.h
@@ -89,6 +89,7 @@
#define DEVID_STM32L43_L44XX 0x435
#define DEVID_STM32C01XX 0x443
#define DEVID_STM32C03XX 0x453
+#define DEVID_STM32U53_U54XX 0x455
#define DEVID_STM32G05_G06XX 0x456
#define DEVID_STM32G07_G08XX 0x460
#define DEVID_STM32L49_L4AXX 0x461
@@ -102,6 +103,7 @@
#define DEVID_STM32L4P_L4QXX 0x471
#define DEVID_STM32L55_L56XX 0x472
#define DEVID_STM32G49_G4AXX 0x479
+#define DEVID_STM32U59_U5AXX 0x481
#define DEVID_STM32U57_U58XX 0x482
#define DEVID_STM32WBA5X 0x492
#define DEVID_STM32WB1XX 0x494
diff --git a/src/flash/nor/stmqspi.c b/src/flash/nor/stmqspi.c
index a1e1d34..df58f6c 100644
--- a/src/flash/nor/stmqspi.c
+++ b/src/flash/nor/stmqspi.c
@@ -1807,7 +1807,7 @@ err:
/* Read SFDP parameter block */
static int read_sfdp_block(struct flash_bank *bank, uint32_t addr,
- uint32_t words, uint32_t *buffer)
+ unsigned int words, uint32_t *buffer)
{
struct target *target = bank->target;
struct stmqspi_flash_bank *stmqspi_info = bank->driver_priv;
@@ -1848,7 +1848,7 @@ static int read_sfdp_block(struct flash_bank *bank, uint32_t addr,
}
}
- LOG_DEBUG("%s: addr=0x%08" PRIx32 " words=0x%08" PRIx32 " dummy=%u",
+ LOG_DEBUG("%s: addr=0x%08" PRIx32 " words=0x%08x dummy=%u",
__func__, addr, words, *dummy);
/* Abort any previous operation */
diff --git a/src/flash/startup.tcl b/src/flash/startup.tcl
index 654f201..0dd84ef 100644
--- a/src/flash/startup.tcl
+++ b/src/flash/startup.tcl
@@ -5,7 +5,7 @@
#
# program utility proc
# usage: program filename
-# optional args: verify, reset, exit and address
+# optional args: preverify, verify, reset, exit and address
#
lappend _telnet_autocomplete_skip program_error
@@ -101,8 +101,8 @@ proc program {filename args} {
return
}
-add_help_text program "write an image to flash, address is only required for binary images. verify, reset, exit are optional"
-add_usage_text program "<filename> \[address\] \[pre-verify\] \[verify\] \[reset\] \[exit\]"
+add_help_text program "write an image to flash, address is only required for binary images. preverify, verify, reset, exit are optional"
+add_usage_text program "<filename> \[address\] \[preverify\] \[verify\] \[reset\] \[exit\]"
# stm32[f0x|f3x] uses the same flash driver as the stm32f1x
proc stm32f0x args { eval stm32f1x $args }
diff --git a/src/helper/binarybuffer.c b/src/helper/binarybuffer.c
index 5f38b43..a7ca5af 100644
--- a/src/helper/binarybuffer.c
+++ b/src/helper/binarybuffer.c
@@ -57,20 +57,20 @@ void *buf_cpy(const void *from, void *_to, unsigned size)
return _to;
}
-static bool buf_cmp_masked(uint8_t a, uint8_t b, uint8_t m)
+static bool buf_eq_masked(uint8_t a, uint8_t b, uint8_t m)
{
- return (a & m) != (b & m);
+ return (a & m) == (b & m);
}
-static bool buf_cmp_trailing(uint8_t a, uint8_t b, uint8_t m, unsigned trailing)
+static bool buf_eq_trailing(uint8_t a, uint8_t b, uint8_t m, unsigned trailing)
{
uint8_t mask = (1 << trailing) - 1;
- return buf_cmp_masked(a, b, mask & m);
+ return buf_eq_masked(a, b, mask & m);
}
-bool buf_cmp(const void *_buf1, const void *_buf2, unsigned size)
+bool buf_eq(const void *_buf1, const void *_buf2, unsigned size)
{
if (!_buf1 || !_buf2)
- return _buf1 != _buf2;
+ return _buf1 == _buf2;
unsigned last = size / 8;
if (memcmp(_buf1, _buf2, last) != 0)
@@ -78,31 +78,30 @@ bool buf_cmp(const void *_buf1, const void *_buf2, unsigned size)
unsigned trailing = size % 8;
if (!trailing)
- return false;
+ return true;
const uint8_t *buf1 = _buf1, *buf2 = _buf2;
- return buf_cmp_trailing(buf1[last], buf2[last], 0xff, trailing);
+ return buf_eq_trailing(buf1[last], buf2[last], 0xff, trailing);
}
-bool buf_cmp_mask(const void *_buf1, const void *_buf2,
+bool buf_eq_mask(const void *_buf1, const void *_buf2,
const void *_mask, unsigned size)
{
if (!_buf1 || !_buf2)
- return _buf1 != _buf2 || _buf1 != _mask;
+ return _buf1 == _buf2 && _buf1 == _mask;
const uint8_t *buf1 = _buf1, *buf2 = _buf2, *mask = _mask;
unsigned last = size / 8;
for (unsigned i = 0; i < last; i++) {
- if (buf_cmp_masked(buf1[i], buf2[i], mask[i]))
- return true;
+ if (!buf_eq_masked(buf1[i], buf2[i], mask[i]))
+ return false;
}
unsigned trailing = size % 8;
if (!trailing)
- return false;
- return buf_cmp_trailing(buf1[last], buf2[last], mask[last], trailing);
+ return true;
+ return buf_eq_trailing(buf1[last], buf2[last], mask[last], trailing);
}
-
void *buf_set_ones(void *_buf, unsigned size)
{
uint8_t *buf = _buf;
@@ -176,19 +175,6 @@ uint32_t flip_u32(uint32_t value, unsigned int num)
return c;
}
-static int ceil_f_to_u32(float x)
-{
- if (x < 0) /* return zero for negative numbers */
- return 0;
-
- uint32_t y = x; /* cut off fraction */
-
- if ((x - y) > 0.0) /* if there was a fractional part, increase by one */
- y++;
-
- return y;
-}
-
char *buf_to_hex_str(const void *_buf, unsigned buf_len)
{
unsigned len_bytes = DIV_ROUND_UP(buf_len, 8);
@@ -206,94 +192,96 @@ char *buf_to_hex_str(const void *_buf, unsigned buf_len)
return str;
}
-/** identify radix, and skip radix-prefix (0, 0x or 0X) */
-static void str_radix_guess(const char **_str, unsigned *_str_len,
- unsigned *_radix)
-{
- unsigned radix = *_radix;
- if (radix != 0)
- return;
- const char *str = *_str;
- unsigned str_len = *_str_len;
- if (str[0] == '0' && (str[1] == 'x' || str[1] == 'X')) {
- radix = 16;
- str += 2;
- str_len -= 2;
- } else if ((str[0] == '0') && (str_len != 1)) {
- radix = 8;
- str += 1;
- str_len -= 1;
- } else
- radix = 10;
- *_str = str;
- *_str_len = str_len;
- *_radix = radix;
-}
-
-int str_to_buf(const char *str, unsigned str_len,
- void *_buf, unsigned buf_len, unsigned radix)
+/*
+ * TCL standard prefix is '0b', '0o', '0d' or '0x' respectively for binary,
+ * octal, decimal or hexadecimal.
+ * The prefix '0' is interpreted by TCL <= 8.6 as octal, but is ignored and
+ * interpreted as part of a decimal number by JimTCL and by TCL >= 9.
+ */
+int str_to_buf(const char *str, void *_buf, unsigned int buf_bitsize)
{
- str_radix_guess(&str, &str_len, &radix);
-
- float factor;
- if (radix == 16)
- factor = 0.5; /* log(16) / log(256) = 0.5 */
- else if (radix == 10)
- factor = 0.41524; /* log(10) / log(256) = 0.41524 */
- else if (radix == 8)
- factor = 0.375; /* log(8) / log(256) = 0.375 */
- else
- return 0;
+ assert(str);
+ assert(_buf);
+ assert(buf_bitsize > 0);
- /* copy to zero-terminated buffer */
- char *charbuf = strndup(str, str_len);
-
- /* number of digits in base-256 notation */
- unsigned b256_len = ceil_f_to_u32(str_len * factor);
- uint8_t *b256_buf = calloc(b256_len, 1);
+ uint8_t *buf = _buf;
+ unsigned int radix = 10; /* default when no prefix */
+
+ if (str[0] == '0') {
+ switch (str[1]) {
+ case 'b':
+ case 'B':
+ radix = 2;
+ str += 2;
+ break;
+ case 'o':
+ case 'O':
+ radix = 8;
+ str += 2;
+ break;
+ case 'd':
+ case 'D':
+ radix = 10;
+ str += 2;
+ break;
+ case 'x':
+ case 'X':
+ radix = 16;
+ str += 2;
+ break;
+ default:
+ break;
+ }
+ }
- /* go through zero terminated buffer
- * input digits (ASCII) */
- unsigned i;
- for (i = 0; charbuf[i]; i++) {
- uint32_t tmp = charbuf[i];
- if ((tmp >= '0') && (tmp <= '9'))
- tmp = (tmp - '0');
- else if ((tmp >= 'a') && (tmp <= 'f'))
- tmp = (tmp - 'a' + 10);
- else if ((tmp >= 'A') && (tmp <= 'F'))
- tmp = (tmp - 'A' + 10);
- else
- continue; /* skip characters other than [0-9,a-f,A-F] */
+ const size_t str_len = strlen(str);
+ if (str_len == 0)
+ return ERROR_INVALID_NUMBER;
+
+ const size_t buf_len = DIV_ROUND_UP(buf_bitsize, 8);
+ memset(buf, 0, buf_len);
+
+ /* Go through the zero-terminated buffer
+ * of input digits (ASCII) */
+ for (; *str; str++) {
+ unsigned int tmp;
+ const char c = *str;
+
+ if ((c >= '0') && (c <= '9')) {
+ tmp = c - '0';
+ } else if ((c >= 'a') && (c <= 'f')) {
+ tmp = c - 'a' + 10;
+ } else if ((c >= 'A') && (c <= 'F')) {
+ tmp = c - 'A' + 10;
+ } else {
+ /* Characters other than [0-9,a-f,A-F] are invalid */
+ return ERROR_INVALID_NUMBER;
+ }
+ /* Error on invalid digit for current radix */
if (tmp >= radix)
- continue; /* skip digits invalid for the current radix */
+ return ERROR_INVALID_NUMBER;
- /* base-256 digits */
- for (unsigned j = 0; j < b256_len; j++) {
- tmp += (uint32_t)b256_buf[j] * radix;
- b256_buf[j] = (uint8_t)(tmp & 0xFF);
+ /* Add the current digit (tmp) to the intermediate result in buf */
+ for (unsigned int j = 0; j < buf_len; j++) {
+ tmp += buf[j] * radix;
+ buf[j] = tmp & 0xFFu;
tmp >>= 8;
}
+ /* buf should be large enough to contain the whole result. */
+ if (tmp != 0)
+ return ERROR_NUMBER_EXCEEDS_BUFFER;
}
- uint8_t *buf = _buf;
- for (unsigned j = 0; j < DIV_ROUND_UP(buf_len, 8); j++) {
- if (j < b256_len)
- buf[j] = b256_buf[j];
- else
- buf[j] = 0;
+ /* Check the partial most significant byte */
+ if (buf_bitsize % 8) {
+ const uint8_t mask = 0xFFu << (buf_bitsize % 8);
+ if ((buf[buf_len - 1] & mask) != 0x0)
+ return ERROR_NUMBER_EXCEEDS_BUFFER;
}
- /* mask out bits that don't belong to the buffer */
- if (buf_len % 8)
- buf[(buf_len / 8)] &= 0xff >> (8 - (buf_len % 8));
-
- free(b256_buf);
- free(charbuf);
-
- return i;
+ return ERROR_OK;
}
void bit_copy_queue_init(struct bit_copy_queue *q)
diff --git a/src/helper/binarybuffer.h b/src/helper/binarybuffer.h
index 3446296..ed13b98 100644
--- a/src/helper/binarybuffer.h
+++ b/src/helper/binarybuffer.h
@@ -14,6 +14,9 @@
#include <helper/list.h>
#include <helper/types.h>
+#define ERROR_INVALID_NUMBER (-1700)
+#define ERROR_NUMBER_EXCEEDS_BUFFER (-1701)
+
/** @file
* Support functions to access arbitrary bits in a byte array
*/
@@ -31,6 +34,7 @@
static inline void buf_set_u32(uint8_t *_buffer,
unsigned first, unsigned num, uint32_t value)
{
+ assert(num >= 1 && num <= 32);
uint8_t *buffer = _buffer;
if ((num == 32) && (first == 0)) {
@@ -61,6 +65,7 @@ static inline void buf_set_u32(uint8_t *_buffer,
static inline void buf_set_u64(uint8_t *_buffer,
unsigned first, unsigned num, uint64_t value)
{
+ assert(num >= 1 && num <= 64);
uint8_t *buffer = _buffer;
if ((num == 32) && (first == 0)) {
@@ -99,6 +104,7 @@ static inline void buf_set_u64(uint8_t *_buffer,
static inline uint32_t buf_get_u32(const uint8_t *_buffer,
unsigned first, unsigned num)
{
+ assert(num >= 1 && num <= 32);
const uint8_t *buffer = _buffer;
if ((num == 32) && (first == 0)) {
@@ -128,6 +134,7 @@ static inline uint32_t buf_get_u32(const uint8_t *_buffer,
static inline uint64_t buf_get_u64(const uint8_t *_buffer,
unsigned first, unsigned num)
{
+ assert(num >= 1 && num <= 64);
const uint8_t *buffer = _buffer;
if ((num == 32) && (first == 0)) {
@@ -165,8 +172,8 @@ static inline uint64_t buf_get_u64(const uint8_t *_buffer,
*/
uint32_t flip_u32(uint32_t value, unsigned width);
-bool buf_cmp(const void *buf1, const void *buf2, unsigned size);
-bool buf_cmp_mask(const void *buf1, const void *buf2,
+bool buf_eq(const void *buf1, const void *buf2, unsigned size);
+bool buf_eq_mask(const void *buf1, const void *buf2,
const void *mask, unsigned size);
/**
@@ -189,8 +196,17 @@ void *buf_set_ones(void *buf, unsigned size);
void *buf_set_buf(const void *src, unsigned src_start,
void *dst, unsigned dst_start, unsigned len);
-int str_to_buf(const char *str, unsigned len,
- void *bin_buf, unsigned buf_size, unsigned radix);
+/**
+ * Parse an unsigned number (provided as a zero-terminated string)
+ * into a bit buffer whose size is buf_len bits. The base of the
+ * number is detected between decimal, hexadecimal and octal.
+ * @param str Input number, zero-terminated string
+ * @param _buf Output buffer, allocated by the caller
+ * @param buf_bitsize Output buffer size in bits
+ * @returns Error on invalid or overflowing number
+ */
+int str_to_buf(const char *str, void *_buf, unsigned int buf_bitsize);
+
char *buf_to_hex_str(const void *buf, unsigned size);
/* read a uint32_t from a buffer in target memory endianness */
diff --git a/src/helper/command.c b/src/helper/command.c
index a775c73..9078693 100644
--- a/src/helper/command.c
+++ b/src/helper/command.c
@@ -1360,6 +1360,27 @@ int command_parse_bool_arg(const char *in, bool *out)
return ERROR_COMMAND_SYNTAX_ERROR;
}
+COMMAND_HELPER(command_parse_str_to_buf, const char *str, void *buf, unsigned int buf_len)
+{
+ assert(str);
+ assert(buf);
+
+ int ret = str_to_buf(str, buf, buf_len);
+ if (ret == ERROR_OK)
+ return ret;
+
+ /* Provide a clear error message to the user */
+ if (ret == ERROR_INVALID_NUMBER) {
+ command_print(CMD, "'%s' is not a valid number", str);
+ } else if (ret == ERROR_NUMBER_EXCEEDS_BUFFER) {
+ command_print(CMD, "Number %s exceeds %u bits", str, buf_len);
+ } else {
+ command_print(CMD, "Could not parse number '%s'", str);
+ }
+
+ return ERROR_COMMAND_ARGUMENT_INVALID;
+}
+
COMMAND_HELPER(handle_command_parse_bool, bool *out, const char *label)
{
switch (CMD_ARGC) {
diff --git a/src/helper/command.h b/src/helper/command.h
index fc26dda..b224bd0 100644
--- a/src/helper/command.h
+++ b/src/helper/command.h
@@ -517,6 +517,15 @@ DECLARE_PARSE_WRAPPER(_target_addr, target_addr_t);
int command_parse_bool_arg(const char *in, bool *out);
COMMAND_HELPER(handle_command_parse_bool, bool *out, const char *label);
+/**
+ * Parse a number (base 10, base 16 or base 8) and store the result
+ * into a bit buffer. Use the prefixes '0' and '0x' for base 8 and 16,
+ * otherwise defaults to base 10.
+ *
+ * In case of parsing error, a user-readable error message is produced.
+ */
+COMMAND_HELPER(command_parse_str_to_buf, const char *str, void *buf, unsigned int buf_len);
+
/** parses an on/off command argument */
#define COMMAND_PARSE_ON_OFF(in, out) \
COMMAND_PARSE_BOOL(in, out, "on", "off")
diff --git a/src/helper/jep106.inc b/src/helper/jep106.inc
index 958dc4e..b74cda8 100644
--- a/src/helper/jep106.inc
+++ b/src/helper/jep106.inc
@@ -8,9 +8,7 @@
* identification code list, please visit the JEDEC website at www.jedec.org .
*/
-/* This file is aligned to revision JEP106BI January 2024. */
-
-/* "NXP (Philips)" is reported below, while missing since JEP106BG */
+/* This file is aligned to revision JEP106BJ.01 July 2024. */
[0][0x01 - 1] = "AMD",
[0][0x02 - 1] = "AMI",
@@ -30,7 +28,7 @@
[0][0x10 - 1] = "NEC",
[0][0x11 - 1] = "RCA",
[0][0x12 - 1] = "Raytheon",
-[0][0x13 - 1] = "Conexant (Rockwell)",
+[0][0x13 - 1] = "Synaptics",
[0][0x14 - 1] = "Seeq",
[0][0x15 - 1] = "NXP (Philips)",
[0][0x16 - 1] = "Synertek",
@@ -1045,7 +1043,7 @@
[8][0x17 - 1] = "Axell Corporation",
[8][0x18 - 1] = "Essencore Limited",
[8][0x19 - 1] = "Phytium",
-[8][0x1a - 1] = "Xi'an UniIC Semiconductors Co Ltd",
+[8][0x1a - 1] = "UniIC Semiconductors Co Ltd",
[8][0x1b - 1] = "Ambiq Micro",
[8][0x1c - 1] = "eveRAM Technology Inc",
[8][0x1d - 1] = "Infomax",
@@ -1452,7 +1450,7 @@
[11][0x34 - 1] = "Acacia Communications",
[11][0x35 - 1] = "Beijinjinshengyihe Technology Co Ltd",
[11][0x36 - 1] = "Zyzyx",
-[11][0x37 - 1] = "T-HEAD Semiconductor Co Ltd",
+[11][0x37 - 1] = "C-SKY Microsystems Co Ltd",
[11][0x38 - 1] = "Shenzhen Hystou Technology Co Ltd",
[11][0x39 - 1] = "Syzexion",
[11][0x3a - 1] = "Kembona",
@@ -1938,4 +1936,31 @@
[15][0x22 - 1] = "SkyeChip",
[15][0x23 - 1] = "Guangzhou Kaishile Trading Co Ltd",
[15][0x24 - 1] = "Jing Pai Digital Technology (Shenzhen) Co",
+[15][0x25 - 1] = "Memoritek",
+[15][0x26 - 1] = "Zhejiang Hikstor Technology Co Ltd",
+[15][0x27 - 1] = "Memoritek PTE Ltd",
+[15][0x28 - 1] = "Longsailing Semiconductor Co Ltd",
+[15][0x29 - 1] = "LX Semicon",
+[15][0x2a - 1] = "Shenzhen Techwinsemi Technology Co Ltd",
+[15][0x2b - 1] = "AOC",
+[15][0x2c - 1] = "GOEPEL Electronic GmbH",
+[15][0x2d - 1] = "Shenzhen G-Bong Technology Co Ltd",
+[15][0x2e - 1] = "Openedges Technology Inc",
+[15][0x2f - 1] = "EA Semi Shangahi Limited",
+[15][0x30 - 1] = "EMBCORF",
+[15][0x31 - 1] = "Shenzhen MicroBT Electronics Technology",
+[15][0x32 - 1] = "Shanghai Simor Chip Semiconductor Co",
+[15][0x33 - 1] = "Xllbyte",
+[15][0x34 - 1] = "Guangzhou Maidite Electronics Co Ltd.",
+[15][0x35 - 1] = "Zhejiang Changchun Technology Co Ltd",
+[15][0x36 - 1] = "Beijing Cloud Security Technology Co Ltd",
+[15][0x37 - 1] = "SSTC Technology and Distribution Inc",
+[15][0x38 - 1] = "Shenzhen Panmin Technology Co Ltd",
+[15][0x39 - 1] = "ITE Tech Inc",
+[15][0x3a - 1] = "Beijing Zettastone Technology Co Ltd",
+[15][0x3b - 1] = "Powerchip Micro Device",
+[15][0x3c - 1] = "Shenzhen Ysemi Computing Co Ltd",
+[15][0x3d - 1] = "Shenzhen Titan Micro Electronics Co Ltd",
+[15][0x3e - 1] = "Shenzhen Macroflash Technology Co Ltd",
+[15][0x3f - 1] = "Advantech Group",
/* EOF */
diff --git a/src/jtag/commands.c b/src/jtag/commands.c
index a60684c..1bca4e8 100644
--- a/src/jtag/commands.c
+++ b/src/jtag/commands.c
@@ -166,10 +166,9 @@ void jtag_scan_field_clone(struct scan_field *dst, const struct scan_field *src)
enum scan_type jtag_scan_type(const struct scan_command *cmd)
{
- int i;
int type = 0;
- for (i = 0; i < cmd->num_fields; i++) {
+ for (unsigned int i = 0; i < cmd->num_fields; i++) {
if (cmd->fields[i].in_value)
type |= SCAN_IN;
if (cmd->fields[i].out_value)
@@ -179,13 +178,12 @@ enum scan_type jtag_scan_type(const struct scan_command *cmd)
return type;
}
-int jtag_scan_size(const struct scan_command *cmd)
+unsigned int jtag_scan_size(const struct scan_command *cmd)
{
- int bit_count = 0;
- int i;
+ unsigned int bit_count = 0;
/* count bits in scan command */
- for (i = 0; i < cmd->num_fields; i++)
+ for (unsigned int i = 0; i < cmd->num_fields; i++)
bit_count += cmd->fields[i].num_bits;
return bit_count;
@@ -193,19 +191,16 @@ int jtag_scan_size(const struct scan_command *cmd)
int jtag_build_buffer(const struct scan_command *cmd, uint8_t **buffer)
{
- int bit_count = 0;
- int i;
-
- bit_count = jtag_scan_size(cmd);
+ unsigned int bit_count = jtag_scan_size(cmd);
*buffer = calloc(1, DIV_ROUND_UP(bit_count, 8));
bit_count = 0;
- LOG_DEBUG_IO("%s num_fields: %i",
+ LOG_DEBUG_IO("%s num_fields: %u",
cmd->ir_scan ? "IRSCAN" : "DRSCAN",
cmd->num_fields);
- for (i = 0; i < cmd->num_fields; i++) {
+ for (unsigned int i = 0; i < cmd->num_fields; i++) {
if (cmd->fields[i].out_value) {
if (LOG_LEVEL_IS(LOG_LVL_DEBUG_IO)) {
char *char_buf = buf_to_hex_str(cmd->fields[i].out_value,
@@ -213,14 +208,14 @@ int jtag_build_buffer(const struct scan_command *cmd, uint8_t **buffer)
? DEBUG_JTAG_IOZ
: cmd->fields[i].num_bits);
- LOG_DEBUG("fields[%i].out_value[%i]: 0x%s", i,
+ LOG_DEBUG("fields[%u].out_value[%u]: 0x%s", i,
cmd->fields[i].num_bits, char_buf);
free(char_buf);
}
buf_set_buf(cmd->fields[i].out_value, 0, *buffer,
bit_count, cmd->fields[i].num_bits);
} else {
- LOG_DEBUG_IO("fields[%i].out_value[%i]: NULL",
+ LOG_DEBUG_IO("fields[%u].out_value[%u]: NULL",
i, cmd->fields[i].num_bits);
}
@@ -234,19 +229,18 @@ int jtag_build_buffer(const struct scan_command *cmd, uint8_t **buffer)
int jtag_read_buffer(uint8_t *buffer, const struct scan_command *cmd)
{
- int i;
int bit_count = 0;
int retval;
/* we return ERROR_OK, unless a check fails, or a handler reports a problem */
retval = ERROR_OK;
- for (i = 0; i < cmd->num_fields; i++) {
+ for (unsigned int i = 0; i < cmd->num_fields; i++) {
/* if neither in_value nor in_handler
* are specified we don't have to examine this field
*/
if (cmd->fields[i].in_value) {
- int num_bits = cmd->fields[i].num_bits;
+ const unsigned int num_bits = cmd->fields[i].num_bits;
uint8_t *captured = buf_set_buf(buffer, bit_count,
malloc(DIV_ROUND_UP(num_bits, 8)), 0, num_bits);
@@ -256,7 +250,7 @@ int jtag_read_buffer(uint8_t *buffer, const struct scan_command *cmd)
? DEBUG_JTAG_IOZ
: num_bits);
- LOG_DEBUG("fields[%i].in_value[%i]: 0x%s",
+ LOG_DEBUG("fields[%u].in_value[%u]: 0x%s",
i, num_bits, char_buf);
free(char_buf);
}
diff --git a/src/jtag/commands.h b/src/jtag/commands.h
index 8259077..29fa842 100644
--- a/src/jtag/commands.h
+++ b/src/jtag/commands.h
@@ -36,7 +36,7 @@ struct scan_command {
/** instruction/not data scan */
bool ir_scan;
/** number of fields in *fields array */
- int num_fields;
+ unsigned int num_fields;
/** pointer to an array of data scan fields */
struct scan_field *fields;
/** state in which JTAG commands should finish */
@@ -50,14 +50,14 @@ struct statemove_command {
struct pathmove_command {
/** number of states in *path */
- int num_states;
+ unsigned int num_states;
/** states that have to be passed */
tap_state_t *path;
};
struct runtest_command {
/** number of cycles to spend in Run-Test/Idle state */
- int num_cycles;
+ unsigned int num_cycles;
/** state in which JTAG commands should finish */
tap_state_t end_state;
};
@@ -65,7 +65,7 @@ struct runtest_command {
struct stableclocks_command {
/** number of clock cycles that should be sent */
- int num_cycles;
+ unsigned int num_cycles;
};
@@ -100,7 +100,7 @@ struct sleep_command {
*/
struct tms_command {
/** How many bits should be clocked out. */
- unsigned num_bits;
+ unsigned int num_bits;
/** The bits to clock out; the LSB is bit 0 of bits[0]. */
const uint8_t *bits;
};
@@ -157,7 +157,7 @@ struct jtag_command *jtag_command_queue_get(void);
void jtag_scan_field_clone(struct scan_field *dst, const struct scan_field *src);
enum scan_type jtag_scan_type(const struct scan_command *cmd);
-int jtag_scan_size(const struct scan_command *cmd);
+unsigned int jtag_scan_size(const struct scan_command *cmd);
int jtag_read_buffer(uint8_t *buffer, const struct scan_command *cmd);
int jtag_build_buffer(const struct scan_command *cmd, uint8_t **buffer);
diff --git a/src/jtag/core.c b/src/jtag/core.c
index c84d5aa..a6f38a1 100644
--- a/src/jtag/core.c
+++ b/src/jtag/core.c
@@ -39,7 +39,7 @@
#include "server/ipdbg.h"
/** The number of JTAG queue flushes (for profiling and debugging purposes). */
-static int jtag_flush_queue_count;
+static unsigned int jtag_flush_queue_count;
/* Sleep this # of ms after flushing the queue */
static int jtag_flush_queue_sleep;
@@ -88,14 +88,14 @@ static enum reset_types jtag_reset_config = RESET_NONE;
tap_state_t cmd_queue_cur_state = TAP_RESET;
static bool jtag_verify_capture_ir = true;
-static int jtag_verify = 1;
+static bool jtag_verify = true;
/* how long the OpenOCD should wait before attempting JTAG communication after reset lines
*deasserted (in ms) */
-static int adapter_nsrst_delay; /* default to no nSRST delay */
-static int jtag_ntrst_delay;/* default to no nTRST delay */
-static int adapter_nsrst_assert_width; /* width of assertion */
-static int jtag_ntrst_assert_width; /* width of assertion */
+static unsigned int adapter_nsrst_delay; /* default to no nSRST delay */
+static unsigned int jtag_ntrst_delay;/* default to no nTRST delay */
+static unsigned int adapter_nsrst_assert_width; /* width of assertion */
+static unsigned int jtag_ntrst_assert_width; /* width of assertion */
/**
* Contains a single callback along with a pointer that will be passed
@@ -186,10 +186,10 @@ struct jtag_tap *jtag_all_taps(void)
return __jtag_all_taps;
};
-unsigned jtag_tap_count(void)
+unsigned int jtag_tap_count(void)
{
struct jtag_tap *t = jtag_all_taps();
- unsigned n = 0;
+ unsigned int n = 0;
while (t) {
n++;
t = t->next_tap;
@@ -197,10 +197,10 @@ unsigned jtag_tap_count(void)
return n;
}
-unsigned jtag_tap_count_enabled(void)
+unsigned int jtag_tap_count_enabled(void)
{
struct jtag_tap *t = jtag_all_taps();
- unsigned n = 0;
+ unsigned int n = 0;
while (t) {
if (t->enabled)
n++;
@@ -212,7 +212,7 @@ unsigned jtag_tap_count_enabled(void)
/** Append a new TAP to the chain of all taps. */
static void jtag_tap_add(struct jtag_tap *t)
{
- unsigned jtag_num_taps = 0;
+ unsigned int jtag_num_taps = 0;
struct jtag_tap **tap = &__jtag_all_taps;
while (*tap) {
@@ -499,7 +499,7 @@ void jtag_add_tlr(void)
*
* @todo Update naming conventions to stop assuming everything is JTAG.
*/
-int jtag_add_tms_seq(unsigned nbits, const uint8_t *seq, enum tap_state state)
+int jtag_add_tms_seq(unsigned int nbits, const uint8_t *seq, enum tap_state state)
{
int retval;
@@ -514,7 +514,7 @@ int jtag_add_tms_seq(unsigned nbits, const uint8_t *seq, enum tap_state state)
return retval;
}
-void jtag_add_pathmove(int num_states, const tap_state_t *path)
+void jtag_add_pathmove(unsigned int num_states, const tap_state_t *path)
{
tap_state_t cur_state = cmd_queue_cur_state;
@@ -525,7 +525,7 @@ void jtag_add_pathmove(int num_states, const tap_state_t *path)
return;
}
- for (int i = 0; i < num_states; i++) {
+ for (unsigned int i = 0; i < num_states; i++) {
if (path[i] == TAP_RESET) {
LOG_ERROR("BUG: TAP_RESET is not a valid state for pathmove sequences");
jtag_set_error(ERROR_JTAG_STATE_INVALID);
@@ -567,12 +567,12 @@ int jtag_add_statemove(tap_state_t goal_state)
/* nothing to do */;
else if (tap_is_state_stable(cur_state) && tap_is_state_stable(goal_state)) {
- unsigned tms_bits = tap_get_tms_path(cur_state, goal_state);
- unsigned tms_count = tap_get_tms_path_len(cur_state, goal_state);
+ unsigned int tms_bits = tap_get_tms_path(cur_state, goal_state);
+ unsigned int tms_count = tap_get_tms_path_len(cur_state, goal_state);
tap_state_t moves[8];
assert(tms_count < ARRAY_SIZE(moves));
- for (unsigned i = 0; i < tms_count; i++, tms_bits >>= 1) {
+ for (unsigned int i = 0; i < tms_count; i++, tms_bits >>= 1) {
bool bit = tms_bits & 1;
cur_state = tap_state_transition(cur_state, bit);
@@ -589,14 +589,14 @@ int jtag_add_statemove(tap_state_t goal_state)
return ERROR_OK;
}
-void jtag_add_runtest(int num_cycles, tap_state_t state)
+void jtag_add_runtest(unsigned int num_cycles, tap_state_t state)
{
jtag_prelude(state);
jtag_set_error(interface_jtag_add_runtest(num_cycles, state));
}
-void jtag_add_clocks(int num_cycles)
+void jtag_add_clocks(unsigned int num_cycles)
{
if (!tap_is_state_stable(cmd_queue_cur_state)) {
LOG_ERROR("jtag_add_clocks() called with TAP in unstable state \"%s\"",
@@ -881,9 +881,9 @@ static int jtag_check_value_inner(uint8_t *captured, uint8_t *in_check_value,
int compare_failed;
if (in_check_mask)
- compare_failed = buf_cmp_mask(captured, in_check_value, in_check_mask, num_bits);
+ compare_failed = !buf_eq_mask(captured, in_check_value, in_check_mask, num_bits);
else
- compare_failed = buf_cmp(captured, in_check_value, num_bits);
+ compare_failed = !buf_eq(captured, in_check_value, num_bits);
if (compare_failed) {
char *captured_str, *in_check_value_str;
@@ -960,16 +960,16 @@ int default_interface_jtag_execute_queue(void)
LOG_DEBUG_IO("JTAG %s SCAN to %s",
cmd->cmd.scan->ir_scan ? "IR" : "DR",
tap_state_name(cmd->cmd.scan->end_state));
- for (int i = 0; i < cmd->cmd.scan->num_fields; i++) {
+ for (unsigned int i = 0; i < cmd->cmd.scan->num_fields; i++) {
struct scan_field *field = cmd->cmd.scan->fields + i;
if (field->out_value) {
char *str = buf_to_hex_str(field->out_value, field->num_bits);
- LOG_DEBUG_IO(" %db out: %s", field->num_bits, str);
+ LOG_DEBUG_IO(" %ub out: %s", field->num_bits, str);
free(str);
}
if (field->in_value) {
char *str = buf_to_hex_str(field->in_value, field->num_bits);
- LOG_DEBUG_IO(" %db in: %s", field->num_bits, str);
+ LOG_DEBUG_IO(" %ub in: %s", field->num_bits, str);
free(str);
}
}
@@ -1029,7 +1029,7 @@ void jtag_execute_queue_noclear(void)
}
}
-int jtag_get_flush_queue_count(void)
+unsigned int jtag_get_flush_queue_count(void)
{
return jtag_flush_queue_count;
}
@@ -1081,7 +1081,7 @@ void jtag_sleep(uint32_t us)
/* a larger IR length than we ever expect to autoprobe */
#define JTAG_IRLEN_MAX 60
-static int jtag_examine_chain_execute(uint8_t *idcode_buffer, unsigned num_idcode)
+static int jtag_examine_chain_execute(uint8_t *idcode_buffer, unsigned int num_idcode)
{
struct scan_field field = {
.num_bits = num_idcode * 32,
@@ -1090,7 +1090,7 @@ static int jtag_examine_chain_execute(uint8_t *idcode_buffer, unsigned num_idcod
};
/* initialize to the end of chain ID value */
- for (unsigned i = 0; i < num_idcode; i++)
+ for (unsigned int i = 0; i < num_idcode; i++)
buf_set_u32(idcode_buffer, i * 32, 32, END_OF_CHAIN_FLAG);
jtag_add_plain_dr_scan(field.num_bits, field.out_value, field.in_value, TAP_DRPAUSE);
@@ -1098,12 +1098,12 @@ static int jtag_examine_chain_execute(uint8_t *idcode_buffer, unsigned num_idcod
return jtag_execute_queue();
}
-static bool jtag_examine_chain_check(uint8_t *idcodes, unsigned count)
+static bool jtag_examine_chain_check(uint8_t *idcodes, unsigned int count)
{
uint8_t zero_check = 0x0;
uint8_t one_check = 0xff;
- for (unsigned i = 0; i < count * 4; i++) {
+ for (unsigned int i = 0; i < count * 4; i++) {
zero_check |= idcodes[i];
one_check &= idcodes[i];
}
@@ -1158,7 +1158,8 @@ static bool jtag_idcode_is_final(uint32_t idcode)
* with the JTAG chain earlier, gives more helpful/explicit error messages.
* Returns TRUE iff garbage was found.
*/
-static bool jtag_examine_chain_end(uint8_t *idcodes, unsigned count, unsigned max)
+static bool jtag_examine_chain_end(uint8_t *idcodes, unsigned int count,
+ unsigned int max)
{
bool triggered = false;
for (; count < max - 31; count += 32) {
@@ -1185,26 +1186,26 @@ static bool jtag_examine_chain_match_tap(const struct jtag_tap *tap)
uint32_t idcode = tap->idcode & mask;
/* Loop over the expected identification codes and test for a match */
- for (unsigned ii = 0; ii < tap->expected_ids_cnt; ii++) {
- uint32_t expected = tap->expected_ids[ii] & mask;
+ for (unsigned int i = 0; i < tap->expected_ids_cnt; i++) {
+ uint32_t expected = tap->expected_ids[i] & mask;
if (idcode == expected)
return true;
/* treat "-expected-id 0" as a "don't-warn" wildcard */
- if (tap->expected_ids[ii] == 0)
+ if (tap->expected_ids[i] == 0)
return true;
}
/* If none of the expected ids matched, warn */
jtag_examine_chain_display(LOG_LVL_WARNING, "UNEXPECTED",
tap->dotted_name, tap->idcode);
- for (unsigned ii = 0; ii < tap->expected_ids_cnt; ii++) {
+ for (unsigned int i = 0; i < tap->expected_ids_cnt; i++) {
char msg[32];
- snprintf(msg, sizeof(msg), "expected %u of %u", ii + 1, tap->expected_ids_cnt);
+ snprintf(msg, sizeof(msg), "expected %u of %u", i + 1, tap->expected_ids_cnt);
jtag_examine_chain_display(LOG_LVL_ERROR, msg,
- tap->dotted_name, tap->expected_ids[ii]);
+ tap->dotted_name, tap->expected_ids[i]);
}
return false;
}
@@ -1215,7 +1216,7 @@ static bool jtag_examine_chain_match_tap(const struct jtag_tap *tap)
static int jtag_examine_chain(void)
{
int retval;
- unsigned max_taps = jtag_tap_count();
+ unsigned int max_taps = jtag_tap_count();
/* Autoprobe up to this many. */
if (max_taps < JTAG_MAX_AUTO_TAPS)
@@ -1243,9 +1244,9 @@ static int jtag_examine_chain(void)
/* Point at the 1st predefined tap, if any */
struct jtag_tap *tap = jtag_tap_next_enabled(NULL);
- unsigned bit_count = 0;
- unsigned autocount = 0;
- for (unsigned i = 0; i < max_taps; i++) {
+ unsigned int bit_count = 0;
+ unsigned int autocount = 0;
+ for (unsigned int i = 0; i < max_taps; i++) {
assert(bit_count < max_taps * 32);
uint32_t idcode = buf_get_u32(idcode_buffer, bit_count, 32);
@@ -1337,7 +1338,7 @@ static int jtag_validate_ircapture(void)
int retval;
/* when autoprobing, accommodate huge IR lengths */
- int total_ir_length = 0;
+ unsigned int total_ir_length = 0;
for (tap = jtag_tap_next_enabled(NULL); tap; tap = jtag_tap_next_enabled(tap)) {
if (tap->ir_length == 0)
total_ir_length += JTAG_IRLEN_MAX;
@@ -1396,7 +1397,7 @@ static int jtag_validate_ircapture(void)
&& tap->ir_length < JTAG_IRLEN_MAX) {
tap->ir_length++;
}
- LOG_WARNING("AUTO %s - use \"jtag newtap %s %s -irlen %d "
+ LOG_WARNING("AUTO %s - use \"jtag newtap %s %s -irlen %u "
"-expected-id 0x%08" PRIx32 "\"",
tap->dotted_name, tap->chip, tap->tapname, tap->ir_length, tap->idcode);
}
@@ -1445,8 +1446,8 @@ done:
void jtag_tap_init(struct jtag_tap *tap)
{
- unsigned ir_len_bits;
- unsigned ir_len_bytes;
+ unsigned int ir_len_bits;
+ unsigned int ir_len_bytes;
/* if we're autoprobing, cope with potentially huge ir_length */
ir_len_bits = tap->ir_length ? tap->ir_length : JTAG_IRLEN_MAX;
@@ -1471,8 +1472,8 @@ void jtag_tap_init(struct jtag_tap *tap)
jtag_register_event_callback(&jtag_reset_callback, tap);
jtag_tap_add(tap);
- LOG_DEBUG("Created Tap: %s @ abs position %d, "
- "irlen %d, capture: 0x%x mask: 0x%x", tap->dotted_name,
+ LOG_DEBUG("Created Tap: %s @ abs position %u, "
+ "irlen %u, capture: 0x%x mask: 0x%x", tap->dotted_name,
tap->abs_chain_position, tap->ir_length,
(unsigned) tap->ir_capture_value,
(unsigned) tap->ir_capture_mask);
@@ -1749,37 +1750,36 @@ int jtag_get_srst(void)
return jtag_srst == 1;
}
-void jtag_set_nsrst_delay(unsigned delay)
+void jtag_set_nsrst_delay(unsigned int delay)
{
adapter_nsrst_delay = delay;
}
-unsigned jtag_get_nsrst_delay(void)
+unsigned int jtag_get_nsrst_delay(void)
{
return adapter_nsrst_delay;
}
-void jtag_set_ntrst_delay(unsigned delay)
+void jtag_set_ntrst_delay(unsigned int delay)
{
jtag_ntrst_delay = delay;
}
-unsigned jtag_get_ntrst_delay(void)
+unsigned int jtag_get_ntrst_delay(void)
{
return jtag_ntrst_delay;
}
-
-void jtag_set_nsrst_assert_width(unsigned delay)
+void jtag_set_nsrst_assert_width(unsigned int delay)
{
adapter_nsrst_assert_width = delay;
}
-unsigned jtag_get_nsrst_assert_width(void)
+unsigned int jtag_get_nsrst_assert_width(void)
{
return adapter_nsrst_assert_width;
}
-void jtag_set_ntrst_assert_width(unsigned delay)
+void jtag_set_ntrst_assert_width(unsigned int delay)
{
jtag_ntrst_assert_width = delay;
}
-unsigned jtag_get_ntrst_assert_width(void)
+unsigned int jtag_get_ntrst_assert_width(void)
{
return jtag_ntrst_assert_width;
}
diff --git a/src/jtag/drivers/amt_jtagaccel.c b/src/jtag/drivers/amt_jtagaccel.c
index b28ce62..489cb24 100644
--- a/src/jtag/drivers/amt_jtagaccel.c
+++ b/src/jtag/drivers/amt_jtagaccel.c
@@ -203,7 +203,7 @@ static void amt_jtagaccel_state_move(void)
tap_set_state(end_state);
}
-static void amt_jtagaccel_runtest(int num_cycles)
+static void amt_jtagaccel_runtest(unsigned int num_cycles)
{
int i = 0;
uint8_t aw_scan_tms_5;
diff --git a/src/jtag/drivers/angie.c b/src/jtag/drivers/angie.c
index 81dd1af..47628fe 100644
--- a/src/jtag/drivers/angie.c
+++ b/src/jtag/drivers/angie.c
@@ -1836,15 +1836,17 @@ static int angie_reset(int trst, int srst)
*/
static int angie_queue_pathmove(struct angie *device, struct jtag_command *cmd)
{
- int ret, i, num_states, batch_size, state_count;
+ int ret, state_count;
tap_state_t *path;
uint8_t tms_sequence;
- num_states = cmd->cmd.pathmove->num_states;
+ unsigned int num_states = cmd->cmd.pathmove->num_states;
path = cmd->cmd.pathmove->path;
state_count = 0;
while (num_states > 0) {
+ unsigned int batch_size;
+
tms_sequence = 0;
/* Determine batch size */
@@ -1853,7 +1855,7 @@ static int angie_queue_pathmove(struct angie *device, struct jtag_command *cmd)
else
batch_size = num_states;
- for (i = 0; i < batch_size; i++) {
+ for (unsigned int i = 0; i < batch_size; i++) {
if (tap_state_transition(tap_get_state(), false) == path[state_count]) {
/* Append '0' transition: clear bit 'i' in tms_sequence */
buf_set_u32(&tms_sequence, i, 1, 0x0);
@@ -1908,14 +1910,13 @@ static int angie_queue_sleep(struct angie *device, struct jtag_command *cmd)
static int angie_queue_stableclocks(struct angie *device, struct jtag_command *cmd)
{
int ret;
- unsigned int num_cycles;
if (!tap_is_state_stable(tap_get_state())) {
LOG_ERROR("JTAG_STABLECLOCKS: state not stable");
return ERROR_FAIL;
}
- num_cycles = cmd->cmd.stableclocks->num_cycles;
+ unsigned int num_cycles = cmd->cmd.stableclocks->num_cycles;
/* TMS stays either high (Test Logic Reset state) or low (all other states) */
if (tap_get_state() == TAP_RESET)
diff --git a/src/jtag/drivers/arm-jtag-ew.c b/src/jtag/drivers/arm-jtag-ew.c
index 4c50c54..aaed16d 100644
--- a/src/jtag/drivers/arm-jtag-ew.c
+++ b/src/jtag/drivers/arm-jtag-ew.c
@@ -44,8 +44,8 @@ static uint8_t usb_out_buffer[ARMJTAGEW_OUT_BUFFER_SIZE];
/* Queue command functions */
static void armjtagew_end_state(tap_state_t state);
static void armjtagew_state_move(void);
-static void armjtagew_path_move(int num_states, tap_state_t *path);
-static void armjtagew_runtest(int num_cycles);
+static void armjtagew_path_move(unsigned int num_states, tap_state_t *path);
+static void armjtagew_runtest(unsigned int num_cycles);
static void armjtagew_scan(bool ir_scan,
enum scan_type type,
uint8_t *buffer,
@@ -95,7 +95,7 @@ static int armjtagew_execute_queue(struct jtag_command *cmd_queue)
while (cmd) {
switch (cmd->type) {
case JTAG_RUNTEST:
- LOG_DEBUG_IO("runtest %i cycles, end in %i",
+ LOG_DEBUG_IO("runtest %u cycles, end in %i",
cmd->cmd.runtest->num_cycles,
cmd->cmd.runtest->end_state);
@@ -111,7 +111,7 @@ static int armjtagew_execute_queue(struct jtag_command *cmd_queue)
break;
case JTAG_PATHMOVE:
- LOG_DEBUG_IO("pathmove: %i states, end in %i",
+ LOG_DEBUG_IO("pathmove: %u states, end in %i",
cmd->cmd.pathmove->num_states,
cmd->cmd.pathmove->path[cmd->cmd.pathmove->num_states - 1]);
@@ -279,11 +279,9 @@ static void armjtagew_state_move(void)
tap_set_state(tap_get_end_state());
}
-static void armjtagew_path_move(int num_states, tap_state_t *path)
+static void armjtagew_path_move(unsigned int num_states, tap_state_t *path)
{
- int i;
-
- for (i = 0; i < num_states; i++) {
+ for (unsigned int i = 0; i < num_states; i++) {
/*
* TODO: The ARM-JTAG-EW hardware delays TDI with 3 TCK cycles when in RTCK mode.
* Either handle that here, or update the documentation with examples
@@ -305,10 +303,8 @@ static void armjtagew_path_move(int num_states, tap_state_t *path)
tap_set_end_state(tap_get_state());
}
-static void armjtagew_runtest(int num_cycles)
+static void armjtagew_runtest(unsigned int num_cycles)
{
- int i;
-
tap_state_t saved_end_state = tap_get_end_state();
/* only do a state_move when we're not already in IDLE */
@@ -318,7 +314,7 @@ static void armjtagew_runtest(int num_cycles)
}
/* execute num_cycles */
- for (i = 0; i < num_cycles; i++)
+ for (unsigned int i = 0; i < num_cycles; i++)
armjtagew_tap_append_step(0, 0);
/* finish in end_state */
diff --git a/src/jtag/drivers/bitbang.c b/src/jtag/drivers/bitbang.c
index 3d839e6..e416592 100644
--- a/src/jtag/drivers/bitbang.c
+++ b/src/jtag/drivers/bitbang.c
@@ -33,7 +33,7 @@
* this function checks the current stable state to decide on the value of TMS
* to use.
*/
-static int bitbang_stableclocks(int num_cycles);
+static int bitbang_stableclocks(unsigned int num_cycles);
static void bitbang_swd_write_reg(uint8_t cmd, uint32_t value, uint32_t ap_delay_clk);
@@ -95,7 +95,7 @@ static int bitbang_execute_tms(struct jtag_command *cmd)
unsigned num_bits = cmd->cmd.tms->num_bits;
const uint8_t *bits = cmd->cmd.tms->bits;
- LOG_DEBUG_IO("TMS: %d bits", num_bits);
+ LOG_DEBUG_IO("TMS: %u bits", num_bits);
int tms = 0;
for (unsigned i = 0; i < num_bits; i++) {
@@ -113,7 +113,7 @@ static int bitbang_execute_tms(struct jtag_command *cmd)
static int bitbang_path_move(struct pathmove_command *cmd)
{
- int num_states = cmd->num_states;
+ unsigned int num_states = cmd->num_states;
int state_count;
int tms = 0;
@@ -147,10 +147,8 @@ static int bitbang_path_move(struct pathmove_command *cmd)
return ERROR_OK;
}
-static int bitbang_runtest(int num_cycles)
+static int bitbang_runtest(unsigned int num_cycles)
{
- int i;
-
tap_state_t saved_end_state = tap_get_end_state();
/* only do a state_move when we're not already in IDLE */
@@ -161,7 +159,7 @@ static int bitbang_runtest(int num_cycles)
}
/* execute num_cycles */
- for (i = 0; i < num_cycles; i++) {
+ for (unsigned int i = 0; i < num_cycles; i++) {
if (bitbang_interface->write(0, 0, 0) != ERROR_OK)
return ERROR_FAIL;
if (bitbang_interface->write(1, 0, 0) != ERROR_OK)
@@ -179,13 +177,12 @@ static int bitbang_runtest(int num_cycles)
return ERROR_OK;
}
-static int bitbang_stableclocks(int num_cycles)
+static int bitbang_stableclocks(unsigned int num_cycles)
{
int tms = (tap_get_state() == TAP_RESET ? 1 : 0);
- int i;
/* send num_cycles clocks onto the cable */
- for (i = 0; i < num_cycles; i++) {
+ for (unsigned int i = 0; i < num_cycles; i++) {
if (bitbang_interface->write(1, tms, 0) != ERROR_OK)
return ERROR_FAIL;
if (bitbang_interface->write(0, tms, 0) != ERROR_OK)
@@ -319,7 +316,7 @@ int bitbang_execute_queue(struct jtag_command *cmd_queue)
while (cmd) {
switch (cmd->type) {
case JTAG_RUNTEST:
- LOG_DEBUG_IO("runtest %i cycles, end in %s",
+ LOG_DEBUG_IO("runtest %u cycles, end in %s",
cmd->cmd.runtest->num_cycles,
tap_state_name(cmd->cmd.runtest->end_state));
bitbang_end_state(cmd->cmd.runtest->end_state);
@@ -343,7 +340,7 @@ int bitbang_execute_queue(struct jtag_command *cmd_queue)
return ERROR_FAIL;
break;
case JTAG_PATHMOVE:
- LOG_DEBUG_IO("pathmove: %i states, end in %s",
+ LOG_DEBUG_IO("pathmove: %u states, end in %s",
cmd->cmd.pathmove->num_states,
tap_state_name(cmd->cmd.pathmove->path[cmd->cmd.pathmove->num_states - 1]));
if (bitbang_path_move(cmd->cmd.pathmove) != ERROR_OK)
diff --git a/src/jtag/drivers/bitq.c b/src/jtag/drivers/bitq.c
index 2e5cca2..ef870e6 100644
--- a/src/jtag/drivers/bitq.c
+++ b/src/jtag/drivers/bitq.c
@@ -18,8 +18,8 @@ struct bitq_interface *bitq_interface; /* low level bit queue interface */
/* state of input queue */
struct bitq_state {
struct jtag_command *cmd; /* command currently processed */
- int field_idx; /* index of field currently being processed */
- int bit_pos; /* position of bit currently being processed */
+ unsigned int field_idx; /* index of field currently being processed */
+ unsigned int bit_pos; /* position of bit currently being processed */
int status; /* processing status */
};
static struct bitq_state bitq_in_state;
@@ -108,9 +108,7 @@ static void bitq_state_move(tap_state_t new_state)
static void bitq_path_move(struct pathmove_command *cmd)
{
- int i;
-
- for (i = 0; i < cmd->num_states; i++) {
+ for (unsigned int i = 0; i < cmd->num_states; i++) {
if (tap_state_transition(tap_get_state(), false) == cmd->path[i])
bitq_io(0, 0, 0);
else if (tap_state_transition(tap_get_state(), true) == cmd->path[i])
@@ -127,16 +125,14 @@ static void bitq_path_move(struct pathmove_command *cmd)
tap_set_end_state(tap_get_state());
}
-static void bitq_runtest(int num_cycles)
+static void bitq_runtest(unsigned int num_cycles)
{
- int i;
-
/* only do a state_move when we're not already in IDLE */
if (tap_get_state() != TAP_IDLE)
bitq_state_move(TAP_IDLE);
/* execute num_cycles */
- for (i = 0; i < num_cycles; i++)
+ for (unsigned int i = 0; i < num_cycles; i++)
bitq_io(0, 0, 0);
/* finish in end_state */
@@ -146,11 +142,10 @@ static void bitq_runtest(int num_cycles)
static void bitq_scan_field(struct scan_field *field, int do_pause)
{
- int bit_cnt;
int tdo_req;
const uint8_t *out_ptr;
- uint8_t out_mask;
+ uint8_t out_mask;
if (field->in_value)
tdo_req = 1;
@@ -159,7 +154,7 @@ static void bitq_scan_field(struct scan_field *field, int do_pause)
if (!field->out_value) {
/* just send zeros and request data from TDO */
- for (bit_cnt = field->num_bits; bit_cnt > 1; bit_cnt--)
+ for (unsigned int i = 0; i < (field->num_bits - 1); i++)
bitq_io(0, 0, tdo_req);
bitq_io(do_pause, 0, tdo_req);
@@ -167,7 +162,7 @@ static void bitq_scan_field(struct scan_field *field, int do_pause)
/* send data, and optionally request TDO */
out_mask = 0x01;
out_ptr = field->out_value;
- for (bit_cnt = field->num_bits; bit_cnt > 1; bit_cnt--) {
+ for (unsigned int i = 0; i < (field->num_bits - 1); i++) {
bitq_io(0, ((*out_ptr) & out_mask) != 0, tdo_req);
if (out_mask == 0x80) {
out_mask = 0x01;
@@ -190,13 +185,12 @@ static void bitq_scan_field(struct scan_field *field, int do_pause)
static void bitq_scan(struct scan_command *cmd)
{
- int i;
-
if (cmd->ir_scan)
bitq_state_move(TAP_IRSHIFT);
else
bitq_state_move(TAP_DRSHIFT);
+ unsigned int i;
for (i = 0; i < cmd->num_fields - 1; i++)
bitq_scan_field(&cmd->fields[i], 0);
@@ -226,7 +220,7 @@ int bitq_execute_queue(struct jtag_command *cmd_queue)
break;
case JTAG_RUNTEST:
- LOG_DEBUG_IO("runtest %i cycles, end in %i", cmd->cmd.runtest->num_cycles, cmd->cmd.runtest->end_state);
+ LOG_DEBUG_IO("runtest %u cycles, end in %i", cmd->cmd.runtest->num_cycles, cmd->cmd.runtest->end_state);
bitq_end_state(cmd->cmd.runtest->end_state);
bitq_runtest(cmd->cmd.runtest->num_cycles);
break;
@@ -238,7 +232,7 @@ int bitq_execute_queue(struct jtag_command *cmd_queue)
break;
case JTAG_PATHMOVE:
- LOG_DEBUG_IO("pathmove: %i states, end in %i", cmd->cmd.pathmove->num_states,
+ LOG_DEBUG_IO("pathmove: %u states, end in %i", cmd->cmd.pathmove->num_states,
cmd->cmd.pathmove->path[cmd->cmd.pathmove->num_states - 1]);
bitq_path_move(cmd->cmd.pathmove);
break;
diff --git a/src/jtag/drivers/buspirate.c b/src/jtag/drivers/buspirate.c
index 3b03337..b01a796 100644
--- a/src/jtag/drivers/buspirate.c
+++ b/src/jtag/drivers/buspirate.c
@@ -27,11 +27,11 @@ static int buspirate_reset(int trst, int srst);
static void buspirate_end_state(tap_state_t state);
static void buspirate_state_move(void);
-static void buspirate_path_move(int num_states, tap_state_t *path);
-static void buspirate_runtest(int num_cycles);
+static void buspirate_path_move(unsigned int num_states, tap_state_t *path);
+static void buspirate_runtest(unsigned int num_cycles);
static void buspirate_scan(bool ir_scan, enum scan_type type,
uint8_t *buffer, int scan_size, struct scan_command *command);
-static void buspirate_stableclocks(int num_cycles);
+static void buspirate_stableclocks(unsigned int num_cycles);
#define CMD_UNKNOWN 0x00
#define CMD_PORT_MODE 0x01
@@ -162,7 +162,7 @@ static int buspirate_execute_queue(struct jtag_command *cmd_queue)
while (cmd) {
switch (cmd->type) {
case JTAG_RUNTEST:
- LOG_DEBUG_IO("runtest %i cycles, end in %s",
+ LOG_DEBUG_IO("runtest %u cycles, end in %s",
cmd->cmd.runtest->num_cycles,
tap_state_name(cmd->cmd.runtest
->end_state));
@@ -180,7 +180,7 @@ static int buspirate_execute_queue(struct jtag_command *cmd_queue)
buspirate_state_move();
break;
case JTAG_PATHMOVE:
- LOG_DEBUG_IO("pathmove: %i states, end in %s",
+ LOG_DEBUG_IO("pathmove: %u states, end in %s",
cmd->cmd.pathmove->num_states,
tap_state_name(cmd->cmd.pathmove
->path[cmd->cmd.pathmove
@@ -210,7 +210,7 @@ static int buspirate_execute_queue(struct jtag_command *cmd_queue)
jtag_sleep(cmd->cmd.sleep->us);
break;
case JTAG_STABLECLOCKS:
- LOG_DEBUG_IO("stable clock %i cycles", cmd->cmd.stableclocks->num_cycles);
+ LOG_DEBUG_IO("stable clock %u cycles", cmd->cmd.stableclocks->num_cycles);
buspirate_stableclocks(cmd->cmd.stableclocks->num_cycles);
break;
default:
@@ -580,11 +580,9 @@ static void buspirate_state_move(void)
tap_set_state(tap_get_end_state());
}
-static void buspirate_path_move(int num_states, tap_state_t *path)
+static void buspirate_path_move(unsigned int num_states, tap_state_t *path)
{
- int i;
-
- for (i = 0; i < num_states; i++) {
+ for (unsigned int i = 0; i < num_states; i++) {
if (tap_state_transition(tap_get_state(), false) == path[i]) {
buspirate_tap_append(0, 0);
} else if (tap_state_transition(tap_get_state(), true)
@@ -604,10 +602,8 @@ static void buspirate_path_move(int num_states, tap_state_t *path)
tap_set_end_state(tap_get_state());
}
-static void buspirate_runtest(int num_cycles)
+static void buspirate_runtest(unsigned int num_cycles)
{
- int i;
-
tap_state_t saved_end_state = tap_get_end_state();
/* only do a state_move when we're not already in IDLE */
@@ -616,7 +612,7 @@ static void buspirate_runtest(int num_cycles)
buspirate_state_move();
}
- for (i = 0; i < num_cycles; i++)
+ for (unsigned int i = 0; i < num_cycles; i++)
buspirate_tap_append(0, 0);
LOG_DEBUG_IO("runtest: cur_state %s end_state %s",
@@ -658,14 +654,13 @@ static void buspirate_scan(bool ir_scan, enum scan_type type,
buspirate_state_move();
}
-static void buspirate_stableclocks(int num_cycles)
+static void buspirate_stableclocks(unsigned int num_cycles)
{
- int i;
int tms = (tap_get_state() == TAP_RESET ? 1 : 0);
buspirate_tap_make_space(0, num_cycles);
- for (i = 0; i < num_cycles; i++)
+ for (unsigned int i = 0; i < num_cycles; i++)
buspirate_tap_append(tms, 0);
}
diff --git a/src/jtag/drivers/cmsis_dap.c b/src/jtag/drivers/cmsis_dap.c
index d7367d8..a6dcfcd 100644
--- a/src/jtag/drivers/cmsis_dap.c
+++ b/src/jtag/drivers/cmsis_dap.c
@@ -1752,7 +1752,7 @@ static void cmsis_dap_execute_scan(struct jtag_command *cmd)
LOG_DEBUG("discarding trailing empty field");
}
- if (cmd->cmd.scan->num_fields == 0) {
+ if (!cmd->cmd.scan->num_fields) {
LOG_DEBUG("empty scan, doing nothing");
return;
}
@@ -1772,11 +1772,11 @@ static void cmsis_dap_execute_scan(struct jtag_command *cmd)
cmsis_dap_end_state(cmd->cmd.scan->end_state);
struct scan_field *field = cmd->cmd.scan->fields;
- unsigned scan_size = 0;
+ unsigned int scan_size = 0;
- for (int i = 0; i < cmd->cmd.scan->num_fields; i++, field++) {
+ for (unsigned int i = 0; i < cmd->cmd.scan->num_fields; i++, field++) {
scan_size += field->num_bits;
- LOG_DEBUG_IO("%s%s field %d/%d %d bits",
+ LOG_DEBUG_IO("%s%s field %u/%u %u bits",
field->in_value ? "in" : "",
field->out_value ? "out" : "",
i,
@@ -1872,16 +1872,16 @@ static void cmsis_dap_execute_pathmove(struct jtag_command *cmd)
cmsis_dap_pathmove(cmd->cmd.pathmove->num_states, cmd->cmd.pathmove->path);
}
-static void cmsis_dap_stableclocks(int num_cycles)
+static void cmsis_dap_stableclocks(unsigned int num_cycles)
{
uint8_t tms = tap_get_state() == TAP_RESET;
/* TODO: Perform optimizations? */
/* Execute num_cycles. */
- for (int i = 0; i < num_cycles; i++)
+ for (unsigned int i = 0; i < num_cycles; i++)
cmsis_dap_add_tms_sequence(&tms, 1);
}
-static void cmsis_dap_runtest(int num_cycles)
+static void cmsis_dap_runtest(unsigned int num_cycles)
{
tap_state_t saved_end_state = tap_get_end_state();
@@ -1901,7 +1901,7 @@ static void cmsis_dap_runtest(int num_cycles)
static void cmsis_dap_execute_runtest(struct jtag_command *cmd)
{
- LOG_DEBUG_IO("runtest %i cycles, end in %i", cmd->cmd.runtest->num_cycles,
+ LOG_DEBUG_IO("runtest %u cycles, end in %i", cmd->cmd.runtest->num_cycles,
cmd->cmd.runtest->end_state);
cmsis_dap_end_state(cmd->cmd.runtest->end_state);
@@ -1910,13 +1910,13 @@ static void cmsis_dap_execute_runtest(struct jtag_command *cmd)
static void cmsis_dap_execute_stableclocks(struct jtag_command *cmd)
{
- LOG_DEBUG_IO("stableclocks %i cycles", cmd->cmd.runtest->num_cycles);
+ LOG_DEBUG_IO("stableclocks %u cycles", cmd->cmd.runtest->num_cycles);
cmsis_dap_stableclocks(cmd->cmd.runtest->num_cycles);
}
static void cmsis_dap_execute_tms(struct jtag_command *cmd)
{
- LOG_DEBUG_IO("TMS: %d bits", cmd->cmd.tms->num_bits);
+ LOG_DEBUG_IO("TMS: %u bits", cmd->cmd.tms->num_bits);
cmsis_dap_cmd_dap_swj_sequence(cmd->cmd.tms->num_bits, cmd->cmd.tms->bits);
}
diff --git a/src/jtag/drivers/cmsis_dap_usb_hid.c b/src/jtag/drivers/cmsis_dap_usb_hid.c
index 98ccc3e..aeec685 100644
--- a/src/jtag/drivers/cmsis_dap_usb_hid.c
+++ b/src/jtag/drivers/cmsis_dap_usb_hid.c
@@ -121,8 +121,12 @@ static int cmsis_dap_hid_open(struct cmsis_dap *dap, uint16_t vids[], uint16_t p
break;
if (cur_dev->serial_number) {
- size_t len = (strlen(serial) + 1) * sizeof(wchar_t);
- wchar_t *wserial = malloc(len);
+ size_t len = mbstowcs(NULL, serial, 0) + 1;
+ wchar_t *wserial = malloc(len * sizeof(wchar_t));
+ if (!wserial) {
+ LOG_ERROR("unable to allocate serial number buffer");
+ return ERROR_FAIL;
+ }
mbstowcs(wserial, serial, len);
if (wcscmp(wserial, cur_dev->serial_number) == 0) {
diff --git a/src/jtag/drivers/driver.c b/src/jtag/drivers/driver.c
index e52816d..2aad4a0 100644
--- a/src/jtag/drivers/driver.c
+++ b/src/jtag/drivers/driver.c
@@ -259,7 +259,7 @@ int interface_add_tms_seq(unsigned num_bits, const uint8_t *seq, enum tap_state
return ERROR_OK;
}
-int interface_jtag_add_pathmove(int num_states, const tap_state_t *path)
+int interface_jtag_add_pathmove(unsigned int num_states, const tap_state_t *path)
{
/* allocate memory for a new list member */
struct jtag_command *cmd = cmd_queue_alloc(sizeof(struct jtag_command));
@@ -272,13 +272,13 @@ int interface_jtag_add_pathmove(int num_states, const tap_state_t *path)
cmd->cmd.pathmove->num_states = num_states;
cmd->cmd.pathmove->path = cmd_queue_alloc(sizeof(tap_state_t) * num_states);
- for (int i = 0; i < num_states; i++)
+ for (unsigned int i = 0; i < num_states; i++)
cmd->cmd.pathmove->path[i] = path[i];
return ERROR_OK;
}
-int interface_jtag_add_runtest(int num_cycles, tap_state_t state)
+int interface_jtag_add_runtest(unsigned int num_cycles, tap_state_t state)
{
/* allocate memory for a new list member */
struct jtag_command *cmd = cmd_queue_alloc(sizeof(struct jtag_command));
@@ -294,7 +294,7 @@ int interface_jtag_add_runtest(int num_cycles, tap_state_t state)
return ERROR_OK;
}
-int interface_jtag_add_clocks(int num_cycles)
+int interface_jtag_add_clocks(unsigned int num_cycles)
{
/* allocate memory for a new list member */
struct jtag_command *cmd = cmd_queue_alloc(sizeof(struct jtag_command));
diff --git a/src/jtag/drivers/ft232r.c b/src/jtag/drivers/ft232r.c
index 766f6dd..a4d072c 100644
--- a/src/jtag/drivers/ft232r.c
+++ b/src/jtag/drivers/ft232r.c
@@ -657,7 +657,7 @@ static int syncbb_execute_tms(struct jtag_command *cmd)
unsigned num_bits = cmd->cmd.tms->num_bits;
const uint8_t *bits = cmd->cmd.tms->bits;
- LOG_DEBUG_IO("TMS: %d bits", num_bits);
+ LOG_DEBUG_IO("TMS: %u bits", num_bits);
int tms = 0;
for (unsigned i = 0; i < num_bits; i++) {
@@ -672,7 +672,7 @@ static int syncbb_execute_tms(struct jtag_command *cmd)
static void syncbb_path_move(struct pathmove_command *cmd)
{
- int num_states = cmd->num_states;
+ unsigned int num_states = cmd->num_states;
int state_count;
int tms = 0;
@@ -702,9 +702,8 @@ static void syncbb_path_move(struct pathmove_command *cmd)
tap_set_end_state(tap_get_state());
}
-static void syncbb_runtest(int num_cycles)
+static void syncbb_runtest(unsigned int num_cycles)
{
- int i;
tap_state_t saved_end_state = tap_get_end_state();
@@ -715,7 +714,7 @@ static void syncbb_runtest(int num_cycles)
}
/* execute num_cycles */
- for (i = 0; i < num_cycles; i++) {
+ for (unsigned int i = 0; i < num_cycles; i++) {
ft232r_write(0, 0, 0);
ft232r_write(1, 0, 0);
}
@@ -735,13 +734,12 @@ static void syncbb_runtest(int num_cycles)
* this function checks the current stable state to decide on the value of TMS
* to use.
*/
-static void syncbb_stableclocks(int num_cycles)
+static void syncbb_stableclocks(unsigned int num_cycles)
{
int tms = (tap_get_state() == TAP_RESET ? 1 : 0);
- int i;
/* send num_cycles clocks onto the cable */
- for (i = 0; i < num_cycles; i++) {
+ for (unsigned int i = 0; i < num_cycles; i++) {
ft232r_write(1, tms, 0);
ft232r_write(0, tms, 0);
}
@@ -832,7 +830,7 @@ static int syncbb_execute_queue(struct jtag_command *cmd_queue)
break;
case JTAG_RUNTEST:
- LOG_DEBUG_IO("runtest %i cycles, end in %s", cmd->cmd.runtest->num_cycles,
+ LOG_DEBUG_IO("runtest %u cycles, end in %s", cmd->cmd.runtest->num_cycles,
tap_state_name(cmd->cmd.runtest->end_state));
syncbb_end_state(cmd->cmd.runtest->end_state);
@@ -854,7 +852,7 @@ static int syncbb_execute_queue(struct jtag_command *cmd_queue)
break;
case JTAG_PATHMOVE:
- LOG_DEBUG_IO("pathmove: %i states, end in %s", cmd->cmd.pathmove->num_states,
+ LOG_DEBUG_IO("pathmove: %u states, end in %s", cmd->cmd.pathmove->num_states,
tap_state_name(cmd->cmd.pathmove->path[cmd->cmd.pathmove->num_states - 1]));
syncbb_path_move(cmd->cmd.pathmove);
diff --git a/src/jtag/drivers/ftdi.c b/src/jtag/drivers/ftdi.c
index 1793cbf..66d0d50 100644
--- a/src/jtag/drivers/ftdi.c
+++ b/src/jtag/drivers/ftdi.c
@@ -383,10 +383,9 @@ static void ftdi_end_state(tap_state_t state)
static void ftdi_execute_runtest(struct jtag_command *cmd)
{
- int i;
- static const uint8_t zero;
+ uint8_t zero = 0;
- LOG_DEBUG_IO("runtest %i cycles, end in %s",
+ LOG_DEBUG_IO("runtest %u cycles, end in %s",
cmd->cmd.runtest->num_cycles,
tap_state_name(cmd->cmd.runtest->end_state));
@@ -394,7 +393,7 @@ static void ftdi_execute_runtest(struct jtag_command *cmd)
move_to_state(TAP_IDLE);
/* TODO: Reuse ftdi_execute_stableclocks */
- i = cmd->cmd.runtest->num_cycles;
+ unsigned int i = cmd->cmd.runtest->num_cycles;
while (i > 0) {
/* there are no state transitions in this code, so omit state tracking */
unsigned this_len = i > 7 ? 7 : i;
@@ -407,7 +406,7 @@ static void ftdi_execute_runtest(struct jtag_command *cmd)
if (tap_get_state() != tap_get_end_state())
move_to_state(tap_get_end_state());
- LOG_DEBUG_IO("runtest: %i, end in %s",
+ LOG_DEBUG_IO("runtest: %u, end in %s",
cmd->cmd.runtest->num_cycles,
tap_state_name(tap_get_end_state()));
}
@@ -430,7 +429,7 @@ static void ftdi_execute_statemove(struct jtag_command *cmd)
*/
static void ftdi_execute_tms(struct jtag_command *cmd)
{
- LOG_DEBUG_IO("TMS: %d bits", cmd->cmd.tms->num_bits);
+ LOG_DEBUG_IO("TMS: %u bits", cmd->cmd.tms->num_bits);
/* TODO: Missing tap state tracking, also missing from ft2232.c! */
DO_CLOCK_TMS_CS_OUT(mpsse_ctx,
@@ -444,9 +443,9 @@ static void ftdi_execute_tms(struct jtag_command *cmd)
static void ftdi_execute_pathmove(struct jtag_command *cmd)
{
tap_state_t *path = cmd->cmd.pathmove->path;
- int num_states = cmd->cmd.pathmove->num_states;
+ unsigned int num_states = cmd->cmd.pathmove->num_states;
- LOG_DEBUG_IO("pathmove: %i states, current: %s end: %s", num_states,
+ LOG_DEBUG_IO("pathmove: %u states, current: %s end: %s", num_states,
tap_state_name(tap_get_state()),
tap_state_name(path[num_states-1]));
@@ -504,7 +503,7 @@ static void ftdi_execute_scan(struct jtag_command *cmd)
LOG_DEBUG_IO("discarding trailing empty field");
}
- if (cmd->cmd.scan->num_fields == 0) {
+ if (!cmd->cmd.scan->num_fields) {
LOG_DEBUG_IO("empty scan, doing nothing");
return;
}
@@ -522,9 +521,9 @@ static void ftdi_execute_scan(struct jtag_command *cmd)
struct scan_field *field = cmd->cmd.scan->fields;
unsigned scan_size = 0;
- for (int i = 0; i < cmd->cmd.scan->num_fields; i++, field++) {
+ for (unsigned int i = 0; i < cmd->cmd.scan->num_fields; i++, field++) {
scan_size += field->num_bits;
- LOG_DEBUG_IO("%s%s field %d/%d %d bits",
+ LOG_DEBUG_IO("%s%s field %u/%u %u bits",
field->in_value ? "in" : "",
field->out_value ? "out" : "",
i,
@@ -644,7 +643,7 @@ static void ftdi_execute_stableclocks(struct jtag_command *cmd)
/* this is only allowed while in a stable state. A check for a stable
* state was done in jtag_add_clocks()
*/
- int num_cycles = cmd->cmd.stableclocks->num_cycles;
+ unsigned int num_cycles = cmd->cmd.stableclocks->num_cycles;
/* 7 bits of either ones or zeros. */
uint8_t tms = tap_get_state() == TAP_RESET ? 0x7f : 0x00;
@@ -658,7 +657,7 @@ static void ftdi_execute_stableclocks(struct jtag_command *cmd)
num_cycles -= this_len;
}
- LOG_DEBUG_IO("clocks %i while in %s",
+ LOG_DEBUG_IO("clocks %u while in %s",
cmd->cmd.stableclocks->num_cycles,
tap_state_name(tap_get_state()));
}
diff --git a/src/jtag/drivers/gw16012.c b/src/jtag/drivers/gw16012.c
index a4c6fd0..d0fe43f 100644
--- a/src/jtag/drivers/gw16012.c
+++ b/src/jtag/drivers/gw16012.c
@@ -185,10 +185,9 @@ static void gw16012_path_move(struct pathmove_command *cmd)
tap_set_end_state(tap_get_state());
}
-static void gw16012_runtest(int num_cycles)
+static void gw16012_runtest(unsigned int num_cycles)
{
tap_state_t saved_end_state = tap_get_end_state();
- int i;
/* only do a state_move when we're not already in IDLE */
if (tap_get_state() != TAP_IDLE) {
@@ -196,7 +195,7 @@ static void gw16012_runtest(int num_cycles)
gw16012_state_move();
}
- for (i = 0; i < num_cycles; i++) {
+ for (unsigned int i = 0; i < num_cycles; i++) {
gw16012_control(0x0); /* single-bit mode */
gw16012_data(0x0); /* TMS cycle with TMS low */
}
@@ -292,7 +291,7 @@ static int gw16012_execute_queue(struct jtag_command *cmd_queue)
gw16012_reset(cmd->cmd.reset->trst, cmd->cmd.reset->srst);
break;
case JTAG_RUNTEST:
- LOG_DEBUG_IO("runtest %i cycles, end in %i", cmd->cmd.runtest->num_cycles,
+ LOG_DEBUG_IO("runtest %u cycles, end in %i", cmd->cmd.runtest->num_cycles,
cmd->cmd.runtest->end_state);
gw16012_end_state(cmd->cmd.runtest->end_state);
gw16012_runtest(cmd->cmd.runtest->num_cycles);
diff --git a/src/jtag/drivers/jlink.c b/src/jtag/drivers/jlink.c
index 1874557..1b2fb4e 100644
--- a/src/jtag/drivers/jlink.c
+++ b/src/jtag/drivers/jlink.c
@@ -80,9 +80,9 @@ static struct device_config tmp_config;
/* Queue command functions */
static void jlink_end_state(tap_state_t state);
static void jlink_state_move(void);
-static void jlink_path_move(int num_states, tap_state_t *path);
-static void jlink_stableclocks(int num_cycles);
-static void jlink_runtest(int num_cycles);
+static void jlink_path_move(unsigned int num_states, tap_state_t *path);
+static void jlink_stableclocks(unsigned int num_cycles);
+static void jlink_runtest(unsigned int num_cycles);
static void jlink_reset(int trst, int srst);
static int jlink_reset_safe(int trst, int srst);
static int jlink_swd_run_queue(void);
@@ -140,7 +140,7 @@ static void jlink_execute_statemove(struct jtag_command *cmd)
static void jlink_execute_pathmove(struct jtag_command *cmd)
{
- LOG_DEBUG_IO("pathmove: %i states, end in %i",
+ LOG_DEBUG_IO("pathmove: %u states, end in %i",
cmd->cmd.pathmove->num_states,
cmd->cmd.pathmove->path[cmd->cmd.pathmove->num_states - 1]);
@@ -159,7 +159,7 @@ static void jlink_execute_scan(struct jtag_command *cmd)
LOG_DEBUG("discarding trailing empty field");
}
- if (cmd->cmd.scan->num_fields == 0) {
+ if (!cmd->cmd.scan->num_fields) {
LOG_DEBUG("empty scan, doing nothing");
return;
}
@@ -181,9 +181,9 @@ static void jlink_execute_scan(struct jtag_command *cmd)
struct scan_field *field = cmd->cmd.scan->fields;
unsigned scan_size = 0;
- for (int i = 0; i < cmd->cmd.scan->num_fields; i++, field++) {
+ for (unsigned int i = 0; i < cmd->cmd.scan->num_fields; i++, field++) {
scan_size += field->num_bits;
- LOG_DEBUG_IO("%s%s field %d/%d %d bits",
+ LOG_DEBUG_IO("%s%s field %u/%u %u bits",
field->in_value ? "in" : "",
field->out_value ? "out" : "",
i,
@@ -564,6 +564,20 @@ static int jlink_open_device(uint32_t ifaces, bool *found_device)
if (!use_serial_number && !use_usb_address && !use_usb_location && num_devices > 1) {
LOG_ERROR("Multiple devices found, specify the desired device");
+ LOG_INFO("Found devices:");
+ for (size_t i = 0; devs[i]; i++) {
+ uint32_t serial;
+ ret = jaylink_device_get_serial_number(devs[i], &serial);
+ if (ret == JAYLINK_ERR_NOT_AVAILABLE) {
+ continue;
+ } else if (ret != JAYLINK_OK) {
+ LOG_WARNING("jaylink_device_get_serial_number() failed: %s",
+ jaylink_strerror(ret));
+ continue;
+ }
+ LOG_INFO("Device %zu serial: %" PRIu32, i, serial);
+ }
+
jaylink_free_devices(devs, true);
jaylink_exit(jayctx);
return ERROR_JTAG_INIT_FAILED;
@@ -885,12 +899,11 @@ static void jlink_state_move(void)
tap_set_state(tap_get_end_state());
}
-static void jlink_path_move(int num_states, tap_state_t *path)
+static void jlink_path_move(unsigned int num_states, tap_state_t *path)
{
- int i;
uint8_t tms = 0xff;
- for (i = 0; i < num_states; i++) {
+ for (unsigned int i = 0; i < num_states; i++) {
if (path[i] == tap_state_transition(tap_get_state(), false))
jlink_clock_data(NULL, 0, NULL, 0, NULL, 0, 1);
else if (path[i] == tap_state_transition(tap_get_state(), true))
@@ -907,17 +920,15 @@ static void jlink_path_move(int num_states, tap_state_t *path)
tap_set_end_state(tap_get_state());
}
-static void jlink_stableclocks(int num_cycles)
+static void jlink_stableclocks(unsigned int num_cycles)
{
- int i;
-
uint8_t tms = tap_get_state() == TAP_RESET;
/* Execute num_cycles. */
- for (i = 0; i < num_cycles; i++)
+ for (unsigned int i = 0; i < num_cycles; i++)
jlink_clock_data(NULL, 0, &tms, 0, NULL, 0, 1);
}
-static void jlink_runtest(int num_cycles)
+static void jlink_runtest(unsigned int num_cycles)
{
tap_state_t saved_end_state = tap_get_end_state();
@@ -964,23 +975,18 @@ static int jlink_reset_safe(int trst, int srst)
COMMAND_HANDLER(jlink_usb_command)
{
- int tmp;
-
if (CMD_ARGC != 1)
return ERROR_COMMAND_SYNTAX_ERROR;
- if (sscanf(CMD_ARGV[0], "%i", &tmp) != 1) {
- command_print(CMD, "Invalid USB address: %s", CMD_ARGV[0]);
- return ERROR_COMMAND_ARGUMENT_INVALID;
- }
+ unsigned int tmp;
+ COMMAND_PARSE_NUMBER(uint, CMD_ARGV[0], tmp);
- if (tmp < JAYLINK_USB_ADDRESS_0 || tmp > JAYLINK_USB_ADDRESS_3) {
+ if (tmp > JAYLINK_USB_ADDRESS_3) {
command_print(CMD, "Invalid USB address: %s", CMD_ARGV[0]);
return ERROR_COMMAND_ARGUMENT_INVALID;
}
usb_address = tmp;
-
use_usb_address = true;
return ERROR_OK;
@@ -1038,38 +1044,35 @@ COMMAND_HANDLER(jlink_handle_free_memory_command)
COMMAND_HANDLER(jlink_handle_jlink_jtag_command)
{
- int tmp;
- int version;
-
if (!CMD_ARGC) {
+ unsigned int version;
+
switch (jtag_command_version) {
- case JAYLINK_JTAG_VERSION_2:
- version = 2;
- break;
- case JAYLINK_JTAG_VERSION_3:
- version = 3;
- break;
- default:
- return ERROR_FAIL;
+ case JAYLINK_JTAG_VERSION_2:
+ version = 2;
+ break;
+ case JAYLINK_JTAG_VERSION_3:
+ version = 3;
+ break;
+ default:
+ return ERROR_FAIL;
}
- command_print(CMD, "JTAG command version: %i", version);
+ command_print(CMD, "JTAG command version: %u", version);
} else if (CMD_ARGC == 1) {
- if (sscanf(CMD_ARGV[0], "%i", &tmp) != 1) {
- command_print(CMD, "Invalid argument: %s", CMD_ARGV[0]);
- return ERROR_COMMAND_ARGUMENT_INVALID;
- }
+ uint8_t tmp;
+ COMMAND_PARSE_NUMBER(u8, CMD_ARGV[0], tmp);
switch (tmp) {
- case 2:
- jtag_command_version = JAYLINK_JTAG_VERSION_2;
- break;
- case 3:
- jtag_command_version = JAYLINK_JTAG_VERSION_3;
- break;
- default:
- command_print(CMD, "Invalid argument: %s", CMD_ARGV[0]);
- return ERROR_COMMAND_ARGUMENT_INVALID;
+ case 2:
+ jtag_command_version = JAYLINK_JTAG_VERSION_2;
+ break;
+ case 3:
+ jtag_command_version = JAYLINK_JTAG_VERSION_3;
+ break;
+ default:
+ command_print(CMD, "Invalid argument: %s", CMD_ARGV[0]);
+ return ERROR_COMMAND_ARGUMENT_INVALID;
}
} else {
return ERROR_COMMAND_SYNTAX_ERROR;
@@ -1080,10 +1083,7 @@ COMMAND_HANDLER(jlink_handle_jlink_jtag_command)
COMMAND_HANDLER(jlink_handle_target_power_command)
{
- int ret;
- int enable;
-
- if (CMD_ARGC != 1)
+ if (CMD_ARGC > 1)
return ERROR_COMMAND_SYNTAX_ERROR;
if (!jaylink_has_cap(caps, JAYLINK_DEV_CAP_SET_TARGET_POWER)) {
@@ -1092,16 +1092,24 @@ COMMAND_HANDLER(jlink_handle_target_power_command)
return ERROR_OK;
}
- if (!strcmp(CMD_ARGV[0], "on")) {
- enable = true;
- } else if (!strcmp(CMD_ARGV[0], "off")) {
- enable = false;
- } else {
- command_print(CMD, "Invalid argument: %s", CMD_ARGV[0]);
- return ERROR_FAIL;
+ if (!CMD_ARGC) {
+ uint32_t state;
+ int ret = jaylink_get_hardware_info(devh, JAYLINK_HW_INFO_TARGET_POWER,
+ &state);
+
+ if (ret != JAYLINK_OK) {
+ command_print(CMD, "Failed to retrieve target power state");
+ return ERROR_FAIL;
+ }
+
+ command_print(CMD, "%d", (bool)state);
+ return ERROR_OK;
}
- ret = jaylink_set_target_power(devh, enable);
+ bool enable;
+ COMMAND_PARSE_ON_OFF(CMD_ARGV[0], enable);
+
+ int ret = jaylink_set_target_power(devh, enable);
if (ret != JAYLINK_OK) {
command_print(CMD, "jaylink_set_target_power() failed: %s",
@@ -1410,8 +1418,6 @@ static int config_trace(bool enabled, enum tpiu_pin_protocol pin_protocol,
COMMAND_HANDLER(jlink_handle_config_usb_address_command)
{
- uint8_t tmp;
-
if (!jaylink_has_cap(caps, JAYLINK_DEV_CAP_READ_CONFIG)) {
command_print(CMD, "Reading configuration is not supported by the "
"device");
@@ -1421,10 +1427,8 @@ COMMAND_HANDLER(jlink_handle_config_usb_address_command)
if (!CMD_ARGC) {
show_config_usb_address(CMD);
} else if (CMD_ARGC == 1) {
- if (sscanf(CMD_ARGV[0], "%" SCNd8, &tmp) != 1) {
- command_print(CMD, "Invalid USB address: %s", CMD_ARGV[0]);
- return ERROR_COMMAND_ARGUMENT_INVALID;
- }
+ uint8_t tmp;
+ COMMAND_PARSE_NUMBER(u8, CMD_ARGV[0], tmp);
if (tmp > JAYLINK_USB_ADDRESS_3) {
command_print(CMD, "Invalid USB address: %u", tmp);
@@ -1883,7 +1887,7 @@ static const struct command_registration jlink_subcommand_handlers[] = {
.handler = &jlink_handle_target_power_command,
.mode = COMMAND_EXEC,
.help = "set the target power supply",
- .usage = "<on|off>"
+ .usage = "[0|1|on|off]"
},
{
.name = "freemem",
diff --git a/src/jtag/drivers/jtag_dpi.c b/src/jtag/drivers/jtag_dpi.c
index 285f96e..046186a 100644
--- a/src/jtag/drivers/jtag_dpi.c
+++ b/src/jtag/drivers/jtag_dpi.c
@@ -163,7 +163,7 @@ out:
return ret;
}
-static int jtag_dpi_runtest(int cycles)
+static int jtag_dpi_runtest(unsigned int num_cycles)
{
char buf[20];
uint8_t *data_buf = last_ir_buf, *read_scan;
@@ -189,7 +189,7 @@ static int jtag_dpi_runtest(int cycles)
return ERROR_FAIL;
}
snprintf(buf, sizeof(buf), "ib %d\n", num_bits);
- while (cycles > 0) {
+ while (num_cycles > 0) {
ret = write_sock(buf, strlen(buf));
if (ret != ERROR_OK) {
LOG_ERROR("write_sock() fail, file %s, line %d",
@@ -209,7 +209,7 @@ static int jtag_dpi_runtest(int cycles)
goto out;
}
- cycles -= num_bits + 6;
+ num_cycles -= num_bits + 6;
}
out:
@@ -217,9 +217,9 @@ out:
return ret;
}
-static int jtag_dpi_stableclocks(int cycles)
+static int jtag_dpi_stableclocks(unsigned int num_cycles)
{
- return jtag_dpi_runtest(cycles);
+ return jtag_dpi_runtest(num_cycles);
}
static int jtag_dpi_execute_queue(struct jtag_command *cmd_queue)
diff --git a/src/jtag/drivers/jtag_vpi.c b/src/jtag/drivers/jtag_vpi.c
index 9dec0d1..a19060c 100644
--- a/src/jtag/drivers/jtag_vpi.c
+++ b/src/jtag/drivers/jtag_vpi.c
@@ -254,7 +254,7 @@ static int jtag_vpi_path_move(struct pathmove_command *cmd)
memset(trans, 0, DIV_ROUND_UP(cmd->num_states, 8));
- for (int i = 0; i < cmd->num_states; i++) {
+ for (unsigned int i = 0; i < cmd->num_states; i++) {
if (tap_state_transition(tap_get_state(), true) == cmd->path[i])
buf_set_u32(trans, i, 1, 1);
tap_set_state(cmd->path[i]);
@@ -440,7 +440,7 @@ static int jtag_vpi_scan(struct scan_command *cmd)
return ERROR_OK;
}
-static int jtag_vpi_runtest(int cycles, tap_state_t state)
+static int jtag_vpi_runtest(unsigned int num_cycles, tap_state_t state)
{
int retval;
@@ -448,22 +448,20 @@ static int jtag_vpi_runtest(int cycles, tap_state_t state)
if (retval != ERROR_OK)
return retval;
- retval = jtag_vpi_queue_tdi(NULL, cycles, NO_TAP_SHIFT);
+ retval = jtag_vpi_queue_tdi(NULL, num_cycles, NO_TAP_SHIFT);
if (retval != ERROR_OK)
return retval;
return jtag_vpi_state_move(state);
}
-static int jtag_vpi_stableclocks(int cycles)
+static int jtag_vpi_stableclocks(unsigned int num_cycles)
{
uint8_t tms_bits[4];
- int cycles_remain = cycles;
+ unsigned int cycles_remain = num_cycles;
int nb_bits;
int retval;
- const int CYCLES_ONE_BATCH = sizeof(tms_bits) * 8;
-
- assert(cycles >= 0);
+ const unsigned int CYCLES_ONE_BATCH = sizeof(tms_bits) * 8;
/* use TMS=1 in TAP RESET state, TMS=0 in all other stable states */
memset(&tms_bits, (tap_get_state() == TAP_RESET) ? 0xff : 0x00, sizeof(tms_bits));
diff --git a/src/jtag/drivers/mpsse.c b/src/jtag/drivers/mpsse.c
index f3499e3..3decddb 100644
--- a/src/jtag/drivers/mpsse.c
+++ b/src/jtag/drivers/mpsse.c
@@ -283,6 +283,9 @@ static bool open_matching_device(struct mpsse_ctx *ctx, const uint16_t vids[], c
case 0x3300:
ctx->type = TYPE_FT232HP;
break;
+ case 0x3600:
+ ctx->type = TYPE_FT4232HA;
+ break;
default:
LOG_ERROR("unsupported FTDI chip type: 0x%04x", desc.bcdDevice);
goto error;
diff --git a/src/jtag/drivers/mpsse.h b/src/jtag/drivers/mpsse.h
index e92a9bb..737560d 100644
--- a/src/jtag/drivers/mpsse.h
+++ b/src/jtag/drivers/mpsse.h
@@ -30,6 +30,7 @@ enum ftdi_chip_type {
TYPE_FT4232HP,
TYPE_FT233HP,
TYPE_FT232HP,
+ TYPE_FT4232HA,
};
struct mpsse_ctx;
diff --git a/src/jtag/drivers/opendous.c b/src/jtag/drivers/opendous.c
index 81b74d4..e828d46 100644
--- a/src/jtag/drivers/opendous.c
+++ b/src/jtag/drivers/opendous.c
@@ -106,8 +106,8 @@ static int opendous_quit(void);
/* Queue command functions */
static void opendous_end_state(tap_state_t state);
static void opendous_state_move(void);
-static void opendous_path_move(int num_states, tap_state_t *path);
-static void opendous_runtest(int num_cycles);
+static void opendous_path_move(unsigned int num_states, tap_state_t *path);
+static void opendous_runtest(unsigned int num_cycles);
static void opendous_scan(int ir_scan, enum scan_type type, uint8_t *buffer,
int scan_size, struct scan_command *command);
static void opendous_reset(int trst, int srst);
@@ -248,7 +248,7 @@ static int opendous_execute_queue(struct jtag_command *cmd_queue)
while (cmd) {
switch (cmd->type) {
case JTAG_RUNTEST:
- LOG_DEBUG_IO("runtest %i cycles, end in %i", cmd->cmd.runtest->num_cycles,
+ LOG_DEBUG_IO("runtest %u cycles, end in %i", cmd->cmd.runtest->num_cycles,
cmd->cmd.runtest->end_state);
if (cmd->cmd.runtest->end_state != -1)
@@ -265,7 +265,7 @@ static int opendous_execute_queue(struct jtag_command *cmd_queue)
break;
case JTAG_PATHMOVE:
- LOG_DEBUG_IO("pathmove: %i states, end in %i",
+ LOG_DEBUG_IO("pathmove: %u states, end in %i",
cmd->cmd.pathmove->num_states,
cmd->cmd.pathmove->path[cmd->cmd.pathmove->num_states - 1]);
@@ -419,11 +419,9 @@ void opendous_state_move(void)
tap_set_state(tap_get_end_state());
}
-void opendous_path_move(int num_states, tap_state_t *path)
+void opendous_path_move(unsigned int num_states, tap_state_t *path)
{
- int i;
-
- for (i = 0; i < num_states; i++) {
+ for (unsigned int i = 0; i < num_states; i++) {
if (path[i] == tap_state_transition(tap_get_state(), false))
opendous_tap_append_step(0, 0);
else if (path[i] == tap_state_transition(tap_get_state(), true))
@@ -440,10 +438,8 @@ void opendous_path_move(int num_states, tap_state_t *path)
tap_set_end_state(tap_get_state());
}
-void opendous_runtest(int num_cycles)
+void opendous_runtest(unsigned int num_cycles)
{
- int i;
-
tap_state_t saved_end_state = tap_get_end_state();
/* only do a state_move when we're not already in IDLE */
@@ -453,7 +449,7 @@ void opendous_runtest(int num_cycles)
}
/* execute num_cycles */
- for (i = 0; i < num_cycles; i++)
+ for (unsigned int i = 0; i < num_cycles; i++)
opendous_tap_append_step(0, 0);
/* finish in end_state */
diff --git a/src/jtag/drivers/openjtag.c b/src/jtag/drivers/openjtag.c
index ea78ca8..0ae885e 100644
--- a/src/jtag/drivers/openjtag.c
+++ b/src/jtag/drivers/openjtag.c
@@ -760,15 +760,17 @@ static void openjtag_execute_runtest(struct jtag_command *cmd)
if (openjtag_variant != OPENJTAG_VARIANT_CY7C65215 ||
cmd->cmd.runtest->num_cycles) {
uint8_t command;
- int cycles = cmd->cmd.runtest->num_cycles;
+ unsigned int num_cycles = cmd->cmd.runtest->num_cycles;
do {
+ const unsigned int num_cycles_cmd = MIN(num_cycles, 16);
+
command = 7;
- command |= (((cycles > 16 ? 16 : cycles) - 1) & 0x0F) << 4;
+ command |= ((num_cycles_cmd - 1) & 0x0F) << 4;
openjtag_add_byte(command);
- cycles -= 16;
- } while (cycles > 0);
+ num_cycles -= num_cycles_cmd;
+ } while (num_cycles > 0);
}
tap_set_end_state(end_state);
diff --git a/src/jtag/drivers/osbdm.c b/src/jtag/drivers/osbdm.c
index 8d4fc90..c41a0e1 100644
--- a/src/jtag/drivers/osbdm.c
+++ b/src/jtag/drivers/osbdm.c
@@ -381,7 +381,7 @@ static int osbdm_quit(void)
static int osbdm_add_pathmove(
struct queue *queue,
tap_state_t *path,
- int num_states)
+ unsigned int num_states)
{
assert(num_states <= 32);
@@ -392,7 +392,7 @@ static int osbdm_add_pathmove(
}
uint32_t tms = 0;
- for (int i = 0; i < num_states; i++) {
+ for (unsigned int i = 0; i < num_states; i++) {
if (tap_state_transition(tap_get_state(), 1) == path[i]) {
tms |= (1 << i);
} else if (tap_state_transition(tap_get_state(), 0) == path[i]) {
@@ -451,7 +451,7 @@ static int osbdm_add_statemove(
static int osbdm_add_stableclocks(
struct queue *queue,
- int count)
+ unsigned int count)
{
if (!tap_is_state_stable(tap_get_state())) {
LOG_ERROR("BUG: current state (%s) is not stable",
@@ -489,7 +489,7 @@ static int osbdm_add_tms(
static int osbdm_add_scan(
struct queue *queue,
struct scan_field *fields,
- int num_fields,
+ unsigned int num_fields,
tap_state_t end_state,
bool ir_scan)
{
@@ -508,7 +508,7 @@ static int osbdm_add_scan(
/* Add scan */
tap_set_end_state(end_state);
- for (int idx = 0; idx < num_fields; idx++) {
+ for (unsigned int idx = 0; idx < num_fields; idx++) {
struct sequence *next = queue_add_tail(queue, fields[idx].num_bits);
if (!next) {
LOG_ERROR("Can't allocate bit sequence");
@@ -536,7 +536,7 @@ static int osbdm_add_scan(
static int osbdm_add_runtest(
struct queue *queue,
- int num_cycles,
+ unsigned int num_cycles,
tap_state_t end_state)
{
if (osbdm_add_statemove(queue, TAP_IDLE, 0) != ERROR_OK)
diff --git a/src/jtag/drivers/rlink.c b/src/jtag/drivers/rlink.c
index afdf16e..f4a4fcb 100644
--- a/src/jtag/drivers/rlink.c
+++ b/src/jtag/drivers/rlink.c
@@ -869,7 +869,7 @@ static void rlink_state_move(void)
static void rlink_path_move(struct pathmove_command *cmd)
{
- int num_states = cmd->num_states;
+ unsigned int num_states = cmd->num_states;
int state_count;
int tms = 0;
@@ -896,10 +896,8 @@ static void rlink_path_move(struct pathmove_command *cmd)
tap_set_end_state(tap_get_state());
}
-static void rlink_runtest(int num_cycles)
+static void rlink_runtest(unsigned int num_cycles)
{
- int i;
-
tap_state_t saved_end_state = tap_get_end_state();
/* only do a state_move when we're not already in RTI */
@@ -909,7 +907,7 @@ static void rlink_runtest(int num_cycles)
}
/* execute num_cycles */
- for (i = 0; i < num_cycles; i++)
+ for (unsigned int i = 0; i < num_cycles; i++)
tap_state_queue_append(0);
/* finish in end_state */
@@ -1323,7 +1321,7 @@ static int rlink_execute_queue(struct jtag_command *cmd_queue)
rlink_state_move();
break;
case JTAG_PATHMOVE:
- LOG_DEBUG_IO("pathmove: %i states, end in %i",
+ LOG_DEBUG_IO("pathmove: %u states, end in %i",
cmd->cmd.pathmove->num_states,
cmd->cmd.pathmove->path[cmd->cmd.pathmove->num_states - 1]);
rlink_path_move(cmd->cmd.pathmove);
diff --git a/src/jtag/drivers/ulink.c b/src/jtag/drivers/ulink.c
index 0fe8989..ad3bc6e 100644
--- a/src/jtag/drivers/ulink.c
+++ b/src/jtag/drivers/ulink.c
@@ -1701,15 +1701,17 @@ static int ulink_queue_reset(struct ulink *device, struct jtag_command *cmd)
*/
static int ulink_queue_pathmove(struct ulink *device, struct jtag_command *cmd)
{
- int ret, i, num_states, batch_size, state_count;
+ int ret, state_count;
tap_state_t *path;
uint8_t tms_sequence;
- num_states = cmd->cmd.pathmove->num_states;
+ unsigned int num_states = cmd->cmd.pathmove->num_states;
path = cmd->cmd.pathmove->path;
state_count = 0;
while (num_states > 0) {
+ unsigned int batch_size;
+
tms_sequence = 0;
/* Determine batch size */
@@ -1718,7 +1720,7 @@ static int ulink_queue_pathmove(struct ulink *device, struct jtag_command *cmd)
else
batch_size = num_states;
- for (i = 0; i < batch_size; i++) {
+ for (unsigned int i = 0; i < batch_size; i++) {
if (tap_state_transition(tap_get_state(), false) == path[state_count]) {
/* Append '0' transition: clear bit 'i' in tms_sequence */
buf_set_u32(&tms_sequence, i, 1, 0x0);
@@ -1774,14 +1776,13 @@ static int ulink_queue_sleep(struct ulink *device, struct jtag_command *cmd)
static int ulink_queue_stableclocks(struct ulink *device, struct jtag_command *cmd)
{
int ret;
- unsigned num_cycles;
if (!tap_is_state_stable(tap_get_state())) {
LOG_ERROR("JTAG_STABLECLOCKS: state not stable");
return ERROR_FAIL;
}
- num_cycles = cmd->cmd.stableclocks->num_cycles;
+ unsigned int num_cycles = cmd->cmd.stableclocks->num_cycles;
/* TMS stays either high (Test Logic Reset state) or low (all other states) */
if (tap_get_state() == TAP_RESET)
diff --git a/src/jtag/drivers/usb_blaster/usb_blaster.c b/src/jtag/drivers/usb_blaster/usb_blaster.c
index c84055c..53dd158 100644
--- a/src/jtag/drivers/usb_blaster/usb_blaster.c
+++ b/src/jtag/drivers/usb_blaster/usb_blaster.c
@@ -474,11 +474,9 @@ static void ublast_tms(struct tms_command *cmd)
*/
static void ublast_path_move(struct pathmove_command *cmd)
{
- int i;
-
- LOG_DEBUG_IO("(num_states=%d, last_state=%d)",
+ LOG_DEBUG_IO("(num_states=%u, last_state=%d)",
cmd->num_states, cmd->path[cmd->num_states - 1]);
- for (i = 0; i < cmd->num_states; i++) {
+ for (unsigned int i = 0; i < cmd->num_states; i++) {
if (tap_state_transition(tap_get_state(), false) == cmd->path[i])
ublast_clock_tms(0);
if (tap_state_transition(tap_get_state(), true) == cmd->path[i])
@@ -675,19 +673,19 @@ static void ublast_queue_tdi(uint8_t *bits, int nb_bits, enum scan_type scan)
ublast_idle_clock();
}
-static void ublast_runtest(int cycles, tap_state_t state)
+static void ublast_runtest(unsigned int num_cycles, tap_state_t state)
{
- LOG_DEBUG_IO("%s(cycles=%i, end_state=%d)", __func__, cycles, state);
+ LOG_DEBUG_IO("%s(cycles=%u, end_state=%d)", __func__, num_cycles, state);
ublast_state_move(TAP_IDLE, 0);
- ublast_queue_tdi(NULL, cycles, SCAN_OUT);
+ ublast_queue_tdi(NULL, num_cycles, SCAN_OUT);
ublast_state_move(state, 0);
}
-static void ublast_stableclocks(int cycles)
+static void ublast_stableclocks(unsigned int num_cycles)
{
- LOG_DEBUG_IO("%s(cycles=%i)", __func__, cycles);
- ublast_queue_tdi(NULL, cycles, SCAN_OUT);
+ LOG_DEBUG_IO("%s(cycles=%u)", __func__, num_cycles);
+ ublast_queue_tdi(NULL, num_cycles, SCAN_OUT);
}
/**
diff --git a/src/jtag/drivers/usbprog.c b/src/jtag/drivers/usbprog.c
index 2d666d0..6e3b3ba 100644
--- a/src/jtag/drivers/usbprog.c
+++ b/src/jtag/drivers/usbprog.c
@@ -37,7 +37,7 @@
static void usbprog_end_state(tap_state_t state);
static void usbprog_state_move(void);
static void usbprog_path_move(struct pathmove_command *cmd);
-static void usbprog_runtest(int num_cycles);
+static void usbprog_runtest(unsigned int num_cycles);
static void usbprog_scan(bool ir_scan, enum scan_type type, uint8_t *buffer, int scan_size);
#define UNKNOWN_COMMAND 0x00
@@ -101,7 +101,7 @@ static int usbprog_execute_queue(struct jtag_command *cmd_queue)
usbprog_reset(cmd->cmd.reset->trst, cmd->cmd.reset->srst);
break;
case JTAG_RUNTEST:
- LOG_DEBUG_IO("runtest %i cycles, end in %i",
+ LOG_DEBUG_IO("runtest %u cycles, end in %i",
cmd->cmd.runtest->num_cycles,
cmd->cmd.runtest->end_state);
usbprog_end_state(cmd->cmd.runtest->end_state);
@@ -113,7 +113,7 @@ static int usbprog_execute_queue(struct jtag_command *cmd_queue)
usbprog_state_move();
break;
case JTAG_PATHMOVE:
- LOG_DEBUG_IO("pathmove: %i states, end in %i",
+ LOG_DEBUG_IO("pathmove: %u states, end in %i",
cmd->cmd.pathmove->num_states,
cmd->cmd.pathmove->path[cmd->cmd.pathmove->num_states - 1]);
usbprog_path_move(cmd->cmd.pathmove);
@@ -189,7 +189,7 @@ static void usbprog_state_move(void)
static void usbprog_path_move(struct pathmove_command *cmd)
{
- int num_states = cmd->num_states;
+ unsigned int num_states = cmd->num_states;
int state_count;
/* There may be queued transitions, and before following a specified
@@ -222,10 +222,8 @@ static void usbprog_path_move(struct pathmove_command *cmd)
tap_set_end_state(tap_get_state());
}
-static void usbprog_runtest(int num_cycles)
+static void usbprog_runtest(unsigned int num_cycles)
{
- int i;
-
/* only do a state_move when we're not already in IDLE */
if (tap_get_state() != TAP_IDLE) {
usbprog_end_state(TAP_IDLE);
@@ -241,7 +239,7 @@ static void usbprog_runtest(int num_cycles)
/* LOG_INFO("NUM CYCLES %i",num_cycles); */
}
- for (i = 0; i < num_cycles; i++) {
+ for (unsigned int i = 0; i < num_cycles; i++) {
usbprog_write(1, 0, 0);
usbprog_write(0, 0, 0);
}
diff --git a/src/jtag/drivers/vdebug.c b/src/jtag/drivers/vdebug.c
index f1fc453..691e576 100644
--- a/src/jtag/drivers/vdebug.c
+++ b/src/jtag/drivers/vdebug.c
@@ -931,11 +931,11 @@ static int vdebug_jtag_tms_seq(const uint8_t *tms, int num, uint8_t f_flush)
static int vdebug_jtag_path_move(struct pathmove_command *cmd, uint8_t f_flush)
{
uint8_t tms[DIV_ROUND_UP(cmd->num_states, 8)];
- LOG_DEBUG_IO("path num states %d", cmd->num_states);
+ LOG_DEBUG_IO("path num states %u", cmd->num_states);
memset(tms, 0, DIV_ROUND_UP(cmd->num_states, 8));
- for (uint8_t i = 0; i < cmd->num_states; i++) {
+ for (unsigned int i = 0; i < cmd->num_states; i++) {
if (tap_state_transition(tap_get_state(), true) == cmd->path[i])
buf_set_u32(tms, i, 1, 1);
tap_set_state(cmd->path[i]);
@@ -970,10 +970,10 @@ static int vdebug_jtag_scan(struct scan_command *cmd, uint8_t f_flush)
uint8_t num_pre = tap_get_tms_path_len(cur, state);
uint8_t tms_post = tap_get_tms_path(state, cmd->end_state);
uint8_t num_post = tap_get_tms_path_len(state, cmd->end_state);
- int num_bits = jtag_scan_size(cmd);
- LOG_DEBUG_IO("scan len:%d fields:%d ir/!dr:%d state cur:%x end:%x",
+ const unsigned int num_bits = jtag_scan_size(cmd);
+ LOG_DEBUG_IO("scan len:%u fields:%u ir/!dr:%d state cur:%x end:%x",
num_bits, cmd->num_fields, cmd->ir_scan, cur, cmd->end_state);
- for (int i = 0; i < cmd->num_fields; i++) {
+ for (unsigned int i = 0; i < cmd->num_fields; i++) {
uint8_t cur_num_pre = i == 0 ? num_pre : 0;
uint8_t cur_tms_pre = i == 0 ? tms_pre : 0;
uint8_t cur_num_post = i == cmd->num_fields - 1 ? num_post : 0;
@@ -992,24 +992,24 @@ static int vdebug_jtag_scan(struct scan_command *cmd, uint8_t f_flush)
return rc;
}
-static int vdebug_jtag_runtest(int cycles, tap_state_t state, uint8_t f_flush)
+static int vdebug_jtag_runtest(unsigned int num_cycles, tap_state_t state, uint8_t f_flush)
{
tap_state_t cur = tap_get_state();
uint8_t tms_pre = tap_get_tms_path(cur, state);
uint8_t num_pre = tap_get_tms_path_len(cur, state);
- LOG_DEBUG_IO("idle len:%d state cur:%x end:%x", cycles, cur, state);
- int rc = vdebug_jtag_shift_tap(vdc.hsocket, pbuf, num_pre, tms_pre, cycles, NULL, 0, 0, NULL, f_flush);
+ LOG_DEBUG_IO("idle len:%u state cur:%x end:%x", num_cycles, cur, state);
+ int rc = vdebug_jtag_shift_tap(vdc.hsocket, pbuf, num_pre, tms_pre, num_cycles, NULL, 0, 0, NULL, f_flush);
if (cur != state)
tap_set_state(state);
return rc;
}
-static int vdebug_jtag_stableclocks(int num, uint8_t f_flush)
+static int vdebug_jtag_stableclocks(unsigned int num_cycles, uint8_t f_flush)
{
- LOG_DEBUG("stab len:%d state cur:%x", num, tap_get_state());
+ LOG_DEBUG("stab len:%u state cur:%x", num_cycles, tap_get_state());
- return vdebug_jtag_shift_tap(vdc.hsocket, pbuf, 0, 0, num, NULL, 0, 0, NULL, f_flush);
+ return vdebug_jtag_shift_tap(vdc.hsocket, pbuf, 0, 0, num_cycles, NULL, 0, 0, NULL, f_flush);
}
static int vdebug_sleep(int us)
diff --git a/src/jtag/drivers/vsllink.c b/src/jtag/drivers/vsllink.c
index 34525d5..ca14217 100644
--- a/src/jtag/drivers/vsllink.c
+++ b/src/jtag/drivers/vsllink.c
@@ -43,10 +43,10 @@ static struct pending_scan_result
/* Queue command functions */
static void vsllink_end_state(tap_state_t state);
static void vsllink_state_move(void);
-static void vsllink_path_move(int num_states, tap_state_t *path);
+static void vsllink_path_move(unsigned int num_states, tap_state_t *path);
static void vsllink_tms(int num_bits, const uint8_t *bits);
-static void vsllink_runtest(int num_cycles);
-static void vsllink_stableclocks(int num_cycles, int tms);
+static void vsllink_runtest(unsigned int num_cycles);
+static void vsllink_stableclocks(unsigned int num_cycles, int tms);
static void vsllink_scan(bool ir_scan, enum scan_type type,
uint8_t *buffer, int scan_size, struct scan_command *command);
static int vsllink_reset(int trst, int srst);
@@ -98,7 +98,7 @@ static int vsllink_execute_queue(struct jtag_command *cmd_queue)
while (cmd) {
switch (cmd->type) {
case JTAG_RUNTEST:
- LOG_DEBUG_IO("runtest %i cycles, end in %s",
+ LOG_DEBUG_IO("runtest %u cycles, end in %s",
cmd->cmd.runtest->num_cycles,
tap_state_name(cmd->cmd.runtest->end_state));
@@ -115,7 +115,7 @@ static int vsllink_execute_queue(struct jtag_command *cmd_queue)
break;
case JTAG_PATHMOVE:
- LOG_DEBUG_IO("pathmove: %i states, end in %s",
+ LOG_DEBUG_IO("pathmove: %u states, end in %s",
cmd->cmd.pathmove->num_states,
tap_state_name(cmd->cmd.pathmove->path[cmd->cmd.pathmove->num_states - 1]));
@@ -161,7 +161,7 @@ static int vsllink_execute_queue(struct jtag_command *cmd_queue)
break;
case JTAG_STABLECLOCKS:
- LOG_DEBUG_IO("add %d clocks",
+ LOG_DEBUG_IO("add %u clocks",
cmd->cmd.stableclocks->num_cycles);
switch (tap_get_state()) {
@@ -371,9 +371,9 @@ static void vsllink_state_move(void)
tap_set_state(tap_get_end_state());
}
-static void vsllink_path_move(int num_states, tap_state_t *path)
+static void vsllink_path_move(unsigned int num_states, tap_state_t *path)
{
- for (int i = 0; i < num_states; i++) {
+ for (unsigned int i = 0; i < num_states; i++) {
if (path[i] == tap_state_transition(tap_get_state(), false))
vsllink_tap_append_step(0, 0);
else if (path[i] == tap_state_transition(tap_get_state(), true))
@@ -397,7 +397,7 @@ static void vsllink_tms(int num_bits, const uint8_t *bits)
vsllink_tap_append_step((bits[i / 8] >> (i % 8)) & 1, 0);
}
-static void vsllink_stableclocks(int num_cycles, int tms)
+static void vsllink_stableclocks(unsigned int num_cycles, int tms)
{
while (num_cycles > 0) {
vsllink_tap_append_step(tms, 0);
@@ -405,7 +405,7 @@ static void vsllink_stableclocks(int num_cycles, int tms)
}
}
-static void vsllink_runtest(int num_cycles)
+static void vsllink_runtest(unsigned int num_cycles)
{
tap_state_t saved_end_state = tap_get_end_state();
diff --git a/src/jtag/drivers/xds110.c b/src/jtag/drivers/xds110.c
index 11fbaaa..f252087 100644
--- a/src/jtag/drivers/xds110.c
+++ b/src/jtag/drivers/xds110.c
@@ -1669,7 +1669,6 @@ static void xds110_execute_tlr_reset(struct jtag_command *cmd)
static void xds110_execute_pathmove(struct jtag_command *cmd)
{
- uint32_t i;
uint32_t num_states;
uint8_t *path;
@@ -1685,7 +1684,7 @@ static void xds110_execute_pathmove(struct jtag_command *cmd)
}
/* Convert requested path states into XDS API states */
- for (i = 0; i < num_states; i++)
+ for (unsigned int i = 0; i < num_states; i++)
path[i] = (uint8_t)xds_jtag_state[cmd->cmd.pathmove->path[i]];
if (xds110.firmware >= OCD_FIRMWARE_VERSION) {
@@ -1704,7 +1703,6 @@ static void xds110_execute_pathmove(struct jtag_command *cmd)
static void xds110_queue_scan(struct jtag_command *cmd)
{
- int i;
uint32_t offset;
uint32_t total_fields;
uint32_t total_bits;
@@ -1715,7 +1713,7 @@ static void xds110_queue_scan(struct jtag_command *cmd)
/* Calculate the total number of bits to scan */
total_bits = 0;
total_fields = 0;
- for (i = 0; i < cmd->cmd.scan->num_fields; i++) {
+ for (unsigned int i = 0; i < cmd->cmd.scan->num_fields; i++) {
total_fields++;
total_bits += (uint32_t)cmd->cmd.scan->fields[i].num_bits;
}
@@ -1756,7 +1754,7 @@ static void xds110_queue_scan(struct jtag_command *cmd)
buffer = &xds110.txn_requests[xds110.txn_request_size];
/* Clear data out buffer to default value of all zeros */
memset((void *)buffer, 0x00, total_bytes);
- for (i = 0; i < cmd->cmd.scan->num_fields; i++) {
+ for (unsigned int i = 0; i < cmd->cmd.scan->num_fields; i++) {
if (cmd->cmd.scan->fields[i].out_value) {
/* Copy over data to scan out into request buffer */
bit_copy(buffer, offset, cmd->cmd.scan->fields[i].out_value, 0,
@@ -1775,7 +1773,7 @@ static void xds110_queue_scan(struct jtag_command *cmd)
static void xds110_queue_runtest(struct jtag_command *cmd)
{
- uint32_t clocks = (uint32_t)cmd->cmd.stableclocks->num_cycles;
+ uint32_t clocks = cmd->cmd.stableclocks->num_cycles;
uint8_t end_state = (uint8_t)xds_jtag_state[cmd->cmd.runtest->end_state];
/* Check if new request would be too large to fit */
@@ -1794,7 +1792,7 @@ static void xds110_queue_runtest(struct jtag_command *cmd)
static void xds110_queue_stableclocks(struct jtag_command *cmd)
{
- uint32_t clocks = (uint32_t)cmd->cmd.stableclocks->num_cycles;
+ uint32_t clocks = cmd->cmd.stableclocks->num_cycles;
/* Check if new request would be too large to fit */
if ((xds110.txn_request_size + 1 + sizeof(clocks) + 1) > MAX_DATA_BLOCK)
diff --git a/src/jtag/drivers/xlnx-pcie-xvc.c b/src/jtag/drivers/xlnx-pcie-xvc.c
index 233ade3..b5c7e2f 100644
--- a/src/jtag/drivers/xlnx-pcie-xvc.c
+++ b/src/jtag/drivers/xlnx-pcie-xvc.c
@@ -128,7 +128,7 @@ static int xlnx_pcie_xvc_execute_stableclocks(struct jtag_command *cmd)
size_t write;
int err;
- LOG_DEBUG("stableclocks %i cycles", cmd->cmd.runtest->num_cycles);
+ LOG_DEBUG("stableclocks %u cycles", cmd->cmd.runtest->num_cycles);
while (left) {
write = MIN(XLNX_XVC_MAX_BITS, left);
@@ -167,7 +167,7 @@ static int xlnx_pcie_xvc_execute_runtest(struct jtag_command *cmd)
{
int err = ERROR_OK;
- LOG_DEBUG("runtest %i cycles, end in %i",
+ LOG_DEBUG("runtest %u cycles, end in %i",
cmd->cmd.runtest->num_cycles,
cmd->cmd.runtest->end_state);
@@ -200,16 +200,15 @@ static int xlnx_pcie_xvc_execute_runtest(struct jtag_command *cmd)
static int xlnx_pcie_xvc_execute_pathmove(struct jtag_command *cmd)
{
- size_t num_states = cmd->cmd.pathmove->num_states;
+ unsigned int num_states = cmd->cmd.pathmove->num_states;
tap_state_t *path = cmd->cmd.pathmove->path;
int err = ERROR_OK;
- size_t i;
- LOG_DEBUG("pathmove: %i states, end in %i",
+ LOG_DEBUG("pathmove: %u states, end in %i",
cmd->cmd.pathmove->num_states,
cmd->cmd.pathmove->path[cmd->cmd.pathmove->num_states - 1]);
- for (i = 0; i < num_states; i++) {
+ for (unsigned int i = 0; i < num_states; i++) {
if (path[i] == tap_state_transition(tap_get_state(), false)) {
err = xlnx_pcie_xvc_transact(1, 1, 0, NULL);
} else if (path[i] == tap_state_transition(tap_get_state(), true)) {
diff --git a/src/jtag/hla/hla_interface.c b/src/jtag/hla/hla_interface.c
index 6ac6801..c73f6c8 100644
--- a/src/jtag/hla/hla_interface.c
+++ b/src/jtag/hla/hla_interface.c
@@ -319,37 +319,37 @@ COMMAND_HANDLER(interface_handle_hla_command)
return ERROR_OK;
}
-static const struct command_registration hl_interface_command_handlers[] = {
+static const struct command_registration hl_interface_subcommand_handlers[] = {
{
- .name = "hla_device_desc",
+ .name = "device_desc",
.handler = &hl_interface_handle_device_desc_command,
.mode = COMMAND_CONFIG,
.help = "set the device description of the adapter",
.usage = "description_string",
},
{
- .name = "hla_layout",
+ .name = "layout",
.handler = &hl_interface_handle_layout_command,
.mode = COMMAND_CONFIG,
.help = "set the layout of the adapter",
.usage = "layout_name",
},
{
- .name = "hla_vid_pid",
+ .name = "vid_pid",
.handler = &hl_interface_handle_vid_pid_command,
.mode = COMMAND_CONFIG,
.help = "the vendor and product ID of the adapter",
.usage = "(vid pid)*",
},
{
- .name = "hla_stlink_backend",
+ .name = "stlink_backend",
.handler = &hl_interface_handle_stlink_backend_command,
.mode = COMMAND_CONFIG,
.help = "select which ST-Link backend to use",
.usage = "usb | tcp [port]",
},
{
- .name = "hla_command",
+ .name = "command",
.handler = &interface_handle_hla_command,
.mode = COMMAND_EXEC,
.help = "execute a custom adapter-specific command",
@@ -358,6 +358,17 @@ static const struct command_registration hl_interface_command_handlers[] = {
COMMAND_REGISTRATION_DONE
};
+static const struct command_registration hl_interface_command_handlers[] = {
+ {
+ .name = "hla",
+ .mode = COMMAND_ANY,
+ .help = "perform hla management",
+ .chain = hl_interface_subcommand_handlers,
+ .usage = "",
+ },
+ COMMAND_REGISTRATION_DONE
+};
+
struct adapter_driver hl_adapter_driver = {
.name = "hla",
.transports = hl_transports,
diff --git a/src/jtag/jtag.h b/src/jtag/jtag.h
index 470ae18..6ba118f 100644
--- a/src/jtag/jtag.h
+++ b/src/jtag/jtag.h
@@ -86,7 +86,7 @@ extern tap_state_t cmd_queue_cur_state;
*/
struct scan_field {
/** The number of bits this field specifies */
- int num_bits;
+ unsigned int num_bits;
/** A pointer to value to be scanned into the device */
const uint8_t *out_value;
/** A pointer to a 32-bit memory location for data scanned out */
@@ -102,12 +102,12 @@ struct jtag_tap {
char *chip;
char *tapname;
char *dotted_name;
- int abs_chain_position;
+ unsigned int abs_chain_position;
/** Is this TAP disabled after JTAG reset? */
bool disabled_after_reset;
/** Is this TAP currently enabled? */
bool enabled;
- int ir_length; /**< size of instruction register */
+ unsigned int ir_length; /**< size of instruction register */
uint32_t ir_capture_value;
uint8_t *expected; /**< Capture-IR expected value */
uint32_t ir_capture_mask;
@@ -150,10 +150,11 @@ struct jtag_tap *jtag_all_taps(void);
const char *jtag_tap_name(const struct jtag_tap *tap);
struct jtag_tap *jtag_tap_by_string(const char *dotted_name);
struct jtag_tap *jtag_tap_by_jim_obj(Jim_Interp *interp, Jim_Obj *obj);
-struct jtag_tap *jtag_tap_by_position(unsigned abs_position);
+struct jtag_tap *jtag_tap_by_position(unsigned int abs_position);
+/* FIXME: "jtag_tap_next_enabled()" should accept a const pointer. */
struct jtag_tap *jtag_tap_next_enabled(struct jtag_tap *p);
-unsigned jtag_tap_count_enabled(void);
-unsigned jtag_tap_count(void);
+unsigned int jtag_tap_count_enabled(void);
+unsigned int jtag_tap_count(void);
/*
* - TRST_ASSERTED triggers two sets of callbacks, after operations to
@@ -229,17 +230,17 @@ enum reset_types {
enum reset_types jtag_get_reset_config(void);
void jtag_set_reset_config(enum reset_types type);
-void jtag_set_nsrst_delay(unsigned delay);
-unsigned jtag_get_nsrst_delay(void);
+void jtag_set_nsrst_delay(unsigned int delay);
+unsigned int jtag_get_nsrst_delay(void);
-void jtag_set_ntrst_delay(unsigned delay);
-unsigned jtag_get_ntrst_delay(void);
+void jtag_set_ntrst_delay(unsigned int delay);
+unsigned int jtag_get_ntrst_delay(void);
-void jtag_set_nsrst_assert_width(unsigned delay);
-unsigned jtag_get_nsrst_assert_width(void);
+void jtag_set_nsrst_assert_width(unsigned int delay);
+unsigned int jtag_get_nsrst_assert_width(void);
-void jtag_set_ntrst_assert_width(unsigned delay);
-unsigned jtag_get_ntrst_assert_width(void);
+void jtag_set_ntrst_assert_width(unsigned int delay);
+unsigned int jtag_get_ntrst_assert_width(void);
/** @returns The current state of TRST. */
int jtag_get_trst(void);
@@ -436,7 +437,7 @@ void jtag_add_tlr(void);
* - ERROR_JTAG_TRANSITION_INVALID -- The path includes invalid
* state transitions.
*/
-void jtag_add_pathmove(int num_states, const tap_state_t *path);
+void jtag_add_pathmove(unsigned int num_states, const tap_state_t *path);
/**
* jtag_add_statemove() moves from the current state to @a goal_state.
@@ -459,7 +460,7 @@ int jtag_add_statemove(tap_state_t goal_state);
* via TAP_IDLE.
* @param endstate The final state.
*/
-void jtag_add_runtest(int num_cycles, tap_state_t endstate);
+void jtag_add_runtest(unsigned int num_cycles, tap_state_t endstate);
/**
* A reset of the TAP state machine can be requested.
@@ -488,14 +489,14 @@ void jtag_add_reset(int req_tlr_or_trst, int srst);
void jtag_add_sleep(uint32_t us);
-int jtag_add_tms_seq(unsigned nbits, const uint8_t *seq, enum tap_state t);
+int jtag_add_tms_seq(unsigned int nbits, const uint8_t *seq, enum tap_state t);
/**
* Function jtag_add_clocks
* first checks that the state in which the clocks are to be issued is
* stable, then queues up num_cycles clocks for transmission.
*/
-void jtag_add_clocks(int num_cycles);
+void jtag_add_clocks(unsigned int num_cycles);
/**
* For software FIFO implementations, the queued commands can be executed
@@ -523,7 +524,7 @@ int jtag_execute_queue(void);
void jtag_execute_queue_noclear(void);
/** @returns the number of times the scan queue has been flushed */
-int jtag_get_flush_queue_count(void);
+unsigned int jtag_get_flush_queue_count(void);
/** Report Tcl event to all TAPs */
void jtag_notify_event(enum jtag_event);
diff --git a/src/jtag/minidriver.h b/src/jtag/minidriver.h
index a40cffa..45b0bf6 100644
--- a/src/jtag/minidriver.h
+++ b/src/jtag/minidriver.h
@@ -51,8 +51,8 @@ int interface_jtag_add_plain_dr_scan(
tap_state_t endstate);
int interface_jtag_add_tlr(void);
-int interface_jtag_add_pathmove(int num_states, const tap_state_t *path);
-int interface_jtag_add_runtest(int num_cycles, tap_state_t endstate);
+int interface_jtag_add_pathmove(unsigned int num_states, const tap_state_t *path);
+int interface_jtag_add_runtest(unsigned int num_cycles, tap_state_t endstate);
int interface_add_tms_seq(unsigned num_bits,
const uint8_t *bits, enum tap_state state);
@@ -67,7 +67,7 @@ int interface_add_tms_seq(unsigned num_bits,
*/
int interface_jtag_add_reset(int trst, int srst);
int interface_jtag_add_sleep(uint32_t us);
-int interface_jtag_add_clocks(int num_cycles);
+int interface_jtag_add_clocks(unsigned int num_cycles);
int interface_jtag_execute_queue(void);
/**
diff --git a/src/jtag/startup.tcl b/src/jtag/startup.tcl
index 41db38e..2d8ebf0 100644
--- a/src/jtag/startup.tcl
+++ b/src/jtag/startup.tcl
@@ -1126,6 +1126,36 @@ proc "cmsis_dap_usb" {args} {
eval cmsis-dap usb $args
}
+lappend _telnet_autocomplete_skip "hla_layout"
+proc "hla_layout" {layout} {
+ echo "DEPRECATED! use 'hla layout', not 'hla_layout'"
+ eval hla layout $layout
+}
+
+lappend _telnet_autocomplete_skip "hla_device_desc"
+proc "hla_device_desc" {desc} {
+ echo "DEPRECATED! use 'hla device_desc', not 'hla_device_desc'"
+ eval hla device_desc $desc
+}
+
+lappend _telnet_autocomplete_skip "hla_vid_pid"
+proc "hla_vid_pid" {args} {
+ echo "DEPRECATED! use 'hla vid_pid', not 'hla_vid_pid'"
+ eval hla vid_pid $args
+}
+
+lappend _telnet_autocomplete_skip "hla_command"
+proc "hla_command" {command} {
+ echo "DEPRECATED! use 'hla command', not 'hla_command'"
+ eval hla command $command
+}
+
+lappend _telnet_autocomplete_skip "hla_stlink_backend"
+proc "hla_stlink_backend" {args} {
+ echo "DEPRECATED! use 'hla stlink_backend', not 'hla_stlink_backend'"
+ eval hla stlink_backend $args
+}
+
lappend _telnet_autocomplete_skip "kitprog_init_acquire_psoc"
proc "kitprog_init_acquire_psoc" {} {
echo "DEPRECATED! use 'kitprog init_acquire_psoc', not 'kitprog_init_acquire_psoc'"
diff --git a/src/jtag/tcl.c b/src/jtag/tcl.c
index 1a4c4b7..624b4e4 100644
--- a/src/jtag/tcl.c
+++ b/src/jtag/tcl.c
@@ -87,8 +87,11 @@ static COMMAND_HELPER(handle_jtag_command_drscan_fields, struct scan_field *fiel
LOG_ERROR("Out of memory");
return ERROR_FAIL;
}
+
fields[field_count].out_value = t;
- str_to_buf(CMD_ARGV[i + 1], strlen(CMD_ARGV[i + 1]), t, bits, 0);
+ int ret = CALL_COMMAND_HANDLER(command_parse_str_to_buf, CMD_ARGV[i + 1], t, bits);
+ if (ret != ERROR_OK)
+ return ret;
fields[field_count].in_value = t;
field_count++;
}
@@ -209,8 +212,8 @@ COMMAND_HANDLER(handle_jtag_flush_count)
if (CMD_ARGC != 0)
return ERROR_COMMAND_SYNTAX_ERROR;
- int count = jtag_get_flush_queue_count();
- command_print_sameline(CMD, "%d", count);
+ const unsigned int count = jtag_get_flush_queue_count();
+ command_print_sameline(CMD, "%u", count);
return ERROR_OK;
}
@@ -445,11 +448,11 @@ static COMMAND_HELPER(handle_jtag_newtap_args, struct jtag_tap *tap)
if (!CMD_ARGC)
return ERROR_COMMAND_ARGUMENT_INVALID;
- COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], tap->ir_length);
+ COMMAND_PARSE_NUMBER(uint, CMD_ARGV[0], tap->ir_length);
CMD_ARGC--;
CMD_ARGV++;
- if (tap->ir_length > (int)(8 * sizeof(tap->ir_capture_value)))
- LOG_WARNING("%s: huge IR length %d", tap->dotted_name, tap->ir_length);
+ if (tap->ir_length > (8 * sizeof(tap->ir_capture_value)))
+ LOG_WARNING("%s: huge IR length %u", tap->dotted_name, tap->ir_length);
break;
case NTAP_OPT_IRMASK:
@@ -811,13 +814,13 @@ COMMAND_HANDLER(handle_scan_chain_command)
expected_mask = buf_get_u32(tap->expected_mask, 0, tap->ir_length);
command_print(CMD,
- "%2d %-18s %c 0x%08x %s %5d 0x%02x 0x%02x",
+ "%2u %-18s %c 0x%08x %s %5u 0x%02x 0x%02x",
tap->abs_chain_position,
tap->dotted_name,
tap->enabled ? 'Y' : 'n',
(unsigned int)(tap->idcode),
expected_id,
- (unsigned int)(tap->ir_length),
+ tap->ir_length,
(unsigned int)(expected),
(unsigned int)(expected_mask));
@@ -969,7 +972,7 @@ COMMAND_HANDLER(handle_irscan_command)
if (retval != ERROR_OK)
goto error_return;
- int field_size = tap->ir_length;
+ unsigned int field_size = tap->ir_length;
fields[i].num_bits = field_size;
uint8_t *v = calloc(1, DIV_ROUND_UP(field_size, 8));
if (!v) {
diff --git a/src/rtos/hwthread.c b/src/rtos/hwthread.c
index f256bc2..e82ab6f 100644
--- a/src/rtos/hwthread.c
+++ b/src/rtos/hwthread.c
@@ -36,7 +36,18 @@ struct target *hwthread_swbp_target(struct rtos *rtos, target_addr_t address,
static inline threadid_t threadid_from_target(const struct target *target)
{
- return target->coreid + 1;
+ if (!target->smp)
+ return 1;
+
+ threadid_t threadid = 1;
+ struct target_list *head;
+ foreach_smp_target(head, target->smp_targets) {
+ if (target == head->target)
+ return threadid;
+ ++threadid;
+ }
+ assert(0 && "Target is not found in it's own SMP group!");
+ return -1;
}
const struct rtos_type hwthread_rtos = {
@@ -59,14 +70,13 @@ struct hwthread_params {
int dummy_param;
};
-static int hwthread_fill_thread(struct rtos *rtos, struct target *curr, int thread_num)
+static int hwthread_fill_thread(struct rtos *rtos, struct target *curr, int thread_num, threadid_t tid)
{
char tmp_str[HW_THREAD_NAME_STR_SIZE];
- threadid_t tid = threadid_from_target(curr);
memset(tmp_str, 0, HW_THREAD_NAME_STR_SIZE);
- /* thread-id is the core-id of this core inside the SMP group plus 1 */
+ /* thread-id is the index of this core inside the SMP group plus 1 */
rtos->thread_details[thread_num].threadid = tid;
/* create the thread name */
rtos->thread_details[thread_num].exists = true;
@@ -131,8 +141,7 @@ static int hwthread_update_threads(struct rtos *rtos)
continue;
threadid_t tid = threadid_from_target(curr);
-
- hwthread_fill_thread(rtos, curr, threads_found);
+ hwthread_fill_thread(rtos, curr, threads_found, tid);
/* find an interesting thread to set as current */
switch (current_reason) {
@@ -189,8 +198,8 @@ static int hwthread_update_threads(struct rtos *rtos)
threads_found++;
}
} else {
- hwthread_fill_thread(rtos, target, threads_found);
- current_thread = threadid_from_target(target);
+ current_thread = 1;
+ hwthread_fill_thread(rtos, target, threads_found, current_thread);
threads_found++;
}
@@ -213,19 +222,17 @@ static int hwthread_smp_init(struct target *target)
return hwthread_update_threads(target->rtos);
}
-static struct target *hwthread_find_thread(struct target *target, int64_t thread_id)
+static struct target *hwthread_find_thread(struct target *target, threadid_t thread_id)
{
- /* Find the thread with that thread_id */
- if (!target)
- return NULL;
- if (target->smp) {
- struct target_list *head;
- foreach_smp_target(head, target->smp_targets) {
- if (thread_id == threadid_from_target(head->target))
- return head->target;
- }
- } else if (thread_id == threadid_from_target(target)) {
+ /* Find the thread with that thread_id (index in SMP group plus 1)*/
+ if (!(target && target->smp))
return target;
+ struct target_list *head;
+ threadid_t tid = 1;
+ foreach_smp_target(head, target->smp_targets) {
+ if (thread_id == tid)
+ return head->target;
+ ++tid;
}
return NULL;
}
@@ -304,7 +311,7 @@ static int hwthread_get_thread_reg_value(struct rtos *rtos, int64_t thread_id,
}
if (!target_was_examined(curr)) {
- LOG_ERROR("Target %d hasn't been examined yet.", curr->coreid);
+ LOG_TARGET_ERROR(curr, "Target hasn't been examined yet.");
return ERROR_FAIL;
}
@@ -392,9 +399,9 @@ static int hwthread_thread_packet(struct connection *connection, const char *pac
return ERROR_FAIL;
}
target->rtos->current_thread = current_threadid;
- } else
- if (current_threadid == 0 || current_threadid == -1)
+ } else if (current_threadid == 0 || current_threadid == -1) {
target->rtos->current_thread = threadid_from_target(target);
+ }
target->rtos->current_threadid = current_threadid;
diff --git a/src/rtos/nuttx.c b/src/rtos/nuttx.c
index 9100148..821e550 100644
--- a/src/rtos/nuttx.c
+++ b/src/rtos/nuttx.c
@@ -32,7 +32,6 @@
struct nuttx_params {
const char *target_name;
const struct rtos_register_stacking *stacking;
- const struct rtos_register_stacking *(*select_stackinfo)(struct target *target);
};
/*
@@ -56,19 +55,12 @@ struct symbols {
bool optional;
};
-/* Used to index the list of retrieved symbols. See nuttx_symbol_list for the order. */
-enum nuttx_symbol_vals {
- NX_SYM_READYTORUN = 0,
- NX_SYM_PIDHASH,
- NX_SYM_NPIDHASH,
- NX_SYM_TCB_INFO,
-};
-
static const struct symbols nuttx_symbol_list[] = {
{ "g_readytorun", false },
{ "g_pidhash", false },
{ "g_npidhash", false },
{ "g_tcbinfo", false },
+ { "g_reg_offs", false},
{ NULL, false }
};
@@ -86,18 +78,14 @@ static char *task_state_str[] = {
"STOPPED",
};
-static const struct rtos_register_stacking *cortexm_select_stackinfo(struct target *target);
-
static const struct nuttx_params nuttx_params_list[] = {
{
.target_name = "cortex_m",
- .stacking = NULL,
- .select_stackinfo = cortexm_select_stackinfo,
+ .stacking = &nuttx_stacking_cortex_m,
},
{
.target_name = "hla_target",
- .stacking = NULL,
- .select_stackinfo = cortexm_select_stackinfo,
+ .stacking = &nuttx_stacking_cortex_m,
},
{
.target_name = "esp32",
@@ -117,28 +105,6 @@ static const struct nuttx_params nuttx_params_list[] = {
},
};
-static bool cortexm_hasfpu(struct target *target)
-{
- uint32_t cpacr;
- struct armv7m_common *armv7m_target = target_to_armv7m(target);
-
- if (!is_armv7m(armv7m_target) || armv7m_target->fp_feature == FP_NONE)
- return false;
-
- int retval = target_read_u32(target, FPU_CPACR, &cpacr);
- if (retval != ERROR_OK) {
- LOG_ERROR("Could not read CPACR register to check FPU state");
- return false;
- }
-
- return cpacr & 0x00F00000;
-}
-
-static const struct rtos_register_stacking *cortexm_select_stackinfo(struct target *target)
-{
- return cortexm_hasfpu(target) ? &nuttx_stacking_cortex_m_fpu : &nuttx_stacking_cortex_m;
-}
-
static bool nuttx_detect_rtos(struct target *target)
{
if (target->rtos->symbols &&
@@ -371,29 +337,25 @@ static int nuttx_getreg_current_thread(struct rtos *rtos,
static int nuttx_getregs_fromstack(struct rtos *rtos, int64_t thread_id,
struct rtos_reg **reg_list, int *num_regs)
{
- uint16_t xcpreg_off;
+ uint16_t regs_off;
uint32_t regsaddr;
const struct nuttx_params *priv = rtos->rtos_specific_params;
const struct rtos_register_stacking *stacking = priv->stacking;
if (!stacking) {
- if (priv->select_stackinfo) {
- stacking = priv->select_stackinfo(rtos->target);
- } else {
- LOG_ERROR("Can't find a way to get stacking info");
- return ERROR_FAIL;
- }
+ LOG_ERROR("Can't find a way to get stacking info");
+ return ERROR_FAIL;
}
int ret = target_read_u16(rtos->target,
rtos->symbols[NX_SYM_TCB_INFO].address + offsetof(struct tcbinfo, regs_off),
- &xcpreg_off);
+ &regs_off);
if (ret != ERROR_OK) {
LOG_ERROR("Failed to read registers' offset: ret = %d", ret);
return ERROR_FAIL;
}
- ret = target_read_u32(rtos->target, thread_id + xcpreg_off, &regsaddr);
+ ret = target_read_u32(rtos->target, thread_id + regs_off, &regsaddr);
if (ret != ERROR_OK) {
LOG_ERROR("Failed to read registers' address: ret = %d", ret);
return ERROR_FAIL;
diff --git a/src/rtos/rtos_nuttx_stackings.c b/src/rtos/rtos_nuttx_stackings.c
index b70cccb..6faa56a 100644
--- a/src/rtos/rtos_nuttx_stackings.c
+++ b/src/rtos/rtos_nuttx_stackings.c
@@ -9,60 +9,100 @@
#include "rtos_nuttx_stackings.h"
#include "rtos_standard_stackings.h"
#include <target/riscv/riscv.h>
+#include <helper/bits.h>
-/* see arch/arm/include/armv7-m/irq_cmnvector.h */
+/* The cortex_m target uses nuttx_tcbinfo_stack_read which uses a symbol
+ * provided by Nuttx to read the registers from memory and place them directly
+ * in the order we need. This is because the register offsets change with
+ * different versions of Nuttx, FPU vs non-FPU and ARMv7 vs ARMv8.
+ * This allows a single function to work with many versions.
+ */
static const struct stack_register_offset nuttx_stack_offsets_cortex_m[] = {
- { ARMV7M_R0, 0x28, 32 }, /* r0 */
- { ARMV7M_R1, 0x2c, 32 }, /* r1 */
- { ARMV7M_R2, 0x30, 32 }, /* r2 */
- { ARMV7M_R3, 0x34, 32 }, /* r3 */
- { ARMV7M_R4, 0x08, 32 }, /* r4 */
- { ARMV7M_R5, 0x0c, 32 }, /* r5 */
- { ARMV7M_R6, 0x10, 32 }, /* r6 */
- { ARMV7M_R7, 0x14, 32 }, /* r7 */
- { ARMV7M_R8, 0x18, 32 }, /* r8 */
- { ARMV7M_R9, 0x1c, 32 }, /* r9 */
- { ARMV7M_R10, 0x20, 32 }, /* r10 */
- { ARMV7M_R11, 0x24, 32 }, /* r11 */
- { ARMV7M_R12, 0x38, 32 }, /* r12 */
- { ARMV7M_R13, 0, 32 }, /* sp */
- { ARMV7M_R14, 0x3c, 32 }, /* lr */
- { ARMV7M_PC, 0x40, 32 }, /* pc */
- { ARMV7M_XPSR, 0x44, 32 }, /* xPSR */
+ { ARMV7M_R0, 0, 32 }, /* r0 */
+ { ARMV7M_R1, 4, 32 }, /* r1 */
+ { ARMV7M_R2, 8, 32 }, /* r2 */
+ { ARMV7M_R3, 12, 32 }, /* r3 */
+ { ARMV7M_R4, 16, 32 }, /* r4 */
+ { ARMV7M_R5, 20, 32 }, /* r5 */
+ { ARMV7M_R6, 24, 32 }, /* r6 */
+ { ARMV7M_R7, 28, 32 }, /* r7 */
+ { ARMV7M_R8, 32, 32 }, /* r8 */
+ { ARMV7M_R9, 36, 32 }, /* r9 */
+ { ARMV7M_R10, 40, 32 }, /* r10 */
+ { ARMV7M_R11, 44, 32 }, /* r11 */
+ { ARMV7M_R12, 48, 32 }, /* r12 */
+ { ARMV7M_R13, 52, 32 }, /* sp */
+ { ARMV7M_R14, 56, 32 }, /* lr */
+ { ARMV7M_PC, 60, 32 }, /* pc */
+ { ARMV7M_XPSR, 64, 32 }, /* xPSR */
};
-const struct rtos_register_stacking nuttx_stacking_cortex_m = {
- .stack_registers_size = 0x48,
- .stack_growth_direction = -1,
- .num_output_registers = 17,
- .register_offsets = nuttx_stack_offsets_cortex_m,
-};
+/* The Nuttx stack frame for most architectures has some registers placed
+ * by hardware and some by software. The hardware register order and number does not change
+ * but the software registers may change with different versions of Nuttx.
+ * For example with ARMv7, nuttx-12.3.0 added a new register which changed all
+ * the offsets. We can either create separate offset tables for each version of Nuttx
+ * which will break again in the future, or read the offsets from the TCB info.
+ * Nuttx provides a symbol (g_reg_offs) which holds all the offsets for each stored register.
+ * This offset table is stored in GDB org.gnu.gdb.xxx feature order.
+ * The same order we need.
+ * Please refer:
+ * https://sourceware.org/gdb/current/onlinedocs/gdb/ARM-Features.html
+ * https://sourceware.org/gdb/current/onlinedocs/gdb/RISC_002dV-Features.html
+ */
+static int nuttx_cortex_m_tcbinfo_stack_read(struct target *target,
+ int64_t stack_ptr, const struct rtos_register_stacking *stacking,
+ uint8_t *stack_data)
+{
+ struct rtos *rtos = target->rtos;
+ target_addr_t xcpreg_off = rtos->symbols[NX_SYM_REG_OFFSETS].address;
-static const struct stack_register_offset nuttx_stack_offsets_cortex_m_fpu[] = {
- { ARMV7M_R0, 0x6c, 32 }, /* r0 */
- { ARMV7M_R1, 0x70, 32 }, /* r1 */
- { ARMV7M_R2, 0x74, 32 }, /* r2 */
- { ARMV7M_R3, 0x78, 32 }, /* r3 */
- { ARMV7M_R4, 0x08, 32 }, /* r4 */
- { ARMV7M_R5, 0x0c, 32 }, /* r5 */
- { ARMV7M_R6, 0x10, 32 }, /* r6 */
- { ARMV7M_R7, 0x14, 32 }, /* r7 */
- { ARMV7M_R8, 0x18, 32 }, /* r8 */
- { ARMV7M_R9, 0x1c, 32 }, /* r9 */
- { ARMV7M_R10, 0x20, 32 }, /* r10 */
- { ARMV7M_R11, 0x24, 32 }, /* r11 */
- { ARMV7M_R12, 0x7c, 32 }, /* r12 */
- { ARMV7M_R13, 0, 32 }, /* sp */
- { ARMV7M_R14, 0x80, 32 }, /* lr */
- { ARMV7M_PC, 0x84, 32 }, /* pc */
- { ARMV7M_XPSR, 0x88, 32 }, /* xPSR */
-};
+ for (int i = 0; i < stacking->num_output_registers; ++i) {
+ uint16_t stack_reg_offset;
+ int ret = target_read_u16(rtos->target, xcpreg_off + 2 * i, &stack_reg_offset);
+ if (ret != ERROR_OK) {
+ LOG_ERROR("Failed to read stack_reg_offset: ret = %d", ret);
+ return ret;
+ }
+ if (stack_reg_offset != UINT16_MAX && stacking->register_offsets[i].offset >= 0) {
+ ret = target_read_buffer(target,
+ stack_ptr + stack_reg_offset,
+ stacking->register_offsets[i].width_bits / 8,
+ &stack_data[stacking->register_offsets[i].offset]);
+ if (ret != ERROR_OK) {
+ LOG_ERROR("Failed to read register: ret = %d", ret);
+ return ret;
+ }
+ }
+ }
+
+ /* Offset match nuttx_stack_offsets_cortex_m */
+ const int XPSR_OFFSET = 64;
+ const int SP_OFFSET = 52;
+ /* Nuttx stack frames (produced in exception_common) store the SP of the ISR minus
+ * the hardware stack frame size. This SP may include an additional 4 byte alignment
+ * depending in xPSR[9]. The Nuttx stack frame stores post alignment since the
+ * hardware will add/remove automatically on both enter/exit.
+ * We need to adjust the SP to get the real SP of the stack.
+ * See Arm Reference manual "Stack alignment on exception entry"
+ */
+ uint32_t xpsr = target_buffer_get_u32(target, &stack_data[XPSR_OFFSET]);
+ if (xpsr & BIT(9)) {
+ uint32_t sp = target_buffer_get_u32(target, &stack_data[SP_OFFSET]);
+ target_buffer_set_u32(target, &stack_data[SP_OFFSET], sp - 4 * stacking->stack_growth_direction);
+ }
-const struct rtos_register_stacking nuttx_stacking_cortex_m_fpu = {
- .stack_registers_size = 0x8c,
+ return ERROR_OK;
+}
+
+const struct rtos_register_stacking nuttx_stacking_cortex_m = {
+ /* nuttx_tcbinfo_stack_read transforms the stack into just output registers */
+ .stack_registers_size = ARRAY_SIZE(nuttx_stack_offsets_cortex_m) * 4,
.stack_growth_direction = -1,
- .num_output_registers = 17,
- .register_offsets = nuttx_stack_offsets_cortex_m_fpu,
+ .num_output_registers = ARRAY_SIZE(nuttx_stack_offsets_cortex_m),
+ .read_stack = nuttx_cortex_m_tcbinfo_stack_read,
+ .calculate_process_stack = NULL, /* Stack alignment done in nuttx_cortex_m_tcbinfo_stack_read */
+ .register_offsets = nuttx_stack_offsets_cortex_m,
};
static const struct stack_register_offset nuttx_stack_offsets_riscv[] = {
diff --git a/src/rtos/rtos_nuttx_stackings.h b/src/rtos/rtos_nuttx_stackings.h
index 213a060..5d55e75 100644
--- a/src/rtos/rtos_nuttx_stackings.h
+++ b/src/rtos/rtos_nuttx_stackings.h
@@ -5,6 +5,15 @@
#include "rtos.h"
+/* Used to index the list of retrieved symbols. See nuttx_symbol_list for the order. */
+enum nuttx_symbol_vals {
+ NX_SYM_READYTORUN = 0,
+ NX_SYM_PIDHASH,
+ NX_SYM_NPIDHASH,
+ NX_SYM_TCB_INFO,
+ NX_SYM_REG_OFFSETS,
+};
+
extern const struct rtos_register_stacking nuttx_stacking_cortex_m;
extern const struct rtos_register_stacking nuttx_stacking_cortex_m_fpu;
extern const struct rtos_register_stacking nuttx_riscv_stacking;
diff --git a/src/rtos/rtos_standard_stackings.c b/src/rtos/rtos_standard_stackings.c
index 0ca664f..360ae9b 100644
--- a/src/rtos/rtos_standard_stackings.c
+++ b/src/rtos/rtos_standard_stackings.c
@@ -327,9 +327,7 @@ target_addr_t rtos_cortex_m_stack_align(struct target *target,
new_stack_ptr = stack_ptr - stacking->stack_growth_direction *
stacking->stack_registers_size;
- xpsr = (target->endianness == TARGET_LITTLE_ENDIAN) ?
- le_to_h_u32(&stack_data[xpsr_offset]) :
- be_to_h_u32(&stack_data[xpsr_offset]);
+ xpsr = target_buffer_get_u32(target, &stack_data[xpsr_offset]);
if ((xpsr & ALIGN_NEEDED) != 0) {
LOG_DEBUG("XPSR(0x%08" PRIx32 ") indicated stack alignment was necessary\r\n",
xpsr);
diff --git a/src/rtt/tcl.c b/src/rtt/tcl.c
index 2b8822f..bae71b6 100644
--- a/src/rtt/tcl.c
+++ b/src/rtt/tcl.c
@@ -19,8 +19,14 @@ COMMAND_HANDLER(handle_rtt_setup_command)
{
struct rtt_source source;
- if (CMD_ARGC != 3)
+ const char *DEFAULT_ID = "SEGGER RTT";
+ const char *selected_id;
+ if (CMD_ARGC < 2 || CMD_ARGC > 3)
return ERROR_COMMAND_SYNTAX_ERROR;
+ if (CMD_ARGC == 2)
+ selected_id = DEFAULT_ID;
+ else
+ selected_id = CMD_ARGV[2];
source.find_cb = &target_rtt_find_control_block;
source.read_cb = &target_rtt_read_control_block;
@@ -38,7 +44,7 @@ COMMAND_HANDLER(handle_rtt_setup_command)
rtt_register_source(source, get_current_target(CMD_CTX));
- if (rtt_setup(address, size, CMD_ARGV[2]) != ERROR_OK)
+ if (rtt_setup(address, size, selected_id) != ERROR_OK)
return ERROR_FAIL;
return ERROR_OK;
@@ -218,7 +224,7 @@ static const struct command_registration rtt_subcommand_handlers[] = {
.handler = handle_rtt_setup_command,
.mode = COMMAND_ANY,
.help = "setup RTT",
- .usage = "<address> <size> <ID>"
+ .usage = "<address> <size> [ID]"
},
{
.name = "start",
diff --git a/src/server/gdb_server.c b/src/server/gdb_server.c
index f4ce5df..8553137 100644
--- a/src/server/gdb_server.c
+++ b/src/server/gdb_server.c
@@ -1599,7 +1599,7 @@ static int gdb_read_memory_packet(struct connection *connection,
* cmd = view%20audit-trail&database = gdb&pr = 2395
*
* For now, the default is to fix up things to make current GDB versions work.
- * This can be overwritten using the gdb_report_data_abort <'enable'|'disable'> command.
+ * This can be overwritten using the "gdb report_data_abort <'enable'|'disable'>" command.
*/
memset(buffer, 0, len);
retval = ERROR_OK;
@@ -1838,18 +1838,9 @@ static int gdb_breakpoint_watchpoint_packet(struct connection *connection,
return ERROR_FAIL;
}
retval = breakpoint_add(target, address, size, bp_type);
- if (retval == ERROR_NOT_IMPLEMENTED) {
- /* Send empty reply to report that breakpoints of this type are not supported */
- gdb_put_packet(connection, "", 0);
- } else if (retval != ERROR_OK) {
- retval = gdb_error(connection, retval);
- if (retval != ERROR_OK)
- return retval;
- } else
- gdb_put_packet(connection, "OK", 2);
} else {
- breakpoint_remove(target, address);
- gdb_put_packet(connection, "OK", 2);
+ assert(packet[0] == 'z');
+ retval = breakpoint_remove(target, address);
}
break;
case 2:
@@ -1858,26 +1849,26 @@ static int gdb_breakpoint_watchpoint_packet(struct connection *connection,
{
if (packet[0] == 'Z') {
retval = watchpoint_add(target, address, size, wp_type, 0, WATCHPOINT_IGNORE_DATA_VALUE_MASK);
- if (retval == ERROR_NOT_IMPLEMENTED) {
- /* Send empty reply to report that watchpoints of this type are not supported */
- gdb_put_packet(connection, "", 0);
- } else if (retval != ERROR_OK) {
- retval = gdb_error(connection, retval);
- if (retval != ERROR_OK)
- return retval;
- } else
- gdb_put_packet(connection, "OK", 2);
} else {
- watchpoint_remove(target, address);
- gdb_put_packet(connection, "OK", 2);
+ assert(packet[0] == 'z');
+ retval = watchpoint_remove(target, address);
}
break;
}
default:
+ {
+ retval = ERROR_NOT_IMPLEMENTED;
break;
+ }
}
- return ERROR_OK;
+ if (retval == ERROR_NOT_IMPLEMENTED) {
+ /* Send empty reply to report that watchpoints of this type are not supported */
+ return gdb_put_packet(connection, "", 0);
+ }
+ if (retval != ERROR_OK)
+ return gdb_error(connection, retval);
+ return gdb_put_packet(connection, "OK", 2);
}
/* print out a string and allocate more space as needed,
@@ -4034,7 +4025,7 @@ COMMAND_HANDLER(handle_gdb_sync_command)
if (!current_gdb_connection) {
command_print(CMD,
- "gdb_sync command can only be run from within gdb using \"monitor gdb_sync\"");
+ "gdb sync command can only be run from within gdb using \"monitor gdb sync\"");
return ERROR_FAIL;
}
@@ -4043,7 +4034,6 @@ COMMAND_HANDLER(handle_gdb_sync_command)
return ERROR_OK;
}
-/* daemon configuration command gdb_port */
COMMAND_HANDLER(handle_gdb_port_command)
{
int retval = CALL_COMMAND_HANDLER(server_pipe_command, &gdb_port);
@@ -4090,7 +4080,6 @@ COMMAND_HANDLER(handle_gdb_report_register_access_error)
return ERROR_OK;
}
-/* gdb_breakpoint_override */
COMMAND_HANDLER(handle_gdb_breakpoint_override_command)
{
if (CMD_ARGC == 0) {
@@ -4167,9 +4156,9 @@ out:
return retval;
}
-static const struct command_registration gdb_command_handlers[] = {
+static const struct command_registration gdb_subcommand_handlers[] = {
{
- .name = "gdb_sync",
+ .name = "sync",
.handler = handle_gdb_sync_command,
.mode = COMMAND_ANY,
.help = "next stepi will return immediately allowing "
@@ -4178,7 +4167,7 @@ static const struct command_registration gdb_command_handlers[] = {
.usage = ""
},
{
- .name = "gdb_port",
+ .name = "port",
.handler = handle_gdb_port_command,
.mode = COMMAND_CONFIG,
.help = "Normally gdb listens to a TCP/IP port. Each subsequent GDB "
@@ -4191,35 +4180,35 @@ static const struct command_registration gdb_command_handlers[] = {
.usage = "[port_num]",
},
{
- .name = "gdb_memory_map",
+ .name = "memory_map",
.handler = handle_gdb_memory_map_command,
.mode = COMMAND_CONFIG,
.help = "enable or disable memory map",
.usage = "('enable'|'disable')"
},
{
- .name = "gdb_flash_program",
+ .name = "flash_program",
.handler = handle_gdb_flash_program_command,
.mode = COMMAND_CONFIG,
.help = "enable or disable flash program",
.usage = "('enable'|'disable')"
},
{
- .name = "gdb_report_data_abort",
+ .name = "report_data_abort",
.handler = handle_gdb_report_data_abort_command,
.mode = COMMAND_CONFIG,
.help = "enable or disable reporting data aborts",
.usage = "('enable'|'disable')"
},
{
- .name = "gdb_report_register_access_error",
+ .name = "report_register_access_error",
.handler = handle_gdb_report_register_access_error,
.mode = COMMAND_CONFIG,
.help = "enable or disable reporting register access errors",
.usage = "('enable'|'disable')"
},
{
- .name = "gdb_breakpoint_override",
+ .name = "breakpoint_override",
.handler = handle_gdb_breakpoint_override_command,
.mode = COMMAND_ANY,
.help = "Display or specify type of breakpoint "
@@ -4227,14 +4216,14 @@ static const struct command_registration gdb_command_handlers[] = {
.usage = "('hard'|'soft'|'disable')"
},
{
- .name = "gdb_target_description",
+ .name = "target_description",
.handler = handle_gdb_target_description_command,
.mode = COMMAND_CONFIG,
.help = "enable or disable target description",
.usage = "('enable'|'disable')"
},
{
- .name = "gdb_save_tdesc",
+ .name = "save_tdesc",
.handler = handle_gdb_save_tdesc_command,
.mode = COMMAND_EXEC,
.help = "Save the target description file",
@@ -4243,6 +4232,17 @@ static const struct command_registration gdb_command_handlers[] = {
COMMAND_REGISTRATION_DONE
};
+static const struct command_registration gdb_command_handlers[] = {
+ {
+ .name = "gdb",
+ .mode = COMMAND_ANY,
+ .help = "GDB commands",
+ .chain = gdb_subcommand_handlers,
+ .usage = "",
+ },
+ COMMAND_REGISTRATION_DONE
+};
+
int gdb_register_commands(struct command_context *cmd_ctx)
{
gdb_port = strdup("3333");
diff --git a/src/server/startup.tcl b/src/server/startup.tcl
index 1d30b1d..cf3eca3 100644
--- a/src/server/startup.tcl
+++ b/src/server/startup.tcl
@@ -41,3 +41,81 @@ proc _telnet_autocomplete_helper pattern {
return [lsort $cmds]
}
+
+lappend _telnet_autocomplete_skip "gdb_sync"
+proc "gdb_sync" {} {
+ echo "DEPRECATED! use 'gdb sync', not 'gdb_sync'"
+ eval gdb sync
+}
+
+lappend _telnet_autocomplete_skip "gdb_port"
+proc "gdb_port" {args} {
+ echo "DEPRECATED! use 'gdb port', not 'gdb_port'"
+ eval gdb port $args
+}
+
+lappend _telnet_autocomplete_skip "gdb_memory_map"
+proc "gdb_memory_map" {state} {
+ echo "DEPRECATED! use 'gdb memory_map', not 'gdb_memory_map'"
+ eval gdb memory_map $state
+}
+
+lappend _telnet_autocomplete_skip "gdb_flash_program"
+proc "gdb_flash_program" {state} {
+ echo "DEPRECATED! use 'gdb flash_program', not 'gdb_flash_program'"
+ eval gdb flash_program $state
+}
+
+lappend _telnet_autocomplete_skip "gdb_report_data_abort"
+proc "gdb_report_data_abort" {state} {
+ echo "DEPRECATED! use 'gdb report_data_abort', not 'gdb_report_data_abort'"
+ eval gdb report_data_abort $state
+}
+
+lappend _telnet_autocomplete_skip "gdb_report_register_access_error"
+proc "gdb_report_register_access_error" {state} {
+ echo "DEPRECATED! use 'gdb report_register_access_error', not 'gdb_report_register_access_error'"
+ eval gdb report_register_access_error $state
+}
+
+lappend _telnet_autocomplete_skip "gdb_breakpoint_override"
+proc "gdb_breakpoint_override" {override} {
+ echo "DEPRECATED! use 'gdb breakpoint_override', not 'gdb_breakpoint_override'"
+ eval gdb breakpoint_override $override
+}
+
+lappend _telnet_autocomplete_skip "gdb_target_description"
+proc "gdb_target_description" {state} {
+ echo "DEPRECATED! use 'gdb target_description', not 'gdb_target_description'"
+ eval gdb target_description $state
+}
+
+lappend _telnet_autocomplete_skip "gdb_save_tdesc"
+proc "gdb_save_tdesc" {} {
+ echo "DEPRECATED! use 'gdb save_tdesc', not 'gdb_save_tdesc'"
+ eval gdb save_tdesc
+}
+
+lappend _telnet_autocomplete_skip "tcl_port"
+proc "tcl_port" {args} {
+ echo "DEPRECATED! use 'tcl port' not 'tcl_port'"
+ eval tcl port $args
+}
+
+lappend _telnet_autocomplete_skip "tcl_notifications"
+proc "tcl_notifications" {state} {
+ echo "DEPRECATED! use 'tcl notifications' not 'tcl_notifications'"
+ eval tcl notifications $state
+}
+
+lappend _telnet_autocomplete_skip "tcl_trace"
+proc "tcl_trace" {state} {
+ echo "DEPRECATED! use 'tcl trace' not 'tcl_trace'"
+ eval tcl trace $state
+}
+
+lappend _telnet_autocomplete_skip "telnet_port"
+proc "telnet_port" {args} {
+ echo "DEPRECATED! use 'telnet port', not 'telnet_port'"
+ eval telnet port $args
+}
diff --git a/src/server/tcl_server.c b/src/server/tcl_server.c
index 16cbedc..16cc55e 100644
--- a/src/server/tcl_server.c
+++ b/src/server/tcl_server.c
@@ -323,25 +323,25 @@ COMMAND_HANDLER(handle_tcl_trace_command)
}
}
-static const struct command_registration tcl_command_handlers[] = {
+static const struct command_registration tcl_subcommand_handlers[] = {
{
- .name = "tcl_port",
+ .name = "port",
.handler = handle_tcl_port_command,
.mode = COMMAND_CONFIG,
.help = "Specify port on which to listen "
"for incoming Tcl syntax. "
- "Read help on 'gdb_port'.",
+ "Read help on 'gdb port'.",
.usage = "[port_num]",
},
{
- .name = "tcl_notifications",
+ .name = "notifications",
.handler = handle_tcl_notifications_command,
.mode = COMMAND_EXEC,
.help = "Target Notification output",
.usage = "[on|off]",
},
{
- .name = "tcl_trace",
+ .name = "trace",
.handler = handle_tcl_trace_command,
.mode = COMMAND_EXEC,
.help = "Target trace output",
@@ -350,6 +350,17 @@ static const struct command_registration tcl_command_handlers[] = {
COMMAND_REGISTRATION_DONE
};
+static const struct command_registration tcl_command_handlers[] = {
+ {
+ .name = "tcl",
+ .mode = COMMAND_ANY,
+ .help = "tcl command group",
+ .usage = "",
+ .chain = tcl_subcommand_handlers,
+ },
+ COMMAND_REGISTRATION_DONE
+};
+
int tcl_register_commands(struct command_context *cmd_ctx)
{
tcl_port = strdup("6666");
diff --git a/src/server/telnet_server.c b/src/server/telnet_server.c
index 938bc5b..a596afe 100644
--- a/src/server/telnet_server.c
+++ b/src/server/telnet_server.c
@@ -967,7 +967,6 @@ int telnet_init(char *banner)
return ERROR_OK;
}
-/* daemon configuration command telnet_port */
COMMAND_HANDLER(handle_telnet_port_command)
{
return CALL_COMMAND_HANDLER(server_pipe_command, &telnet_port);
@@ -978,22 +977,33 @@ COMMAND_HANDLER(handle_exit_command)
return ERROR_COMMAND_CLOSE_CONNECTION;
}
+static const struct command_registration telnet_subcommand_handlers[] = {
+ {
+ .name = "port",
+ .handler = handle_telnet_port_command,
+ .mode = COMMAND_CONFIG,
+ .help = "Specify port on which to listen "
+ "for incoming telnet connections. "
+ "Read help on 'gdb port'.",
+ .usage = "[port_num]",
+ },
+ COMMAND_REGISTRATION_DONE
+};
+
static const struct command_registration telnet_command_handlers[] = {
{
.name = "exit",
.handler = handle_exit_command,
- .mode = COMMAND_EXEC,
+ .mode = COMMAND_ANY,
.usage = "",
.help = "exit telnet session",
},
{
- .name = "telnet_port",
- .handler = handle_telnet_port_command,
+ .name = "telnet",
+ .chain = telnet_subcommand_handlers,
.mode = COMMAND_CONFIG,
- .help = "Specify port on which to listen "
- "for incoming telnet connections. "
- "Read help on 'gdb_port'.",
- .usage = "[port_num]",
+ .help = "telnet commands",
+ .usage = "",
},
COMMAND_REGISTRATION_DONE
};
diff --git a/src/svf/svf.c b/src/svf/svf.c
index dd3d517..4708899 100644
--- a/src/svf/svf.c
+++ b/src/svf/svf.c
@@ -932,7 +932,7 @@ static int svf_check_tdo(void)
index_var = svf_check_tdo_para[i].buffer_offset;
len = svf_check_tdo_para[i].bit_len;
if ((svf_check_tdo_para[i].enabled)
- && buf_cmp_mask(&svf_tdi_buffer[index_var], &svf_tdo_buffer[index_var],
+ && !buf_eq_mask(&svf_tdi_buffer[index_var], &svf_tdo_buffer[index_var],
&svf_mask_buffer[index_var], len)) {
LOG_ERROR("tdo check error at line %d",
svf_check_tdo_para[i].line_num);
diff --git a/src/target/aarch64.c b/src/target/aarch64.c
index 6a70b2d..f0d486f 100644
--- a/src/target/aarch64.c
+++ b/src/target/aarch64.c
@@ -193,6 +193,20 @@ static int aarch64_mmu_modify(struct target *target, int enable)
return retval;
}
+static int aarch64_read_prsr(struct target *target, uint32_t *prsr)
+{
+ struct armv8_common *armv8 = target_to_armv8(target);
+ int retval;
+
+ retval = mem_ap_read_atomic_u32(armv8->debug_ap,
+ armv8->debug_base + CPUV8_DBG_PRSR, prsr);
+ if (retval != ERROR_OK)
+ return retval;
+
+ armv8->sticky_reset |= *prsr & PRSR_SR;
+ return ERROR_OK;
+}
+
/*
* Basic debug access, very low level assumes state is saved
*/
@@ -213,8 +227,7 @@ static int aarch64_init_debug_access(struct target *target)
/* Clear Sticky Power Down status Bit in PRSR to enable access to
the registers in the Core Power Domain */
- retval = mem_ap_read_atomic_u32(armv8->debug_ap,
- armv8->debug_base + CPUV8_DBG_PRSR, &dummy);
+ retval = aarch64_read_prsr(target, &dummy);
if (retval != ERROR_OK)
return retval;
@@ -281,12 +294,10 @@ static int aarch64_set_dscr_bits(struct target *target, unsigned long bit_mask,
static int aarch64_check_state_one(struct target *target,
uint32_t mask, uint32_t val, int *p_result, uint32_t *p_prsr)
{
- struct armv8_common *armv8 = target_to_armv8(target);
uint32_t prsr;
int retval;
- retval = mem_ap_read_atomic_u32(armv8->debug_ap,
- armv8->debug_base + CPUV8_DBG_PRSR, &prsr);
+ retval = aarch64_read_prsr(target, &prsr);
if (retval != ERROR_OK)
return retval;
@@ -506,16 +517,28 @@ static int update_halt_gdb(struct target *target, enum target_debug_reason debug
static int aarch64_poll(struct target *target)
{
+ struct armv8_common *armv8 = target_to_armv8(target);
enum target_state prev_target_state;
int retval = ERROR_OK;
- int halted;
+ uint32_t prsr;
- retval = aarch64_check_state_one(target,
- PRSR_HALT, PRSR_HALT, &halted, NULL);
+ retval = aarch64_read_prsr(target, &prsr);
if (retval != ERROR_OK)
return retval;
- if (halted) {
+ if (armv8->sticky_reset) {
+ armv8->sticky_reset = false;
+ if (target->state != TARGET_RESET) {
+ target->state = TARGET_RESET;
+ LOG_TARGET_INFO(target, "external reset detected");
+ if (armv8->arm.core_cache) {
+ register_cache_invalidate(armv8->arm.core_cache);
+ register_cache_invalidate(armv8->arm.core_cache->next);
+ }
+ }
+ }
+
+ if (prsr & PRSR_HALT) {
prev_target_state = target->state;
if (prev_target_state != TARGET_HALTED) {
enum target_debug_reason debug_reason = target->debug_reason;
@@ -546,8 +569,11 @@ static int aarch64_poll(struct target *target)
break;
}
}
- } else
+ } else if (prsr & PRSR_RESET) {
+ target->state = TARGET_RESET;
+ } else {
target->state = TARGET_RUNNING;
+ }
return retval;
}
@@ -663,8 +689,7 @@ static int aarch64_prepare_restart_one(struct target *target)
if (retval == ERROR_OK) {
/* clear sticky bits in PRSR, SDR is now 0 */
- retval = mem_ap_read_atomic_u32(armv8->debug_ap,
- armv8->debug_base + CPUV8_DBG_PRSR, &tmp);
+ retval = aarch64_read_prsr(target, &tmp);
}
return retval;
diff --git a/src/target/arm.h b/src/target/arm.h
index 486666b..0de322a 100644
--- a/src/target/arm.h
+++ b/src/target/arm.h
@@ -58,11 +58,12 @@ enum arm_arch {
ARM_ARCH_V8M,
};
-/** Known ARM implementor IDs */
-enum arm_implementor {
- ARM_IMPLEMENTOR_ARM = 0x41,
- ARM_IMPLEMENTOR_INFINEON = 0x49,
- ARM_IMPLEMENTOR_REALTEK = 0x72,
+/** Known ARM implementer IDs */
+enum arm_implementer {
+ ARM_IMPLEMENTER_ARM = 0x41,
+ ARM_IMPLEMENTER_INFINEON = 0x49,
+ ARM_IMPLEMENTER_ARM_CHINA = 0x63,
+ ARM_IMPLEMENTER_REALTEK = 0x72,
};
/**
diff --git a/src/target/arm_adi_v5.c b/src/target/arm_adi_v5.c
index 9129ace..3a5afc6 100644
--- a/src/target/arm_adi_v5.c
+++ b/src/target/arm_adi_v5.c
@@ -795,11 +795,12 @@ int dap_dp_init(struct adiv5_dap *dap)
dap->dp_ctrl_stat = CDBGPWRUPREQ | CSYSPWRUPREQ;
/*
- * This write operation clears the sticky error bit in jtag mode only and
- * is ignored in swd mode. It also powers-up system and debug domains in
- * both jtag and swd modes, if not done before.
+ * This write operation clears the sticky error and overrun bits in jtag
+ * mode only and is ignored in swd mode. It also powers-up system and
+ * debug domains in both jtag and swd modes, if not done before.
*/
- retval = dap_queue_dp_write(dap, DP_CTRL_STAT, dap->dp_ctrl_stat | SSTICKYERR);
+ retval = dap_queue_dp_write(dap, DP_CTRL_STAT,
+ dap->dp_ctrl_stat | SSTICKYERR | SSTICKYORUN);
if (retval != ERROR_OK)
return retval;
@@ -1453,11 +1454,13 @@ static const struct dap_part_nums {
{ ARM_ID, 0x4af, "Cortex-A15 ROM", "(ROM Table)", },
{ ARM_ID, 0x4b5, "Cortex-R5 ROM", "(ROM Table)", },
{ ARM_ID, 0x4b8, "Cortex-R52 ROM", "(ROM Table)", },
+ { ARM_ID, 0x4bd, "Cortex-R52+ ROM", "(ROM Table)", },
{ ARM_ID, 0x4c0, "Cortex-M0+ ROM", "(ROM Table)", },
{ ARM_ID, 0x4c3, "Cortex-M3 ROM", "(ROM Table)", },
{ ARM_ID, 0x4c4, "Cortex-M4 ROM", "(ROM Table)", },
{ ARM_ID, 0x4c7, "Cortex-M7 PPB ROM", "(Private Peripheral Bus ROM Table)", },
{ ARM_ID, 0x4c8, "Cortex-M7 ROM", "(ROM Table)", },
+ { ARM_ID, 0x4c9, "STAR ROM", "(ROM Table)", },
{ ARM_ID, 0x4e0, "Cortex-A35 ROM", "(v7 Memory Map ROM Table)", },
{ ARM_ID, 0x4e4, "Cortex-A76 ROM", "(ROM Table)", },
{ ARM_ID, 0x906, "CoreSight CTI", "(Cross Trigger)", },
@@ -1499,6 +1502,7 @@ static const struct dap_part_nums {
{ ARM_ID, 0x9ae, "Cortex-A17 PMU", "(Performance Monitor Unit)", },
{ ARM_ID, 0x9af, "Cortex-A15 PMU", "(Performance Monitor Unit)", },
{ ARM_ID, 0x9b6, "Cortex-R52 PMU/CTI/ETM", "(Performance Monitor Unit/Cross Trigger/ETM)", },
+ { ARM_ID, 0x9bb, "Cortex-R52+ PMU/CTI/ETM", "(Performance Monitor Unit/Cross Trigger/ETM)", },
{ ARM_ID, 0x9b7, "Cortex-R7 PMU", "(Performance Monitor Unit)", },
{ ARM_ID, 0x9d3, "Cortex-A53 PMU", "(Performance Monitor Unit)", },
{ ARM_ID, 0x9d7, "Cortex-A57 PMU", "(Performance Monitor Unit)", },
@@ -1533,6 +1537,10 @@ static const struct dap_part_nums {
{ ARM_ID, 0xd0b, "Cortex-A76 Debug", "(Debug Unit)", },
{ ARM_ID, 0xd0c, "Neoverse N1", "(Debug Unit)", },
{ ARM_ID, 0xd13, "Cortex-R52 Debug", "(Debug Unit)", },
+ { ARM_ID, 0xd16, "Cortex-R52+ Debug", "(Debug Unit)", },
+ { ARM_ID, 0xd21, "STAR Debug", "(Debug Unit)", },
+ { ARM_ID, 0xd22, "Cortex-M55 Debug", "(Debug Unit)", },
+ { ARM_ID, 0xd43, "Cortex-A65AE Debug", "(Debug Unit)", },
{ ARM_ID, 0xd49, "Neoverse N2", "(Debug Unit)", },
{ 0x017, 0x120, "TI SDTI", "(System Debug Trace Interface)", }, /* from OMAP3 memmap */
{ 0x017, 0x343, "TI DAPCTL", "", }, /* from OMAP3 memmap */
@@ -1552,6 +1560,9 @@ static const struct dap_part_nums {
{ 0x1eb, 0x211, "Tegra 210 ROM", "(ROM Table)", },
{ 0x1eb, 0x302, "Denver Debug", "(Debug Unit)", },
{ 0x1eb, 0x402, "Denver PMU", "(Performance Monitor Unit)", },
+ { 0x575, 0x132, "STAR SCS", "(System Control Space)", },
+ { 0x575, 0x4d2, "Cortex-M52 ROM", "(ROM Table)", },
+ { 0x575, 0xd24, "Cortex-M52 Debug", "(Debug Unit)", },
};
static const struct dap_part_nums *pidr_to_part_num(unsigned int designer_id, unsigned int part_num)
diff --git a/src/target/arm_cti.c b/src/target/arm_cti.c
index 7637ad0..97d1fb3 100644
--- a/src/target/arm_cti.c
+++ b/src/target/arm_cti.c
@@ -157,48 +157,44 @@ int arm_cti_clear_channel(struct arm_cti *self, uint32_t channel)
return arm_cti_write_reg(self, CTI_APPCLEAR, CTI_CHNL(channel));
}
-static uint32_t cti_regs[28];
-
static const struct {
uint32_t offset;
const char *label;
- uint32_t *p_val;
} cti_names[] = {
- { CTI_CTR, "CTR", &cti_regs[0] },
- { CTI_GATE, "GATE", &cti_regs[1] },
- { CTI_INEN0, "INEN0", &cti_regs[2] },
- { CTI_INEN1, "INEN1", &cti_regs[3] },
- { CTI_INEN2, "INEN2", &cti_regs[4] },
- { CTI_INEN3, "INEN3", &cti_regs[5] },
- { CTI_INEN4, "INEN4", &cti_regs[6] },
- { CTI_INEN5, "INEN5", &cti_regs[7] },
- { CTI_INEN6, "INEN6", &cti_regs[8] },
- { CTI_INEN7, "INEN7", &cti_regs[9] },
- { CTI_INEN8, "INEN8", &cti_regs[10] },
- { CTI_OUTEN0, "OUTEN0", &cti_regs[11] },
- { CTI_OUTEN1, "OUTEN1", &cti_regs[12] },
- { CTI_OUTEN2, "OUTEN2", &cti_regs[13] },
- { CTI_OUTEN3, "OUTEN3", &cti_regs[14] },
- { CTI_OUTEN4, "OUTEN4", &cti_regs[15] },
- { CTI_OUTEN5, "OUTEN5", &cti_regs[16] },
- { CTI_OUTEN6, "OUTEN6", &cti_regs[17] },
- { CTI_OUTEN7, "OUTEN7", &cti_regs[18] },
- { CTI_OUTEN8, "OUTEN8", &cti_regs[19] },
- { CTI_TRIN_STATUS, "TRIN", &cti_regs[20] },
- { CTI_TROUT_STATUS, "TROUT", &cti_regs[21] },
- { CTI_CHIN_STATUS, "CHIN", &cti_regs[22] },
- { CTI_CHOU_STATUS, "CHOUT", &cti_regs[23] },
- { CTI_APPSET, "APPSET", &cti_regs[24] },
- { CTI_APPCLEAR, "APPCLR", &cti_regs[25] },
- { CTI_APPPULSE, "APPPULSE", &cti_regs[26] },
- { CTI_INACK, "INACK", &cti_regs[27] },
+ { CTI_CTR, "CTR" },
+ { CTI_GATE, "GATE" },
+ { CTI_INEN0, "INEN0" },
+ { CTI_INEN1, "INEN1" },
+ { CTI_INEN2, "INEN2" },
+ { CTI_INEN3, "INEN3" },
+ { CTI_INEN4, "INEN4" },
+ { CTI_INEN5, "INEN5" },
+ { CTI_INEN6, "INEN6" },
+ { CTI_INEN7, "INEN7" },
+ { CTI_INEN8, "INEN8" },
+ { CTI_OUTEN0, "OUTEN0" },
+ { CTI_OUTEN1, "OUTEN1" },
+ { CTI_OUTEN2, "OUTEN2" },
+ { CTI_OUTEN3, "OUTEN3" },
+ { CTI_OUTEN4, "OUTEN4" },
+ { CTI_OUTEN5, "OUTEN5" },
+ { CTI_OUTEN6, "OUTEN6" },
+ { CTI_OUTEN7, "OUTEN7" },
+ { CTI_OUTEN8, "OUTEN8" },
+ { CTI_TRIN_STATUS, "TRIN" },
+ { CTI_TROUT_STATUS, "TROUT" },
+ { CTI_CHIN_STATUS, "CHIN" },
+ { CTI_CHOU_STATUS, "CHOUT" },
+ { CTI_APPSET, "APPSET" },
+ { CTI_APPCLEAR, "APPCLR" },
+ { CTI_APPPULSE, "APPPULSE" },
+ { CTI_INACK, "INACK" },
+ { CTI_DEVCTL, "DEVCTL" },
};
static int cti_find_reg_offset(const char *name)
{
- unsigned int i;
-
- for (i = 0; i < ARRAY_SIZE(cti_names); i++) {
+ for (size_t i = 0; i < ARRAY_SIZE(cti_names); i++) {
if (!strcmp(name, cti_names[i].label))
return cti_names[i].offset;
}
@@ -226,10 +222,11 @@ COMMAND_HANDLER(handle_cti_dump)
struct arm_cti *cti = CMD_DATA;
struct adiv5_ap *ap = cti->ap;
int retval = ERROR_OK;
+ uint32_t values[ARRAY_SIZE(cti_names)];
- for (int i = 0; (retval == ERROR_OK) && (i < (int)ARRAY_SIZE(cti_names)); i++)
+ for (size_t i = 0; (retval == ERROR_OK) && (i < ARRAY_SIZE(cti_names)); i++)
retval = mem_ap_read_u32(ap,
- cti->spot.base + cti_names[i].offset, cti_names[i].p_val);
+ cti->spot.base + cti_names[i].offset, &values[i]);
if (retval == ERROR_OK)
retval = dap_run(ap->dap);
@@ -237,9 +234,9 @@ COMMAND_HANDLER(handle_cti_dump)
if (retval != ERROR_OK)
return JIM_ERR;
- for (int i = 0; i < (int)ARRAY_SIZE(cti_names); i++)
+ for (size_t i = 0; i < ARRAY_SIZE(cti_names); i++)
command_print(CMD, "%8.8s (0x%04"PRIx32") 0x%08"PRIx32,
- cti_names[i].label, cti_names[i].offset, *cti_names[i].p_val);
+ cti_names[i].label, cti_names[i].offset, values[i]);
return JIM_OK;
}
@@ -323,7 +320,6 @@ COMMAND_HANDLER(handle_cti_ack)
int retval = arm_cti_ack_events(cti, 1 << event);
-
if (retval != ERROR_OK)
return retval;
@@ -437,6 +433,7 @@ static int cti_configure(struct jim_getopt_info *goi, struct arm_cti *cti)
return JIM_OK;
}
+
static int cti_create(struct jim_getopt_info *goi)
{
struct command_context *cmd_ctx;
@@ -538,7 +535,6 @@ COMMAND_HANDLER(cti_handle_names)
return ERROR_OK;
}
-
static const struct command_registration cti_subcommand_handlers[] = {
{
.name = "create",
diff --git a/src/target/arm_cti.h b/src/target/arm_cti.h
index cfcde65..1513f02 100644
--- a/src/target/arm_cti.h
+++ b/src/target/arm_cti.h
@@ -39,6 +39,7 @@
#define CTI_CHIN_STATUS 0x138
#define CTI_CHOU_STATUS 0x13C
#define CTI_GATE 0x140
+#define CTI_DEVCTL 0x150
#define CTI_UNLOCK 0xFB0
#define CTI_CHNL(x) (1 << x)
diff --git a/src/target/armv8.h b/src/target/armv8.h
index f5aa211..156b5f8 100644
--- a/src/target/armv8.h
+++ b/src/target/armv8.h
@@ -213,6 +213,8 @@ struct armv8_common {
/* True if OpenOCD provides pointer auth related info to GDB */
bool enable_pauth;
+ bool sticky_reset;
+
/* last run-control command issued to this target (resume, halt, step) */
enum run_control_op last_run_control_op;
diff --git a/src/target/avrt.c b/src/target/avrt.c
index 61bef32..8886a46 100644
--- a/src/target/avrt.c
+++ b/src/target/avrt.c
@@ -31,10 +31,10 @@ static int avr_assert_reset(struct target *target);
static int avr_deassert_reset(struct target *target);
/* IR and DR functions */
-static int mcu_write_ir(struct jtag_tap *tap, uint8_t *ir_in, uint8_t *ir_out, int ir_len, int rti);
-static int mcu_write_dr(struct jtag_tap *tap, uint8_t *dr_in, uint8_t *dr_out, int dr_len, int rti);
-static int mcu_write_ir_u8(struct jtag_tap *tap, uint8_t *ir_in, uint8_t ir_out, int ir_len, int rti);
-static int mcu_write_dr_u32(struct jtag_tap *tap, uint32_t *ir_in, uint32_t ir_out, int dr_len, int rti);
+static int mcu_write_ir(struct jtag_tap *tap, uint8_t *ir_in, uint8_t *ir_out, int ir_len);
+static int mcu_write_dr(struct jtag_tap *tap, uint8_t *dr_in, uint8_t *dr_out, int dr_len);
+static int mcu_write_ir_u8(struct jtag_tap *tap, uint8_t *ir_in, uint8_t ir_out, int ir_len);
+static int mcu_write_dr_u32(struct jtag_tap *tap, uint32_t *ir_in, uint32_t ir_out, int dr_len);
struct target_type avr_target = {
.name = "avr",
@@ -137,23 +137,23 @@ static int avr_deassert_reset(struct target *target)
int avr_jtag_senddat(struct jtag_tap *tap, uint32_t *dr_in, uint32_t dr_out,
int len)
{
- return mcu_write_dr_u32(tap, dr_in, dr_out, len, 1);
+ return mcu_write_dr_u32(tap, dr_in, dr_out, len);
}
int avr_jtag_sendinstr(struct jtag_tap *tap, uint8_t *ir_in, uint8_t ir_out)
{
- return mcu_write_ir_u8(tap, ir_in, ir_out, AVR_JTAG_INS_LEN, 1);
+ return mcu_write_ir_u8(tap, ir_in, ir_out, AVR_JTAG_INS_LEN);
}
/* IR and DR functions */
static int mcu_write_ir(struct jtag_tap *tap, uint8_t *ir_in, uint8_t *ir_out,
- int ir_len, int rti)
+ int ir_len)
{
if (!tap) {
LOG_ERROR("invalid tap");
return ERROR_FAIL;
}
- if (ir_len != tap->ir_length) {
+ if ((unsigned int)ir_len != tap->ir_length) {
LOG_ERROR("invalid ir_len");
return ERROR_FAIL;
}
@@ -166,7 +166,7 @@ static int mcu_write_ir(struct jtag_tap *tap, uint8_t *ir_in, uint8_t *ir_out,
}
static int mcu_write_dr(struct jtag_tap *tap, uint8_t *dr_in, uint8_t *dr_out,
- int dr_len, int rti)
+ int dr_len)
{
if (!tap) {
LOG_ERROR("invalid tap");
@@ -181,27 +181,27 @@ static int mcu_write_dr(struct jtag_tap *tap, uint8_t *dr_in, uint8_t *dr_out,
}
static int mcu_write_ir_u8(struct jtag_tap *tap, uint8_t *ir_in,
- uint8_t ir_out, int ir_len, int rti)
+ uint8_t ir_out, int ir_len)
{
if (ir_len > 8) {
LOG_ERROR("ir_len overflow, maximum is 8");
return ERROR_FAIL;
}
- mcu_write_ir(tap, ir_in, &ir_out, ir_len, rti);
+ mcu_write_ir(tap, ir_in, &ir_out, ir_len);
return ERROR_OK;
}
static int mcu_write_dr_u32(struct jtag_tap *tap, uint32_t *dr_in,
- uint32_t dr_out, int dr_len, int rti)
+ uint32_t dr_out, int dr_len)
{
if (dr_len > 32) {
LOG_ERROR("dr_len overflow, maximum is 32");
return ERROR_FAIL;
}
- mcu_write_dr(tap, (uint8_t *)dr_in, (uint8_t *)&dr_out, dr_len, rti);
+ mcu_write_dr(tap, (uint8_t *)dr_in, (uint8_t *)&dr_out, dr_len);
return ERROR_OK;
}
diff --git a/src/target/breakpoints.c b/src/target/breakpoints.c
index 77f7673..0427ba3 100644
--- a/src/target/breakpoints.c
+++ b/src/target/breakpoints.c
@@ -39,7 +39,7 @@ static int bpwp_unique_id;
static int breakpoint_add_internal(struct target *target,
target_addr_t address,
- uint32_t length,
+ unsigned int length,
enum breakpoint_type type)
{
struct breakpoint *breakpoint = target->breakpoints;
@@ -102,7 +102,7 @@ fail:
static int context_breakpoint_add_internal(struct target *target,
uint32_t asid,
- uint32_t length,
+ unsigned int length,
enum breakpoint_type type)
{
struct breakpoint *breakpoint = target->breakpoints;
@@ -152,7 +152,7 @@ static int context_breakpoint_add_internal(struct target *target,
static int hybrid_breakpoint_add_internal(struct target *target,
target_addr_t address,
uint32_t asid,
- uint32_t length,
+ unsigned int length,
enum breakpoint_type type)
{
struct breakpoint *breakpoint = target->breakpoints;
@@ -208,7 +208,7 @@ static int hybrid_breakpoint_add_internal(struct target *target,
int breakpoint_add(struct target *target,
target_addr_t address,
- uint32_t length,
+ unsigned int length,
enum breakpoint_type type)
{
if (target->smp && type == BKPT_HARD) {
@@ -232,7 +232,7 @@ int breakpoint_add(struct target *target,
int context_breakpoint_add(struct target *target,
uint32_t asid,
- uint32_t length,
+ unsigned int length,
enum breakpoint_type type)
{
if (target->smp) {
@@ -256,7 +256,7 @@ int context_breakpoint_add(struct target *target,
int hybrid_breakpoint_add(struct target *target,
target_addr_t address,
uint32_t asid,
- uint32_t length,
+ unsigned int length,
enum breakpoint_type type)
{
if (target->smp) {
@@ -542,7 +542,7 @@ struct breakpoint *breakpoint_find(struct target *target, target_addr_t address)
}
static int watchpoint_add_internal(struct target *target, target_addr_t address,
- uint32_t length, enum watchpoint_rw rw, uint64_t value, uint64_t mask)
+ unsigned int length, enum watchpoint_rw rw, uint64_t value, uint64_t mask)
{
struct watchpoint *watchpoint = target->watchpoints;
struct watchpoint **watchpoint_p = &target->watchpoints;
@@ -598,7 +598,7 @@ bye:
}
LOG_TARGET_DEBUG(target, "added %s watchpoint at " TARGET_ADDR_FMT
- " of length 0x%8.8" PRIx32 " (WPID: %d)",
+ " of length 0x%8.8x (WPID: %d)",
watchpoint_rw_strings[(*watchpoint_p)->rw],
(*watchpoint_p)->address,
(*watchpoint_p)->length,
@@ -608,7 +608,7 @@ bye:
}
int watchpoint_add(struct target *target, target_addr_t address,
- uint32_t length, enum watchpoint_rw rw, uint64_t value, uint64_t mask)
+ unsigned int length, enum watchpoint_rw rw, uint64_t value, uint64_t mask)
{
if (target->smp) {
struct target_list *head;
diff --git a/src/target/breakpoints.h b/src/target/breakpoints.h
index 0ec65de..ac5d701 100644
--- a/src/target/breakpoints.h
+++ b/src/target/breakpoints.h
@@ -26,7 +26,7 @@ enum watchpoint_rw {
struct breakpoint {
target_addr_t address;
uint32_t asid;
- int length;
+ unsigned int length;
enum breakpoint_type type;
bool is_set;
unsigned int number;
@@ -40,7 +40,7 @@ struct breakpoint {
struct watchpoint {
target_addr_t address;
- uint32_t length;
+ unsigned int length;
uint64_t mask;
uint64_t value;
enum watchpoint_rw rw;
@@ -52,11 +52,12 @@ struct watchpoint {
int breakpoint_clear_target(struct target *target);
int breakpoint_add(struct target *target,
- target_addr_t address, uint32_t length, enum breakpoint_type type);
+ target_addr_t address, unsigned int length, enum breakpoint_type type);
int context_breakpoint_add(struct target *target,
- uint32_t asid, uint32_t length, enum breakpoint_type type);
+ uint32_t asid, unsigned int length, enum breakpoint_type type);
int hybrid_breakpoint_add(struct target *target,
- target_addr_t address, uint32_t asid, uint32_t length, enum breakpoint_type type);
+ target_addr_t address, uint32_t asid, unsigned int length,
+ enum breakpoint_type type);
int breakpoint_remove(struct target *target, target_addr_t address);
int breakpoint_remove_all(struct target *target);
@@ -70,7 +71,7 @@ static inline void breakpoint_hw_set(struct breakpoint *breakpoint, unsigned int
int watchpoint_clear_target(struct target *target);
int watchpoint_add(struct target *target,
- target_addr_t address, uint32_t length,
+ target_addr_t address, unsigned int length,
enum watchpoint_rw rw, uint64_t value, uint64_t mask);
int watchpoint_remove(struct target *target, target_addr_t address);
int watchpoint_remove_all(struct target *target);
diff --git a/src/target/cortex_m.c b/src/target/cortex_m.c
index 34c7cd4..3b95b64 100644
--- a/src/target/cortex_m.c
+++ b/src/target/cortex_m.c
@@ -100,6 +100,12 @@ static const struct cortex_m_part_info cortex_m_parts[] = {
.flags = CORTEX_M_F_HAS_FPV5,
},
{
+ .impl_part = CORTEX_M52_PARTNO,
+ .name = "Cortex-M52",
+ .arch = ARM_ARCH_V8M,
+ .flags = CORTEX_M_F_HAS_FPV5,
+ },
+ {
.impl_part = CORTEX_M55_PARTNO,
.name = "Cortex-M55",
.arch = ARM_ARCH_V8M,
@@ -273,7 +279,8 @@ static int cortex_m_fast_read_all_regs(struct target *target)
/* because the DCB_DCRDR is used for the emulated dcc channel
* we have to save/restore the DCB_DCRDR when used */
- if (target->dbg_msg_enabled) {
+ bool dbg_msg_enabled = target->dbg_msg_enabled;
+ if (dbg_msg_enabled) {
retval = mem_ap_read_u32(armv7m->debug_ap, DCB_DCRDR, &dcrdr);
if (retval != ERROR_OK)
return retval;
@@ -326,7 +333,7 @@ static int cortex_m_fast_read_all_regs(struct target *target)
if (retval != ERROR_OK)
return retval;
- if (target->dbg_msg_enabled) {
+ if (dbg_msg_enabled) {
/* restore DCB_DCRDR - this needs to be in a separate
* transaction otherwise the emulated DCC channel breaks */
retval = mem_ap_write_atomic_u32(armv7m->debug_ap, DCB_DCRDR, dcrdr);
@@ -797,6 +804,42 @@ static int cortex_m_examine_exception_reason(struct target *target)
return retval;
}
+/* Errata 3092511 workaround
+ * Cortex-M7 can halt in an incorrect address when breakpoint
+ * and exception occurs simultaneously */
+static int cortex_m_erratum_check_breakpoint(struct target *target)
+{
+ struct cortex_m_common *cortex_m = target_to_cm(target);
+ struct armv7m_common *armv7m = &cortex_m->armv7m;
+ struct arm *arm = &armv7m->arm;
+
+ uint32_t pc = buf_get_u32(arm->pc->value, 0, 32);
+
+ /* To reduce the workaround processing cost we assume FPB is in sync
+ * with OpenOCD breakpoints. If the target app writes to FPB
+ * OpenOCD will resume after the break set by app */
+ struct breakpoint *bkpt = breakpoint_find(target, pc);
+ if (bkpt) {
+ LOG_TARGET_DEBUG(target, "Erratum 3092511: breakpoint confirmed");
+ return ERROR_OK;
+ }
+ if (pc >= 0xe0000000u)
+ /* not executable area, do not read instruction @ pc */
+ return ERROR_OK;
+
+ uint16_t insn;
+ int retval = target_read_u16(target, pc, &insn);
+ if (retval != ERROR_OK)
+ return ERROR_OK; /* do not propagate the error, just avoid workaround */
+
+ if ((insn & 0xff00) == (ARMV5_T_BKPT(0) & 0xff00)) {
+ LOG_TARGET_DEBUG(target, "Erratum 3092511: breakpoint embedded in code confirmed");
+ return ERROR_OK;
+ }
+ LOG_TARGET_DEBUG(target, "Erratum 3092511: breakpoint not found, proceed with resume");
+ return ERROR_TARGET_HALTED_DO_RESUME;
+}
+
static int cortex_m_debug_entry(struct target *target)
{
uint32_t xpsr;
@@ -883,6 +926,17 @@ static int cortex_m_debug_entry(struct target *target)
secure_state ? "Secure" : "Non-Secure",
target_state_name(target));
+ /* Errata 3092511 workaround
+ * Cortex-M7 can halt in an incorrect address when breakpoint
+ * and exception occurs simultaneously */
+ if (cortex_m->incorrect_halt_erratum
+ && armv7m->exception_number
+ && cortex_m->nvic_dfsr == (DFSR_BKPT | DFSR_HALTED)) {
+ retval = cortex_m_erratum_check_breakpoint(target);
+ if (retval != ERROR_OK)
+ return retval;
+ }
+
if (armv7m->post_debug_entry) {
retval = armv7m->post_debug_entry(target);
if (retval != ERROR_OK)
@@ -960,6 +1014,28 @@ static int cortex_m_poll_one(struct target *target)
if ((prev_target_state == TARGET_RUNNING) || (prev_target_state == TARGET_RESET)) {
retval = cortex_m_debug_entry(target);
+ /* Errata 3092511 workaround
+ * Cortex-M7 can halt in an incorrect address when breakpoint
+ * and exception occurs simultaneously */
+ if (retval == ERROR_TARGET_HALTED_DO_RESUME) {
+ struct arm *arm = &armv7m->arm;
+ LOG_TARGET_INFO(target, "Resuming after incorrect halt @ PC 0x%08" PRIx32
+ ", ARM Cortex-M7 erratum 3092511",
+ buf_get_u32(arm->pc->value, 0, 32));
+ /* We don't need to restore registers, just restart the core */
+ cortex_m_set_maskints_for_run(target);
+ retval = cortex_m_write_debug_halt_mask(target, 0, C_HALT);
+ if (retval != ERROR_OK)
+ return retval;
+
+ target->debug_reason = DBG_REASON_NOTHALTED;
+ /* registers are now invalid */
+ register_cache_invalidate(armv7m->arm.core_cache);
+
+ target->state = TARGET_RUNNING;
+ return ERROR_OK;
+ }
+
/* arm_semihosting needs to know registers, don't run if debug entry returned error */
if (retval == ERROR_OK && arm_semihosting(target, &retval) != 0)
return retval;
@@ -1582,7 +1658,7 @@ static int cortex_m_step(struct target *target, int current,
cortex_m->dcb_dhcsr, cortex_m->nvic_icsr);
retval = cortex_m_debug_entry(target);
- if (retval != ERROR_OK)
+ if (retval != ERROR_OK && retval != ERROR_TARGET_HALTED_DO_RESUME)
return retval;
target_call_event_callbacks(target, TARGET_EVENT_HALTED);
@@ -2537,8 +2613,8 @@ int cortex_m_examine(struct target *target)
if (retval != ERROR_OK)
return retval;
- /* Inspect implementor/part to look for recognized cores */
- unsigned int impl_part = cpuid & (ARM_CPUID_IMPLEMENTOR_MASK | ARM_CPUID_PARTNO_MASK);
+ /* Inspect implementer/part to look for recognized cores */
+ unsigned int impl_part = cpuid & (ARM_CPUID_IMPLEMENTER_MASK | ARM_CPUID_PARTNO_MASK);
for (unsigned int n = 0; n < ARRAY_SIZE(cortex_m_parts); n++) {
if (impl_part == cortex_m_parts[n].impl_part) {
@@ -2560,14 +2636,22 @@ int cortex_m_examine(struct target *target)
(uint8_t)((cpuid >> 0) & 0xf));
cortex_m->maskints_erratum = false;
+ cortex_m->incorrect_halt_erratum = false;
if (impl_part == CORTEX_M7_PARTNO) {
uint8_t rev, patch;
rev = (cpuid >> 20) & 0xf;
patch = (cpuid >> 0) & 0xf;
if ((rev == 0) && (patch < 2)) {
- LOG_TARGET_WARNING(target, "Silicon bug: single stepping may enter pending exception handler!");
+ LOG_TARGET_WARNING(target, "Erratum 702596: single stepping may enter pending exception handler!");
cortex_m->maskints_erratum = true;
}
+ /* TODO: add revision check when a Cortex-M7 revision with fixed 3092511 is out */
+ LOG_TARGET_WARNING(target, "Erratum 3092511: Cortex-M7 can halt in an incorrect address when breakpoint and exception occurs simultaneously");
+ cortex_m->incorrect_halt_erratum = true;
+ if (armv7m->is_hla_target)
+ LOG_WARNING("No erratum 3092511 workaround on hla adapter");
+ else
+ LOG_INFO("The erratum 3092511 workaround will resume after an incorrect halt");
}
LOG_TARGET_DEBUG(target, "cpuid: 0x%8.8" PRIx32 "", cpuid);
diff --git a/src/target/cortex_m.h b/src/target/cortex_m.h
index a585b78..144f245 100644
--- a/src/target/cortex_m.h
+++ b/src/target/cortex_m.h
@@ -31,35 +31,36 @@
#define CPUID 0xE000ED00
-#define ARM_CPUID_IMPLEMENTOR_POS 24
-#define ARM_CPUID_IMPLEMENTOR_MASK (0xFF << ARM_CPUID_IMPLEMENTOR_POS)
+#define ARM_CPUID_IMPLEMENTER_POS 24
+#define ARM_CPUID_IMPLEMENTER_MASK (0xFF << ARM_CPUID_IMPLEMENTER_POS)
#define ARM_CPUID_PARTNO_POS 4
#define ARM_CPUID_PARTNO_MASK (0xFFF << ARM_CPUID_PARTNO_POS)
-#define ARM_MAKE_CPUID(impl, partno) ((((impl) << ARM_CPUID_IMPLEMENTOR_POS) & ARM_CPUID_IMPLEMENTOR_MASK) | \
+#define ARM_MAKE_CPUID(impl, partno) ((((impl) << ARM_CPUID_IMPLEMENTER_POS) & ARM_CPUID_IMPLEMENTER_MASK) | \
(((partno) << ARM_CPUID_PARTNO_POS) & ARM_CPUID_PARTNO_MASK))
/** Known Arm Cortex masked CPU Ids
- * This includes the implementor and part number, but _not_ the revision or
+ * This includes the implementer and part number, but _not_ the revision or
* patch fields.
*/
enum cortex_m_impl_part {
CORTEX_M_PARTNO_INVALID,
- STAR_MC1_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTOR_ARM, 0x132), /* FIXME - confirm implementor! */
- CORTEX_M0_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTOR_ARM, 0xC20),
- CORTEX_M1_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTOR_ARM, 0xC21),
- CORTEX_M3_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTOR_ARM, 0xC23),
- CORTEX_M4_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTOR_ARM, 0xC24),
- CORTEX_M7_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTOR_ARM, 0xC27),
- CORTEX_M0P_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTOR_ARM, 0xC60),
- CORTEX_M23_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTOR_ARM, 0xD20),
- CORTEX_M33_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTOR_ARM, 0xD21),
- CORTEX_M35P_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTOR_ARM, 0xD31),
- CORTEX_M55_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTOR_ARM, 0xD22),
- CORTEX_M85_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTOR_ARM, 0xD23),
- INFINEON_SLX2_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTOR_INFINEON, 0xDB0),
- REALTEK_M200_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTOR_REALTEK, 0xd20),
- REALTEK_M300_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTOR_REALTEK, 0xd22),
+ STAR_MC1_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTER_ARM_CHINA, 0x132),
+ CORTEX_M0_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTER_ARM, 0xC20),
+ CORTEX_M1_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTER_ARM, 0xC21),
+ CORTEX_M3_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTER_ARM, 0xC23),
+ CORTEX_M4_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTER_ARM, 0xC24),
+ CORTEX_M7_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTER_ARM, 0xC27),
+ CORTEX_M0P_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTER_ARM, 0xC60),
+ CORTEX_M23_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTER_ARM, 0xD20),
+ CORTEX_M33_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTER_ARM, 0xD21),
+ CORTEX_M35P_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTER_ARM, 0xD31),
+ CORTEX_M52_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTER_ARM_CHINA, 0xD24),
+ CORTEX_M55_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTER_ARM, 0xD22),
+ CORTEX_M85_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTER_ARM, 0xD23),
+ INFINEON_SLX2_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTER_INFINEON, 0xDB0),
+ REALTEK_M200_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTER_REALTEK, 0xd20),
+ REALTEK_M300_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTER_REALTEK, 0xd22),
};
/* Relevant Cortex-M flags, used in struct cortex_m_part_info.flags */
@@ -149,6 +150,7 @@ struct cortex_m_part_info {
#define VC_CORERESET BIT(0)
/* DCB_DSCSR bit and field definitions */
+#define DSCSR_CDSKEY BIT(17)
#define DSCSR_CDS BIT(16)
/* NVIC registers */
@@ -256,6 +258,10 @@ struct cortex_m_common {
/* Whether this target has the erratum that makes C_MASKINTS not apply to
* already pending interrupts */
bool maskints_erratum;
+
+ /* Errata 3092511 Cortex-M7 can halt in an incorrect address when breakpoint
+ * and exception occurs simultaneously */
+ bool incorrect_halt_erratum;
};
static inline bool is_cortex_m_or_hla(const struct cortex_m_common *cortex_m)
diff --git a/src/target/esirisc.c b/src/target/esirisc.c
index 0f76b59..14d34ff 100644
--- a/src/target/esirisc.c
+++ b/src/target/esirisc.c
@@ -483,7 +483,7 @@ static int esirisc_add_breakpoint(struct target *target, struct breakpoint *brea
* The default linker scripts provided by the eSi-RISC toolchain do
* not specify attributes on memory regions, which results in
* incorrect application of software breakpoints by GDB. Targets
- * must be configured with `gdb_breakpoint_override hard` as
+ * must be configured with `gdb breakpoint_override hard` as
* software breakpoints are not supported.
*/
if (breakpoint->type != BKPT_HARD)
diff --git a/src/target/esirisc_jtag.c b/src/target/esirisc_jtag.c
index 1ec1726..5960e26 100644
--- a/src/target/esirisc_jtag.c
+++ b/src/target/esirisc_jtag.c
@@ -58,11 +58,12 @@ static int esirisc_jtag_get_padding(void)
return padding;
}
-static int esirisc_jtag_count_bits(int num_fields, struct scan_field *fields)
+static int esirisc_jtag_count_bits(unsigned int num_fields,
+ struct scan_field *fields)
{
int bit_count = 0;
- for (int i = 0; i < num_fields; ++i)
+ for (unsigned int i = 0; i < num_fields; ++i)
bit_count += fields[i].num_bits;
return bit_count;
diff --git a/src/target/espressif/esp32s3.c b/src/target/espressif/esp32s3.c
index 22e1630..2afb4b0 100644
--- a/src/target/espressif/esp32s3.c
+++ b/src/target/espressif/esp32s3.c
@@ -421,4 +421,5 @@ struct target_type esp32s3_target = {
.deinit_target = esp_xtensa_target_deinit,
.commands = esp32s3_command_handlers,
+ .profiling = esp_xtensa_profiling,
};
diff --git a/src/target/espressif/esp_xtensa.c b/src/target/espressif/esp_xtensa.c
index 11895d2..9b57f34 100644
--- a/src/target/espressif/esp_xtensa.c
+++ b/src/target/espressif/esp_xtensa.c
@@ -179,3 +179,75 @@ int esp_xtensa_breakpoint_remove(struct target *target, struct breakpoint *break
return xtensa_breakpoint_remove(target, breakpoint);
/* flash breakpoints will be handled in another patch */
}
+
+int esp_xtensa_profiling(struct target *target, uint32_t *samples,
+ uint32_t max_num_samples, uint32_t *num_samples, uint32_t seconds)
+{
+ struct timeval timeout, now;
+ struct xtensa *xtensa = target_to_xtensa(target);
+ int retval = ERROR_OK;
+ int res;
+
+ /* Vary samples per pass to avoid sampling a periodic function periodically */
+ #define MIN_PASS 200
+ #define MAX_PASS 1000
+
+ gettimeofday(&timeout, NULL);
+ timeval_add_time(&timeout, seconds, 0);
+
+ uint8_t buf[sizeof(uint32_t) * MAX_PASS];
+
+ /* Capture one sample to verify the register is present and working */
+ xtensa_queue_dbg_reg_read(xtensa, XDMREG_DEBUGPC, buf);
+ res = xtensa_dm_queue_execute(&xtensa->dbg_mod);
+ if (res != ERROR_OK) {
+ LOG_TARGET_INFO(target, "Failed to read DEBUGPC, fallback to stop-and-go");
+ return target_profiling_default(target, samples, max_num_samples, num_samples, seconds);
+ } else if (buf[0] == 0 && buf[1] == 0 && buf[2] == 0 && buf[3] == 0) {
+ LOG_TARGET_INFO(target, "NULL DEBUGPC, fallback to stop-and-go");
+ return target_profiling_default(target, samples, max_num_samples, num_samples, seconds);
+ }
+
+ LOG_TARGET_INFO(target, "Starting XTENSA DEBUGPC profiling. Sampling as fast as we can...");
+
+ /* Make sure the target is running */
+ target_poll(target);
+ if (target->state == TARGET_HALTED)
+ retval = target_resume(target, 1, 0, 0, 0);
+
+ if (retval != ERROR_OK) {
+ LOG_TARGET_ERROR(target, "Error while resuming target");
+ return retval;
+ }
+
+ uint32_t sample_count = 0;
+
+ for (;;) {
+ uint32_t remaining = max_num_samples - sample_count;
+ uint32_t this_pass = rand() % (MAX_PASS - MIN_PASS) + MIN_PASS;
+ this_pass = this_pass > remaining ? remaining : this_pass;
+ for (uint32_t i = 0; i < this_pass; ++i)
+ xtensa_queue_dbg_reg_read(xtensa, XDMREG_DEBUGPC, buf + i * sizeof(uint32_t));
+ res = xtensa_dm_queue_execute(&xtensa->dbg_mod);
+ if (res != ERROR_OK) {
+ LOG_TARGET_ERROR(target, "Failed to read DEBUGPC!");
+ return res;
+ }
+
+ for (uint32_t i = 0; i < this_pass; ++i) {
+ uint32_t sample32 = buf_get_u32(buf + i * sizeof(uint32_t), 0, 32);
+ samples[sample_count++] = sample32;
+ }
+ gettimeofday(&now, NULL);
+ if (sample_count >= max_num_samples || timeval_compare(&now, &timeout) > 0) {
+ LOG_TARGET_INFO(target, "Profiling completed. %" PRIu32 " samples.", sample_count);
+ break;
+ }
+ }
+
+ *num_samples = sample_count;
+ return retval;
+
+ #undef MIN_PASS
+ #undef MAX_PASS
+}
diff --git a/src/target/espressif/esp_xtensa.h b/src/target/espressif/esp_xtensa.h
index 00f67a3..56c903f 100644
--- a/src/target/espressif/esp_xtensa.h
+++ b/src/target/espressif/esp_xtensa.h
@@ -37,6 +37,9 @@ void esp_xtensa_queue_tdi_idle(struct target *target);
int esp_xtensa_breakpoint_add(struct target *target, struct breakpoint *breakpoint);
int esp_xtensa_breakpoint_remove(struct target *target, struct breakpoint *breakpoint);
int esp_xtensa_poll(struct target *target);
+int esp_xtensa_profiling(struct target *target, uint32_t *samples,
+ uint32_t max_num_samples, uint32_t *num_samples, uint32_t seconds);
+
int esp_xtensa_on_halt(struct target *target);
#endif /* OPENOCD_TARGET_ESP_XTENSA_H */
diff --git a/src/target/lakemont.c b/src/target/lakemont.c
index 6c0964b..1fcd642 100644
--- a/src/target/lakemont.c
+++ b/src/target/lakemont.c
@@ -224,10 +224,10 @@ static int irscan(struct target *t, uint8_t *out,
if (ir_len != t->tap->ir_length) {
retval = ERROR_FAIL;
if (t->tap->enabled)
- LOG_ERROR("%s tap enabled but tap irlen=%d",
+ LOG_ERROR("%s tap enabled but tap irlen=%u",
__func__, t->tap->ir_length);
else
- LOG_ERROR("%s tap not enabled and irlen=%d",
+ LOG_ERROR("%s tap not enabled and irlen=%u",
__func__, t->tap->ir_length);
return retval;
}
diff --git a/src/target/riscv/batch.c b/src/target/riscv/batch.c
index bb1070a..349820a 100644
--- a/src/target/riscv/batch.c
+++ b/src/target/riscv/batch.c
@@ -6,6 +6,7 @@
#include "batch.h"
#include "debug_defines.h"
+#include "debug_reg_printer.h"
#include "riscv.h"
#include "field_helpers.h"
@@ -131,15 +132,141 @@ static void add_idle_before_batch(const struct riscv_batch *batch, size_t start_
}
static int get_delay(const struct riscv_batch *batch, size_t scan_idx,
- const struct riscv_scan_delays *delays)
+ const struct riscv_scan_delays *delays, bool resets_delays,
+ size_t reset_delays_after)
{
assert(batch);
assert(scan_idx < batch->used_scans);
+ const bool delays_were_reset = resets_delays
+ && (scan_idx >= reset_delays_after);
const enum riscv_scan_delay_class delay_class =
batch->delay_classes[scan_idx];
const unsigned int delay = riscv_scan_get_delay(delays, delay_class);
assert(delay <= INT_MAX);
- return delay;
+ return delays_were_reset ? 0 : delay;
+}
+
+static unsigned int decode_dmi(const struct riscv_batch *batch, char *text,
+ uint32_t address, uint32_t data)
+{
+ static const struct {
+ uint32_t address;
+ enum riscv_debug_reg_ordinal ordinal;
+ } description[] = {
+ {DM_DMCONTROL, DM_DMCONTROL_ORDINAL},
+ {DM_DMSTATUS, DM_DMSTATUS_ORDINAL},
+ {DM_ABSTRACTCS, DM_ABSTRACTCS_ORDINAL},
+ {DM_COMMAND, DM_COMMAND_ORDINAL},
+ {DM_SBCS, DM_SBCS_ORDINAL}
+ };
+
+ for (unsigned int i = 0; i < ARRAY_SIZE(description); i++) {
+ if (riscv_get_dmi_address(batch->target, description[i].address)
+ == address) {
+ const riscv_debug_reg_ctx_t context = {
+ .XLEN = { .value = 0, .is_set = false },
+ .DXLEN = { .value = 0, .is_set = false },
+ .abits = { .value = 0, .is_set = false },
+ };
+ return riscv_debug_reg_to_s(text, description[i].ordinal,
+ context, data, RISCV_DEBUG_REG_HIDE_ALL_0);
+ }
+ }
+ if (text)
+ text[0] = '\0';
+ return 0;
+}
+
+static void log_dmi_decoded(const struct riscv_batch *batch, bool write,
+ uint32_t address, uint32_t data)
+{
+ const size_t size = decode_dmi(batch, /* text */ NULL, address, data) + 1;
+ char * const decoded = malloc(size);
+ if (!decoded) {
+ LOG_ERROR("Not enough memory to allocate %zu bytes.", size);
+ return;
+ }
+ decode_dmi(batch, decoded, address, data);
+ LOG_DEBUG("%s: %s", write ? "write" : "read", decoded);
+ free(decoded);
+}
+
+static void log_batch(const struct riscv_batch *batch, size_t start_idx,
+ const struct riscv_scan_delays *delays, bool resets_delays,
+ size_t reset_delays_after)
+{
+ if (debug_level < LOG_LVL_DEBUG)
+ return;
+
+ const unsigned int scan_bits = batch->fields->num_bits;
+ assert(scan_bits == (unsigned int)riscv_get_dmi_scan_length(batch->target));
+ const unsigned int abits = scan_bits - DTM_DMI_OP_LENGTH
+ - DTM_DMI_DATA_LENGTH;
+
+ /* Determine the "op" and "address" of the scan that preceded the first
+ * executed scan.
+ * FIXME: The code here assumes that there were no DMI operations between
+ * the last execution of the batch and the current one.
+ * Caching the info about the last executed DMI scan in "dm013_info_t"
+ * would be a more robust solution.
+ */
+ bool last_scan_was_read = false;
+ uint32_t last_scan_address = -1 /* to silence maybe-uninitialized */;
+ if (start_idx > 0) {
+ const struct scan_field * const field = &batch->fields[start_idx - 1];
+ assert(field->out_value);
+ last_scan_was_read = buf_get_u32(field->out_value, DTM_DMI_OP_OFFSET,
+ DTM_DMI_OP_LENGTH) == DTM_DMI_OP_READ;
+ last_scan_address = buf_get_u32(field->out_value,
+ DTM_DMI_ADDRESS_OFFSET, abits);
+ }
+
+ /* Decode and log every executed scan */
+ for (size_t i = start_idx; i < batch->used_scans; ++i) {
+ static const char * const op_string[] = {"-", "r", "w", "?"};
+ const int delay = get_delay(batch, i, delays, resets_delays,
+ reset_delays_after);
+ const struct scan_field * const field = &batch->fields[i];
+
+ assert(field->out_value);
+ const unsigned int out_op = buf_get_u32(field->out_value,
+ DTM_DMI_OP_OFFSET, DTM_DMI_OP_LENGTH);
+ const uint32_t out_data = buf_get_u32(field->out_value,
+ DTM_DMI_DATA_OFFSET, DTM_DMI_DATA_LENGTH);
+ const uint32_t out_address = buf_get_u32(field->out_value,
+ DTM_DMI_ADDRESS_OFFSET, abits);
+ if (field->in_value) {
+ static const char * const status_string[] = {
+ "+", "?", "F", "b"
+ };
+ const unsigned int in_op = buf_get_u32(field->in_value,
+ DTM_DMI_OP_OFFSET, DTM_DMI_OP_LENGTH);
+ const uint32_t in_data = buf_get_u32(field->in_value,
+ DTM_DMI_DATA_OFFSET, DTM_DMI_DATA_LENGTH);
+ const uint32_t in_address = buf_get_u32(field->in_value,
+ DTM_DMI_ADDRESS_OFFSET, abits);
+
+ LOG_DEBUG("%db %s %08" PRIx32 " @%02" PRIx32
+ " -> %s %08" PRIx32 " @%02" PRIx32 "; %di",
+ field->num_bits, op_string[out_op], out_data, out_address,
+ status_string[in_op], in_data, in_address, delay);
+
+ if (last_scan_was_read && in_op == DTM_DMI_OP_SUCCESS)
+ log_dmi_decoded(batch, /*write*/ false,
+ last_scan_address, in_data);
+ } else {
+ LOG_DEBUG("%db %s %08" PRIx32 " @%02" PRIx32 " -> ?; %di",
+ field->num_bits, op_string[out_op], out_data, out_address,
+ delay);
+ }
+
+ if (out_op == DTM_DMI_OP_WRITE)
+ log_dmi_decoded(batch, /*write*/ true, out_address,
+ out_data);
+
+ last_scan_was_read = out_op == DTM_DMI_OP_READ;
+ last_scan_address = out_address;
+ }
}
int riscv_batch_run_from(struct riscv_batch *batch, size_t start_idx,
@@ -147,6 +274,7 @@ int riscv_batch_run_from(struct riscv_batch *batch, size_t start_idx,
size_t reset_delays_after)
{
assert(batch->used_scans);
+ assert(start_idx < batch->used_scans);
assert(batch->last_scan == RISCV_SCAN_TYPE_NOP);
assert(!batch->was_run || riscv_batch_was_scan_busy(batch, start_idx));
assert(start_idx == 0 || !riscv_batch_was_scan_busy(batch, start_idx - 1));
@@ -157,17 +285,16 @@ int riscv_batch_run_from(struct riscv_batch *batch, size_t start_idx,
LOG_TARGET_DEBUG(batch->target, "Running batch of scans [%zu, %zu)",
start_idx, batch->used_scans);
+ unsigned int delay = 0 /* to silence maybe-uninitialized */;
for (size_t i = start_idx; i < batch->used_scans; ++i) {
if (bscan_tunnel_ir_width != 0)
riscv_add_bscan_tunneled_scan(batch->target, batch->fields + i, batch->bscan_ctxt + i);
else
jtag_add_dr_scan(batch->target->tap, 1, batch->fields + i, TAP_IDLE);
- const bool delays_were_reset = resets_delays
- && (i >= reset_delays_after);
- const int delay = get_delay(batch, i, delays);
-
- if (!delays_were_reset)
+ delay = get_delay(batch, i, delays, resets_delays,
+ reset_delays_after);
+ if (delay > 0)
jtag_add_runtest(delay, TAP_IDLE);
}
@@ -188,25 +315,20 @@ int riscv_batch_run_from(struct riscv_batch *batch, size_t start_idx,
}
}
- for (size_t i = start_idx; i < batch->used_scans; ++i) {
- const int delay = get_delay(batch, i, delays);
- riscv_log_dmi_scan(batch->target, delay, batch->fields + i,
- /*discard_in*/ false);
- }
-
+ log_batch(batch, start_idx, delays, resets_delays, reset_delays_after);
batch->was_run = true;
- batch->last_scan_delay = get_delay(batch, batch->used_scans - 1, delays);
+ batch->last_scan_delay = delay;
return ERROR_OK;
}
-void riscv_batch_add_dm_write(struct riscv_batch *batch, uint64_t address, uint32_t data,
+void riscv_batch_add_dmi_write(struct riscv_batch *batch, uint64_t address, uint32_t data,
bool read_back, enum riscv_scan_delay_class delay_class)
{
assert(batch->used_scans < batch->allocated_scans);
struct scan_field *field = batch->fields + batch->used_scans;
field->num_bits = riscv_get_dmi_scan_length(batch->target);
field->out_value = (void *)(batch->data_out + batch->used_scans * DMI_SCAN_BUF_SIZE);
- riscv_fill_dm_write(batch->target, (char *)field->out_value, address, data);
+ riscv_fill_dmi_write(batch->target, (char *)field->out_value, address, data);
if (read_back) {
field->in_value = (void *)(batch->data_in + batch->used_scans * DMI_SCAN_BUF_SIZE);
riscv_fill_dm_nop(batch->target, (char *)field->in_value);
@@ -218,7 +340,7 @@ void riscv_batch_add_dm_write(struct riscv_batch *batch, uint64_t address, uint3
batch->used_scans++;
}
-size_t riscv_batch_add_dm_read(struct riscv_batch *batch, uint64_t address,
+size_t riscv_batch_add_dmi_read(struct riscv_batch *batch, uint64_t address,
enum riscv_scan_delay_class delay_class)
{
assert(batch->used_scans < batch->allocated_scans);
@@ -226,7 +348,7 @@ size_t riscv_batch_add_dm_read(struct riscv_batch *batch, uint64_t address,
field->num_bits = riscv_get_dmi_scan_length(batch->target);
field->out_value = (void *)(batch->data_out + batch->used_scans * DMI_SCAN_BUF_SIZE);
field->in_value = (void *)(batch->data_in + batch->used_scans * DMI_SCAN_BUF_SIZE);
- riscv_fill_dm_read(batch->target, (char *)field->out_value, address);
+ riscv_fill_dmi_read(batch->target, (char *)field->out_value, address);
riscv_fill_dm_nop(batch->target, (char *)field->in_value);
batch->delay_classes[batch->used_scans] = delay_class;
batch->last_scan = RISCV_SCAN_TYPE_READ;
diff --git a/src/target/riscv/batch.h b/src/target/riscv/batch.h
index 1a39939..6fcfeb2 100644
--- a/src/target/riscv/batch.h
+++ b/src/target/riscv/batch.h
@@ -190,14 +190,32 @@ int riscv_batch_run_from(struct riscv_batch *batch, size_t start_idx,
size_t riscv_batch_finished_scans(const struct riscv_batch *batch);
/* Adds a DM register write to this batch. */
-void riscv_batch_add_dm_write(struct riscv_batch *batch, uint64_t address, uint32_t data,
+void riscv_batch_add_dmi_write(struct riscv_batch *batch, uint64_t address, uint32_t data,
bool read_back, enum riscv_scan_delay_class delay_class);
+static inline void
+riscv_batch_add_dm_write(struct riscv_batch *batch, uint64_t address, uint32_t data,
+ bool read_back, enum riscv_scan_delay_class delay_type)
+{
+ return riscv_batch_add_dmi_write(batch,
+ riscv_get_dmi_address(batch->target, address), data,
+ read_back, delay_type);
+}
+
/* DM register reads must be handled in two parts: the first one schedules a read and
* provides a key, the second one actually obtains the result of the read -
* status (op) and the actual data. */
-size_t riscv_batch_add_dm_read(struct riscv_batch *batch, uint64_t address,
+size_t riscv_batch_add_dmi_read(struct riscv_batch *batch, uint64_t address,
enum riscv_scan_delay_class delay_class);
+
+static inline size_t
+riscv_batch_add_dm_read(struct riscv_batch *batch, uint64_t address,
+ enum riscv_scan_delay_class delay_type)
+{
+ return riscv_batch_add_dmi_read(batch,
+ riscv_get_dmi_address(batch->target, address), delay_type);
+}
+
unsigned int riscv_batch_get_dmi_read_op(const struct riscv_batch *batch, size_t key);
uint32_t riscv_batch_get_dmi_read_data(const struct riscv_batch *batch, size_t key);
@@ -210,10 +228,4 @@ size_t riscv_batch_available_scans(struct riscv_batch *batch);
/* Return true iff the last scan in the batch returned DMI_OP_BUSY. */
bool riscv_batch_was_batch_busy(const struct riscv_batch *batch);
-/* TODO: The function is defined in `riscv-013.c`. This is done to reduce the
- * diff of the commit. The intention is to move the function definition to
- * a separate module (e.g. `riscv013-jtag-dtm.c/h`) in another commit. */
-void riscv_log_dmi_scan(const struct target *target, int idle, const struct scan_field *field,
- bool discard_in);
-
#endif /* OPENOCD_TARGET_RISCV_BATCH_H */
diff --git a/src/target/riscv/opcodes.h b/src/target/riscv/opcodes.h
index 99ae90f..1164bd6 100644
--- a/src/target/riscv/opcodes.h
+++ b/src/target/riscv/opcodes.h
@@ -194,26 +194,26 @@ static uint32_t fld(unsigned int dest, unsigned int base, uint16_t offset)
return imm_i(offset) | inst_rs1(base) | inst_rd(dest) | MATCH_FLD;
}
-static uint32_t fmv_x_w(unsigned dest, unsigned src) __attribute__ ((unused));
-static uint32_t fmv_x_w(unsigned dest, unsigned src)
+static uint32_t fmv_x_w(unsigned int dest, unsigned int src) __attribute__ ((unused));
+static uint32_t fmv_x_w(unsigned int dest, unsigned int src)
{
return inst_rs1(src) | inst_rd(dest) | MATCH_FMV_X_W;
}
-static uint32_t fmv_x_d(unsigned dest, unsigned src) __attribute__ ((unused));
-static uint32_t fmv_x_d(unsigned dest, unsigned src)
+static uint32_t fmv_x_d(unsigned int dest, unsigned int src) __attribute__ ((unused));
+static uint32_t fmv_x_d(unsigned int dest, unsigned int src)
{
return inst_rs1(src) | inst_rd(dest) | MATCH_FMV_X_D;
}
-static uint32_t fmv_w_x(unsigned dest, unsigned src) __attribute__ ((unused));
-static uint32_t fmv_w_x(unsigned dest, unsigned src)
+static uint32_t fmv_w_x(unsigned int dest, unsigned int src) __attribute__ ((unused));
+static uint32_t fmv_w_x(unsigned int dest, unsigned int src)
{
return inst_rs1(src) | inst_rd(dest) | MATCH_FMV_W_X;
}
-static uint32_t fmv_d_x(unsigned dest, unsigned src) __attribute__ ((unused));
-static uint32_t fmv_d_x(unsigned dest, unsigned src)
+static uint32_t fmv_d_x(unsigned int dest, unsigned int src) __attribute__ ((unused));
+static uint32_t fmv_d_x(unsigned int dest, unsigned int src)
{
return inst_rs1(src) | inst_rd(dest) | MATCH_FMV_D_X;
}
diff --git a/src/target/riscv/program.c b/src/target/riscv/program.c
index c4ffb3f..6246d00 100644
--- a/src/target/riscv/program.c
+++ b/src/target/riscv/program.c
@@ -30,7 +30,7 @@ int riscv_program_init(struct riscv_program *p, struct target *target)
int riscv_program_write(struct riscv_program *program)
{
- for (unsigned i = 0; i < program->instruction_count; ++i) {
+ for (unsigned int i = 0; i < program->instruction_count; ++i) {
LOG_TARGET_DEBUG(program->target, "progbuf[%02x] = DASM(0x%08x)",
i, program->progbuf[i]);
if (riscv_write_progbuf(program->target, i, program->progbuf[i]) != ERROR_OK)
@@ -183,8 +183,8 @@ int riscv_program_ebreak(struct riscv_program *p)
{
struct target *target = p->target;
RISCV_INFO(r);
- if (p->instruction_count == riscv_progbuf_size(p->target) &&
- r->impebreak) {
+ if (p->instruction_count == riscv_progbuf_size(target) &&
+ r->get_impebreak(target)) {
return ERROR_OK;
}
return riscv_program_insert(p, ebreak());
diff --git a/src/target/riscv/riscv-011.c b/src/target/riscv/riscv-011.c
index cd30a52..0e635b3 100644
--- a/src/target/riscv/riscv-011.c
+++ b/src/target/riscv/riscv-011.c
@@ -273,38 +273,6 @@ static uint16_t dram_address(unsigned int index)
return 0x40 + index - 0x10;
}
-static int dtmcontrol_scan(struct target *target, uint32_t out, uint32_t *in_ptr)
-{
- struct scan_field field;
- uint8_t in_value[4];
- uint8_t out_value[4] = { 0 };
-
- buf_set_u32(out_value, 0, 32, out);
-
- jtag_add_ir_scan(target->tap, &select_dtmcontrol, TAP_IDLE);
-
- field.num_bits = 32;
- field.out_value = out_value;
- field.in_value = in_value;
- jtag_add_dr_scan(target->tap, 1, &field, TAP_IDLE);
-
- /* Always return to dbus. */
- jtag_add_ir_scan(target->tap, &select_dbus, TAP_IDLE);
-
- int retval = jtag_execute_queue();
- if (retval != ERROR_OK) {
- LOG_ERROR("failed jtag scan: %d", retval);
- return retval;
- }
-
- uint32_t in = buf_get_u32(field.in_value, 0, 32);
- LOG_DEBUG("DTMCONTROL: 0x%x -> 0x%x", out, in);
-
- if (in_ptr)
- *in_ptr = in;
- return ERROR_OK;
-}
-
static uint32_t idcode_scan(struct target *target)
{
struct scan_field field;
@@ -408,7 +376,7 @@ static void dump_field(const struct scan_field *field)
log_printf_lf(LOG_LVL_DEBUG,
__FILE__, __LINE__, "scan",
- "%db %s %c%c:%08x @%02x -> %s %c%c:%08x @%02x",
+ "%ub %s %c%c:%08x @%02x -> %s %c%c:%08x @%02x",
field->num_bits,
op_string[out_op], out_interrupt, out_haltnot, out_data,
out_address,
@@ -475,7 +443,7 @@ static uint64_t dbus_read(struct target *target, uint16_t address)
* While somewhat nonintuitive, this is an efficient way to get the data.
*/
- unsigned i = 0;
+ unsigned int i = 0;
do {
status = dbus_scan(target, &address_in, &value, DBUS_OP_READ, address, 0);
if (status == DBUS_STATUS_BUSY)
@@ -496,7 +464,7 @@ static uint64_t dbus_read(struct target *target, uint16_t address)
static void dbus_write(struct target *target, uint16_t address, uint64_t value)
{
dbus_status_t status = DBUS_STATUS_BUSY;
- unsigned i = 0;
+ unsigned int i = 0;
while (status == DBUS_STATUS_BUSY && i++ < 256) {
status = dbus_scan(target, NULL, NULL, DBUS_OP_WRITE, address, value);
if (status == DBUS_STATUS_BUSY)
@@ -657,13 +625,13 @@ static void scans_add_read(scans_t *scans, slot_t slot, bool set_interrupt)
}
static uint32_t scans_get_u32(scans_t *scans, unsigned int index,
- unsigned first, unsigned num)
+ unsigned int first, unsigned int num)
{
return buf_get_u32(scans->in + scans->scan_size * index, first, num);
}
static uint64_t scans_get_u64(scans_t *scans, unsigned int index,
- unsigned first, unsigned num)
+ unsigned int first, unsigned int num)
{
return buf_get_u64(scans->in + scans->scan_size * index, first, num);
}
@@ -695,7 +663,7 @@ static int read_bits(struct target *target, bits_t *result)
riscv011_info_t *info = get_info(target);
do {
- unsigned i = 0;
+ unsigned int i = 0;
do {
status = dbus_scan(target, &address_in, &value, DBUS_OP_READ, 0, 0);
if (status == DBUS_STATUS_BUSY) {
@@ -741,7 +709,7 @@ static int wait_for_debugint_clear(struct target *target, bool ignore_first)
if (!bits.interrupt)
return ERROR_OK;
- if (time(NULL) - start > riscv_command_timeout_sec) {
+ if (time(NULL) - start > riscv_get_command_timeout_sec()) {
LOG_ERROR("Timed out waiting for debug int to clear."
"Increase timeout with riscv set_command_timeout_sec.");
return ERROR_FAIL;
@@ -1025,7 +993,7 @@ static int wait_for_state(struct target *target, enum target_state state)
return result;
if (target->state == state)
return ERROR_OK;
- if (time(NULL) - start > riscv_command_timeout_sec) {
+ if (time(NULL) - start > riscv_get_command_timeout_sec()) {
LOG_ERROR("Timed out waiting for state %d. "
"Increase timeout with riscv set_command_timeout_sec.", state);
return ERROR_FAIL;
@@ -1186,7 +1154,7 @@ static int full_step(struct target *target, bool announce)
return result;
if (target->state != TARGET_DEBUG_RUNNING)
break;
- if (time(NULL) - start > riscv_command_timeout_sec) {
+ if (time(NULL) - start > riscv_get_command_timeout_sec()) {
LOG_ERROR("Timed out waiting for step to complete."
"Increase timeout with riscv set_command_timeout_sec");
return ERROR_FAIL;
@@ -1289,7 +1257,7 @@ static int register_write(struct target *target, unsigned int number,
int result = update_mstatus_actual(target);
if (result != ERROR_OK)
return result;
- unsigned i = 0;
+ unsigned int i = 0;
if ((info->mstatus_actual & MSTATUS_FS) == 0) {
info->mstatus_actual = set_field(info->mstatus_actual, MSTATUS_FS, 1);
cache_set_load(target, i++, S0, SLOT1);
@@ -1350,7 +1318,7 @@ int riscv011_get_register(struct target *target, riscv_reg_t *value,
int result = update_mstatus_actual(target);
if (result != ERROR_OK)
return result;
- unsigned i = 0;
+ unsigned int i = 0;
if ((info->mstatus_actual & MSTATUS_FS) == 0) {
info->mstatus_actual = set_field(info->mstatus_actual, MSTATUS_FS, 1);
cache_set_load(target, i++, S0, SLOT1);
@@ -1554,7 +1522,7 @@ static int examine(struct target *target)
/* 0x00000000 0x00000000:00000003 0x00000000:00000003:ffffffff:ffffffff */
cache_set32(target, 4, sw(S1, ZERO, DEBUG_RAM_START + 4));
cache_set_jump(target, 5);
- for (unsigned i = 6; i < info->dramsize; i++)
+ for (unsigned int i = 6; i < info->dramsize; i++)
cache_set32(target, i, i * 0x01020304);
cache_write(target, 0, false);
@@ -1585,7 +1553,7 @@ static int examine(struct target *target)
LOG_DEBUG("Discovered XLEN is %d", riscv_xlen(target));
if (read_remote_csr(target, &r->misa, CSR_MISA) != ERROR_OK) {
- const unsigned old_csr_misa = 0xf10;
+ const unsigned int old_csr_misa = 0xf10;
LOG_WARNING("Failed to read misa at 0x%x; trying 0x%x.", CSR_MISA,
old_csr_misa);
if (read_remote_csr(target, &r->misa, old_csr_misa) != ERROR_OK) {
@@ -1664,7 +1632,7 @@ static riscv_error_t handle_halt_routine(struct target *target)
unsigned int dbus_busy = 0;
unsigned int interrupt_set = 0;
- unsigned result = 0;
+ unsigned int result = 0;
uint64_t value = 0;
reg_cache_set(target, 0, 0);
/* The first scan result is the result from something old we don't care
@@ -2036,7 +2004,7 @@ static int read_memory(struct target *target, target_addr_t address,
cache_write(target, CACHE_NO_READ, false);
riscv011_info_t *info = get_info(target);
- const unsigned max_batch_size = 256;
+ const unsigned int max_batch_size = 256;
scans_t *scans = scans_new(target, max_batch_size);
if (!scans)
return ERROR_FAIL;
@@ -2194,7 +2162,7 @@ static int write_memory(struct target *target, target_addr_t address,
if (setup_write_memory(target, size) != ERROR_OK)
return ERROR_FAIL;
- const unsigned max_batch_size = 256;
+ const unsigned int max_batch_size = 256;
scans_t *scans = scans_new(target, max_batch_size);
if (!scans)
return ERROR_FAIL;
@@ -2344,10 +2312,10 @@ static int wait_for_authbusy(struct target *target)
uint32_t dminfo = dbus_read(target, DMINFO);
if (!get_field(dminfo, DMINFO_AUTHBUSY))
break;
- if (time(NULL) - start > riscv_command_timeout_sec) {
+ if (time(NULL) - start > riscv_get_command_timeout_sec()) {
LOG_ERROR("Timed out after %ds waiting for authbusy to go low (dminfo=0x%x). "
"Increase the timeout with riscv set_command_timeout_sec.",
- riscv_command_timeout_sec,
+ riscv_get_command_timeout_sec(),
dminfo);
return ERROR_FAIL;
}
@@ -2388,6 +2356,16 @@ static int riscv011_authdata_write(struct target *target, uint32_t value, unsign
return ERROR_OK;
}
+static bool riscv011_get_impebreak(const struct target *target)
+{
+ return false;
+}
+
+static unsigned int riscv011_get_progbufsize(const struct target *target)
+{
+ return 0;
+}
+
static int init_target(struct command_context *cmd_ctx,
struct target *target)
{
@@ -2397,6 +2375,8 @@ static int init_target(struct command_context *cmd_ctx,
generic_info->authdata_read = &riscv011_authdata_read;
generic_info->authdata_write = &riscv011_authdata_write;
generic_info->print_info = &riscv011_print_info;
+ generic_info->get_impebreak = &riscv011_get_impebreak;
+ generic_info->get_progbufsize = &riscv011_get_progbufsize;
generic_info->version_specific = calloc(1, sizeof(riscv011_info_t));
if (!generic_info->version_specific)
diff --git a/src/target/riscv/riscv-011_reg.c b/src/target/riscv/riscv-011_reg.c
index 7f29064..44ea1a4 100644
--- a/src/target/riscv/riscv-011_reg.c
+++ b/src/target/riscv/riscv-011_reg.c
@@ -38,7 +38,9 @@ static const struct reg_arch_type *riscv011_gdb_regno_reg_type(uint32_t regno)
static int riscv011_init_reg(struct target *target, uint32_t regno)
{
- return riscv_reg_impl_init_one(target, regno, riscv011_gdb_regno_reg_type(regno));
+ return riscv_reg_impl_init_cache_entry(target, regno,
+ riscv_reg_impl_gdb_regno_exist(target, regno),
+ riscv011_gdb_regno_reg_type(regno));
}
int riscv011_reg_init_all(struct target *target)
diff --git a/src/target/riscv/riscv-013.c b/src/target/riscv/riscv-013.c
index 07b6da0..85125c9 100644
--- a/src/target/riscv/riscv-013.c
+++ b/src/target/riscv/riscv-013.c
@@ -16,6 +16,7 @@
#include "target/target.h"
#include "target/algorithm.h"
#include "target/target_type.h"
+#include <helper/align.h>
#include <helper/log.h>
#include "jtag/jtag.h"
#include "target/register.h"
@@ -56,10 +57,7 @@ static int riscv013_invalidate_cached_progbuf(struct target *target);
static int riscv013_execute_progbuf(struct target *target, uint32_t *cmderr);
static void riscv013_fill_dmi_write(struct target *target, char *buf, uint64_t a, uint32_t d);
static void riscv013_fill_dmi_read(struct target *target, char *buf, uint64_t a);
-static void riscv013_fill_dmi_nop(struct target *target, char *buf);
static int riscv013_get_dmi_scan_length(struct target *target);
-static void riscv013_fill_dm_write(struct target *target, char *buf, uint64_t a, uint32_t d);
-static void riscv013_fill_dm_read(struct target *target, char *buf, uint64_t a);
static void riscv013_fill_dm_nop(struct target *target, char *buf);
static unsigned int register_size(struct target *target, enum gdb_regno number);
static int register_read_direct(struct target *target, riscv_reg_t *value,
@@ -70,6 +68,8 @@ static int read_memory(struct target *target, target_addr_t address,
uint32_t size, uint32_t count, uint8_t *buffer, uint32_t increment);
static int write_memory(struct target *target, target_addr_t address,
uint32_t size, uint32_t count, const uint8_t *buffer);
+static bool riscv013_get_impebreak(const struct target *target);
+static unsigned int riscv013_get_progbufsize(const struct target *target);
typedef enum {
HALT_GROUP,
@@ -115,7 +115,7 @@ typedef enum {
typedef struct {
struct list_head list;
- int abs_chain_position;
+ unsigned int abs_chain_position;
/* The base address to access this DM on DMI */
uint32_t base;
/* The number of harts connected to this DM. */
@@ -150,13 +150,15 @@ typedef struct {
typedef struct {
/* The indexed used to address this hart in its DM. */
- unsigned index;
+ unsigned int index;
/* Number of address bits in the dbus register. */
- unsigned abits;
+ unsigned int abits;
/* Number of abstract command data registers. */
- unsigned datacount;
+ unsigned int datacount;
/* Number of words in the Program Buffer. */
- unsigned progbufsize;
+ unsigned int progbufsize;
+ /* Hart contains an implicit ebreak at the end of the program buffer. */
+ bool impebreak;
/* We cache the read-only bits of sbcs here. */
uint32_t sbcs;
@@ -223,7 +225,7 @@ static dm013_info_t *get_dm(struct target *target)
if (info->dm)
return info->dm;
- int abs_chain_position = target->tap->abs_chain_position;
+ unsigned int abs_chain_position = target->tap->abs_chain_position;
dm013_info_t *entry;
dm013_info_t *dm = NULL;
@@ -347,82 +349,6 @@ static uint32_t set_dmcontrol_hartsel(uint32_t initial, int hart_index)
return initial;
}
-static unsigned int decode_dmi(const struct target *target, char *text, uint32_t address, uint32_t data)
-{
- static const struct {
- uint32_t address;
- enum riscv_debug_reg_ordinal ordinal;
- } description[] = {
- {DM_DMCONTROL, DM_DMCONTROL_ORDINAL},
- {DM_DMSTATUS, DM_DMSTATUS_ORDINAL},
- {DM_ABSTRACTCS, DM_ABSTRACTCS_ORDINAL},
- {DM_COMMAND, DM_COMMAND_ORDINAL},
- {DM_SBCS, DM_SBCS_ORDINAL}
- };
-
- for (unsigned i = 0; i < ARRAY_SIZE(description); i++) {
- if (riscv_get_dmi_address(target, description[i].address) == address) {
- const riscv_debug_reg_ctx_t context = {
- .XLEN = { .value = 0, .is_set = false },
- .DXLEN = { .value = 0, .is_set = false },
- .abits = { .value = 0, .is_set = false },
- };
- return riscv_debug_reg_to_s(text, description[i].ordinal,
- context, data, RISCV_DEBUG_REG_HIDE_ALL_0);
- }
- }
- if (text)
- text[0] = '\0';
- return 0;
-}
-
-void riscv_log_dmi_scan(const struct target *target, int idle, const struct scan_field *field, bool discard_in)
-{
- static const char * const op_string[] = {"-", "r", "w", "?"};
- static const char * const status_string[] = {"+", "?", "F", "b"};
-
- if (debug_level < LOG_LVL_DEBUG)
- return;
-
- assert(field->out_value);
- const uint64_t out = buf_get_u64(field->out_value, 0, field->num_bits);
- const unsigned int out_op = get_field(out, DTM_DMI_OP);
- const uint32_t out_data = get_field(out, DTM_DMI_DATA);
- const uint32_t out_address = out >> DTM_DMI_ADDRESS_OFFSET;
-
- if (field->in_value) {
- const uint64_t in = buf_get_u64(field->in_value, 0, field->num_bits);
- const unsigned int in_op = get_field(in, DTM_DMI_OP);
- const uint32_t in_data = get_field(in, DTM_DMI_DATA);
- const uint32_t in_address = in >> DTM_DMI_ADDRESS_OFFSET;
-
- LOG_DEBUG("%db %s %08" PRIx32 " @%02" PRIx32 " -> %s %08" PRIx32 " @%02" PRIx32 "; %di",
- field->num_bits, op_string[out_op], out_data, out_address,
- status_string[in_op], in_data, in_address, idle);
-
- if (!discard_in && in_op == DTM_DMI_OP_SUCCESS) {
- char in_decoded[decode_dmi(target, NULL, in_address, in_data) + 1];
- decode_dmi(target, in_decoded, in_address, in_data);
- /* FIXME: The current code assumes that the hardware
- * provides the read address in the dmi.address field
- * when returning the dmi.data. That is however not
- * required by the spec, and therefore not guaranteed.
- * See https://github.com/riscv-collab/riscv-openocd/issues/1043
- */
- LOG_DEBUG("read: %s", in_decoded);
- }
- } else {
- LOG_DEBUG("%db %s %08" PRIx32 " @%02" PRIx32 " -> ?; %di",
- field->num_bits, op_string[out_op], out_data, out_address,
- idle);
- }
- if (out_op == DTM_DMI_OP_WRITE) {
- char out_decoded[decode_dmi(target, NULL, out_address, out_data) + 1];
- decode_dmi(target, out_decoded, out_address, out_data);
- LOG_DEBUG("write: %s", out_decoded);
- }
-}
-
/*** Utility functions. ***/
static void select_dmi(struct target *target)
@@ -431,42 +357,31 @@ static void select_dmi(struct target *target)
select_dmi_via_bscan(target);
return;
}
- jtag_add_ir_scan(target->tap, &select_dbus, TAP_IDLE);
-}
-
-static int dtmcontrol_scan(struct target *target, uint32_t out, uint32_t *in_ptr)
-{
- struct scan_field field;
- uint8_t in_value[4];
- uint8_t out_value[4] = { 0 };
-
- if (bscan_tunnel_ir_width != 0)
- return dtmcontrol_scan_via_bscan(target, out, in_ptr);
-
- buf_set_u32(out_value, 0, 32, out);
-
- jtag_add_ir_scan(target->tap, &select_dtmcontrol, TAP_IDLE);
-
- field.num_bits = 32;
- field.out_value = out_value;
- field.in_value = in_value;
- jtag_add_dr_scan(target->tap, 1, &field, TAP_IDLE);
-
- /* Always return to dmi. */
- select_dmi(target);
-
- int retval = jtag_execute_queue();
- if (retval != ERROR_OK) {
- LOG_ERROR("failed jtag scan: %d", retval);
- return retval;
+ if (!target->tap->enabled)
+ LOG_TARGET_ERROR(target, "BUG: Target's TAP '%s' is disabled!",
+ jtag_tap_name(target->tap));
+
+ bool need_ir_scan = false;
+ /* FIXME: make "tap" a const pointer. */
+ for (struct jtag_tap *tap = jtag_tap_next_enabled(NULL);
+ tap; tap = jtag_tap_next_enabled(tap)) {
+ if (tap != target->tap) {
+ /* Different TAP than ours - check if it is in bypass */
+ if (!tap->bypass) {
+ need_ir_scan = true;
+ break;
+ }
+ } else {
+ /* Our TAP - check if the correct instruction is already loaded */
+ if (!buf_eq(target->tap->cur_instr, select_dbus.out_value, target->tap->ir_length)) {
+ need_ir_scan = true;
+ break;
+ }
+ }
}
- uint32_t in = buf_get_u32(field.in_value, 0, 32);
- LOG_DEBUG("DTMCS: 0x%x -> 0x%x", out, in);
-
- if (in_ptr)
- *in_ptr = in;
- return ERROR_OK;
+ if (need_ir_scan)
+ jtag_add_ir_scan(target->tap, &select_dbus, TAP_IDLE);
}
static int increase_dmi_busy_delay(struct target *target)
@@ -506,220 +421,6 @@ static void decrement_reset_delays_counter(struct target *target, size_t finishe
"resetting learned delays (reset_delays_wait counter expired)");
reset_learned_delays(target);
}
-/**
- * exec: If this is set, assume the scan results in an execution, so more
- * run-test/idle cycles may be required.
- */
-static dmi_status_t dmi_scan(struct target *target, uint32_t *address_in,
- uint32_t *data_in, dmi_op_t op, uint32_t address_out, uint32_t data_out,
- bool exec)
-{
- riscv013_info_t *info = get_info(target);
- unsigned num_bits = info->abits + DTM_DMI_OP_LENGTH + DTM_DMI_DATA_LENGTH;
- size_t num_bytes = (num_bits + 7) / 8;
- uint8_t in[num_bytes];
- uint8_t out[num_bytes];
- struct scan_field field = {
- .num_bits = num_bits,
- .out_value = out,
- .in_value = in
- };
- riscv_bscan_tunneled_scan_context_t bscan_ctxt;
-
- decrement_reset_delays_counter(target, 1);
-
- memset(in, 0, num_bytes);
- memset(out, 0, num_bytes);
-
- if (info->abits == 0) {
- LOG_TARGET_ERROR(target, "Can't access DMI because addrbits=0.");
- return DMI_STATUS_FAILED;
- }
-
- buf_set_u32(out, DTM_DMI_OP_OFFSET, DTM_DMI_OP_LENGTH, op);
- buf_set_u32(out, DTM_DMI_DATA_OFFSET, DTM_DMI_DATA_LENGTH, data_out);
- buf_set_u32(out, DTM_DMI_ADDRESS_OFFSET, info->abits, address_out);
-
- /* I wanted to place this code in a different function, but the way JTAG command
- queueing works in the jtag handling functions, the scan fields either have to be
- heap allocated, global/static, or else they need to stay on the stack until
- the jtag_execute_queue() call. Heap or static fields in this case doesn't seem
- the best fit. Declaring stack based field values in a subsidiary function call wouldn't
- work. */
- if (bscan_tunnel_ir_width != 0) {
- riscv_add_bscan_tunneled_scan(target, &field, &bscan_ctxt);
- } else {
- /* Assume dbus is already selected. */
- jtag_add_dr_scan(target->tap, 1, &field, TAP_IDLE);
- }
-
- int idle_count = exec
- ? riscv_scan_get_delay(&info->learned_delays, RISCV_DELAY_ABSTRACT_COMMAND)
- : riscv_scan_get_delay(&info->learned_delays, RISCV_DELAY_BASE);
-
- if (idle_count)
- jtag_add_runtest(idle_count, TAP_IDLE);
-
- int retval = jtag_execute_queue();
- if (retval != ERROR_OK) {
- LOG_ERROR("dmi_scan failed jtag scan");
- if (data_in)
- *data_in = ~0;
- return DMI_STATUS_FAILED;
- }
-
- if (bscan_tunnel_ir_width != 0) {
- /* need to right-shift "in" by one bit, because of clock skew between BSCAN TAP and DM TAP */
- buffer_shr(in, num_bytes, 1);
- }
-
- if (data_in)
- *data_in = buf_get_u32(in, DTM_DMI_DATA_OFFSET, DTM_DMI_DATA_LENGTH);
-
- if (address_in)
- *address_in = buf_get_u32(in, DTM_DMI_ADDRESS_OFFSET, info->abits);
- riscv_log_dmi_scan(target, idle_count, &field, /*discard_in*/ !data_in);
- return buf_get_u32(in, DTM_DMI_OP_OFFSET, DTM_DMI_OP_LENGTH);
-}
-
-/**
- * @param target
- * @param data_in The data we received from the target.
- * @param dmi_busy_encountered
- * If non-NULL, will be updated to reflect whether DMI busy was
- * encountered while executing this operation or not.
- * @param op The operation to perform (read/write/nop).
- * @param address The address argument to that operation.
- * @param data_out The data to send to the target.
- * @param timeout_sec
- * @param exec When true, this scan will execute something, so extra RTI
- * cycles may be added.
- * @param ensure_success
- * Scan a nop after the requested operation, ensuring the
- * DMI operation succeeded.
- */
-static int dmi_op_timeout(struct target *target, uint32_t *data_in,
- bool *dmi_busy_encountered, int op, uint32_t address,
- uint32_t data_out, int timeout_sec, bool exec, bool ensure_success)
-{
- select_dmi(target);
-
- dmi_status_t status;
-
- if (dmi_busy_encountered)
- *dmi_busy_encountered = false;
-
- const char *op_name;
- switch (op) {
- case DMI_OP_NOP:
- op_name = "nop";
- break;
- case DMI_OP_READ:
- op_name = "read";
- break;
- case DMI_OP_WRITE:
- op_name = "write";
- break;
- default:
- LOG_ERROR("Invalid DMI operation: %d", op);
- return ERROR_FAIL;
- }
-
- keep_alive();
-
- time_t start = time(NULL);
- /* This first loop performs the request. Note that if for some reason this
- * stays busy, it is actually due to the previous access. */
- while (1) {
- status = dmi_scan(target, NULL, NULL, op, address, data_out,
- exec);
- if (status == DMI_STATUS_BUSY) {
- int result = increase_dmi_busy_delay(target);
- if (result != ERROR_OK)
- return result;
- if (dmi_busy_encountered)
- *dmi_busy_encountered = true;
- } else if (status == DMI_STATUS_SUCCESS) {
- break;
- } else {
- dtmcontrol_scan(target, DTM_DTMCS_DMIRESET, NULL /* discard result */);
- break;
- }
- if (time(NULL) - start > timeout_sec)
- return ERROR_TIMEOUT_REACHED;
- }
-
- if (status != DMI_STATUS_SUCCESS) {
- LOG_TARGET_ERROR(target, "Failed DMI %s at 0x%x; status=%d", op_name, address, status);
- return ERROR_FAIL;
- }
-
- if (ensure_success) {
- /* This second loop ensures the request succeeded, and gets back data.
- * Note that NOP can result in a 'busy' result as well, but that would be
- * noticed on the next DMI access we do. */
- while (1) {
- status = dmi_scan(target, NULL, data_in, DMI_OP_NOP, address, 0,
- false);
- if (status == DMI_STATUS_BUSY) {
- int result = increase_dmi_busy_delay(target);
- if (result != ERROR_OK)
- return result;
- if (dmi_busy_encountered)
- *dmi_busy_encountered = true;
- } else if (status == DMI_STATUS_SUCCESS) {
- break;
- } else {
- if (data_in) {
- LOG_TARGET_ERROR(target,
- "Failed DMI %s (NOP) at 0x%x; value=0x%x, status=%d",
- op_name, address, *data_in, status);
- } else {
- LOG_TARGET_ERROR(target,
- "Failed DMI %s (NOP) at 0x%x; status=%d", op_name, address,
- status);
- }
- dtmcontrol_scan(target, DTM_DTMCS_DMIRESET, NULL /* discard result */);
- return ERROR_FAIL;
- }
- if (time(NULL) - start > timeout_sec)
- return ERROR_TIMEOUT_REACHED;
- }
- }
-
- return ERROR_OK;
-}
-
-static int dmi_op(struct target *target, uint32_t *data_in,
- bool *dmi_busy_encountered, int op, uint32_t address,
- uint32_t data_out, bool exec, bool ensure_success)
-{
- int result = dmi_op_timeout(target, data_in, dmi_busy_encountered, op,
- address, data_out, riscv_command_timeout_sec, exec, ensure_success);
- if (result == ERROR_TIMEOUT_REACHED) {
- LOG_TARGET_ERROR(target, "DMI operation didn't complete in %d seconds. The target is "
- "either really slow or broken. You could increase the "
- "timeout with riscv set_command_timeout_sec.",
- riscv_command_timeout_sec);
- return ERROR_FAIL;
- }
- return result;
-}
-
-static int dmi_read(struct target *target, uint32_t *value, uint32_t address)
-{
- return dmi_op(target, value, NULL, DMI_OP_READ, address, 0, false, true);
-}
-
-static int dmi_read_exec(struct target *target, uint32_t *value, uint32_t address)
-{
- return dmi_op(target, value, NULL, DMI_OP_READ, address, 0, true, true);
-}
-
-static int dmi_write(struct target *target, uint32_t address, uint32_t value)
-{
- return dmi_op(target, NULL, NULL, DMI_OP_WRITE, address, value, false, true);
-}
static uint32_t riscv013_get_dmi_address(const struct target *target, uint32_t address)
{
@@ -731,34 +432,22 @@ static uint32_t riscv013_get_dmi_address(const struct target *target, uint32_t a
return address + base;
}
-static int dm_op_timeout(struct target *target, uint32_t *data_in,
- bool *dmi_busy_encountered, int op, uint32_t address,
- uint32_t data_out, int timeout_sec, bool exec, bool ensure_success)
-{
- dm013_info_t *dm = get_dm(target);
- if (!dm)
- return ERROR_FAIL;
- return dmi_op_timeout(target, data_in, dmi_busy_encountered, op, address + dm->base,
- data_out, timeout_sec, exec, ensure_success);
-}
+static int batch_run_timeout(struct target *target, struct riscv_batch *batch);
-static int dm_op(struct target *target, uint32_t *data_in,
- bool *dmi_busy_encountered, int op, uint32_t address,
- uint32_t data_out, bool exec, bool ensure_success)
+static int dmi_read(struct target *target, uint32_t *value, uint32_t address)
{
- dm013_info_t *dm = get_dm(target);
- if (!dm)
- return ERROR_FAIL;
- return dmi_op(target, data_in, dmi_busy_encountered, op, address + dm->base,
- data_out, exec, ensure_success);
+ struct riscv_batch *batch = riscv_batch_alloc(target, 1);
+ riscv_batch_add_dmi_read(batch, address, RISCV_DELAY_BASE);
+ int res = batch_run_timeout(target, batch);
+ if (res == ERROR_OK && value)
+ *value = riscv_batch_get_dmi_read_data(batch, 0);
+ riscv_batch_free(batch);
+ return res;
}
static int dm_read(struct target *target, uint32_t *value, uint32_t address)
{
- dm013_info_t *dm = get_dm(target);
- if (!dm)
- return ERROR_FAIL;
- return dmi_read(target, value, address + dm->base);
+ return dmi_read(target, value, riscv013_get_dmi_address(target, address));
}
static int dm_read_exec(struct target *target, uint32_t *value, uint32_t address)
@@ -766,16 +455,29 @@ static int dm_read_exec(struct target *target, uint32_t *value, uint32_t address
dm013_info_t *dm = get_dm(target);
if (!dm)
return ERROR_FAIL;
+ struct riscv_batch *batch = riscv_batch_alloc(target, 1);
+ riscv_batch_add_dm_read(batch, address, RISCV_DELAY_ABSTRACT_COMMAND);
dm->abstract_cmd_maybe_busy = true;
- return dmi_read_exec(target, value, address + dm->base);
+ int res = batch_run_timeout(target, batch);
+ if (res == ERROR_OK && value)
+ *value = riscv_batch_get_dmi_read_data(batch, 0);
+ riscv_batch_free(batch);
+ return res;
+}
+
+static int dmi_write(struct target *target, uint32_t address, uint32_t value)
+{
+ struct riscv_batch *batch = riscv_batch_alloc(target, 1);
+ riscv_batch_add_dmi_write(batch, address, value, /*read_back*/ true,
+ RISCV_DELAY_BASE);
+ int res = batch_run_timeout(target, batch);
+ riscv_batch_free(batch);
+ return res;
}
static int dm_write(struct target *target, uint32_t address, uint32_t value)
{
- dm013_info_t *dm = get_dm(target);
- if (!dm)
- return ERROR_FAIL;
- return dmi_write(target, address + dm->base, value);
+ return dmi_write(target, riscv013_get_dmi_address(target, address), value);
}
static bool check_dbgbase_exists(struct target *target)
@@ -805,11 +507,10 @@ static bool check_dbgbase_exists(struct target *target)
return false;
}
-static int dmstatus_read_timeout(struct target *target, uint32_t *dmstatus,
- bool authenticated, unsigned timeout_sec)
+static int dmstatus_read(struct target *target, uint32_t *dmstatus,
+ bool authenticated)
{
- int result = dm_op_timeout(target, dmstatus, NULL, DMI_OP_READ,
- DM_DMSTATUS, 0, timeout_sec, false, true);
+ int result = dm_read(target, dmstatus, DM_DMSTATUS);
if (result != ERROR_OK)
return result;
int dmstatus_version = get_field(*dmstatus, DM_DMSTATUS_VERSION);
@@ -827,19 +528,6 @@ static int dmstatus_read_timeout(struct target *target, uint32_t *dmstatus,
return ERROR_OK;
}
-static int dmstatus_read(struct target *target, uint32_t *dmstatus,
- bool authenticated)
-{
- int result = dmstatus_read_timeout(target, dmstatus, authenticated,
- riscv_command_timeout_sec);
- if (result == ERROR_TIMEOUT_REACHED)
- LOG_TARGET_ERROR(target, "DMSTATUS read didn't complete in %d seconds. The target is "
- "either really slow or broken. You could increase the "
- "timeout with `riscv set_command_timeout_sec`.",
- riscv_command_timeout_sec);
- return result;
-}
-
static int increase_ac_busy_delay(struct target *target)
{
riscv013_info_t *info = get_info(target);
@@ -847,7 +535,7 @@ static int increase_ac_busy_delay(struct target *target)
RISCV_DELAY_ABSTRACT_COMMAND);
}
-static uint32_t __attribute__((unused)) abstract_register_size(unsigned width)
+static uint32_t __attribute__((unused)) abstract_register_size(unsigned int width)
{
switch (width) {
case 32:
@@ -890,12 +578,12 @@ static int wait_for_idle(struct target *target, uint32_t *abstractcs)
dm->abstract_cmd_maybe_busy = false;
return ERROR_OK;
}
- } while ((time(NULL) - start) < riscv_command_timeout_sec);
+ } while ((time(NULL) - start) < riscv_get_command_timeout_sec());
LOG_TARGET_ERROR(target,
"Timed out after %ds waiting for busy to go low (abstractcs=0x%" PRIx32 "). "
"Increase the timeout with riscv set_command_timeout_sec.",
- riscv_command_timeout_sec,
+ riscv_get_command_timeout_sec(),
*abstractcs);
if (!dm->abstract_cmd_maybe_busy)
@@ -955,9 +643,7 @@ clear_cmderr:
return res;
}
-static int batch_run_timeout(struct target *target, struct riscv_batch *batch);
-
-static int execute_abstract_command(struct target *target, uint32_t command,
+int riscv013_execute_abstract_command(struct target *target, uint32_t command,
uint32_t *cmderr)
{
assert(cmderr);
@@ -1073,10 +759,10 @@ static void abstract_data_write_fill_batch(struct riscv_batch *batch,
}
/* TODO: reuse "abstract_data_write_fill_batch()" here*/
-static int write_abstract_arg(struct target *target, unsigned index,
- riscv_reg_t value, unsigned size_bits)
+static int write_abstract_arg(struct target *target, unsigned int index,
+ riscv_reg_t value, unsigned int size_bits)
{
- unsigned offset = index * size_bits / 32;
+ unsigned int offset = index * size_bits / 32;
switch (size_bits) {
default:
LOG_TARGET_ERROR(target, "Unsupported size: %d bits", size_bits);
@@ -1093,8 +779,8 @@ static int write_abstract_arg(struct target *target, unsigned index,
/**
* @par size in bits
*/
-static uint32_t access_register_command(struct target *target, uint32_t number,
- unsigned size, uint32_t flags)
+uint32_t riscv013_access_register_command(struct target *target, uint32_t number,
+ unsigned int size, uint32_t flags)
{
uint32_t command = set_field(0, DM_COMMAND_CMDTYPE, 0);
switch (size) {
@@ -1150,11 +836,11 @@ static int register_read_abstract_with_size(struct target *target,
if (number >= GDB_REGNO_V0 && number <= GDB_REGNO_V31)
return ERROR_FAIL;
- uint32_t command = access_register_command(target, number, size,
+ uint32_t command = riscv013_access_register_command(target, number, size,
AC_ACCESS_REGISTER_TRANSFER);
uint32_t cmderr;
- int result = execute_abstract_command(target, command, &cmderr);
+ int result = riscv013_execute_abstract_command(target, command, &cmderr);
if (result != ERROR_OK) {
if (cmderr == CMDERR_NOT_SUPPORTED) {
if (number >= GDB_REGNO_FPR0 && number <= GDB_REGNO_FPR31) {
@@ -1199,7 +885,7 @@ static int register_write_abstract(struct target *target, enum gdb_regno number,
return ERROR_FAIL;
const unsigned int size_bits = register_size(target, number);
- const uint32_t command = access_register_command(target, number, size_bits,
+ const uint32_t command = riscv013_access_register_command(target, number, size_bits,
AC_ACCESS_REGISTER_TRANSFER |
AC_ACCESS_REGISTER_WRITE);
LOG_DEBUG_REG(target, AC_ACCESS_REGISTER, command);
@@ -1242,7 +928,7 @@ cleanup:
* Sets the AAMSIZE field of a memory access abstract command based on
* the width (bits).
*/
-static uint32_t abstract_memory_size(unsigned width)
+static uint32_t abstract_memory_size(unsigned int width)
{
switch (width) {
case 8:
@@ -1424,7 +1110,7 @@ typedef struct {
static int scratch_reserve(struct target *target,
scratch_mem_t *scratch,
struct riscv_program *program,
- unsigned size_bytes)
+ unsigned int size_bytes)
{
riscv_addr_t alignment = 1;
while (alignment < size_bytes)
@@ -1456,7 +1142,7 @@ static int scratch_reserve(struct target *target,
return ERROR_FAIL;
/* Allow for ebreak at the end of the program. */
- unsigned program_size = (program->instruction_count + 1) * 4;
+ unsigned int program_size = (program->instruction_count + 1) * 4;
scratch->hart_address = (info->progbuf_address + program_size + alignment - 1) &
~(alignment - 1);
if ((info->progbuf_writable == YNM_YES) &&
@@ -1572,12 +1258,10 @@ static unsigned int register_size(struct target *target, enum gdb_regno number)
return riscv_xlen(target);
}
-static bool has_sufficient_progbuf(struct target *target, unsigned size)
+static bool has_sufficient_progbuf(struct target *target, unsigned int size)
{
RISCV013_INFO(info);
- RISCV_INFO(r);
-
- return info->progbufsize + r->impebreak >= size;
+ return info->progbufsize + info->impebreak >= size;
}
/**
@@ -1898,10 +1582,10 @@ static int wait_for_authbusy(struct target *target, uint32_t *dmstatus)
*dmstatus = value;
if (!get_field(value, DM_DMSTATUS_AUTHBUSY))
break;
- if (time(NULL) - start > riscv_command_timeout_sec) {
+ if (time(NULL) - start > riscv_get_command_timeout_sec()) {
LOG_TARGET_ERROR(target, "Timed out after %ds waiting for authbusy to go low (dmstatus=0x%x). "
"Increase the timeout with riscv set_command_timeout_sec.",
- riscv_command_timeout_sec,
+ riscv_get_command_timeout_sec(),
value);
return ERROR_FAIL;
}
@@ -2091,11 +1775,10 @@ static int reset_dm(struct target *target)
if (result != ERROR_OK)
return result;
- if (time(NULL) - start > riscv_reset_timeout_sec) {
- /* TODO: Introduce a separate timeout for this. */
+ if (time(NULL) - start > riscv_get_command_timeout_sec()) {
LOG_TARGET_ERROR(target, "DM didn't acknowledge reset in %d s. "
- "Increase the timeout with 'riscv set_reset_timeout_sec'.",
- riscv_reset_timeout_sec);
+ "Increase the timeout with 'riscv set_command_timeout_sec'.",
+ riscv_get_command_timeout_sec());
return ERROR_TIMEOUT_REACHED;
}
} while (get_field32(dmcontrol, DM_DMCONTROL_DMACTIVE));
@@ -2114,11 +1797,10 @@ static int reset_dm(struct target *target)
if (result != ERROR_OK)
return result;
- if (time(NULL) - start > riscv_reset_timeout_sec) {
- /* TODO: Introduce a separate timeout for this. */
+ if (time(NULL) - start > riscv_get_command_timeout_sec()) {
LOG_TARGET_ERROR(target, "Debug Module did not become active in %d s. "
- "Increase the timeout with 'riscv set_reset_timeout_sec'.",
- riscv_reset_timeout_sec);
+ "Increase the timeout with 'riscv set_command_timeout_sec'.",
+ riscv_get_command_timeout_sec());
return ERROR_TIMEOUT_REACHED;
}
} while (!get_field32(dmcontrol, DM_DMCONTROL_DMACTIVE));
@@ -2304,14 +1986,13 @@ static int examine(struct target *target)
LOG_TARGET_INFO(target, "datacount=%d progbufsize=%d",
info->datacount, info->progbufsize);
- RISCV_INFO(r);
- r->impebreak = get_field(dmstatus, DM_DMSTATUS_IMPEBREAK);
+ info->impebreak = get_field(dmstatus, DM_DMSTATUS_IMPEBREAK);
if (!has_sufficient_progbuf(target, 2)) {
LOG_TARGET_WARNING(target, "We won't be able to execute fence instructions on this "
"target. Memory may not always appear consistent. "
"(progbufsize=%d, impebreak=%d)", info->progbufsize,
- r->impebreak);
+ info->impebreak);
}
if (info->progbufsize < 4 && riscv_enable_virtual) {
@@ -2327,6 +2008,8 @@ static int examine(struct target *target)
enum riscv_hart_state state_at_examine_start;
if (riscv_get_hart_state(target, &state_at_examine_start) != ERROR_OK)
return ERROR_FAIL;
+
+ RISCV_INFO(r);
const bool hart_halted_at_examine_start = state_at_examine_start == RISCV_STATE_HALTED;
if (!hart_halted_at_examine_start) {
r->prepped = true;
@@ -2340,74 +2023,9 @@ static int examine(struct target *target)
target->state = TARGET_HALTED;
target->debug_reason = hart_halted_at_examine_start ? DBG_REASON_UNDEFINED : DBG_REASON_DBGRQ;
- /* Without knowing anything else we can at least mess with the
- * program buffer. */
- r->progbuf_size = info->progbufsize;
-
- result = register_read_abstract_with_size(target, NULL, GDB_REGNO_S0, 64);
- if (result == ERROR_OK)
- r->xlen = 64;
- else
- r->xlen = 32;
-
- /* Save s0 and s1. The register cache hasn't be initialized yet so we
- * need to take care of this manually. */
- uint64_t s0, s1;
- if (register_read_abstract(target, &s0, GDB_REGNO_S0) != ERROR_OK) {
- LOG_TARGET_ERROR(target, "Fatal: Failed to read s0.");
- return ERROR_FAIL;
- }
- if (register_read_abstract(target, &s1, GDB_REGNO_S1) != ERROR_OK) {
- LOG_TARGET_ERROR(target, "Fatal: Failed to read s1.");
- return ERROR_FAIL;
- }
-
- if (register_read_direct(target, &r->misa, GDB_REGNO_MISA)) {
- LOG_TARGET_ERROR(target, "Fatal: Failed to read MISA.");
- return ERROR_FAIL;
- }
-
- uint64_t value;
- if (register_read_direct(target, &value, GDB_REGNO_VLENB) != ERROR_OK) {
- if (riscv_supports_extension(target, 'V'))
- LOG_TARGET_WARNING(target, "Couldn't read vlenb; vector register access won't work.");
- r->vlenb = 0;
- } else {
- r->vlenb = value;
- LOG_TARGET_INFO(target, "Vector support with vlenb=%d", r->vlenb);
- }
-
- if (register_read_direct(target, &value, GDB_REGNO_MTOPI) == ERROR_OK) {
- r->mtopi_readable = true;
-
- if (register_read_direct(target, &value, GDB_REGNO_MTOPEI) == ERROR_OK) {
- LOG_TARGET_INFO(target, "S?aia detected with IMSIC");
- r->mtopei_readable = true;
- } else {
- r->mtopei_readable = false;
- LOG_TARGET_INFO(target, "S?aia detected without IMSIC");
- }
- } else {
- r->mtopi_readable = false;
- }
-
- /* Display this as early as possible to help people who are using
- * really slow simulators. */
- LOG_TARGET_DEBUG(target, " XLEN=%d, misa=0x%" PRIx64, r->xlen, r->misa);
-
- /* Restore s0 and s1. */
- if (register_write_direct(target, GDB_REGNO_S0, s0) != ERROR_OK) {
- LOG_TARGET_ERROR(target, "Fatal: Failed to write back s0.");
- return ERROR_FAIL;
- }
- if (register_write_direct(target, GDB_REGNO_S1, s1) != ERROR_OK) {
- LOG_TARGET_ERROR(target, "Fatal: Failed to write back s1.");
- return ERROR_FAIL;
- }
-
- /* Now init registers based on what we discovered. */
- if (riscv013_reg_init_all(target) != ERROR_OK)
- return ERROR_FAIL;
+ result = riscv013_reg_examine_all(target);
+ if (result != ERROR_OK)
+ return result;
if (set_dcsr_ebreak(target, false) != ERROR_OK)
return ERROR_FAIL;
@@ -2488,13 +2106,13 @@ static int riscv013_authdata_write(struct target *target, uint32_t value, unsign
}
/* Try to find out the widest memory access size depending on the selected memory access methods. */
-static unsigned riscv013_data_bits(struct target *target)
+static unsigned int riscv013_data_bits(struct target *target)
{
RISCV013_INFO(info);
RISCV_INFO(r);
- for (unsigned int i = 0; i < RISCV_NUM_MEM_ACCESS_METHODS; i++) {
- int method = r->mem_access_methods[i];
+ for (unsigned int i = 0; i < r->num_enabled_mem_access_methods; i++) {
+ riscv_mem_access_method_t method = r->mem_access_methods[i];
if (method == RISCV_MEM_ACCESS_PROGBUF) {
if (has_sufficient_progbuf(target, 3))
@@ -2515,9 +2133,9 @@ static unsigned riscv013_data_bits(struct target *target)
* take those into account as well. For now we assume abstract commands
* support XLEN-wide accesses. */
return riscv_xlen(target);
- } else if (method == RISCV_MEM_ACCESS_UNSPECIFIED)
- /* No further mem access method to try. */
- break;
+ } else {
+ assert(false);
+ }
}
LOG_TARGET_ERROR(target, "Unable to determine supported data bits on this target. Assuming 32 bits.");
return 32;
@@ -2743,21 +2361,42 @@ static uint32_t sb_sbaccess(unsigned int size_bytes)
return 0;
}
-static int sb_write_address(struct target *target, target_addr_t address,
- bool ensure_success)
+static unsigned int get_sbaadress_reg_count(const struct target *target)
{
RISCV013_INFO(info);
- unsigned int sbasize = get_field(info->sbcs, DM_SBCS_SBASIZE);
+ const unsigned int sbasize = get_field(info->sbcs, DM_SBCS_SBASIZE);
+ return DIV_ROUND_UP(sbasize, 32);
+}
+
+static void batch_fill_sb_write_address(const struct target *target,
+ struct riscv_batch *batch, target_addr_t address,
+ enum riscv_scan_delay_class sbaddr0_delay)
+{
/* There currently is no support for >64-bit addresses in OpenOCD. */
- if (sbasize > 96)
- dm_op(target, NULL, NULL, DMI_OP_WRITE, DM_SBADDRESS3, 0, false, false);
- if (sbasize > 64)
- dm_op(target, NULL, NULL, DMI_OP_WRITE, DM_SBADDRESS2, 0, false, false);
- if (sbasize > 32)
- dm_op(target, NULL, NULL, DMI_OP_WRITE, DM_SBADDRESS1,
- (uint32_t)(address >> 32), false, false);
- return dm_op(target, NULL, NULL, DMI_OP_WRITE, DM_SBADDRESS0,
- (uint32_t)address, false, ensure_success);
+ assert(sizeof(target_addr_t) == sizeof(uint64_t));
+ const uint32_t addresses[] = {DM_SBADDRESS0, DM_SBADDRESS1, DM_SBADDRESS2, DM_SBADDRESS3};
+ const uint32_t values[] = {(uint32_t)address, (uint32_t)(address >> 32), 0, 0};
+ const unsigned int reg_count = get_sbaadress_reg_count(target);
+ assert(reg_count > 0);
+ assert(reg_count <= ARRAY_SIZE(addresses));
+ assert(ARRAY_SIZE(addresses) == ARRAY_SIZE(values));
+
+ for (unsigned int i = reg_count - 1; i > 0; --i)
+ riscv_batch_add_dm_write(batch, addresses[i], values[i], /* read back */ true,
+ RISCV_DELAY_BASE);
+ riscv_batch_add_dm_write(batch, addresses[0], values[0], /* read back */ true,
+ sbaddr0_delay);
+}
+
+static int sb_write_address(struct target *target, target_addr_t address,
+ enum riscv_scan_delay_class sbaddr0_delay)
+{
+ struct riscv_batch *batch = riscv_batch_alloc(target,
+ get_sbaadress_reg_count(target));
+ batch_fill_sb_write_address(target, batch, address, sbaddr0_delay);
+ const int res = batch_run_timeout(target, batch);
+ riscv_batch_free(batch);
+ return res;
}
static int batch_run(struct target *target, struct riscv_batch *batch)
@@ -2769,12 +2408,16 @@ static int batch_run(struct target *target, struct riscv_batch *batch)
const int result = riscv_batch_run_from(batch, 0, &info->learned_delays,
/*resets_delays*/ r->reset_delays_wait >= 0,
r->reset_delays_wait);
+ if (result != ERROR_OK)
+ return result;
/* TODO: To use `riscv_batch_finished_scans()` here, it is needed for
* all scans to not discard input, meaning
* "riscv_batch_add_dm_write(..., false)" should not be used. */
const size_t finished_scans = batch->used_scans;
decrement_reset_delays_counter(target, finished_scans);
- return result;
+ if (riscv_batch_was_batch_busy(batch))
+ return increase_dmi_busy_delay(target);
+ return ERROR_OK;
}
/* It is expected that during creation of the batch
@@ -2797,12 +2440,12 @@ static int batch_run_timeout(struct target *target, struct riscv_batch *batch)
&info->learned_delays,
/*resets_delays*/ r->reset_delays_wait >= 0,
r->reset_delays_wait);
+ if (result != ERROR_OK)
+ return result;
const size_t new_finished_scans = riscv_batch_finished_scans(batch);
assert(new_finished_scans >= finished_scans);
decrement_reset_delays_counter(target, new_finished_scans - finished_scans);
finished_scans = new_finished_scans;
- if (result != ERROR_OK)
- return result;
if (!riscv_batch_was_batch_busy(batch)) {
assert(finished_scans == batch->used_scans);
return ERROR_OK;
@@ -2810,7 +2453,7 @@ static int batch_run_timeout(struct target *target, struct riscv_batch *batch)
result = increase_dmi_busy_delay(target);
if (result != ERROR_OK)
return result;
- } while (time(NULL) - start < riscv_command_timeout_sec);
+ } while (time(NULL) - start < riscv_get_command_timeout_sec());
assert(result == ERROR_OK);
assert(riscv_batch_was_batch_busy(batch));
@@ -2825,7 +2468,7 @@ static int batch_run_timeout(struct target *target, struct riscv_batch *batch)
LOG_TARGET_ERROR(target, "DMI operation didn't complete in %d seconds. "
"The target is either really slow or broken. You could increase "
"the timeout with riscv set_command_timeout_sec.",
- riscv_command_timeout_sec);
+ riscv_get_command_timeout_sec());
return ERROR_TIMEOUT_REACHED;
}
@@ -3108,8 +2751,8 @@ static int init_target(struct command_context *cmd_ctx,
generic_info->write_progbuf = &riscv013_write_progbuf;
generic_info->execute_progbuf = &riscv013_execute_progbuf;
generic_info->invalidate_cached_progbuf = &riscv013_invalidate_cached_progbuf;
- generic_info->fill_dm_write = &riscv013_fill_dm_write;
- generic_info->fill_dm_read = &riscv013_fill_dm_read;
+ generic_info->fill_dmi_write = &riscv013_fill_dmi_write;
+ generic_info->fill_dmi_read = &riscv013_fill_dmi_read;
generic_info->fill_dm_nop = &riscv013_fill_dm_nop;
generic_info->get_dmi_scan_length = &riscv013_get_dmi_scan_length;
generic_info->authdata_read = &riscv013_authdata_read;
@@ -3120,6 +2763,8 @@ static int init_target(struct command_context *cmd_ctx,
generic_info->read_memory = read_memory;
generic_info->data_bits = &riscv013_data_bits;
generic_info->print_info = &riscv013_print_info;
+ generic_info->get_impebreak = &riscv013_get_impebreak;
+ generic_info->get_progbufsize = &riscv013_get_progbufsize;
generic_info->handle_became_unavailable = &handle_became_unavailable;
generic_info->tick = &tick;
@@ -3225,21 +2870,15 @@ static int deassert_reset(struct target *target)
time_t start = time(NULL);
LOG_TARGET_DEBUG(target, "Waiting for hart to come out of reset.");
do {
- result = dmstatus_read_timeout(target, &dmstatus, true,
- riscv_reset_timeout_sec);
- if (result == ERROR_TIMEOUT_REACHED)
- LOG_TARGET_ERROR(target, "Hart didn't complete a DMI read coming "
- "out of reset in %ds; Increase the timeout with riscv "
- "set_reset_timeout_sec.",
- riscv_reset_timeout_sec);
+ result = dmstatus_read(target, &dmstatus, true);
if (result != ERROR_OK)
return result;
- if (time(NULL) - start > riscv_reset_timeout_sec) {
+ if (time(NULL) - start > riscv_get_command_timeout_sec()) {
LOG_TARGET_ERROR(target, "Hart didn't leave reset in %ds; "
"dmstatus=0x%x (allunavail=%s, allhavereset=%s); "
- "Increase the timeout with riscv set_reset_timeout_sec.",
- riscv_reset_timeout_sec, dmstatus,
+ "Increase the timeout with riscv set_command_timeout_sec.",
+ riscv_get_command_timeout_sec(), dmstatus,
get_field(dmstatus, DM_DMSTATUS_ALLUNAVAIL) ? "true" : "false",
get_field(dmstatus, DM_DMSTATUS_ALLHAVERESET) ? "true" : "false");
return ERROR_TIMEOUT_REACHED;
@@ -3404,7 +3043,7 @@ static int read_memory_bus_word(struct target *target, target_addr_t address,
static target_addr_t sb_read_address(struct target *target)
{
RISCV013_INFO(info);
- unsigned sbasize = get_field(info->sbcs, DM_SBCS_SBASIZE);
+ unsigned int sbasize = get_field(info->sbcs, DM_SBCS_SBASIZE);
target_addr_t address = 0;
uint32_t v;
if (sbasize > 32) {
@@ -3425,10 +3064,10 @@ static int read_sbcs_nonbusy(struct target *target, uint32_t *sbcs)
return ERROR_FAIL;
if (!get_field(*sbcs, DM_SBCS_SBBUSY))
return ERROR_OK;
- if (time(NULL) - start > riscv_command_timeout_sec) {
+ if (time(NULL) - start > riscv_get_command_timeout_sec()) {
LOG_TARGET_ERROR(target, "Timed out after %ds waiting for sbbusy to go low (sbcs=0x%x). "
"Increase the timeout with riscv set_command_timeout_sec.",
- riscv_command_timeout_sec, *sbcs);
+ riscv_get_command_timeout_sec(), *sbcs);
return ERROR_FAIL;
}
}
@@ -3562,6 +3201,9 @@ static int read_memory_bus_v1(struct target *target, target_addr_t address,
return ERROR_NOT_IMPLEMENTED;
}
+ assert(size <= 16);
+ assert(IS_PWR_OF_2(size));
+
dm013_info_t *dm = get_dm(target);
if (!dm)
return ERROR_FAIL;
@@ -3570,6 +3212,9 @@ static int read_memory_bus_v1(struct target *target, target_addr_t address,
target_addr_t next_address = address;
target_addr_t end_address = address + (increment ? count : 1) * size;
+ /* TODO: Reading all the elements in a single batch will boost the
+ * performance.
+ */
while (next_address < end_address) {
uint32_t sbcs_write = set_field(0, DM_SBCS_SBREADONADDR, 1);
sbcs_write |= sb_sbaccess(size);
@@ -3581,96 +3226,50 @@ static int read_memory_bus_v1(struct target *target, target_addr_t address,
return ERROR_FAIL;
/* This address write will trigger the first read. */
- if (sb_write_address(target, next_address, true) != ERROR_OK)
+ if (sb_write_address(target, next_address, RISCV_DELAY_SYSBUS_READ) != ERROR_OK)
return ERROR_FAIL;
- unsigned int bus_master_read_delay = riscv_scan_get_delay(&info->learned_delays,
- RISCV_DELAY_SYSBUS_READ);
- if (bus_master_read_delay) {
- LOG_TARGET_DEBUG(target, "Waiting %d cycles for bus master read delay",
- bus_master_read_delay);
- jtag_add_runtest(bus_master_read_delay, TAP_IDLE);
- if (jtag_execute_queue() != ERROR_OK) {
- LOG_TARGET_ERROR(target, "Failed to scan idle sequence");
- return ERROR_FAIL;
- }
- }
-
/* First read has been started. Optimistically assume that it has
* completed. */
static int sbdata[4] = {DM_SBDATA0, DM_SBDATA1, DM_SBDATA2, DM_SBDATA3};
+ /* TODO: The only purpose of "sbvalue" is to be passed to
+ * "log_memory_access()". If "log_memory_access()" were to
+ * accept "uint8_t *" instead of "uint32_t *", "sbvalue" would
+ * be unnecessary.
+ */
uint32_t sbvalue[4] = {0};
- assert(size <= 16);
- target_addr_t next_read = address - 1;
- uint32_t buffer_offset = 0;
- int next_read_j = 0;
for (uint32_t i = (next_address - address) / size; i < count - 1; i++) {
- for (int j = (size - 1) / 4; j >= 0; j--) {
- unsigned attempt = 0;
- while (1) {
- if (attempt++ > 100) {
- LOG_TARGET_ERROR(target, "DMI keeps being busy in while reading memory"
- " just past " TARGET_ADDR_FMT, next_read);
- return ERROR_FAIL;
- }
- keep_alive();
- dmi_status_t status = dmi_scan(target, NULL, &sbvalue[next_read_j],
- DMI_OP_READ, sbdata[j] + dm->base, 0, false);
- /* By reading from sbdata0, we have just initiated another system bus read.
- * If necessary add a delay so the read can finish. */
- bus_master_read_delay = riscv_scan_get_delay(&info->learned_delays,
- RISCV_DELAY_SYSBUS_READ);
- if (j == 0 && bus_master_read_delay) {
- LOG_TARGET_DEBUG(target, "Waiting %d cycles for bus master read delay",
- bus_master_read_delay);
- jtag_add_runtest(bus_master_read_delay, TAP_IDLE);
- if (jtag_execute_queue() != ERROR_OK) {
- LOG_TARGET_ERROR(target, "Failed to scan idle sequence");
- return ERROR_FAIL;
- }
- }
+ const uint32_t size_in_words = DIV_ROUND_UP(size, 4);
+ struct riscv_batch *batch = riscv_batch_alloc(target, size_in_words);
+ /* Read of sbdata0 must be performed as last because it
+ * starts the new bus data transfer
+ * (in case "sbcs.sbreadondata" was set above).
+ * We don't want to start the next bus read before we
+ * fetch all the data from the last bus read. */
+ for (uint32_t j = size_in_words - 1; j > 0; --j)
+ riscv_batch_add_dm_read(batch, sbdata[j], RISCV_DELAY_BASE);
+ riscv_batch_add_dm_read(batch, sbdata[0], RISCV_DELAY_SYSBUS_READ);
+
+ int res = batch_run_timeout(target, batch);
+ if (res != ERROR_OK) {
+ riscv_batch_free(batch);
+ return res;
+ }
- if (status == DMI_STATUS_BUSY)
- increase_dmi_busy_delay(target);
- else if (status == DMI_STATUS_SUCCESS)
- break;
- else
- return ERROR_FAIL;
- }
- if (next_read != address - 1) {
- buf_set_u32(buffer + buffer_offset, 0, 8 * MIN(size, 4), sbvalue[next_read_j]);
- if (next_read_j == 0) {
- log_memory_access(next_read, sbvalue, size, true);
- memset(sbvalue, 0, size);
- }
- }
- next_read_j = j;
- next_read = address + i * increment + next_read_j * 4;
- buffer_offset = i * size + next_read_j * 4;
+ const size_t last_key = batch->read_keys_used - 1;
+ for (size_t k = 0; k <= last_key; ++k) {
+ sbvalue[k] = riscv_batch_get_dmi_read_data(batch, last_key - k);
+ buf_set_u32(buffer + i * size + k * 4, 0, MIN(32, 8 * size), sbvalue[k]);
}
+
+ riscv_batch_free(batch);
+ const target_addr_t read_addr = address + i * increment;
+ log_memory_access(read_addr, sbvalue, size, true);
}
uint32_t sbcs_read = 0;
if (count > 1) {
- unsigned attempt = 0;
- while (1) {
- if (attempt++ > 100) {
- LOG_TARGET_ERROR(target, "DMI keeps being busy in while reading memory"
- " just past " TARGET_ADDR_FMT, next_read);
- return ERROR_FAIL;
- }
- dmi_status_t status = dmi_scan(target, NULL, &sbvalue[0], DMI_OP_NOP, 0, 0, false);
- if (status == DMI_STATUS_BUSY)
- increase_dmi_busy_delay(target);
- else if (status == DMI_STATUS_SUCCESS)
- break;
- else
- return ERROR_FAIL;
- }
- buf_set_u32(buffer + buffer_offset, 0, 8 * MIN(size, 4), sbvalue[0]);
- log_memory_access(next_read, sbvalue, size, true);
-
/* "Writes to sbcs while sbbusy is high result in undefined behavior.
* A debugger must not write to sbcs until it reads sbbusy as 0." */
if (read_sbcs_nonbusy(target, &sbcs_read) != ERROR_OK)
@@ -3718,7 +3317,7 @@ static int read_memory_bus_v1(struct target *target, target_addr_t address,
continue;
}
- unsigned error = get_field(sbcs_read, DM_SBCS_SBERROR);
+ unsigned int error = get_field(sbcs_read, DM_SBCS_SBERROR);
if (error == DM_SBCS_SBERROR_NONE) {
next_address = end_address;
} else {
@@ -3733,7 +3332,7 @@ static int read_memory_bus_v1(struct target *target, target_addr_t address,
return ERROR_OK;
}
-static void log_mem_access_result(struct target *target, bool success, int method, bool is_read)
+static void log_mem_access_result(struct target *target, bool success, riscv_mem_access_method_t method, bool is_read)
{
RISCV_INFO(r);
bool warn = false;
@@ -3748,18 +3347,8 @@ static void log_mem_access_result(struct target *target, bool success, int metho
/* Determine the log message severity. Show warnings only once. */
if (!success) {
- if (method == RISCV_MEM_ACCESS_PROGBUF) {
- warn = r->mem_access_progbuf_warn;
- r->mem_access_progbuf_warn = false;
- }
- if (method == RISCV_MEM_ACCESS_SYSBUS) {
- warn = r->mem_access_sysbus_warn;
- r->mem_access_sysbus_warn = false;
- }
- if (method == RISCV_MEM_ACCESS_ABSTRACT) {
- warn = r->mem_access_abstract_warn;
- r->mem_access_abstract_warn = false;
- }
+ warn = r->mem_access_warn[method];
+ r->mem_access_warn[method] = false;
}
if (warn)
@@ -3768,101 +3357,180 @@ static void log_mem_access_result(struct target *target, bool success, int metho
LOG_TARGET_DEBUG(target, "%s", msg);
}
-static bool mem_should_skip_progbuf(struct target *target, target_addr_t address,
- uint32_t size, bool is_read, char **skip_reason)
+typedef enum {
+ MEM_ACCESS_RESULT_TYPE_OK,
+ MEM_ACCESS_RESULT_TYPE_DISABLED,
+ MEM_ACCESS_RESULT_TYPE_SKIPPED,
+ MEM_ACCESS_RESULT_TYPE_FAILED
+} mem_access_result_type_t;
+
+#define LIST_OF_MEM_ACCESS_RESULTS \
+ MEM_ACCESS_RESULT_HANDLER(MEM_ACCESS_OK, \
+ MEM_ACCESS_RESULT_TYPE_OK, "ok") \
+ MEM_ACCESS_RESULT_HANDLER(MEM_ACCESS_DISABLED, \
+ MEM_ACCESS_RESULT_TYPE_DISABLED, "disabled") \
+ MEM_ACCESS_RESULT_HANDLER(MEM_ACCESS_SKIPPED_ABSTRACT_ACCESS_CMDERR, \
+ MEM_ACCESS_RESULT_TYPE_SKIPPED, "skipped (abstract access cmderr)") \
+ MEM_ACCESS_RESULT_HANDLER(MEM_ACCESS_SKIPPED_PROGBUF_NOT_PRESENT, \
+ MEM_ACCESS_RESULT_TYPE_SKIPPED, "skipped (progbuf not present)") \
+ MEM_ACCESS_RESULT_HANDLER(MEM_ACCESS_SKIPPED_PROGBUF_INSUFFICIENT, \
+ MEM_ACCESS_RESULT_TYPE_SKIPPED, "skipped (insufficient progbuf)") \
+ MEM_ACCESS_RESULT_HANDLER(MEM_ACCESS_SKIPPED_UNSUPPORTED_ACCESS_SIZE, \
+ MEM_ACCESS_RESULT_TYPE_SKIPPED, "skipped (unsupported access size)") \
+ MEM_ACCESS_RESULT_HANDLER(MEM_ACCESS_SKIPPED_XLEN_TOO_SHORT, \
+ MEM_ACCESS_RESULT_TYPE_SKIPPED, "skipped (xlen too short)") \
+ MEM_ACCESS_RESULT_HANDLER(MEM_ACCESS_SKIPPED_TARGET_NOT_HALTED, \
+ MEM_ACCESS_RESULT_TYPE_SKIPPED, "skipped (target not halted)") \
+ MEM_ACCESS_RESULT_HANDLER(MEM_ACCESS_SKIPPED_TOO_LARGE_ADDRESS, \
+ MEM_ACCESS_RESULT_TYPE_SKIPPED, "skipped (address too large)") \
+ MEM_ACCESS_RESULT_HANDLER(MEM_ACCESS_SKIPPED_UNSUPPORTED_INCREMENT_SIZE, \
+ MEM_ACCESS_RESULT_TYPE_SKIPPED, "skipped (increment size not supported)") \
+ MEM_ACCESS_RESULT_HANDLER(MEM_ACCESS_SKIPPED_TARGET_SELECT_FAILED, \
+ MEM_ACCESS_RESULT_TYPE_SKIPPED, "skipped (dm target select failed)") \
+ MEM_ACCESS_RESULT_HANDLER(MEM_ACCESS_SKIPPED_FENCE_EXEC_FAILED, \
+ MEM_ACCESS_RESULT_TYPE_SKIPPED, "skipped (fence execution failed)") \
+ MEM_ACCESS_RESULT_HANDLER(MEM_ACCESS_FAILED, \
+ MEM_ACCESS_RESULT_TYPE_FAILED, "failed") \
+ MEM_ACCESS_RESULT_HANDLER(MEM_ACCESS_FAILED_DM_ACCESS_FAILED, \
+ MEM_ACCESS_RESULT_TYPE_FAILED, "failed (DM register access failed)") \
+ MEM_ACCESS_RESULT_HANDLER(MEM_ACCESS_FAILED_PRIV_MOD_FAILED, \
+ MEM_ACCESS_RESULT_TYPE_FAILED, "failed (privilege modification failed)") \
+
+
+#define MEM_ACCESS_RESULT_HANDLER(name, kind, msg) name,
+typedef enum {
+ LIST_OF_MEM_ACCESS_RESULTS
+} mem_access_result_t;
+#undef MEM_ACCESS_RESULT_HANDLER
+
+bool is_mem_access_failed(mem_access_result_t status)
+{
+ #define MEM_ACCESS_RESULT_HANDLER(name, kind, msg) \
+ case name: return kind == MEM_ACCESS_RESULT_TYPE_FAILED;
+ switch (status) {
+ LIST_OF_MEM_ACCESS_RESULTS
+ }
+ #undef MEM_ACCESS_RESULT_HANDLER
+ LOG_ERROR("Unknown memory access status: %d", status);
+ assert(false);
+ return false;
+}
+
+bool is_mem_access_skipped(mem_access_result_t status)
{
- assert(skip_reason);
+ #define MEM_ACCESS_RESULT_HANDLER(name, kind, msg) \
+ case name: return kind == MEM_ACCESS_RESULT_TYPE_SKIPPED;
+ switch (status) {
+ LIST_OF_MEM_ACCESS_RESULTS
+ }
+ #undef MEM_ACCESS_RESULT_HANDLER
+ LOG_ERROR("Unknown memory access status: %d", status);
+ assert(false);
+ return false;
+}
+
+const char *mem_access_result_to_str(mem_access_result_t status)
+{
+ #define MEM_ACCESS_RESULT_HANDLER(name, kind, msg) \
+ [name] = msg,
+ static const char * const table[] = {
+ LIST_OF_MEM_ACCESS_RESULTS
+ };
+ #undef MEM_ACCESS_RESULT_HANDLER
+ assert(status < ARRAY_SIZE(table));
+ return table[status];
+}
+
+static mem_access_result_t mem_should_skip_progbuf(struct target *target,
+ target_addr_t address, uint32_t size, bool is_read)
+{
+ if (!has_sufficient_progbuf(target, 1)) {
+ LOG_TARGET_DEBUG(target, "Skipping mem %s via progbuf "
+ "- progbuf not present", is_read ? "read" : "write");
+ return MEM_ACCESS_SKIPPED_PROGBUF_NOT_PRESENT;
+ }
if (!has_sufficient_progbuf(target, 3)) {
LOG_TARGET_DEBUG(target, "Skipping mem %s via progbuf - insufficient progbuf size.",
is_read ? "read" : "write");
- *skip_reason = "skipped (insufficient progbuf)";
- return true;
+ return MEM_ACCESS_SKIPPED_PROGBUF_INSUFFICIENT;
}
if (target->state != TARGET_HALTED) {
- LOG_TARGET_DEBUG(target, "Skipping mem %s via progbuf - target not halted.",
- is_read ? "read" : "write");
- *skip_reason = "skipped (target not halted)";
- return true;
+ LOG_TARGET_DEBUG(target,
+ "Skipping mem %s via progbuf - target not halted.",
+ is_read ? "read" : "write");
+ return MEM_ACCESS_SKIPPED_TARGET_NOT_HALTED;
}
if (riscv_xlen(target) < size * 8) {
- LOG_TARGET_DEBUG(target, "Skipping mem %s via progbuf - XLEN (%d) is too short for %d-bit memory access.",
- is_read ? "read" : "write", riscv_xlen(target), size * 8);
- *skip_reason = "skipped (XLEN too short)";
- return true;
+ LOG_TARGET_DEBUG(target,
+ "Skipping mem %s via progbuf - "
+ "XLEN (%d) is too short for %d-bit memory access.",
+ is_read ? "read" : "write", riscv_xlen(target), size * 8);
+ return MEM_ACCESS_SKIPPED_XLEN_TOO_SHORT;
}
if (size > 8) {
- LOG_TARGET_DEBUG(target, "Skipping mem %s via progbuf - unsupported size.",
- is_read ? "read" : "write");
- *skip_reason = "skipped (unsupported size)";
- return true;
+ LOG_TARGET_DEBUG(target,
+ "Skipping mem %s via progbuf - unsupported size.",
+ is_read ? "read" : "write");
+ return MEM_ACCESS_SKIPPED_UNSUPPORTED_ACCESS_SIZE;
}
if ((sizeof(address) * 8 > riscv_xlen(target)) && (address >> riscv_xlen(target))) {
- LOG_TARGET_DEBUG(target, "Skipping mem %s via progbuf - progbuf only supports %u-bit address.",
- is_read ? "read" : "write", riscv_xlen(target));
- *skip_reason = "skipped (too large address)";
- return true;
+ LOG_TARGET_DEBUG(target,
+ "Skipping mem %s via progbuf - progbuf only supports %u-bit address.",
+ is_read ? "read" : "write", riscv_xlen(target));
+ return MEM_ACCESS_SKIPPED_TOO_LARGE_ADDRESS;
}
- return false;
+ return MEM_ACCESS_OK;
}
-static bool mem_should_skip_sysbus(struct target *target, target_addr_t address,
- uint32_t size, uint32_t increment, bool is_read, char **skip_reason)
+static mem_access_result_t
+mem_should_skip_sysbus(struct target *target, target_addr_t address,
+ uint32_t size, uint32_t increment, bool is_read)
{
- assert(skip_reason);
-
RISCV013_INFO(info);
if (!sba_supports_access(target, size)) {
LOG_TARGET_DEBUG(target, "Skipping mem %s via system bus - unsupported size.",
is_read ? "read" : "write");
- *skip_reason = "skipped (unsupported size)";
- return true;
+ return MEM_ACCESS_SKIPPED_UNSUPPORTED_ACCESS_SIZE;
}
unsigned int sbasize = get_field(info->sbcs, DM_SBCS_SBASIZE);
if ((sizeof(address) * 8 > sbasize) && (address >> sbasize)) {
LOG_TARGET_DEBUG(target, "Skipping mem %s via system bus - sba only supports %u-bit address.",
is_read ? "read" : "write", sbasize);
- *skip_reason = "skipped (too large address)";
- return true;
+ return MEM_ACCESS_SKIPPED_TOO_LARGE_ADDRESS;
}
if (is_read && increment != size && (get_field(info->sbcs, DM_SBCS_SBVERSION) == 0 || increment != 0)) {
LOG_TARGET_DEBUG(target, "Skipping mem read via system bus - "
"sba reads only support size==increment or also size==0 for sba v1.");
- *skip_reason = "skipped (unsupported increment)";
- return true;
+ return MEM_ACCESS_SKIPPED_UNSUPPORTED_INCREMENT_SIZE;
}
- return false;
+ return MEM_ACCESS_OK;
}
-static bool mem_should_skip_abstract(struct target *target, target_addr_t address,
- uint32_t size, uint32_t increment, bool is_read, char **skip_reason)
+static mem_access_result_t
+mem_should_skip_abstract(struct target *target, target_addr_t address,
+ uint32_t size, uint32_t increment, bool is_read)
{
- assert(skip_reason);
-
if (size > 8) {
/* TODO: Add 128b support if it's ever used. Involves modifying
read/write_abstract_arg() to work on two 64b values. */
LOG_TARGET_DEBUG(target, "Skipping mem %s via abstract access - unsupported size: %d bits",
is_read ? "read" : "write", size * 8);
- *skip_reason = "skipped (unsupported size)";
- return true;
+ return MEM_ACCESS_SKIPPED_UNSUPPORTED_ACCESS_SIZE;
}
if ((sizeof(address) * 8 > riscv_xlen(target)) && (address >> riscv_xlen(target))) {
LOG_TARGET_DEBUG(target, "Skipping mem %s via abstract access - abstract access only supports %u-bit address.",
is_read ? "read" : "write", riscv_xlen(target));
- *skip_reason = "skipped (too large address)";
- return true;
+ return MEM_ACCESS_SKIPPED_TOO_LARGE_ADDRESS;
}
if (is_read && size != increment) {
LOG_TARGET_ERROR(target, "Skipping mem read via abstract access - "
"abstract command reads only support size==increment.");
- *skip_reason = "skipped (unsupported increment)";
- return true;
+ return MEM_ACCESS_SKIPPED_UNSUPPORTED_INCREMENT_SIZE;
}
-
- return false;
+ return MEM_ACCESS_OK;
}
/*
@@ -3870,12 +3538,16 @@ static bool mem_should_skip_abstract(struct target *target, target_addr_t addres
* supported are 1, 2, and 4 bytes despite the spec's support of 8 and 16 byte
* aamsize fields in the memory access abstract command.
*/
-static int read_memory_abstract(struct target *target, target_addr_t address,
- uint32_t size, uint32_t count, uint8_t *buffer, uint32_t increment)
+static mem_access_result_t
+read_memory_abstract(struct target *target, target_addr_t address,
+ uint32_t size, uint32_t count, uint8_t *buffer, uint32_t increment)
{
- RISCV013_INFO(info);
+ mem_access_result_t skip_reason =
+ mem_should_skip_abstract(target, address, size, increment, /* is_read = */ true);
+ if (skip_reason != MEM_ACCESS_OK)
+ return skip_reason;
- int result = ERROR_OK;
+ RISCV013_INFO(info);
bool use_aampostincrement = info->has_aampostincrement != YNM_NO;
LOG_TARGET_DEBUG(target, "Reading %d words of %d bytes from 0x%" TARGET_PRIxADDR, count,
@@ -3884,13 +3556,14 @@ static int read_memory_abstract(struct target *target, target_addr_t address,
memset(buffer, 0, count * size);
/* Convert the size (bytes) to width (bits) */
- unsigned width = size << 3;
+ unsigned int width = size << 3;
/* Create the command (physical address, postincrement, read) */
uint32_t command = access_memory_command(target, false, width, use_aampostincrement, false);
/* Execute the reads */
uint8_t *p = buffer;
+ int result = ERROR_OK;
bool updateaddr = true;
unsigned int width32 = (width < 32) ? 32 : width;
for (uint32_t c = 0; c < count; c++) {
@@ -3900,13 +3573,13 @@ static int read_memory_abstract(struct target *target, target_addr_t address,
result = write_abstract_arg(target, 1, address + c * size, riscv_xlen(target));
if (result != ERROR_OK) {
LOG_TARGET_ERROR(target, "Failed to write arg1.");
- return result;
+ return MEM_ACCESS_FAILED_DM_ACCESS_FAILED;
}
}
/* Execute the command */
uint32_t cmderr;
- result = execute_abstract_command(target, command, &cmderr);
+ result = riscv013_execute_abstract_command(target, command, &cmderr);
/* TODO: we need to modify error handling here. */
/* NOTE: in case of timeout cmderr is set to CMDERR_NONE */
@@ -3916,7 +3589,7 @@ static int read_memory_abstract(struct target *target, target_addr_t address,
riscv_reg_t new_address;
result = read_abstract_arg(target, &new_address, 1, riscv_xlen(target));
if (result != ERROR_OK)
- return result;
+ return MEM_ACCESS_FAILED_DM_ACCESS_FAILED;
if (new_address == address + size) {
LOG_TARGET_DEBUG(target, "aampostincrement is supported on this target.");
@@ -3928,7 +3601,7 @@ static int read_memory_abstract(struct target *target, target_addr_t address,
} else {
/* Try the same access but with postincrement disabled. */
command = access_memory_command(target, false, width, false, false);
- result = execute_abstract_command(target, command, &cmderr);
+ result = riscv013_execute_abstract_command(target, command, &cmderr);
if (result == ERROR_OK) {
LOG_TARGET_DEBUG(target, "aampostincrement is not supported on this target.");
info->has_aampostincrement = YNM_NO;
@@ -3936,14 +3609,17 @@ static int read_memory_abstract(struct target *target, target_addr_t address,
}
}
+ /* TODO:
+ * (1) Only the 1st access can result in a 'skip'
+ * (2) Analyze cmderr value */
if (result != ERROR_OK)
- return result;
+ return MEM_ACCESS_SKIPPED_ABSTRACT_ACCESS_CMDERR;
/* Copy arg0 to buffer (rounded width up to nearest 32) */
riscv_reg_t value;
result = read_abstract_arg(target, &value, 0, width32);
if (result != ERROR_OK)
- return result;
+ return MEM_ACCESS_FAILED_DM_ACCESS_FAILED;
buf_set_u64(p, 0, 8 * size, value);
if (info->has_aampostincrement == YNM_YES)
@@ -3951,7 +3627,7 @@ static int read_memory_abstract(struct target *target, target_addr_t address,
p += size;
}
- return result;
+ return MEM_ACCESS_OK;
}
/*
@@ -3959,9 +3635,16 @@ static int read_memory_abstract(struct target *target, target_addr_t address,
* sizes supported are 1, 2, and 4 bytes despite the spec's support of 8 and 16
* byte aamsize fields in the memory access abstract command.
*/
-static int write_memory_abstract(struct target *target, target_addr_t address,
- uint32_t size, uint32_t count, const uint8_t *buffer)
+static mem_access_result_t
+write_memory_abstract(struct target *target, target_addr_t address,
+ uint32_t size, uint32_t count, const uint8_t *buffer)
{
+ mem_access_result_t skip_reason =
+ mem_should_skip_abstract(target, address, size,
+ /* increment = */ 0, /* is_read = */ false);
+ if (skip_reason != MEM_ACCESS_OK)
+ return skip_reason;
+
RISCV013_INFO(info);
int result = ERROR_OK;
bool use_aampostincrement = info->has_aampostincrement != YNM_NO;
@@ -3970,7 +3653,7 @@ static int write_memory_abstract(struct target *target, target_addr_t address,
size, address);
/* Convert the size (bytes) to width (bits) */
- unsigned width = size << 3;
+ unsigned int width = size << 3;
/* Create the command (physical address, postincrement, write) */
uint32_t command = access_memory_command(target, false, width, use_aampostincrement, true);
@@ -3984,7 +3667,7 @@ static int write_memory_abstract(struct target *target, target_addr_t address,
result = write_abstract_arg(target, 0, value, riscv_xlen(target));
if (result != ERROR_OK) {
LOG_TARGET_ERROR(target, "Failed to write arg0.");
- return result;
+ return MEM_ACCESS_FAILED_DM_ACCESS_FAILED;
}
/* Update the address if it is the first time or aampostincrement is not supported by the target. */
@@ -3993,13 +3676,13 @@ static int write_memory_abstract(struct target *target, target_addr_t address,
result = write_abstract_arg(target, 1, address + c * size, riscv_xlen(target));
if (result != ERROR_OK) {
LOG_TARGET_ERROR(target, "Failed to write arg1.");
- return result;
+ return MEM_ACCESS_FAILED_DM_ACCESS_FAILED;
}
}
/* Execute the command */
uint32_t cmderr;
- result = execute_abstract_command(target, command, &cmderr);
+ result = riscv013_execute_abstract_command(target, command, &cmderr);
/* TODO: we need to modify error handling here. */
/* NOTE: in case of timeout cmderr is set to CMDERR_NONE */
@@ -4009,7 +3692,7 @@ static int write_memory_abstract(struct target *target, target_addr_t address,
riscv_reg_t new_address;
result = read_abstract_arg(target, &new_address, 1, riscv_xlen(target));
if (result != ERROR_OK)
- return result;
+ return MEM_ACCESS_FAILED_DM_ACCESS_FAILED;
if (new_address == address + size) {
LOG_TARGET_DEBUG(target, "aampostincrement is supported on this target.");
@@ -4021,7 +3704,7 @@ static int write_memory_abstract(struct target *target, target_addr_t address,
} else {
/* Try the same access but with postincrement disabled. */
command = access_memory_command(target, false, width, false, true);
- result = execute_abstract_command(target, command, &cmderr);
+ result = riscv013_execute_abstract_command(target, command, &cmderr);
if (result == ERROR_OK) {
LOG_TARGET_DEBUG(target, "aampostincrement is not supported on this target.");
info->has_aampostincrement = YNM_NO;
@@ -4029,15 +3712,18 @@ static int write_memory_abstract(struct target *target, target_addr_t address,
}
}
+ /* TODO:
+ * (1) Only the 1st access can result in a 'skip'
+ * (2) Analyze cmderr value */
if (result != ERROR_OK)
- return result;
+ return MEM_ACCESS_SKIPPED_ABSTRACT_ACCESS_CMDERR;
if (info->has_aampostincrement == YNM_YES)
updateaddr = false;
p += size;
}
- return result;
+ return MEM_ACCESS_OK;
}
/**
@@ -4067,11 +3753,11 @@ static int read_memory_progbuf_inner_startup(struct target *target,
/* AC_ACCESS_REGISTER_POSTEXEC is used to trigger first stage of the
* pipeline (memory -> s1) whenever this command is executed.
*/
- const uint32_t startup_command = access_register_command(target,
+ const uint32_t startup_command = riscv013_access_register_command(target,
GDB_REGNO_S1, riscv_xlen(target),
AC_ACCESS_REGISTER_TRANSFER | AC_ACCESS_REGISTER_POSTEXEC);
uint32_t cmderr;
- if (execute_abstract_command(target, startup_command, &cmderr) != ERROR_OK)
+ if (riscv013_execute_abstract_command(target, startup_command, &cmderr) != ERROR_OK)
return ERROR_FAIL;
/* TODO: we need to modify error handling here. */
/* NOTE: in case of timeout cmderr is set to CMDERR_NONE */
@@ -4554,11 +4240,11 @@ static int read_memory_progbuf_inner_one(struct target *target,
if (write_abstract_arg(target, 0, access.target_address, riscv_xlen(target))
!= ERROR_OK)
return ERROR_FAIL;
- uint32_t command = access_register_command(target, GDB_REGNO_S1,
+ uint32_t command = riscv013_access_register_command(target, GDB_REGNO_S1,
riscv_xlen(target), AC_ACCESS_REGISTER_WRITE |
AC_ACCESS_REGISTER_TRANSFER | AC_ACCESS_REGISTER_POSTEXEC);
uint32_t cmderr;
- if (execute_abstract_command(target, command, &cmderr) != ERROR_OK)
+ if (riscv013_execute_abstract_command(target, command, &cmderr) != ERROR_OK)
return ERROR_FAIL;
return read_word_from_s1(target, access, 0);
@@ -4567,32 +4253,32 @@ static int read_memory_progbuf_inner_one(struct target *target,
/**
* Read the requested memory, silently handling memory access errors.
*/
-static int read_memory_progbuf(struct target *target, target_addr_t address,
- uint32_t size, uint32_t count, uint8_t *buffer, uint32_t increment)
+static mem_access_result_t
+read_memory_progbuf(struct target *target, target_addr_t address,
+ uint32_t size, uint32_t count, uint8_t *buffer, uint32_t increment)
{
- if (riscv_xlen(target) < size * 8) {
- LOG_TARGET_ERROR(target, "XLEN (%d) is too short for %"
- PRIu32 "-bit memory read.", riscv_xlen(target), size * 8);
- return ERROR_FAIL;
- }
+ mem_access_result_t skip_reason =
+ mem_should_skip_progbuf(target, address, size, /* is_read = */ true);
+ if (skip_reason != MEM_ACCESS_OK)
+ return skip_reason;
LOG_TARGET_DEBUG(target, "reading %" PRIu32 " elements of %" PRIu32
" bytes from 0x%" TARGET_PRIxADDR, count, size, address);
if (dm013_select_target(target) != ERROR_OK)
- return ERROR_FAIL;
+ return MEM_ACCESS_SKIPPED_TARGET_SELECT_FAILED;
select_dmi(target);
memset(buffer, 0, count*size);
if (execute_fence(target) != ERROR_OK)
- return ERROR_FAIL;
+ return MEM_ACCESS_SKIPPED_FENCE_EXEC_FAILED;
uint64_t mstatus = 0;
uint64_t mstatus_old = 0;
if (modify_privilege(target, &mstatus, &mstatus_old) != ERROR_OK)
- return ERROR_FAIL;
+ return MEM_ACCESS_FAILED_PRIV_MOD_FAILED;
const bool mprven = riscv_enable_virtual && get_field(mstatus, MSTATUS_MPRV);
const struct memory_access_info access = {
@@ -4607,9 +4293,32 @@ static int read_memory_progbuf(struct target *target, target_addr_t address,
if (mstatus != mstatus_old &&
register_write_direct(target, GDB_REGNO_MSTATUS, mstatus_old) != ERROR_OK)
- return ERROR_FAIL;
+ return MEM_ACCESS_FAILED;
- return result;
+ return (result == ERROR_OK) ? MEM_ACCESS_OK : MEM_ACCESS_FAILED;
+}
+
+static mem_access_result_t
+read_memory_sysbus(struct target *target, target_addr_t address,
+ uint32_t size, uint32_t count, uint8_t *buffer, uint32_t increment)
+{
+ mem_access_result_t skip_reason =
+ mem_should_skip_sysbus(target, address, size, increment, /* is_read = */ true);
+ if (skip_reason != MEM_ACCESS_OK)
+ return skip_reason;
+
+ int ret = ERROR_FAIL;
+ uint64_t sbver = get_field(get_info(target)->sbcs, DM_SBCS_SBVERSION);
+ if (sbver == 0) {
+ ret = read_memory_bus_v0(target, address, size, count, buffer, increment);
+ } else if (sbver == 1) {
+ ret = read_memory_bus_v1(target, address, size, count, buffer, increment);
+ } else {
+ LOG_TARGET_ERROR(target,
+ "Unknown system bus version: %" PRIu64, sbver);
+ }
+
+ return (ret == ERROR_OK) ? MEM_ACCESS_OK : MEM_ACCESS_FAILED;
}
static int read_memory(struct target *target, target_addr_t address,
@@ -4618,62 +4327,58 @@ static int read_memory(struct target *target, target_addr_t address,
if (count == 0)
return ERROR_OK;
- if (size != 1 && size != 2 && size != 4 && size != 8 && size != 16) {
+ if (!IS_PWR_OF_2(size) || size < 1 || size > 16) {
LOG_TARGET_ERROR(target, "BUG: Unsupported size for memory read: %d", size);
return ERROR_FAIL;
}
- int ret = ERROR_FAIL;
- RISCV_INFO(r);
- RISCV013_INFO(info);
-
- char *progbuf_result = "disabled";
- char *sysbus_result = "disabled";
- char *abstract_result = "disabled";
-
- for (unsigned int i = 0; i < RISCV_NUM_MEM_ACCESS_METHODS; i++) {
- int method = r->mem_access_methods[i];
-
- if (method == RISCV_MEM_ACCESS_PROGBUF) {
- if (mem_should_skip_progbuf(target, address, size, true, &progbuf_result))
- continue;
-
- ret = read_memory_progbuf(target, address, size, count, buffer, increment);
-
- if (ret != ERROR_OK)
- progbuf_result = "failed";
- } else if (method == RISCV_MEM_ACCESS_SYSBUS) {
- if (mem_should_skip_sysbus(target, address, size, increment, true, &sysbus_result))
- continue;
-
- if (get_field(info->sbcs, DM_SBCS_SBVERSION) == 0)
- ret = read_memory_bus_v0(target, address, size, count, buffer, increment);
- else if (get_field(info->sbcs, DM_SBCS_SBVERSION) == 1)
- ret = read_memory_bus_v1(target, address, size, count, buffer, increment);
-
- if (ret != ERROR_OK)
- sysbus_result = "failed";
- } else if (method == RISCV_MEM_ACCESS_ABSTRACT) {
- if (mem_should_skip_abstract(target, address, size, increment, true, &abstract_result))
- continue;
-
- ret = read_memory_abstract(target, address, size, count, buffer, increment);
+ mem_access_result_t skip_reason[] = {
+ [RISCV_MEM_ACCESS_PROGBUF] = MEM_ACCESS_DISABLED,
+ [RISCV_MEM_ACCESS_SYSBUS] = MEM_ACCESS_DISABLED,
+ [RISCV_MEM_ACCESS_ABSTRACT] = MEM_ACCESS_DISABLED,
+ };
- if (ret != ERROR_OK)
- abstract_result = "failed";
- } else if (method == RISCV_MEM_ACCESS_UNSPECIFIED)
- /* No further mem access method to try. */
- break;
+ RISCV_INFO(r);
+ for (unsigned int i = 0; i < r->num_enabled_mem_access_methods; ++i) {
+ riscv_mem_access_method_t method = r->mem_access_methods[i];
+ switch (method) {
+ case RISCV_MEM_ACCESS_PROGBUF:
+ skip_reason[method] =
+ read_memory_progbuf(target, address,
+ size, count, buffer, increment);
+ break;
+ case RISCV_MEM_ACCESS_SYSBUS:
+ skip_reason[method] =
+ read_memory_sysbus(target, address,
+ size, count, buffer, increment);
+ break;
+ case RISCV_MEM_ACCESS_ABSTRACT:
+ skip_reason[method] =
+ read_memory_abstract(target, address,
+ size, count, buffer, increment);
+ break;
+ default:
+ LOG_TARGET_ERROR(target, "Unknown memory access method: %d", method);
+ assert(false);
+ return ERROR_FAIL;
+ }
- log_mem_access_result(target, ret == ERROR_OK, method, true);
+ if (is_mem_access_failed(skip_reason[method]))
+ goto failure;
- if (ret == ERROR_OK)
- return ret;
+ const bool success = (skip_reason[method] == MEM_ACCESS_OK);
+ log_mem_access_result(target, success, method, /* is_read = */ true);
+ if (success)
+ return ERROR_OK;
}
- LOG_TARGET_ERROR(target, "Failed to read memory (addr=0x%" PRIx64 ")", address);
- LOG_TARGET_ERROR(target, " progbuf=%s, sysbus=%s, abstract=%s", progbuf_result, sysbus_result, abstract_result);
- return ret;
+failure:
+ LOG_TARGET_ERROR(target, "Failed to read memory (addr=0x%" PRIx64 ")\n"
+ " progbuf=%s, sysbus=%s, abstract=%s", address,
+ mem_access_result_to_str(skip_reason[RISCV_MEM_ACCESS_PROGBUF]),
+ mem_access_result_to_str(skip_reason[RISCV_MEM_ACCESS_SYSBUS]),
+ mem_access_result_to_str(skip_reason[RISCV_MEM_ACCESS_ABSTRACT]));
+ return ERROR_FAIL;
}
static int write_memory_bus_v0(struct target *target, target_addr_t address,
@@ -4740,9 +4445,10 @@ static int write_memory_bus_v1(struct target *target, target_addr_t address,
target_addr_t next_address = address;
target_addr_t end_address = address + count * size;
- int result;
+ int result = sb_write_address(target, next_address, RISCV_DELAY_BASE);
+ if (result != ERROR_OK)
+ return result;
- sb_write_address(target, next_address, true);
while (next_address < end_address) {
LOG_TARGET_DEBUG(target, "Transferring burst starting at address 0x%" TARGET_PRIxADDR,
next_address);
@@ -4896,14 +4602,14 @@ static int write_memory_progbuf_startup(struct target *target, target_addr_t *ad
/* Write and execute command that moves the value from data0 [, data1]
* into S1 and executes program buffer. */
- uint32_t command = access_register_command(target,
+ uint32_t command = riscv013_access_register_command(target,
GDB_REGNO_S1, riscv_xlen(target),
AC_ACCESS_REGISTER_POSTEXEC |
AC_ACCESS_REGISTER_TRANSFER |
AC_ACCESS_REGISTER_WRITE);
uint32_t cmderr;
- if (execute_abstract_command(target, command, &cmderr) != ERROR_OK)
+ if (riscv013_execute_abstract_command(target, command, &cmderr) != ERROR_OK)
return ERROR_FAIL;
log_memory_access64(*address_p, value, size, /*is_read*/ false);
@@ -5126,25 +4832,25 @@ static int write_memory_progbuf_inner(struct target *target, target_addr_t start
return write_memory_progbuf_teardown(target);
}
-static int write_memory_progbuf(struct target *target, target_addr_t address,
+static mem_access_result_t
+write_memory_progbuf(struct target *target, target_addr_t address,
uint32_t size, uint32_t count, const uint8_t *buffer)
{
- if (riscv_xlen(target) < size * 8) {
- LOG_TARGET_ERROR(target, "XLEN (%u) is too short for %" PRIu32 "-bit memory write.",
- riscv_xlen(target), size * 8);
- return ERROR_FAIL;
- }
+ mem_access_result_t skip_reason =
+ mem_should_skip_progbuf(target, address, size, /* is_read = */ false);
+ if (skip_reason != MEM_ACCESS_OK)
+ return skip_reason;
LOG_TARGET_DEBUG(target, "writing %" PRIu32 " words of %" PRIu32
" bytes to 0x%" TARGET_PRIxADDR, count, size, address);
if (dm013_select_target(target) != ERROR_OK)
- return ERROR_FAIL;
+ return MEM_ACCESS_SKIPPED_TARGET_SELECT_FAILED;
uint64_t mstatus = 0;
uint64_t mstatus_old = 0;
if (modify_privilege(target, &mstatus, &mstatus_old) != ERROR_OK)
- return ERROR_FAIL;
+ return MEM_ACCESS_FAILED_PRIV_MOD_FAILED;
const bool mprven = riscv_enable_virtual && get_field(mstatus, MSTATUS_MPRV);
@@ -5153,73 +4859,109 @@ static int write_memory_progbuf(struct target *target, target_addr_t address,
/* Restore MSTATUS */
if (mstatus != mstatus_old)
if (register_write_direct(target, GDB_REGNO_MSTATUS, mstatus_old))
- return ERROR_FAIL;
+ return MEM_ACCESS_FAILED;
if (execute_fence(target) != ERROR_OK)
- return ERROR_FAIL;
+ return MEM_ACCESS_SKIPPED_FENCE_EXEC_FAILED;
- return result;
+ return result == ERROR_OK ? MEM_ACCESS_OK : MEM_ACCESS_FAILED;
}
-static int write_memory(struct target *target, target_addr_t address,
- uint32_t size, uint32_t count, const uint8_t *buffer)
+static mem_access_result_t
+write_memory_sysbus(struct target *target, target_addr_t address,
+ uint32_t size, uint32_t count, const uint8_t *buffer)
{
- if (size != 1 && size != 2 && size != 4 && size != 8 && size != 16) {
- LOG_TARGET_ERROR(target, "BUG: Unsupported size for memory write: %d", size);
- return ERROR_FAIL;
- }
+ riscv013_info_t *info = get_info(target);
+ mem_access_result_t skip_reason =
+ mem_should_skip_sysbus(target, address, size, 0, /* is_read = */ false);
+ if (skip_reason != MEM_ACCESS_OK)
+ return skip_reason;
+ /* TODO: write_memory_bus_* should return mem_access_result_t too*/
int ret = ERROR_FAIL;
- RISCV_INFO(r);
- RISCV013_INFO(info);
-
- char *progbuf_result = "disabled";
- char *sysbus_result = "disabled";
- char *abstract_result = "disabled";
-
- for (unsigned int i = 0; i < RISCV_NUM_MEM_ACCESS_METHODS; i++) {
- int method = r->mem_access_methods[i];
+ uint64_t sbver = get_field(info->sbcs, DM_SBCS_SBVERSION);
+ if (sbver == 0) {
+ ret = write_memory_bus_v0(target, address, size, count, buffer);
+ } else if (sbver == 1) {
+ ret = write_memory_bus_v1(target, address, size, count, buffer);
+ } else {
+ LOG_TARGET_ERROR(target,
+ "Unknown system bus version: %" PRIu64, sbver);
+ }
- if (method == RISCV_MEM_ACCESS_PROGBUF) {
- if (mem_should_skip_progbuf(target, address, size, false, &progbuf_result))
- continue;
+ if (ret != ERROR_OK)
+ skip_reason = MEM_ACCESS_FAILED;
- ret = write_memory_progbuf(target, address, size, count, buffer);
+ return skip_reason;
+}
- if (ret != ERROR_OK)
- progbuf_result = "failed";
- } else if (method == RISCV_MEM_ACCESS_SYSBUS) {
- if (mem_should_skip_sysbus(target, address, size, 0, false, &sysbus_result))
- continue;
+static int write_memory(struct target *target, target_addr_t address,
+ uint32_t size, uint32_t count, const uint8_t *buffer)
+{
+ if (!IS_PWR_OF_2(size) || size < 1 || size > 16) {
+ LOG_TARGET_ERROR(target, "BUG: Unsupported size for memory write: %d", size);
+ return ERROR_FAIL;
+ }
- if (get_field(info->sbcs, DM_SBCS_SBVERSION) == 0)
- ret = write_memory_bus_v0(target, address, size, count, buffer);
- else if (get_field(info->sbcs, DM_SBCS_SBVERSION) == 1)
- ret = write_memory_bus_v1(target, address, size, count, buffer);
+ mem_access_result_t skip_reason[] = {
+ [RISCV_MEM_ACCESS_PROGBUF] = MEM_ACCESS_DISABLED,
+ [RISCV_MEM_ACCESS_SYSBUS] = MEM_ACCESS_DISABLED,
+ [RISCV_MEM_ACCESS_ABSTRACT] = MEM_ACCESS_DISABLED
+ };
- if (ret != ERROR_OK)
- sysbus_result = "failed";
- } else if (method == RISCV_MEM_ACCESS_ABSTRACT) {
- if (mem_should_skip_abstract(target, address, size, 0, false, &abstract_result))
- continue;
+ RISCV_INFO(r);
+ for (unsigned int i = 0; i < r->num_enabled_mem_access_methods; ++i) {
+ riscv_mem_access_method_t method = r->mem_access_methods[i];
+ switch (method) {
+ case RISCV_MEM_ACCESS_PROGBUF:
+ skip_reason[method] =
+ write_memory_progbuf(target, address,
+ size, count, buffer);
+ break;
+ case RISCV_MEM_ACCESS_SYSBUS:
+ skip_reason[method] =
+ write_memory_sysbus(target, address,
+ size, count, buffer);
+ break;
+ case RISCV_MEM_ACCESS_ABSTRACT:
+ skip_reason[method] =
+ write_memory_abstract(target, address,
+ size, count, buffer);
+ break;
+ default:
+ LOG_TARGET_ERROR(target, "Unknown memory access method: %d", method);
+ assert(false);
+ return ERROR_FAIL;
+ }
- ret = write_memory_abstract(target, address, size, count, buffer);
+ if (is_mem_access_failed(skip_reason[method]))
+ goto failure;
- if (ret != ERROR_OK)
- abstract_result = "failed";
- } else if (method == RISCV_MEM_ACCESS_UNSPECIFIED)
- /* No further mem access method to try. */
- break;
+ const bool success = (skip_reason[method] == MEM_ACCESS_OK);
+ log_mem_access_result(target, success, method, /* is_read = */ false);
+ if (success)
+ return ERROR_OK;
+ }
- log_mem_access_result(target, ret == ERROR_OK, method, false);
+failure:
+ LOG_TARGET_ERROR(target, "Failed to write memory (addr=0x%" PRIx64 ")\n"
+ "progbuf=%s, sysbus=%s, abstract=%s", address,
+ mem_access_result_to_str(skip_reason[RISCV_MEM_ACCESS_PROGBUF]),
+ mem_access_result_to_str(skip_reason[RISCV_MEM_ACCESS_SYSBUS]),
+ mem_access_result_to_str(skip_reason[RISCV_MEM_ACCESS_ABSTRACT]));
+ return ERROR_FAIL;
+}
- if (ret == ERROR_OK)
- return ret;
- }
+static bool riscv013_get_impebreak(const struct target *target)
+{
+ RISCV013_INFO(r);
+ return r->impebreak;
+}
- LOG_TARGET_ERROR(target, "Target %s: Failed to write memory (addr=0x%" PRIx64 ")", target_name(target), address);
- LOG_TARGET_ERROR(target, " progbuf=%s, sysbus=%s, abstract=%s", progbuf_result, sysbus_result, abstract_result);
- return ret;
+static unsigned int riscv013_get_progbufsize(const struct target *target)
+{
+ RISCV013_INFO(r);
+ return r->progbufsize;
}
static int arch_state(struct target *target)
@@ -5326,13 +5068,13 @@ static int select_prepped_harts(struct target *target)
}
assert(dm->hart_count);
- unsigned hawindow_count = (dm->hart_count + 31) / 32;
+ unsigned int hawindow_count = (dm->hart_count + 31) / 32;
uint32_t *hawindow = calloc(hawindow_count, sizeof(uint32_t));
if (!hawindow)
return ERROR_FAIL;
target_list_t *entry;
- unsigned total_selected = 0;
+ unsigned int total_selected = 0;
unsigned int selected_index = 0;
list_for_each_entry(entry, &dm->target_list, list) {
struct target *t = entry->target;
@@ -5364,7 +5106,7 @@ static int select_prepped_harts(struct target *target)
return ERROR_FAIL;
}
- for (unsigned i = 0; i < hawindow_count; i++) {
+ for (unsigned int i = 0; i < hawindow_count; i++) {
if (dm_write(target, DM_HAWINDOWSEL, i) != ERROR_OK) {
free(hawindow);
return ERROR_FAIL;
@@ -5561,8 +5303,7 @@ static int riscv013_invalidate_cached_progbuf(struct target *target)
}
LOG_TARGET_DEBUG(target, "Invalidating progbuf cache");
- for (unsigned int i = 0; i < 15; i++)
- dm->progbuf_cache[i] = 0;
+ memset(dm->progbuf_cache, 0, sizeof(dm->progbuf_cache));
return ERROR_OK;
}
@@ -5574,7 +5315,7 @@ static int riscv013_execute_progbuf(struct target *target, uint32_t *cmderr)
run_program = set_field(run_program, AC_ACCESS_REGISTER_TRANSFER, 0);
run_program = set_field(run_program, AC_ACCESS_REGISTER_REGNO, 0x1000);
- return execute_abstract_command(target, run_program, cmderr);
+ return riscv013_execute_abstract_command(target, run_program, cmderr);
}
static void riscv013_fill_dmi_write(struct target *target, char *buf, uint64_t a, uint32_t d)
@@ -5593,7 +5334,7 @@ static void riscv013_fill_dmi_read(struct target *target, char *buf, uint64_t a)
buf_set_u64((unsigned char *)buf, DTM_DMI_ADDRESS_OFFSET, info->abits, a);
}
-static void riscv013_fill_dmi_nop(struct target *target, char *buf)
+static void riscv013_fill_dm_nop(struct target *target, char *buf)
{
RISCV013_INFO(info);
buf_set_u64((unsigned char *)buf, DTM_DMI_OP_OFFSET, DTM_DMI_OP_LENGTH, DMI_OP_NOP);
@@ -5607,27 +5348,6 @@ static int riscv013_get_dmi_scan_length(struct target *target)
return info->abits + DTM_DMI_DATA_LENGTH + DTM_DMI_OP_LENGTH;
}
-void riscv013_fill_dm_write(struct target *target, char *buf, uint64_t a, uint32_t d)
-{
- dm013_info_t *dm = get_dm(target);
- if (!dm)
- return;
- riscv013_fill_dmi_write(target, buf, a + dm->base, d);
-}
-
-void riscv013_fill_dm_read(struct target *target, char *buf, uint64_t a)
-{
- dm013_info_t *dm = get_dm(target);
- if (!dm)
- return;
- riscv013_fill_dmi_read(target, buf, a + dm->base);
-}
-
-void riscv013_fill_dm_nop(struct target *target, char *buf)
-{
- riscv013_fill_dmi_nop(target, buf);
-}
-
static int maybe_execute_fence_i(struct target *target)
{
if (has_sufficient_progbuf(target, 2))
diff --git a/src/target/riscv/riscv-013.h b/src/target/riscv/riscv-013.h
index f39393c..ca2d4ae 100644
--- a/src/target/riscv/riscv-013.h
+++ b/src/target/riscv/riscv-013.h
@@ -19,5 +19,9 @@ int riscv013_set_register(struct target *target, enum gdb_regno rid,
riscv_reg_t value);
int riscv013_set_register_buf(struct target *target, enum gdb_regno regno,
const uint8_t *value);
+uint32_t riscv013_access_register_command(struct target *target, uint32_t number,
+ unsigned int size, uint32_t flags);
+int riscv013_execute_abstract_command(struct target *target, uint32_t command,
+ uint32_t *cmderr);
#endif /* OPENOCD_TARGET_RISCV_RISCV_013_H */
diff --git a/src/target/riscv/riscv-013_reg.c b/src/target/riscv/riscv-013_reg.c
index a71a01c..514103b 100644
--- a/src/target/riscv/riscv-013_reg.c
+++ b/src/target/riscv/riscv-013_reg.c
@@ -5,10 +5,12 @@
#endif
#include "riscv-013_reg.h"
+#include "field_helpers.h"
#include "riscv_reg.h"
#include "riscv_reg_impl.h"
#include "riscv-013.h"
+#include "debug_defines.h"
#include <helper/time_support.h>
static int riscv013_reg_get(struct reg *reg)
@@ -44,7 +46,6 @@ static int riscv013_reg_get(struct reg *reg)
static int riscv013_reg_set(struct reg *reg, uint8_t *buf)
{
struct target *target = riscv_reg_impl_get_target(reg);
- RISCV_INFO(r);
char *str = buf_to_hex_str(buf, reg->size);
LOG_TARGET_DEBUG(target, "Write 0x%s to %s (valid=%d).", str, reg->name,
@@ -57,17 +58,6 @@ static int riscv013_reg_set(struct reg *reg, uint8_t *buf)
buf_get_u64(buf, 0, reg->size) == 0)
return ERROR_OK;
- if (reg->number == GDB_REGNO_TDATA1 ||
- reg->number == GDB_REGNO_TDATA2) {
- r->manual_hwbp_set = true;
- /* When enumerating triggers, we clear any triggers with DMODE set,
- * assuming they were left over from a previous debug session. So make
- * sure that is done before a user might be setting their own triggers.
- */
- if (riscv_enumerate_triggers(target) != ERROR_OK)
- return ERROR_FAIL;
- }
-
if (reg->number >= GDB_REGNO_V0 && reg->number <= GDB_REGNO_V31) {
if (riscv013_set_register_buf(target, reg->number, buf) != ERROR_OK)
return ERROR_FAIL;
@@ -85,33 +75,277 @@ static int riscv013_reg_set(struct reg *reg, uint8_t *buf)
static const struct reg_arch_type *riscv013_gdb_regno_reg_type(uint32_t regno)
{
- static const struct reg_arch_type riscv011_reg_type = {
+ static const struct reg_arch_type riscv013_reg_type = {
.get = riscv013_reg_get,
.set = riscv013_reg_set
};
- return &riscv011_reg_type;
+ return &riscv013_reg_type;
}
-static int riscv013_init_reg(struct target *target, uint32_t regno)
+static int init_cache_entry(struct target *target, uint32_t regno)
+{
+ struct reg * const reg = riscv_reg_impl_cache_entry(target, regno);
+ if (riscv_reg_impl_is_initialized(reg))
+ return ERROR_OK;
+ return riscv_reg_impl_init_cache_entry(target, regno,
+ riscv_reg_impl_gdb_regno_exist(target, regno),
+ riscv013_gdb_regno_reg_type(regno));
+}
+
+/**
+ * Some registers are optional (e.g. "misa"). For such registers it is first
+ * assumed they exist (via "assume_reg_exist()"), then the read is attempted
+ * (via the usual "riscv_reg_get()") and if the read fails, the register is
+ * marked as non-existing (via "riscv_reg_impl_set_exist()").
+ */
+static int assume_reg_exist(struct target *target, uint32_t regno)
{
- return riscv_reg_impl_init_one(target, regno, riscv013_gdb_regno_reg_type(regno));
+ return riscv_reg_impl_init_cache_entry(target, regno,
+ /* exist */ true, riscv013_gdb_regno_reg_type(regno));
}
-int riscv013_reg_init_all(struct target *target)
+static int examine_xlen(struct target *target)
{
- if (riscv_reg_impl_init_cache(target) != ERROR_OK)
+ RISCV_INFO(r);
+ unsigned int cmderr;
+
+ const uint32_t command = riscv013_access_register_command(target,
+ GDB_REGNO_S0, /* size */ 64, AC_ACCESS_REGISTER_TRANSFER);
+ int res = riscv013_execute_abstract_command(target, command, &cmderr);
+ if (res == ERROR_OK) {
+ r->xlen = 64;
+ return ERROR_OK;
+ }
+ if (res == ERROR_TIMEOUT_REACHED)
return ERROR_FAIL;
+ r->xlen = 32;
+
+ return ERROR_OK;
+}
+
+static int examine_vlenb(struct target *target)
+{
+ RISCV_INFO(r);
+
+ /* Reading "vlenb" requires "mstatus.vs" to be set, so "mstatus" should
+ * be accessible.*/
+ int res = init_cache_entry(target, GDB_REGNO_MSTATUS);
+ if (res != ERROR_OK)
+ return res;
+
+ res = assume_reg_exist(target, GDB_REGNO_VLENB);
+ if (res != ERROR_OK)
+ return res;
+
+ riscv_reg_t vlenb_val;
+ if (riscv_reg_get(target, &vlenb_val, GDB_REGNO_VLENB) != ERROR_OK) {
+ if (riscv_supports_extension(target, 'V'))
+ LOG_TARGET_WARNING(target, "Couldn't read vlenb; vector register access won't work.");
+ r->vlenb = 0;
+ return riscv_reg_impl_set_exist(target, GDB_REGNO_VLENB, false);
+ }
+ /* As defined by RISC-V V extension specification:
+ * https://github.com/riscv/riscv-v-spec/blob/2f68ef7256d6ec53e4d2bd7cb12862f406d64e34/v-spec.adoc?plain=1#L67-L72 */
+ const unsigned int vlen_max = 65536;
+ const unsigned int vlenb_max = vlen_max / 8;
+ if (vlenb_val > vlenb_max) {
+ LOG_TARGET_WARNING(target, "'vlenb == %" PRIu64
+ "' is greater than maximum allowed by specification (%u); vector register access won't work.",
+ vlenb_val, vlenb_max);
+ r->vlenb = 0;
+ return ERROR_OK;
+ }
+ assert(vlenb_max <= UINT_MAX);
+ r->vlenb = (unsigned int)vlenb_val;
+
+ LOG_TARGET_INFO(target, "Vector support with vlenb=%u", r->vlenb);
+ return ERROR_OK;
+}
+
+enum misa_mxl {
+ MISA_MXL_INVALID = 0,
+ MISA_MXL_32 = 1,
+ MISA_MXL_64 = 2,
+ MISA_MXL_128 = 3
+};
+
+unsigned int mxl_to_xlen(enum misa_mxl mxl)
+{
+ switch (mxl) {
+ case MISA_MXL_32:
+ return 32;
+ case MISA_MXL_64:
+ return 64;
+ case MISA_MXL_128:
+ return 128;
+ case MISA_MXL_INVALID:
+ assert(0);
+ }
+ return 0;
+}
+
+static int check_misa_mxl(const struct target *target)
+{
+ RISCV_INFO(r);
+
+ if (r->misa == 0) {
+ LOG_TARGET_WARNING(target, "'misa' register is read as zero."
+ "OpenOCD will not be able to determine some hart's capabilities.");
+ return ERROR_OK;
+ }
+ const unsigned int dxlen = riscv_xlen(target);
+ assert(dxlen <= sizeof(riscv_reg_t) * CHAR_BIT);
+ assert(dxlen >= 2);
+ const riscv_reg_t misa_mxl_mask = (riscv_reg_t)0x3 << (dxlen - 2);
+ const unsigned int mxl = get_field(r->misa, misa_mxl_mask);
+ if (mxl == MISA_MXL_INVALID) {
+ /* This is not an error!
+ * Imagine the platform that:
+ * - Has no abstract access to CSRs, so that CSRs are read
+ * through Program Buffer via "csrr" instruction.
+ * - Complies to v1.10 of the Priveleged Spec, so that misa.mxl
+ * is WARL and MXLEN may be chainged.
+ * https://github.com/riscv/riscv-isa-manual/commit/9a7dd2fe29011587954560b5dcf1875477b27ad8
+ * - DXLEN == MXLEN on reset == 64.
+ * In a following scenario:
+ * - misa.mxl was written, so that MXLEN is 32.
+ * - Debugger connects to the target.
+ * - Debugger observes DXLEN == 64.
+ * - Debugger reads misa:
+ * - Abstract access fails with "cmderr == not supported".
+ * - Access via Program Buffer involves reading "misa" to an
+ * "xreg" via "csrr", so that the "xreg" is filled with
+ * zero-extended value of "misa" (since "misa" is
+ * MXLEN-wide).
+ * - Debugger derives "misa.mxl" assumig "misa" is DXLEN-bit
+ * wide (64) while MXLEN is 32 and therefore erroneously
+ * assumes "misa.mxl" to be zero (invalid).
+ */
+ LOG_TARGET_WARNING(target, "Detected DXLEN (%u) does not match "
+ "MXLEN: misa.mxl == 0, misa == 0x%" PRIx64 ".",
+ dxlen, r->misa);
+ return ERROR_OK;
+ }
+ const unsigned int mxlen = mxl_to_xlen(mxl);
+ if (dxlen < mxlen) {
+ LOG_TARGET_ERROR(target,
+ "MXLEN (%u) reported in misa.mxl field exceeds "
+ "the detected DXLEN (%u)",
+ mxlen, dxlen);
+ return ERROR_FAIL;
+ }
+ /* NOTE:
+ * The value of "misa.mxl" may stil not coincide with "xlen".
+ * "misa[26:XLEN-3]" bits are marked as WIRI in at least version 1.10
+ * of RISC-V Priveleged Spec. Therefore, if "xlen" is erroneously
+ * assumed to be 32 when it actually is 64, "mxl" will be read from
+ * this WIRI field and may be equal to "MISA_MXL_32" by coincidence.
+ * This is not an issue though from the version 1.11 onward, since
+ * "misa[26:XLEN-3]" became WARL and equal to 0.
+ */
+
+ /* Display this as early as possible to help people who are using
+ * really slow simulators. */
+ LOG_TARGET_DEBUG(target, " XLEN=%d, misa=0x%" PRIx64, riscv_xlen(target), r->misa);
+ return ERROR_OK;
+}
+
+static int examine_misa(struct target *target)
+{
+ RISCV_INFO(r);
+
+ int res = init_cache_entry(target, GDB_REGNO_MISA);
+ if (res != ERROR_OK)
+ return res;
+
+ res = riscv_reg_get(target, &r->misa, GDB_REGNO_MISA);
+ if (res != ERROR_OK)
+ return res;
+ return check_misa_mxl(target);
+}
+
+static int examine_mtopi(struct target *target)
+{
+ RISCV_INFO(r);
+
+ /* Assume the registers exist */
+ r->mtopi_readable = true;
+ r->mtopei_readable = true;
+
+ int res = assume_reg_exist(target, GDB_REGNO_MTOPI);
+ if (res != ERROR_OK)
+ return res;
+ res = assume_reg_exist(target, GDB_REGNO_MTOPEI);
+ if (res != ERROR_OK)
+ return res;
+
+ riscv_reg_t value;
+ if (riscv_reg_get(target, &value, GDB_REGNO_MTOPI) != ERROR_OK) {
+ r->mtopi_readable = false;
+ r->mtopei_readable = false;
+ } else if (riscv_reg_get(target, &value, GDB_REGNO_MTOPEI) != ERROR_OK) {
+ LOG_TARGET_INFO(target, "S?aia detected without IMSIC");
+ r->mtopei_readable = false;
+ } else {
+ LOG_TARGET_INFO(target, "S?aia detected with IMSIC");
+ }
+ res = riscv_reg_impl_set_exist(target, GDB_REGNO_MTOPI, r->mtopi_readable);
+ if (res != ERROR_OK)
+ return res;
+
+ return riscv_reg_impl_set_exist(target, GDB_REGNO_MTOPEI, r->mtopei_readable);
+}
+
+/**
+ * This function assumes target's DM to be initialized (target is able to
+ * access DMs registers, execute program buffer, etc.)
+ */
+int riscv013_reg_examine_all(struct target *target)
+{
+ int res = riscv_reg_impl_init_cache(target);
+ if (res != ERROR_OK)
+ return res;
init_shared_reg_info(target);
+ assert(target->state == TARGET_HALTED);
+
+ res = examine_xlen(target);
+ if (res != ERROR_OK)
+ return res;
+
+ /* Reading CSRs may clobber "s0", "s1", so it should be possible to
+ * save them in cache. */
+ res = init_cache_entry(target, GDB_REGNO_S0);
+ if (res != ERROR_OK)
+ return res;
+ res = init_cache_entry(target, GDB_REGNO_S1);
+ if (res != ERROR_OK)
+ return res;
+
+ res = examine_misa(target);
+ if (res != ERROR_OK)
+ return res;
+
+ res = examine_vlenb(target);
+ if (res != ERROR_OK)
+ return res;
+
riscv_reg_impl_init_vector_reg_type(target);
- for (uint32_t regno = 0; regno < target->reg_cache->num_regs; ++regno)
- if (riscv013_init_reg(target, regno) != ERROR_OK)
- return ERROR_FAIL;
+ res = examine_mtopi(target);
+ if (res != ERROR_OK)
+ return res;
- if (riscv_reg_impl_expose_csrs(target) != ERROR_OK)
- return ERROR_FAIL;
+ for (uint32_t regno = 0; regno < target->reg_cache->num_regs; ++regno) {
+ res = init_cache_entry(target, regno);
+ if (res != ERROR_OK)
+ return res;
+ }
+
+ res = riscv_reg_impl_expose_csrs(target);
+ if (res != ERROR_OK)
+ return res;
riscv_reg_impl_hide_csrs(target);
diff --git a/src/target/riscv/riscv-013_reg.h b/src/target/riscv/riscv-013_reg.h
index e7a9447..e542a35 100644
--- a/src/target/riscv/riscv-013_reg.h
+++ b/src/target/riscv/riscv-013_reg.h
@@ -13,10 +13,11 @@
*/
/**
- * Init initialize register cache. After this function all registers can be
- * safely accessed via functions described here and in `riscv_reg.h`.
+ * This function assumes target is halted.
+ * After this function all registers can be safely accessed via functions
+ * described here and in `riscv_reg.h`.
*/
-int riscv013_reg_init_all(struct target *target);
+int riscv013_reg_examine_all(struct target *target);
/**
* This function is used to save the value of a register in cache. The register
diff --git a/src/target/riscv/riscv.c b/src/target/riscv/riscv.c
index 9c4796d..a8d0ef8 100644
--- a/src/target/riscv/riscv.c
+++ b/src/target/riscv/riscv.c
@@ -54,7 +54,8 @@ struct scan_field select_idcode = {
};
static bscan_tunnel_type_t bscan_tunnel_type;
-int bscan_tunnel_ir_width; /* if zero, then tunneling is not present/active */
+#define BSCAN_TUNNEL_IR_WIDTH_NBITS 7
+uint8_t bscan_tunnel_ir_width; /* if zero, then tunneling is not present/active */
static int bscan_tunnel_ir_id; /* IR ID of the JTAG TAP to access the tunnel. Valid when not 0 */
static const uint8_t bscan_zero[4] = {0};
@@ -67,7 +68,6 @@ static struct scan_field select_user4 = {
};
-static uint8_t bscan_tunneled_ir_width[4] = {5}; /* overridden by assignment in riscv_init_target */
static struct scan_field _bscan_tunnel_data_register_select_dmi[] = {
{
.num_bits = 3,
@@ -80,8 +80,8 @@ static struct scan_field _bscan_tunnel_data_register_select_dmi[] = {
.in_value = NULL,
},
{
- .num_bits = 7,
- .out_value = bscan_tunneled_ir_width,
+ .num_bits = BSCAN_TUNNEL_IR_WIDTH_NBITS,
+ .out_value = &bscan_tunnel_ir_width,
.in_value = NULL,
},
{
@@ -98,8 +98,8 @@ static struct scan_field _bscan_tunnel_nested_tap_select_dmi[] = {
.in_value = NULL,
},
{
- .num_bits = 7,
- .out_value = bscan_tunneled_ir_width,
+ .num_bits = BSCAN_TUNNEL_IR_WIDTH_NBITS,
+ .out_value = &bscan_tunnel_ir_width,
.in_value = NULL,
},
{
@@ -140,10 +140,15 @@ struct tdata1_cache {
};
/* Wall-clock timeout for a command/access. Settable via RISC-V Target commands.*/
-int riscv_command_timeout_sec = DEFAULT_COMMAND_TIMEOUT_SEC;
+static int riscv_command_timeout_sec_value = DEFAULT_COMMAND_TIMEOUT_SEC;
-/* Wall-clock timeout after reset. Settable via RISC-V Target commands.*/
-int riscv_reset_timeout_sec = DEFAULT_RESET_TIMEOUT_SEC;
+/* DEPRECATED Wall-clock timeout after reset. Settable via RISC-V Target commands.*/
+static int riscv_reset_timeout_sec = DEFAULT_COMMAND_TIMEOUT_SEC;
+
+int riscv_get_command_timeout_sec(void)
+{
+ return MAX(riscv_command_timeout_sec_value, riscv_reset_timeout_sec);
+}
static bool riscv_enable_virt2phys = true;
@@ -295,7 +300,6 @@ void select_dmi_via_bscan(struct target *target)
int dtmcontrol_scan_via_bscan(struct target *target, uint32_t out, uint32_t *in_ptr)
{
/* On BSCAN TAP: Select IR=USER4, issue tunneled IR scan via BSCAN TAP's DR */
- uint8_t tunneled_ir_width[4] = {bscan_tunnel_ir_width};
uint8_t tunneled_dr_width[4] = {32};
uint8_t out_value[5] = {0};
uint8_t in_value[5] = {0};
@@ -311,8 +315,8 @@ int dtmcontrol_scan_via_bscan(struct target *target, uint32_t out, uint32_t *in_
tunneled_ir[1].num_bits = bscan_tunnel_ir_width;
tunneled_ir[1].out_value = ir_dtmcontrol;
tunneled_ir[1].in_value = NULL;
- tunneled_ir[2].num_bits = 7;
- tunneled_ir[2].out_value = tunneled_ir_width;
+ tunneled_ir[2].num_bits = BSCAN_TUNNEL_IR_WIDTH_NBITS;
+ tunneled_ir[2].out_value = &bscan_tunnel_ir_width;
tunneled_ir[2].in_value = NULL;
tunneled_ir[3].num_bits = 1;
tunneled_ir[3].out_value = bscan_zero;
@@ -324,7 +328,7 @@ int dtmcontrol_scan_via_bscan(struct target *target, uint32_t out, uint32_t *in_
tunneled_dr[1].num_bits = 32 + 1;
tunneled_dr[1].out_value = out_value;
tunneled_dr[1].in_value = in_value;
- tunneled_dr[2].num_bits = 7;
+ tunneled_dr[2].num_bits = BSCAN_TUNNEL_IR_WIDTH_NBITS;
tunneled_dr[2].out_value = tunneled_dr_width;
tunneled_dr[2].in_value = NULL;
tunneled_dr[3].num_bits = 1;
@@ -338,8 +342,8 @@ int dtmcontrol_scan_via_bscan(struct target *target, uint32_t out, uint32_t *in_
tunneled_ir[2].num_bits = bscan_tunnel_ir_width;
tunneled_ir[2].out_value = ir_dtmcontrol;
tunneled_ir[1].in_value = NULL;
- tunneled_ir[1].num_bits = 7;
- tunneled_ir[1].out_value = tunneled_ir_width;
+ tunneled_ir[1].num_bits = BSCAN_TUNNEL_IR_WIDTH_NBITS;
+ tunneled_ir[1].out_value = &bscan_tunnel_ir_width;
tunneled_ir[2].in_value = NULL;
tunneled_ir[0].num_bits = 1;
tunneled_ir[0].out_value = bscan_zero;
@@ -378,22 +382,23 @@ int dtmcontrol_scan_via_bscan(struct target *target, uint32_t out, uint32_t *in_
return ERROR_OK;
}
-static int dtmcontrol_scan(struct target *target, uint32_t out, uint32_t *in_ptr)
+/* TODO: rename "dtmcontrol"-> "dtmcs" */
+int dtmcontrol_scan(struct target *target, uint32_t out, uint32_t *in_ptr)
{
- struct scan_field field;
- uint8_t in_value[4];
- uint8_t out_value[4] = { 0 };
+ uint8_t value[4];
if (bscan_tunnel_ir_width != 0)
return dtmcontrol_scan_via_bscan(target, out, in_ptr);
- buf_set_u32(out_value, 0, 32, out);
+ buf_set_u32(value, 0, 32, out);
jtag_add_ir_scan(target->tap, &select_dtmcontrol, TAP_IDLE);
- field.num_bits = 32;
- field.out_value = out_value;
- field.in_value = in_value;
+ struct scan_field field = {
+ .num_bits = 32,
+ .out_value = value,
+ .in_value = in_ptr ? value : NULL
+ };
jtag_add_dr_scan(target->tap, 1, &field, TAP_IDLE);
/* Always return to dbus. */
@@ -401,15 +406,18 @@ static int dtmcontrol_scan(struct target *target, uint32_t out, uint32_t *in_ptr
int retval = jtag_execute_queue();
if (retval != ERROR_OK) {
- LOG_TARGET_ERROR(target, "dtmcontrol scan failed, error code = %d", retval);
+ LOG_TARGET_ERROR(target, "dtmcs scan failed, error code = %d", retval);
return retval;
}
- uint32_t in = buf_get_u32(field.in_value, 0, 32);
- LOG_DEBUG("DTMCONTROL: 0x%x -> 0x%x", out, in);
-
- if (in_ptr)
+ if (in_ptr) {
+ assert(field.in_value);
+ uint32_t in = buf_get_u32(field.in_value, 0, 32);
+ LOG_TARGET_DEBUG(target, "DTMCS: 0x%" PRIx32 " -> 0x%" PRIx32, out, in);
*in_ptr = in;
+ } else {
+ LOG_TARGET_DEBUG(target, "DTMCS: 0x%" PRIx32 " -> ?", out);
+ }
return ERROR_OK;
}
@@ -468,7 +476,6 @@ static int riscv_init_target(struct command_context *cmd_ctx,
}
h_u32_to_le(ir_user4, ir_user4_raw);
select_user4.num_bits = target->tap->ir_length;
- bscan_tunneled_ir_width[0] = bscan_tunnel_ir_width;
if (bscan_tunnel_type == BSCAN_TUNNEL_DATA_REGISTER)
bscan_tunnel_data_register_select_dmi[1].num_bits = bscan_tunnel_ir_width;
else /* BSCAN_TUNNEL_NESTED_TAP */
@@ -522,6 +529,8 @@ static void riscv_deinit_target(struct target *target)
if (!info)
return;
+ free(info->reserved_triggers);
+
range_list_t *entry, *tmp;
list_for_each_entry_safe(entry, tmp, &info->hide_csr, list) {
free(entry->name);
@@ -612,9 +621,27 @@ static int find_first_trigger_by_id(struct target *target, int unique_id)
return -1;
}
-static int set_trigger(struct target *target, unsigned int idx, riscv_reg_t tdata1, riscv_reg_t tdata2,
- riscv_reg_t tdata1_ignore_mask)
+static unsigned int count_trailing_ones(riscv_reg_t reg)
+{
+ assert(sizeof(riscv_reg_t) * 8 == 64);
+ for (unsigned int i = 0; i < 64; i++) {
+ if ((1 & (reg >> i)) == 0)
+ return i;
+ }
+ return 64;
+}
+
+static int set_trigger(struct target *target, unsigned int idx, riscv_reg_t tdata1, riscv_reg_t tdata2)
{
+ RISCV_INFO(r);
+ assert(r->reserved_triggers);
+ assert(idx < r->trigger_count);
+ if (r->reserved_triggers[idx]) {
+ LOG_TARGET_DEBUG(target,
+ "Trigger %u is reserved by 'reserve_trigger' command.", idx);
+ return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
+ }
+
riscv_reg_t tdata1_rb, tdata2_rb;
// Select which trigger to use
if (riscv_reg_set(target, GDB_REGNO_TSELECT, idx) != ERROR_OK)
@@ -637,20 +664,51 @@ static int set_trigger(struct target *target, unsigned int idx, riscv_reg_t tdat
return ERROR_FAIL;
if (riscv_reg_get(target, &tdata2_rb, GDB_REGNO_TDATA2) != ERROR_OK)
return ERROR_FAIL;
- bool tdata1_config_denied = (tdata1 & ~tdata1_ignore_mask) != (tdata1_rb & ~tdata1_ignore_mask);
- bool tdata2_config_denied = tdata2 != tdata2_rb;
- if (tdata1_config_denied || tdata2_config_denied) {
+
+ const uint32_t type = get_field(tdata1, CSR_TDATA1_TYPE(riscv_xlen(target)));
+ const bool is_mcontrol = type == CSR_TDATA1_TYPE_MCONTROL;
+
+ /* Determine if tdata1 supports what we need.
+ * For mcontrol triggers, we don't care about
+ * the value in the read-only "maskmax" field.
+ */
+ const riscv_reg_t tdata1_ignore_mask = is_mcontrol ? CSR_MCONTROL_MASKMAX(riscv_xlen(target)) : 0;
+ const bool tdata1_config_denied = (tdata1 & ~tdata1_ignore_mask) != (tdata1_rb & ~tdata1_ignore_mask);
+
+ /* Determine if tdata1.maxmask is sufficient
+ * (only relevant for mcontrol triggers and NAPOT match type)
+ */
+ bool unsupported_napot_range = false;
+ riscv_reg_t maskmax_value = 0;
+ if (!tdata1_config_denied) {
+ const bool is_napot_match = get_field(tdata1_rb, CSR_MCONTROL_MATCH) == CSR_MCONTROL_MATCH_NAPOT;
+ if (is_mcontrol && is_napot_match) {
+ maskmax_value = get_field(tdata1_rb, CSR_MCONTROL_MASKMAX(riscv_xlen(target)));
+ const unsigned int napot_size = count_trailing_ones(tdata2) + 1;
+ if (maskmax_value < napot_size)
+ unsupported_napot_range = true;
+ }
+ }
+
+ const bool tdata2_config_denied = tdata2 != tdata2_rb;
+ if (tdata1_config_denied || tdata2_config_denied || unsupported_napot_range) {
LOG_TARGET_DEBUG(target, "Trigger %u doesn't support what we need.", idx);
if (tdata1_config_denied)
LOG_TARGET_DEBUG(target,
- "After writing 0x%" PRIx64 " to tdata1 it contains 0x%" PRIx64 "; tdata1_ignore_mask=0x%" PRIx64,
- tdata1, tdata1_rb, tdata1_ignore_mask);
+ "After writing 0x%" PRIx64 " to tdata1 it contains 0x%" PRIx64,
+ tdata1, tdata1_rb);
if (tdata2_config_denied)
LOG_TARGET_DEBUG(target,
- "wrote 0x%" PRIx64 " to tdata2 but read back 0x%" PRIx64,
+ "After writing 0x%" PRIx64 " to tdata2 it contains 0x%" PRIx64,
tdata2, tdata2_rb);
+
+ if (unsupported_napot_range)
+ LOG_TARGET_DEBUG(target,
+ "The requested NAPOT match range (tdata2=0x%" PRIx64 ") exceeds maskmax_value=0x%" PRIx64,
+ tdata2, maskmax_value);
+
if (riscv_reg_set(target, GDB_REGNO_TDATA1, 0) != ERROR_OK)
return ERROR_FAIL;
return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
@@ -699,7 +757,7 @@ static int maybe_add_trigger_t1(struct target *target, struct trigger *trigger)
tdata1 = set_field(tdata1, bpcontrol_bpaction, 0); /* cause bp exception */
tdata1 = set_field(tdata1, bpcontrol_bpmatch, 0); /* exact match */
tdata2 = trigger->address;
- ret = set_trigger(target, idx, tdata1, tdata2, 0);
+ ret = set_trigger(target, idx, tdata1, tdata2);
if (ret != ERROR_OK)
return ret;
r->trigger_unique_id[idx] = trigger->unique_id;
@@ -709,13 +767,11 @@ static int maybe_add_trigger_t1(struct target *target, struct trigger *trigger)
struct trigger_request_info {
riscv_reg_t tdata1;
riscv_reg_t tdata2;
- riscv_reg_t tdata1_ignore_mask;
};
static void log_trigger_request_info(struct trigger_request_info trig_info)
{
- LOG_DEBUG("tdata1=%" PRIx64 ", tdata2=%" PRIx64 ", tdata1_ignore_mask=%" PRIx64,
- trig_info.tdata1, trig_info.tdata2, trig_info.tdata1_ignore_mask);
+ LOG_DEBUG("tdata1=%" PRIx64 ", tdata2=%" PRIx64, trig_info.tdata1, trig_info.tdata2);
};
static struct tdata1_cache *tdata1_cache_alloc(struct list_head *tdata1_cache_head, riscv_reg_t tdata1)
@@ -798,12 +854,12 @@ static bool wp_triggers_cache_search(struct target *target, unsigned int idx,
}
static int try_use_trigger_and_cache_result(struct target *target, unsigned int idx, riscv_reg_t tdata1,
- riscv_reg_t tdata2, riscv_reg_t tdata1_ignore_mask)
+ riscv_reg_t tdata2)
{
if (wp_triggers_cache_search(target, idx, tdata1, tdata2))
return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
- int ret = set_trigger(target, idx, tdata1, tdata2, tdata1_ignore_mask);
+ int ret = set_trigger(target, idx, tdata1, tdata2);
/* Add these values to the cache to remember that they are not supported. */
if (ret == ERROR_TARGET_RESOURCE_NOT_AVAILABLE)
@@ -826,8 +882,7 @@ static int try_setup_single_match_trigger(struct target *target,
for (unsigned int idx = 0;
find_next_free_trigger(target, trigger_type, false, &idx) == ERROR_OK;
++idx) {
- ret = try_use_trigger_and_cache_result(target, idx, trig_info.tdata1, trig_info.tdata2,
- trig_info.tdata1_ignore_mask);
+ ret = try_use_trigger_and_cache_result(target, idx, trig_info.tdata1, trig_info.tdata2);
if (ret == ERROR_OK) {
r->trigger_unique_id[idx] = trigger->unique_id;
@@ -855,16 +910,14 @@ static int try_setup_chained_match_triggers(struct target *target,
for (unsigned int idx = 0;
find_next_free_trigger(target, trigger_type, true, &idx) == ERROR_OK;
++idx) {
- ret = try_use_trigger_and_cache_result(target, idx, t1.tdata1, t1.tdata2,
- t1.tdata1_ignore_mask);
+ ret = try_use_trigger_and_cache_result(target, idx, t1.tdata1, t1.tdata2);
if (ret == ERROR_TARGET_RESOURCE_NOT_AVAILABLE)
continue;
else if (ret != ERROR_OK)
return ret;
- ret = try_use_trigger_and_cache_result(target, idx + 1, t2.tdata1, t2.tdata2,
- t2.tdata1_ignore_mask);
+ ret = try_use_trigger_and_cache_result(target, idx + 1, t2.tdata1, t2.tdata2);
if (ret == ERROR_OK) {
r->trigger_unique_id[idx] = trigger->unique_id;
@@ -872,7 +925,7 @@ static int try_setup_chained_match_triggers(struct target *target,
return ERROR_OK;
}
/* Undo the setting of the previous trigger */
- int ret_undo = set_trigger(target, idx, 0, 0, 0);
+ int ret_undo = set_trigger(target, idx, 0, 0);
if (ret_undo != ERROR_OK)
return ret_undo;
@@ -900,7 +953,6 @@ struct match_triggers_tdata1_fields {
riscv_reg_t ge;
riscv_reg_t eq;
} match;
- riscv_reg_t tdata1_ignore_mask;
};
static struct match_triggers_tdata1_fields fill_match_triggers_tdata1_fields_t2(struct target *target,
@@ -933,8 +985,7 @@ static struct match_triggers_tdata1_fields fill_match_triggers_tdata1_fields_t2(
.lt = field_value(CSR_MCONTROL_MATCH, CSR_MCONTROL_MATCH_LT),
.ge = field_value(CSR_MCONTROL_MATCH, CSR_MCONTROL_MATCH_GE),
.eq = field_value(CSR_MCONTROL_MATCH, CSR_MCONTROL_MATCH_EQUAL)
- },
- .tdata1_ignore_mask = CSR_MCONTROL_MASKMAX(riscv_xlen(target))
+ }
};
return result;
}
@@ -971,8 +1022,7 @@ static struct match_triggers_tdata1_fields fill_match_triggers_tdata1_fields_t6(
.lt = field_value(CSR_MCONTROL6_MATCH, CSR_MCONTROL6_MATCH_LT),
.ge = field_value(CSR_MCONTROL6_MATCH, CSR_MCONTROL6_MATCH_GE),
.eq = field_value(CSR_MCONTROL6_MATCH, CSR_MCONTROL6_MATCH_EQUAL)
- },
- .tdata1_ignore_mask = 0
+ }
};
return result;
}
@@ -991,8 +1041,7 @@ static int maybe_add_trigger_t2_t6_for_wp(struct target *target,
struct trigger_request_info napot = {
.tdata1 = fields.common | fields.size.any |
fields.chain.disable | fields.match.napot,
- .tdata2 = trigger->address | ((trigger->length - 1) >> 1),
- .tdata1_ignore_mask = fields.tdata1_ignore_mask
+ .tdata2 = trigger->address | ((trigger->length - 1) >> 1)
};
ret = try_setup_single_match_trigger(target, trigger, napot);
if (ret != ERROR_TARGET_RESOURCE_NOT_AVAILABLE)
@@ -1008,14 +1057,12 @@ static int maybe_add_trigger_t2_t6_for_wp(struct target *target,
struct trigger_request_info ge_1 = {
.tdata1 = fields.common | fields.size.any | fields.chain.enable |
fields.match.ge,
- .tdata2 = trigger->address,
- .tdata1_ignore_mask = fields.tdata1_ignore_mask
+ .tdata2 = trigger->address
};
struct trigger_request_info lt_2 = {
.tdata1 = fields.common | fields.size.any | fields.chain.disable |
fields.match.lt,
- .tdata2 = trigger->address + trigger->length,
- .tdata1_ignore_mask = fields.tdata1_ignore_mask
+ .tdata2 = trigger->address + trigger->length
};
ret = try_setup_chained_match_triggers(target, trigger, ge_1, lt_2);
if (ret != ERROR_TARGET_RESOURCE_NOT_AVAILABLE)
@@ -1025,14 +1072,12 @@ static int maybe_add_trigger_t2_t6_for_wp(struct target *target,
struct trigger_request_info lt_1 = {
.tdata1 = fields.common | fields.size.any | fields.chain.enable |
fields.match.lt,
- .tdata2 = trigger->address + trigger->length,
- .tdata1_ignore_mask = fields.tdata1_ignore_mask
+ .tdata2 = trigger->address + trigger->length
};
struct trigger_request_info ge_2 = {
.tdata1 = fields.common | fields.size.any | fields.chain.disable |
fields.match.ge,
- .tdata2 = trigger->address,
- .tdata1_ignore_mask = fields.tdata1_ignore_mask
+ .tdata2 = trigger->address
};
ret = try_setup_chained_match_triggers(target, trigger, lt_1, ge_2);
if (ret != ERROR_TARGET_RESOURCE_NOT_AVAILABLE)
@@ -1048,8 +1093,7 @@ static int maybe_add_trigger_t2_t6_for_wp(struct target *target,
struct trigger_request_info eq = {
.tdata1 = fields.common | fields.size.any | fields.chain.disable |
fields.match.eq,
- .tdata2 = trigger->address,
- .tdata1_ignore_mask = fields.tdata1_ignore_mask
+ .tdata2 = trigger->address
};
ret = try_setup_single_match_trigger(target, trigger, eq);
if (ret != ERROR_OK)
@@ -1086,8 +1130,7 @@ static int maybe_add_trigger_t2_t6_for_bp(struct target *target,
struct trigger_request_info eq = {
.tdata1 = fields.common | fields.size.any | fields.chain.disable |
fields.match.eq,
- .tdata2 = trigger->address,
- .tdata1_ignore_mask = fields.tdata1_ignore_mask
+ .tdata2 = trigger->address
};
return try_setup_single_match_trigger(target, trigger, eq);
@@ -1130,7 +1173,7 @@ static int maybe_add_trigger_t3(struct target *target, bool vs, bool vu,
ret = find_next_free_trigger(target, CSR_TDATA1_TYPE_ICOUNT, false, &idx);
if (ret != ERROR_OK)
return ret;
- ret = set_trigger(target, idx, tdata1, 0, 0);
+ ret = set_trigger(target, idx, tdata1, 0);
if (ret != ERROR_OK)
return ret;
r->trigger_unique_id[idx] = unique_id;
@@ -1163,7 +1206,7 @@ static int maybe_add_trigger_t4(struct target *target, bool vs, bool vu,
ret = find_next_free_trigger(target, CSR_TDATA1_TYPE_ITRIGGER, false, &idx);
if (ret != ERROR_OK)
return ret;
- ret = set_trigger(target, idx, tdata1, tdata2, 0);
+ ret = set_trigger(target, idx, tdata1, tdata2);
if (ret != ERROR_OK)
return ret;
r->trigger_unique_id[idx] = unique_id;
@@ -1195,7 +1238,7 @@ static int maybe_add_trigger_t5(struct target *target, bool vs, bool vu,
ret = find_next_free_trigger(target, CSR_TDATA1_TYPE_ETRIGGER, false, &idx);
if (ret != ERROR_OK)
return ret;
- ret = set_trigger(target, idx, tdata1, tdata2, 0);
+ ret = set_trigger(target, idx, tdata1, tdata2);
if (ret != ERROR_OK)
return ret;
r->trigger_unique_id[idx] = unique_id;
@@ -2448,87 +2491,48 @@ static int riscv_deassert_reset(struct target *target)
return tt->deassert_reset(target);
}
-/* state must be riscv_reg_t state[RISCV_MAX_HWBPS] = {0}; */
-static int disable_triggers(struct target *target, riscv_reg_t *state)
+/* "wp_is_set" array must have at least "r->trigger_count" items. */
+static int disable_watchpoints(struct target *target, bool *wp_is_set)
{
RISCV_INFO(r);
-
LOG_TARGET_DEBUG(target, "Disabling triggers.");
- if (riscv_enumerate_triggers(target) != ERROR_OK)
- return ERROR_FAIL;
-
- if (r->manual_hwbp_set) {
- /* Look at every trigger that may have been set. */
- riscv_reg_t tselect;
- if (riscv_reg_get(target, &tselect, GDB_REGNO_TSELECT) != ERROR_OK)
- return ERROR_FAIL;
- for (unsigned int t = 0; t < r->trigger_count; t++) {
- if (riscv_reg_set(target, GDB_REGNO_TSELECT, t) != ERROR_OK)
- return ERROR_FAIL;
- riscv_reg_t tdata1;
- if (riscv_reg_get(target, &tdata1, GDB_REGNO_TDATA1) != ERROR_OK)
+ /* TODO: The algorithm is flawed and may result in a situation described in
+ * https://github.com/riscv-collab/riscv-openocd/issues/1108
+ */
+ memset(wp_is_set, false, r->trigger_count);
+ struct watchpoint *watchpoint = target->watchpoints;
+ int i = 0;
+ while (watchpoint) {
+ LOG_TARGET_DEBUG(target, "Watchpoint %" PRIu32 ": set=%s",
+ watchpoint->unique_id,
+ wp_is_set[i] ? "true" : "false");
+ wp_is_set[i] = watchpoint->is_set;
+ if (watchpoint->is_set) {
+ if (riscv_remove_watchpoint(target, watchpoint) != ERROR_OK)
return ERROR_FAIL;
- if (tdata1 & CSR_TDATA1_DMODE(riscv_xlen(target))) {
- state[t] = tdata1;
- if (riscv_reg_set(target, GDB_REGNO_TDATA1, 0) != ERROR_OK)
- return ERROR_FAIL;
- }
- }
- if (riscv_reg_set(target, GDB_REGNO_TSELECT, tselect) != ERROR_OK)
- return ERROR_FAIL;
-
- } else {
- /* Just go through the triggers we manage. */
- struct watchpoint *watchpoint = target->watchpoints;
- int i = 0;
- while (watchpoint) {
- LOG_TARGET_DEBUG(target, "Watchpoint %d: set=%d", i, watchpoint->is_set);
- state[i] = watchpoint->is_set;
- if (watchpoint->is_set) {
- if (riscv_remove_watchpoint(target, watchpoint) != ERROR_OK)
- return ERROR_FAIL;
- }
- watchpoint = watchpoint->next;
- i++;
}
+ watchpoint = watchpoint->next;
+ i++;
}
return ERROR_OK;
}
-static int enable_triggers(struct target *target, riscv_reg_t *state)
+static int enable_watchpoints(struct target *target, bool *wp_is_set)
{
- RISCV_INFO(r);
-
- if (r->manual_hwbp_set) {
- /* Look at every trigger that may have been set. */
- riscv_reg_t tselect;
- if (riscv_reg_get(target, &tselect, GDB_REGNO_TSELECT) != ERROR_OK)
- return ERROR_FAIL;
- for (unsigned int t = 0; t < r->trigger_count; t++) {
- if (state[t] != 0) {
- if (riscv_reg_set(target, GDB_REGNO_TSELECT, t) != ERROR_OK)
- return ERROR_FAIL;
- if (riscv_reg_set(target, GDB_REGNO_TDATA1, state[t]) != ERROR_OK)
- return ERROR_FAIL;
- }
- }
- if (riscv_reg_set(target, GDB_REGNO_TSELECT, tselect) != ERROR_OK)
- return ERROR_FAIL;
-
- } else {
- struct watchpoint *watchpoint = target->watchpoints;
- int i = 0;
- while (watchpoint) {
- LOG_TARGET_DEBUG(target, "Watchpoint %d: cleared=%" PRId64, i, state[i]);
- if (state[i]) {
- if (riscv_add_watchpoint(target, watchpoint) != ERROR_OK)
- return ERROR_FAIL;
- }
- watchpoint = watchpoint->next;
- i++;
+ struct watchpoint *watchpoint = target->watchpoints;
+ int i = 0;
+ while (watchpoint) {
+ LOG_TARGET_DEBUG(target, "Watchpoint %" PRIu32
+ ": %s to be re-enabled.", watchpoint->unique_id,
+ wp_is_set[i] ? "needs " : "does not need");
+ if (wp_is_set[i]) {
+ if (riscv_add_watchpoint(target, watchpoint) != ERROR_OK)
+ return ERROR_FAIL;
}
+ watchpoint = watchpoint->next;
+ i++;
}
return ERROR_OK;
@@ -3294,7 +3298,7 @@ static int riscv_run_algorithm(struct target *target, int num_mem_params,
GDB_REGNO_PC,
GDB_REGNO_MSTATUS, GDB_REGNO_MEPC, GDB_REGNO_MCAUSE,
};
- for (unsigned i = 0; i < ARRAY_SIZE(regnums); i++) {
+ for (unsigned int i = 0; i < ARRAY_SIZE(regnums); i++) {
enum gdb_regno regno = regnums[i];
riscv_reg_t reg_value;
if (riscv_reg_get(target, &reg_value, regno) != ERROR_OK)
@@ -3389,8 +3393,8 @@ static int riscv_checksum_memory(struct target *target,
static const uint8_t *crc_code;
- unsigned xlen = riscv_xlen(target);
- unsigned crc_code_size;
+ unsigned int xlen = riscv_xlen(target);
+ unsigned int crc_code_size;
if (xlen == 32) {
crc_code = riscv32_crc_code;
crc_code_size = sizeof(riscv32_crc_code);
@@ -3776,10 +3780,17 @@ static int riscv_openocd_step_impl(struct target *target, int current,
return ERROR_FAIL;
}
- riscv_reg_t trigger_state[RISCV_MAX_HWBPS] = {0};
- if (disable_triggers(target, trigger_state) != ERROR_OK)
+ if (riscv_enumerate_triggers(target) != ERROR_OK)
return ERROR_FAIL;
+ RISCV_INFO(r);
+ bool *wps_to_enable = calloc(r->trigger_count, sizeof(*wps_to_enable));
+ if (disable_watchpoints(target, wps_to_enable) != ERROR_OK) {
+ LOG_TARGET_ERROR(target, "Failed to temporarily disable "
+ "watchpoints before single-step.");
+ return ERROR_FAIL;
+ }
+
bool success = true;
uint64_t current_mstatus;
RISCV_INFO(info);
@@ -3809,9 +3820,10 @@ static int riscv_openocd_step_impl(struct target *target, int current,
}
_exit:
- if (enable_triggers(target, trigger_state) != ERROR_OK) {
+ if (enable_watchpoints(target, wps_to_enable) != ERROR_OK) {
success = false;
- LOG_TARGET_ERROR(target, "Unable to enable triggers.");
+ LOG_TARGET_ERROR(target, "Failed to re-enable watchpoints "
+ "after single-step.");
}
if (breakpoint && (riscv_add_breakpoint(target, breakpoint) != ERROR_OK)) {
@@ -3853,13 +3865,14 @@ COMMAND_HANDLER(riscv_set_command_timeout_sec)
return ERROR_FAIL;
}
- riscv_command_timeout_sec = timeout;
+ riscv_command_timeout_sec_value = timeout;
return ERROR_OK;
}
COMMAND_HANDLER(riscv_set_reset_timeout_sec)
{
+ LOG_WARNING("The command 'riscv set_reset_timeout_sec' is deprecated! Please, use 'riscv set_command_timeout_sec'.");
if (CMD_ARGC != 1) {
LOG_ERROR("Command takes exactly 1 parameter.");
return ERROR_COMMAND_SYNTAX_ERROR;
@@ -3882,9 +3895,10 @@ COMMAND_HANDLER(riscv_set_mem_access)
int sysbus_cnt = 0;
int abstract_cnt = 0;
- if (CMD_ARGC < 1 || CMD_ARGC > RISCV_NUM_MEM_ACCESS_METHODS) {
- LOG_ERROR("Command takes 1 to %d parameters", RISCV_NUM_MEM_ACCESS_METHODS);
- return ERROR_COMMAND_SYNTAX_ERROR;
+ if (CMD_ARGC < 1 || CMD_ARGC > RISCV_MEM_ACCESS_MAX_METHODS_NUM) {
+ command_print(CMD, "Command takes 1 to %d parameters",
+ RISCV_MEM_ACCESS_MAX_METHODS_NUM);
+ return ERROR_COMMAND_ARGUMENT_INVALID;
}
/* Check argument validity */
@@ -3907,8 +3921,7 @@ COMMAND_HANDLER(riscv_set_mem_access)
}
/* Args are valid, store them */
- for (unsigned int i = 0; i < RISCV_NUM_MEM_ACCESS_METHODS; i++)
- r->mem_access_methods[i] = RISCV_MEM_ACCESS_UNSPECIFIED;
+ r->num_enabled_mem_access_methods = CMD_ARGC;
for (unsigned int i = 0; i < CMD_ARGC; i++) {
if (strcmp("progbuf", CMD_ARGV[i]) == 0)
r->mem_access_methods[i] = RISCV_MEM_ACCESS_PROGBUF;
@@ -3919,9 +3932,8 @@ COMMAND_HANDLER(riscv_set_mem_access)
}
/* Reset warning flags */
- r->mem_access_progbuf_warn = true;
- r->mem_access_sysbus_warn = true;
- r->mem_access_abstract_warn = true;
+ for (size_t i = 0; i < RISCV_MEM_ACCESS_MAX_METHODS_NUM; ++i)
+ r->mem_access_warn[i] = true;
return ERROR_OK;
}
@@ -3945,8 +3957,8 @@ static int parse_ranges(struct list_head *ranges, const char *tcl_arg, const cha
/* For backward compatibility, allow multiple parameters within one TCL argument, separated by ',' */
char *arg = strtok(args, ",");
while (arg) {
- unsigned low = 0;
- unsigned high = 0;
+ unsigned int low = 0;
+ unsigned int high = 0;
char *name = NULL;
char *dash = strchr(arg, '-');
@@ -4376,18 +4388,23 @@ COMMAND_HANDLER(riscv_resume_order)
COMMAND_HANDLER(riscv_use_bscan_tunnel)
{
- int irwidth = 0;
+ uint8_t irwidth = 0;
int tunnel_type = BSCAN_TUNNEL_NESTED_TAP;
- if (CMD_ARGC > 2) {
- LOG_ERROR("Command takes at most two arguments");
+ if (CMD_ARGC < 1 || CMD_ARGC > 2)
return ERROR_COMMAND_SYNTAX_ERROR;
- } else if (CMD_ARGC == 1) {
- COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], irwidth);
- } else if (CMD_ARGC == 2) {
- COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], irwidth);
- COMMAND_PARSE_NUMBER(int, CMD_ARGV[1], tunnel_type);
+
+ if (CMD_ARGC >= 1) {
+ COMMAND_PARSE_NUMBER(u8, CMD_ARGV[0], irwidth);
+ assert(BSCAN_TUNNEL_IR_WIDTH_NBITS < 8);
+ if (irwidth >= (uint8_t)1 << BSCAN_TUNNEL_IR_WIDTH_NBITS) {
+ command_print(CMD, "'value' does not fit into %d bits.",
+ BSCAN_TUNNEL_IR_WIDTH_NBITS);
+ return ERROR_COMMAND_ARGUMENT_OVERFLOW;
+ }
}
+ if (CMD_ARGC == 2)
+ COMMAND_PARSE_NUMBER(int, CMD_ARGV[1], tunnel_type);
if (tunnel_type == BSCAN_TUNNEL_NESTED_TAP)
LOG_INFO("Nested Tap based Bscan Tunnel Selected");
else if (tunnel_type == BSCAN_TUNNEL_DATA_REGISTER)
@@ -5025,6 +5042,57 @@ COMMAND_HANDLER(riscv_set_enable_trigger_feature)
return ERROR_OK;
}
+static COMMAND_HELPER(report_reserved_triggers, struct target *target)
+{
+ RISCV_INFO(r);
+ if (riscv_enumerate_triggers(target) != ERROR_OK)
+ return ERROR_FAIL;
+ const char *separator = "";
+ for (riscv_reg_t t = 0; t < r->trigger_count; ++t) {
+ if (r->reserved_triggers[t]) {
+ command_print_sameline(CMD, "%s%" PRIu64, separator, t);
+ separator = " ";
+ }
+ }
+ command_print_sameline(CMD, "\n");
+ return ERROR_OK;
+}
+
+COMMAND_HANDLER(handle_reserve_trigger)
+{
+ struct target *target = get_current_target(CMD_CTX);
+ if (CMD_ARGC == 0)
+ return CALL_COMMAND_HANDLER(report_reserved_triggers, target);
+
+ if (CMD_ARGC != 2)
+ return ERROR_COMMAND_SYNTAX_ERROR;
+
+ riscv_reg_t t;
+ COMMAND_PARSE_NUMBER(u64, CMD_ARGV[0], t);
+
+ if (riscv_enumerate_triggers(target) != ERROR_OK)
+ return ERROR_FAIL;
+ RISCV_INFO(r);
+ if (r->trigger_count == 0) {
+ command_print(CMD, "Error: There are no triggers on the target.");
+ return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
+ }
+ if (t >= r->trigger_count) {
+ command_print(CMD, "Error: trigger with index %" PRIu64
+ " does not exist. There are only %u triggers"
+ " on the target (with indexes 0 .. %u).",
+ t, r->trigger_count, r->trigger_count - 1);
+ return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
+ }
+ if (r->trigger_unique_id[t] != -1) {
+ command_print(CMD, "Error: trigger with index %" PRIu64
+ " is already in use and can not be reserved.", t);
+ return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
+ }
+ COMMAND_PARSE_ON_OFF(CMD_ARGV[1], r->reserved_triggers[t]);
+ return ERROR_OK;
+}
+
static const struct command_registration riscv_exec_command_handlers[] = {
{
.name = "dump_sample_buf",
@@ -5066,7 +5134,7 @@ static const struct command_registration riscv_exec_command_handlers[] = {
.handler = riscv_set_reset_timeout_sec,
.mode = COMMAND_ANY,
.usage = "[sec]",
- .help = "Set the wall-clock timeout (in seconds) after reset is deasserted"
+ .help = "DEPRECATED. Use 'riscv set_command_timeout_sec' instead."
},
{
.name = "set_mem_access",
@@ -5189,18 +5257,14 @@ static const struct command_registration riscv_exec_command_handlers[] = {
{
.name = "use_bscan_tunnel",
.handler = riscv_use_bscan_tunnel,
- .mode = COMMAND_ANY,
+ .mode = COMMAND_CONFIG,
.usage = "value [type]",
- .help = "Enable or disable use of a BSCAN tunnel to reach DM. Supply "
- "the width of the DM transport TAP's instruction register to "
- "enable. Supply a value of 0 to disable. Pass A second argument "
- "(optional) to indicate Bscan Tunnel Type {0:(default) NESTED_TAP , "
- "1: DATA_REGISTER}"
+ .help = "Enable or disable use of a BSCAN tunnel to reach DM."
},
{
.name = "set_bscan_tunnel_ir",
.handler = riscv_set_bscan_tunnel_ir,
- .mode = COMMAND_ANY,
+ .mode = COMMAND_CONFIG,
.usage = "value",
.help = "Specify the JTAG TAP IR used to access the bscan tunnel. "
"By default it is 0x23 << (ir_length - 6), which map some "
@@ -5281,6 +5345,14 @@ static const struct command_registration riscv_exec_command_handlers[] = {
.usage = "[('eq'|'napot'|'ge_lt'|'all') ('wp'|'none')]",
.help = "Control whether OpenOCD is allowed to use certain RISC-V trigger features for watchpoints."
},
+ {
+ .name = "reserve_trigger",
+ .handler = handle_reserve_trigger,
+ /* TODO: Move this to COMMAND_ANY */
+ .mode = COMMAND_EXEC,
+ .usage = "[index ('on'|'off')]",
+ .help = "Controls which RISC-V triggers shall not be touched by OpenOCD.",
+ },
COMMAND_REGISTRATION_DONE
};
@@ -5403,9 +5475,9 @@ static void riscv_info_init(struct target *target, struct riscv_info *r)
r->mem_access_methods[1] = RISCV_MEM_ACCESS_SYSBUS;
r->mem_access_methods[2] = RISCV_MEM_ACCESS_ABSTRACT;
- r->mem_access_progbuf_warn = true;
- r->mem_access_sysbus_warn = true;
- r->mem_access_abstract_warn = true;
+ r->num_enabled_mem_access_methods = RISCV_MEM_ACCESS_MAX_METHODS_NUM;
+ for (size_t i = 0; i < RISCV_MEM_ACCESS_MAX_METHODS_NUM; ++i)
+ r->mem_access_warn[i] = true;
INIT_LIST_HEAD(&r->expose_csr);
INIT_LIST_HEAD(&r->expose_custom);
@@ -5506,7 +5578,7 @@ static int riscv_step_rtos_hart(struct target *target)
bool riscv_supports_extension(const struct target *target, char letter)
{
RISCV_INFO(r);
- unsigned num;
+ unsigned int num;
if (letter >= 'a' && letter <= 'z')
num = letter - 'a';
else if (letter >= 'A' && letter <= 'Z')
@@ -5516,7 +5588,7 @@ bool riscv_supports_extension(const struct target *target, char letter)
return r->misa & BIT(num);
}
-unsigned riscv_xlen(const struct target *target)
+unsigned int riscv_xlen(const struct target *target)
{
RISCV_INFO(r);
return r->xlen;
@@ -5559,7 +5631,7 @@ static enum riscv_halt_reason riscv_halt_reason(struct target *target)
size_t riscv_progbuf_size(struct target *target)
{
RISCV_INFO(r);
- return r->progbuf_size;
+ return r->get_progbufsize(target);
}
int riscv_write_progbuf(struct target *target, int index, riscv_insn_t insn)
@@ -5581,16 +5653,16 @@ int riscv_execute_progbuf(struct target *target, uint32_t *cmderr)
return r->execute_progbuf(target, cmderr);
}
-void riscv_fill_dm_write(struct target *target, char *buf, uint64_t a, uint32_t d)
+void riscv_fill_dmi_write(struct target *target, char *buf, uint64_t a, uint32_t d)
{
RISCV_INFO(r);
- r->fill_dm_write(target, buf, a, d);
+ r->fill_dmi_write(target, buf, a, d);
}
-void riscv_fill_dm_read(struct target *target, char *buf, uint64_t a)
+void riscv_fill_dmi_read(struct target *target, char *buf, uint64_t a)
{
RISCV_INFO(r);
- r->fill_dm_read(target, buf, a);
+ r->fill_dmi_read(target, buf, a);
}
void riscv_fill_dm_nop(struct target *target, char *buf)
@@ -5705,6 +5777,8 @@ int riscv_enumerate_triggers(struct target *target)
"Assuming that triggers are not implemented.");
r->triggers_enumerated = true;
r->trigger_count = 0;
+ free(r->reserved_triggers);
+ r->reserved_triggers = NULL;
return ERROR_OK;
}
@@ -5739,6 +5813,8 @@ int riscv_enumerate_triggers(struct target *target)
r->triggers_enumerated = true;
r->trigger_count = t;
LOG_TARGET_INFO(target, "Found %d triggers", r->trigger_count);
+ free(r->reserved_triggers);
+ r->reserved_triggers = calloc(t, sizeof(*r->reserved_triggers));
create_wp_trigger_cache(target);
return ERROR_OK;
}
diff --git a/src/target/riscv/riscv.h b/src/target/riscv/riscv.h
index c13af8e..33afdcd 100644
--- a/src/target/riscv/riscv.h
+++ b/src/target/riscv/riscv.h
@@ -22,8 +22,7 @@ struct riscv_program;
#define RISCV_MAX_HWBPS 16
#define RISCV_MAX_DMS 100
-#define DEFAULT_COMMAND_TIMEOUT_SEC 2
-#define DEFAULT_RESET_TIMEOUT_SEC 30
+#define DEFAULT_COMMAND_TIMEOUT_SEC 5
#define RISCV_SATP_MODE(xlen) ((xlen) == 32 ? SATP32_MODE : SATP64_MODE)
#define RISCV_SATP_PPN(xlen) ((xlen) == 32 ? SATP32_PPN : SATP64_PPN)
@@ -33,8 +32,6 @@ struct riscv_program;
#define PG_MAX_LEVEL 5
-#define RISCV_NUM_MEM_ACCESS_METHODS 3
-
#define RISCV_BATCH_ALLOC_SIZE 128
extern struct target_type riscv011_target;
@@ -53,12 +50,12 @@ typedef enum {
YNM_NO
} yes_no_maybe_t;
-enum riscv_mem_access_method {
- RISCV_MEM_ACCESS_UNSPECIFIED,
+typedef enum riscv_mem_access_method {
RISCV_MEM_ACCESS_PROGBUF,
RISCV_MEM_ACCESS_SYSBUS,
- RISCV_MEM_ACCESS_ABSTRACT
-};
+ RISCV_MEM_ACCESS_ABSTRACT,
+ RISCV_MEM_ACCESS_MAX_METHODS_NUM
+} riscv_mem_access_method_t;
enum riscv_halt_reason {
RISCV_HALT_INTERRUPT,
@@ -168,12 +165,6 @@ struct riscv_info {
* most recent halt was not caused by a trigger, then this is -1. */
int64_t trigger_hit;
- /* The number of entries in the program buffer. */
- int progbuf_size;
-
- /* This hart contains an implicit ebreak at the end of the program buffer. */
- bool impebreak;
-
bool triggers_enumerated;
/* Decremented every scan, and when it reaches 0 we clear the learned
@@ -227,8 +218,8 @@ struct riscv_info {
int (*execute_progbuf)(struct target *target, uint32_t *cmderr);
int (*invalidate_cached_progbuf)(struct target *target);
int (*get_dmi_scan_length)(struct target *target);
- void (*fill_dm_write)(struct target *target, char *buf, uint64_t a, uint32_t d);
- void (*fill_dm_read)(struct target *target, char *buf, uint64_t a);
+ void (*fill_dmi_write)(struct target *target, char *buf, uint64_t a, uint32_t d);
+ void (*fill_dmi_read)(struct target *target, char *buf, uint64_t a);
void (*fill_dm_nop)(struct target *target, char *buf);
int (*authdata_read)(struct target *target, uint32_t *value, unsigned int index);
@@ -237,6 +228,9 @@ struct riscv_info {
int (*dmi_read)(struct target *target, uint32_t *value, uint32_t address);
int (*dmi_write)(struct target *target, uint32_t address, uint32_t value);
+ bool (*get_impebreak)(const struct target *target);
+ unsigned int (*get_progbufsize)(const struct target *target);
+
/* Get the DMI address of target's DM's register.
* The function should return the passed address
* if the target is not assigned a DM yet.
@@ -251,7 +245,7 @@ struct riscv_info {
int (*read_memory)(struct target *target, target_addr_t address,
uint32_t size, uint32_t count, uint8_t *buffer, uint32_t increment);
- unsigned (*data_bits)(struct target *target);
+ unsigned int (*data_bits)(struct target *target);
COMMAND_HELPER((*print_info), struct target *target);
@@ -273,18 +267,16 @@ struct riscv_info {
struct reg_data_type_union vector_union;
struct reg_data_type type_vector;
- /* Set when trigger registers are changed by the user. This indicates we need
- * to beware that we may hit a trigger that we didn't realize had been set. */
- bool manual_hwbp_set;
+ bool *reserved_triggers;
/* Memory access methods to use, ordered by priority, highest to lowest. */
- int mem_access_methods[RISCV_NUM_MEM_ACCESS_METHODS];
+ riscv_mem_access_method_t mem_access_methods[RISCV_MEM_ACCESS_MAX_METHODS_NUM];
+
+ unsigned int num_enabled_mem_access_methods;
/* Different memory regions may need different methods but single configuration is applied
* for all. Following flags are used to warn only once about failing memory access method. */
- bool mem_access_progbuf_warn;
- bool mem_access_sysbus_warn;
- bool mem_access_abstract_warn;
+ bool mem_access_warn[RISCV_MEM_ACCESS_MAX_METHODS_NUM];
/* In addition to the ones in the standard spec, we'll also expose additional
* CSRs in this list. */
@@ -328,22 +320,19 @@ typedef struct {
typedef struct {
const char *name;
int level;
- unsigned va_bits;
+ unsigned int va_bits;
/* log2(PTESIZE) */
- unsigned pte_shift;
- unsigned vpn_shift[PG_MAX_LEVEL];
- unsigned vpn_mask[PG_MAX_LEVEL];
- unsigned pte_ppn_shift[PG_MAX_LEVEL];
- unsigned pte_ppn_mask[PG_MAX_LEVEL];
- unsigned pa_ppn_shift[PG_MAX_LEVEL];
- unsigned pa_ppn_mask[PG_MAX_LEVEL];
+ unsigned int pte_shift;
+ unsigned int vpn_shift[PG_MAX_LEVEL];
+ unsigned int vpn_mask[PG_MAX_LEVEL];
+ unsigned int pte_ppn_shift[PG_MAX_LEVEL];
+ unsigned int pte_ppn_mask[PG_MAX_LEVEL];
+ unsigned int pa_ppn_shift[PG_MAX_LEVEL];
+ unsigned int pa_ppn_mask[PG_MAX_LEVEL];
} virt2phys_info_t;
/* Wall-clock timeout for a command/access. Settable via RISC-V Target commands.*/
-extern int riscv_command_timeout_sec;
-
-/* Wall-clock timeout after reset. Settable via RISC-V Target commands.*/
-extern int riscv_reset_timeout_sec;
+int riscv_get_command_timeout_sec(void);
extern bool riscv_enable_virtual;
@@ -366,12 +355,13 @@ extern struct scan_field select_dtmcontrol;
extern struct scan_field select_dbus;
extern struct scan_field select_idcode;
+int dtmcontrol_scan(struct target *target, uint32_t out, uint32_t *in_ptr);
+
extern struct scan_field *bscan_tunneled_select_dmi;
extern uint32_t bscan_tunneled_select_dmi_num_fields;
typedef enum { BSCAN_TUNNEL_NESTED_TAP, BSCAN_TUNNEL_DATA_REGISTER } bscan_tunnel_type_t;
-extern int bscan_tunnel_ir_width;
+extern uint8_t bscan_tunnel_ir_width;
-int dtmcontrol_scan_via_bscan(struct target *target, uint32_t out, uint32_t *in_ptr);
void select_dmi_via_bscan(struct target *target);
/*** OpenOCD Interface */
@@ -391,7 +381,7 @@ int riscv_openocd_step(
bool riscv_supports_extension(const struct target *target, char letter);
/* Returns XLEN for the given (or current) hart. */
-unsigned riscv_xlen(const struct target *target);
+unsigned int riscv_xlen(const struct target *target);
/* Returns VLENB for the given (or current) hart. */
unsigned int riscv_vlenb(const struct target *target);
@@ -412,8 +402,8 @@ int riscv_write_progbuf(struct target *target, int index, riscv_insn_t insn);
int riscv_execute_progbuf(struct target *target, uint32_t *cmderr);
void riscv_fill_dm_nop(struct target *target, char *buf);
-void riscv_fill_dm_write(struct target *target, char *buf, uint64_t a, uint32_t d);
-void riscv_fill_dm_read(struct target *target, char *buf, uint64_t a);
+void riscv_fill_dmi_write(struct target *target, char *buf, uint64_t a, uint32_t d);
+void riscv_fill_dmi_read(struct target *target, char *buf, uint64_t a);
int riscv_get_dmi_scan_length(struct target *target);
uint32_t riscv_get_dmi_address(const struct target *target, uint32_t dm_address);
diff --git a/src/target/riscv/riscv_reg.c b/src/target/riscv/riscv_reg.c
index f8e5dfe..4f386f4 100644
--- a/src/target/riscv/riscv_reg.c
+++ b/src/target/riscv/riscv_reg.c
@@ -376,8 +376,19 @@ static bool is_known_standard_csr(unsigned int csr_num)
return is_csr_in_buf[csr_num];
}
-static bool gdb_regno_exist(const struct target *target, uint32_t regno)
-{
+bool riscv_reg_impl_gdb_regno_exist(const struct target *target, uint32_t regno)
+{
+ switch (regno) {
+ case GDB_REGNO_VLENB:
+ case GDB_REGNO_MTOPI:
+ case GDB_REGNO_MTOPEI:
+ assert(false
+ && "Existence of other registers is determined "
+ "depending on existence of these ones, so "
+ "whether these register exist or not should be "
+ "set explicitly.");
+ };
+
if (regno <= GDB_REGNO_XPR15 ||
regno == GDB_REGNO_PC ||
regno == GDB_REGNO_PRIV)
@@ -397,6 +408,13 @@ static bool gdb_regno_exist(const struct target *target, uint32_t regno)
case CSR_FRM:
case CSR_FCSR:
return riscv_supports_extension(target, 'F');
+ case CSR_VSTART:
+ case CSR_VXSAT:
+ case CSR_VXRM:
+ case CSR_VL:
+ case CSR_VCSR:
+ case CSR_VTYPE:
+ return vlenb_exists(target);
case CSR_SCOUNTEREN:
case CSR_SSTATUS:
case CSR_STVEC:
@@ -591,14 +609,15 @@ static int resize_reg(const struct target *target, uint32_t regno, bool exist,
return ERROR_OK;
}
-static int set_reg_exist(const struct target *target, uint32_t regno, bool exist)
+int riscv_reg_impl_set_exist(const struct target *target, uint32_t regno, bool exist)
{
const struct reg *reg = riscv_reg_impl_cache_entry(target, regno);
assert(riscv_reg_impl_is_initialized(reg));
return resize_reg(target, regno, exist, reg->size);
}
-int riscv_reg_impl_init_one(struct target *target, uint32_t regno, const struct reg_arch_type *reg_type)
+int riscv_reg_impl_init_cache_entry(struct target *target, uint32_t regno,
+ bool exist, const struct reg_arch_type *reg_type)
{
struct reg * const reg = riscv_reg_impl_cache_entry(target, regno);
if (riscv_reg_impl_is_initialized(reg))
@@ -626,8 +645,7 @@ int riscv_reg_impl_init_one(struct target *target, uint32_t regno, const struct
reg_arch_info->target = target;
reg_arch_info->custom_number = gdb_regno_custom_number(target, regno);
}
- return resize_reg(target, regno, gdb_regno_exist(target, regno),
- gdb_regno_size(target, regno));
+ return resize_reg(target, regno, exist, gdb_regno_size(target, regno));
}
static int init_custom_register_names(struct list_head *expose_custom,
@@ -717,7 +735,7 @@ int riscv_reg_impl_expose_csrs(const struct target *target)
csr_number);
continue;
}
- if (set_reg_exist(target, regno, /*exist*/ true) != ERROR_OK)
+ if (riscv_reg_impl_set_exist(target, regno, /*exist*/ true) != ERROR_OK)
return ERROR_FAIL;
LOG_TARGET_DEBUG(target, "Exposing additional CSR %d (name=%s)",
csr_number, reg->name);
@@ -738,7 +756,7 @@ void riscv_reg_impl_hide_csrs(const struct target *target)
struct reg * const reg = riscv_reg_impl_cache_entry(target, regno);
const unsigned int csr_number = regno - GDB_REGNO_CSR0;
if (!reg->exist) {
- LOG_TARGET_WARNING(target,
+ LOG_TARGET_DEBUG(target,
"Not hiding CSR %d: register does not exist.",
csr_number);
continue;
@@ -826,15 +844,8 @@ static int riscv_set_or_write_register(struct target *target,
return riscv_set_or_write_register(target, GDB_REGNO_DCSR, dcsr, write_through);
}
- if (!target->reg_cache) {
- assert(!target_was_examined(target));
- LOG_TARGET_DEBUG(target,
- "No cache, writing to target: %s <- 0x%" PRIx64,
- riscv_reg_gdb_regno_name(target, regid), value);
- return riscv013_set_register(target, regid, value);
- }
-
struct reg *reg = riscv_reg_impl_cache_entry(target, regid);
+ assert(riscv_reg_impl_is_initialized(reg));
if (!reg->exist) {
LOG_TARGET_DEBUG(target, "Register %s does not exist.", reg->name);
@@ -927,21 +938,15 @@ int riscv_reg_get(struct target *target, riscv_reg_t *value,
RISCV_INFO(r);
assert(r);
if (r->dtm_version == DTM_DTMCS_VERSION_0_11)
- return riscv013_get_register(target, value, regid);
+ return riscv011_get_register(target, value, regid);
keep_alive();
if (regid == GDB_REGNO_PC)
return riscv_reg_get(target, value, GDB_REGNO_DPC);
- if (!target->reg_cache) {
- assert(!target_was_examined(target));
- LOG_TARGET_DEBUG(target, "No cache, reading %s from target",
- riscv_reg_gdb_regno_name(target, regid));
- return riscv013_get_register(target, value, regid);
- }
-
struct reg *reg = riscv_reg_impl_cache_entry(target, regid);
+ assert(riscv_reg_impl_is_initialized(reg));
if (!reg->exist) {
LOG_TARGET_DEBUG(target, "Register %s does not exist.", reg->name);
return ERROR_FAIL;
diff --git a/src/target/riscv/riscv_reg_impl.h b/src/target/riscv/riscv_reg_impl.h
index 906a5b6..7a483ad 100644
--- a/src/target/riscv/riscv_reg_impl.h
+++ b/src/target/riscv/riscv_reg_impl.h
@@ -13,7 +13,7 @@
* This file describes the helpers to use during register cache initialization
* of a RISC-V target. Each cache entry proceedes through the following stages:
* - not allocated before `riscv_reg_impl_init_cache()`
- * - not initialized before the call to `riscv_reg_impl_init_one()` with appropriate regno.
+ * - not initialized before the call to `riscv_reg_impl_init_cache_entry()` with appropriate regno.
* - initialized until `riscv_reg_free_all()` is called.
*/
static inline bool riscv_reg_impl_is_initialized(const struct reg *reg)
@@ -37,8 +37,18 @@ static inline bool riscv_reg_impl_is_initialized(const struct reg *reg)
int riscv_reg_impl_init_cache(struct target *target);
/** Initialize register. */
-int riscv_reg_impl_init_one(struct target *target, uint32_t regno,
- const struct reg_arch_type *reg_type);
+int riscv_reg_impl_init_cache_entry(struct target *target, uint32_t regno,
+ bool exist, const struct reg_arch_type *reg_type);
+
+/**
+ * For most registers, returns whether they exist or not.
+ * For some registers the "exist" bit should be set explicitly.
+ */
+bool riscv_reg_impl_gdb_regno_exist(const struct target *target, uint32_t regno);
+
+/** Mark register as existing or not. */
+int riscv_reg_impl_set_exist(const struct target *target,
+ uint32_t regno, bool exist);
/** Return the entry in the register cache of the target. */
struct reg *riscv_reg_impl_cache_entry(const struct target *target,
diff --git a/src/target/target.c b/src/target/target.c
index fd9c34f..3f412a0 100644
--- a/src/target/target.c
+++ b/src/target/target.c
@@ -3125,11 +3125,18 @@ COMMAND_HANDLER(handle_reg_command)
/* set register value */
if (CMD_ARGC == 2) {
uint8_t *buf = malloc(DIV_ROUND_UP(reg->size, 8));
- if (!buf)
+ if (!buf) {
+ LOG_ERROR("Failed to allocate memory");
return ERROR_FAIL;
- str_to_buf(CMD_ARGV[1], strlen(CMD_ARGV[1]), buf, reg->size, 0);
+ }
+
+ int retval = CALL_COMMAND_HANDLER(command_parse_str_to_buf, CMD_ARGV[1], buf, reg->size);
+ if (retval != ERROR_OK) {
+ free(buf);
+ return retval;
+ }
- int retval = reg->type->set(reg, buf);
+ retval = reg->type->set(reg, buf);
if (retval != ERROR_OK) {
LOG_ERROR("Could not write to register '%s'", reg->name);
} else {
@@ -3898,7 +3905,7 @@ static int handle_bp_command_list(struct command_invocation *cmd)
while (breakpoint) {
if (breakpoint->type == BKPT_SOFT) {
char *buf = buf_to_hex_str(breakpoint->orig_instr,
- breakpoint->length);
+ breakpoint->length * 8);
command_print(cmd, "Software breakpoint(IVA): addr=" TARGET_ADDR_FMT ", len=0x%x, orig_instr=0x%s",
breakpoint->address,
breakpoint->length,
@@ -3927,7 +3934,7 @@ static int handle_bp_command_list(struct command_invocation *cmd)
}
static int handle_bp_command_set(struct command_invocation *cmd,
- target_addr_t addr, uint32_t asid, uint32_t length, int hw)
+ target_addr_t addr, uint32_t asid, unsigned int length, int hw)
{
struct target *target = get_current_target(cmd->ctx);
int retval;
@@ -4044,7 +4051,7 @@ COMMAND_HANDLER(handle_wp_command)
while (watchpoint) {
char wp_type = (watchpoint->rw == WPT_READ ? 'r' : (watchpoint->rw == WPT_WRITE ? 'w' : 'a'));
command_print(CMD, "address: " TARGET_ADDR_FMT
- ", len: 0x%8.8" PRIx32
+ ", len: 0x%8.8x"
", r/w/a: %c, value: 0x%8.8" PRIx64
", mask: 0x%8.8" PRIx64,
watchpoint->address,
@@ -4186,7 +4193,7 @@ static void write_gmon(uint32_t *samples, uint32_t sample_num, const char *filen
uint32_t start_address, uint32_t end_address, struct target *target, uint32_t duration_ms)
{
uint32_t i;
- FILE *f = fopen(filename, "w");
+ FILE *f = fopen(filename, "wb");
if (!f)
return;
write_string(f, "gmon");
@@ -4772,63 +4779,63 @@ static int target_jim_get_reg(Jim_Interp *interp, int argc,
return JIM_OK;
}
-static int target_jim_set_reg(Jim_Interp *interp, int argc,
- Jim_Obj * const *argv)
+COMMAND_HANDLER(handle_set_reg_command)
{
- if (argc != 2) {
- Jim_WrongNumArgs(interp, 1, argv, "dict");
- return JIM_ERR;
- }
+ if (CMD_ARGC != 1)
+ return ERROR_COMMAND_SYNTAX_ERROR;
int tmp;
#if JIM_VERSION >= 80
- Jim_Obj **dict = Jim_DictPairs(interp, argv[1], &tmp);
+ Jim_Obj **dict = Jim_DictPairs(CMD_CTX->interp, CMD_JIMTCL_ARGV[0], &tmp);
if (!dict)
- return JIM_ERR;
+ return ERROR_FAIL;
#else
Jim_Obj **dict;
- int ret = Jim_DictPairs(interp, argv[1], &dict, &tmp);
+ int ret = Jim_DictPairs(CMD_CTX->interp, CMD_JIMTCL_ARGV[0], &dict, &tmp);
if (ret != JIM_OK)
- return ret;
+ return ERROR_FAIL;
#endif
const unsigned int length = tmp;
- struct command_context *cmd_ctx = current_command_context(interp);
- assert(cmd_ctx);
- const struct target *target = get_current_target(cmd_ctx);
+
+ const struct target *target = get_current_target(CMD_CTX);
+ assert(target);
for (unsigned int i = 0; i < length; i += 2) {
const char *reg_name = Jim_String(dict[i]);
const char *reg_value = Jim_String(dict[i + 1]);
- struct reg *reg = register_get_by_name(target->reg_cache, reg_name,
- false);
+ struct reg *reg = register_get_by_name(target->reg_cache, reg_name, false);
if (!reg || !reg->exist) {
- Jim_SetResultFormatted(interp, "unknown register '%s'", reg_name);
- return JIM_ERR;
+ command_print(CMD, "unknown register '%s'", reg_name);
+ return ERROR_FAIL;
}
uint8_t *buf = malloc(DIV_ROUND_UP(reg->size, 8));
-
if (!buf) {
LOG_ERROR("Failed to allocate memory");
- return JIM_ERR;
+ return ERROR_FAIL;
}
- str_to_buf(reg_value, strlen(reg_value), buf, reg->size, 0);
- int retval = reg->type->set(reg, buf);
+ int retval = CALL_COMMAND_HANDLER(command_parse_str_to_buf, reg_value, buf, reg->size);
+ if (retval != ERROR_OK) {
+ free(buf);
+ return retval;
+ }
+
+ retval = reg->type->set(reg, buf);
free(buf);
if (retval != ERROR_OK) {
- Jim_SetResultFormatted(interp, "failed to set '%s' to register '%s'",
+ command_print(CMD, "failed to set '%s' to register '%s'",
reg_value, reg_name);
- return JIM_ERR;
+ return retval;
}
}
- return JIM_OK;
+ return ERROR_OK;
}
/**
@@ -5568,7 +5575,7 @@ static const struct command_registration target_instance_command_handlers[] = {
{
.name = "set_reg",
.mode = COMMAND_EXEC,
- .jim_handler = target_jim_set_reg,
+ .handler = handle_set_reg_command,
.help = "Set target register values",
.usage = "dict",
},
@@ -5789,7 +5796,7 @@ static int target_create(struct jim_getopt_info *goi)
}
target->dbgmsg = NULL;
- target->dbg_msg_enabled = 0;
+ target->dbg_msg_enabled = false;
target->endianness = TARGET_ENDIAN_UNKNOWN;
@@ -6703,7 +6710,7 @@ static const struct command_registration target_exec_command_handlers[] = {
{
.name = "set_reg",
.mode = COMMAND_EXEC,
- .jim_handler = target_jim_set_reg,
+ .handler = handle_set_reg_command,
.help = "Set target register values",
.usage = "dict",
},
diff --git a/src/target/target.h b/src/target/target.h
index c74b8c2..9ff2f78 100644
--- a/src/target/target.h
+++ b/src/target/target.h
@@ -163,7 +163,7 @@ struct target {
struct watchpoint *watchpoints; /* list of watchpoints */
struct trace *trace_info; /* generic trace information */
struct debug_msg_receiver *dbgmsg; /* list of debug message receivers */
- uint32_t dbg_msg_enabled; /* debug message status */
+ bool dbg_msg_enabled; /* debug message status */
void *arch_info; /* architecture specific information */
void *private_config; /* pointer to target specific config data (for jim_configure hook) */
struct target *next; /* next target in list */
@@ -805,6 +805,7 @@ int target_profiling_default(struct target *target, uint32_t *samples, uint32_t
#define ERROR_TARGET_ALGO_EXIT (-313)
#define ERROR_TARGET_SIZE_NOT_SUPPORTED (-314)
#define ERROR_TARGET_PACKING_NOT_SUPPORTED (-315)
+#define ERROR_TARGET_HALTED_DO_RESUME (-316) /* used to workaround incorrect debug halt */
extern bool get_target_reset_nag(void);
diff --git a/src/target/target_request.c b/src/target/target_request.c
index 72c8421..bccae07 100644
--- a/src/target/target_request.c
+++ b/src/target/target_request.c
@@ -164,7 +164,7 @@ static int add_debug_msg_receiver(struct command_context *cmd_ctx, struct target
(*p)->next = NULL;
/* enable callback */
- target->dbg_msg_enabled = 1;
+ target->dbg_msg_enabled = true;
return ERROR_OK;
}
@@ -225,7 +225,7 @@ int delete_debug_msg_receiver(struct command_context *cmd_ctx, struct target *ta
free(c);
if (!*p) {
/* disable callback */
- target->dbg_msg_enabled = 0;
+ target->dbg_msg_enabled = false;
}
return ERROR_OK;
} else
diff --git a/src/target/xtensa/xtensa.c b/src/target/xtensa/xtensa.c
index 702b8fc..8369cc4 100644
--- a/src/target/xtensa/xtensa.c
+++ b/src/target/xtensa/xtensa.c
@@ -540,7 +540,7 @@ static void xtensa_queue_exec_ins_wide(struct xtensa *xtensa, uint8_t *ops, uint
for (int32_t i = oplenw - 1; i > 0; i--)
xtensa_queue_dbg_reg_write(xtensa,
XDMREG_DIR0 + i,
- target_buffer_get_u32(xtensa->target, &ops_padded[sizeof(uint32_t)*i]));
+ target_buffer_get_u32(xtensa->target, &ops_padded[sizeof(uint32_t) * i]));
/* Write DIR0EXEC last */
xtensa_queue_dbg_reg_write(xtensa,
XDMREG_DIR0EXEC,
@@ -3966,10 +3966,10 @@ COMMAND_HELPER(xtensa_cmd_xtreg_do, struct xtensa *xtensa)
rptr->type = XT_REG_OTHER;
}
- /* Register flags */
+ /* Register flags: includes intsetN, intclearN for LX8 */
if ((strcmp(rptr->name, "mmid") == 0) || (strcmp(rptr->name, "eraccess") == 0) ||
- (strcmp(rptr->name, "ddr") == 0) || (strcmp(rptr->name, "intset") == 0) ||
- (strcmp(rptr->name, "intclear") == 0))
+ (strcmp(rptr->name, "ddr") == 0) || (strncmp(rptr->name, "intset", 6) == 0) ||
+ (strncmp(rptr->name, "intclear", 8) == 0) || (strcmp(rptr->name, "mesrclr") == 0))
rptr->flags = XT_REGF_NOREAD;
else
rptr->flags = 0;
diff --git a/src/target/xtensa/xtensa_chip.c b/src/target/xtensa/xtensa_chip.c
index ac4a49c..ce6d35c 100644
--- a/src/target/xtensa/xtensa_chip.c
+++ b/src/target/xtensa/xtensa_chip.c
@@ -103,7 +103,7 @@ static int xtensa_chip_target_create(struct target *target, Jim_Interp *interp)
LOG_DEBUG("DAP: ap_num %" PRId64 " DAP %p\n", pc->ap_num, pc->dap);
} else {
xtensa_chip_dm_cfg.tap = target->tap;
- LOG_DEBUG("JTAG: %s:%s pos %d", target->tap->chip, target->tap->tapname,
+ LOG_DEBUG("JTAG: %s:%s pos %u", target->tap->chip, target->tap->tapname,
target->tap->abs_chain_position);
}
diff --git a/src/target/xtensa/xtensa_debug_module.h b/src/target/xtensa/xtensa_debug_module.h
index 495da2a..8391a96 100644
--- a/src/target/xtensa/xtensa_debug_module.h
+++ b/src/target/xtensa/xtensa_debug_module.h
@@ -75,6 +75,7 @@ enum xtensa_dm_reg {
XDMREG_DELAYCNT,
XDMREG_MEMADDRSTART,
XDMREG_MEMADDREND,
+ XDMREG_DEBUGPC,/*Unsupported, undocumented, may not be present*/
XDMREG_EXTTIMELO,
XDMREG_EXTTIMEHI,
XDMREG_TRAXRSVD48,
@@ -184,6 +185,7 @@ struct xtensa_dm_reg_offsets {
{ .nar = 0x07, .apb = 0x001c }, /* XDMREG_DELAYCNT */ \
{ .nar = 0x08, .apb = 0x0020 }, /* XDMREG_MEMADDRSTART */ \
{ .nar = 0x09, .apb = 0x0024 }, /* XDMREG_MEMADDREND */ \
+ { .nar = 0x0f, .apb = 0x003c }, /* XDMREG_DEBUGPC */ \
{ .nar = 0x10, .apb = 0x0040 }, /* XDMREG_EXTTIMELO */ \
{ .nar = 0x11, .apb = 0x0044 }, /* XDMREG_EXTTIMEHI */ \
{ .nar = 0x12, .apb = 0x0048 }, /* XDMREG_TRAXRSVD48 */ \
diff --git a/src/transport/transport.c b/src/transport/transport.c
index 81d3d58..bf306e7 100644
--- a/src/transport/transport.c
+++ b/src/transport/transport.c
@@ -278,7 +278,6 @@ COMMAND_HANDLER(handle_transport_select)
if (session) {
if (!strcmp(session->name, CMD_ARGV[0])) {
LOG_WARNING("Transport \"%s\" was already selected", session->name);
- command_print(CMD, "%s", session->name);
return ERROR_OK;
}
command_print(CMD, "Can't change session's transport after the initial selection was made");
@@ -301,7 +300,6 @@ COMMAND_HANDLER(handle_transport_select)
int retval = transport_select(CMD_CTX, CMD_ARGV[0]);
if (retval != ERROR_OK)
return retval;
- command_print(CMD, "%s", session->name);
return ERROR_OK;
}
}