diff options
Diffstat (limited to 'src')
83 files changed, 2085 insertions, 833 deletions
diff --git a/src/Makefile.am b/src/Makefile.am index 4d1c1a2..4dbe93f 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -34,7 +34,10 @@ if RELEASE else %C%_libopenocd_la_CPPFLAGS += -DRELSTR=\"`$(top_srcdir)/guess-rev.sh $(top_srcdir)`\" %C%_libopenocd_la_CPPFLAGS += -DGITVERSION=\"`cd $(top_srcdir) && git describe`\" -%C%_libopenocd_la_CPPFLAGS += -DPKGBLDDATE=\"`date +%F-%R`\" +%C%_libopenocd_la_CPPFLAGS += -DPKGBLDDATE=\"`DATE_FMT=+%F-%R; \ + SOURCE_DATE_EPOCH="$${SOURCE_DATE_EPOCH:-$$(date +%s)}"; \ + date -u -d "@$$SOURCE_DATE_EPOCH" "$$DATE_FMT" 2>/dev/null || \ + date -u -r "$$SOURCE_DATE_EPOCH" "$$DATE_FMT" 2>/dev/null || date -u "$$DATE_FMT"`\" endif # add default CPPFLAGS diff --git a/src/flash/nor/Makefile.am b/src/flash/nor/Makefile.am index 8296877..147807f 100644 --- a/src/flash/nor/Makefile.am +++ b/src/flash/nor/Makefile.am @@ -45,6 +45,7 @@ NOR_DRIVERS = \ %D%/max32xxx.c \ %D%/mdr.c \ %D%/msp432.c \ + %D%/mspm0.c \ %D%/mrvlqspi.c \ %D%/niietcm4.c \ %D%/non_cfi.c \ diff --git a/src/flash/nor/driver.h b/src/flash/nor/driver.h index 852a55a..794566f 100644 --- a/src/flash/nor/driver.h +++ b/src/flash/nor/driver.h @@ -274,6 +274,7 @@ extern const struct flash_driver max32xxx_flash; extern const struct flash_driver mdr_flash; extern const struct flash_driver mrvlqspi_flash; extern const struct flash_driver msp432_flash; +extern const struct flash_driver mspm0_flash; extern const struct flash_driver niietcm4_flash; extern const struct flash_driver npcx_flash; extern const struct flash_driver nrf51_flash; diff --git a/src/flash/nor/drivers.c b/src/flash/nor/drivers.c index ce97b81..67d8624 100644 --- a/src/flash/nor/drivers.c +++ b/src/flash/nor/drivers.c @@ -51,6 +51,7 @@ static const struct flash_driver * const flash_drivers[] = { &mdr_flash, &mrvlqspi_flash, &msp432_flash, + &mspm0_flash, &niietcm4_flash, &npcx_flash, &nrf5_flash, diff --git a/src/flash/nor/mspm0.c b/src/flash/nor/mspm0.c new file mode 100644 index 0000000..4731c89 --- /dev/null +++ b/src/flash/nor/mspm0.c @@ -0,0 +1,1131 @@ +// SPDX-License-Identifier: GPL-2.0-or-later + +/*************************************************************************** + * Copyright (C) 2023-2025 Texas Instruments Incorporated - https://www.ti.com/ + * + * NOR flash driver for MSPM0L and MSPM0G class of uC from Texas Instruments. + * + * See: + * https://www.ti.com/microcontrollers-mcus-processors/arm-based-microcontrollers/arm-cortex-m0-mcus/overview.html + ***************************************************************************/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "imp.h" +#include <helper/bits.h> +#include <helper/time_support.h> + +/* MSPM0 Region memory map */ +#define MSPM0_FLASH_BASE_NONMAIN 0x41C00000 +#define MSPM0_FLASH_END_NONMAIN 0x41C00400 +#define MSPM0_FLASH_BASE_MAIN 0x0 +#define MSPM0_FLASH_BASE_DATA 0x41D00000 + +/* MSPM0 FACTORYREGION registers */ +#define MSPM0_FACTORYREGION 0x41C40000 +#define MSPM0_TRACEID (MSPM0_FACTORYREGION + 0x000) +#define MSPM0_DID (MSPM0_FACTORYREGION + 0x004) +#define MSPM0_USERID (MSPM0_FACTORYREGION + 0x008) +#define MSPM0_SRAMFLASH (MSPM0_FACTORYREGION + 0x018) + +/* MSPM0 FCTL registers */ +#define FLASH_CONTROL_BASE 0x400CD000 +#define FCTL_REG_DESC (FLASH_CONTROL_BASE + 0x10FC) +#define FCTL_REG_CMDEXEC (FLASH_CONTROL_BASE + 0x1100) +#define FCTL_REG_CMDTYPE (FLASH_CONTROL_BASE + 0x1104) +#define FCTL_REG_CMDADDR (FLASH_CONTROL_BASE + 0x1120) +#define FCTL_REG_CMDBYTEN (FLASH_CONTROL_BASE + 0x1124) +#define FCTL_REG_CMDDATA0 (FLASH_CONTROL_BASE + 0x1130) +#define FCTL_REG_CMDWEPROTA (FLASH_CONTROL_BASE + 0x11D0) +#define FCTL_REG_CMDWEPROTB (FLASH_CONTROL_BASE + 0x11D4) +#define FCTL_REG_CMDWEPROTNM (FLASH_CONTROL_BASE + 0x1210) +#define FCTL_REG_STATCMD (FLASH_CONTROL_BASE + 0x13D0) + +/* FCTL_STATCMD[CMDDONE] Bits */ +#define FCTL_STATCMD_CMDDONE_MASK 0x00000001 +#define FCTL_STATCMD_CMDDONE_STATDONE 0x00000001 + +/* FCTL_STATCMD[CMDPASS] Bits */ +#define FCTL_STATCMD_CMDPASS_MASK 0x00000002 +#define FCTL_STATCMD_CMDPASS_STATPASS 0x00000002 + +/* + * FCTL_CMDEXEC Bits + * FCTL_CMDEXEC[VAL] Bits + */ +#define FCTL_CMDEXEC_VAL_EXECUTE 0x00000001 + +/* FCTL_CMDTYPE[COMMAND] Bits */ +#define FCTL_CMDTYPE_COMMAND_PROGRAM 0x00000001 +#define FCTL_CMDTYPE_COMMAND_ERASE 0x00000002 + +/* FCTL_CMDTYPE[SIZE] Bits */ +#define FCTL_CMDTYPE_SIZE_ONEWORD 0x00000000 +#define FCTL_CMDTYPE_SIZE_SECTOR 0x00000040 + +/* FCTL_FEATURE_VER_B minimum */ +#define FCTL_FEATURE_VER_B 0xA + +#define MSPM0_MAX_PROTREGS 3 + +#define MSPM0_FLASH_TIMEOUT_MS 8000 +#define ERR_STRING_MAX 255 + +/* SYSCTL BASE */ +#define SYSCTL_BASE 0x400AF000 +#define SYSCTL_SECCFG_SECSTATUS (SYSCTL_BASE + 0x00003048) + +/* TI manufacturer ID */ +#define TI_MANUFACTURER_ID 0x17 + +/* Defines for probe status */ +#define MSPM0_NO_ID_FOUND 0 +#define MSPM0_DEV_ID_FOUND 1 +#define MSPM0_DEV_PART_ID_FOUND 2 + +struct mspm0_flash_bank { + /* chip id register */ + uint32_t did; + /* Device Unique ID register */ + uint32_t traceid; + unsigned char version; + + const char *name; + + /* Decoded flash information */ + unsigned int data_flash_size_kb; + unsigned int main_flash_size_kb; + unsigned int main_flash_num_banks; + unsigned int sector_size; + /* Decoded SRAM information */ + unsigned int sram_size_kb; + + /* Flash word size: 64 bit = 8, 128bit = 16 bytes */ + unsigned char flash_word_size_bytes; + + /* Protection register stuff */ + unsigned int protect_reg_base; + unsigned int protect_reg_count; + + /* Flashctl version: A - CMDWEPROTA/B, B- CMDWEPROTB */ + unsigned char flash_version; +}; + +struct mspm0_part_info { + const char *part_name; + unsigned short part; + unsigned char variant; +}; + +struct mspm0_family_info { + const char *family_name; + unsigned short part_num; + unsigned char part_count; + const struct mspm0_part_info *part_info; +}; + +/* https://www.ti.com/lit/ds/symlink/mspm0l1346.pdf Table 8-13 and so on */ +static const struct mspm0_part_info mspm0l_parts[] = { + { "MSPM0L1105TDGS20R", 0x51DB, 0x16 }, + { "MSPM0L1105TDGS28R", 0x51DB, 0x83 }, + { "MSPM0L1105TDYYR", 0x51DB, 0x54 }, + { "MSPM0L1105TRGER", 0x51DB, 0x86 }, + { "MSPM0L1105TRHBR", 0x51DB, 0x68 }, + { "MSPM0L1106TDGS20R", 0x5552, 0x4B }, + { "MSPM0L1106TDGS28R", 0x5552, 0x98 }, + { "MSPM0L1106TDYYR", 0x5552, 0x9D }, + { "MSPM0L1106TRGER", 0x5552, 0x90 }, + { "MSPM0L1106TRHBR", 0x5552, 0x53 }, + { "MSPM0L1303SRGER", 0xef0, 0x17 }, + { "MSPM0L1303TRGER", 0xef0, 0xe2 }, + { "MSPM0L1304QDGS20R", 0xd717, 0x91 }, + { "MSPM0L1304QDGS28R", 0xd717, 0xb6 }, + { "MSPM0L1304QDYYR", 0xd717, 0xa0 }, + { "MSPM0L1304QRHBR", 0xd717, 0xa9 }, + { "MSPM0L1304SDGS20R", 0xd717, 0xfa }, + { "MSPM0L1304SDGS28R", 0xd717, 0x73 }, + { "MSPM0L1304SDYYR", 0xd717, 0xb7 }, + { "MSPM0L1304SRGER", 0xd717, 0x26 }, + { "MSPM0L1304SRHBR", 0xd717, 0xe4 }, + { "MSPM0L1304TDGS20R", 0xd717, 0x33 }, + { "MSPM0L1304TDGS28R", 0xd717, 0xa8 }, + { "MSPM0L1304TDYYR", 0xd717, 0xf9 }, + { "MSPM0L1304TRGER", 0xd717, 0xb7 }, + { "MSPM0L1304TRHBR", 0xd717, 0x5a }, + { "MSPM0L1305QDGS20R", 0x4d03, 0xb7 }, + { "MSPM0L1305QDGS28R", 0x4d03, 0x74 }, + { "MSPM0L1305QDYYR", 0x4d03, 0xec }, + { "MSPM0L1305QRHBR", 0x4d03, 0x78 }, + { "MSPM0L1305SDGS20R", 0x4d03, 0xc7 }, + { "MSPM0L1305SDGS28R", 0x4d03, 0x64 }, + { "MSPM0L1305SDYYR", 0x4d03, 0x91 }, + { "MSPM0L1305SRGER", 0x4d03, 0x73 }, + { "MSPM0L1305SRHBR", 0x4d03, 0x2d }, + { "MSPM0L1305TDGS20R", 0x4d03, 0xa0 }, + { "MSPM0L1305TDGS28R", 0x4d03, 0xfb }, + { "MSPM0L1305TDYYR", 0x4d03, 0xde }, + { "MSPM0L1305TRGER", 0x4d03, 0xea }, + { "MSPM0L1305TRHBR", 0x4d03, 0x85 }, + { "MSPM0L1306QDGS20R", 0xbb70, 0x59 }, + { "MSPM0L1306QDGS28R", 0xbb70, 0xf7 }, + { "MSPM0L1306QDYYR", 0xbb70, 0x9f }, + { "MSPM0L1306QRHBR", 0xbb70, 0xc2 }, + { "MSPM0L1306SDGS20R", 0xbb70, 0xf4 }, + { "MSPM0L1306SDGS28R", 0xbb70, 0x5 }, + { "MSPM0L1306SDYYR", 0xbb70, 0xe }, + { "MSPM0L1306SRGER", 0xbb70, 0x7f }, + { "MSPM0L1306SRHBR", 0xbb70, 0x3c }, + { "MSPM0L1306TDGS20R", 0xbb70, 0xa }, + { "MSPM0L1306TDGS28R", 0xbb70, 0x63 }, + { "MSPM0L1306TDYYR", 0xbb70, 0x35 }, + { "MSPM0L1306TRGER", 0xbb70, 0xaa }, + { "MSPM0L1306TRHBR", 0xbb70, 0x52 }, + { "MSPM0L1343TDGS20R", 0xb231, 0x2e }, + { "MSPM0L1344TDGS20R", 0x40b0, 0xd0 }, + { "MSPM0L1345TDGS28R", 0x98b4, 0x74 }, + { "MSPM0L1346TDGS28R", 0xf2b5, 0xef }, +}; + +/* https://www.ti.com/lit/ds/symlink/mspm0g3506.pdf Table 8-20 */ +static const struct mspm0_part_info mspm0g_parts[] = { + { "MSPM0G1105TPTR", 0x8934, 0xD }, + { "MSPM0G1105TRGZR", 0x8934, 0xFE }, + { "MSPM0G1106TPMR", 0x477B, 0xD4 }, + { "MSPM0G1106TPTR", 0x477B, 0x71 }, + { "MSPM0G1106TRGZR", 0x477B, 0xBB }, + { "MSPM0G1106TRHBR", 0x477B, 0x0 }, + { "MSPM0G1107TDGS28R", 0x807B, 0x82 }, + { "MSPM0G1107TPMR", 0x807B, 0xB3 }, + { "MSPM0G1107TPTR", 0x807B, 0x32 }, + { "MSPM0G1107TRGER", 0x807B, 0x79 }, + { "MSPM0G1107TRGZR", 0x807B, 0x20 }, + { "MSPM0G1107TRHBR", 0x807B, 0xBC }, + { "MSPM0G1505SDGS28R", 0x13C4, 0x73 }, + { "MSPM0G1505SPMR", 0x13C4, 0x53 }, + { "MSPM0G1505SPTR", 0x13C4, 0x3E }, + { "MSPM0G1505SRGER", 0x13C4, 0x47 }, + { "MSPM0G1505SRGZR", 0x13C4, 0x34 }, + { "MSPM0G1505SRHBR", 0x13C4, 0x30 }, + { "MSPM0G1506SDGS28R", 0x5AE0, 0x3A }, + { "MSPM0G1506SPMR", 0x5AE0, 0xF6 }, + { "MSPM0G1506SRGER", 0x5AE0, 0x67 }, + { "MSPM0G1506SRGZR", 0x5AE0, 0x75 }, + { "MSPM0G1506SRHBR", 0x5AE0, 0x57 }, + { "MSPM0G1507SDGS28R", 0x2655, 0x6D }, + { "MSPM0G1507SPMR", 0x2655, 0x97 }, + { "MSPM0G1507SRGER", 0x2655, 0x83 }, + { "MSPM0G1507SRGZR", 0x2655, 0xD3 }, + { "MSPM0G1507SRHBR", 0x2655, 0x4D }, + { "MSPM0G3105SDGS20R", 0x4749, 0x21 }, + { "MSPM0G3105SDGS28R", 0x4749, 0xDD }, + { "MSPM0G3105SRHBR", 0x4749, 0xBE }, + { "MSPM0G3106SDGS20R", 0x54C7, 0xD2 }, + { "MSPM0G3106SDGS28R", 0x54C7, 0xB9 }, + { "MSPM0G3106SRHBR", 0x54C7, 0x67 }, + { "MSPM0G3107SDGS20R", 0xAB39, 0x5C }, + { "MSPM0G3107SDGS28R", 0xAB39, 0xCC }, + { "MSPM0G3107SRHBR", 0xAB39, 0xB7 }, + { "MSPM0G3505SDGS28R", 0xc504, 0x8e }, + { "MSPM0G3505SPMR", 0xc504, 0x1d }, + { "MSPM0G3505SPTR", 0xc504, 0x93 }, + { "MSPM0G3505SRGZR", 0xc504, 0xc7 }, + { "MSPM0G3505SRHBR", 0xc504, 0xe7 }, + { "MSPM0G3505TDGS28R", 0xc504, 0xdf }, + { "MSPM0G3506SDGS28R", 0x151f, 0x8 }, + { "MSPM0G3506SPMR", 0x151f, 0xd4 }, + { "MSPM0G3506SPTR", 0x151f, 0x39 }, + { "MSPM0G3506SRGZR", 0x151f, 0xfe }, + { "MSPM0G3506SRHBR", 0x151f, 0xb5 }, + { "MSPM0G3507SDGS28R", 0xae2d, 0xca }, + { "MSPM0G3507SPMR", 0xae2d, 0xc7 }, + { "MSPM0G3507SPTR", 0xae2d, 0x3f }, + { "MSPM0G3507SRGZR", 0xae2d, 0xf7 }, + { "MSPM0G3507SRHBR", 0xae2d, 0x4c }, + { "M0G3107QPMRQ1", 0x4e2f, 0x51 }, + { "M0G3107QPTRQ1", 0x4e2f, 0xc7}, + { "M0G3107QRGZRQ1", 0x4e2f, 0x8a }, + { "M0G3107QRHBRQ1", 0x4e2f, 0x9a}, + { "M0G3107QDGS28RQ1", 0x4e2f, 0xd5}, + { "M0G3107QDGS28RQ1", 0x4e2f, 0x67}, + { "M0G3107QDGS20RQ1", 0x4e2f, 0xfd}, + { "M0G3106QPMRQ1", 0x54C7, 0x08}, + { "M0G3105QDGS32RQ1", 0x1349, 0x08}, + { "M0G3106QPTRQ1", 0x54C7, 0x3F}, + { "M0G3105QDGS28RQ1", 0x1349, 0x1B}, + { "M0G3106QRGZRQ1", 0x94AD, 0xE6}, + { "M0G3105QDGS20RQ1", 0x1349, 0xFB}, + { "M0G3106QRHBRQ1", 0x94AD, 0x20}, + { "M0G3106QDGS32RQ1", 0x94AD, 0x8D}, + { "M0G3106QDGS28RQ1", 0x94AD, 0x03}, + { "M0G3106QDGS20RQ1", 0x94AD, 0x6F}, + { "M0G3105QPMRQ1", 0x1349, 0xD0}, + { "M0G3105QPTRQ1", 0x1349, 0xEF}, + { "M0G3105QRGZRQ1", 0x1349, 0x70}, + { "M0G3105QRHBRQ1", 0x1349, 0x01}, +}; + +/* https://www.ti.com/lit/gpn/mspm0c1104 Table 8-12 and so on */ +static const struct mspm0_part_info mspm0c_parts[] = { + { "MSPS003F4SPW20R", 0x57b3, 0x70}, + { "MSPM0C1104SDGS20R", 0x57b3, 0x71}, + { "MSPM0C1104SRUKR", 0x57b3, 0x73}, + { "MSPM0C1104SDYYR", 0x57b3, 0x75}, + { "MSPM0C1104SDDFR", 0x57b3, 0x77}, + { "MSPM0C1104SDSGR", 0x57b3, 0x79}, +}; + +/* https://www.ti.com/lit/gpn/MSPM0L2228 Table 8-16 and so on */ +static const struct mspm0_part_info mspm0lx22x_parts[] = { + { "MSPM0L1227SRGER", 0x7C32, 0xF1}, + { "MSPM0L1227SPTR", 0x7C32, 0xC9}, + { "MSPM0L1227SPMR", 0x7C32, 0x1C}, + { "MSPM0L1227SPNAR", 0x7C32, 0x91}, + { "MSPM0L1227SPNR", 0x7C32, 0x39}, + { "MSPM0L1228SRGER", 0x33F7, 0x13}, + { "MSPM0L1228SRHBR", 0x33F7, 0x3A}, + { "MSPM0L1228SRGZR", 0x33F7, 0xBC}, + { "MSPM0L1228SPTR", 0x33F7, 0xF8}, + { "MSPM0L1228SPMR", 0x33F7, 0xCE}, + { "MSPM0L1228SPNAR", 0x33F7, 0x59}, + { "MSPM0L1228SPNR", 0x33F7, 0x7}, + { "MSPM0L2227SRGZR", 0x5E8F, 0x90}, + { "MSPM0L2227SPTR", 0x5E8F, 0xA}, + { "MSPM0L2227SPMR", 0x5E8F, 0x6D}, + { "MSPM0L2227SPNAR", 0x5E8F, 0x24}, + { "MSPM0L2227SPNR", 0x5E8F, 0x68}, + { "MSPM0L2228SRGZR", 0x2C38, 0xB8}, + { "MSPM0L2228SPTR", 0x2C38, 0x25}, + { "MSPM0L2228SPMR", 0x2C38, 0x6E}, + { "MSPM0L2228SPNAR", 0x2C38, 0x63}, + { "MSPM0L2228SPNR", 0x2C38, 0x3C}, +}; + +static const struct mspm0_family_info mspm0_finf[] = { + { "MSPM0L", 0xbb82, ARRAY_SIZE(mspm0l_parts), mspm0l_parts }, + { "MSPM0Lx22x", 0xbb9f, ARRAY_SIZE(mspm0lx22x_parts), mspm0lx22x_parts }, + { "MSPM0G", 0xbb88, ARRAY_SIZE(mspm0g_parts), mspm0g_parts }, + { "MSPM0C", 0xbba1, ARRAY_SIZE(mspm0c_parts), mspm0c_parts }, +}; + +/* + * OpenOCD command interface + */ + +/* + * flash_bank mspm0 <base> <size> 0 0 <target#> + */ +FLASH_BANK_COMMAND_HANDLER(mspm0_flash_bank_command) +{ + struct mspm0_flash_bank *mspm0_info; + + switch (bank->base) { + case MSPM0_FLASH_BASE_NONMAIN: + case MSPM0_FLASH_BASE_MAIN: + case MSPM0_FLASH_BASE_DATA: + break; + default: + LOG_ERROR("Invalid bank address " TARGET_ADDR_FMT, bank->base); + return ERROR_FAIL; + } + + mspm0_info = calloc(1, sizeof(struct mspm0_flash_bank)); + if (!mspm0_info) { + LOG_ERROR("%s: Out of memory for mspm0_info!", __func__); + return ERROR_FAIL; + } + + bank->driver_priv = mspm0_info; + + mspm0_info->sector_size = 0x400; + + return ERROR_OK; +} + +/* + * Chip identification and status + */ +static int get_mspm0_info(struct flash_bank *bank, struct command_invocation *cmd) +{ + struct mspm0_flash_bank *mspm0_info = bank->driver_priv; + + if (mspm0_info->did == 0) + return ERROR_FLASH_BANK_NOT_PROBED; + + command_print_sameline(cmd, + "\nTI MSPM0 information: Chip is " + "%s rev %d Device Unique ID: 0x%" PRIu32 "\n", + mspm0_info->name, mspm0_info->version, + mspm0_info->traceid); + command_print_sameline(cmd, + "main flash: %uKiB in %u bank(s), sram: %uKiB, data flash: %uKiB", + mspm0_info->main_flash_size_kb, + mspm0_info->main_flash_num_banks, mspm0_info->sram_size_kb, + mspm0_info->data_flash_size_kb); + + return ERROR_OK; +} + +/* Extract a bitfield helper */ +static unsigned int mspm0_extract_val(unsigned int var, unsigned char hi, unsigned char lo) +{ + return (var & GENMASK(hi, lo)) >> lo; +} + +static int mspm0_read_part_info(struct flash_bank *bank) +{ + struct mspm0_flash_bank *mspm0_info = bank->driver_priv; + struct target *target = bank->target; + const struct mspm0_family_info *minfo = NULL; + + /* Read and parse chip identification and flash version register */ + uint32_t did; + int retval = target_read_u32(target, MSPM0_DID, &did); + if (retval != ERROR_OK) { + LOG_ERROR("Failed to read device ID"); + return retval; + } + retval = target_read_u32(target, MSPM0_TRACEID, &mspm0_info->traceid); + if (retval != ERROR_OK) { + LOG_ERROR("Failed to read trace ID"); + return retval; + } + uint32_t userid; + retval = target_read_u32(target, MSPM0_USERID, &userid); + if (retval != ERROR_OK) { + LOG_ERROR("Failed to read user ID"); + return retval; + } + uint32_t flashram; + retval = target_read_u32(target, MSPM0_SRAMFLASH, &flashram); + if (retval != ERROR_OK) { + LOG_ERROR("Failed to read sramflash register"); + return retval; + } + uint32_t flashdesc; + retval = target_read_u32(target, FCTL_REG_DESC, &flashdesc); + if (retval != ERROR_OK) { + LOG_ERROR("Failed to read flashctl description register"); + return retval; + } + + unsigned char version = mspm0_extract_val(did, 31, 28); + unsigned short pnum = mspm0_extract_val(did, 27, 12); + unsigned char variant = mspm0_extract_val(userid, 23, 16); + unsigned short part = mspm0_extract_val(userid, 15, 0); + unsigned short manufacturer = mspm0_extract_val(did, 11, 1); + + /* + * Valid DIE and manufacturer ID? + * Check the ALWAYS_1 bit to be 1 and manufacturer to be 0x17. All MSPM0 + * devices within the Device ID field of the factory constants will + * always read 0x17 as it is TI's JEDEC bank and company code. If 1 + * and 0x17 is not read from their respective registers then it truly + * is not a MSPM0 device so we will return an error instead of + * going any further. + */ + if (!(did & BIT(0)) || !(manufacturer & TI_MANUFACTURER_ID)) { + LOG_WARNING("Unknown Device ID[0x%" PRIx32 "], cannot identify target", + did); + LOG_DEBUG("did 0x%" PRIx32 ", traceid 0x%" PRIx32 ", userid 0x%" PRIx32 + ", flashram 0x%" PRIx32 "", did, mspm0_info->traceid, userid, + flashram); + return ERROR_FLASH_OPERATION_FAILED; + } + + /* Initialize master index selector and probe status*/ + unsigned char minfo_idx = 0xff; + unsigned char probe_status = MSPM0_NO_ID_FOUND; + + /* Check if we at least know the family of devices */ + for (unsigned int i = 0; i < ARRAY_SIZE(mspm0_finf); i++) { + if (mspm0_finf[i].part_num == pnum) { + minfo_idx = i; + minfo = &mspm0_finf[i]; + probe_status = MSPM0_DEV_ID_FOUND; + break; + } + } + + /* Initialize part index selector*/ + unsigned char pinfo_idx = 0xff; + + /* + * If we can identify the part number then we will attempt to identify + * the specific chip. Otherwise, if we do not know the part number then + * it would be useless to identify the specific chip. + */ + if (probe_status == MSPM0_DEV_ID_FOUND) { + /* Can we specifically identify the chip */ + for (unsigned int i = 0; i < minfo->part_count; i++) { + if (minfo->part_info[i].part == part + && minfo->part_info[i].variant == variant) { + pinfo_idx = i; + probe_status = MSPM0_DEV_PART_ID_FOUND; + break; + } + } + } + + /* + * We will check the status of our probe within this switch-case statement + * using these three scenarios. + * + * 1) Device, part, and variant ID is unknown. + * 2) Device ID is known but the part/variant ID is unknown. + * 3) Device ID and part/variant ID is known + * + * For scenario 1, we allow the user to continue because if the + * manufacturer matches TI's JEDEC value and ALWAYS_1 from the device ID + * field is correct then the assumption the user is using an MSPM0 device + * can be made. + */ + switch (probe_status) { + case MSPM0_NO_ID_FOUND: + mspm0_info->name = "mspm0x"; + LOG_INFO("Unidentified PART[0x%x]/variant[0x%x" + "], unknown DeviceID[0x%x" + "]. Attempting to proceed as %s.", part, variant, pnum, + mspm0_info->name); + break; + case MSPM0_DEV_ID_FOUND: + mspm0_info->name = mspm0_finf[minfo_idx].family_name; + LOG_INFO("Unidentified PART[0x%x]/variant[0x%x" + "], known DeviceID[0x%x" + "]. Attempting to proceed as %s.", part, variant, pnum, + mspm0_info->name); + break; + case MSPM0_DEV_PART_ID_FOUND: + default: + mspm0_info->name = mspm0_finf[minfo_idx].part_info[pinfo_idx].part_name; + LOG_DEBUG("Part: %s detected", mspm0_info->name); + break; + } + + mspm0_info->did = did; + mspm0_info->version = version; + mspm0_info->data_flash_size_kb = mspm0_extract_val(flashram, 31, 26); + mspm0_info->main_flash_size_kb = mspm0_extract_val(flashram, 11, 0); + mspm0_info->main_flash_num_banks = mspm0_extract_val(flashram, 13, 12) + 1; + mspm0_info->sram_size_kb = mspm0_extract_val(flashram, 25, 16); + mspm0_info->flash_version = mspm0_extract_val(flashdesc, 15, 12); + + /* + * Hardcode flash_word_size unless we find some other pattern + * See section 7.7 (Foot note mentions the flash word size). + * almost all values seem to be 8 bytes, but if there are variance, + * then we should update mspm0_part_info structure with this info. + */ + mspm0_info->flash_word_size_bytes = 8; + + LOG_DEBUG("Detected: main flash: %uKb in %u banks, sram: %uKb, data flash: %uKb", + mspm0_info->main_flash_size_kb, mspm0_info->main_flash_num_banks, + mspm0_info->sram_size_kb, mspm0_info->data_flash_size_kb); + + return ERROR_OK; +} + +/* + * Decode error values + */ +static const struct { + const unsigned char bit_offset; + const char *fail_string; +} mspm0_fctl_fail_decode_strings[] = { + { 2, "CMDINPROGRESS" }, + { 4, "FAILWEPROT" }, + { 5, "FAILVERIFY" }, + { 6, "FAILILLADDR" }, + { 7, "FAILMODE" }, + { 12, "FAILMISC" }, +}; + +static const char *mspm0_fctl_translate_ret_err(unsigned int return_code) +{ + for (unsigned int i = 0; i < ARRAY_SIZE(mspm0_fctl_fail_decode_strings); i++) { + if (return_code & BIT(mspm0_fctl_fail_decode_strings[i].bit_offset)) + return mspm0_fctl_fail_decode_strings[i].fail_string; + } + + /* If unknown error notify the user*/ + return "FAILUNKNOWN"; +} + +static int mspm0_fctl_get_sector_reg(struct flash_bank *bank, unsigned int addr, + unsigned int *reg, unsigned int *sector_mask) +{ + struct mspm0_flash_bank *mspm0_info = bank->driver_priv; + struct target *target = bank->target; + int ret = ERROR_OK; + unsigned int sector_num = (addr >> 10); + unsigned int sector_in_bank = sector_num; + unsigned int phys_sector_num = sector_num; + uint32_t sysctl_sec_status; + unsigned int exec_upper_bank; + + /* + * If the device has dual banks we will need to check if it is configured + * to execute from the upper bank. In the scenario that we are executing + * from upper bank then we will need to protect it using CMDWEPROTA rather + * than CMDWEPROTB. We also need to take into account what sector + * we're using when going between banks. + */ + if (mspm0_info->main_flash_num_banks > 1 && + bank->base == MSPM0_FLASH_BASE_MAIN) { + ret = target_read_u32(target, SYSCTL_SECCFG_SECSTATUS, &sysctl_sec_status); + if (ret != ERROR_OK) + return ret; + exec_upper_bank = mspm0_extract_val(sysctl_sec_status, 12, 12); + if (exec_upper_bank) { + if (sector_num > (mspm0_info->main_flash_size_kb / 2)) { + phys_sector_num = + sector_num - (mspm0_info->main_flash_size_kb / 2); + } else { + phys_sector_num = + sector_num + (mspm0_info->main_flash_size_kb / 2); + } + } + sector_in_bank = + sector_num % (mspm0_info->main_flash_size_kb / + mspm0_info->main_flash_num_banks); + } + + /* + * NOTE: MSPM0 devices of version A will use CMDWEPROTA and CMDWEPROTB + * for MAIN flash. CMDWEPROTC is included in the TRM/DATASHEET but for + * all practical purposes, it is considered reserved. If the flash + * version on the device is version B, then we will only use + * CMDWEPROTB for MAIN and DATA flash if the device has it. + */ + switch (bank->base) { + case MSPM0_FLASH_BASE_MAIN: + case MSPM0_FLASH_BASE_DATA: + if (mspm0_info->flash_version < FCTL_FEATURE_VER_B) { + /* Use CMDWEPROTA */ + if (phys_sector_num < 32) { + *sector_mask = BIT(phys_sector_num); + *reg = FCTL_REG_CMDWEPROTA; + } + + /* Use CMDWEPROTB */ + if (phys_sector_num >= 32 && sector_in_bank < 256) { + /* Dual bank system */ + if (mspm0_info->main_flash_num_banks > 1) + *sector_mask = BIT(sector_in_bank / 8); + else /* Single bank system */ + *sector_mask = BIT((sector_in_bank - 32) / 8); + *reg = FCTL_REG_CMDWEPROTB; + } + } else { + *sector_mask = BIT((sector_in_bank / 8) % 32); + *reg = FCTL_REG_CMDWEPROTB; + } + break; + case MSPM0_FLASH_BASE_NONMAIN: + *sector_mask = BIT(sector_num % 32); + *reg = FCTL_REG_CMDWEPROTNM; + break; + default: + /* + * Not expected to reach here due to check in mspm0_address_check() + * but adding it as another layer of safety. + */ + ret = ERROR_FLASH_DST_OUT_OF_BANK; + break; + } + + if (ret != ERROR_OK) + LOG_ERROR("Unable to map sector protect reg for address 0x%08x", addr); + + return ret; +} + +static int mspm0_address_check(struct flash_bank *bank, unsigned int addr) +{ + struct mspm0_flash_bank *mspm0_info = bank->driver_priv; + unsigned int flash_main_size = mspm0_info->main_flash_size_kb * 1024; + unsigned int flash_data_size = mspm0_info->data_flash_size_kb * 1024; + int ret = ERROR_FLASH_SECTOR_INVALID; + + /* + * Before unprotecting any memory lets make sure that the address and + * bank given is a known bank and whether or not the address falls under + * the proper bank. + */ + switch (bank->base) { + case MSPM0_FLASH_BASE_MAIN: + if (addr <= (MSPM0_FLASH_BASE_MAIN + flash_main_size)) + ret = ERROR_OK; + break; + case MSPM0_FLASH_BASE_NONMAIN: + if (addr >= MSPM0_FLASH_BASE_NONMAIN && addr <= MSPM0_FLASH_END_NONMAIN) + ret = ERROR_OK; + break; + case MSPM0_FLASH_BASE_DATA: + if (addr >= MSPM0_FLASH_BASE_DATA && + addr <= (MSPM0_FLASH_BASE_DATA + flash_data_size)) + ret = ERROR_OK; + break; + default: + ret = ERROR_FLASH_DST_OUT_OF_BANK; + break; + } + + return ret; +} + +static int mspm0_fctl_unprotect_sector(struct flash_bank *bank, unsigned int addr) +{ + struct target *target = bank->target; + unsigned int reg = 0x0; + uint32_t sector_mask = 0x0; + int ret; + + ret = mspm0_address_check(bank, addr); + switch (ret) { + case ERROR_FLASH_SECTOR_INVALID: + LOG_ERROR("Unable to map sector protect reg for address 0x%08x", addr); + break; + case ERROR_FLASH_DST_OUT_OF_BANK: + LOG_ERROR("Unable to determine which bank to use 0x%08x", addr); + break; + default: + mspm0_fctl_get_sector_reg(bank, addr, ®, §or_mask); + ret = target_write_u32(target, reg, ~sector_mask); + break; + } + + return ret; +} + +static int mspm0_fctl_cfg_command(struct flash_bank *bank, + uint32_t addr, + uint32_t cmd, + uint32_t byte_en) +{ + struct target *target = bank->target; + + /* + * Configure the flash operation within the CMDTYPE register, byte_en + * bits if needed, and then set the address where the flash operation + * will execute. + */ + int retval = target_write_u32(target, FCTL_REG_CMDTYPE, cmd); + if (retval != ERROR_OK) + return retval; + if (byte_en != 0) { + retval = target_write_u32(target, FCTL_REG_CMDBYTEN, byte_en); + if (retval != ERROR_OK) + return retval; + } + + return target_write_u32(target, FCTL_REG_CMDADDR, addr); +} + +static int mspm0_fctl_wait_cmd_ok(struct flash_bank *bank) +{ + struct target *target = bank->target; + uint32_t return_code = 0; + int64_t start_ms; + int64_t elapsed_ms; + + start_ms = timeval_ms(); + while ((return_code & FCTL_STATCMD_CMDDONE_MASK) != FCTL_STATCMD_CMDDONE_STATDONE) { + int retval = target_read_u32(target, FCTL_REG_STATCMD, &return_code); + if (retval != ERROR_OK) + return retval; + + elapsed_ms = timeval_ms() - start_ms; + if (elapsed_ms > 500) + keep_alive(); + if (elapsed_ms > MSPM0_FLASH_TIMEOUT_MS) + break; + } + + if ((return_code & FCTL_STATCMD_CMDPASS_MASK) != FCTL_STATCMD_CMDPASS_STATPASS) { + LOG_ERROR("Flash command failed: %s", mspm0_fctl_translate_ret_err(return_code)); + return ERROR_FAIL; + } + + return ERROR_OK; +} + +static int mspm0_fctl_sector_erase(struct flash_bank *bank, uint32_t addr) +{ + struct target *target = bank->target; + + /* + * TRM Says: + * Note that the CMDWEPROTx registers are reset to a protected state + * at the end of all program and erase operations. These registers + * must be re-configured by software before a new operation is + * initiated. + * + * This means that as we start erasing sector by sector, the protection + * registers are reset and need to be unprotected *again* for the next + * erase operation. Unfortunately, this means that we cannot do a unitary + * unprotect operation independent of flash erase operation + */ + int retval = mspm0_fctl_unprotect_sector(bank, addr); + if (retval != ERROR_OK) { + LOG_ERROR("Unprotecting sector of memory at address 0x%08" PRIx32 + " failed", addr); + return retval; + } + + /* Actual erase operation */ + retval = mspm0_fctl_cfg_command(bank, addr, + (FCTL_CMDTYPE_COMMAND_ERASE | FCTL_CMDTYPE_SIZE_SECTOR), 0); + if (retval != ERROR_OK) + return retval; + retval = target_write_u32(target, FCTL_REG_CMDEXEC, FCTL_CMDEXEC_VAL_EXECUTE); + if (retval != ERROR_OK) + return retval; + + return mspm0_fctl_wait_cmd_ok(bank); +} + +static int mspm0_protect_check(struct flash_bank *bank) +{ + struct mspm0_flash_bank *mspm0_info = bank->driver_priv; + + if (mspm0_info->did == 0) + return ERROR_FLASH_BANK_NOT_PROBED; + + /* + * TRM Says: + * Note that the CMDWEPROTx registers are reset to a protected state + * at the end of all program and erase operations. These registers + * must be re-configured by software before a new operation is + * initiated. + * + * This means that when any flash operation is performed at a block level, + * the block is locked back again. This prevents usage where we can set a + * protection level once at the flash level and then do erase / write + * operation without touching the protection register (since it is + * reset by hardware automatically). In effect, we cannot use the hardware + * defined protection scheme in openOCD. + * + * To deal with this protection scheme, the CMDWEPROTx register that + * correlates to the sector is modified at the time of operation and as far + * openOCD is concerned, the flash operates as completely un-protected + * flash. + */ + for (unsigned int i = 0; i < bank->num_sectors; i++) + bank->sectors[i].is_protected = 0; + + return ERROR_OK; +} + +static int mspm0_erase(struct flash_bank *bank, unsigned int first, unsigned int last) +{ + struct target *target = bank->target; + struct mspm0_flash_bank *mspm0_info = bank->driver_priv; + int retval = ERROR_OK; + uint32_t protect_reg_cache[MSPM0_MAX_PROTREGS]; + + if (bank->target->state != TARGET_HALTED) { + LOG_ERROR("Please halt target for erasing flash"); + return ERROR_TARGET_NOT_HALTED; + } + + if (mspm0_info->did == 0) + return ERROR_FLASH_BANK_NOT_PROBED; + + /* Pick a copy of the current protection config for later restoration */ + for (unsigned int i = 0; i < mspm0_info->protect_reg_count; i++) { + retval = target_read_u32(target, + mspm0_info->protect_reg_base + (i * 4), + &protect_reg_cache[i]); + if (retval != ERROR_OK) { + LOG_ERROR("Failed saving flashctl protection status"); + return retval; + } + } + + switch (bank->base) { + case MSPM0_FLASH_BASE_MAIN: + for (unsigned int csa = first; csa <= last; csa++) { + unsigned int addr = csa * mspm0_info->sector_size; + retval = mspm0_fctl_sector_erase(bank, addr); + if (retval != ERROR_OK) + LOG_ERROR("Sector erase on MAIN failed at address 0x%08x " + "(sector: %u)", addr, csa); + } + break; + case MSPM0_FLASH_BASE_NONMAIN: + retval = mspm0_fctl_sector_erase(bank, MSPM0_FLASH_BASE_NONMAIN); + if (retval != ERROR_OK) + LOG_ERROR("Sector erase on NONMAIN failed"); + break; + case MSPM0_FLASH_BASE_DATA: + for (unsigned int csa = first; csa <= last; csa++) { + unsigned int addr = (MSPM0_FLASH_BASE_DATA + + (csa * mspm0_info->sector_size)); + retval = mspm0_fctl_sector_erase(bank, addr); + if (retval != ERROR_OK) + LOG_ERROR("Sector erase on DATA bank failed at address 0x%08x " + "(sector: %u)", addr, csa); + } + break; + default: + LOG_ERROR("Invalid memory region access"); + retval = ERROR_FLASH_BANK_INVALID; + break; + } + + /* If there were any issues in our checks, return the error */ + if (retval != ERROR_OK) + return retval; + + /* + * TRM Says: + * Note that the CMDWEPROTx registers are reset to a protected state + * at the end of all program and erase operations. These registers + * must be re-configured by software before a new operation is + * initiated + * Let us just Dump the protection registers back to the system. + * That way we retain the protection status as requested by the user + */ + for (unsigned int i = 0; i < mspm0_info->protect_reg_count; i++) { + retval = target_write_u32(target, mspm0_info->protect_reg_base + (i * 4), + protect_reg_cache[i]); + if (retval != ERROR_OK) { + LOG_ERROR("Failed re-applying protection status of flashctl"); + return retval; + } + } + + return retval; +} + +static int mspm0_write(struct flash_bank *bank, const unsigned char *buffer, + unsigned int offset, unsigned int count) +{ + struct target *target = bank->target; + struct mspm0_flash_bank *mspm0_info = bank->driver_priv; + uint32_t protect_reg_cache[MSPM0_MAX_PROTREGS]; + int retval; + + /* + * XXX: TRM Says: + * The number of program operations applied to a given word line must be + * monitored to ensure that the maximum word line program limit before + * erase is not violated. + * + * There is no reasonable way we can maintain that state in OpenOCD. So, + * Let the manufacturing path figure this out. + */ + + if (bank->target->state != TARGET_HALTED) { + LOG_ERROR("Please halt target for programming flash"); + return ERROR_TARGET_NOT_HALTED; + } + + if (mspm0_info->did == 0) + return ERROR_FLASH_BANK_NOT_PROBED; + + /* + * Pick a copy of the current protection config for later restoration + * We need to restore these regs after every write, so instead of trying + * to figure things out on the fly, we just context save and restore + */ + for (unsigned int i = 0; i < mspm0_info->protect_reg_count; i++) { + retval = target_read_u32(target, + mspm0_info->protect_reg_base + (i * 4), + &protect_reg_cache[i]); + if (retval != ERROR_OK) { + LOG_ERROR("Failed saving flashctl protection status"); + return retval; + } + } + + /* Add proper memory offset for bank being written to */ + unsigned int addr = bank->base + offset; + + while (count) { + unsigned int num_bytes_to_write; + uint32_t bytes_en; + + /* + * If count is not 64 bit aligned, we will do byte wise op to keep things simple + * Usually this might mean we need to additional write ops towards + * trailing edge, but that is a tiny penalty for image downloads. + * NOTE: we are going to assume the device does not support multi-word + * programming - there does not seem to be discoverability! + */ + if (count < mspm0_info->flash_word_size_bytes) + num_bytes_to_write = count; + else + num_bytes_to_write = mspm0_info->flash_word_size_bytes; + + /* Data bytes to write */ + bytes_en = (1 << num_bytes_to_write) - 1; + /* ECC chunks to write */ + switch (mspm0_info->flash_word_size_bytes) { + case 8: + bytes_en |= BIT(8); + break; + case 16: + bytes_en |= BIT(16); + bytes_en |= (num_bytes_to_write > 8) ? BIT(17) : 0; + break; + default: + LOG_ERROR("Invalid flash_word_size_bytes %d", + mspm0_info->flash_word_size_bytes); + return ERROR_FAIL; + } + + retval = mspm0_fctl_cfg_command(bank, addr, + (FCTL_CMDTYPE_COMMAND_PROGRAM | FCTL_CMDTYPE_SIZE_ONEWORD), + bytes_en); + if (retval != ERROR_OK) + return retval; + + retval = mspm0_fctl_unprotect_sector(bank, addr); + if (retval != ERROR_OK) + return retval; + + retval = target_write_buffer(target, FCTL_REG_CMDDATA0, num_bytes_to_write, buffer); + if (retval != ERROR_OK) + return retval; + + addr += num_bytes_to_write; + buffer += num_bytes_to_write; + count -= num_bytes_to_write; + + retval = target_write_u32(target, FCTL_REG_CMDEXEC, FCTL_CMDEXEC_VAL_EXECUTE); + if (retval != ERROR_OK) + return retval; + + retval = mspm0_fctl_wait_cmd_ok(bank); + if (retval != ERROR_OK) + return retval; + } + + /* + * TRM Says: + * Note that the CMDWEPROTx registers are reset to a protected state + * at the end of all program and erase operations. These registers + * must be re-configured by software before a new operation is + * initiated + * Let us just Dump the protection registers back to the system. + * That way we retain the protection status as requested by the user + */ + for (unsigned int i = 0; i < mspm0_info->protect_reg_count; i++) { + retval = target_write_u32(target, + mspm0_info->protect_reg_base + (i * 4), + protect_reg_cache[i]); + if (retval != ERROR_OK) { + LOG_ERROR("Failed re-applying protection status of flashctl"); + return retval; + } + } + + return ERROR_OK; +} + +static int mspm0_probe(struct flash_bank *bank) +{ + struct mspm0_flash_bank *mspm0_info = bank->driver_priv; + + /* + * If this is a mspm0 chip, it has flash; probe() is just + * to figure out how much is present. Only do it once. + */ + if (mspm0_info->did != 0) + return ERROR_OK; + + /* + * mspm0_read_part_info() already handled error checking and + * reporting. Note that it doesn't write, so we don't care about + * whether the target is halted or not. + */ + int retval = mspm0_read_part_info(bank); + if (retval != ERROR_OK) + return retval; + + if (bank->sectors) { + free(bank->sectors); + bank->sectors = NULL; + } + + bank->write_start_alignment = 4; + bank->write_end_alignment = 4; + + switch (bank->base) { + case MSPM0_FLASH_BASE_NONMAIN: + bank->size = 1024; + bank->num_sectors = 0x1; + mspm0_info->protect_reg_base = FCTL_REG_CMDWEPROTNM; + mspm0_info->protect_reg_count = 1; + break; + case MSPM0_FLASH_BASE_MAIN: + bank->size = (mspm0_info->main_flash_size_kb * 1024); + bank->num_sectors = bank->size / mspm0_info->sector_size; + /* + * If the feature version bit read from the FCTL_REG_DESC is + * greater than or equal to 0xA then it means that the device + * will exclusively use CMDWEPROTB ONLY for MAIN memory protection + */ + if (mspm0_info->flash_version >= FCTL_FEATURE_VER_B) { + mspm0_info->protect_reg_base = FCTL_REG_CMDWEPROTB; + mspm0_info->protect_reg_count = 1; + } else { + mspm0_info->protect_reg_base = FCTL_REG_CMDWEPROTA; + mspm0_info->protect_reg_count = 3; + } + break; + case MSPM0_FLASH_BASE_DATA: + if (!mspm0_info->data_flash_size_kb) { + LOG_INFO("Data region NOT available!"); + bank->size = 0x0; + bank->num_sectors = 0x0; + return ERROR_OK; + } + /* + * Any MSPM0 device containing data bank will have a flashctl + * feature version of 0xA or higher. Since data bank is treated + * like MAIN memory, it will also exclusively use CMDWEPROTB for + * protection. + */ + bank->size = (mspm0_info->data_flash_size_kb * 1024); + bank->num_sectors = bank->size / mspm0_info->sector_size; + mspm0_info->protect_reg_base = FCTL_REG_CMDWEPROTB; + mspm0_info->protect_reg_count = 1; + break; + default: + LOG_ERROR("Invalid bank address " TARGET_ADDR_FMT, + bank->base); + return ERROR_FAIL; + } + + bank->sectors = calloc(bank->num_sectors, sizeof(struct flash_sector)); + if (!bank->sectors) { + LOG_ERROR("Out of memory for sectors!"); + return ERROR_FAIL; + } + for (unsigned int i = 0; i < bank->num_sectors; i++) { + bank->sectors[i].offset = i * mspm0_info->sector_size; + bank->sectors[i].size = mspm0_info->sector_size; + bank->sectors[i].is_erased = -1; + } + + return ERROR_OK; +} + +const struct flash_driver mspm0_flash = { + .name = "mspm0", + .flash_bank_command = mspm0_flash_bank_command, + .erase = mspm0_erase, + .protect = NULL, + .write = mspm0_write, + .read = default_flash_read, + .probe = mspm0_probe, + .auto_probe = mspm0_probe, + .erase_check = default_flash_blank_check, + .protect_check = mspm0_protect_check, + .info = get_mspm0_info, + .free_driver_priv = default_flash_free_driver_priv, +}; diff --git a/src/flash/nor/rsl10.c b/src/flash/nor/rsl10.c index c286e9a..c330997 100644 --- a/src/flash/nor/rsl10.c +++ b/src/flash/nor/rsl10.c @@ -155,11 +155,6 @@ static int rsl10_get_probed_chip_if_halted(struct flash_bank *bank, struct rsl10 static int rsl10_protect_check(struct flash_bank *bank) { - struct rsl10_bank *nbank = bank->driver_priv; - struct rsl10_info *chip = nbank->chip; - - assert(chip); - uint32_t status; int retval = target_read_u32(bank->target, RSL10_FLASH_REG_IF_STATUS, &status); diff --git a/src/flash/nor/stm32l4x.c b/src/flash/nor/stm32l4x.c index 3062fca..fa57db8 100644 --- a/src/flash/nor/stm32l4x.c +++ b/src/flash/nor/stm32l4x.c @@ -370,11 +370,15 @@ static const struct stm32l4_rev stm32u53_u54xx_revs[] = { static const struct stm32l4_rev stm32u57_u58xx_revs[] = { { 0x1000, "A" }, { 0x1001, "Z" }, { 0x1003, "Y" }, { 0x2000, "B" }, - { 0x2001, "X" }, { 0x3000, "C" }, { 0x3001, "W" }, + { 0x2001, "X" }, { 0x3000, "C" }, { 0x3001, "W" }, { 0x3007, "U" }, }; static const struct stm32l4_rev stm32u59_u5axx_revs[] = { - { 0x3001, "X" }, + { 0x3001, "X" }, { 0x3002, "W" }, +}; + +static const struct stm32l4_rev stm32u5f_u5gxx_revs[] = { + { 0x1000, "A" }, { 0x1001, "Z" }, }; static const struct stm32l4_rev stm32wba5x_revs[] = { @@ -675,6 +679,18 @@ static const struct stm32l4_part_info stm32l4_parts[] = { .otp_size = 512, }, { + .id = DEVID_STM32U5F_U5GXX, + .revs = stm32u5f_u5gxx_revs, + .num_revs = ARRAY_SIZE(stm32u5f_u5gxx_revs), + .device_str = "STM32U5F/U5Gxx", + .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_STM32WBA5X, .revs = stm32wba5x_revs, .num_revs = ARRAY_SIZE(stm32wba5x_revs), @@ -2095,6 +2111,7 @@ static int stm32l4_probe(struct flash_bank *bank) case DEVID_STM32U53_U54XX: case DEVID_STM32U57_U58XX: case DEVID_STM32U59_U5AXX: + case DEVID_STM32U5F_U5GXX: /* 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 @@ -2102,7 +2119,7 @@ static int stm32l4_probe(struct flash_bank *bank) * 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: + * U59x/U5Ax/U5Fx/U5Gx 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 diff --git a/src/flash/nor/stm32l4x.h b/src/flash/nor/stm32l4x.h index f152c9f..3199d4f 100644 --- a/src/flash/nor/stm32l4x.h +++ b/src/flash/nor/stm32l4x.h @@ -103,6 +103,7 @@ #define DEVID_STM32L4R_L4SXX 0x470 #define DEVID_STM32L4P_L4QXX 0x471 #define DEVID_STM32L55_L56XX 0x472 +#define DEVID_STM32U5F_U5GXX 0x476 #define DEVID_STM32G49_G4AXX 0x479 #define DEVID_STM32U59_U5AXX 0x481 #define DEVID_STM32U57_U58XX 0x482 diff --git a/src/helper/command.c b/src/helper/command.c index d90d341..3d4379d 100644 --- a/src/helper/command.c +++ b/src/helper/command.c @@ -41,6 +41,7 @@ static int jim_command_dispatch(Jim_Interp *interp, int argc, Jim_Obj * const *a static int help_add_command(struct command_context *cmd_ctx, const char *cmd_name, const char *help_text, const char *usage_text); static int help_del_command(struct command_context *cmd_ctx, const char *cmd_name); +static enum command_mode get_command_mode(Jim_Interp *interp, const char *cmd_name); /* set of functions to wrap jimtcl internal data */ static inline bool jimcmd_is_proc(Jim_Cmd *cmd) @@ -673,7 +674,7 @@ COMMAND_HANDLER(handle_echo) } if (CMD_ARGC != 1) - return ERROR_FAIL; + return ERROR_COMMAND_SYNTAX_ERROR; LOG_USER("%s", CMD_ARGV[0]); return ERROR_OK; @@ -779,24 +780,7 @@ static COMMAND_HELPER(command_help_show, struct help_entry *c, if (is_match && show_help) { char *msg; - /* TODO: factorize jim_command_mode() to avoid running jim command here */ - char *request = alloc_printf("command mode %s", c->cmd_name); - if (!request) { - LOG_ERROR("Out of memory"); - return ERROR_FAIL; - } - int retval = Jim_Eval(CMD_CTX->interp, request); - free(request); - enum command_mode mode = COMMAND_UNKNOWN; - if (retval != JIM_ERR) { - const char *result = Jim_GetString(Jim_GetResult(CMD_CTX->interp), NULL); - if (!strcmp(result, "any")) - mode = COMMAND_ANY; - else if (!strcmp(result, "config")) - mode = COMMAND_CONFIG; - else if (!strcmp(result, "exec")) - mode = COMMAND_EXEC; - } + enum command_mode mode = get_command_mode(CMD_CTX->interp, c->cmd_name); /* Normal commands are runtime-only; highlight exceptions */ if (mode != COMMAND_EXEC) { @@ -809,6 +793,7 @@ static COMMAND_HELPER(command_help_show, struct help_entry *c, case COMMAND_ANY: stage_msg = " (command valid any time)"; break; + case COMMAND_UNKNOWN: default: stage_msg = " (?mode error?)"; break; @@ -817,11 +802,13 @@ static COMMAND_HELPER(command_help_show, struct help_entry *c, } else msg = alloc_printf("%s", c->help ? c->help : ""); - if (msg) { - command_help_show_wrap(msg, n + 3, n + 3); - free(msg); - } else - return -ENOMEM; + if (!msg) { + LOG_ERROR("Out of memory"); + return ERROR_FAIL; + } + + command_help_show_wrap(msg, n + 3, n + 3); + free(msg); } return ERROR_OK; @@ -936,35 +923,41 @@ static int jim_command_dispatch(Jim_Interp *interp, int argc, Jim_Obj * const *a return retval; } +static enum command_mode get_command_mode(Jim_Interp *interp, const char *cmd_name) +{ + if (!cmd_name) + return COMMAND_UNKNOWN; + + Jim_Obj *s = Jim_NewStringObj(interp, cmd_name, -1); + Jim_IncrRefCount(s); + Jim_Cmd *cmd = Jim_GetCommand(interp, s, JIM_NONE); + Jim_DecrRefCount(interp, s); + + if (!cmd || !(jimcmd_is_proc(cmd) || jimcmd_is_oocd_command(cmd))) + return COMMAND_UNKNOWN; + + /* tcl proc */ + if (jimcmd_is_proc(cmd)) + return COMMAND_ANY; + + struct command *c = jimcmd_privdata(cmd); + return c->mode; +} + static int jim_command_mode(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { struct command_context *cmd_ctx = current_command_context(interp); - enum command_mode mode; + enum command_mode mode = cmd_ctx->mode; if (argc > 1) { char *full_name = alloc_concatenate_strings(argc - 1, argv + 1); if (!full_name) return JIM_ERR; - Jim_Obj *s = Jim_NewStringObj(interp, full_name, -1); - Jim_IncrRefCount(s); - Jim_Cmd *cmd = Jim_GetCommand(interp, s, JIM_NONE); - Jim_DecrRefCount(interp, s); - free(full_name); - if (!cmd || !(jimcmd_is_proc(cmd) || jimcmd_is_oocd_command(cmd))) { - Jim_SetResultString(interp, "unknown", -1); - return JIM_OK; - } - if (jimcmd_is_proc(cmd)) { - /* tcl proc */ - mode = COMMAND_ANY; - } else { - struct command *c = jimcmd_privdata(cmd); + mode = get_command_mode(interp, full_name); - mode = c->mode; - } - } else - mode = cmd_ctx->mode; + free(full_name); + } const char *mode_str; switch (mode) { @@ -977,6 +970,7 @@ static int jim_command_mode(Jim_Interp *interp, int argc, Jim_Obj *const *argv) case COMMAND_EXEC: mode_str = "exec"; break; + case COMMAND_UNKNOWN: default: mode_str = "unknown"; break; diff --git a/src/helper/jep106.inc b/src/helper/jep106.inc index 53d0355..8bbaf4c 100644 --- a/src/helper/jep106.inc +++ b/src/helper/jep106.inc @@ -2,18 +2,18 @@ /* * The manufacturer's standard identification code list appears in JEP106. - * Copyright (c) 2024 JEDEC. All rights reserved. + * Copyright (c) 2025 JEDEC. All rights reserved. * * JEP106 is regularly updated. For the current manufacturer's standard * identification code list, please visit the JEDEC website at www.jedec.org . */ -/* This file is aligned to revision JEP106BK September 2024. */ +/* This file is aligned to revision JEP106BL February 2025. */ [0][0x01 - 1] = "AMD", [0][0x02 - 1] = "AMI", [0][0x03 - 1] = "Fairchild", -[0][0x04 - 1] = "Fujitsu", +[0][0x04 - 1] = "RAMXEED Limited", [0][0x05 - 1] = "GTE", [0][0x06 - 1] = "Harris", [0][0x07 - 1] = "Hitachi", @@ -1373,7 +1373,7 @@ [10][0x65 - 1] = "Esperanto Technologies", [10][0x66 - 1] = "JinSheng Electronic (Shenzhen) Co Ltd", [10][0x67 - 1] = "Shenzhen Shi Bolunshuai Technology", -[10][0x68 - 1] = "Shanghai Rui Xuan Information Tech", +[10][0x68 - 1] = "Shanghai Ruixuan Information Tech", [10][0x69 - 1] = "Fraunhofer IIS", [10][0x6a - 1] = "Kandou Bus SA", [10][0x6b - 1] = "Acer", @@ -1745,7 +1745,7 @@ [13][0x5f - 1] = "Guangdong OPPO Mobile Telecommunication", [13][0x60 - 1] = "Akeana", [13][0x61 - 1] = "Lyczar", -[13][0x62 - 1] = "Shenzhen Qiji Technology Co Ltd", +[13][0x62 - 1] = "QJTEK", [13][0x63 - 1] = "Shenzhen Shangzhaoyuan Technology", [13][0x64 - 1] = "Han Stor", [13][0x65 - 1] = "China Micro Semicon Co., Ltd.", @@ -1893,7 +1893,7 @@ [14][0x75 - 1] = "HOGE Technology Co Ltd", [14][0x76 - 1] = "United Micro Technology (Shenzhen) Co", [14][0x77 - 1] = "Fabric of Truth Inc", -[14][0x78 - 1] = "Epitech", +[14][0x78 - 1] = "Elpitech", [14][0x79 - 1] = "Elitestek", [14][0x7a - 1] = "Cornelis Networks Inc", [14][0x7b - 1] = "WingSemi Technologies Co Ltd", @@ -1916,7 +1916,7 @@ [15][0x0e - 1] = "Shenzhen Ranshuo Technology Co Limited", [15][0x0f - 1] = "ScaleFlux", [15][0x10 - 1] = "XC Memory", -[15][0x11 - 1] = "Guangzhou Beimu Technology Co., Ltd", +[15][0x11 - 1] = "Guangzhou Beimu Technology Co Ltd", [15][0x12 - 1] = "Rays Semiconductor Nanjing Co Ltd", [15][0x13 - 1] = "Milli-Centi Intelligence Technology Jiangsu", [15][0x14 - 1] = "Zilia Technologies", @@ -1925,7 +1925,7 @@ [15][0x17 - 1] = "Nanjing Houmo Technology Co Ltd", [15][0x18 - 1] = "Suzhou Yige Technology Co Ltd", [15][0x19 - 1] = "Shenzhen Techwinsemi Technology Co Ltd", -[15][0x1a - 1] = "Pure Array Technology (Shanghai) Co. Ltd", +[15][0x1a - 1] = "Pure Array Technology (Shanghai) Co Ltd", [15][0x1b - 1] = "Shenzhen Techwinsemi Technology Udstore", [15][0x1c - 1] = "RISE MODE", [15][0x1d - 1] = "NEWREESTAR", @@ -2016,4 +2016,37 @@ [15][0x72 - 1] = "KEYSOM", [15][0x73 - 1] = "Shenzhen YYF Info Tech Co Ltd", [15][0x74 - 1] = "Sharetronics Data Technology Co Ltd", +[15][0x75 - 1] = "AptCore Limited", +[15][0x76 - 1] = "Uchampion Semiconductor Co Ltd", +[15][0x77 - 1] = "YCT Semiconductor", +[15][0x78 - 1] = "FADU Inc", +[15][0x79 - 1] = "Hefei CLT Microelectronics Co LTD", +[15][0x7a - 1] = "Smart Technologies (BD) Ltd", +[15][0x7b - 1] = "Zhangdian District Qunyuan Computer Firm", +[15][0x7c - 1] = "Silicon Xpandas Electronics Co Ltd", +[15][0x7d - 1] = "PC Components Y Multimedia S", +[15][0x7e - 1] = "Shenzhen Tanlr Technology Group Co Ltd", +[16][0x01 - 1] = "Shenzhen JIEQING Technology Co Ltd", +[16][0x02 - 1] = "Orionix", +[16][0x03 - 1] = "JoulWatt Technology Co Ltd", +[16][0x04 - 1] = "Tenstorrent", +[16][0x05 - 1] = "Unis Flash Memory Technology (Chengdu)", +[16][0x06 - 1] = "Huatu Stars", +[16][0x07 - 1] = "Ardor Gaming", +[16][0x08 - 1] = "QuanZhou KunFang Semiconductor Co Ltd", +[16][0x09 - 1] = "EIAI PLANET", +[16][0x0a - 1] = "Ningbo Lingkai Semiconductor Technology Inc", +[16][0x0b - 1] = "Shenzhen Hancun Technology Co Ltd", +[16][0x0c - 1] = "Hongkong Manyi Technology Co Limited", +[16][0x0d - 1] = "Shenzhen Storgon Technology Co Ltd", +[16][0x0e - 1] = "YUNTU Microelectronics", +[16][0x0f - 1] = "Essencore", +[16][0x10 - 1] = "Shenzhen Xingyun Lianchuang Computer Tech", +[16][0x11 - 1] = "ShenZhen Aoscar Digital Tech Co Ltd", +[16][0x12 - 1] = "XOC Technologies Inc", +[16][0x13 - 1] = "BOS Semiconductors", +[16][0x14 - 1] = "Eliyan Corp", +[16][0x15 - 1] = "Hangzhou Lishu Technology Co Ltd", +[16][0x16 - 1] = "Tier IV Inc", +[16][0x17 - 1] = "Wuhan Xuanluzhe Network Technology Co", /* EOF */ diff --git a/src/helper/log.h b/src/helper/log.h index e2bb131..ac24f8e 100644 --- a/src/helper/log.h +++ b/src/helper/log.h @@ -85,7 +85,8 @@ struct log_callback { int log_add_callback(log_callback_fn fn, void *priv); int log_remove_callback(log_callback_fn fn, void *priv); -char *alloc_vprintf(const char *fmt, va_list ap); +char *alloc_vprintf(const char *fmt, va_list ap) + __attribute__ ((format (PRINTF_ATTRIBUTE_FORMAT, 1, 0))); char *alloc_printf(const char *fmt, ...) __attribute__ ((format (PRINTF_ATTRIBUTE_FORMAT, 1, 2))); diff --git a/src/jtag/adapter.c b/src/jtag/adapter.c index 04942f7..2fcbd60 100644 --- a/src/jtag/adapter.c +++ b/src/jtag/adapter.c @@ -392,37 +392,22 @@ COMMAND_HANDLER(handle_adapter_name) return ERROR_OK; } -COMMAND_HANDLER(adapter_transports_command) +COMMAND_HANDLER(dump_adapter_driver_list) { - char **transports; - int retval; - - retval = CALL_COMMAND_HANDLER(transport_list_parse, &transports); - if (retval != ERROR_OK) - return retval; - - retval = allow_transports(CMD_CTX, (const char **)transports); - - if (retval != ERROR_OK) { - for (unsigned int i = 0; transports[i]; i++) - free(transports[i]); - free(transports); + for (unsigned int i = 0; adapter_drivers[i]; i++) { + const char *name = adapter_drivers[i]->name; + command_print(CMD, "%u: %s", i + 1, name); } - return retval; + + return ERROR_OK; } COMMAND_HANDLER(handle_adapter_list_command) { - if (strcmp(CMD_NAME, "list") == 0 && CMD_ARGC > 0) + if (CMD_ARGC) return ERROR_COMMAND_SYNTAX_ERROR; - command_print(CMD, "The following debug adapters are available:"); - for (unsigned int i = 0; adapter_drivers[i]; i++) { - const char *name = adapter_drivers[i]->name; - command_print(CMD, "%u: %s", i + 1, name); - } - - return ERROR_OK; + return CALL_COMMAND_HANDLER(dump_adapter_driver_list); } COMMAND_HANDLER(handle_adapter_driver_command) @@ -459,7 +444,8 @@ COMMAND_HANDLER(handle_adapter_driver_command) */ LOG_ERROR("The specified debug interface was not found (%s)", CMD_ARGV[0]); - CALL_COMMAND_HANDLER(handle_adapter_list_command); + command_print(CMD, "The following adapter drivers are available:"); + CALL_COMMAND_HANDLER(dump_adapter_driver_list); return ERROR_JTAG_INVALID_INTERFACE; } @@ -1138,13 +1124,6 @@ static const struct command_registration adapter_command_handlers[] = { .chain = adapter_srst_command_handlers, }, { - .name = "transports", - .handler = adapter_transports_command, - .mode = COMMAND_CONFIG, - .help = "Declare transports the adapter supports.", - .usage = "transport ...", - }, - { .name = "usb", .mode = COMMAND_ANY, .help = "usb adapter command group", diff --git a/src/jtag/drivers/bcm2835gpio.c b/src/jtag/drivers/bcm2835gpio.c index 095601f..e8689aa 100644 --- a/src/jtag/drivers/bcm2835gpio.c +++ b/src/jtag/drivers/bcm2835gpio.c @@ -427,7 +427,7 @@ static int bcm2835gpio_blink(bool on) return ERROR_OK; } -static struct bitbang_interface bcm2835gpio_bitbang = { +static const struct bitbang_interface bcm2835gpio_bitbang_swd_write_generic = { .read = bcm2835gpio_read, .write = bcm2835gpio_write, .swdio_read = bcm2835_swdio_read, @@ -436,11 +436,19 @@ static struct bitbang_interface bcm2835gpio_bitbang = { .blink = bcm2835gpio_blink, }; +static const struct bitbang_interface bcm2835gpio_bitbang_swd_write_fast = { + .read = bcm2835gpio_read, + .write = bcm2835gpio_write, + .swdio_read = bcm2835_swdio_read, + .swdio_drive = bcm2835_swdio_drive, + .swd_write = bcm2835gpio_swd_write_fast, + .blink = bcm2835gpio_blink, +}; + static int bcm2835gpio_init(void) { LOG_INFO("BCM2835 GPIO JTAG/SWD bitbang driver"); - bitbang_interface = &bcm2835gpio_bitbang; adapter_gpio_config = adapter_gpio_get_config(); if (transport_is_jtag() && !bcm2835gpio_jtag_mode_possible()) { @@ -509,6 +517,8 @@ LOG_INFO("pads conf set to %08x", pads_base[BCM2835_PADS_GPIO_0_27_OFFSET]); initialize_gpio(ADAPTER_GPIO_IDX_TRST); } + const struct bitbang_interface *bcm2835gpio_bitbang = &bcm2835gpio_bitbang_swd_write_generic; + if (transport_is_swd()) { /* swdio and its buffer should be initialized in the order that prevents * two outputs from being connected together. This will occur if the @@ -529,16 +539,18 @@ LOG_INFO("pads conf set to %08x", pads_base[BCM2835_PADS_GPIO_0_27_OFFSET]); if (adapter_gpio_config[ADAPTER_GPIO_IDX_SWCLK].drive == ADAPTER_GPIO_DRIVE_MODE_PUSH_PULL && adapter_gpio_config[ADAPTER_GPIO_IDX_SWDIO].drive == ADAPTER_GPIO_DRIVE_MODE_PUSH_PULL) { LOG_DEBUG("BCM2835 GPIO using fast mode for SWD write"); - bcm2835gpio_bitbang.swd_write = bcm2835gpio_swd_write_fast; + bcm2835gpio_bitbang = &bcm2835gpio_bitbang_swd_write_fast; } else { LOG_DEBUG("BCM2835 GPIO using generic mode for SWD write"); - bcm2835gpio_bitbang.swd_write = bcm2835gpio_swd_write_generic; + assert(bcm2835gpio_bitbang == &bcm2835gpio_bitbang_swd_write_generic); } } initialize_gpio(ADAPTER_GPIO_IDX_SRST); initialize_gpio(ADAPTER_GPIO_IDX_LED); + bitbang_interface = bcm2835gpio_bitbang; + return ERROR_OK; } diff --git a/src/jtag/drivers/cmsis_dap.c b/src/jtag/drivers/cmsis_dap.c index c8a7cf8..be9ebae 100644 --- a/src/jtag/drivers/cmsis_dap.c +++ b/src/jtag/drivers/cmsis_dap.c @@ -39,14 +39,22 @@ #include "cmsis_dap.h" #include "libusb_helper.h" -static const struct cmsis_dap_backend *const cmsis_dap_backends[] = { -#if BUILD_CMSIS_DAP_USB == 1 - &cmsis_dap_usb_backend, +/* Create a dummy backend for 'backend' command if real one does not build */ +#if BUILD_CMSIS_DAP_USB == 0 +const struct cmsis_dap_backend cmsis_dap_usb_backend = { + .name = "usb_bulk", +}; #endif -#if BUILD_CMSIS_DAP_HID == 1 - &cmsis_dap_hid_backend, +#if BUILD_CMSIS_DAP_HID == 0 +const struct cmsis_dap_backend cmsis_dap_hid_backend = { + .name = "hid" +}; #endif + +static const struct cmsis_dap_backend *const cmsis_dap_backends[] = { + &cmsis_dap_usb_backend, + &cmsis_dap_hid_backend, }; /* USB Config */ @@ -261,26 +269,32 @@ static int cmsis_dap_open(void) return ERROR_FAIL; } + int retval = ERROR_FAIL; if (cmsis_dap_backend >= 0) { /* Use forced backend */ backend = cmsis_dap_backends[cmsis_dap_backend]; - if (backend->open(dap, cmsis_dap_vid, cmsis_dap_pid, adapter_get_required_serial()) != ERROR_OK) - backend = NULL; + if (backend->open) + retval = backend->open(dap, cmsis_dap_vid, cmsis_dap_pid, adapter_get_required_serial()); + else + LOG_ERROR("Requested CMSIS-DAP backend is disabled by configure"); + } else { /* Try all backends */ for (unsigned int i = 0; i < ARRAY_SIZE(cmsis_dap_backends); i++) { backend = cmsis_dap_backends[i]; - if (backend->open(dap, cmsis_dap_vid, cmsis_dap_pid, adapter_get_required_serial()) == ERROR_OK) + if (!backend->open) + continue; + + retval = backend->open(dap, cmsis_dap_vid, cmsis_dap_pid, adapter_get_required_serial()); + if (retval == ERROR_OK) break; - else - backend = NULL; } } - if (!backend) { + if (retval != ERROR_OK) { LOG_ERROR("unable to find a matching CMSIS-DAP device"); free(dap); - return ERROR_FAIL; + return retval; } dap->backend = backend; @@ -293,7 +307,8 @@ static int cmsis_dap_open(void) static void cmsis_dap_close(struct cmsis_dap *dap) { if (dap->backend) { - dap->backend->close(dap); + if (dap->backend->close) + dap->backend->close(dap); dap->backend = NULL; } @@ -2192,22 +2207,27 @@ COMMAND_HANDLER(cmsis_dap_handle_vid_pid_command) COMMAND_HANDLER(cmsis_dap_handle_backend_command) { - if (CMD_ARGC == 1) { - if (strcmp(CMD_ARGV[0], "auto") == 0) { - cmsis_dap_backend = -1; /* autoselect */ - } else { - for (unsigned int i = 0; i < ARRAY_SIZE(cmsis_dap_backends); i++) { - if (strcasecmp(cmsis_dap_backends[i]->name, CMD_ARGV[0]) == 0) { + if (CMD_ARGC != 1) + return ERROR_COMMAND_SYNTAX_ERROR; + + if (strcmp(CMD_ARGV[0], "auto") == 0) { + cmsis_dap_backend = -1; /* autoselect */ + } else { + for (unsigned int i = 0; i < ARRAY_SIZE(cmsis_dap_backends); i++) { + if (strcasecmp(cmsis_dap_backends[i]->name, CMD_ARGV[0]) == 0) { + if (cmsis_dap_backends[i]->open) { cmsis_dap_backend = i; return ERROR_OK; } - } - command_print(CMD, "invalid backend argument to cmsis-dap backend <backend>"); - return ERROR_COMMAND_ARGUMENT_INVALID; + command_print(CMD, "Requested cmsis-dap backend %s is disabled by configure", + cmsis_dap_backends[i]->name); + return ERROR_NOT_IMPLEMENTED; + } } - } else { - return ERROR_COMMAND_SYNTAX_ERROR; + + command_print(CMD, "invalid argument %s to cmsis-dap backend", CMD_ARGV[0]); + return ERROR_COMMAND_ARGUMENT_INVALID; } return ERROR_OK; diff --git a/src/jtag/drivers/linuxspidev.c b/src/jtag/drivers/linuxspidev.c index 6a149a9..18abdc7 100644 --- a/src/jtag/drivers/linuxspidev.c +++ b/src/jtag/drivers/linuxspidev.c @@ -302,8 +302,20 @@ static int spidev_init(void) return ERROR_JTAG_INIT_FAILED; } + int ret; // Set SPI mode. - int ret = ioctl(spi_fd, SPI_IOC_WR_MODE32, &spi_mode); +#ifdef SPI_IOC_WR_MODE32 + ret = ioctl(spi_fd, SPI_IOC_WR_MODE32, &spi_mode); +#else + // Linux pre 3.15 does not support MODE32, use 8-bit ioctl + if (spi_mode & ~0xff) { + LOG_ERROR("SPI mode 0x%" PRIx32 ", system permits 8 bits only", spi_mode); + return ERROR_JTAG_INIT_FAILED; + } + + uint8_t mode = (uint8_t)spi_mode; + ret = ioctl(spi_fd, SPI_IOC_WR_MODE, &mode); +#endif if (ret == -1) { LOG_ERROR("Failed to set SPI mode 0x%" PRIx32, spi_mode); return ERROR_JTAG_INIT_FAILED; diff --git a/src/rtos/Makefile.am b/src/rtos/Makefile.am index 0796910..5267fea 100644 --- a/src/rtos/Makefile.am +++ b/src/rtos/Makefile.am @@ -11,15 +11,15 @@ noinst_LTLIBRARIES += %D%/librtos.la %D%/rtos_ucos_iii_stackings.c \ %D%/rtos_riot_stackings.c \ %D%/rtos_nuttx_stackings.c \ - %D%/FreeRTOS.c \ - %D%/ThreadX.c \ - %D%/eCos.c \ + %D%/freertos.c \ + %D%/threadx.c \ + %D%/ecos.c \ %D%/linux.c \ %D%/chibios.c \ %D%/chromium-ec.c \ - %D%/embKernel.c \ + %D%/embkernel.c \ %D%/mqx.c \ - %D%/uCOS-III.c \ + %D%/ucos_iii.c \ %D%/nuttx.c \ %D%/rtkernel.c \ %D%/hwthread.c \ diff --git a/src/rtos/eCos.c b/src/rtos/ecos.c index 7048b00..7048b00 100644 --- a/src/rtos/eCos.c +++ b/src/rtos/ecos.c diff --git a/src/rtos/embKernel.c b/src/rtos/embkernel.c index 7e6de79..7e6de79 100644 --- a/src/rtos/embKernel.c +++ b/src/rtos/embkernel.c diff --git a/src/rtos/FreeRTOS.c b/src/rtos/freertos.c index 02409a5..02409a5 100644 --- a/src/rtos/FreeRTOS.c +++ b/src/rtos/freertos.c diff --git a/src/rtos/linux.c b/src/rtos/linux.c index 5467988..5efdc9f 100644 --- a/src/rtos/linux.c +++ b/src/rtos/linux.c @@ -1040,6 +1040,10 @@ static int linux_gdb_thread_packet(struct target *target, return ERROR_TARGET_FAILURE; char *out_str = calloc(MAX_THREADS * 17 + 10, 1); + if (!out_str) { + LOG_ERROR("Out of memory"); + return ERROR_FAIL; + } char *tmp_str = out_str; tmp_str += sprintf(tmp_str, "m"); struct threads *temp = linux_os->thread_list; @@ -1116,23 +1120,13 @@ static int linux_thread_extra_info(struct target *target, while (temp) { if (temp->threadid == threadid) { - char *pid = " PID: "; - char *pid_current = "*PID: "; - char *name = "Name: "; - int str_size = strlen(pid) + strlen(name); - char *tmp_str = calloc(1, str_size + 50); - char *tmp_str_ptr = tmp_str; - - /* discriminate current task */ - if (temp->status == 3) - tmp_str_ptr += sprintf(tmp_str_ptr, "%s", - pid_current); - else - tmp_str_ptr += sprintf(tmp_str_ptr, "%s", pid); - - tmp_str_ptr += sprintf(tmp_str_ptr, "%d, ", (int)temp->pid); - sprintf(tmp_str_ptr, "%s", name); - sprintf(tmp_str_ptr, "%s", temp->name); + char *tmp_str = alloc_printf("%cPID: %" PRIu32 ", Name: %s", + temp->status == 3 ? '*' : ' ', + temp->pid, temp->name); + if (!tmp_str) { + LOG_ERROR("Out of memory"); + return ERROR_FAIL; + } char *hex_str = calloc(1, strlen(tmp_str) * 2 + 1); size_t pkt_len = hexify(hex_str, (const uint8_t *)tmp_str, strlen(tmp_str), strlen(tmp_str) * 2 + 1); diff --git a/src/rtos/rtos.c b/src/rtos/rtos.c index 2bd7d3b..e87e51c 100644 --- a/src/rtos/rtos.c +++ b/src/rtos/rtos.c @@ -370,6 +370,10 @@ int rtos_thread_packet(struct connection *connection, char const *packet, int pa str_size += strlen(detail->extra_info_str); char *tmp_str = calloc(str_size + 9, sizeof(char)); + if (!tmp_str) { + LOG_ERROR("Out of memory"); + return ERROR_FAIL; + } char *tmp_str_ptr = tmp_str; if (detail->thread_name_str) diff --git a/src/rtos/ThreadX.c b/src/rtos/threadx.c index 61c4926..61c4926 100644 --- a/src/rtos/ThreadX.c +++ b/src/rtos/threadx.c diff --git a/src/rtos/uCOS-III.c b/src/rtos/ucos_iii.c index f19d06e..f19d06e 100644 --- a/src/rtos/uCOS-III.c +++ b/src/rtos/ucos_iii.c diff --git a/src/rtt/rtt.c b/src/rtt/rtt.c index 42c3ee3..15b9a37 100644 --- a/src/rtt/rtt.c +++ b/src/rtt/rtt.c @@ -140,8 +140,8 @@ int rtt_start(void) addr); rtt.ctrl.address = addr; } else { - LOG_INFO("rtt: No control block found"); - return ERROR_OK; + LOG_ERROR("rtt: No control block found"); + return ERROR_FAIL; } } diff --git a/src/server/gdb_server.c b/src/server/gdb_server.c index 6ddee0a..d9825c5 100644 --- a/src/server/gdb_server.c +++ b/src/server/gdb_server.c @@ -955,7 +955,7 @@ static void gdb_fileio_reply(struct target *target, struct connection *connectio /* encounter unknown syscall, continue */ gdb_connection->frontend_state = TARGET_RUNNING; - target_resume(target, 1, 0x0, 0, 0); + target_resume(target, true, 0x0, false, false); return; } @@ -965,7 +965,7 @@ static void gdb_fileio_reply(struct target *target, struct connection *connectio if (program_exited) { /* Use target_resume() to let target run its own exit syscall handler. */ gdb_connection->frontend_state = TARGET_RUNNING; - target_resume(target, 1, 0x0, 0, 0); + target_resume(target, true, 0x0, false, false); } else { gdb_connection->frontend_state = TARGET_HALTED; rtos_update_threads(target); @@ -1755,7 +1755,7 @@ static int gdb_step_continue_packet(struct connection *connection, char const *packet, int packet_size) { struct target *target = get_available_target_from_connection(connection); - int current = 0; + bool current = false; uint64_t address = 0x0; int retval = ERROR_OK; @@ -1764,17 +1764,17 @@ static int gdb_step_continue_packet(struct connection *connection, if (packet_size > 1) address = strtoull(packet + 1, NULL, 16); else - current = 1; + current = true; gdb_running_type = packet[0]; if (packet[0] == 'c') { LOG_DEBUG("continue"); /* resume at current address, don't handle breakpoints, not debugging */ - retval = target_resume(target, current, address, 0, 0); + retval = target_resume(target, current, address, false, false); } else if (packet[0] == 's') { LOG_DEBUG("step"); /* step at current or address, don't handle breakpoints */ - retval = target_step(target, current, address, 0); + retval = target_step(target, current, address, false); } return retval; } @@ -3080,7 +3080,7 @@ static bool gdb_handle_vcont_packet(struct connection *connection, const char *p LOG_TARGET_DEBUG(target, "target continue"); gdb_connection->output_flag = GDB_OUTPUT_ALL; - retval = target_resume(target, 1, 0, 0, 0); + retval = target_resume(target, true, 0, false, false); if (retval == ERROR_TARGET_NOT_HALTED) LOG_TARGET_INFO(target, "target was not halted when resume was requested"); @@ -3108,7 +3108,7 @@ static bool gdb_handle_vcont_packet(struct connection *connection, const char *p bool fake_step = false; struct target *ct = target; - int current_pc = 1; + bool current_pc = true; int64_t thread_id; parse++; if (parse[0] == ':') { @@ -3222,7 +3222,7 @@ static bool gdb_handle_vcont_packet(struct connection *connection, const char *p "Pretending to gdb that it is running until it's available again."); retval = ERROR_FAIL; } else { - retval = target_step(ct, current_pc, 0, 0); + retval = target_step(ct, current_pc, 0, false); if (retval == ERROR_TARGET_NOT_HALTED) LOG_TARGET_INFO(ct, "target was not halted when step was requested"); } @@ -3551,9 +3551,9 @@ static int gdb_fileio_response_packet(struct connection *connection, /* After File-I/O ends, keep continue or step */ if (gdb_running_type == 'c') - retval = target_resume(target, 1, 0x0, 0, 0); + retval = target_resume(target, true, 0x0, false, false); else if (gdb_running_type == 's') - retval = target_step(target, 1, 0x0, 0); + retval = target_step(target, true, 0x0, false); else retval = ERROR_FAIL; @@ -3994,7 +3994,8 @@ static int gdb_target_add_one(struct target *target) } } } else if (strcmp(gdb_port_next, "pipe") == 0) { - gdb_port_next = "disabled"; + free(gdb_port_next); + gdb_port_next = strdup("disabled"); } } return retval; diff --git a/src/target/aarch64.c b/src/target/aarch64.c index 3cc8130..ce7808e 100644 --- a/src/target/aarch64.c +++ b/src/target/aarch64.c @@ -589,8 +589,8 @@ static int aarch64_halt(struct target *target) return aarch64_halt_one(target, HALT_SYNC); } -static int aarch64_restore_one(struct target *target, int current, - uint64_t *address, int handle_breakpoints, int debug_execution) +static int aarch64_restore_one(struct target *target, bool current, + uint64_t *address, bool handle_breakpoints, bool debug_execution) { struct armv8_common *armv8 = target_to_armv8(target); struct arm *arm = &armv8->arm; @@ -602,7 +602,7 @@ static int aarch64_restore_one(struct target *target, int current, if (!debug_execution) target_free_all_working_areas(target); - /* current = 1: continue on current pc, otherwise continue at <address> */ + /* current = true: continue on current pc, otherwise continue at <address> */ resume_pc = buf_get_u64(arm->pc->value, 0, 64); if (!current) resume_pc = *address; @@ -753,7 +753,8 @@ static int aarch64_restart_one(struct target *target, enum restart_mode mode) /* * prepare all but the current target for restart */ -static int aarch64_prep_restart_smp(struct target *target, int handle_breakpoints, struct target **p_first) +static int aarch64_prep_restart_smp(struct target *target, + bool handle_breakpoints, struct target **p_first) { int retval = ERROR_OK; struct target_list *head; @@ -772,7 +773,8 @@ static int aarch64_prep_restart_smp(struct target *target, int handle_breakpoint continue; /* resume at current address, not in step mode */ - retval = aarch64_restore_one(curr, 1, &address, handle_breakpoints, 0); + retval = aarch64_restore_one(curr, true, &address, handle_breakpoints, + false); if (retval == ERROR_OK) retval = aarch64_prepare_restart_one(curr); if (retval != ERROR_OK) { @@ -799,7 +801,7 @@ static int aarch64_step_restart_smp(struct target *target) LOG_DEBUG("%s", target_name(target)); - retval = aarch64_prep_restart_smp(target, 0, &first); + retval = aarch64_prep_restart_smp(target, false, &first); if (retval != ERROR_OK) return retval; @@ -864,8 +866,8 @@ static int aarch64_step_restart_smp(struct target *target) return retval; } -static int aarch64_resume(struct target *target, int current, - target_addr_t address, int handle_breakpoints, int debug_execution) +static int aarch64_resume(struct target *target, bool current, + target_addr_t address, bool handle_breakpoints, bool debug_execution) { int retval = 0; uint64_t addr = address; @@ -1113,8 +1115,8 @@ static int aarch64_post_debug_entry(struct target *target) /* * single-step a target */ -static int aarch64_step(struct target *target, int current, target_addr_t address, - int handle_breakpoints) +static int aarch64_step(struct target *target, bool current, target_addr_t address, + bool handle_breakpoints) { struct armv8_common *armv8 = target_to_armv8(target); struct aarch64_common *aarch64 = target_to_aarch64(target); @@ -1147,7 +1149,7 @@ static int aarch64_step(struct target *target, int current, target_addr_t addres if (retval != ERROR_OK) return retval; - if (target->smp && (current == 1)) { + if (target->smp && current) { /* * isolate current target so that it doesn't get resumed * together with the others @@ -1164,7 +1166,7 @@ static int aarch64_step(struct target *target, int current, target_addr_t addres } /* all other targets running, restore and restart the current target */ - retval = aarch64_restore_one(target, current, &address, 0, 0); + retval = aarch64_restore_one(target, current, &address, false, false); if (retval == ERROR_OK) retval = aarch64_restart_one(target, RESTART_LAZY); @@ -2855,6 +2857,14 @@ static void aarch64_deinit_target(struct target *target) struct aarch64_common *aarch64 = target_to_aarch64(target); struct armv8_common *armv8 = &aarch64->armv8_common; struct arm_dpm *dpm = &armv8->dpm; + uint64_t address; + + if (target->state == TARGET_HALTED) { + // Restore the previous state of the target (gp registers, MMU, caches, etc) + int retval = aarch64_restore_one(target, true, &address, false, false); + if (retval != ERROR_OK) + LOG_TARGET_ERROR(target, "Failed to restore target state"); + } if (armv8->debug_ap) dap_put_ap(armv8->debug_ap); diff --git a/src/target/adi_v5_swd.c b/src/target/adi_v5_swd.c index dda1b06..e50f8f1 100644 --- a/src/target/adi_v5_swd.c +++ b/src/target/adi_v5_swd.c @@ -502,9 +502,6 @@ static int swd_queue_dp_read(struct adiv5_dap *dap, unsigned int reg, static int swd_queue_dp_write(struct adiv5_dap *dap, unsigned int reg, uint32_t data) { - const struct swd_driver *swd = adiv5_dap_swd_driver(dap); - assert(swd); - int retval = swd_check_reconnect(dap); if (retval != ERROR_OK) return retval; diff --git a/src/target/algorithm.c b/src/target/algorithm.c index 64abffc..dee1f36 100644 --- a/src/target/algorithm.c +++ b/src/target/algorithm.c @@ -26,7 +26,8 @@ void destroy_mem_param(struct mem_param *param) param->value = NULL; } -void init_reg_param(struct reg_param *param, char *reg_name, uint32_t size, enum param_direction direction) +void init_reg_param(struct reg_param *param, const char *reg_name, + uint32_t size, enum param_direction direction) { param->reg_name = reg_name; param->size = size; diff --git a/src/target/algorithm.h b/src/target/algorithm.h index 25f1a66..45b3fd9 100644 --- a/src/target/algorithm.h +++ b/src/target/algorithm.h @@ -35,8 +35,8 @@ void init_mem_param(struct mem_param *param, uint32_t address, uint32_t size, enum param_direction dir); void destroy_mem_param(struct mem_param *param); -void init_reg_param(struct reg_param *param, - char *reg_name, uint32_t size, enum param_direction dir); +void init_reg_param(struct reg_param *param, const char *reg_name, + uint32_t size, enum param_direction dir); void destroy_reg_param(struct reg_param *param); #endif /* OPENOCD_TARGET_ALGORITHM_H */ diff --git a/src/target/arc.c b/src/target/arc.c index 0c111d5..8757caf 100644 --- a/src/target/arc.c +++ b/src/target/arc.c @@ -1100,7 +1100,7 @@ static int arc_assert_reset(struct target *target) /* Resume the target and continue from the current * PC register value. */ LOG_TARGET_DEBUG(target, "Starting CPU execution after reset"); - CHECK_RETVAL(target_resume(target, 1, 0, 0, 0)); + CHECK_RETVAL(target_resume(target, true, 0, false, false)); } target->state = TARGET_RESET; @@ -1246,7 +1246,7 @@ exit: return retval; } -static int arc_enable_interrupts(struct target *target, int enable) +static int arc_enable_interrupts(struct target *target, bool enable) { uint32_t value; @@ -1269,8 +1269,8 @@ static int arc_enable_interrupts(struct target *target, int enable) return ERROR_OK; } -static int arc_resume(struct target *target, int current, target_addr_t address, - int handle_breakpoints, int debug_execution) +static int arc_resume(struct target *target, bool current, target_addr_t address, + bool handle_breakpoints, bool debug_execution) { struct arc_common *arc = target_to_arc(target); uint32_t resume_pc = 0; @@ -1297,7 +1297,7 @@ static int arc_resume(struct target *target, int current, target_addr_t address, CHECK_RETVAL(arc_enable_watchpoints(target)); } - /* current = 1: continue on current PC, otherwise continue at <address> */ + /* current = true: continue on current PC, otherwise continue at <address> */ if (!current) { target_buffer_set_u32(target, pc->value, address); pc->dirty = true; @@ -2030,7 +2030,7 @@ static int arc_hit_watchpoint(struct target *target, struct watchpoint **hit_wat /* Helper function which switches core to single_step mode by * doing aux r/w operations. */ -static int arc_config_step(struct target *target, int enable_step) +static int arc_config_step(struct target *target, bool enable_step) { uint32_t value; @@ -2071,10 +2071,10 @@ static int arc_single_step_core(struct target *target) CHECK_RETVAL(arc_debug_entry(target)); /* disable interrupts while stepping */ - CHECK_RETVAL(arc_enable_interrupts(target, 0)); + CHECK_RETVAL(arc_enable_interrupts(target, false)); /* configure single step mode */ - CHECK_RETVAL(arc_config_step(target, 1)); + CHECK_RETVAL(arc_config_step(target, true)); /* exit debug mode */ CHECK_RETVAL(arc_exit_debug(target)); @@ -2082,8 +2082,8 @@ static int arc_single_step_core(struct target *target) return ERROR_OK; } -static int arc_step(struct target *target, int current, target_addr_t address, - int handle_breakpoints) +static int arc_step(struct target *target, bool current, target_addr_t address, + bool handle_breakpoints) { /* get pointers to arch-specific information */ struct arc_common *arc = target_to_arc(target); @@ -2095,7 +2095,7 @@ static int arc_step(struct target *target, int current, target_addr_t address, return ERROR_TARGET_NOT_HALTED; } - /* current = 1: continue on current pc, otherwise continue at <address> */ + /* current = true: continue on current pc, otherwise continue at <address> */ if (!current) { buf_set_u32(pc->value, 0, 32, address); pc->dirty = true; @@ -2120,10 +2120,10 @@ static int arc_step(struct target *target, int current, target_addr_t address, CHECK_RETVAL(target_call_event_callbacks(target, TARGET_EVENT_RESUMED)); /* disable interrupts while stepping */ - CHECK_RETVAL(arc_enable_interrupts(target, 0)); + CHECK_RETVAL(arc_enable_interrupts(target, false)); /* do a single step */ - CHECK_RETVAL(arc_config_step(target, 1)); + CHECK_RETVAL(arc_config_step(target, true)); /* make sure we done our step */ alive_sleep(1); diff --git a/src/target/arm11.c b/src/target/arm11.c index c583a2e..756b36b 100644 --- a/src/target/arm11.c +++ b/src/target/arm11.c @@ -30,8 +30,8 @@ #endif -static int arm11_step(struct target *target, int current, - target_addr_t address, int handle_breakpoints); +static int arm11_step(struct target *target, bool current, + target_addr_t address, bool handle_breakpoints); /** Check and if necessary take control of the system @@ -401,7 +401,8 @@ static int arm11_halt(struct target *target) return ERROR_OK; } -static uint32_t arm11_nextpc(struct arm11_common *arm11, int current, uint32_t address) +static uint32_t arm11_nextpc(struct arm11_common *arm11, bool current, + uint32_t address) { void *value = arm11->arm.pc->value; @@ -435,8 +436,8 @@ static uint32_t arm11_nextpc(struct arm11_common *arm11, int current, uint32_t a return address; } -static int arm11_resume(struct target *target, int current, - target_addr_t address, int handle_breakpoints, int debug_execution) +static int arm11_resume(struct target *target, bool current, + target_addr_t address, bool handle_breakpoints, bool debug_execution) { /* LOG_DEBUG("current %d address %08x handle_breakpoints %d debug_execution %d", */ /* current, address, handle_breakpoints, debug_execution); */ @@ -469,7 +470,7 @@ static int arm11_resume(struct target *target, int current, for (bp = target->breakpoints; bp; bp = bp->next) { if (bp->address == address) { LOG_DEBUG("must step over %08" TARGET_PRIxADDR "", bp->address); - arm11_step(target, 1, 0, 0); + arm11_step(target, true, 0, false); break; } } @@ -543,8 +544,8 @@ static int arm11_resume(struct target *target, int current, return ERROR_OK; } -static int arm11_step(struct target *target, int current, - target_addr_t address, int handle_breakpoints) +static int arm11_step(struct target *target, bool current, + target_addr_t address, bool handle_breakpoints) { LOG_DEBUG("target->state: %s", target_state_name(target)); @@ -569,13 +570,13 @@ static int arm11_step(struct target *target, int current, /* skip over BKPT */ if ((next_instruction & 0xFFF00070) == 0xe1200070) { - address = arm11_nextpc(arm11, 0, address + 4); + address = arm11_nextpc(arm11, false, address + 4); LOG_DEBUG("Skipping BKPT %08" TARGET_PRIxADDR, address); } /* skip over Wait for interrupt / Standby * mcr 15, 0, r?, cr7, cr0, {4} */ else if ((next_instruction & 0xFFFF0FFF) == 0xee070f90) { - address = arm11_nextpc(arm11, 0, address + 4); + address = arm11_nextpc(arm11, false, address + 4); LOG_DEBUG("Skipping WFI %08" TARGET_PRIxADDR, address); } /* ignore B to self */ diff --git a/src/target/arm7_9_common.c b/src/target/arm7_9_common.c index ad814e0..5550fb1 100644 --- a/src/target/arm7_9_common.c +++ b/src/target/arm7_9_common.c @@ -1697,10 +1697,10 @@ static void arm7_9_enable_breakpoints(struct target *target) } int arm7_9_resume(struct target *target, - int current, + bool current, target_addr_t address, - int handle_breakpoints, - int debug_execution) + bool handle_breakpoints, + bool debug_execution) { struct arm7_9_common *arm7_9 = target_to_arm7_9(target); struct arm *arm = &arm7_9->arm; @@ -1717,7 +1717,7 @@ int arm7_9_resume(struct target *target, if (!debug_execution) target_free_all_working_areas(target); - /* current = 1: continue on current pc, otherwise continue at <address> */ + /* current = true: continue on current pc, otherwise continue at <address> */ if (!current) buf_set_u32(arm->pc->value, 0, 32, address); @@ -1900,7 +1900,8 @@ void arm7_9_disable_eice_step(struct target *target) embeddedice_store_reg(&arm7_9->eice_cache->reg_list[EICE_W1_CONTROL_VALUE]); } -int arm7_9_step(struct target *target, int current, target_addr_t address, int handle_breakpoints) +int arm7_9_step(struct target *target, bool current, target_addr_t address, + bool handle_breakpoints) { struct arm7_9_common *arm7_9 = target_to_arm7_9(target); struct arm *arm = &arm7_9->arm; @@ -1912,7 +1913,7 @@ int arm7_9_step(struct target *target, int current, target_addr_t address, int h return ERROR_TARGET_NOT_HALTED; } - /* current = 1: continue on current pc, otherwise continue at <address> */ + /* current = true: continue on current pc, otherwise continue at <address> */ if (!current) buf_set_u32(arm->pc->value, 0, 32, address); diff --git a/src/target/arm7_9_common.h b/src/target/arm7_9_common.h index 92d0fd5..c4a5b08 100644 --- a/src/target/arm7_9_common.h +++ b/src/target/arm7_9_common.h @@ -145,10 +145,10 @@ int arm7_9_early_halt(struct target *target); int arm7_9_soft_reset_halt(struct target *target); int arm7_9_halt(struct target *target); -int arm7_9_resume(struct target *target, int current, target_addr_t address, - int handle_breakpoints, int debug_execution); -int arm7_9_step(struct target *target, int current, target_addr_t address, - int handle_breakpoints); +int arm7_9_resume(struct target *target, bool current, target_addr_t address, + bool handle_breakpoints, bool debug_execution); +int arm7_9_step(struct target *target, bool current, target_addr_t address, + bool handle_breakpoints); int arm7_9_read_memory(struct target *target, target_addr_t address, uint32_t size, uint32_t count, uint8_t *buffer); int arm7_9_write_memory(struct target *target, target_addr_t address, diff --git a/src/target/arm_adi_v5.c b/src/target/arm_adi_v5.c index 0c7633b..df897b8 100644 --- a/src/target/arm_adi_v5.c +++ b/src/target/arm_adi_v5.c @@ -2367,7 +2367,9 @@ static int adiv5_jim_spot_configure(struct jim_getopt_info *goi, return e; dap = dap_instance_by_jim_obj(goi->interp, o_t); if (!dap) { - Jim_SetResultString(goi->interp, "DAP name invalid!", -1); + const char *dap_name = Jim_GetString(o_t, NULL); + Jim_SetResultFormatted(goi->interp, "DAP '%s' not found", + dap_name); return JIM_ERR; } if (*dap_p && *dap_p != dap) { diff --git a/src/target/arm_semihosting.c b/src/target/arm_semihosting.c index b557589..a7c47bf 100644 --- a/src/target/arm_semihosting.c +++ b/src/target/arm_semihosting.c @@ -50,7 +50,7 @@ static int arm_semihosting_resume(struct target *target, int *retval) if (is_armv8(target_to_armv8(target))) { struct armv8_common *armv8 = target_to_armv8(target); if (armv8->last_run_control_op == ARMV8_RUNCONTROL_RESUME) { - *retval = target_resume(target, 1, 0, 0, 0); + *retval = target_resume(target, true, 0, false, false); if (*retval != ERROR_OK) { LOG_ERROR("Failed to resume target"); return 0; @@ -58,7 +58,7 @@ static int arm_semihosting_resume(struct target *target, int *retval) } else if (armv8->last_run_control_op == ARMV8_RUNCONTROL_STEP) target->debug_reason = DBG_REASON_SINGLESTEP; } else { - *retval = target_resume(target, 1, 0, 0, 0); + *retval = target_resume(target, true, 0, false, false); if (*retval != ERROR_OK) { LOG_ERROR("Failed to resume target"); return 0; diff --git a/src/target/armv4_5.c b/src/target/armv4_5.c index a258c7f..597dc89 100644 --- a/src/target/armv4_5.c +++ b/src/target/armv4_5.c @@ -1514,7 +1514,7 @@ int armv4_5_run_algorithm_inner(struct target *target, } } - retval = target_resume(target, 0, entry_point, 1, 1); + retval = target_resume(target, false, entry_point, true, true); if (retval != ERROR_OK) return retval; retval = run_it(target, exit_point, timeout_ms, arch_info); diff --git a/src/target/armv7a.c b/src/target/armv7a.c index e22d309..c14155e 100644 --- a/src/target/armv7a.c +++ b/src/target/armv7a.c @@ -101,14 +101,14 @@ static int armv7a_read_midr(struct target *target) armv7a->arch = (midr >> 16) & 0xf; armv7a->variant = (midr >> 20) & 0xf; armv7a->implementor = (midr >> 24) & 0xff; - LOG_DEBUG("%s rev %" PRIx32 ", partnum %" PRIx32 ", arch %" PRIx32 - ", variant %" PRIx32 ", implementor %" PRIx32, - target->cmd_name, - armv7a->rev, - armv7a->partnum, - armv7a->arch, - armv7a->variant, - armv7a->implementor); + LOG_TARGET_DEBUG(target, + "rev %" PRIx32 ", partnum %" PRIx32 ", arch %" PRIx32 + ", variant %" PRIx32 ", implementor %" PRIx32, + armv7a->rev, + armv7a->partnum, + armv7a->arch, + armv7a->variant, + armv7a->implementor); done: dpm->finish(dpm); diff --git a/src/target/armv7m.c b/src/target/armv7m.c index 440ca49..dc2d84f 100644 --- a/src/target/armv7m.c +++ b/src/target/armv7m.c @@ -642,7 +642,7 @@ int armv7m_start_algorithm(struct target *target, /* save previous core mode */ armv7m_algorithm_info->core_mode = core_mode; - retval = target_resume(target, 0, entry_point, 1, 1); + retval = target_resume(target, false, entry_point, true, true); return retval; } diff --git a/src/target/armv8.c b/src/target/armv8.c index 50a9f46..4039073 100644 --- a/src/target/armv8.c +++ b/src/target/armv8.c @@ -1686,12 +1686,12 @@ static int armv8_set_core_reg(struct reg *reg, uint8_t *buf) struct arm_reg *armv8_reg = reg->arch_info; struct target *target = armv8_reg->target; struct arm *arm = target_to_arm(target); - uint64_t value = buf_get_u64(buf, 0, reg->size); if (target->state != TARGET_HALTED) return ERROR_TARGET_NOT_HALTED; if (reg->size <= 64) { + uint64_t value = buf_get_u64(buf, 0, reg->size); if (reg == arm->cpsr) armv8_set_cpsr(arm, (uint32_t)value); else { @@ -1699,6 +1699,7 @@ static int armv8_set_core_reg(struct reg *reg, uint8_t *buf) reg->valid = true; } } else if (reg->size <= 128) { + uint64_t value = buf_get_u64(buf, 0, 64); uint64_t hvalue = buf_get_u64(buf + 8, 0, reg->size - 64); buf_set_u64(reg->value, 0, 64, value); diff --git a/src/target/armv8.h b/src/target/armv8.h index 49ab3e5..dba12f9 100644 --- a/src/target/armv8.h +++ b/src/target/armv8.h @@ -162,6 +162,7 @@ struct armv8_cache_common { /* l2 external unified cache if some */ void *l2_cache; int (*flush_all_data_cache)(struct target *target); + int (*invalidate_all_instruction_cache)(struct target *target); int (*display_cache_info)(struct command_invocation *cmd, struct armv8_cache_common *armv8_cache); }; diff --git a/src/target/armv8_cache.c b/src/target/armv8_cache.c index 66d4e00..1c251be 100644 --- a/src/target/armv8_cache.c +++ b/src/target/armv8_cache.c @@ -61,6 +61,7 @@ static int armv8_cache_d_inner_flush_level(struct armv8_common *armv8, struct ar goto done; c_way -= 1; } while (c_way >= 0); + keep_alive(); c_index -= 1; } while (c_index >= 0); @@ -140,6 +141,36 @@ done: return retval; } +static int armv8_cache_i_inner_clean_inval_all(struct armv8_common *armv8) +{ + struct arm_dpm *dpm = armv8->arm.dpm; + int retval; + + retval = armv8_i_cache_sanity_check(armv8); + if (retval != ERROR_OK) + return retval; + + LOG_DEBUG("flushing cache"); + + retval = dpm->prepare(dpm); + if (retval != ERROR_OK) + goto done; + + retval = dpm->instr_execute(dpm, armv8_opcode(armv8, ARMV8_OPC_ICIALLU)); + if (retval != ERROR_OK) + goto done; + + dpm->finish(dpm); + LOG_DEBUG("flushing cache done"); + return retval; + +done: + LOG_ERROR("i-cache invalidate failed"); + dpm->finish(dpm); + + return retval; +} + int armv8_cache_i_inner_inval_virt(struct armv8_common *armv8, target_addr_t va, size_t size) { struct arm_dpm *dpm = armv8->arm.dpm; @@ -252,6 +283,32 @@ static int armv8_flush_all_data(struct target *target) return retval; } +static int armv8_flush_all_instruction(struct target *target) +{ + int retval = ERROR_FAIL; + /* check that armv8_cache is correctly identify */ + struct armv8_common *armv8 = target_to_armv8(target); + if (armv8->armv8_mmu.armv8_cache.info == -1) { + LOG_ERROR("trying to flush un-identified cache"); + return retval; + } + + if (target->smp) { + /* look if all the other target have been flushed in order to flush icache */ + struct target_list *head; + foreach_smp_target(head, target->smp_targets) { + struct target *curr = head->target; + if (curr->state == TARGET_HALTED) { + LOG_TARGET_INFO(curr, "Wait flushing instruction l1."); + retval = armv8_cache_i_inner_clean_inval_all(target_to_armv8(curr)); + } + } + } else { + retval = armv8_cache_i_inner_clean_inval_all(armv8); + } + return retval; +} + static int get_cache_info(struct arm_dpm *dpm, int cl, int ct, uint32_t *cache_reg) { struct armv8_common *armv8 = dpm->arm->arch_info; @@ -411,6 +468,12 @@ int armv8_identify_cache(struct armv8_common *armv8) armv8->armv8_mmu.armv8_cache.flush_all_data_cache = armv8_flush_all_data; } + if (!armv8->armv8_mmu.armv8_cache.invalidate_all_instruction_cache) { + armv8->armv8_mmu.armv8_cache.display_cache_info = + armv8_handle_inner_cache_info_command; + armv8->armv8_mmu.armv8_cache.invalidate_all_instruction_cache = + armv8_flush_all_instruction; + } done: armv8_dpm_modeswitch(dpm, ARM_MODE_ANY); diff --git a/src/target/armv8_opcodes.c b/src/target/armv8_opcodes.c index 2635b3e..0f6c810 100644 --- a/src/target/armv8_opcodes.c +++ b/src/target/armv8_opcodes.c @@ -41,6 +41,7 @@ static const uint32_t a64_opcodes[ARMV8_OPC_NUM] = { [ARMV8_OPC_STRH_IP] = ARMV8_STRH_IP(1, 0), [ARMV8_OPC_STRW_IP] = ARMV8_STRW_IP(1, 0), [ARMV8_OPC_STRD_IP] = ARMV8_STRD_IP(1, 0), + [ARMV8_OPC_ICIALLU] = ARMV8_SYS(SYSTEM_ICIALLU, 0x1F), }; static const uint32_t t32_opcodes[ARMV8_OPC_NUM] = { @@ -68,6 +69,7 @@ static const uint32_t t32_opcodes[ARMV8_OPC_NUM] = { [ARMV8_OPC_STRB_IP] = ARMV8_STRB_IP_T3(1, 0), [ARMV8_OPC_STRH_IP] = ARMV8_STRH_IP_T3(1, 0), [ARMV8_OPC_STRW_IP] = ARMV8_STRW_IP_T3(1, 0), + [ARMV8_OPC_ICIALLU] = ARMV4_5_MCR(15, 0, 0, 7, 5, 0), }; void armv8_select_opcodes(struct armv8_common *armv8, bool state_is_aarch64) diff --git a/src/target/armv8_opcodes.h b/src/target/armv8_opcodes.h index 9200dac..9f18e94 100644 --- a/src/target/armv8_opcodes.h +++ b/src/target/armv8_opcodes.h @@ -72,6 +72,8 @@ #define SYSTEM_DCCISW 0x43F2 #define SYSTEM_DCCSW 0x43D2 #define SYSTEM_ICIVAU 0x5BA9 +/* Attention, SYSTEM_ICIALLU requires rt=0x1f */ +#define SYSTEM_ICIALLU 0x03A8 #define SYSTEM_DCCVAU 0x5BD9 #define SYSTEM_DCCIVAC 0x5BF1 @@ -207,6 +209,7 @@ enum armv8_opcode { ARMV8_OPC_LDRH_IP, ARMV8_OPC_LDRW_IP, ARMV8_OPC_LDRD_IP, + ARMV8_OPC_ICIALLU, ARMV8_OPC_NUM, }; diff --git a/src/target/avr32_ap7k.c b/src/target/avr32_ap7k.c index bbbf236..1b051dc 100644 --- a/src/target/avr32_ap7k.c +++ b/src/target/avr32_ap7k.c @@ -300,8 +300,8 @@ static int avr32_ap7k_deassert_reset(struct target *target) return ERROR_OK; } -static int avr32_ap7k_resume(struct target *target, int current, - target_addr_t address, int handle_breakpoints, int debug_execution) +static int avr32_ap7k_resume(struct target *target, bool current, + target_addr_t address, bool handle_breakpoints, bool debug_execution) { struct avr32_ap7k_common *ap7k = target_to_ap7k(target); struct breakpoint *breakpoint = NULL; @@ -321,7 +321,7 @@ static int avr32_ap7k_resume(struct target *target, int current, */ } - /* current = 1: continue on current pc, otherwise continue at <address> */ + /* current = true: continue on current pc, otherwise continue at <address> */ if (!current) { #if 0 if (retval != ERROR_OK) @@ -382,8 +382,8 @@ static int avr32_ap7k_resume(struct target *target, int current, return ERROR_OK; } -static int avr32_ap7k_step(struct target *target, int current, - target_addr_t address, int handle_breakpoints) +static int avr32_ap7k_step(struct target *target, bool current, + target_addr_t address, bool handle_breakpoints) { LOG_ERROR("%s: implement me", __func__); diff --git a/src/target/avrt.c b/src/target/avrt.c index 8886a46..3afe320 100644 --- a/src/target/avrt.c +++ b/src/target/avrt.c @@ -22,10 +22,10 @@ static int avr_init_target(struct command_context *cmd_ctx, struct target *targe static int avr_arch_state(struct target *target); static int avr_poll(struct target *target); static int avr_halt(struct target *target); -static int avr_resume(struct target *target, int current, target_addr_t address, - int handle_breakpoints, int debug_execution); -static int avr_step(struct target *target, int current, target_addr_t address, - int handle_breakpoints); +static int avr_resume(struct target *target, bool current, target_addr_t address, + bool handle_breakpoints, bool debug_execution); +static int avr_step(struct target *target, bool current, target_addr_t address, + bool handle_breakpoints); static int avr_assert_reset(struct target *target); static int avr_deassert_reset(struct target *target); @@ -105,14 +105,15 @@ static int avr_halt(struct target *target) return ERROR_OK; } -static int avr_resume(struct target *target, int current, target_addr_t address, - int handle_breakpoints, int debug_execution) +static int avr_resume(struct target *target, bool current, target_addr_t address, + bool handle_breakpoints, bool debug_execution) { LOG_DEBUG("%s", __func__); return ERROR_OK; } -static int avr_step(struct target *target, int current, target_addr_t address, int handle_breakpoints) +static int avr_step(struct target *target, bool current, target_addr_t address, + bool handle_breakpoints) { LOG_DEBUG("%s", __func__); return ERROR_OK; diff --git a/src/target/cortex_a.c b/src/target/cortex_a.c index bfe6980..9c60645 100644 --- a/src/target/cortex_a.c +++ b/src/target/cortex_a.c @@ -817,8 +817,8 @@ static int cortex_a_halt(struct target *target) return ERROR_OK; } -static int cortex_a_internal_restore(struct target *target, int current, - target_addr_t *address, int handle_breakpoints, int debug_execution) +static int cortex_a_internal_restore(struct target *target, bool current, + target_addr_t *address, bool handle_breakpoints, bool debug_execution) { struct armv7a_common *armv7a = target_to_armv7a(target); struct arm *arm = &armv7a->arm; @@ -849,7 +849,7 @@ static int cortex_a_internal_restore(struct target *target, int current, } #endif - /* current = 1: continue on current pc, otherwise continue at <address> */ + /* current = true: continue on current pc, otherwise continue at <address> */ resume_pc = buf_get_u32(arm->pc->value, 0, 32); if (!current) resume_pc = *address; @@ -965,7 +965,7 @@ static int cortex_a_internal_restart(struct target *target) return ERROR_OK; } -static int cortex_a_restore_smp(struct target *target, int handle_breakpoints) +static int cortex_a_restore_smp(struct target *target, bool handle_breakpoints) { int retval = 0; struct target_list *head; @@ -976,16 +976,16 @@ static int cortex_a_restore_smp(struct target *target, int handle_breakpoints) if ((curr != target) && (curr->state != TARGET_RUNNING) && target_was_examined(curr)) { /* resume current address , not in step mode */ - retval += cortex_a_internal_restore(curr, 1, &address, - handle_breakpoints, 0); + retval += cortex_a_internal_restore(curr, true, &address, + handle_breakpoints, false); retval += cortex_a_internal_restart(curr); } } return retval; } -static int cortex_a_resume(struct target *target, int current, - target_addr_t address, int handle_breakpoints, int debug_execution) +static int cortex_a_resume(struct target *target, bool current, + target_addr_t address, bool handle_breakpoints, bool debug_execution) { int retval = 0; /* dummy resume for smp toggle in order to reduce gdb impact */ @@ -997,7 +997,8 @@ static int cortex_a_resume(struct target *target, int current, target_call_event_callbacks(target, TARGET_EVENT_RESUMED); return 0; } - cortex_a_internal_restore(target, current, &address, handle_breakpoints, debug_execution); + cortex_a_internal_restore(target, current, &address, handle_breakpoints, + debug_execution); if (target->smp) { target->gdb_service->core[0] = -1; retval = cortex_a_restore_smp(target, handle_breakpoints); @@ -1168,8 +1169,8 @@ static int cortex_a_set_dscr_bits(struct target *target, return retval; } -static int cortex_a_step(struct target *target, int current, target_addr_t address, - int handle_breakpoints) +static int cortex_a_step(struct target *target, bool current, target_addr_t address, + bool handle_breakpoints) { struct cortex_a_common *cortex_a = target_to_cortex_a(target); struct armv7a_common *armv7a = target_to_armv7a(target); @@ -1184,7 +1185,7 @@ static int cortex_a_step(struct target *target, int current, target_addr_t addre return ERROR_TARGET_NOT_HALTED; } - /* current = 1: continue on current pc, otherwise continue at <address> */ + /* current = true: continue on current pc, otherwise continue at <address> */ r = arm->pc; if (!current) buf_set_u32(r->value, 0, 32, address); @@ -1195,7 +1196,7 @@ static int cortex_a_step(struct target *target, int current, target_addr_t addre * But since Cortex-A uses breakpoint for single step, * we MUST handle breakpoints. */ - handle_breakpoints = 1; + handle_breakpoints = true; if (handle_breakpoints) { breakpoint = breakpoint_find(target, address); if (breakpoint) @@ -1222,7 +1223,7 @@ static int cortex_a_step(struct target *target, int current, target_addr_t addre target->debug_reason = DBG_REASON_SINGLESTEP; - retval = cortex_a_resume(target, 1, address, 0, 0); + retval = cortex_a_resume(target, true, address, false, false); if (retval != ERROR_OK) return retval; @@ -2922,14 +2923,12 @@ static int cortex_a_examine_first(struct target *target) armv7a->debug_ap->memaccess_tck = 80; if (!target->dbgbase_set) { - LOG_DEBUG("%s's dbgbase is not set, trying to detect using the ROM table", - target->cmd_name); + LOG_TARGET_DEBUG(target, "dbgbase is not set, trying to detect using the ROM table"); /* Lookup Processor DAP */ retval = dap_lookup_cs_component(armv7a->debug_ap, ARM_CS_C9_DEVTYPE_CORE_DEBUG, &armv7a->debug_base, target->coreid); if (retval != ERROR_OK) { - LOG_ERROR("Can't detect %s's dbgbase from the ROM table; you need to specify it explicitly.", - target->cmd_name); + LOG_TARGET_ERROR(target, "Can't detect dbgbase from the ROM table; you need to specify it explicitly"); return retval; } LOG_DEBUG("Detected core %" PRId32 " dbgbase: " TARGET_ADDR_FMT, @@ -2938,8 +2937,9 @@ static int cortex_a_examine_first(struct target *target) armv7a->debug_base = target->dbgbase; if ((armv7a->debug_base & (1UL<<31)) == 0) - LOG_WARNING("Debug base address for target %s has bit 31 set to 0. Access to debug registers will likely fail!\n" - "Please fix the target configuration.", target_name(target)); + LOG_TARGET_WARNING(target, + "Debug base address has bit 31 set to 0. Access to debug registers will likely fail!\n" + "Please fix the target configuration"); retval = mem_ap_read_atomic_u32(armv7a->debug_ap, armv7a->debug_base + CPUDBG_DIDR, &didr); diff --git a/src/target/cortex_m.c b/src/target/cortex_m.c index 9314d66..e17f23c 100644 --- a/src/target/cortex_m.c +++ b/src/target/cortex_m.c @@ -1359,7 +1359,7 @@ static int cortex_m_restore_one(struct target *target, bool current, r->valid = true; } - /* current = 1: continue on current pc, otherwise continue at <address> */ + /* current = true: continue on current pc, otherwise continue at <address> */ r = armv7m->arm.pc; if (!current) { buf_set_u32(r->value, 0, 32, *address); @@ -1444,7 +1444,7 @@ static int cortex_m_restore_smp(struct target *target, bool handle_breakpoints) continue; int retval = cortex_m_restore_one(curr, true, &address, - handle_breakpoints, false); + handle_breakpoints, false); if (retval != ERROR_OK) return retval; @@ -1457,22 +1457,23 @@ static int cortex_m_restore_smp(struct target *target, bool handle_breakpoints) return ERROR_OK; } -static int cortex_m_resume(struct target *target, int current, - target_addr_t address, int handle_breakpoints, int debug_execution) +static int cortex_m_resume(struct target *target, bool current, + target_addr_t address, bool handle_breakpoints, bool debug_execution) { - int retval = cortex_m_restore_one(target, !!current, &address, !!handle_breakpoints, !!debug_execution); + int retval = cortex_m_restore_one(target, current, &address, + handle_breakpoints, debug_execution); if (retval != ERROR_OK) { LOG_TARGET_ERROR(target, "context restore failed, aborting resume"); return retval; } if (target->smp && !debug_execution) { - retval = cortex_m_restore_smp(target, !!handle_breakpoints); + retval = cortex_m_restore_smp(target, handle_breakpoints); if (retval != ERROR_OK) LOG_TARGET_WARNING(target, "resume of a SMP target failed, trying to resume current one"); } - cortex_m_restart_one(target, !!debug_execution); + cortex_m_restart_one(target, debug_execution); if (retval != ERROR_OK) { LOG_TARGET_ERROR(target, "resume failed"); return retval; @@ -1485,8 +1486,8 @@ static int cortex_m_resume(struct target *target, int current, } /* int irqstepcount = 0; */ -static int cortex_m_step(struct target *target, int current, - target_addr_t address, int handle_breakpoints) +static int cortex_m_step(struct target *target, bool current, + target_addr_t address, bool handle_breakpoints) { struct cortex_m_common *cortex_m = target_to_cm(target); struct armv7m_common *armv7m = &cortex_m->armv7m; @@ -1506,7 +1507,7 @@ static int cortex_m_step(struct target *target, int current, if (target->smp && target->gdb_service) target->gdb_service->target = target; - /* current = 1: continue on current pc, otherwise continue at <address> */ + /* current = true: continue on current pc, otherwise continue at <address> */ if (!current) { buf_set_u32(pc->value, 0, 32, address); pc->dirty = true; @@ -2316,7 +2317,7 @@ int cortex_m_profiling(struct target *target, uint32_t *samples, /* Make sure the target is running */ target_poll(target); if (target->state == TARGET_HALTED) - retval = target_resume(target, 1, 0, 0, 0); + retval = target_resume(target, true, 0, false, false); if (retval != ERROR_OK) { LOG_TARGET_ERROR(target, "Error while resuming target"); diff --git a/src/target/dsp563xx.c b/src/target/dsp563xx.c index 0547947..629056f 100644 --- a/src/target/dsp563xx.c +++ b/src/target/dsp563xx.c @@ -1115,10 +1115,10 @@ static int dsp563xx_halt(struct target *target) } static int dsp563xx_resume(struct target *target, - int current, + bool current, target_addr_t address, - int handle_breakpoints, - int debug_execution) + bool handle_breakpoints, + bool debug_execution) { int err; struct dsp563xx_common *dsp563xx = target_to_dsp563xx(target); @@ -1132,7 +1132,7 @@ static int dsp563xx_resume(struct target *target, if (current && dsp563xx->core_cache->reg_list[DSP563XX_REG_IDX_PC].dirty) { dsp563xx_write_core_reg(target, DSP563XX_REG_IDX_PC); address = dsp563xx->core_regs[DSP563XX_REG_IDX_PC]; - current = 0; + current = false; } LOG_DEBUG("%s %08X %08" TARGET_PRIXADDR, __func__, current, address); @@ -1172,9 +1172,9 @@ static int dsp563xx_resume(struct target *target, } static int dsp563xx_step_ex(struct target *target, - int current, + bool current, uint32_t address, - int handle_breakpoints, + bool handle_breakpoints, int steps) { int err; @@ -1196,7 +1196,7 @@ static int dsp563xx_step_ex(struct target *target, if (current && dsp563xx->core_cache->reg_list[DSP563XX_REG_IDX_PC].dirty) { dsp563xx_write_core_reg(target, DSP563XX_REG_IDX_PC); address = dsp563xx->core_regs[DSP563XX_REG_IDX_PC]; - current = 0; + current = false; } LOG_DEBUG("%s %08X %08" PRIX32, __func__, current, address); @@ -1288,9 +1288,9 @@ static int dsp563xx_step_ex(struct target *target, } static int dsp563xx_step(struct target *target, - int current, + bool current, target_addr_t address, - int handle_breakpoints) + bool handle_breakpoints) { int err; struct dsp563xx_common *dsp563xx = target_to_dsp563xx(target); @@ -1359,7 +1359,7 @@ static int dsp563xx_deassert_reset(struct target *target) * reset vector and need 2 cycles to fill * the cache (fetch,decode,execute) */ - err = dsp563xx_step_ex(target, 1, 0, 1, 1); + err = dsp563xx_step_ex(target, true, 0, true, 1); if (err != ERROR_OK) return err; } @@ -1419,7 +1419,7 @@ static int dsp563xx_run_algorithm(struct target *target, } /* exec */ - retval = target_resume(target, 0, entry_point, 1, 1); + retval = target_resume(target, false, entry_point, true, true); if (retval != ERROR_OK) return retval; @@ -1972,7 +1972,7 @@ static int dsp563xx_add_custom_watchpoint(struct target *target, uint32_t addres if (err == ERROR_OK && was_running) { /* Resume from current PC */ - err = dsp563xx_resume(target, 1, 0x0, 0, 0); + err = dsp563xx_resume(target, true, 0x0, false, false); } return err; diff --git a/src/target/dsp5680xx.c b/src/target/dsp5680xx.c index b370aaf..3f9a674 100644 --- a/src/target/dsp5680xx.c +++ b/src/target/dsp5680xx.c @@ -993,8 +993,8 @@ static int dsp5680xx_poll(struct target *target) return ERROR_OK; } -static int dsp5680xx_resume(struct target *target, int current, - target_addr_t address, int hb, int d) +static int dsp5680xx_resume(struct target *target, bool current, + target_addr_t address, bool handle_breakpoints, bool debug_execution) { if (target->state == TARGET_RUNNING) { LOG_USER("Target already running."); @@ -2048,7 +2048,7 @@ int dsp5680xx_f_wr(struct target *t, const uint8_t *b, uint32_t a, uint32_t coun retval = core_tx_upper_data(target, tmp, &drscan_data); err_check_propagate(retval); - retval = dsp5680xx_resume(target, 0, ram_addr, 0, 0); + retval = dsp5680xx_resume(target, false, ram_addr, false, false); err_check_propagate(retval); int counter = FLUSH_COUNT_FLASH; @@ -2234,8 +2234,8 @@ int dsp5680xx_f_lock(struct target *target) return retval; } -static int dsp5680xx_step(struct target *target, int current, target_addr_t address, - int handle_breakpoints) +static int dsp5680xx_step(struct target *target, bool current, target_addr_t address, + bool handle_breakpoints) { err_check(ERROR_FAIL, DSP5680XX_ERROR_NOT_IMPLEMENTED_STEP, "Not implemented yet."); diff --git a/src/target/esirisc.c b/src/target/esirisc.c index fc2d201..da40928 100644 --- a/src/target/esirisc.c +++ b/src/target/esirisc.c @@ -846,8 +846,9 @@ static int esirisc_enable_step(struct target *target) return ERROR_OK; } -static int esirisc_resume_or_step(struct target *target, int current, target_addr_t address, - int handle_breakpoints, int debug_execution, bool step) +static int esirisc_resume_or_step(struct target *target, bool current, + target_addr_t address, bool handle_breakpoints, bool debug_execution, + bool step) { struct esirisc_common *esirisc = target_to_esirisc(target); struct esirisc_jtag *jtag_info = &esirisc->jtag_info; @@ -917,8 +918,8 @@ static int esirisc_resume_or_step(struct target *target, int current, target_add return ERROR_OK; } -static int esirisc_resume(struct target *target, int current, target_addr_t address, - int handle_breakpoints, int debug_execution) +static int esirisc_resume(struct target *target, bool current, + target_addr_t address, bool handle_breakpoints, bool debug_execution) { LOG_TARGET_DEBUG(target, "-"); @@ -926,13 +927,13 @@ static int esirisc_resume(struct target *target, int current, target_addr_t addr handle_breakpoints, debug_execution, false); } -static int esirisc_step(struct target *target, int current, target_addr_t address, - int handle_breakpoints) +static int esirisc_step(struct target *target, bool current, + target_addr_t address, bool handle_breakpoints) { LOG_TARGET_DEBUG(target, "-"); return esirisc_resume_or_step(target, current, address, - handle_breakpoints, 0, true); + handle_breakpoints, false, true); } static int esirisc_debug_step(struct target *target) diff --git a/src/target/espressif/esp32.c b/src/target/espressif/esp32.c index 324aa39..4deb5e0 100644 --- a/src/target/espressif/esp32.c +++ b/src/target/espressif/esp32.c @@ -175,7 +175,8 @@ static int esp32_soc_reset(struct target *target) LOG_DEBUG("Resuming the target"); xtensa = target_to_xtensa(target); xtensa->suppress_dsr_errors = true; - res = xtensa_resume(target, 0, ESP32_RTC_SLOW_MEM_BASE + 4, 0, 0); + res = xtensa_resume(target, false, ESP32_RTC_SLOW_MEM_BASE + 4, false, + false); xtensa->suppress_dsr_errors = false; if (res != ERROR_OK) { LOG_ERROR("Failed to run stub (%d)!", res); diff --git a/src/target/espressif/esp32_apptrace.c b/src/target/espressif/esp32_apptrace.c index 125f366..3070960 100644 --- a/src/target/espressif/esp32_apptrace.c +++ b/src/target/espressif/esp32_apptrace.c @@ -649,7 +649,7 @@ static int esp32_apptrace_wait4halt(struct esp32_apptrace_cmd_ctx *ctx, struct t if (res != ERROR_OK) return res; if (target->state == TARGET_HALTED) { - LOG_USER("%s: HALTED", target->cmd_name); + LOG_TARGET_USER(target, "HALTED"); break; } alive_sleep(500); @@ -708,7 +708,7 @@ int esp32_apptrace_safe_halt_targets(struct esp32_apptrace_cmd_ctx *ctx, } while (stat) { /* allow this CPU to leave ERI write critical section */ - res = target_resume(ctx->cpus[k], 1, 0, 1, 0); + res = target_resume(ctx->cpus[k], true, 0, true, false); if (res != ERROR_OK) { LOG_ERROR("Failed to resume target (%d)!", res); breakpoint_remove(ctx->cpus[k], bp_addr); @@ -796,7 +796,7 @@ static int esp32_apptrace_connect_targets(struct esp32_apptrace_cmd_ctx *ctx, /* in SMP mode we need to call target_resume for one core only */ continue; } - res = target_resume(ctx->cpus[k], 1, 0, 1, 0); + res = target_resume(ctx->cpus[k], true, 0, true, false); if (res != ERROR_OK) { command_print(ctx->cmd, "Failed to resume target (%d)!", res); return res; @@ -1352,7 +1352,7 @@ static int esp32_sysview_stop(struct esp32_apptrace_cmd_ctx *ctx) /* in SMP mode we need to call target_resume for one core only */ continue; } - res = target_resume(ctx->cpus[k], 1, 0, 1, 0); + res = target_resume(ctx->cpus[k], true, 0, true, false); if (res != ERROR_OK) { LOG_ERROR("sysview: Failed to resume target '%s' (%d)!", target_name(ctx->cpus[k]), res); return res; diff --git a/src/target/espressif/esp32s2.c b/src/target/espressif/esp32s2.c index 2abde47..4f3914f 100644 --- a/src/target/espressif/esp32s2.c +++ b/src/target/espressif/esp32s2.c @@ -370,7 +370,8 @@ static int esp32s2_on_halt(struct target *target) return ret; } -static int esp32s2_step(struct target *target, int current, target_addr_t address, int handle_breakpoints) +static int esp32s2_step(struct target *target, bool current, + target_addr_t address, bool handle_breakpoints) { int ret = xtensa_step(target, current, address, handle_breakpoints); if (ret == ERROR_OK) { @@ -397,7 +398,7 @@ static int esp32s2_poll(struct target *target) if (ret == ERROR_OK && esp_xtensa->semihost.need_resume) { esp_xtensa->semihost.need_resume = false; /* Resume xtensa_resume will handle BREAK instruction. */ - ret = target_resume(target, 1, 0, 1, 0); + ret = target_resume(target, true, 0, true, false); if (ret != ERROR_OK) { LOG_ERROR("Failed to resume target"); return ret; diff --git a/src/target/espressif/esp32s3.c b/src/target/espressif/esp32s3.c index 2afb4b0..7507c11 100644 --- a/src/target/espressif/esp32s3.c +++ b/src/target/espressif/esp32s3.c @@ -175,7 +175,8 @@ static int esp32s3_soc_reset(struct target *target) LOG_DEBUG("Resuming the target"); xtensa = target_to_xtensa(target); xtensa->suppress_dsr_errors = true; - res = xtensa_resume(target, 0, ESP32_S3_RTC_SLOW_MEM_BASE + 4, 0, 0); + res = xtensa_resume(target, false, ESP32_S3_RTC_SLOW_MEM_BASE + 4, false, + false); xtensa->suppress_dsr_errors = false; if (res != ERROR_OK) { LOG_ERROR("Failed to run stub (%d)!", res); diff --git a/src/target/espressif/esp_xtensa.c b/src/target/espressif/esp_xtensa.c index 9b57f34..4cadcb3 100644 --- a/src/target/espressif/esp_xtensa.c +++ b/src/target/espressif/esp_xtensa.c @@ -213,7 +213,7 @@ int esp_xtensa_profiling(struct target *target, uint32_t *samples, /* Make sure the target is running */ target_poll(target); if (target->state == TARGET_HALTED) - retval = target_resume(target, 1, 0, 0, 0); + retval = target_resume(target, true, 0, false, false); if (retval != ERROR_OK) { LOG_TARGET_ERROR(target, "Error while resuming target"); diff --git a/src/target/espressif/esp_xtensa_apptrace.c b/src/target/espressif/esp_xtensa_apptrace.c index 5741ab0..313f6ce 100644 --- a/src/target/espressif/esp_xtensa_apptrace.c +++ b/src/target/espressif/esp_xtensa_apptrace.c @@ -277,7 +277,7 @@ static int esp_xtensa_swdbg_activate(struct target *target, int enab) xtensa_dm_queue_tdi_idle(&xtensa->dbg_mod); int res = xtensa_dm_queue_execute(&xtensa->dbg_mod); if (res != ERROR_OK) { - LOG_ERROR("%s: writing DCR failed!", target->cmd_name); + LOG_TARGET_ERROR(target, "writing DCR failed"); return res; } diff --git a/src/target/espressif/esp_xtensa_smp.c b/src/target/espressif/esp_xtensa_smp.c index c49146d..b9e2156 100644 --- a/src/target/espressif/esp_xtensa_smp.c +++ b/src/target/espressif/esp_xtensa_smp.c @@ -218,7 +218,7 @@ int esp_xtensa_smp_poll(struct target *target) !esp_xtensa_smp->other_core_does_resume) { esp_xtensa->semihost.need_resume = false; /* Resume xtensa_resume will handle BREAK instruction. */ - ret = target_resume(target, 1, 0, 1, 0); + ret = target_resume(target, true, 0, true, false); if (ret != ERROR_OK) { LOG_ERROR("Failed to resume target"); return ret; @@ -229,7 +229,7 @@ int esp_xtensa_smp_poll(struct target *target) /* check whether any core polled by esp_xtensa_smp_update_halt_gdb() requested resume */ if (target->smp && other_core_resume_req) { /* Resume xtensa_resume will handle BREAK instruction. */ - ret = target_resume(target, 1, 0, 1, 0); + ret = target_resume(target, true, 0, true, false); if (ret != ERROR_OK) { LOG_ERROR("Failed to resume target"); return ret; @@ -334,8 +334,7 @@ static inline int esp_xtensa_smp_smpbreak_restore(struct target *target, uint32_ } static int esp_xtensa_smp_resume_cores(struct target *target, - int handle_breakpoints, - int debug_execution) + bool handle_breakpoints, bool debug_execution) { struct target_list *head; struct target *curr; @@ -348,7 +347,7 @@ static int esp_xtensa_smp_resume_cores(struct target *target, if ((curr != target) && (curr->state != TARGET_RUNNING) && target_was_examined(curr)) { /* resume current address, not in SMP mode */ curr->smp = 0; - int res = esp_xtensa_smp_resume(curr, 1, 0, handle_breakpoints, debug_execution); + int res = esp_xtensa_smp_resume(curr, true, 0, handle_breakpoints, debug_execution); curr->smp = 1; if (res != ERROR_OK) return res; @@ -358,10 +357,10 @@ static int esp_xtensa_smp_resume_cores(struct target *target, } int esp_xtensa_smp_resume(struct target *target, - int current, + bool current, target_addr_t address, - int handle_breakpoints, - int debug_execution) + bool handle_breakpoints, + bool debug_execution) { int res; uint32_t smp_break; @@ -420,9 +419,9 @@ int esp_xtensa_smp_resume(struct target *target, } int esp_xtensa_smp_step(struct target *target, - int current, + bool current, target_addr_t address, - int handle_breakpoints) + bool handle_breakpoints) { int res; uint32_t smp_break = 0; diff --git a/src/target/espressif/esp_xtensa_smp.h b/src/target/espressif/esp_xtensa_smp.h index 39afd8a..ec074c1 100644 --- a/src/target/espressif/esp_xtensa_smp.h +++ b/src/target/espressif/esp_xtensa_smp.h @@ -27,14 +27,14 @@ struct esp_xtensa_smp_common { int esp_xtensa_smp_poll(struct target *target); int esp_xtensa_smp_resume(struct target *target, - int current, + bool current, target_addr_t address, - int handle_breakpoints, - int debug_execution); + bool handle_breakpoints, + bool debug_execution); int esp_xtensa_smp_step(struct target *target, - int current, + bool current, target_addr_t address, - int handle_breakpoints); + bool handle_breakpoints); int esp_xtensa_smp_assert_reset(struct target *target); int esp_xtensa_smp_deassert_reset(struct target *target); int esp_xtensa_smp_soft_reset_halt(struct target *target); diff --git a/src/target/feroceon.c b/src/target/feroceon.c index 1e7eb09..840ca1b 100644 --- a/src/target/feroceon.c +++ b/src/target/feroceon.c @@ -526,7 +526,7 @@ static int feroceon_bulk_write_memory(struct target *target, arm->core_state = ARM_STATE_ARM; embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_COMMS_DATA], 0); - arm7_9_resume(target, 0, arm7_9->dcc_working_area->address, 1, 1); + arm7_9_resume(target, false, arm7_9->dcc_working_area->address, true, true); /* send data over */ x = 0; diff --git a/src/target/hla_target.c b/src/target/hla_target.c index 6b0d2e9..ef05df2 100644 --- a/src/target/hla_target.c +++ b/src/target/hla_target.c @@ -406,7 +406,8 @@ static int hl_deassert_reset(struct target *target) target->SAVED_DCRDR = 0; /* clear both DCC busy bits on initial resume */ - return target->reset_halt ? ERROR_OK : target_resume(target, 1, 0, 0, 0); + return target->reset_halt ? ERROR_OK : target_resume(target, true, 0, false, + false); } static int adapter_halt(struct target *target) @@ -434,9 +435,9 @@ static int adapter_halt(struct target *target) return ERROR_OK; } -static int adapter_resume(struct target *target, int current, - target_addr_t address, int handle_breakpoints, - int debug_execution) +static int adapter_resume(struct target *target, bool current, + target_addr_t address, bool handle_breakpoints, + bool debug_execution) { int res; struct hl_interface *adapter = target_to_adapter(target); @@ -525,8 +526,8 @@ static int adapter_resume(struct target *target, int current, return ERROR_OK; } -static int adapter_step(struct target *target, int current, - target_addr_t address, int handle_breakpoints) +static int adapter_step(struct target *target, bool current, + target_addr_t address, bool handle_breakpoints) { int res; struct hl_interface *adapter = target_to_adapter(target); diff --git a/src/target/lakemont.c b/src/target/lakemont.c index 0340d0d..39a50c7 100644 --- a/src/target/lakemont.c +++ b/src/target/lakemont.c @@ -988,8 +988,8 @@ int lakemont_halt(struct target *t) } } -int lakemont_resume(struct target *t, int current, target_addr_t address, - int handle_breakpoints, int debug_execution) +int lakemont_resume(struct target *t, bool current, target_addr_t address, + bool handle_breakpoints, bool debug_execution) { struct breakpoint *bp = NULL; struct x86_32_common *x86_32 = target_to_x86_32(t); @@ -1004,7 +1004,7 @@ int lakemont_resume(struct target *t, int current, target_addr_t address, bp = breakpoint_find(t, eip); if (bp /*&& bp->type == BKPT_SOFT*/) { /* the step will step over the breakpoint */ - if (lakemont_step(t, 0, 0, 1) != ERROR_OK) { + if (lakemont_step(t, false, 0, true) != ERROR_OK) { LOG_ERROR("%s stepping over a software breakpoint at 0x%08" PRIx32 " " "failed to resume the target", __func__, eip); return ERROR_FAIL; @@ -1029,8 +1029,8 @@ int lakemont_resume(struct target *t, int current, target_addr_t address, return ERROR_OK; } -int lakemont_step(struct target *t, int current, - target_addr_t address, int handle_breakpoints) +int lakemont_step(struct target *t, bool current, target_addr_t address, + bool handle_breakpoints) { struct x86_32_common *x86_32 = target_to_x86_32(t); uint32_t eflags = buf_get_u32(x86_32->cache->reg_list[EFLAGS].value, 0, 32); diff --git a/src/target/lakemont.h b/src/target/lakemont.h index ca6557f..4c84f74 100644 --- a/src/target/lakemont.h +++ b/src/target/lakemont.h @@ -84,10 +84,10 @@ int lakemont_init_arch_info(struct target *t, struct x86_32_common *x86_32); int lakemont_poll(struct target *t); int lakemont_arch_state(struct target *t); int lakemont_halt(struct target *t); -int lakemont_resume(struct target *t, int current, target_addr_t address, - int handle_breakpoints, int debug_execution); -int lakemont_step(struct target *t, int current, - target_addr_t address, int handle_breakpoints); +int lakemont_resume(struct target *t, bool current, target_addr_t address, + bool handle_breakpoints, bool debug_execution); +int lakemont_step(struct target *t, bool current, + target_addr_t address, bool handle_breakpoints); int lakemont_reset_assert(struct target *t); int lakemont_reset_deassert(struct target *t); int lakemont_update_after_probemode_entry(struct target *t); diff --git a/src/target/ls1_sap.c b/src/target/ls1_sap.c index 9bd00c0..692f4cc 100644 --- a/src/target/ls1_sap.c +++ b/src/target/ls1_sap.c @@ -55,15 +55,15 @@ static int ls1_sap_halt(struct target *target) return ERROR_OK; } -static int ls1_sap_resume(struct target *target, int current, target_addr_t address, - int handle_breakpoints, int debug_execution) +static int ls1_sap_resume(struct target *target, bool current, + target_addr_t address, bool handle_breakpoints, bool debug_execution) { LOG_DEBUG("%s", __func__); return ERROR_OK; } -static int ls1_sap_step(struct target *target, int current, target_addr_t address, - int handle_breakpoints) +static int ls1_sap_step(struct target *target, bool current, + target_addr_t address, bool handle_breakpoints) { LOG_DEBUG("%s", __func__); return ERROR_OK; diff --git a/src/target/mem_ap.c b/src/target/mem_ap.c index 5b2bbb1..fdc52c3 100644 --- a/src/target/mem_ap.c +++ b/src/target/mem_ap.c @@ -102,8 +102,9 @@ static int mem_ap_halt(struct target *target) return ERROR_OK; } -static int mem_ap_resume(struct target *target, int current, target_addr_t address, - int handle_breakpoints, int debug_execution) +static int mem_ap_resume(struct target *target, bool current, + target_addr_t address, bool handle_breakpoints, + bool debug_execution) { LOG_TARGET_DEBUG(target, "%s", __func__); target->state = TARGET_RUNNING; @@ -111,8 +112,8 @@ static int mem_ap_resume(struct target *target, int current, target_addr_t addre return ERROR_OK; } -static int mem_ap_step(struct target *target, int current, target_addr_t address, - int handle_breakpoints) +static int mem_ap_step(struct target *target, bool current, + target_addr_t address, bool handle_breakpoints) { LOG_TARGET_DEBUG(target, "%s", __func__); target->state = TARGET_HALTED; diff --git a/src/target/mips32.c b/src/target/mips32.c index fcb7042..4527c5f 100644 --- a/src/target/mips32.c +++ b/src/target/mips32.c @@ -588,7 +588,7 @@ static int mips32_run_and_wait(struct target *target, target_addr_t entry_point, int retval; /* This code relies on the target specific resume() and poll()->debug_entry() * sequence to write register values to the processor and the read them back */ - retval = target_resume(target, 0, entry_point, 0, 1); + retval = target_resume(target, false, entry_point, false, true); if (retval != ERROR_OK) return retval; diff --git a/src/target/mips_m4k.c b/src/target/mips_m4k.c index 1543de3..dc74501 100644 --- a/src/target/mips_m4k.c +++ b/src/target/mips_m4k.c @@ -30,9 +30,9 @@ static int mips_m4k_set_breakpoint(struct target *target, struct breakpoint *breakpoint); static int mips_m4k_unset_breakpoint(struct target *target, struct breakpoint *breakpoint); -static int mips_m4k_internal_restore(struct target *target, int current, - target_addr_t address, int handle_breakpoints, - int debug_execution); +static int mips_m4k_internal_restore(struct target *target, bool current, + target_addr_t address, bool handle_breakpoints, + bool debug_execution); static int mips_m4k_halt(struct target *target); static int mips_m4k_bulk_write_memory(struct target *target, target_addr_t address, uint32_t count, const uint8_t *buffer); @@ -398,7 +398,8 @@ static int mips_m4k_single_step_core(struct target *target) return ERROR_OK; } -static int mips_m4k_restore_smp(struct target *target, uint32_t address, int handle_breakpoints) +static int mips_m4k_restore_smp(struct target *target, uint32_t address, + bool handle_breakpoints) { int retval = ERROR_OK; struct target_list *head; @@ -408,8 +409,8 @@ static int mips_m4k_restore_smp(struct target *target, uint32_t address, int han struct target *curr = head->target; if ((curr != target) && (curr->state != TARGET_RUNNING)) { /* resume current address , not in step mode */ - ret = mips_m4k_internal_restore(curr, 1, address, - handle_breakpoints, 0); + ret = mips_m4k_internal_restore(curr, true, address, + handle_breakpoints, false); if (ret != ERROR_OK) { LOG_TARGET_ERROR(curr, "failed to resume at address: 0x%" PRIx32, @@ -421,8 +422,9 @@ static int mips_m4k_restore_smp(struct target *target, uint32_t address, int han return retval; } -static int mips_m4k_internal_restore(struct target *target, int current, - target_addr_t address, int handle_breakpoints, int debug_execution) +static int mips_m4k_internal_restore(struct target *target, bool current, + target_addr_t address, bool handle_breakpoints, + bool debug_execution) { struct mips32_common *mips32 = target_to_mips32(target); struct mips_ejtag *ejtag_info = &mips32->ejtag_info; @@ -440,7 +442,7 @@ static int mips_m4k_internal_restore(struct target *target, int current, mips_m4k_enable_watchpoints(target); } - /* current = 1: continue on current pc, otherwise continue at <address> */ + /* current = true: continue on current pc, otherwise continue at <address> */ if (!current) { mips_m4k_isa_filter(mips32->isa_imp, &address); buf_set_u32(mips32->core_cache->reg_list[MIPS32_REGLIST_C0_PC_INDEX].value, 0, 32, address); @@ -448,7 +450,7 @@ static int mips_m4k_internal_restore(struct target *target, int current, mips32->core_cache->reg_list[MIPS32_REGLIST_C0_PC_INDEX].valid = true; } - if ((mips32->isa_imp > 1) && debug_execution) /* if more than one isa supported */ + if (mips32->isa_imp > 1 && debug_execution) /* if more than one isa supported */ buf_set_u32(mips32->core_cache->reg_list[MIPS32_REGLIST_C0_PC_INDEX].value, 0, 1, mips32->isa_mode); if (!current) @@ -494,8 +496,8 @@ static int mips_m4k_internal_restore(struct target *target, int current, return ERROR_OK; } -static int mips_m4k_resume(struct target *target, int current, - target_addr_t address, int handle_breakpoints, int debug_execution) +static int mips_m4k_resume(struct target *target, bool current, + target_addr_t address, bool handle_breakpoints, bool debug_execution) { int retval = ERROR_OK; @@ -521,8 +523,8 @@ static int mips_m4k_resume(struct target *target, int current, return retval; } -static int mips_m4k_step(struct target *target, int current, - target_addr_t address, int handle_breakpoints) +static int mips_m4k_step(struct target *target, bool current, + target_addr_t address, bool handle_breakpoints) { /* get pointers to arch-specific information */ struct mips32_common *mips32 = target_to_mips32(target); @@ -534,7 +536,7 @@ static int mips_m4k_step(struct target *target, int current, return ERROR_TARGET_NOT_HALTED; } - /* current = 1: continue on current pc, otherwise continue at <address> */ + /* current = true: continue on current pc, otherwise continue at <address> */ if (!current) { mips_m4k_isa_filter(mips32->isa_imp, &address); buf_set_u32(mips32->core_cache->reg_list[MIPS32_REGLIST_C0_PC_INDEX].value, 0, 32, address); diff --git a/src/target/mips_mips64.c b/src/target/mips_mips64.c index 9921e93..85e3779 100644 --- a/src/target/mips_mips64.c +++ b/src/target/mips_mips64.c @@ -592,9 +592,9 @@ static int mips_mips64_unset_breakpoint(struct target *target, return ERROR_OK; } -static int mips_mips64_resume(struct target *target, int current, - uint64_t address, int handle_breakpoints, - int debug_execution) +static int mips_mips64_resume(struct target *target, bool current, + uint64_t address, bool handle_breakpoints, + bool debug_execution) { struct mips64_common *mips64 = target->arch_info; struct mips_ejtag *ejtag_info = &mips64->ejtag_info; @@ -622,7 +622,7 @@ static int mips_mips64_resume(struct target *target, int current, } pc = &mips64->core_cache->reg_list[MIPS64_PC]; - /* current = 1: continue on current pc, otherwise continue at <address> */ + /* current = true: continue on current pc, otherwise continue at <address> */ if (!current) { buf_set_u64(pc->value, 0, 64, address); pc->dirty = true; @@ -696,8 +696,8 @@ static int mips_mips64_resume(struct target *target, int current, return ERROR_OK; } -static int mips_mips64_step(struct target *target, int current, - uint64_t address, int handle_breakpoints) +static int mips_mips64_step(struct target *target, bool current, + uint64_t address, bool handle_breakpoints) { struct mips64_common *mips64 = target->arch_info; struct mips_ejtag *ejtag_info = &mips64->ejtag_info; @@ -713,7 +713,7 @@ static int mips_mips64_step(struct target *target, int current, if (mips64->mips64mode32) address = mips64_extend_sign(address); - /* current = 1: continue on current pc, otherwise continue at + /* current = true: continue on current pc, otherwise continue at * <address> */ if (!current) { buf_set_u64(pc->value, 0, 64, address); diff --git a/src/target/openrisc/or1k.c b/src/target/openrisc/or1k.c index efc076c..4b9d3bc 100644 --- a/src/target/openrisc/or1k.c +++ b/src/target/openrisc/or1k.c @@ -775,9 +775,9 @@ static bool is_any_soft_breakpoint(struct target *target) return false; } -static int or1k_resume_or_step(struct target *target, int current, - uint32_t address, int handle_breakpoints, - int debug_execution, int step) +static int or1k_resume_or_step(struct target *target, bool current, + uint32_t address, bool handle_breakpoints, bool debug_execution, + int step) { struct or1k_common *or1k = target_to_or1k(target); struct or1k_du *du_core = or1k_to_du(or1k); @@ -885,9 +885,8 @@ static int or1k_resume_or_step(struct target *target, int current, return ERROR_OK; } -static int or1k_resume(struct target *target, int current, - target_addr_t address, int handle_breakpoints, - int debug_execution) +static int or1k_resume(struct target *target, bool current, + target_addr_t address, bool handle_breakpoints, bool debug_execution) { return or1k_resume_or_step(target, current, address, handle_breakpoints, @@ -895,12 +894,12 @@ static int or1k_resume(struct target *target, int current, NO_SINGLE_STEP); } -static int or1k_step(struct target *target, int current, - target_addr_t address, int handle_breakpoints) +static int or1k_step(struct target *target, bool current, + target_addr_t address, bool handle_breakpoints) { return or1k_resume_or_step(target, current, address, handle_breakpoints, - 0, + false, SINGLE_STEP); } @@ -1216,7 +1215,7 @@ static int or1k_profiling(struct target *target, uint32_t *samples, /* Make sure the target is running */ target_poll(target); if (target->state == TARGET_HALTED) - retval = target_resume(target, 1, 0, 0, 0); + retval = target_resume(target, true, 0, false, false); if (retval != ERROR_OK) { LOG_ERROR("Error while resuming target"); diff --git a/src/target/quark_d20xx.c b/src/target/quark_d20xx.c index d63a42a..90cf667 100644 --- a/src/target/quark_d20xx.c +++ b/src/target/quark_d20xx.c @@ -65,7 +65,7 @@ static int quark_d20xx_reset_deassert(struct target *t) } /* resume target if reset mode is run */ if (!t->reset_halt) { - retval = lakemont_resume(t, 1, 0, 0, 0); + retval = lakemont_resume(t, true, 0, false, false); if (retval != ERROR_OK) { LOG_ERROR("%s could not resume target", __func__); return retval; diff --git a/src/target/riscv/riscv-011.c b/src/target/riscv/riscv-011.c index ef80e43..54de6a1 100644 --- a/src/target/riscv/riscv-011.c +++ b/src/target/riscv/riscv-011.c @@ -1458,8 +1458,8 @@ static int strict_step(struct target *target, bool announce) return ERROR_OK; } -static int step(struct target *target, int current, target_addr_t address, - int handle_breakpoints) +static int step(struct target *target, bool current, target_addr_t address, + bool handle_breakpoints) { jtag_add_ir_scan(target->tap, &select_dbus, TAP_IDLE); @@ -1889,8 +1889,16 @@ static int handle_halt(struct target *target, bool announce) if (target->debug_reason == DBG_REASON_BREAKPOINT) { int retval; - if (riscv_semihosting(target, &retval) != 0) - return retval; + /* Hotfix: Don't try to handle semihosting before the target is marked as examined. */ + /* TODO: The code should be rearranged so that: + * - Semihosting is not attempted before the target is examined. + * - When the target is already halted on a semihosting magic sequence + * at the time when OpenOCD connects to it, this semihosting attempt + * gets handled right after the examination. + */ + if (target_was_examined(target)) + if (riscv_semihosting(target, &retval) != SEMIHOSTING_NONE) + return retval; } if (announce) @@ -1952,8 +1960,9 @@ static int riscv011_poll(struct target *target) return poll_target(target, true); } -static int riscv011_resume(struct target *target, int current, - target_addr_t address, int handle_breakpoints, int debug_execution) +static int riscv011_resume(struct target *target, bool current, + target_addr_t address, bool handle_breakpoints, + bool debug_execution) { RISCV_INFO(r); jtag_add_ir_scan(target->tap, &select_dbus, TAP_IDLE); diff --git a/src/target/riscv/riscv-013.c b/src/target/riscv/riscv-013.c index d02059c..b5c6bfb 100644 --- a/src/target/riscv/riscv-013.c +++ b/src/target/riscv/riscv-013.c @@ -145,6 +145,66 @@ typedef struct { struct target *target; } target_list_t; +struct ac_cache { + uint32_t *commands; + size_t size; +}; + +static int ac_cache_elem_comparator(const void *p_lhs, const void *p_rhs) +{ + uint32_t lhs = *(const uint32_t *)p_lhs; + uint32_t rhs = *(const uint32_t *)p_rhs; + if (lhs < rhs) + return -1; + if (lhs > rhs) + return 1; + return 0; +} + +static struct ac_cache ac_cache_construct(void) +{ + struct ac_cache cache = { + cache.commands = NULL, + cache.size = 0, + }; + return cache; +} + +static void ac_cache_free(struct ac_cache *cache) +{ + free(cache->commands); + cache->commands = NULL; + cache->size = 0; +} + +static void ac_cache_insert(struct ac_cache *cache, uint32_t command) +{ + assert(cache); + + size_t old_size = cache->size; + size_t new_size = old_size + 1; + size_t entry_size = sizeof(*cache->commands); + + uint32_t *commands = realloc(cache->commands, new_size * entry_size); + if (!commands) { + LOG_ERROR("Reallocation to %zu bytes failed", new_size * entry_size); + return; + } + + commands[old_size] = command; + cache->commands = commands; + cache->size = new_size; + + qsort(cache->commands, cache->size, entry_size, + ac_cache_elem_comparator); +} + +static bool ac_cache_contains(const struct ac_cache *cache, uint32_t command) +{ + return bsearch(&command, cache->commands, cache->size, + sizeof(*cache->commands), ac_cache_elem_comparator); +} + typedef struct { /* The indexed used to address this hart in its DM. */ unsigned int index; @@ -175,12 +235,7 @@ typedef struct { */ struct riscv_scan_delays learned_delays; - bool abstract_read_csr_supported; - bool abstract_write_csr_supported; - bool abstract_read_fpr_supported; - bool abstract_write_fpr_supported; - - yes_no_maybe_t has_aampostincrement; + struct ac_cache ac_not_supported_cache; /* Some fields from hartinfo. */ uint8_t datasize; @@ -483,6 +538,7 @@ static bool check_dbgbase_exists(struct target *target) { uint32_t next_dm = 0; unsigned int count = 1; + riscv013_info_t *info = get_info(target); LOG_TARGET_DEBUG(target, "Searching for DM with DMI base address (dbgbase) = 0x%x", target->dbgbase); while (1) { @@ -497,6 +553,12 @@ static bool check_dbgbase_exists(struct target *target) LOG_TARGET_ERROR(target, "Reached the end of DM chain (detected %u DMs in total).", count); break; } + if (next_dm >> info->abits) { + LOG_TARGET_ERROR(target, "The address of the next Debug Module does not fit into %u bits, " + "which is the width of the DMI bus address. This is a HW bug", + info->abits); + break; + } /* Safety: Avoid looping forever in case of buggy nextdm values in the hardware. */ if (count++ > RISCV_MAX_DMS) { LOG_TARGET_ERROR(target, "Supporting no more than %d DMs on a DMI bus. Aborting", RISCV_MAX_DMS); @@ -651,6 +713,30 @@ clear_cmderr: return res; } +enum riscv_debug_reg_ordinal get_cmdtype(uint32_t command) +{ + switch (get_field(command, DM_COMMAND_CMDTYPE)) { + case 0: + return AC_ACCESS_REGISTER_ORDINAL; + case 1: + return AC_QUICK_ACCESS_ORDINAL; + case 2: + return AC_ACCESS_MEMORY_ORDINAL; + default: + assert(false && "Unknown command type value"); + return 0; + } +} + +static void mark_command_as_unsupported(struct target *target, uint32_t command) +{ + LOG_TARGET_DEBUG(target, "Caching the abstract " + "command 0x%" PRIx32 " as not supported", command); + log_debug_reg(target, get_cmdtype(command), + command, __FILE__, __LINE__, __func__); + ac_cache_insert(&get_info(target)->ac_not_supported_cache, command); +} + int riscv013_execute_abstract_command(struct target *target, uint32_t command, uint32_t *cmderr) { @@ -684,6 +770,9 @@ int riscv013_execute_abstract_command(struct target *target, uint32_t command, res = abstract_cmd_batch_check_and_clear_cmderr(target, batch, abstractcs_read_key, cmderr); + if (res != ERROR_OK && *cmderr == CMDERR_NOT_SUPPORTED) + mark_command_as_unsupported(target, command); + cleanup: riscv_batch_free(batch); return res; @@ -829,38 +918,35 @@ uint32_t riscv013_access_register_command(struct target *target, uint32_t number return command; } +static bool is_command_unsupported(struct target *target, uint32_t command) +{ + bool unsupported = ac_cache_contains(&get_info(target)->ac_not_supported_cache, command); + if (!unsupported) + return false; + + LOG_TARGET_DEBUG(target, "Abstract command 0x%" + PRIx32 " is cached as not supported", command); + log_debug_reg(target, get_cmdtype(command), + command, __FILE__, __LINE__, __func__); + return true; +} + static int register_read_abstract_with_size(struct target *target, riscv_reg_t *value, enum gdb_regno number, unsigned int size) { - RISCV013_INFO(info); - - if (number >= GDB_REGNO_FPR0 && number <= GDB_REGNO_FPR31 && - !info->abstract_read_fpr_supported) - return ERROR_FAIL; - if (number >= GDB_REGNO_CSR0 && number <= GDB_REGNO_CSR4095 && - !info->abstract_read_csr_supported) - return ERROR_FAIL; /* The spec doesn't define abstract register numbers for vector registers. */ if (number >= GDB_REGNO_V0 && number <= GDB_REGNO_V31) return ERROR_FAIL; uint32_t command = riscv013_access_register_command(target, number, size, AC_ACCESS_REGISTER_TRANSFER); + if (is_command_unsupported(target, command)) + return ERROR_FAIL; uint32_t 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) { - info->abstract_read_fpr_supported = false; - LOG_TARGET_INFO(target, "Disabling abstract command reads from FPRs."); - } else if (number >= GDB_REGNO_CSR0 && number <= GDB_REGNO_CSR4095) { - info->abstract_read_csr_supported = false; - LOG_TARGET_INFO(target, "Disabling abstract command reads from CSRs."); - } - } + if (result != ERROR_OK) return result; - } if (value) return read_abstract_arg(target, value, 0, size); @@ -879,23 +965,17 @@ static int register_read_abstract(struct target *target, riscv_reg_t *value, static int register_write_abstract(struct target *target, enum gdb_regno number, riscv_reg_t value) { - RISCV013_INFO(info); - dm013_info_t *dm = get_dm(target); if (!dm) return ERROR_FAIL; - if (number >= GDB_REGNO_FPR0 && number <= GDB_REGNO_FPR31 && - !info->abstract_write_fpr_supported) - return ERROR_FAIL; - if (number >= GDB_REGNO_CSR0 && number <= GDB_REGNO_CSR4095 && - !info->abstract_write_csr_supported) - return ERROR_FAIL; - const unsigned int size_bits = register_size(target, number); const uint32_t command = riscv013_access_register_command(target, number, size_bits, AC_ACCESS_REGISTER_TRANSFER | AC_ACCESS_REGISTER_WRITE); + if (is_command_unsupported(target, command)) + return ERROR_FAIL; + LOG_DEBUG_REG(target, AC_ACCESS_REGISTER, command); assert(size_bits % 32 == 0); const unsigned int size_in_words = size_bits / 32; @@ -915,18 +995,9 @@ static int register_write_abstract(struct target *target, enum gdb_regno number, uint32_t cmderr; res = abstract_cmd_batch_check_and_clear_cmderr(target, batch, abstractcs_read_key, &cmderr); + if (res != ERROR_OK && cmderr == CMDERR_NOT_SUPPORTED) + mark_command_as_unsupported(target, command); - if (res != ERROR_OK) { - if (cmderr == CMDERR_NOT_SUPPORTED) { - if (number >= GDB_REGNO_FPR0 && number <= GDB_REGNO_FPR31) { - info->abstract_write_fpr_supported = false; - LOG_TARGET_INFO(target, "Disabling abstract command writes to FPRs."); - } else if (number >= GDB_REGNO_CSR0 && number <= GDB_REGNO_CSR4095) { - info->abstract_write_csr_supported = false; - LOG_TARGET_INFO(target, "Disabling abstract command writes to CSRs."); - } - } - } cleanup: riscv_batch_free(batch); return res; @@ -1709,6 +1780,10 @@ static void deinit_target(struct target *target) if (!info) return; + riscv013_info_t *vsinfo = info->version_specific; + if (vsinfo) + ac_cache_free(&vsinfo->ac_not_supported_cache); + riscv013_dm_free(target); free(info->version_specific); @@ -2824,17 +2899,7 @@ static int init_target(struct command_context *cmd_ctx, info->progbufsize = -1; reset_learned_delays(target); - /* Assume all these abstract commands are supported until we learn - * otherwise. - * TODO: The spec allows eg. one CSR to be able to be accessed abstractly - * while another one isn't. We don't track that this closely here, but in - * the future we probably should. */ - info->abstract_read_csr_supported = true; - info->abstract_write_csr_supported = true; - info->abstract_read_fpr_supported = true; - info->abstract_write_fpr_supported = true; - - info->has_aampostincrement = YNM_MAYBE; + info->ac_not_supported_cache = ac_cache_construct(); return ERROR_OK; } @@ -3724,16 +3789,22 @@ read_memory_abstract(struct target *target, const riscv_mem_access_args_t args) { assert(riscv_mem_access_is_read(args)); - RISCV013_INFO(info); - bool use_aampostincrement = info->has_aampostincrement != YNM_NO; - memset(args.read_buffer, 0, args.count * args.size); /* Convert the size (bytes) to width (bits) */ unsigned int width = args.size << 3; - /* Create the command (physical address, postincrement, read) */ - uint32_t command = access_memory_command(target, false, width, use_aampostincrement, false); + uint32_t command = access_memory_command(target, /* virtual = */ false, + width, /* postincrement = */ true, /* is_write = */ false); + bool use_aampostincrement = !is_command_unsupported(target, command); + if (!use_aampostincrement) + /* It is already known that this abstract memory + * access with aampostincrement=1 is not supported. + * So try aampostincrement=0 right away. + * + * TODO: check if new command is supported */ + command = access_memory_command(target, /* virtual = */ false, + width, /* postincrement = */ false, /* is_write = */ false); /* Execute the reads */ uint8_t *p = args.read_buffer; @@ -3754,33 +3825,14 @@ read_memory_abstract(struct target *target, const riscv_mem_access_args_t args) /* Execute the command */ uint32_t 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 */ - if (info->has_aampostincrement == YNM_MAYBE) { - if (result == ERROR_OK) { - /* Safety: double-check that the address was really auto-incremented */ - riscv_reg_t new_address; - result = read_abstract_arg(target, &new_address, 1, riscv_xlen(target)); - if (result != ERROR_OK) - return mem_access_result(MEM_ACCESS_FAILED_DM_ACCESS_FAILED); - - if (new_address == args.address + args.size) { - LOG_TARGET_DEBUG(target, "aampostincrement is supported on this target."); - info->has_aampostincrement = YNM_YES; - } else { - LOG_TARGET_WARNING(target, "Buggy aampostincrement! Address not incremented correctly."); - info->has_aampostincrement = YNM_NO; - } - } else { - /* Try the same access but with postincrement disabled. */ - command = access_memory_command(target, false, width, false, false); - 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; - } - } + if (use_aampostincrement && result != ERROR_OK && + cmderr == CMDERR_NOT_SUPPORTED) { + LOG_TARGET_DEBUG(target, "Trying the same abstract memory " + "read command, but without aampostincrement"); + use_aampostincrement = false; + command = access_memory_command(target, /* virtual = */ false, + width, /* postincrement = */ false, /* is_write = */ false); + result = riscv013_execute_abstract_command(target, command, &cmderr); } /* TODO: @@ -3796,7 +3848,7 @@ read_memory_abstract(struct target *target, const riscv_mem_access_args_t args) return mem_access_result(MEM_ACCESS_FAILED_DM_ACCESS_FAILED); buf_set_u64(p, 0, 8 * args.size, value); - if (info->has_aampostincrement == YNM_YES) + if (use_aampostincrement) updateaddr = false; p += args.size; } @@ -3814,15 +3866,22 @@ write_memory_abstract(struct target *target, const riscv_mem_access_args_t args) { assert(riscv_mem_access_is_write(args)); - RISCV013_INFO(info); int result = ERROR_OK; - bool use_aampostincrement = info->has_aampostincrement != YNM_NO; /* Convert the size (bytes) to width (bits) */ unsigned int width = args.size << 3; - /* Create the command (physical address, postincrement, write) */ - uint32_t command = access_memory_command(target, false, width, use_aampostincrement, true); + uint32_t command = access_memory_command(target, /* virtual = */ false, + width, /* postincrement = */ true, /* is_write = */ true); + bool use_aampostincrement = !is_command_unsupported(target, command); + if (!use_aampostincrement) + /* It is already known that this abstract memory + * access with aampostincrement=1 is not supported. + * So try aampostincrement=0 right away. + * + * TODO: check if new command is supported */ + command = access_memory_command(target, /* virtual = */ false, + width, /* postincrement = */ false, /* is_write = */ true); /* Execute the writes */ const uint8_t *p = args.write_buffer; @@ -3849,33 +3908,14 @@ write_memory_abstract(struct target *target, const riscv_mem_access_args_t args) /* Execute the command */ uint32_t 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 */ - if (info->has_aampostincrement == YNM_MAYBE) { - if (result == ERROR_OK) { - /* Safety: double-check that the address was really auto-incremented */ - riscv_reg_t new_address; - result = read_abstract_arg(target, &new_address, 1, riscv_xlen(target)); - if (result != ERROR_OK) - return mem_access_result(MEM_ACCESS_FAILED_DM_ACCESS_FAILED); - - if (new_address == args.address + args.size) { - LOG_TARGET_DEBUG(target, "aampostincrement is supported on this target."); - info->has_aampostincrement = YNM_YES; - } else { - LOG_TARGET_WARNING(target, "Buggy aampostincrement! Address not incremented correctly."); - info->has_aampostincrement = YNM_NO; - } - } else { - /* Try the same access but with postincrement disabled. */ - command = access_memory_command(target, false, width, false, true); - 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; - } - } + if (use_aampostincrement && result != ERROR_OK && + cmderr == CMDERR_NOT_SUPPORTED) { + LOG_TARGET_DEBUG(target, "Trying the same abstract memory " + "write command, but without aampostincrement"); + use_aampostincrement = false; + command = access_memory_command(target, /* virtual = */ false, + width, /* postincrement = */ false, /* is_write = */ true); + result = riscv013_execute_abstract_command(target, command, &cmderr); } /* TODO: @@ -3884,7 +3924,7 @@ write_memory_abstract(struct target *target, const riscv_mem_access_args_t args) if (result != ERROR_OK) return mem_access_result(MEM_ACCESS_SKIPPED_ABSTRACT_ACCESS_CMDERR); - if (info->has_aampostincrement == YNM_YES) + if (use_aampostincrement) updateaddr = false; p += args.size; } diff --git a/src/target/riscv/riscv.c b/src/target/riscv/riscv.c index cd31881..aae5eb3 100644 --- a/src/target/riscv/riscv.c +++ b/src/target/riscv/riscv.c @@ -294,6 +294,10 @@ static enum riscv_halt_reason riscv_halt_reason(struct target *target); static void riscv_info_init(struct target *target, struct riscv_info *r); static int riscv_step_rtos_hart(struct target *target); +static const riscv_reg_t mstatus_ie_mask = MSTATUS_MIE | MSTATUS_HIE | MSTATUS_SIE | MSTATUS_UIE; +static int riscv_interrupts_disable(struct target *target, riscv_reg_t *old_mstatus); +static int riscv_interrupts_restore(struct target *target, riscv_reg_t old_mstatus); + static void riscv_sample_buf_maybe_add_timestamp(struct target *target, bool before) { RISCV_INFO(r); @@ -2433,8 +2437,8 @@ static int riscv_hit_watchpoint(struct target *target, struct watchpoint **hit_w return ERROR_FAIL; } -static int oldriscv_step(struct target *target, int current, uint32_t address, - int handle_breakpoints) +static int oldriscv_step(struct target *target, bool current, uint32_t address, + bool handle_breakpoints) { struct target_type *tt = get_target_type(target); if (!tt) @@ -2442,14 +2446,15 @@ static int oldriscv_step(struct target *target, int current, uint32_t address, return tt->step(target, current, address, handle_breakpoints); } -static int riscv_openocd_step_impl(struct target *target, int current, - target_addr_t address, int handle_breakpoints, int handle_callbacks); +static int riscv_openocd_step_impl(struct target *target, bool current, + target_addr_t address, bool handle_breakpoints, int handle_callbacks); -static int old_or_new_riscv_step_impl(struct target *target, int current, - target_addr_t address, int handle_breakpoints, int handle_callbacks) +static int old_or_new_riscv_step_impl(struct target *target, bool current, + target_addr_t address, bool handle_breakpoints, int handle_callbacks) { RISCV_INFO(r); - LOG_TARGET_DEBUG(target, "handle_breakpoints=%d", handle_breakpoints); + LOG_TARGET_DEBUG(target, "handle_breakpoints=%s", + handle_breakpoints ? "true" : "false"); if (!r->get_hart_state) return oldriscv_step(target, current, address, handle_breakpoints); else @@ -2457,8 +2462,8 @@ static int old_or_new_riscv_step_impl(struct target *target, int current, handle_callbacks); } -static int old_or_new_riscv_step(struct target *target, int current, - target_addr_t address, int handle_breakpoints) +static int old_or_new_riscv_step(struct target *target, bool current, + target_addr_t address, bool handle_breakpoints) { return old_or_new_riscv_step_impl(target, current, address, handle_breakpoints, true /* handle callbacks*/); @@ -2822,8 +2827,8 @@ static int enable_watchpoints(struct target *target, bool *wp_is_set) /** * Get everything ready to resume. */ -static int resume_prep(struct target *target, int current, - target_addr_t address, int handle_breakpoints, int debug_execution) +static int resume_prep(struct target *target, bool current, + target_addr_t address, bool handle_breakpoints, bool debug_execution) { assert(target->state == TARGET_HALTED); RISCV_INFO(r); @@ -2864,8 +2869,8 @@ static int resume_prep(struct target *target, int current, * Resume all the harts that have been prepped, as close to instantaneous as * possible. */ -static int resume_go(struct target *target, int current, - target_addr_t address, int handle_breakpoints, int debug_execution) +static int resume_go(struct target *target, bool current, + target_addr_t address, bool handle_breakpoints, bool debug_execution) { assert(target->state == TARGET_HALTED); RISCV_INFO(r); @@ -2883,7 +2888,7 @@ static int resume_go(struct target *target, int current, return result; } -static int resume_finish(struct target *target, int debug_execution) +static int resume_finish(struct target *target, bool debug_execution) { assert(target->state == TARGET_HALTED); if (riscv_reg_cache_any_dirty(target, LOG_LVL_ERROR)) { @@ -2908,10 +2913,10 @@ static int resume_finish(struct target *target, int debug_execution) */ static int riscv_resume( struct target *target, - int current, + bool current, target_addr_t address, - int handle_breakpoints, - int debug_execution, + bool handle_breakpoints, + bool debug_execution, bool single_hart) { int result = ERROR_OK; @@ -2972,8 +2977,8 @@ static int riscv_resume( return result; } -static int riscv_target_resume(struct target *target, int current, - target_addr_t address, int handle_breakpoints, int debug_execution) +static int riscv_target_resume(struct target *target, bool current, + target_addr_t address, bool handle_breakpoints, bool debug_execution) { if (target->state != TARGET_HALTED) { LOG_TARGET_ERROR(target, "Not halted."); @@ -3648,14 +3653,13 @@ static int riscv_run_algorithm(struct target *target, int num_mem_params, } /* Disable Interrupts before attempting to run the algorithm. */ - uint64_t current_mstatus; - uint64_t irq_disabled_mask = MSTATUS_MIE | MSTATUS_HIE | MSTATUS_SIE | MSTATUS_UIE; - if (riscv_interrupts_disable(target, irq_disabled_mask, ¤t_mstatus) != ERROR_OK) + riscv_reg_t current_mstatus; + if (riscv_interrupts_disable(target, ¤t_mstatus) != ERROR_OK) return ERROR_FAIL; /* Run algorithm */ - LOG_TARGET_DEBUG(target, "Resume at 0x%" TARGET_PRIxADDR, entry_point); - if (riscv_resume(target, 0, entry_point, 0, 1, true) != ERROR_OK) + LOG_TARGET_DEBUG(target, "resume at 0x%" TARGET_PRIxADDR, entry_point); + if (riscv_resume(target, false, entry_point, false, true, true) != ERROR_OK) return ERROR_FAIL; int64_t start = timeval_ms(); @@ -4196,8 +4200,8 @@ int riscv_openocd_poll(struct target *target) return ERROR_OK; } -static int riscv_openocd_step_impl(struct target *target, int current, - target_addr_t address, int handle_breakpoints, int handle_callbacks) +static int riscv_openocd_step_impl(struct target *target, bool current, + target_addr_t address, bool handle_breakpoints, int handle_callbacks) { LOG_TARGET_DEBUG(target, "stepping hart"); @@ -4230,14 +4234,12 @@ static int riscv_openocd_step_impl(struct target *target, int current, } bool success = true; - uint64_t current_mstatus; + riscv_reg_t current_mstatus; RISCV_INFO(info); if (info->isrmask_mode == RISCV_ISRMASK_STEPONLY) { /* Disable Interrupts before stepping. */ - uint64_t irq_disabled_mask = MSTATUS_MIE | MSTATUS_HIE | MSTATUS_SIE | MSTATUS_UIE; - if (riscv_interrupts_disable(target, irq_disabled_mask, - ¤t_mstatus) != ERROR_OK) { + if (riscv_interrupts_disable(target, ¤t_mstatus) != ERROR_OK) { success = false; LOG_TARGET_ERROR(target, "Unable to disable interrupts."); goto _exit; @@ -4291,8 +4293,8 @@ _exit: return success ? ERROR_OK : ERROR_FAIL; } -int riscv_openocd_step(struct target *target, int current, - target_addr_t address, int handle_breakpoints) +int riscv_openocd_step(struct target *target, bool current, + target_addr_t address, bool handle_breakpoints) { return riscv_openocd_step_impl(target, current, address, handle_breakpoints, true /* handle_callbacks */); @@ -6004,50 +6006,35 @@ static int riscv_resume_go_all_harts(struct target *target) return ERROR_OK; } -int riscv_interrupts_disable(struct target *target, uint64_t irq_mask, uint64_t *old_mstatus) +static int riscv_interrupts_disable(struct target *target, riscv_reg_t *old_mstatus) { LOG_TARGET_DEBUG(target, "Disabling interrupts."); - struct reg *reg_mstatus = register_get_by_name(target->reg_cache, - "mstatus", true); - if (!reg_mstatus) { - LOG_TARGET_ERROR(target, "Couldn't find mstatus!"); - return ERROR_FAIL; + riscv_reg_t current_mstatus; + int ret = riscv_reg_get(target, ¤t_mstatus, GDB_REGNO_MSTATUS); + if (ret != ERROR_OK) { + LOG_TARGET_ERROR(target, "Failed to read mstatus!"); + return ret; } - - int retval = reg_mstatus->type->get(reg_mstatus); - if (retval != ERROR_OK) - return retval; - - RISCV_INFO(info); - uint8_t mstatus_bytes[8] = { 0 }; - uint64_t current_mstatus = buf_get_u64(reg_mstatus->value, 0, reg_mstatus->size); - buf_set_u64(mstatus_bytes, 0, info->xlen, set_field(current_mstatus, - irq_mask, 0)); - - retval = reg_mstatus->type->set(reg_mstatus, mstatus_bytes); - if (retval != ERROR_OK) - return retval; - if (old_mstatus) *old_mstatus = current_mstatus; - - return ERROR_OK; + return riscv_reg_set(target, GDB_REGNO_MSTATUS, current_mstatus & ~mstatus_ie_mask); } -int riscv_interrupts_restore(struct target *target, uint64_t old_mstatus) +static int riscv_interrupts_restore(struct target *target, riscv_reg_t old_mstatus) { LOG_TARGET_DEBUG(target, "Restoring interrupts."); - struct reg *reg_mstatus = register_get_by_name(target->reg_cache, - "mstatus", true); - if (!reg_mstatus) { - LOG_TARGET_ERROR(target, "Couldn't find mstatus!"); - return ERROR_FAIL; + riscv_reg_t current_mstatus; + int ret = riscv_reg_get(target, ¤t_mstatus, GDB_REGNO_MSTATUS); + if (ret != ERROR_OK) { + LOG_TARGET_ERROR(target, "Failed to read mstatus!"); + return ret; } - - RISCV_INFO(info); - uint8_t mstatus_bytes[8]; - buf_set_u64(mstatus_bytes, 0, info->xlen, old_mstatus); - return reg_mstatus->type->set(reg_mstatus, mstatus_bytes); + if ((current_mstatus & mstatus_ie_mask) != 0) { + LOG_TARGET_WARNING(target, "Interrupt enable bits in mstatus changed during single-step."); + LOG_TARGET_WARNING(target, "OpenOCD might have affected the program when it restored the interrupt bits after single-step."); + LOG_TARGET_WARNING(target, "Hint: Use 'riscv set_maskisr off' to prevent OpenOCD from touching mstatus during single-step."); + } + return riscv_reg_set(target, GDB_REGNO_MSTATUS, current_mstatus | (old_mstatus & mstatus_ie_mask)); } static int riscv_step_rtos_hart(struct target *target) diff --git a/src/target/riscv/riscv.h b/src/target/riscv/riscv.h index 031abe5..082445e 100644 --- a/src/target/riscv/riscv.h +++ b/src/target/riscv/riscv.h @@ -450,9 +450,9 @@ int riscv_halt(struct target *target); int riscv_openocd_step( struct target *target, - int current, + bool current, target_addr_t address, - int handle_breakpoints + bool handle_breakpoints ); /*** RISC-V Interface ***/ @@ -503,7 +503,4 @@ void riscv_add_bscan_tunneled_scan(struct jtag_tap *tap, const struct scan_field int riscv_read_by_any_size(struct target *target, target_addr_t address, uint32_t size, uint8_t *buffer); int riscv_write_by_any_size(struct target *target, target_addr_t address, uint32_t size, uint8_t *buffer); -int riscv_interrupts_disable(struct target *target, uint64_t ie_mask, uint64_t *old_mstatus); -int riscv_interrupts_restore(struct target *target, uint64_t old_mstatus); - #endif /* OPENOCD_TARGET_RISCV_RISCV_H */ diff --git a/src/target/riscv/riscv_reg.c b/src/target/riscv/riscv_reg.c index 1a0d402..e35cd7f 100644 --- a/src/target/riscv/riscv_reg.c +++ b/src/target/riscv/riscv_reg.c @@ -56,7 +56,6 @@ static const char * const default_reg_names[GDB_REGNO_COUNT] = { [GDB_REGNO_T5] = "t5", [GDB_REGNO_T6] = "t6", [GDB_REGNO_PC] = "pc", - [GDB_REGNO_CSR0] = "csr0", [GDB_REGNO_PRIV] = "priv", [GDB_REGNO_FT0] = "ft0", [GDB_REGNO_FT1] = "ft1", @@ -196,7 +195,8 @@ const char *riscv_reg_gdb_regno_name(const struct target *target, enum gdb_regno } if (regno >= GDB_REGNO_CSR0 && regno <= GDB_REGNO_CSR4095) { init_custom_csr_names(target); - info->reg_names[regno] = init_reg_name_with_prefix("csr", regno - GDB_REGNO_CSR0); + if (!info->reg_names[regno]) + info->reg_names[regno] = init_reg_name_with_prefix("csr", regno - GDB_REGNO_CSR0); return info->reg_names[regno]; } assert(!"Encountered uninitialized entry in reg_names table"); diff --git a/src/target/stm8.c b/src/target/stm8.c index fb5c81f..76482e8 100644 --- a/src/target/stm8.c +++ b/src/target/stm8.c @@ -980,9 +980,9 @@ static int stm8_single_step_core(struct target *target) return ERROR_OK; } -static int stm8_resume(struct target *target, int current, - target_addr_t address, int handle_breakpoints, - int debug_execution) +static int stm8_resume(struct target *target, bool current, + target_addr_t address, bool handle_breakpoints, + bool debug_execution) { struct stm8_common *stm8 = target_to_stm8(target); struct breakpoint *breakpoint = NULL; @@ -1004,7 +1004,7 @@ static int stm8_resume(struct target *target, int current, stm8_set_hwbreak(target, comparator_list); } - /* current = 1: continue on current pc, + /* current = true: continue on current pc, otherwise continue at <address> */ if (!current) { buf_set_u32(stm8->core_cache->reg_list[STM8_PC].value, @@ -1290,8 +1290,8 @@ static int stm8_arch_state(struct target *target) return ERROR_OK; } -static int stm8_step(struct target *target, int current, - target_addr_t address, int handle_breakpoints) +static int stm8_step(struct target *target, bool current, + target_addr_t address, bool handle_breakpoints) { LOG_DEBUG("%x " TARGET_ADDR_FMT " %x", current, address, handle_breakpoints); @@ -1305,7 +1305,7 @@ static int stm8_step(struct target *target, int current, return ERROR_TARGET_NOT_HALTED; } - /* current = 1: continue on current pc, otherwise continue at <address> */ + /* current = true: continue on current pc, otherwise continue at <address> */ if (!current) { buf_set_u32(stm8->core_cache->reg_list[STM8_PC].value, 0, 32, address); stm8->core_cache->reg_list[STM8_PC].dirty = true; @@ -1789,7 +1789,7 @@ static int stm8_run_and_wait(struct target *target, uint32_t entry_point, /* This code relies on the target specific resume() and poll()->debug_entry() sequence to write register values to the processor and the read them back */ - retval = target_resume(target, 0, entry_point, 0, 1); + retval = target_resume(target, false, entry_point, false, true); if (retval != ERROR_OK) return retval; diff --git a/src/target/target.c b/src/target/target.c index 56eff92..442e8be 100644 --- a/src/target/target.c +++ b/src/target/target.c @@ -31,6 +31,7 @@ #endif #include <helper/align.h> +#include <helper/list.h> #include <helper/nvp.h> #include <helper/time_support.h> #include <jtag/jtag.h> @@ -52,6 +53,13 @@ /* default halt wait timeout (ms) */ #define DEFAULT_HALT_TIMEOUT 5000 +struct target_event_action { + enum target_event event; + Jim_Interp *interp; + Jim_Obj *body; + struct list_head list; +}; + static int target_read_buffer_default(struct target *target, target_addr_t address, uint32_t count, uint8_t *buffer); static int target_write_buffer_default(struct target *target, target_addr_t address, @@ -554,8 +562,8 @@ int target_halt(struct target *target) * hand the infrastructure for running such helpers might use this * procedure but rely on hardware breakpoint to detect termination.) */ -int target_resume(struct target *target, int current, target_addr_t address, - int handle_breakpoints, int debug_execution) +int target_resume(struct target *target, bool current, target_addr_t address, + bool handle_breakpoints, bool debug_execution) { int retval; @@ -580,7 +588,8 @@ int target_resume(struct target *target, int current, target_addr_t address, * in the correct order. */ bool save_poll_mask = jtag_poll_mask(); - retval = target->type->resume(target, current, address, handle_breakpoints, debug_execution); + retval = target->type->resume(target, current, address, handle_breakpoints, + debug_execution); jtag_poll_unmask(save_poll_mask); if (retval != ERROR_OK) @@ -1414,7 +1423,7 @@ bool target_supports_gdb_connection(const struct target *target) } int target_step(struct target *target, - int current, target_addr_t address, int handle_breakpoints) + bool current, target_addr_t address, bool handle_breakpoints) { int retval; @@ -2199,12 +2208,11 @@ static void target_destroy(struct target *target) jtag_unregister_event_callback(jtag_enable_callback, target); - struct target_event_action *teap = target->event_action; - while (teap) { - struct target_event_action *next = teap->next; + struct target_event_action *teap, *temp; + list_for_each_entry_safe(teap, temp, &target->events_action, list) { + list_del(&teap->list); Jim_DecrRefCount(teap->interp, teap->body); free(teap); - teap = next; } target_free_all_working_areas(target); @@ -2315,7 +2323,7 @@ int target_profiling_default(struct target *target, uint32_t *samples, uint32_t t = buf_get_u32(reg->value, 0, 32); samples[sample_count++] = t; /* current pc, addr = 0, do not handle breakpoints, not debugging */ - retval = target_resume(target, 1, 0, 0, 0); + retval = target_resume(target, true, 0, false, false); target_poll(target); alive_sleep(10); /* sleep 10ms, i.e. <100 samples/second. */ } else if (target->state == TARGET_RUNNING) { @@ -3297,7 +3305,7 @@ COMMAND_HANDLER(handle_reset_command) COMMAND_HANDLER(handle_resume_command) { - int current = 1; + bool current = true; if (CMD_ARGC > 1) return ERROR_COMMAND_SYNTAX_ERROR; @@ -3309,10 +3317,10 @@ COMMAND_HANDLER(handle_resume_command) target_addr_t addr = 0; if (CMD_ARGC == 1) { COMMAND_PARSE_ADDRESS(CMD_ARGV[0], addr); - current = 0; + current = false; } - return target_resume(target, current, addr, 1, 0); + return target_resume(target, current, addr, true, false); } COMMAND_HANDLER(handle_step_command) @@ -3334,7 +3342,7 @@ COMMAND_HANDLER(handle_step_command) struct target *target = get_current_target(CMD_CTX); - return target_step(target, current_pc, addr, 1); + return target_step(target, current_pc, addr, true); } void target_handle_md_output(struct command_invocation *cmd, @@ -4363,7 +4371,7 @@ COMMAND_HANDLER(handle_profile_command) } else if (target->state == TARGET_HALTED && !halted_before_profiling) { /* The target was running before we started and is halted now. Resume * it, for consistency. */ - retval = target_resume(target, 1, 0, 0, 0); + retval = target_resume(target, true, 0, false, false); if (retval != ERROR_OK) { free(samples); return retval; @@ -4430,15 +4438,17 @@ COMMAND_HANDLER(handle_target_read_memory) return ERROR_COMMAND_ARGUMENT_INVALID; } - const unsigned int width = width_bits / 8; - - if ((addr + (count * width)) < addr) { - command_print(CMD, "read_memory: addr + count wraps to zero"); + if (count > 65536) { + command_print(CMD, "too large read request, exceeds 64K elements"); return ERROR_COMMAND_ARGUMENT_INVALID; } - if (count > 65536) { - command_print(CMD, "read_memory: too large read request, exceeds 64K elements"); + const unsigned int width = width_bits / 8; + /* -1 is needed to handle cases when (addr + count * width) results in zero + * due to overflow. + */ + if ((addr + count * width - 1) < addr) { + command_print(CMD, "memory region wraps over address zero"); return ERROR_COMMAND_ARGUMENT_INVALID; } @@ -4465,13 +4475,13 @@ COMMAND_HANDLER(handle_target_read_memory) retval = target_read_memory(target, addr, width, chunk_len, buffer); if (retval != ERROR_OK) { - LOG_DEBUG("read_memory: read at " TARGET_ADDR_FMT " with width=%u and count=%zu failed", + LOG_DEBUG("read at " TARGET_ADDR_FMT " with width=%u and count=%zu failed", addr, width_bits, chunk_len); /* * FIXME: we append the errmsg to the list of value already read. * Add a way to flush and replace old output, but LOG_DEBUG() it */ - command_print(CMD, "read_memory: failed to read memory"); + command_print(CMD, "failed to read memory"); free(buffer); return retval; } @@ -4507,50 +4517,36 @@ COMMAND_HANDLER(handle_target_read_memory) return ERROR_OK; } -static int target_jim_write_memory(Jim_Interp *interp, int argc, - Jim_Obj * const *argv) +COMMAND_HANDLER(handle_target_write_memory) { /* - * argv[1] = memory address - * argv[2] = desired element width in bits - * argv[3] = list of data to write - * argv[4] = optional "phys" + * CMD_ARGV[0] = memory address + * CMD_ARGV[1] = desired element width in bits + * CMD_ARGV[2] = list of data to write + * CMD_ARGV[3] = optional "phys" */ - if (argc < 4 || argc > 5) { - Jim_WrongNumArgs(interp, 1, argv, "address width data ['phys']"); - return JIM_ERR; - } + if (CMD_ARGC < 3 || CMD_ARGC > 4) + return ERROR_COMMAND_SYNTAX_ERROR; /* Arg 1: Memory address. */ - int e; - jim_wide wide_addr; - e = Jim_GetWide(interp, argv[1], &wide_addr); - - if (e != JIM_OK) - return e; - - target_addr_t addr = (target_addr_t)wide_addr; + target_addr_t addr; + COMMAND_PARSE_NUMBER(u64, CMD_ARGV[0], addr); /* Arg 2: Bit width of one element. */ - long l; - e = Jim_GetLong(interp, argv[2], &l); - - if (e != JIM_OK) - return e; + unsigned int width_bits; + COMMAND_PARSE_NUMBER(uint, CMD_ARGV[1], width_bits); - const unsigned int width_bits = l; - size_t count = Jim_ListLength(interp, argv[3]); + /* Arg 3: Elements to write. */ + size_t count = Jim_ListLength(CMD_CTX->interp, CMD_JIMTCL_ARGV[2]); /* Arg 4: Optional 'phys'. */ bool is_phys = false; - if (argc > 4) { - const char *phys = Jim_GetString(argv[4], NULL); - - if (strcmp(phys, "phys")) { - Jim_SetResultFormatted(interp, "invalid argument '%s', must be 'phys'", phys); - return JIM_ERR; + if (CMD_ARGC == 4) { + if (strcmp(CMD_ARGV[3], "phys")) { + command_print(CMD, "invalid argument '%s', must be 'phys'", CMD_ARGV[3]); + return ERROR_COMMAND_ARGUMENT_INVALID; } is_phys = true; @@ -4563,32 +4559,32 @@ static int target_jim_write_memory(Jim_Interp *interp, int argc, case 64: break; default: - Jim_SetResultString(interp, "invalid width, must be 8, 16, 32 or 64", -1); - return JIM_ERR; + command_print(CMD, "invalid width, must be 8, 16, 32 or 64"); + return ERROR_COMMAND_ARGUMENT_INVALID; } - const unsigned int width = width_bits / 8; - - if ((addr + (count * width)) < addr) { - Jim_SetResultString(interp, "write_memory: addr + len wraps to zero", -1); - return JIM_ERR; + if (count > 65536) { + command_print(CMD, "too large memory write request, exceeds 64K elements"); + return ERROR_COMMAND_ARGUMENT_INVALID; } - if (count > 65536) { - Jim_SetResultString(interp, "write_memory: too large memory write request, exceeds 64K elements", -1); - return JIM_ERR; + const unsigned int width = width_bits / 8; + /* -1 is needed to handle cases when (addr + count * width) results in zero + * due to overflow. + */ + if ((addr + count * width - 1) < addr) { + command_print(CMD, "memory region wraps over address zero"); + return ERROR_COMMAND_ARGUMENT_INVALID; } - struct command_context *cmd_ctx = current_command_context(interp); - assert(cmd_ctx); - struct target *target = get_current_target(cmd_ctx); + struct target *target = get_current_target(CMD_CTX); const size_t buffersize = 4096; uint8_t *buffer = malloc(buffersize); if (!buffer) { LOG_ERROR("Failed to allocate memory"); - return JIM_ERR; + return ERROR_FAIL; } size_t j = 0; @@ -4598,9 +4594,14 @@ static int target_jim_write_memory(Jim_Interp *interp, int argc, const size_t chunk_len = MIN(count, max_chunk_len); for (size_t i = 0; i < chunk_len; i++, j++) { - Jim_Obj *tmp = Jim_ListGetIndex(interp, argv[3], j); + Jim_Obj *tmp = Jim_ListGetIndex(CMD_CTX->interp, CMD_JIMTCL_ARGV[2], j); jim_wide element_wide; - Jim_GetWide(interp, tmp, &element_wide); + int jimretval = Jim_GetWide(CMD_CTX->interp, tmp, &element_wide); + if (jimretval != JIM_OK) { + command_print(CMD, "invalid value \"%s\"", Jim_GetString(tmp, NULL)); + free(buffer); + return ERROR_COMMAND_ARGUMENT_INVALID; + } const uint64_t v = element_wide; @@ -4630,11 +4631,11 @@ static int target_jim_write_memory(Jim_Interp *interp, int argc, retval = target_write_memory(target, addr, width, chunk_len, buffer); if (retval != ERROR_OK) { - LOG_ERROR("write_memory: write at " TARGET_ADDR_FMT " with width=%u and count=%zu failed", + LOG_DEBUG("write at " TARGET_ADDR_FMT " with width=%u and count=%zu failed", addr, width_bits, chunk_len); - Jim_SetResultString(interp, "write_memory: failed to write memory", -1); - e = JIM_ERR; - break; + command_print(CMD, "failed to write memory"); + free(buffer); + return retval; } addr += chunk_len * width; @@ -4642,7 +4643,7 @@ static int target_jim_write_memory(Jim_Interp *interp, int argc, free(buffer); - return e; + return ERROR_OK; } /* FIX? should we propagate errors here rather than printing them @@ -4653,7 +4654,7 @@ void target_handle_event(struct target *target, enum target_event e) struct target_event_action *teap; int retval; - for (teap = target->event_action; teap; teap = teap->next) { + list_for_each_entry(teap, &target->events_action, list) { if (teap->event == e) { LOG_DEBUG("target: %s (%s) event: %d (%s) action: %s", target_name(target), @@ -4692,63 +4693,46 @@ void target_handle_event(struct target *target, enum target_event e) } } -static int target_jim_get_reg(Jim_Interp *interp, int argc, - Jim_Obj * const *argv) +COMMAND_HANDLER(handle_target_get_reg) { - bool force = false; + if (CMD_ARGC < 1 || CMD_ARGC > 2) + return ERROR_COMMAND_SYNTAX_ERROR; - if (argc == 3) { - const char *option = Jim_GetString(argv[1], NULL); + bool force = false; + Jim_Obj *next_argv = CMD_JIMTCL_ARGV[0]; - if (!strcmp(option, "-force")) { - argc--; - argv++; - force = true; - } else { - Jim_SetResultFormatted(interp, "invalid option '%s'", option); - return JIM_ERR; + if (CMD_ARGC == 2) { + if (strcmp(CMD_ARGV[0], "-force")) { + command_print(CMD, "invalid argument '%s', must be '-force'", CMD_ARGV[0]); + return ERROR_COMMAND_ARGUMENT_INVALID; } - } - if (argc != 2) { - Jim_WrongNumArgs(interp, 1, argv, "[-force] list"); - return JIM_ERR; + force = true; + next_argv = CMD_JIMTCL_ARGV[1]; } - const int length = Jim_ListLength(interp, argv[1]); - - Jim_Obj *result_dict = Jim_NewDictObj(interp, NULL, 0); + const int length = Jim_ListLength(CMD_CTX->interp, next_argv); - if (!result_dict) - return JIM_ERR; - - 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); for (int i = 0; i < length; i++) { - Jim_Obj *elem = Jim_ListGetIndex(interp, argv[1], i); - - if (!elem) - return JIM_ERR; + Jim_Obj *elem = Jim_ListGetIndex(CMD_CTX->interp, next_argv, i); const char *reg_name = Jim_String(elem); - 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_COMMAND_ARGUMENT_INVALID; } if (force || !reg->valid) { int retval = reg->type->get(reg); if (retval != ERROR_OK) { - Jim_SetResultFormatted(interp, "failed to read register '%s'", - reg_name); - return JIM_ERR; + command_print(CMD, "failed to read register '%s'", reg_name); + return retval; } } @@ -4756,27 +4740,15 @@ static int target_jim_get_reg(Jim_Interp *interp, int argc, if (!reg_value) { LOG_ERROR("Failed to allocate memory"); - return JIM_ERR; + return ERROR_FAIL; } - char *tmp = alloc_printf("0x%s", reg_value); + command_print(CMD, "%s 0x%s", reg_name, reg_value); free(reg_value); - - if (!tmp) { - LOG_ERROR("Failed to allocate memory"); - return JIM_ERR; - } - - Jim_DictAddElement(interp, result_dict, elem, - Jim_NewStringObj(interp, tmp, -1)); - - free(tmp); } - Jim_SetResult(interp, result_dict); - - return JIM_OK; + return ERROR_OK; } COMMAND_HANDLER(handle_set_reg_command) @@ -4845,7 +4817,7 @@ bool target_has_event_action(const struct target *target, enum target_event even { struct target_event_action *teap; - for (teap = target->event_action; teap; teap = teap->next) { + list_for_each_entry(teap, &target->events_action, list) { if (teap->event == event) return true; } @@ -4965,13 +4937,14 @@ no_params: { struct target_event_action *teap; - teap = target->event_action; /* replace existing? */ - while (teap) { + list_for_each_entry(teap, &target->events_action, list) if (teap->event == (enum target_event)n->value) break; - teap = teap->next; - } + + /* not found! */ + if (&teap->list == &target->events_action) + teap = NULL; if (goi->is_configure) { /* START_DEPRECATED_TPIU */ @@ -4979,6 +4952,17 @@ no_params: LOG_INFO("DEPRECATED target event %s; use TPIU events {pre,post}-{enable,disable}", n->name); /* END_DEPRECATED_TPIU */ + jim_getopt_obj(goi, &o); + if (Jim_Length(o) == 0) { + /* empty action, drop existing one */ + if (teap) { + list_del(&teap->list); + Jim_DecrRefCount(teap->interp, teap->body); + free(teap); + } + break; + } + bool replace = true; if (!teap) { /* create new */ @@ -4987,7 +4971,6 @@ no_params: } teap->event = n->value; teap->interp = goi->interp; - jim_getopt_obj(goi, &o); if (teap->body) Jim_DecrRefCount(teap->interp, teap->body); teap->body = Jim_DuplicateObj(goi->interp, o); @@ -5005,8 +4988,7 @@ no_params: if (!replace) { /* add to head of event list */ - teap->next = target->event_action; - target->event_action = teap; + list_add(&teap->list, &target->events_action); } Jim_SetEmptyResult(goi->interp); } else { @@ -5421,19 +5403,19 @@ COMMAND_HANDLER(handle_target_wait_state) COMMAND_HANDLER(handle_target_event_list) { struct target *target = get_current_target(CMD_CTX); - struct target_event_action *teap = target->event_action; + struct target_event_action *teap; command_print(CMD, "Event actions for target %s\n", target_name(target)); command_print(CMD, "%-25s | Body", "Event"); command_print(CMD, "------------------------- | " "----------------------------------------"); - while (teap) { + + list_for_each_entry(teap, &target->events_action, list) command_print(CMD, "%-25s | %s", target_event_name(teap->event), Jim_GetString(teap->body, NULL)); - teap = teap->next; - } + command_print(CMD, "***END***"); return ERROR_OK; } @@ -5568,9 +5550,9 @@ static const struct command_registration target_instance_command_handlers[] = { { .name = "get_reg", .mode = COMMAND_EXEC, - .jim_handler = target_jim_get_reg, + .handler = handle_target_get_reg, .help = "Get register values from the target", - .usage = "list", + .usage = "[-force] list", }, { .name = "set_reg", @@ -5589,7 +5571,7 @@ static const struct command_registration target_instance_command_handlers[] = { { .name = "write_memory", .mode = COMMAND_EXEC, - .jim_handler = target_jim_write_memory, + .handler = handle_target_write_memory, .help = "Write Tcl list of 8/16/32/64 bit numbers to target memory", .usage = "address width data ['phys']", }, @@ -5786,6 +5768,8 @@ static int target_create(struct jim_getopt_info *goi) target->halt_issued = false; + INIT_LIST_HEAD(&target->events_action); + /* initialize trace information */ target->trace_info = calloc(1, sizeof(struct trace)); if (!target->trace_info) { @@ -5806,6 +5790,16 @@ static int target_create(struct jim_getopt_info *goi) target->gdb_port_override = NULL; target->gdb_max_connections = 1; + cp = Jim_GetString(new_cmd, NULL); + target->cmd_name = strdup(cp); + if (!target->cmd_name) { + LOG_ERROR("Out of memory"); + free(target->trace_info); + free(target->type); + free(target); + return JIM_ERR; + } + /* Do the rest as "configure" options */ goi->is_configure = true; e = target_configure(goi, target); @@ -5842,19 +5836,6 @@ static int target_create(struct jim_getopt_info *goi) target->endianness = TARGET_LITTLE_ENDIAN; } - cp = Jim_GetString(new_cmd, NULL); - target->cmd_name = strdup(cp); - if (!target->cmd_name) { - LOG_ERROR("Out of memory"); - rtos_destroy(target); - free(target->gdb_port_override); - free(target->trace_info); - free(target->type); - free(target->private_config); - free(target); - return JIM_ERR; - } - if (target->type->target_create) { e = (*(target->type->target_create))(target, goi->interp); if (e != ERROR_OK) { @@ -6706,9 +6687,9 @@ static const struct command_registration target_exec_command_handlers[] = { { .name = "get_reg", .mode = COMMAND_EXEC, - .jim_handler = target_jim_get_reg, + .handler = handle_target_get_reg, .help = "Get register values from the target", - .usage = "list", + .usage = "[-force] list", }, { .name = "set_reg", @@ -6727,7 +6708,7 @@ static const struct command_registration target_exec_command_handlers[] = { { .name = "write_memory", .mode = COMMAND_EXEC, - .jim_handler = target_jim_write_memory, + .handler = handle_target_write_memory, .help = "Write Tcl list of 8/16/32/64 bit numbers to target memory", .usage = "address width data ['phys']", }, diff --git a/src/target/target.h b/src/target/target.h index 2f4c1a0..d16c3a0 100644 --- a/src/target/target.h +++ b/src/target/target.h @@ -142,7 +142,7 @@ struct target { */ bool running_alg; - struct target_event_action *event_action; + struct list_head events_action; bool reset_halt; /* attempt resetting the CPU into the halted mode? */ target_addr_t working_area; /* working area (initialised RAM). Evaluated @@ -301,13 +301,6 @@ enum target_event { TARGET_EVENT_SEMIHOSTING_USER_CMD_0X107 = 0x107, }; -struct target_event_action { - enum target_event event; - Jim_Interp *interp; - Jim_Obj *body; - struct target_event_action *next; -}; - bool target_has_event_action(const struct target *target, enum target_event event); struct target_event_callback { @@ -392,8 +385,8 @@ int target_unregister_trace_callback( * yet it is possible to detect error conditions. */ int target_poll(struct target *target); -int target_resume(struct target *target, int current, target_addr_t address, - int handle_breakpoints, int debug_execution); +int target_resume(struct target *target, bool current, target_addr_t address, + bool handle_breakpoints, bool debug_execution); int target_halt(struct target *target); int target_call_event_callbacks(struct target *target, enum target_event event); int target_call_reset_callbacks(struct target *target, enum target_reset_mode reset_mode); @@ -542,7 +535,7 @@ bool target_supports_gdb_connection(const struct target *target); * This routine is a wrapper for target->type->step. */ int target_step(struct target *target, - int current, target_addr_t address, int handle_breakpoints); + bool current, target_addr_t address, bool handle_breakpoints); /** * Run an algorithm on the @a target given. * diff --git a/src/target/target_type.h b/src/target/target_type.h index f35a59c..ce98cba 100644 --- a/src/target/target_type.h +++ b/src/target/target_type.h @@ -42,10 +42,10 @@ struct target_type { /* halt will log a warning, but return ERROR_OK if the target is already halted. */ int (*halt)(struct target *target); /* See target.c target_resume() for documentation. */ - int (*resume)(struct target *target, int current, target_addr_t address, - int handle_breakpoints, int debug_execution); - int (*step)(struct target *target, int current, target_addr_t address, - int handle_breakpoints); + int (*resume)(struct target *target, bool current, target_addr_t address, + bool handle_breakpoints, bool debug_execution); + int (*step)(struct target *target, bool current, target_addr_t address, + bool handle_breakpoints); /* target reset control. assert reset can be invoked when OpenOCD and * the target is out of sync. * diff --git a/src/target/xscale.c b/src/target/xscale.c index 83afd5d..5cc790a 100644 --- a/src/target/xscale.c +++ b/src/target/xscale.c @@ -47,8 +47,8 @@ */ /* forward declarations */ -static int xscale_resume(struct target *, int current, - target_addr_t address, int handle_breakpoints, int debug_execution); +static int xscale_resume(struct target *, bool current, + target_addr_t address, bool handle_breakpoints, bool debug_execution); static int xscale_debug_entry(struct target *); static int xscale_restore_banked(struct target *); static int xscale_get_reg(struct reg *reg); @@ -997,7 +997,7 @@ static int xscale_debug_entry(struct target *target) * can only happen in fill mode. */ if (xscale->arch_debug_reason == XSCALE_DBG_REASON_TB_FULL) { if (--xscale->trace.fill_counter > 0) - xscale_resume(target, 1, 0x0, 1, 0); + xscale_resume(target, true, 0x0, true, false); } else /* entered debug for other reason; reset counter */ xscale->trace.fill_counter = 0; } @@ -1106,8 +1106,8 @@ static void xscale_free_trace_data(struct xscale_common *xscale) xscale->trace.data = NULL; } -static int xscale_resume(struct target *target, int current, - target_addr_t address, int handle_breakpoints, int debug_execution) +static int xscale_resume(struct target *target, bool current, + target_addr_t address, bool handle_breakpoints, bool debug_execution) { struct xscale_common *xscale = target_to_xscale(target); struct arm *arm = &xscale->arm; @@ -1130,7 +1130,7 @@ static int xscale_resume(struct target *target, int current, if (retval != ERROR_OK) return retval; - /* current = 1: continue on current pc, otherwise continue at <address> */ + /* current = true: continue on current pc, otherwise continue at <address> */ if (!current) buf_set_u32(arm->pc->value, 0, 32, address); @@ -1277,8 +1277,8 @@ static int xscale_resume(struct target *target, int current, return ERROR_OK; } -static int xscale_step_inner(struct target *target, int current, - uint32_t address, int handle_breakpoints) +static int xscale_step_inner(struct target *target, bool current, + uint32_t address, bool handle_breakpoints) { struct xscale_common *xscale = target_to_xscale(target); struct arm *arm = &xscale->arm; @@ -1372,8 +1372,8 @@ static int xscale_step_inner(struct target *target, int current, return ERROR_OK; } -static int xscale_step(struct target *target, int current, - target_addr_t address, int handle_breakpoints) +static int xscale_step(struct target *target, bool current, + target_addr_t address, bool handle_breakpoints) { struct arm *arm = target_to_arm(target); struct breakpoint *breakpoint = NULL; @@ -1386,7 +1386,7 @@ static int xscale_step(struct target *target, int current, return ERROR_TARGET_NOT_HALTED; } - /* current = 1: continue on current pc, otherwise continue at <address> */ + /* current = true: continue on current pc, otherwise continue at <address> */ if (!current) buf_set_u32(arm->pc->value, 0, 32, address); @@ -1598,7 +1598,7 @@ static int xscale_deassert_reset(struct target *target) target->state = TARGET_HALTED; /* resume the target */ - xscale_resume(target, 1, 0x0, 1, 0); + xscale_resume(target, true, 0x0, true, false); } } diff --git a/src/target/xtensa/xtensa.c b/src/target/xtensa/xtensa.c index 3b888fe..3a877ed 100644 --- a/src/target/xtensa/xtensa.c +++ b/src/target/xtensa/xtensa.c @@ -1591,10 +1591,10 @@ int xtensa_halt(struct target *target) } int xtensa_prepare_resume(struct target *target, - int current, + bool current, target_addr_t address, - int handle_breakpoints, - int debug_execution) + bool handle_breakpoints, + bool debug_execution) { struct xtensa *xtensa = target_to_xtensa(target); uint32_t bpena = 0; @@ -1671,13 +1671,14 @@ int xtensa_do_resume(struct target *target) } int xtensa_resume(struct target *target, - int current, + bool current, target_addr_t address, - int handle_breakpoints, - int debug_execution) + bool handle_breakpoints, + bool debug_execution) { LOG_TARGET_DEBUG(target, "start"); - int res = xtensa_prepare_resume(target, current, address, handle_breakpoints, debug_execution); + int res = xtensa_prepare_resume(target, current, address, + handle_breakpoints, debug_execution); if (res != ERROR_OK) { LOG_TARGET_ERROR(target, "Failed to prepare for resume!"); return res; @@ -1719,7 +1720,8 @@ static bool xtensa_pc_in_winexc(struct target *target, target_addr_t pc) return false; } -int xtensa_do_step(struct target *target, int current, target_addr_t address, int handle_breakpoints) +int xtensa_do_step(struct target *target, bool current, target_addr_t address, + bool handle_breakpoints) { struct xtensa *xtensa = target_to_xtensa(target); int res; @@ -1844,7 +1846,7 @@ int xtensa_do_step(struct target *target, int current, target_addr_t address, in /* Now that ICOUNT (LX) or DCR.StepRequest (NX) is set, * we can resume as if we were going to run */ - res = xtensa_prepare_resume(target, current, address, 0, 0); + res = xtensa_prepare_resume(target, current, address, false, false); if (res != ERROR_OK) { LOG_TARGET_ERROR(target, "Failed to prepare resume for single step"); return res; @@ -1941,7 +1943,8 @@ int xtensa_do_step(struct target *target, int current, target_addr_t address, in return res; } -int xtensa_step(struct target *target, int current, target_addr_t address, int handle_breakpoints) +int xtensa_step(struct target *target, bool current, target_addr_t address, + bool handle_breakpoints) { int retval = xtensa_do_step(target, current, address, handle_breakpoints); if (retval != ERROR_OK) @@ -2806,7 +2809,7 @@ int xtensa_start_algorithm(struct target *target, } } - return xtensa_resume(target, 0, entry_point, 1, 1); + return xtensa_resume(target, false, entry_point, true, true); } /** Waits for an algorithm in the target. */ diff --git a/src/target/xtensa/xtensa.h b/src/target/xtensa/xtensa.h index 4192776..a920f77 100644 --- a/src/target/xtensa/xtensa.h +++ b/src/target/xtensa/xtensa.h @@ -378,18 +378,20 @@ int xtensa_poll(struct target *target); void xtensa_on_poll(struct target *target); int xtensa_halt(struct target *target); int xtensa_resume(struct target *target, - int current, + bool current, target_addr_t address, - int handle_breakpoints, - int debug_execution); + bool handle_breakpoints, + bool debug_execution); int xtensa_prepare_resume(struct target *target, - int current, + bool current, target_addr_t address, - int handle_breakpoints, - int debug_execution); + bool handle_breakpoints, + bool debug_execution); int xtensa_do_resume(struct target *target); -int xtensa_step(struct target *target, int current, target_addr_t address, int handle_breakpoints); -int xtensa_do_step(struct target *target, int current, target_addr_t address, int handle_breakpoints); +int xtensa_step(struct target *target, bool current, target_addr_t address, + bool handle_breakpoints); +int xtensa_do_step(struct target *target, bool current, target_addr_t address, + bool handle_breakpoints); int xtensa_mmu_is_enabled(struct target *target, int *enabled); int xtensa_read_memory(struct target *target, target_addr_t address, uint32_t size, uint32_t count, uint8_t *buffer); int xtensa_read_buffer(struct target *target, target_addr_t address, uint32_t count, uint8_t *buffer); diff --git a/src/transport/transport.c b/src/transport/transport.c index c7293e7..0af1360 100644 --- a/src/transport/transport.c +++ b/src/transport/transport.c @@ -166,54 +166,6 @@ struct transport *get_current_transport(void) * Infrastructure for Tcl interface to transports. */ -/** - * Makes and stores a copy of a set of transports passed as - * parameters to a command. - * - * @param vector where the resulting copy is stored, as an argv-style - * NULL-terminated vector. - */ -COMMAND_HELPER(transport_list_parse, char ***vector) -{ - char **argv; - unsigned int n = CMD_ARGC; - unsigned int j = 0; - - *vector = NULL; - - if (n < 1) - return ERROR_COMMAND_SYNTAX_ERROR; - - /* our return vector must be NULL terminated */ - argv = calloc(n + 1, sizeof(char *)); - if (!argv) - return ERROR_FAIL; - - for (unsigned int i = 0; i < n; i++) { - struct transport *t; - - for (t = transport_list; t; t = t->next) { - if (strcmp(t->name, CMD_ARGV[i]) != 0) - continue; - argv[j++] = strdup(CMD_ARGV[i]); - break; - } - if (!t) { - LOG_ERROR("no such transport '%s'", CMD_ARGV[i]); - goto fail; - } - } - - *vector = argv; - return ERROR_OK; - -fail: - for (unsigned int i = 0; i < n; i++) - free(argv[i]); - free(argv); - return ERROR_FAIL; -} - COMMAND_HANDLER(handle_transport_init) { LOG_DEBUG("%s", __func__); diff --git a/src/transport/transport.h b/src/transport/transport.h index 00d8b07..2e3dcc6 100644 --- a/src/transport/transport.h +++ b/src/transport/transport.h @@ -77,8 +77,6 @@ struct transport *get_current_transport(void); int transport_register_commands(struct command_context *ctx); -COMMAND_HELPER(transport_list_parse, char ***vector); - int allow_transports(struct command_context *ctx, const char * const *vector); bool transport_is_jtag(void); |