diff options
Diffstat (limited to 'src')
309 files changed, 11483 insertions, 5884 deletions
diff --git a/src/Makefile.am b/src/Makefile.am index 6d79cd6..4dbe93f 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -17,8 +17,12 @@ bin_PROGRAMS += %D%/openocd if INTERNAL_JIMTCL %C%_openocd_LDADD += $(top_builddir)/jimtcl/libjim.a else +if HAVE_JIMTCL_PKG_CONFIG +%C%_openocd_LDADD += $(JIMTCL_LIBS) +else %C%_openocd_LDADD += -ljim endif +endif %C%_libopenocd_la_CPPFLAGS = @@ -30,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/common.c b/src/flash/common.c index ebd9396..9f40a3a 100644 --- a/src/flash/common.c +++ b/src/flash/common.c @@ -11,14 +11,14 @@ #include "common.h" #include <helper/log.h> -unsigned get_flash_name_index(const char *name) +unsigned int get_flash_name_index(const char *name) { const char *name_index = strrchr(name, '.'); if (!name_index) return 0; if (name_index[1] < '0' || name_index[1] > '9') return ~0U; - unsigned requested; + unsigned int requested; int retval = parse_uint(name_index + 1, &requested); /* detect parsing error by forcing past end of bank list */ return (retval == ERROR_OK) ? requested : ~0U; @@ -26,7 +26,7 @@ unsigned get_flash_name_index(const char *name) bool flash_driver_name_matches(const char *name, const char *expected) { - unsigned blen = strlen(name); + unsigned int blen = strlen(name); /* only match up to the length of the driver name... */ if (strncmp(name, expected, blen) != 0) return false; diff --git a/src/flash/common.h b/src/flash/common.h index 15aea5b..6ceaa8d 100644 --- a/src/flash/common.h +++ b/src/flash/common.h @@ -17,7 +17,7 @@ * name provides a suffix but it does not parse as an unsigned integer, * the routine returns ~0U. This will prevent further matching. */ -unsigned get_flash_name_index(const char *name); +unsigned int get_flash_name_index(const char *name); /** * Attempt to match the @c expected name with the @c name of a driver. * @param name The name of the driver (from the bank's device structure). diff --git a/src/flash/nand/arm_io.c b/src/flash/nand/arm_io.c index 80bd0cf..dd012e1 100644 --- a/src/flash/nand/arm_io.c +++ b/src/flash/nand/arm_io.c @@ -31,12 +31,12 @@ * @return Success or failure of the operation */ static int arm_code_to_working_area(struct target *target, - const uint32_t *code, unsigned code_size, - unsigned additional, struct working_area **area) + const uint32_t *code, unsigned int code_size, + unsigned int additional, struct working_area **area) { uint8_t code_buf[code_size]; int retval; - unsigned size = code_size + additional; + unsigned int size = code_size + additional; /* REVISIT this assumes size doesn't ever change. * That's usually correct; but there are boards with diff --git a/src/flash/nand/arm_io.h b/src/flash/nand/arm_io.h index 10f0e66..760dc7e 100644 --- a/src/flash/nand/arm_io.h +++ b/src/flash/nand/arm_io.h @@ -27,7 +27,7 @@ struct arm_nand_data { struct working_area *copy_area; /** The chunk size is the page size or ECC chunk. */ - unsigned chunk_size; + unsigned int chunk_size; /** Where data is read from or written to. */ uint32_t data; diff --git a/src/flash/nand/at91sam9.c b/src/flash/nand/at91sam9.c index bfbba67..41cb07b 100644 --- a/src/flash/nand/at91sam9.c +++ b/src/flash/nand/at91sam9.c @@ -389,9 +389,8 @@ static int at91sam9_read_page(struct nand_device *nand, uint32_t page, uint32_t bit = parity & 0x0F; data[word] ^= (0x1) << bit; - LOG_INFO("Data word %d, bit %d corrected.", - (unsigned) word, - (unsigned) bit); + LOG_INFO("Data word %" PRIu32 ", bit %" PRIu32 " corrected.", + word, bit); } } @@ -533,7 +532,7 @@ COMMAND_HANDLER(handle_at91sam9_cle_command) { struct nand_device *nand = NULL; struct at91sam9_nand *info = NULL; - unsigned num, address_line; + unsigned int num, address_line; if (CMD_ARGC != 2) { command_print(CMD, "incorrect number of arguments for 'at91sam9 cle' command"); @@ -563,7 +562,7 @@ COMMAND_HANDLER(handle_at91sam9_ale_command) { struct nand_device *nand = NULL; struct at91sam9_nand *info = NULL; - unsigned num, address_line; + unsigned int num, address_line; if (CMD_ARGC != 2) return ERROR_COMMAND_SYNTAX_ERROR; @@ -591,7 +590,7 @@ COMMAND_HANDLER(handle_at91sam9_rdy_busy_command) { struct nand_device *nand = NULL; struct at91sam9_nand *info = NULL; - unsigned num, base_pioc, pin_num; + unsigned int num, base_pioc, pin_num; if (CMD_ARGC != 3) return ERROR_COMMAND_SYNTAX_ERROR; @@ -622,7 +621,7 @@ COMMAND_HANDLER(handle_at91sam9_ce_command) { struct nand_device *nand = NULL; struct at91sam9_nand *info = NULL; - unsigned num, base_pioc, pin_num; + unsigned int num, base_pioc, pin_num; if (CMD_ARGC != 3) return ERROR_COMMAND_SYNTAX_ERROR; diff --git a/src/flash/nand/core.c b/src/flash/nand/core.c index 37e1d12..c5430ae 100644 --- a/src/flash/nand/core.c +++ b/src/flash/nand/core.c @@ -165,8 +165,8 @@ static struct nand_ecclayout nand_oob_8 = { */ static struct nand_device *get_nand_device_by_name(const char *name) { - unsigned requested = get_flash_name_index(name); - unsigned found = 0; + unsigned int requested = get_flash_name_index(name); + unsigned int found = 0; struct nand_device *nand; for (nand = nand_devices; nand; nand = nand->next) { @@ -194,7 +194,7 @@ struct nand_device *get_nand_device_by_num(int num) return NULL; } -COMMAND_HELPER(nand_command_get_device, unsigned name_index, +COMMAND_HELPER(nand_command_get_device, unsigned int name_index, struct nand_device **nand) { const char *str = CMD_ARGV[name_index]; @@ -202,7 +202,7 @@ COMMAND_HELPER(nand_command_get_device, unsigned name_index, if (*nand) return ERROR_OK; - unsigned num; + unsigned int num; COMMAND_PARSE_NUMBER(uint, str, num); *nand = get_nand_device_by_num(num); if (!*nand) { diff --git a/src/flash/nand/core.h b/src/flash/nand/core.h index 137298c..4286e11 100644 --- a/src/flash/nand/core.h +++ b/src/flash/nand/core.h @@ -209,7 +209,7 @@ int nand_correct_data(struct nand_device *nand, u_char *dat, int nand_register_commands(struct command_context *cmd_ctx); /** helper for parsing a nand device command argument string */ -COMMAND_HELPER(nand_command_get_device, unsigned name_index, +COMMAND_HELPER(nand_command_get_device, unsigned int name_index, struct nand_device **nand); diff --git a/src/flash/nand/davinci.c b/src/flash/nand/davinci.c index b7169fe..17040fe 100644 --- a/src/flash/nand/davinci.c +++ b/src/flash/nand/davinci.c @@ -379,7 +379,7 @@ static int davinci_writepage_tail(struct nand_device *nand, static int davinci_write_page_ecc1(struct nand_device *nand, uint32_t page, uint8_t *data, uint32_t data_size, uint8_t *oob, uint32_t oob_size) { - unsigned oob_offset; + unsigned int oob_offset; struct davinci_nand *info = nand->controller_priv; struct target *target = nand->target; const uint32_t fcr_addr = info->aemif + NANDFCR; diff --git a/src/flash/nand/driver.c b/src/flash/nand/driver.c index ce79e13..5d99102 100644 --- a/src/flash/nand/driver.c +++ b/src/flash/nand/driver.c @@ -33,7 +33,7 @@ static struct nand_flash_controller *nand_flash_controllers[] = { struct nand_flash_controller *nand_driver_find_by_name(const char *name) { - for (unsigned i = 0; nand_flash_controllers[i]; i++) { + for (unsigned int i = 0; nand_flash_controllers[i]; i++) { struct nand_flash_controller *controller = nand_flash_controllers[i]; if (strcmp(name, controller->name) == 0) return controller; @@ -42,7 +42,7 @@ struct nand_flash_controller *nand_driver_find_by_name(const char *name) } int nand_driver_walk(nand_driver_walker_t f, void *x) { - for (unsigned i = 0; nand_flash_controllers[i]; i++) { + for (unsigned int i = 0; nand_flash_controllers[i]; i++) { int retval = (*f)(nand_flash_controllers[i], x); if (retval != ERROR_OK) return retval; diff --git a/src/flash/nand/fileio.c b/src/flash/nand/fileio.c index ca618b3..613ae3c 100644 --- a/src/flash/nand/fileio.c +++ b/src/flash/nand/fileio.c @@ -107,7 +107,7 @@ COMMAND_HELPER(nand_fileio_parse_args, struct nand_fileio_state *state, { nand_fileio_init(state); - unsigned minargs = need_size ? 4 : 3; + unsigned int minargs = need_size ? 4 : 3; if (minargs > CMD_ARGC) return ERROR_COMMAND_SYNTAX_ERROR; @@ -131,7 +131,7 @@ COMMAND_HELPER(nand_fileio_parse_args, struct nand_fileio_state *state, } if (minargs < CMD_ARGC) { - for (unsigned i = minargs; i < CMD_ARGC; i++) { + for (unsigned int i = minargs; i < CMD_ARGC; i++) { if (!strcmp(CMD_ARGV[i], "oob_raw")) state->oob_format |= NAND_OOB_RAW; else if (!strcmp(CMD_ARGV[i], "oob_only")) diff --git a/src/flash/nand/lpc3180.c b/src/flash/nand/lpc3180.c index c1af1d7..d221c34 100644 --- a/src/flash/nand/lpc3180.c +++ b/src/flash/nand/lpc3180.c @@ -890,8 +890,7 @@ static int lpc3180_read_page(struct nand_device *nand, if (mlc_isr & 0x8) { if (mlc_isr & 0x40) { - LOG_ERROR("uncorrectable error detected: 0x%2.2x", - (unsigned)mlc_isr); + LOG_ERROR("uncorrectable error detected: 0x%2.2" PRIx32, mlc_isr); free(page_buffer); free(oob_buffer); return ERROR_NAND_OPERATION_FAILED; @@ -1275,7 +1274,7 @@ COMMAND_HANDLER(handle_lpc3180_select_command) if ((CMD_ARGC < 1) || (CMD_ARGC > 3)) return ERROR_COMMAND_SYNTAX_ERROR; - unsigned num; + unsigned int num; COMMAND_PARSE_NUMBER(uint, CMD_ARGV[0], num); struct nand_device *nand = get_nand_device_by_num(num); if (!nand) { diff --git a/src/flash/nand/lpc32xx.c b/src/flash/nand/lpc32xx.c index 1fdae9f..c67f2aa 100644 --- a/src/flash/nand/lpc32xx.c +++ b/src/flash/nand/lpc32xx.c @@ -1386,8 +1386,7 @@ static int lpc32xx_read_page_mlc(struct nand_device *nand, uint32_t page, if (mlc_isr & 0x8) { if (mlc_isr & 0x40) { - LOG_ERROR("uncorrectable error detected: " - "0x%2.2x", (unsigned)mlc_isr); + LOG_ERROR("uncorrectable error detected: 0x%2.2" PRIx32, mlc_isr); return ERROR_NAND_OPERATION_FAILED; } @@ -1743,7 +1742,7 @@ COMMAND_HANDLER(handle_lpc32xx_select_command) if ((CMD_ARGC < 1) || (CMD_ARGC > 3)) return ERROR_COMMAND_SYNTAX_ERROR; - unsigned num; + unsigned int num; COMMAND_PARSE_NUMBER(uint, CMD_ARGV[0], num); struct nand_device *nand = get_nand_device_by_num(num); if (!nand) { diff --git a/src/flash/nand/mx3.h b/src/flash/nand/mx3.h index b272962..648cd86 100644 --- a/src/flash/nand/mx3.h +++ b/src/flash/nand/mx3.h @@ -86,10 +86,10 @@ enum mx_nf_finalize_action { }; struct mx3_nf_flags { - unsigned target_little_endian:1; - unsigned nand_readonly:1; - unsigned one_kb_sram:1; - unsigned hw_ecc_enabled:1; + unsigned int target_little_endian:1; + unsigned int nand_readonly:1; + unsigned int one_kb_sram:1; + unsigned int hw_ecc_enabled:1; }; struct mx3_nf_controller { diff --git a/src/flash/nand/mxc.h b/src/flash/nand/mxc.h index ae2c03a..e9dc0a2 100644 --- a/src/flash/nand/mxc.h +++ b/src/flash/nand/mxc.h @@ -138,11 +138,11 @@ enum mxc_nf_finalize_action { }; struct mxc_nf_flags { - unsigned target_little_endian:1; - unsigned nand_readonly:1; - unsigned one_kb_sram:1; - unsigned hw_ecc_enabled:1; - unsigned biswap_enabled:1; + unsigned int target_little_endian:1; + unsigned int nand_readonly:1; + unsigned int one_kb_sram:1; + unsigned int hw_ecc_enabled:1; + unsigned int biswap_enabled:1; }; struct mxc_nf_controller { diff --git a/src/flash/nor/Makefile.am b/src/flash/nor/Makefile.am index afa11e7..147807f 100644 --- a/src/flash/nor/Makefile.am +++ b/src/flash/nor/Makefile.am @@ -26,6 +26,7 @@ NOR_DRIVERS = \ %D%/cc26xx.c \ %D%/cfi.c \ %D%/dsp5680xx_flash.c \ + %D%/dw-spi.c \ %D%/efm32.c \ %D%/em357.c \ %D%/eneispif.c \ @@ -44,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 \ @@ -89,6 +91,7 @@ NORHEADERS = \ %D%/cc26xx.h \ %D%/cfi.h \ %D%/driver.h \ + %D%/dw-spi-helper.h \ %D%/imp.h \ %D%/non_cfi.h \ %D%/ocl.h \ diff --git a/src/flash/nor/aducm360.c b/src/flash/nor/aducm360.c index ce9bf24..aa573ac 100644 --- a/src/flash/nor/aducm360.c +++ b/src/flash/nor/aducm360.c @@ -79,7 +79,7 @@ static int aducm360_build_sector_list(struct flash_bank *bank) /* sector size is 512 */ bank->num_sectors = bank->size / FLASH_SECTOR_SIZE; bank->sectors = malloc(sizeof(struct flash_sector) * bank->num_sectors); - for (unsigned i = 0; i < bank->num_sectors; ++i) { + for (unsigned int i = 0; i < bank->num_sectors; ++i) { bank->sectors[i].offset = offset; bank->sectors[i].size = FLASH_SECTOR_SIZE; offset += bank->sectors[i].size; diff --git a/src/flash/nor/at91sam3.c b/src/flash/nor/at91sam3.c index b1cb8f1..b86a18d 100644 --- a/src/flash/nor/at91sam3.c +++ b/src/flash/nor/at91sam3.c @@ -154,15 +154,15 @@ struct sam3_bank_private { struct sam3_chip *chip; /* so we can find the original bank pointer */ struct flash_bank *bank; - unsigned bank_number; + unsigned int bank_number; uint32_t controller_address; uint32_t base_address; uint32_t flash_wait_states; bool present; - unsigned size_bytes; - unsigned nsectors; - unsigned sector_size; - unsigned page_size; + unsigned int size_bytes; + unsigned int nsectors; + unsigned int sector_size; + unsigned int page_size; }; struct sam3_chip_details { @@ -176,12 +176,12 @@ struct sam3_chip_details { uint32_t chipid_cidr; const char *name; - unsigned n_gpnvms; + unsigned int n_gpnvms; #define SAM3_N_NVM_BITS 3 - unsigned gpnvm[SAM3_N_NVM_BITS]; - unsigned total_flash_size; - unsigned total_sram_size; - unsigned n_banks; + unsigned int gpnvm[SAM3_N_NVM_BITS]; + unsigned int total_flash_size; + unsigned int total_sram_size; + unsigned int n_banks; #define SAM3_MAX_FLASH_BANKS 2 /* these are "initialized" from the global const data */ struct sam3_bank_private bank[SAM3_MAX_FLASH_BANKS]; @@ -2029,7 +2029,7 @@ static int efc_get_result(struct sam3_bank_private *private, uint32_t *v) } static int efc_start_command(struct sam3_bank_private *private, - unsigned command, unsigned argument) + unsigned int command, unsigned int argument) { uint32_t n, v; int r; @@ -2051,7 +2051,7 @@ do_retry: case AT91C_EFC_FCMD_CLB: n = (private->size_bytes / private->page_size); if (argument >= n) - LOG_ERROR("*BUG*: Embedded flash has only %u pages", (unsigned)(n)); + LOG_ERROR("*BUG*: Embedded flash has only %" PRIu32 " pages", n); break; case AT91C_EFC_FCMD_SFB: @@ -2124,8 +2124,8 @@ do_retry: * @param status - put command status bits here */ static int efc_perform_command(struct sam3_bank_private *private, - unsigned command, - unsigned argument, + unsigned int command, + unsigned int argument, uint32_t *status) { @@ -2220,7 +2220,7 @@ static int flashd_erase_entire_bank(struct sam3_bank_private *private) * @param puthere - result stored here. */ /* ------------------------------------------------------------------------------ */ -static int flashd_get_gpnvm(struct sam3_bank_private *private, unsigned gpnvm, unsigned *puthere) +static int flashd_get_gpnvm(struct sam3_bank_private *private, unsigned int gpnvm, unsigned int *puthere) { uint32_t v; int r; @@ -2261,10 +2261,10 @@ static int flashd_get_gpnvm(struct sam3_bank_private *private, unsigned gpnvm, u * @param gpnvm GPNVM index. * @returns 0 if successful; otherwise returns an error code. */ -static int flashd_clr_gpnvm(struct sam3_bank_private *private, unsigned gpnvm) +static int flashd_clr_gpnvm(struct sam3_bank_private *private, unsigned int gpnvm) { int r; - unsigned v; + unsigned int v; LOG_DEBUG("Here"); if (private->bank_number != 0) { @@ -2293,10 +2293,10 @@ static int flashd_clr_gpnvm(struct sam3_bank_private *private, unsigned gpnvm) * @param private info about the bank * @param gpnvm GPNVM index. */ -static int flashd_set_gpnvm(struct sam3_bank_private *private, unsigned gpnvm) +static int flashd_set_gpnvm(struct sam3_bank_private *private, unsigned int gpnvm) { int r; - unsigned v; + unsigned int v; if (private->bank_number != 0) { LOG_ERROR("GPNVM only works with Bank0"); @@ -2346,8 +2346,8 @@ static int flashd_get_lock_bits(struct sam3_bank_private *private, uint32_t *v) */ static int flashd_unlock(struct sam3_bank_private *private, - unsigned start_sector, - unsigned end_sector) + unsigned int start_sector, + unsigned int end_sector) { int r; uint32_t status; @@ -2376,8 +2376,8 @@ static int flashd_unlock(struct sam3_bank_private *private, * @param end_sector - last sector (inclusive) to lock */ static int flashd_lock(struct sam3_bank_private *private, - unsigned start_sector, - unsigned end_sector) + unsigned int start_sector, + unsigned int end_sector) { uint32_t status; uint32_t pg; @@ -2405,8 +2405,8 @@ static int flashd_lock(struct sam3_bank_private *private, static uint32_t sam3_reg_fieldname(struct sam3_chip *chip, const char *regname, uint32_t value, - unsigned shift, - unsigned width) + unsigned int shift, + unsigned int width) { uint32_t v; int hwidth, dwidth; @@ -2491,7 +2491,7 @@ static const char *const sramsize[] = { }; -static const struct archnames { unsigned value; const char *name; } archnames[] = { +static const struct archnames { unsigned int value; const char *name; } archnames[] = { { 0x19, "AT91SAM9xx Series" }, { 0x29, "AT91SAM9XExx Series" }, { 0x34, "AT91x34 Series" }, @@ -2867,8 +2867,8 @@ static int sam3_read_this_reg(struct sam3_chip *chip, uint32_t *goes_here) r = target_read_u32(chip->target, reg->address, goes_here); if (r != ERROR_OK) { - LOG_ERROR("Cannot read SAM3 register: %s @ 0x%08x, Err: %d", - reg->name, (unsigned)(reg->address), r); + LOG_ERROR("Cannot read SAM3 register: %s @ 0x%08" PRIx32 ", Err: %d", + reg->name, reg->address, r); } return r; } @@ -2883,8 +2883,8 @@ static int sam3_read_all_regs(struct sam3_chip *chip) r = sam3_read_this_reg(chip, sam3_get_reg_ptr(&(chip->cfg), reg)); if (r != ERROR_OK) { - LOG_ERROR("Cannot read SAM3 register: %s @ 0x%08x, Error: %d", - reg->name, ((unsigned)(reg->address)), r); + LOG_ERROR("Cannot read SAM3 register: %s @ 0x%08" PRIx32 ", Error: %d", + reg->name, reg->address, r); return r; } reg++; @@ -2951,7 +2951,7 @@ static int sam3_protect_check(struct flash_bank *bank) { int r; uint32_t v = 0; - unsigned x; + unsigned int x; struct sam3_bank_private *private; LOG_DEBUG("Begin"); @@ -3071,7 +3071,7 @@ static int sam3_get_details(struct sam3_bank_private *private) const struct sam3_chip_details *details; struct sam3_chip *chip; struct flash_bank *saved_banks[SAM3_MAX_FLASH_BANKS]; - unsigned x; + unsigned int x; LOG_DEBUG("Begin"); details = all_sam3_details; @@ -3264,7 +3264,7 @@ static int sam3_protect(struct flash_bank *bank, int set, unsigned int first, } -static int sam3_page_read(struct sam3_bank_private *private, unsigned pagenum, uint8_t *buf) +static int sam3_page_read(struct sam3_bank_private *private, unsigned int pagenum, uint8_t *buf) { uint32_t adr; int r; @@ -3283,7 +3283,7 @@ static int sam3_page_read(struct sam3_bank_private *private, unsigned pagenum, u return r; } -static int sam3_page_write(struct sam3_bank_private *private, unsigned pagenum, const uint8_t *buf) +static int sam3_page_write(struct sam3_bank_private *private, unsigned int pagenum, const uint8_t *buf) { uint32_t adr; uint32_t status; @@ -3347,10 +3347,10 @@ static int sam3_write(struct flash_bank *bank, uint32_t count) { int n; - unsigned page_cur; - unsigned page_end; + unsigned int page_cur; + unsigned int page_end; int r; - unsigned page_offset; + unsigned int page_offset; struct sam3_bank_private *private; uint8_t *pagebuffer; @@ -3497,7 +3497,7 @@ COMMAND_HANDLER(sam3_handle_info_command) if (!chip) return ERROR_OK; - unsigned x; + unsigned int x; int r; /* bank0 must exist before we can do anything */ @@ -3549,7 +3549,7 @@ need_define: COMMAND_HANDLER(sam3_handle_gpnvm_command) { - unsigned x, v; + unsigned int x, v; int r, who; struct sam3_chip *chip; diff --git a/src/flash/nor/at91sam4.c b/src/flash/nor/at91sam4.c index 6212753..26a8037 100644 --- a/src/flash/nor/at91sam4.c +++ b/src/flash/nor/at91sam4.c @@ -134,15 +134,15 @@ struct sam4_bank_private { struct sam4_chip *chip; /* so we can find the original bank pointer */ struct flash_bank *bank; - unsigned bank_number; + unsigned int bank_number; uint32_t controller_address; uint32_t base_address; uint32_t flash_wait_states; bool present; - unsigned size_bytes; - unsigned nsectors; - unsigned sector_size; - unsigned page_size; + unsigned int size_bytes; + unsigned int nsectors; + unsigned int sector_size; + unsigned int page_size; }; struct sam4_chip_details { @@ -156,12 +156,12 @@ struct sam4_chip_details { uint32_t chipid_cidr; const char *name; - unsigned n_gpnvms; + unsigned int n_gpnvms; #define SAM4_N_NVM_BITS 3 - unsigned gpnvm[SAM4_N_NVM_BITS]; - unsigned total_flash_size; - unsigned total_sram_size; - unsigned n_banks; + unsigned int gpnvm[SAM4_N_NVM_BITS]; + unsigned int total_flash_size; + unsigned int total_sram_size; + unsigned int n_banks; #define SAM4_MAX_FLASH_BANKS 2 /* these are "initialized" from the global const data */ struct sam4_bank_private bank[SAM4_MAX_FLASH_BANKS]; @@ -1479,7 +1479,7 @@ static int efc_get_result(struct sam4_bank_private *private, uint32_t *v) } static int efc_start_command(struct sam4_bank_private *private, - unsigned command, unsigned argument) + unsigned int command, unsigned int argument) { uint32_t n, v; int r; @@ -1501,7 +1501,7 @@ do_retry: case AT91C_EFC_FCMD_CLB: n = (private->size_bytes / private->page_size); if (argument >= n) - LOG_ERROR("*BUG*: Embedded flash has only %u pages", (unsigned)(n)); + LOG_ERROR("*BUG*: Embedded flash has only %" PRIu32 " pages", n); break; case AT91C_EFC_FCMD_SFB: @@ -1574,8 +1574,8 @@ do_retry: * @param status - put command status bits here */ static int efc_perform_command(struct sam4_bank_private *private, - unsigned command, - unsigned argument, + unsigned int command, + unsigned int argument, uint32_t *status) { @@ -1716,7 +1716,7 @@ static int flashd_erase_pages(struct sam4_bank_private *private, * @param puthere - result stored here. */ /* ------------------------------------------------------------------------------ */ -static int flashd_get_gpnvm(struct sam4_bank_private *private, unsigned gpnvm, unsigned *puthere) +static int flashd_get_gpnvm(struct sam4_bank_private *private, unsigned int gpnvm, unsigned int *puthere) { uint32_t v; int r; @@ -1757,10 +1757,10 @@ static int flashd_get_gpnvm(struct sam4_bank_private *private, unsigned gpnvm, u * @param gpnvm GPNVM index. * @returns 0 if successful; otherwise returns an error code. */ -static int flashd_clr_gpnvm(struct sam4_bank_private *private, unsigned gpnvm) +static int flashd_clr_gpnvm(struct sam4_bank_private *private, unsigned int gpnvm) { int r; - unsigned v; + unsigned int v; LOG_DEBUG("Here"); if (private->bank_number != 0) { @@ -1789,10 +1789,10 @@ static int flashd_clr_gpnvm(struct sam4_bank_private *private, unsigned gpnvm) * @param private info about the bank * @param gpnvm GPNVM index. */ -static int flashd_set_gpnvm(struct sam4_bank_private *private, unsigned gpnvm) +static int flashd_set_gpnvm(struct sam4_bank_private *private, unsigned int gpnvm) { int r; - unsigned v; + unsigned int v; if (private->bank_number != 0) { LOG_ERROR("GPNVM only works with Bank0"); @@ -1846,8 +1846,8 @@ static int flashd_get_lock_bits(struct sam4_bank_private *private, uint32_t *v) */ static int flashd_unlock(struct sam4_bank_private *private, - unsigned start_sector, - unsigned end_sector) + unsigned int start_sector, + unsigned int end_sector) { int r; uint32_t status; @@ -1876,8 +1876,8 @@ static int flashd_unlock(struct sam4_bank_private *private, * @param end_sector - last sector (inclusive) to lock */ static int flashd_lock(struct sam4_bank_private *private, - unsigned start_sector, - unsigned end_sector) + unsigned int start_sector, + unsigned int end_sector) { uint32_t status; uint32_t pg; @@ -1905,8 +1905,8 @@ static int flashd_lock(struct sam4_bank_private *private, static uint32_t sam4_reg_fieldname(struct sam4_chip *chip, const char *regname, uint32_t value, - unsigned shift, - unsigned width) + unsigned int shift, + unsigned int width) { uint32_t v; int hwidth, dwidth; @@ -1991,7 +1991,7 @@ static const char *const sramsize[] = { }; -static const struct archnames { unsigned value; const char *name; } archnames[] = { +static const struct archnames { unsigned int value; const char *name; } archnames[] = { { 0x19, "AT91SAM9xx Series" }, { 0x29, "AT91SAM9XExx Series" }, { 0x34, "AT91x34 Series" }, @@ -2374,8 +2374,8 @@ static int sam4_read_this_reg(struct sam4_chip *chip, uint32_t *goes_here) r = target_read_u32(chip->target, reg->address, goes_here); if (r != ERROR_OK) { - LOG_ERROR("Cannot read SAM4 register: %s @ 0x%08x, Err: %d", - reg->name, (unsigned)(reg->address), r); + LOG_ERROR("Cannot read SAM4 register: %s @ 0x%08" PRIx32 ", Err: %d", + reg->name, reg->address, r); } return r; } @@ -2390,8 +2390,8 @@ static int sam4_read_all_regs(struct sam4_chip *chip) r = sam4_read_this_reg(chip, sam4_get_reg_ptr(&(chip->cfg), reg)); if (r != ERROR_OK) { - LOG_ERROR("Cannot read SAM4 register: %s @ 0x%08x, Error: %d", - reg->name, ((unsigned)(reg->address)), r); + LOG_ERROR("Cannot read SAM4 register: %s @ 0x%08" PRIx32 ", Error: %d", + reg->name, reg->address, r); return r; } reg++; @@ -2444,7 +2444,7 @@ static int sam4_protect_check(struct flash_bank *bank) { int r; uint32_t v[4] = {0}; - unsigned x; + unsigned int x; struct sam4_bank_private *private; LOG_DEBUG("Begin"); @@ -2557,7 +2557,7 @@ static int sam4_get_details(struct sam4_bank_private *private) const struct sam4_chip_details *details; struct sam4_chip *chip; struct flash_bank *saved_banks[SAM4_MAX_FLASH_BANKS]; - unsigned x; + unsigned int x; LOG_DEBUG("Begin"); details = all_sam4_details; @@ -2796,7 +2796,7 @@ static int sam4_protect(struct flash_bank *bank, int set, unsigned int first, } -static int sam4_page_read(struct sam4_bank_private *private, unsigned pagenum, uint8_t *buf) +static int sam4_page_read(struct sam4_bank_private *private, unsigned int pagenum, uint8_t *buf) { uint32_t adr; int r; @@ -2841,7 +2841,7 @@ static int sam4_set_wait(struct sam4_bank_private *private) return r; } -static int sam4_page_write(struct sam4_bank_private *private, unsigned pagenum, const uint8_t *buf) +static int sam4_page_write(struct sam4_bank_private *private, unsigned int pagenum, const uint8_t *buf) { uint32_t adr; uint32_t status; @@ -2891,10 +2891,10 @@ static int sam4_write(struct flash_bank *bank, uint32_t count) { int n; - unsigned page_cur; - unsigned page_end; + unsigned int page_cur; + unsigned int page_end; int r; - unsigned page_offset; + unsigned int page_offset; struct sam4_bank_private *private; uint8_t *pagebuffer; @@ -3045,7 +3045,7 @@ COMMAND_HANDLER(sam4_handle_info_command) if (!chip) return ERROR_OK; - unsigned x; + unsigned int x; int r; /* bank0 must exist before we can do anything */ @@ -3097,7 +3097,7 @@ need_define: COMMAND_HANDLER(sam4_handle_gpnvm_command) { - unsigned x, v; + unsigned int x, v; int r, who; struct sam4_chip *chip; diff --git a/src/flash/nor/at91samd.c b/src/flash/nor/at91samd.c index 36298f1..0f7b0bb 100644 --- a/src/flash/nor/at91samd.c +++ b/src/flash/nor/at91samd.c @@ -365,7 +365,7 @@ static const struct samd_family *samd_find_family(uint32_t id) uint8_t family = SAMD_GET_FAMILY(id); uint8_t series = SAMD_GET_SERIES(id); - for (unsigned i = 0; i < ARRAY_SIZE(samd_families); i++) { + for (unsigned int i = 0; i < ARRAY_SIZE(samd_families); i++) { if (samd_families[i].processor == processor && samd_families[i].series == series && samd_families[i].family == family) @@ -387,7 +387,7 @@ static const struct samd_part *samd_find_part(uint32_t id) if (!family) return NULL; - for (unsigned i = 0; i < family->num_parts; i++) { + for (unsigned int i = 0; i < family->num_parts; i++) { if (family->parts[i].id == devsel) return &family->parts[i]; } diff --git a/src/flash/nor/ath79.c b/src/flash/nor/ath79.c index 1d1ec02..7ce42b2 100644 --- a/src/flash/nor/ath79.c +++ b/src/flash/nor/ath79.c @@ -513,7 +513,7 @@ static int ath79_erase(struct flash_bank *bank, unsigned int first, if (ath79_info->dev->erase_cmd == 0x00) return ERROR_FLASH_OPER_UNSUPPORTED; - for (unsigned sector = first; sector <= last; sector++) { + for (unsigned int sector = first; sector <= last; sector++) { if (bank->sectors[sector].is_protected) { LOG_ERROR("Flash sector %u protected", sector); return ERROR_FAIL; diff --git a/src/flash/nor/atsame5.c b/src/flash/nor/atsame5.c index c590081..f34958f 100644 --- a/src/flash/nor/atsame5.c +++ b/src/flash/nor/atsame5.c @@ -85,6 +85,9 @@ #define SAME_SERIES_51 0x01 #define SAME_SERIES_53 0x03 #define SAME_SERIES_54 0x04 +#define PIC32CXSG_SERIES_41 0x07 +#define PIC32CXSG_SERIES_60 0x00 +#define PIC32CXSG_SERIES_61 0x02 /* Device ID macros */ #define SAMD_GET_PROCESSOR(id) (id >> 28) @@ -148,6 +151,27 @@ static const struct samd_part same54_parts[] = { { 0x03, "SAME54N19A", 512, 192 }, }; +/* See PIC32CX SG41/SG60/SG61 Family Silicon Errata and Datasheet Clarifications + * DS80000985G */ +/* Known PIC32CX-SG41 parts. */ +static const struct samd_part pic32cxsg41_parts[] = { + { 0x00, "PIC32CX1025SG41128", 1024, 256 }, + { 0x01, "PIC32CX1025SG41100", 1024, 256 }, + { 0x02, "PIC32CX1025SG41064", 1024, 256 }, +}; + +/* Known PIC32CX-SG60 parts. */ +static const struct samd_part pic32cxsg60_parts[] = { + { 0x00, "PIC32CX1025SG60128", 1024, 256 }, + { 0x01, "PIC32CX1025SG60100", 1024, 256 }, +}; + +/* Known PIC32CX-SG61 parts. */ +static const struct samd_part pic32cxsg61_parts[] = { + { 0x00, "PIC32CX1025SG61128", 1024, 256 }, + { 0x01, "PIC32CX1025SG61100", 1024, 256 }, +}; + /* Each family of parts contains a parts table in the DEVSEL field of DID. The * processor ID, family ID, and series ID are used to determine which exact * family this is and then we can use the corresponding table. */ @@ -169,6 +193,12 @@ static const struct samd_family samd_families[] = { same53_parts, ARRAY_SIZE(same53_parts) }, { SAMD_PROCESSOR_M4, SAMD_FAMILY_E, SAME_SERIES_54, same54_parts, ARRAY_SIZE(same54_parts) }, + { SAMD_PROCESSOR_M4, SAMD_FAMILY_E, PIC32CXSG_SERIES_41, + pic32cxsg41_parts, ARRAY_SIZE(pic32cxsg41_parts) }, + { SAMD_PROCESSOR_M4, SAMD_FAMILY_E, PIC32CXSG_SERIES_60, + pic32cxsg60_parts, ARRAY_SIZE(pic32cxsg60_parts) }, + { SAMD_PROCESSOR_M4, SAMD_FAMILY_E, PIC32CXSG_SERIES_61, + pic32cxsg61_parts, ARRAY_SIZE(pic32cxsg61_parts) }, }; struct samd_info { @@ -194,7 +224,7 @@ static const struct samd_family *samd_find_family(uint32_t id) uint8_t family = SAMD_GET_FAMILY(id); uint8_t series = SAMD_GET_SERIES(id); - for (unsigned i = 0; i < ARRAY_SIZE(samd_families); i++) { + for (unsigned int i = 0; i < ARRAY_SIZE(samd_families); i++) { if (samd_families[i].processor == processor && samd_families[i].series == series && samd_families[i].family == family) @@ -216,7 +246,7 @@ static const struct samd_part *samd_find_part(uint32_t id) if (!family) return NULL; - for (unsigned i = 0; i < family->num_parts; i++) { + for (unsigned int i = 0; i < family->num_parts; i++) { if (family->parts[i].id == devsel) return &family->parts[i]; } diff --git a/src/flash/nor/atsamv.c b/src/flash/nor/atsamv.c index 24c432c..d6d8938 100644 --- a/src/flash/nor/atsamv.c +++ b/src/flash/nor/atsamv.c @@ -55,8 +55,8 @@ struct samv_flash_bank { bool probed; - unsigned size_bytes; - unsigned gpnvm[SAMV_NUM_GPNVM_BITS]; + unsigned int size_bytes; + unsigned int gpnvm[SAMV_NUM_GPNVM_BITS]; }; /* The actual sector size of the SAMV7 flash memory is 128K bytes. @@ -82,7 +82,7 @@ static int samv_efc_get_result(struct target *target, uint32_t *v) } static int samv_efc_start_command(struct target *target, - unsigned command, unsigned argument) + unsigned int command, unsigned int argument) { uint32_t v; samv_efc_get_status(target, &v); @@ -100,7 +100,7 @@ static int samv_efc_start_command(struct target *target, } static int samv_efc_perform_command(struct target *target, - unsigned command, unsigned argument, uint32_t *status) + unsigned int command, unsigned int argument, uint32_t *status) { int r; uint32_t v; @@ -166,7 +166,7 @@ static int samv_erase_pages(struct target *target, first_page | erase_pages, status); } -static int samv_get_gpnvm(struct target *target, unsigned gpnvm, unsigned *out) +static int samv_get_gpnvm(struct target *target, unsigned int gpnvm, unsigned int *out) { uint32_t v; int r; @@ -190,10 +190,10 @@ static int samv_get_gpnvm(struct target *target, unsigned gpnvm, unsigned *out) return r; } -static int samv_clear_gpnvm(struct target *target, unsigned gpnvm) +static int samv_clear_gpnvm(struct target *target, unsigned int gpnvm) { int r; - unsigned v; + unsigned int v; if (gpnvm >= SAMV_NUM_GPNVM_BITS) { LOG_ERROR("invalid gpnvm %d, max: %d", gpnvm, SAMV_NUM_GPNVM_BITS); @@ -209,10 +209,10 @@ static int samv_clear_gpnvm(struct target *target, unsigned gpnvm) return r; } -static int samv_set_gpnvm(struct target *target, unsigned gpnvm) +static int samv_set_gpnvm(struct target *target, unsigned int gpnvm) { int r; - unsigned v; + unsigned int v; if (gpnvm >= SAMV_NUM_GPNVM_BITS) { LOG_ERROR("invalid gpnvm %d, max: %d", gpnvm, SAMV_NUM_GPNVM_BITS); return ERROR_FAIL; @@ -231,7 +231,7 @@ static int samv_set_gpnvm(struct target *target, unsigned gpnvm) } static int samv_flash_unlock(struct target *target, - unsigned start_sector, unsigned end_sector) + unsigned int start_sector, unsigned int end_sector) { int r; uint32_t status; @@ -251,7 +251,7 @@ static int samv_flash_unlock(struct target *target, } static int samv_flash_lock(struct target *target, - unsigned start_sector, unsigned end_sector) + unsigned int start_sector, unsigned int end_sector) { uint32_t status; uint32_t pg; @@ -419,7 +419,7 @@ static int samv_protect(struct flash_bank *bank, int set, unsigned int first, } static int samv_page_read(struct target *target, - unsigned page_num, uint8_t *buf) + unsigned int page_num, uint8_t *buf) { uint32_t addr = SAMV_FLASH_BASE + page_num * SAMV_PAGE_SIZE; int r = target_read_memory(target, addr, 4, SAMV_PAGE_SIZE / 4, buf); @@ -430,7 +430,7 @@ static int samv_page_read(struct target *target, } static int samv_page_write(struct target *target, - unsigned pagenum, const uint8_t *buf) + unsigned int pagenum, const uint8_t *buf) { uint32_t status; const uint32_t addr = SAMV_FLASH_BASE + pagenum * SAMV_PAGE_SIZE; @@ -618,7 +618,7 @@ COMMAND_HANDLER(samv_handle_gpnvm_command) return ERROR_COMMAND_SYNTAX_ERROR; } - unsigned v = 0; + unsigned int v = 0; if (!strcmp("show", CMD_ARGV[0])) { if (who == -1) { showall: diff --git a/src/flash/nor/cfi.c b/src/flash/nor/cfi.c index 78bc91e..2a15e49 100644 --- a/src/flash/nor/cfi.c +++ b/src/flash/nor/cfi.c @@ -806,7 +806,7 @@ int cfi_flash_bank_cmd(struct flash_bank *bank, unsigned int argc, const char ** } bank->driver_priv = cfi_info; - for (unsigned i = 6; i < argc; i++) { + for (unsigned int i = 6; i < argc; i++) { if (strcmp(argv[i], "x16_as_x8") == 0) cfi_info->x16_as_x8 = true; else if (strcmp(argv[i], "data_swap") == 0) @@ -2219,8 +2219,7 @@ static int cfi_read(struct flash_bank *bank, uint8_t *buffer, uint32_t offset, u uint8_t current_word[CFI_MAX_BUS_WIDTH]; int retval; - LOG_DEBUG("reading buffer of %i byte at 0x%8.8x", - (int)count, (unsigned)offset); + LOG_DEBUG("reading buffer of %" PRIi32 " byte at 0x%8.8" PRIx32, count, offset); if (bank->target->state != TARGET_HALTED) { LOG_ERROR("Target not halted"); diff --git a/src/flash/nor/cfi.h b/src/flash/nor/cfi.h index ec7f474..3a76d98 100644 --- a/src/flash/nor/cfi.h +++ b/src/flash/nor/cfi.h @@ -58,10 +58,10 @@ struct cfi_flash_bank { void *alt_ext; /* calculated timeouts */ - unsigned word_write_timeout; - unsigned buf_write_timeout; - unsigned block_erase_timeout; - unsigned chip_erase_timeout; + unsigned int word_write_timeout; + unsigned int buf_write_timeout; + unsigned int block_erase_timeout; + unsigned int chip_erase_timeout; /* memory accessors */ int (*write_mem)(struct flash_bank *bank, target_addr_t addr, diff --git a/src/flash/nor/core.c b/src/flash/nor/core.c index 5e6c971..5c4f2ac 100644 --- a/src/flash/nor/core.c +++ b/src/flash/nor/core.c @@ -164,7 +164,7 @@ int default_flash_verify(struct flash_bank *bank, void flash_bank_add(struct flash_bank *bank) { /* put flash bank in linked list */ - unsigned bank_num = 0; + unsigned int bank_num = 0; if (flash_banks) { /* find last flash bank */ struct flash_bank *p = flash_banks; @@ -242,8 +242,8 @@ void flash_free_all_banks(void) struct flash_bank *get_flash_bank_by_name_noprobe(const char *name) { - unsigned requested = get_flash_name_index(name); - unsigned found = 0; + unsigned int requested = get_flash_name_index(name); + unsigned int found = 0; struct flash_bank *bank; for (bank = flash_banks; bank; bank = bank->next) { diff --git a/src/flash/nor/core.h b/src/flash/nor/core.h index ff175a1..f8cf5e2 100644 --- a/src/flash/nor/core.h +++ b/src/flash/nor/core.h @@ -250,7 +250,7 @@ int get_flash_bank_by_num(unsigned int num, struct flash_bank **bank); * @param bank On output, contains a pointer to the bank or NULL. * @returns ERROR_OK on success, or an error indicating the problem. */ -COMMAND_HELPER(flash_command_get_bank, unsigned name_index, +COMMAND_HELPER(flash_command_get_bank, unsigned int name_index, struct flash_bank **bank); /** * Retrieves @a bank from a command argument, reporting errors parsing diff --git a/src/flash/nor/driver.h b/src/flash/nor/driver.h index 211661e..794566f 100644 --- a/src/flash/nor/driver.h +++ b/src/flash/nor/driver.h @@ -254,6 +254,7 @@ extern const struct flash_driver cc26xx_flash; extern const struct flash_driver cc3220sf_flash; extern const struct flash_driver cfi_flash; extern const struct flash_driver dsp5680xx_flash; +extern const struct flash_driver dw_spi_flash; extern const struct flash_driver efm32_flash; extern const struct flash_driver em357_flash; extern const struct flash_driver eneispif_flash; @@ -273,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 3435988..67d8624 100644 --- a/src/flash/nor/drivers.c +++ b/src/flash/nor/drivers.c @@ -31,6 +31,7 @@ static const struct flash_driver * const flash_drivers[] = { &cc26xx_flash, &cfi_flash, &dsp5680xx_flash, + &dw_spi_flash, &efm32_flash, &em357_flash, &eneispif_flash, @@ -50,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, @@ -91,7 +93,7 @@ static const struct flash_driver * const flash_drivers[] = { const struct flash_driver *flash_driver_find_by_name(const char *name) { - for (unsigned i = 0; flash_drivers[i]; i++) { + for (unsigned int i = 0; flash_drivers[i]; i++) { if (strcmp(name, flash_drivers[i]->name) == 0) return flash_drivers[i]; } diff --git a/src/flash/nor/dw-spi-helper.h b/src/flash/nor/dw-spi-helper.h new file mode 100644 index 0000000..d353755 --- /dev/null +++ b/src/flash/nor/dw-spi-helper.h @@ -0,0 +1,102 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/** + * @file + * Driver for SPI NOR flash chips connected via DesignWare SPI Core. + * + * In order to avoid using stack, all helper function arguments are packed + * into a single struct, passed by pointer. + * + * Pointers are represented by 64 bit integers to make structs compatible + * with 64 bit targets. + * + * This file contains helper function argument structures. + */ + +#ifndef OPENOCD_FLASH_NOR_DW_SPI_HELPER_H +#define OPENOCD_FLASH_NOR_DW_SPI_HELPER_H + +#include <stdint.h> + +/** + * @brief Arguments for transaction helper function. + */ +struct dw_spi_transaction { + uint64_t buffer; + ///< Pointer to data buffer to send over SPI. + ///< Return values are stored in place of output data when + ///< dw_spi_transaction::read_flag is 1. + uint32_t size; ///< Size of dw_spi_transaction::buffer. + uint64_t status_reg; ///< Pointer to SR register. + uint64_t data_reg; ///< Pointer to DR register. + uint8_t read_flag; + ///< When 1, store RX FIFO data to dw_spi_transaction::buffer. +} __attribute__((packed)); + +/** + * @brief Arguments for check_fill helper function. + */ +struct dw_spi_check_fill { + uint32_t address; ///< Starting address. Sector aligned. + uint32_t sector_size; ///< Sector size. + uint32_t sector_count; ///< Number of sectors to check. + uint64_t status_reg; ///< Pointer to SR register. + uint64_t data_reg; ///< Pointer to DR register. + uint64_t fill_status_array; + ///< Pointer to array describing sectors fill status. + ///< 1 if filled, 0 if not filled. + uint8_t pattern; ///< Fill pattern. + uint8_t read_cmd; ///< Read data command. + uint8_t four_byte_mode; ///< Four byte addressing mode flag. +} __attribute__((packed)); + +/** + * @brief Arguments for erase helper function. + */ +struct dw_spi_erase { + uint32_t address; ///< First sector address. Sector aligned. + uint32_t sector_size; ///< Sector size. + uint32_t sector_count; ///< Number of sectors to erase. + uint64_t status_reg; ///< Pointer to SR register. + uint64_t data_reg; ///< Pointer to DR register. + uint8_t read_status_cmd; ///< Read status command. + uint8_t write_enable_cmd; ///< Write enable command. + uint8_t erase_sector_cmd; ///< Erase sector command. + uint8_t write_enable_mask; ///< Write enable mask. + uint8_t busy_mask; ///< Busy mask. + uint8_t four_byte_mode; ///< Four byte addressing mode flag. +} __attribute__((packed)); + +/** + * @brief Arguments for program helper function. + */ +struct dw_spi_program { + uint32_t address; + ///< First page address. Page aligned when write is crossing + ///< the page boundary. + uint32_t page_size; ///< Page size. + uint64_t buffer; ///< Data buffer pointer. + uint32_t buffer_size; ///< Size of dw_spi_program::buffer. + uint64_t status_reg; ///< Pointer to SR register. + uint64_t data_reg; ///< Pointer to DR register. + uint8_t read_status_cmd; ///< Read status command. + uint8_t write_enable_cmd; ///< Write enable command. + uint8_t program_cmd; ///< Program command. + uint8_t write_enable_mask; ///< Write enable mask. + uint8_t busy_mask; ///< Busy mask. + uint8_t four_byte_mode; ///< Four byte addressing mode flag. +} __attribute__((packed)); + +/** + * @brief Arguments for read helper function. + */ +struct dw_spi_read { + uint32_t address; ///< First sector address. + uint64_t buffer; ///< Data buffer pointer. + uint32_t buffer_size; ///< Size of dw_spi_read::buffer. + uint64_t status_reg; ///< Pointer to SR register. + uint64_t data_reg; ///< Pointer to DR register. + uint8_t read_cmd; ///< Read data command. + uint8_t four_byte_mode; ///< Four byte addressing mode flag. +} __attribute__((packed)); + +#endif /* OPENOCD_FLASH_NOR_DW_SPI_HELPER_H */ diff --git a/src/flash/nor/dw-spi.c b/src/flash/nor/dw-spi.c new file mode 100644 index 0000000..e196547 --- /dev/null +++ b/src/flash/nor/dw-spi.c @@ -0,0 +1,1608 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/** + * @file + * Driver for SPI NOR flash chips connected via DesignWare SPI Core. + * Controller's Linux driver is located at drivers/spi/spi-dw-mmio.c. + * DW-SPI is used in a number of processors, including Microsemi Jaguar2 and + * Ocelot switch chips. + * + * Serial interface (SI) nCS0 pin, which is usually connected to the external + * flash, cannot be controlled via GPIO controller: it is asserted only when + * TX FIFO is not empty. Since JTAG is not fast enough to fill TX FIFO and + * collect data from RX FIFO at the same time even on the slowest SPI clock + * speeds, driver can only operate using functions, loaded in target's memory. + * Therefore, it requires the user to set up DRAM controller and provide + * work-area. + * + * In Microsemi devices, serial interface pins may be governed either + * by Boot or Master controller. For these devices, additional configuration of + * spi_mst address is required to switch between the two. + * + * Currently supported devices typically have much more RAM then NOR Flash + * (Jaguar2 reference design has 256MB RAM and 32MB NOR Flash), so supporting + * work-area sizes smaller then transfer buffer seems like the unnecessary + * complication. + * + * This code was tested on Jaguar2 VSC7448 connected to Macronix MX25L25635F. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "dw-spi-helper.h" +#include "imp.h" +#include "spi.h" + +#include <helper/bits.h> +#include <helper/time_support.h> +#include <target/algorithm.h> +#include <target/breakpoints.h> +#include <target/mips32.h> +#include <target/target_type.h> + +/** + * @brief IP block placement map. + * + * Used for dynamic definition of the register map. + * + * IP block is used on different chips and placed in different locations. + * This structure defines some implementation specific variables. + */ +struct dw_spi_regmap { + uint32_t freq; ///< Clock frequency. + target_addr_t simc; ///< Absolute offset of SIMC register block. + target_addr_t spi_mst; + ///< Absolute offset of ICPU_CFG:SPI_MST register. 0 if not available. + uint8_t si_if_owner_offset; + ///< Offset of \ref si_mode bits in ICPU_CFG:SPI_MST. +}; + +/** + * @brief Register map for Jaguar2 switch devices. + */ +static const struct dw_spi_regmap jaguar2_regmap = { + .freq = 250000000UL, + .simc = 0x70101000UL, + .spi_mst = 0x70000024UL, + .si_if_owner_offset = 6, +}; + +/** + * @brief Register map for Ocelot switch devices. + */ +static const struct dw_spi_regmap ocelot_regmap = { + .freq = 250000000UL, + .simc = 0x70101000UL, + .spi_mst = 0x70000024UL, + .si_if_owner_offset = 4, +}; + +#define DW_SPI_IF_OWNER_WIDTH 2 ///< IF owner register field width. + +/** + * @brief Owner of the SI interface. + */ +enum dw_spi_si_mode { + DW_SPI_SI_MODE_BOOT = 1, + ///< Boot controller maps contents of SPI Flash to memory in read-only mode. + DW_SPI_SI_MODE_MASTER = 2, + ///< SPI controller mode for reading/writing SPI Flash. +}; + +#define DW_SPI_REG_CTRLR0 0x00 ///< General configuration register. +#define DW_SPI_REG_SIMCEN 0x08 ///< Master controller enable register. +#define DW_SPI_REG_SER 0x10 ///< Slave select register. +#define DW_SPI_REG_BAUDR 0x14 ///< Baud rate configuration register. +#define DW_SPI_REG_SR 0x28 ///< Status register. +#define DW_SPI_REG_IMR 0x2c ///< Interrupt configuration register. +#define DW_SPI_REG_DR 0x60 ///< Data register. + +#define DW_SPI_REG_CTRLR0_DFS(x) ((x) & GENMASK(3, 0)) ///< Data frame size. +#define DW_SPI_REG_CTRLR0_FRF(x) (((x) << 4) & GENMASK(5, 4)) ///< SI protocol. +#define DW_SPI_REG_CTRLR0_SCPH(x) ((!!(x)) << 6) ///< Probe position. +#define DW_SPI_REG_CTRLR0_SCPOL(x) ((!!(x)) << 7) ///< Probe polarity. +#define DW_SPI_REG_CTRLR0_TMOD(x) (((x) << 8) & GENMASK(9, 8)) ///< SI mode. +#define DW_SPI_REG_SIMCEN_SIMCEN(x) (!!(x)) ///< Controller enable. +#define DW_SPI_REG_SER_SER(x) ((x) & GENMASK(15, 0)) ///< Slave select bitmask. +#define DW_SPI_REG_BAUDR_SCKDV(x) ((x) & GENMASK(15, 0)) ///< Clock divisor. + +/** + * @brief Driver private state. + */ +struct dw_spi_driver { + bool probed; ///< Bank is probed. + uint32_t id; ///< Chip ID. + unsigned int speed; ///< Flash speed. + unsigned int timeout; ///< Flash timeout in milliseconds. + uint8_t chip_select_bitmask; ///< Chip select bitmask. + bool four_byte_mode; ///< Flash chip is in 32bit address mode. + enum dw_spi_si_mode saved_ctrl_mode; + ///< Previously selected controller mode. + struct dw_spi_regmap regmap; ///< SI controller regmap. + const struct flash_device *spi_flash; ///< SPI flash device info. +}; + +/** + * @brief Register used to pass argument struct to helper functions. + */ +#define DW_SPI_ARG_REG "r4" + +/** + * @brief Default timeout value in ms for flash transaction jobs. + */ +#define DW_SPI_TIMEOUT_DEFAULT (600 * 1000) + +/** + * @brief Timeout value in ms for short flash transactions, + * e.g. reading flash ID and status register. + */ +#define DW_SPI_TIMEOUT_TRANSACTION 1000 + +/** + * @brief Select SI interface owner. + * + * Mode selection is skipped if Boot controller not available on target + * (i.e. spi_mst command argument is not configured). + * + * @param[in] bank: Flash bank. + * @param[in] mode: New controller mode. + * @return Command execution status. + */ +static int +dw_spi_ctrl_mode(const struct flash_bank *const bank, enum dw_spi_si_mode mode) +{ + struct target *const target = bank->target; + const struct dw_spi_driver *const driver = bank->driver_priv; + const struct dw_spi_regmap *const regmap = &driver->regmap; + + if (!regmap->spi_mst) + return ERROR_OK; + + uint32_t ctrl; + int ret = target_read_u32(target, regmap->spi_mst, &ctrl); + if (ret) { + LOG_ERROR("DW SPI SPI:MST register read error"); + return ret; + } + ctrl &= ~GENMASK(DW_SPI_IF_OWNER_WIDTH + driver->regmap.si_if_owner_offset, + driver->regmap.si_if_owner_offset); + ctrl |= mode << driver->regmap.si_if_owner_offset; + + ret = target_write_u32(target, regmap->spi_mst, ctrl); + if (ret) + LOG_ERROR("DW SPI controller mode configuration error"); + + return ret; +} + +/** + * @brief Select master controller as SI interface owner. + * + * Previous interface owner is restored via dw_spi_ctrl_mode_restore() function. + * Mode selection is skipped if Boot controller not available on target + * (i.e. spi_mst command argument is not configured). + * + * @param[in] bank: Flash bank. + * @param[in] mode: New controller mode. + * @return Command execution status. + */ +static int +dw_spi_ctrl_mode_configure(const struct flash_bank *const bank, + enum dw_spi_si_mode mode) +{ + struct target *const target = bank->target; + struct dw_spi_driver *const driver = bank->driver_priv; + const struct dw_spi_regmap *const regmap = &driver->regmap; + + if (!regmap->spi_mst) + return ERROR_OK; + + uint32_t ctrl; + int ret = target_read_u32(target, regmap->spi_mst, &ctrl); + if (ret) { + LOG_ERROR("DW SPI controller mode query error"); + return ret; + } + driver->saved_ctrl_mode = + (enum dw_spi_si_mode)((ctrl >> driver->regmap.si_if_owner_offset) & + GENMASK(DW_SPI_IF_OWNER_WIDTH, 0)); + + return dw_spi_ctrl_mode(bank, mode); +} + +/** + * @brief Restore SI controller mode. + * + * Restore initially configured SI controller mode. Undo configuration done by + * dw_spi_ctrl_mode_configure() function. + * Mode selection is skipped if Boot controller not available on target + * (i.e. spi_mst command argument is not configured). + * + * @param[in] bank: Flash bank. + * @return Command execution status. + */ +static int +dw_spi_ctrl_mode_restore(const struct flash_bank *const bank) +{ + const struct dw_spi_driver *const driver = bank->driver_priv; + + return dw_spi_ctrl_mode(bank, driver->saved_ctrl_mode); +} + +/** + * @brief Enable master controller. + * + * Configuration of the master controller must be done when it is disabled. + * + * @param[in] bank: Flash bank. + * @param[in] value: New enable state. + * @return Command execution status. + */ +static int +dw_spi_master_ctrl_enable(const struct flash_bank *const bank, bool value) +{ + struct target *const target = bank->target; + const struct dw_spi_driver *const driver = bank->driver_priv; + const struct dw_spi_regmap *const regmap = &driver->regmap; + + int ret = target_write_u32(target, regmap->simc + DW_SPI_REG_SIMCEN, + DW_SPI_REG_SIMCEN_SIMCEN(value)); + if (ret) + LOG_ERROR("DW SPI master controller enable flag configuration error"); + + return ret; +} + +/** + * @brief Configure SI transfer mode. + * + * @param[in] bank: Flash bank. + * @return Command execution status. + */ +static int +dw_spi_ctrl_configure_si(const struct flash_bank *const bank) +{ + struct target *const target = bank->target; + const struct dw_spi_driver *const driver = bank->driver_priv; + const struct dw_spi_regmap *const regmap = &driver->regmap; + + // 8 bit frame; Motorola protocol; middle lo probe; TX RX mode + const uint32_t mode = DW_SPI_REG_CTRLR0_DFS(0x7) | + DW_SPI_REG_CTRLR0_FRF(0) | + DW_SPI_REG_CTRLR0_SCPH(0) | + DW_SPI_REG_CTRLR0_SCPOL(0) | + DW_SPI_REG_CTRLR0_TMOD(0); + + int ret = target_write_u32(target, regmap->simc + DW_SPI_REG_CTRLR0, mode); + if (ret) { + LOG_ERROR("DW SPI master controller configuration query error"); + return ret; + } + + ret = target_write_u32(target, regmap->simc + DW_SPI_REG_SER, + DW_SPI_REG_SER_SER(driver->chip_select_bitmask)); + if (ret) + LOG_ERROR("DW SPI slave select configuration error"); + + return ret; +} + +/** + * @brief Configure SI transfer speed. + * + * @param[in] bank: Flash bank. + * @return Command execution status. + */ +static int +dw_spi_ctrl_configure_speed(const struct flash_bank *const bank) +{ + struct target *const target = bank->target; + const struct dw_spi_driver *const driver = bank->driver_priv; + const struct dw_spi_regmap *const regmap = &driver->regmap; + + // divisor LSB must be zero + const uint16_t div = MIN((regmap->freq / driver->speed), 0xfffe) & 0xfffe; + + int ret = target_write_u32(target, regmap->simc + DW_SPI_REG_BAUDR, + DW_SPI_REG_BAUDR_SCKDV(div)); + if (ret) { + LOG_ERROR("DW SPI speed configuration error"); + return ret; + } + + unsigned int speed = regmap->freq / div; + LOG_DEBUG("DW SPI setting NOR controller speed to %u kHz", speed / 1000); + + return ret; +} + +/** + * @brief Disable SI master controller interrupts. + * + * @param[in] bank: Flash bank. + * @return Command execution status. + */ +static int +dw_spi_ctrl_disable_interrupts(const struct flash_bank *const bank) +{ + struct target *const target = bank->target; + const struct dw_spi_driver *const driver = bank->driver_priv; + const struct dw_spi_regmap *const regmap = &driver->regmap; + + int ret = target_write_u32(target, regmap->simc + DW_SPI_REG_IMR, 0); + if (ret) + LOG_ERROR("DW SPI disable interrupts error"); + + return ret; +} + +/** + * @brief Do data transaction. + * + * Buffer data are sent and replaced with received data. Total buffer size + * is a sum of TX and RX messages. RX portion of the buffer is initially + * filled with dummy values, which get replaced by the message. + * + * @param[in] bank: Flash bank. + * @param[in,out] buffer: Data buffer. If \p read flag is set, buffer is + * filled with received data. + * @param[in] size: \p buffer size. + * @param[in] read: The read flag. If set to true, read values will override + * \p buffer. + * @return Command execution status. + */ +static int +dw_spi_ctrl_transaction(const struct flash_bank *const bank, + uint8_t *const buffer, size_t size, bool read) +{ + struct target *const target = bank->target; + const struct dw_spi_driver *const driver = bank->driver_priv; + const struct dw_spi_regmap *const regmap = &driver->regmap; + + static const uint8_t target_code[] = { +#include "../../../contrib/loaders/flash/dw-spi/mipsel-linux-gnu-transaction.inc" + }; + const size_t target_code_size = sizeof(target_code); + const size_t total_working_area_size = + target_code_size + sizeof(struct dw_spi_transaction) + size; + + // allocate working area, memory args and data buffer + struct working_area *helper; + int ret = target_alloc_working_area(target, target_code_size, &helper); + if (ret) { + LOG_ERROR("DW SPI could not allocate working area. Need %zx", + total_working_area_size); + goto err_helper; + } + + struct working_area *helper_args; + ret = target_alloc_working_area(target, sizeof(struct dw_spi_transaction), + &helper_args); + if (ret) { + LOG_ERROR("DW SPI could not allocate working area. Need %zx", + total_working_area_size); + goto err_helper_args; + } + + struct working_area *target_buffer; + ret = target_alloc_working_area(target, size, &target_buffer); + if (ret) { + LOG_ERROR("DW SPI could not allocate working area. Need %zx", + total_working_area_size); + goto err_target_buffer; + } + + // write algorithm code and buffer to working areas + ret = target_write_buffer(target, helper->address, target_code_size, + target_code); + if (ret) { + LOG_ERROR("DW SPI writing to working area error"); + goto err_write_buffer; + } + + ret = target_write_buffer(target, target_buffer->address, size, buffer); + if (ret) { + LOG_ERROR("DW SPI writing to working area error"); + goto err_write_buffer; + } + + // prepare helper execution + struct mips32_algorithm mips32_algo = { .common_magic = MIPS32_COMMON_MAGIC, + .isa_mode = MIPS32_ISA_MIPS32 }; + + struct reg_param reg_param; + init_reg_param(®_param, DW_SPI_ARG_REG, 32, PARAM_OUT); + struct mem_param mem_param; + init_mem_param(&mem_param, helper_args->address, helper_args->size, + PARAM_OUT); + + // Set the arguments for the helper + buf_set_u32(reg_param.value, 0, 32, helper_args->address); + + struct dw_spi_transaction *helper_args_val = + (struct dw_spi_transaction *)mem_param.value; + target_buffer_set_u32(target, (uint8_t *)&helper_args_val->buffer, + target_buffer->address); + target_buffer_set_u32(target, (uint8_t *)&helper_args_val->size, size); + target_buffer_set_u32(target, (uint8_t *)&helper_args_val->status_reg, + regmap->simc + DW_SPI_REG_SR); + target_buffer_set_u32(target, (uint8_t *)&helper_args_val->data_reg, + regmap->simc + DW_SPI_REG_DR); + helper_args_val->read_flag = read; + + ret = target_run_algorithm(target, 1, &mem_param, 1, ®_param, + helper->address, 0, DW_SPI_TIMEOUT_TRANSACTION, + &mips32_algo); + + if (ret) { + LOG_ERROR("DW SPI flash algorithm error"); + goto cleanup; + } + + if (read) { + ret = target_read_buffer(target, target_buffer->address, size, buffer); + if (ret) + LOG_ERROR("DW SPI target buffer read error"); + } + +cleanup: + destroy_reg_param(®_param); + destroy_mem_param(&mem_param); + +err_write_buffer: + target_free_working_area(target, target_buffer); +err_target_buffer: + target_free_working_area(target, helper_args); +err_helper_args: + target_free_working_area(target, helper); +err_helper: + + return ret; +} + +/** + * @brief Check that selected region is filled with pattern. + * + * This function is used for Flash erase checking. + * + * @param[in] bank: Flash bank. + * @param[in] address: Starting address. Sector aligned. + * @param[in] sector_size: Size of sector. + * @param[in] sector_count: Number of sectors. + * @param[in] pattern: Fill pattern. + * @param[in] read_cmd: Flash read command. + * @param[out] buffer: Filled flag array. Must hold \p sector_count number + * of entries. + * @return Command execution status. + */ +static int +dw_spi_ctrl_check_sectors_fill(const struct flash_bank *const bank, + uint32_t address, size_t sector_size, + size_t sector_count, uint8_t pattern, + uint8_t read_cmd, uint8_t *buffer) +{ + struct target *const target = bank->target; + const struct dw_spi_driver *const driver = bank->driver_priv; + const struct dw_spi_regmap *const regmap = &driver->regmap; + + static const uint8_t target_code[] = { +#include "../../../contrib/loaders/flash/dw-spi/mipsel-linux-gnu-check_fill.inc" + }; + const size_t target_code_size = sizeof(target_code); + const size_t total_working_area_size = + target_code_size + sizeof(struct dw_spi_check_fill) + sector_count; + + // allocate working area, memory args and data buffer + struct working_area *helper; + int ret = target_alloc_working_area(target, target_code_size, &helper); + if (ret) { + LOG_ERROR("DW SPI could not allocate working area. Need %zx", + total_working_area_size); + goto err_helper; + } + + struct working_area *helper_args; + ret = target_alloc_working_area(target, sizeof(struct dw_spi_check_fill), + &helper_args); + if (ret) { + LOG_ERROR("DW SPI could not allocate working area. Need %zx", + total_working_area_size); + goto err_helper_args; + } + + struct working_area *target_buffer; + ret = target_alloc_working_area(target, sector_count, &target_buffer); + if (ret) { + LOG_ERROR("DW SPI could not allocate working area. Need %zx", + total_working_area_size); + goto err_target_buffer; + } + + // write algorithm code and buffer to working areas + ret = target_write_buffer(target, helper->address, target_code_size, + target_code); + if (ret) { + LOG_ERROR("DW SPI writing to working area error"); + goto err_write_buffer; + } + + // prepare helper execution + struct mips32_algorithm mips32_algo = { .common_magic = MIPS32_COMMON_MAGIC, + .isa_mode = MIPS32_ISA_MIPS32 }; + + struct reg_param reg_param; + init_reg_param(®_param, DW_SPI_ARG_REG, 32, PARAM_OUT); + struct mem_param mem_param; + init_mem_param(&mem_param, helper_args->address, helper_args->size, + PARAM_OUT); + + // Set the arguments for the helper + buf_set_u32(reg_param.value, 0, 32, helper_args->address); + + struct dw_spi_check_fill *helper_args_val = + (struct dw_spi_check_fill *)mem_param.value; + target_buffer_set_u32(target, (uint8_t *)&helper_args_val->address, + address); + target_buffer_set_u32(target, (uint8_t *)&helper_args_val->sector_size, + sector_size); + target_buffer_set_u32(target, (uint8_t *)&helper_args_val->sector_count, + sector_count); + target_buffer_set_u32(target, (uint8_t *)&helper_args_val->status_reg, + regmap->simc + DW_SPI_REG_SR); + target_buffer_set_u32(target, (uint8_t *)&helper_args_val->data_reg, + regmap->simc + DW_SPI_REG_DR); + target_buffer_set_u32(target, + (uint8_t *)&helper_args_val->fill_status_array, + target_buffer->address); + helper_args_val->pattern = pattern; + helper_args_val->read_cmd = read_cmd; + helper_args_val->four_byte_mode = driver->four_byte_mode; + + ret = target_run_algorithm(target, 1, &mem_param, 1, ®_param, + helper->address, 0, driver->timeout, + &mips32_algo); + + if (ret) { + LOG_ERROR("DW SPI flash algorithm error"); + goto cleanup; + } + + ret = target_read_buffer(target, target_buffer->address, sector_count, + buffer); + if (ret) + LOG_ERROR("DW SPI target buffer read error"); + +cleanup: + destroy_reg_param(®_param); + destroy_mem_param(&mem_param); + +err_write_buffer: + target_free_working_area(target, target_buffer); +err_target_buffer: + target_free_working_area(target, helper_args); +err_helper_args: + target_free_working_area(target, helper); +err_helper: + + return ret; +} + +/** + * @brief Write flash region. + * + * @param[in] bank: Flash bank. + * @param[in] address: First page address. Page aligned when write is crossing + * the page boundary. + * @param[in] buffer: Data buffer. + * @param[in] buffer_size: \p buffer size. + * @param[in] page_size: Size of flash page. + * @param[in] stat_cmd: Flash command to read chip status. + * @param[in] we_cmd: Flash command to enable write. + * @param[in] program_cmd: Flash command to program chip. + * @param[in] we_mask: Status byte write enable mask. + * @param[in] busy_mask: Status byte write busy mask. + * @return Command execution status. + */ +static int +dw_spi_ctrl_program(const struct flash_bank *const bank, uint32_t address, + const uint8_t *const buffer, size_t buffer_size, + uint32_t page_size, uint8_t stat_cmd, uint8_t we_cmd, + uint8_t program_cmd, uint8_t we_mask, uint8_t busy_mask) +{ + struct target *const target = bank->target; + const struct dw_spi_driver *const driver = bank->driver_priv; + const struct dw_spi_regmap *const regmap = &driver->regmap; + + static const uint8_t target_code[] = { +#include "../../../contrib/loaders/flash/dw-spi/mipsel-linux-gnu-program.inc" + }; + const size_t target_code_size = sizeof(target_code); + const size_t total_working_area_size = + target_code_size + sizeof(struct dw_spi_program) + buffer_size; + + // allocate working area, memory args and data buffer + struct working_area *helper; + int ret = target_alloc_working_area(target, target_code_size, &helper); + if (ret) { + LOG_ERROR("DW SPI could not allocate working area. Need %zx", + total_working_area_size); + goto err_helper; + } + + struct working_area *helper_args; + ret = target_alloc_working_area(target, sizeof(struct dw_spi_program), + &helper_args); + if (ret) { + LOG_ERROR("DW SPI could not allocate working area. Need %zx", + total_working_area_size); + goto err_helper_args; + } + + struct working_area *target_buffer; + ret = target_alloc_working_area(target, buffer_size, &target_buffer); + if (ret) { + LOG_ERROR("DW SPI could not allocate working area. Need %zx", + total_working_area_size); + goto err_target_buffer; + } + + // write algorithm code and buffer to working areas + ret = target_write_buffer(target, helper->address, target_code_size, + target_code); + if (ret) { + LOG_ERROR("DW SPI writing to working area error"); + goto err_write_buffer; + } + + ret = target_write_buffer(target, target_buffer->address, buffer_size, + buffer); + if (ret) { + LOG_ERROR("DW SPI writing to working area error"); + goto err_write_buffer; + } + + // prepare helper execution + struct mips32_algorithm mips32_algo = { .common_magic = MIPS32_COMMON_MAGIC, + .isa_mode = MIPS32_ISA_MIPS32 }; + + struct reg_param reg_param; + init_reg_param(®_param, DW_SPI_ARG_REG, 32, PARAM_OUT); + struct mem_param mem_param; + init_mem_param(&mem_param, helper_args->address, helper_args->size, + PARAM_OUT); + + // Set the arguments for the helper + buf_set_u32(reg_param.value, 0, 32, helper_args->address); + struct dw_spi_program *helper_args_val = + (struct dw_spi_program *)mem_param.value; + target_buffer_set_u32(target, (uint8_t *)&helper_args_val->address, + address); + target_buffer_set_u32(target, (uint8_t *)&helper_args_val->page_size, + page_size); + target_buffer_set_u32(target, (uint8_t *)&helper_args_val->buffer, + target_buffer->address); + target_buffer_set_u32(target, (uint8_t *)&helper_args_val->buffer_size, + buffer_size); + target_buffer_set_u32(target, (uint8_t *)&helper_args_val->status_reg, + regmap->simc + DW_SPI_REG_SR); + target_buffer_set_u32(target, (uint8_t *)&helper_args_val->data_reg, + regmap->simc + DW_SPI_REG_DR); + helper_args_val->read_status_cmd = stat_cmd; + helper_args_val->write_enable_cmd = we_cmd; + helper_args_val->program_cmd = program_cmd; + helper_args_val->write_enable_mask = we_mask; + helper_args_val->busy_mask = busy_mask; + helper_args_val->four_byte_mode = driver->four_byte_mode; + + ret = target_run_algorithm(target, 1, &mem_param, 1, ®_param, + helper->address, 0, driver->timeout, + &mips32_algo); + if (ret) + LOG_ERROR("DW SPI flash algorithm error"); + + destroy_reg_param(®_param); + destroy_mem_param(&mem_param); + +err_write_buffer: + target_free_working_area(target, target_buffer); +err_target_buffer: + target_free_working_area(target, helper_args); +err_helper_args: + target_free_working_area(target, helper); +err_helper: + + return ret; +} + +/** + * @brief Erase sectors. + * + * @param[in] bank: Flash bank. + * @param[in] address: Flash address. Must be sector aligned. + * @param[in] sector_size: Size of flash sector. + * @param[in] sector_count: Number of sectors to erase. + * @param[in] stat_cmd: Flash command to read chip status. + * @param[in] we_cmd: Flash command to set enable write. + * @param[in] erase_sector_cmd: Flash command to set erase sector. + * @param[in] we_mask: Status byte write enable mask. + * @param[in] busy_mask: Status byte write busy mask. + * @return Command execution status. + */ +static int +dw_spi_ctrl_erase_sectors(const struct flash_bank *const bank, uint32_t address, + uint32_t sector_size, size_t sector_count, + uint8_t stat_cmd, uint8_t we_cmd, + uint8_t erase_sector_cmd, uint8_t we_mask, + uint8_t busy_mask) +{ + struct target *const target = bank->target; + const struct dw_spi_driver *const driver = bank->driver_priv; + const struct dw_spi_regmap *const regmap = &driver->regmap; + + static const uint8_t target_code[] = { +#include "../../../contrib/loaders/flash/dw-spi/mipsel-linux-gnu-erase.inc" + }; + const size_t target_code_size = sizeof(target_code); + const size_t total_working_area_size = + target_code_size + sizeof(struct dw_spi_erase); + + // allocate working area and memory args + struct working_area *helper; + int ret = target_alloc_working_area(target, target_code_size, &helper); + if (ret) { + LOG_ERROR("DW SPI could not allocate working area. Need %zx", + total_working_area_size); + goto err_helper; + } + + struct working_area *helper_args; + ret = target_alloc_working_area(target, sizeof(struct dw_spi_erase), + &helper_args); + if (ret) { + LOG_ERROR("DW SPI could not allocate working area. Need %zx", + total_working_area_size); + goto err_helper_args; + } + + // write algorithm code to working area + ret = target_write_buffer(target, helper->address, target_code_size, + target_code); + if (ret) { + LOG_ERROR("DW SPI writing to working area error"); + goto err_write_buffer; + } + + // prepare helper execution + struct mips32_algorithm mips32_algo = { .common_magic = MIPS32_COMMON_MAGIC, + .isa_mode = MIPS32_ISA_MIPS32 }; + + struct reg_param reg_param; + init_reg_param(®_param, DW_SPI_ARG_REG, 32, PARAM_OUT); + struct mem_param mem_param; + init_mem_param(&mem_param, helper_args->address, helper_args->size, + PARAM_OUT); + + // Set the arguments for the helper + buf_set_u32(reg_param.value, 0, 32, helper_args->address); + struct dw_spi_erase *helper_args_val = + (struct dw_spi_erase *)mem_param.value; + target_buffer_set_u32(target, (uint8_t *)&helper_args_val->address, + address); + target_buffer_set_u32(target, (uint8_t *)&helper_args_val->sector_size, + sector_size); + target_buffer_set_u32(target, (uint8_t *)&helper_args_val->sector_count, + sector_count); + target_buffer_set_u32(target, (uint8_t *)&helper_args_val->status_reg, + regmap->simc + DW_SPI_REG_SR); + target_buffer_set_u32(target, (uint8_t *)&helper_args_val->data_reg, + regmap->simc + DW_SPI_REG_DR); + helper_args_val->read_status_cmd = stat_cmd; + helper_args_val->write_enable_cmd = we_cmd; + helper_args_val->erase_sector_cmd = erase_sector_cmd; + helper_args_val->write_enable_mask = we_mask; + helper_args_val->busy_mask = busy_mask; + helper_args_val->four_byte_mode = driver->four_byte_mode; + + ret = target_run_algorithm(target, 1, &mem_param, 1, ®_param, + helper->address, 0, driver->timeout, + &mips32_algo); + if (ret) + LOG_ERROR("DW SPI flash algorithm error"); + + destroy_reg_param(®_param); + destroy_mem_param(&mem_param); + +err_write_buffer: + target_free_working_area(target, helper_args); +err_helper_args: + target_free_working_area(target, helper); +err_helper: + + return ret; +} + +/** + * @brief Read flash data. + * + * @param[in] bank: Flash bank. + * @param[in] address: Flash address. + * @param[out] buffer: Data buffer. + * @param[in] buffer_size: \p buffer size. + * @param[in] read_cmd: Flash command to read data from flash. + * @return Command execution status. + */ +static int +dw_spi_ctrl_read(const struct flash_bank *const bank, uint32_t address, + uint8_t *buffer, size_t buffer_size, uint8_t read_cmd) +{ + struct target *const target = bank->target; + const struct dw_spi_driver *const driver = bank->driver_priv; + const struct dw_spi_regmap *const regmap = &driver->regmap; + + static const uint8_t target_code[] = { +#include "../../../contrib/loaders/flash/dw-spi/mipsel-linux-gnu-read.inc" + }; + const size_t target_code_size = sizeof(target_code); + const size_t total_working_area_size = + target_code_size + sizeof(struct dw_spi_read) + buffer_size; + + // allocate working area and memory args + struct working_area *helper; + int ret = target_alloc_working_area(target, target_code_size, &helper); + if (ret) { + LOG_ERROR("DW SPI could not allocate working area. Need %zx", + total_working_area_size); + goto err_helper; + } + + struct working_area *helper_args; + ret = target_alloc_working_area(target, sizeof(struct dw_spi_read), + &helper_args); + if (ret) { + LOG_ERROR("DW SPI could not allocate working area. Need %zx", + total_working_area_size); + goto err_helper_args; + } + + struct working_area *target_buffer; + ret = target_alloc_working_area(target, buffer_size, &target_buffer); + if (ret) { + LOG_ERROR("DW SPI could not allocate working area. Need %zx", + total_working_area_size); + goto err_target_buffer; + } + + // write algorithm code to working area + ret = target_write_buffer(target, helper->address, target_code_size, + target_code); + if (ret) { + LOG_ERROR("DW SPI writing to working area error"); + goto err_write_buffer; + } + + // prepare helper execution + struct mips32_algorithm mips32_algo = { .common_magic = MIPS32_COMMON_MAGIC, + .isa_mode = MIPS32_ISA_MIPS32 }; + + struct reg_param reg_param; + init_reg_param(®_param, DW_SPI_ARG_REG, 32, PARAM_OUT); + struct mem_param mem_param; + init_mem_param(&mem_param, helper_args->address, helper_args->size, + PARAM_OUT); + + // Set the arguments for the helper + buf_set_u32(reg_param.value, 0, 32, helper_args->address); + struct dw_spi_read *helper_args_val = (struct dw_spi_read *)mem_param.value; + target_buffer_set_u32(target, (uint8_t *)&helper_args_val->address, + address); + target_buffer_set_u32(target, (uint8_t *)&helper_args_val->buffer, + target_buffer->address); + target_buffer_set_u32(target, (uint8_t *)&helper_args_val->buffer_size, + buffer_size); + target_buffer_set_u32(target, (uint8_t *)&helper_args_val->status_reg, + regmap->simc + DW_SPI_REG_SR); + target_buffer_set_u32(target, (uint8_t *)&helper_args_val->data_reg, + regmap->simc + DW_SPI_REG_DR); + helper_args_val->read_cmd = read_cmd; + helper_args_val->four_byte_mode = driver->four_byte_mode; + + ret = target_run_algorithm(target, 1, &mem_param, 1, ®_param, + helper->address, 0, driver->timeout, + &mips32_algo); + if (ret) { + LOG_ERROR("DW SPI flash algorithm error"); + goto cleanup; + } + + ret = + target_read_buffer(target, target_buffer->address, buffer_size, buffer); + if (ret) + LOG_ERROR("DW SPI target buffer read error"); + +cleanup: + destroy_reg_param(®_param); + destroy_mem_param(&mem_param); + +err_write_buffer: + target_free_working_area(target, target_buffer); +err_target_buffer: + target_free_working_area(target, helper_args); +err_helper_args: + target_free_working_area(target, helper); +err_helper: + + return ret; +} + +/** + * @brief Read Flash device ID. + * + * @param[in] bank: Flash bank handle. + * @return Command execution status. + */ +static int +dw_spi_read_id(const struct flash_bank *const bank) +{ + struct dw_spi_driver *const driver = bank->driver_priv; + + const size_t buffer_size = 1 + 3 + 1; + uint8_t buffer[buffer_size]; + + memset(buffer, 0, buffer_size); + buffer[0] = SPIFLASH_READ_ID; + + int ret = dw_spi_ctrl_transaction(bank, buffer, buffer_size, true); + if (ret) { + LOG_ERROR("DW SPI flash ID read error"); + return ret; + } + + buffer[buffer_size - 1] = 0; + // use le_to_h_u32 to decode flash ID as per JEDEC SFDP + driver->id = le_to_h_u32(buffer + 1); + LOG_DEBUG("DW SPI read flash ID %" PRIx32, driver->id); + + return ERROR_OK; +} + +/** + * @brief Read Flash device status. + * + * @param[in] bank: Flash bank handle. + * @param[out] status: The status byte. + * @return Command execution status. + */ +static int +dw_spi_read_status(const struct flash_bank *const bank, uint8_t *const status) +{ + const int buffer_size = 2; + uint8_t buffer[buffer_size]; + + memset(buffer, 0, buffer_size); + buffer[0] = SPIFLASH_READ_STATUS; + + int ret = dw_spi_ctrl_transaction(bank, buffer, buffer_size, true); + if (ret) { + LOG_ERROR("DW SPI flash status read error"); + return ret; + } + + *status = buffer[1]; + + return ERROR_OK; +} + +/** + * @brief Wait for Flash command to finish. + * + * @param[in] bank: Flash bank handle. + * @param[in] timeout: The timeout in ms. + * @return Command execution status. + */ +static int +dw_spi_wait_finish(const struct flash_bank *const bank, unsigned int timeout) +{ + const int64_t end_time = timeval_ms() + timeout; + while (timeval_ms() <= end_time) { + uint8_t status; + int ret = dw_spi_read_status(bank, &status); + if (ret) { + LOG_ERROR("DW SPI status query error"); + return ret; + } + if (!(status & SPIFLASH_BSY_BIT)) + return ERROR_OK; + + alive_sleep(1); + } + + LOG_ERROR("DW SPI process timeout"); + return ERROR_TIMEOUT_REACHED; +} + +/** + * @brief Flash device write enable. + * + * @param[in] bank: Flash bank handle. + * @return Command execution status. + */ +static int +dw_spi_write_enable(const struct flash_bank *const bank) +{ + const int buffer_size = 1; + uint8_t buffer[buffer_size]; + + memset(buffer, 0, buffer_size); + buffer[0] = SPIFLASH_WRITE_ENABLE; + + int ret = dw_spi_ctrl_transaction(bank, buffer, buffer_size, false); + if (ret) { + LOG_ERROR("DW SPI flash write enable error"); + return ret; + } + + uint8_t status; + ret = dw_spi_read_status(bank, &status); + if (ret) + return ret; + + return status & SPIFLASH_WE_BIT ? ERROR_OK : ERROR_FAIL; +} + +/** + * @brief Erase Flash chip. + * + * @param[in] bank: Flash bank handle. + * @return Command execution status. + */ +static int +dw_spi_erase_chip(const struct flash_bank *const bank) +{ + const struct dw_spi_driver *const driver = bank->driver_priv; + + const int buffer_size = 1; + uint8_t buffer[buffer_size]; + + int ret = dw_spi_write_enable(bank); + if (ret) + return ret; + + memset(buffer, 0, buffer_size); + buffer[0] = driver->spi_flash->chip_erase_cmd; + + ret = dw_spi_ctrl_transaction(bank, buffer, buffer_size, false); + if (ret) { + LOG_ERROR("DW SPI erase flash error"); + return ret; + } + + ret = dw_spi_wait_finish(bank, driver->timeout); + if (ret) { + LOG_ERROR("DW SPI erase flash timeout"); + return ret; + } + + return ERROR_OK; +} + +/** + * @brief Flash device erase sectors. + * + * @param[in] bank: Flash bank handle. + * @param[in] first: The first sector to erase. + * @param[in] last: The last sector to erase. + * @return Command execution status. + */ +static int +dw_spi_erase_sectors(const struct flash_bank *const bank, unsigned int first, + unsigned int last) +{ + const struct dw_spi_driver *const driver = bank->driver_priv; + + if (first == 0 && last >= (bank->num_sectors - 1)) { + // full erase + int ret = dw_spi_erase_chip(bank); + if (ret) + return ret; + } else { + // partial erase + int ret = dw_spi_ctrl_erase_sectors(bank, bank->sectors[first].offset, + driver->spi_flash->sectorsize, + last - first + 1, + SPIFLASH_READ_STATUS, + SPIFLASH_WRITE_ENABLE, + driver->spi_flash->erase_cmd, + SPIFLASH_WE_BIT, SPIFLASH_BSY_BIT); + if (ret) { + LOG_ERROR("DW SPI flash erase sectors error"); + return ret; + } + } + + return ERROR_OK; +} + +/** + * @brief Flash bank blank check. + */ +static int +dw_spi_blank_check(struct flash_bank *bank, size_t sector_count, + uint8_t pattern) +{ + const struct dw_spi_driver *const driver = bank->driver_priv; + + uint8_t *erased = malloc(sector_count); + if (!erased) { + LOG_ERROR("could not allocate memory"); + return ERROR_FAIL; + } + + // set initial erased value to unknown + memset(erased, 2, sector_count); + for (unsigned int sector_idx = 0; sector_idx < sector_count; sector_idx++) + bank->sectors[sector_idx].is_erased = 2; + + int ret = dw_spi_ctrl_check_sectors_fill(bank, 0, bank->sectors[0].size, + sector_count, pattern, + driver->spi_flash->read_cmd, + erased); + if (!ret) { + for (unsigned int sector_idx = 0; sector_idx < sector_count; + sector_idx++) + bank->sectors[sector_idx].is_erased = erased[sector_idx]; + } else { + LOG_ERROR("DW SPI flash erase check error"); + } + + free(erased); + + return ret; +} + +/** + * @brief Write buffer to Flash. + * + * @param[in] bank: Flash bank handle. + * @param[in] buffer: Data buffer. + * @param[in] offset: Flash address offset. + * @param[in] count: \p buffer size. + * @return Command execution status. + */ +static int +dw_spi_write_buffer(const struct flash_bank *const bank, const uint8_t *buffer, + uint32_t offset, uint32_t count) +{ + const struct dw_spi_driver *const driver = bank->driver_priv; + const size_t page_size = driver->spi_flash->pagesize; + + // Write unaligned first sector separately as helper function does + // not handle this case well. + struct { + uint32_t address; + const uint8_t *buffer; + size_t count; + } chunks[2] = { + { .address = offset, .buffer = buffer, .count = 0 }, + { .address = offset, .buffer = buffer, .count = count }, + }; + + if (offset % page_size) { + // start is not aligned + chunks[0].count = MIN(page_size - (offset % page_size), count); + chunks[1].count -= chunks[0].count; + chunks[1].address += chunks[0].count; + chunks[1].buffer += chunks[0].count; + } + + for (unsigned int chunk_idx = 0; chunk_idx < ARRAY_SIZE(chunks); + chunk_idx++) { + if (chunks[chunk_idx].count > 0) { + int ret = dw_spi_ctrl_program(bank, chunks[chunk_idx].address, + chunks[chunk_idx].buffer, + chunks[chunk_idx].count, page_size, + SPIFLASH_READ_STATUS, + SPIFLASH_WRITE_ENABLE, + driver->spi_flash->pprog_cmd, + SPIFLASH_WE_BIT, SPIFLASH_BSY_BIT); + if (ret) { + LOG_ERROR("DW SPI flash write error"); + return ret; + } + } + } + + return ERROR_OK; +} + +/** + * @brief Search for Flash chip info. + * + * @param[in] bank: Flash bank handle. + * @return Command execution status. + */ +static int +dw_spi_spiflash_search(const struct flash_bank *const bank) +{ + struct dw_spi_driver *const driver = bank->driver_priv; + + int ret = dw_spi_read_id(bank); + if (ret) + return ret; + + unsigned int idx = 0; + while (flash_devices[idx].name) { + if (flash_devices[idx].device_id == driver->id) { + driver->spi_flash = &flash_devices[idx]; + return ERROR_OK; + } + idx++; + } + + LOG_ERROR("DW SPI could not find Flash with ID %" PRIx32 + " in SPI Flash table: either Flash device is not supported " + "or communication speed is too high", + driver->id); + return ERROR_FAIL; +} + +/** + * @brief Handle flash bank command. + * + * @param[in] CMD_ARGC: Number of arguments. + * @param[in] CMD_ARGV: Command arguments. + * @return Command execution status. + */ +FLASH_BANK_COMMAND_HANDLER(dw_spi_flash_bank_command) +{ + unsigned int speed = 1000000; + unsigned int timeout = DW_SPI_TIMEOUT_DEFAULT; + uint8_t chip_select_bitmask = BIT(0); + struct dw_spi_regmap regmap = { 0 }; + + if (CMD_ARGC < 6) + return ERROR_COMMAND_SYNTAX_ERROR; + + for (unsigned int idx = 6; idx < CMD_ARGC; idx++) { + if (strcmp(CMD_ARGV[idx], "-jaguar2") == 0) { + // Fast config for Jaguar2 chips. + memcpy(®map, &jaguar2_regmap, sizeof(jaguar2_regmap)); + } else if (strcmp(CMD_ARGV[idx], "-ocelot") == 0) { + // Fast config for Ocelot chips. + memcpy(®map, &ocelot_regmap, sizeof(ocelot_regmap)); + } else if (strcmp(CMD_ARGV[idx], "-freq") == 0) { + COMMAND_PARSE_NUMBER(u32, CMD_ARGV[++idx], regmap.freq); + } else if (strcmp(CMD_ARGV[idx], "-simc") == 0) { + COMMAND_PARSE_NUMBER(target_addr, CMD_ARGV[++idx], regmap.simc); + } else if (strcmp(CMD_ARGV[idx], "-spi_mst") == 0) { + COMMAND_PARSE_NUMBER(target_addr, CMD_ARGV[++idx], regmap.spi_mst); + } else if (strcmp(CMD_ARGV[idx], "-if_owner_offset") == 0) { + COMMAND_PARSE_NUMBER(u8, CMD_ARGV[++idx], + regmap.si_if_owner_offset); + } else if (strcmp(CMD_ARGV[idx], "-speed") == 0) { + COMMAND_PARSE_NUMBER(uint, CMD_ARGV[++idx], speed); + } else if (strcmp(CMD_ARGV[idx], "-timeout") == 0) { + COMMAND_PARSE_NUMBER(uint, CMD_ARGV[++idx], timeout); + timeout *= 1000; // convert to ms + } else if (strcmp(CMD_ARGV[idx], "-chip_select") == 0) { + unsigned int cs_bit; + COMMAND_PARSE_NUMBER(uint, CMD_ARGV[++idx], cs_bit); + chip_select_bitmask = BIT(cs_bit); + } else { + LOG_WARNING("DW SPI unknown argument %s", CMD_ARGV[idx]); + } + } + + if (!regmap.simc) { + LOG_ERROR("DW SPI cannot use boot controller with unconfigured simc"); + return ERROR_COMMAND_SYNTAX_ERROR; + } + + bank->driver_priv = malloc(sizeof(struct dw_spi_driver)); + if (!bank->driver_priv) { + LOG_ERROR("could not allocate memory"); + return ERROR_FAIL; + } + + struct dw_spi_driver *driver = bank->driver_priv; + memset(driver, 0, sizeof(struct dw_spi_driver)); + driver->speed = speed; + driver->timeout = timeout; + driver->chip_select_bitmask = chip_select_bitmask; + driver->four_byte_mode = true; // 24bit commands not provided by spi.h + memcpy(&driver->regmap, ®map, sizeof(regmap)); + + return ERROR_OK; +} + +/** + * @brief Assert target is halted. + * + * @param[in] bank: Flash bank handle. + * @return Command execution status. + */ +static int +dw_spi_assert_halted(const struct flash_bank *const bank) +{ + if (bank->target->state != TARGET_HALTED) { + LOG_ERROR("target not halted"); + return ERROR_TARGET_NOT_HALTED; + } + return ERROR_OK; +} + +/** + * @brief Prepare master controller for transaction. + * + * @param[in] bank: Flash bank handle. + * @return Command execution status. + */ +static int +dw_spi_master_ctrl_configure(struct flash_bank *bank) +{ + int ret = dw_spi_assert_halted(bank); + if (ret) + return ret; + ret = dw_spi_ctrl_mode_configure(bank, DW_SPI_SI_MODE_MASTER); + if (ret) { + LOG_ERROR("DW SPI switch to master controller mode error"); + return ret; + } + ret = dw_spi_master_ctrl_enable(bank, false); + if (ret) { + LOG_ERROR("DW SPI disable master controller error"); + return ret; + } + ret = dw_spi_ctrl_configure_speed(bank); + if (ret) { + LOG_ERROR("DW SPI speed configuration error"); + return ret; + } + ret = dw_spi_ctrl_disable_interrupts(bank); + if (ret) { + LOG_ERROR("DW SPI disable SPI interrupts error"); + return ret; + } + ret = dw_spi_ctrl_configure_si(bank); + if (ret) { + LOG_ERROR("DW SPI controller configuration error"); + return ret; + } + ret = dw_spi_master_ctrl_enable(bank, true); + if (ret) { + LOG_ERROR("DW SPI enable master controller error"); + return ret; + } + + return ERROR_OK; +} + +/** + * @brief Restore SI controller selection. + * + * @param[in] bank: Flash bank handle. + * @return Command execution status. + */ +static int +dw_spi_master_ctrl_restore(struct flash_bank *bank) +{ + int ret = dw_spi_master_ctrl_enable(bank, false); + if (ret) { + LOG_ERROR("DW SPI disable master controller error"); + return ret; + } + ret = dw_spi_ctrl_mode_restore(bank); + if (ret) { + LOG_ERROR("DW SPI controller restore error"); + return ret; + } + + return ret; +} + +/** + * @brief Flash bank probe. + * + * @param[in] bank: Flash bank handle. + * @return Command execution status. + */ +static int +dw_spi_probe(struct flash_bank *bank) +{ + struct dw_spi_driver *const driver = bank->driver_priv; + + if (!driver) + return ERROR_FAIL; + + if (strcmp(bank->target->type->name, mips_m4k_target.name) != 0 || + bank->target->endianness != TARGET_LITTLE_ENDIAN) { + LOG_ERROR("DW SPI currently only supports " + "little endian mips_m4k target"); + return ERROR_TARGET_INVALID; + } + + int ret = dw_spi_master_ctrl_configure(bank); + if (ret) + return ret; + + ret = dw_spi_spiflash_search(bank); + if (ret) + goto err; + + bank->write_start_alignment = 0; + bank->write_end_alignment = 0; + + uint32_t flash_size = driver->spi_flash->size_in_bytes; + if (!bank->size) { + bank->size = flash_size; + LOG_INFO("DW SPI probed flash size 0x%" PRIx32, flash_size); + } else { + if (flash_size > bank->size) + LOG_WARNING("DW SPI probed flash size 0x%" PRIx32 + " is greater then declared 0x%" PRIx32, + flash_size, bank->size); + if (flash_size < bank->size) { + LOG_ERROR("DW SPI probed flash size 0x%" PRIx32 + " is smaller then declared 0x%" PRIx32, + flash_size, bank->size); + ret = ERROR_FLASH_BANK_INVALID; + goto err; + } + } + bank->num_sectors = bank->size / driver->spi_flash->sectorsize; + + // free previously allocated in case of reprobing + free(bank->sectors); + + bank->sectors = + alloc_block_array(0, driver->spi_flash->sectorsize, bank->num_sectors); + + if (!bank->sectors) { + LOG_ERROR("could not allocate memory"); + ret = ERROR_FAIL; + goto err; + } + + driver->probed = true; + +err: + dw_spi_master_ctrl_restore(bank); + return ret; +} + +/** + * @brief Flash bank erase sectors. + * + * @param[in] bank: Flash bank handle. + * @param[in] first: The first sector to erase. + * @param[in] last: The last sector to erase. + * @return Command execution status. + */ +static int +dw_spi_erase(struct flash_bank *bank, unsigned int first, unsigned int last) +{ + int ret = dw_spi_master_ctrl_configure(bank); + if (ret) + return ret; + + ret = dw_spi_erase_sectors(bank, first, last); + dw_spi_master_ctrl_restore(bank); + return ret; +} + +/** + * @brief Flash bank write data. + * + * @param[in] bank: Flash bank handle. + * @param[in] buffer: Data buffer. + * @param[in] offset: Flash address offset. + * @param[in] count: \p buffer size. + * @return Command execution status. + */ +static int +dw_spi_write(struct flash_bank *bank, const uint8_t *buffer, uint32_t offset, + uint32_t count) +{ + int ret = dw_spi_master_ctrl_configure(bank); + if (ret) + return ret; + + ret = dw_spi_write_buffer(bank, buffer, offset, count); + dw_spi_master_ctrl_restore(bank); + return ret; +} + +/** + * @brief Flash bank read data using master controller. + * + * @param[in] bank: Flash bank handle. + * @param[out] buffer: Data buffer. + * @param[in] offset: Flash address offset. + * @param[in] count: \p buffer size. + * @return Command execution status. + */ +static int +dw_spi_read(struct flash_bank *bank, uint8_t *buffer, uint32_t offset, + uint32_t count) +{ + struct dw_spi_driver *const driver = bank->driver_priv; + + int ret = dw_spi_master_ctrl_configure(bank); + if (ret) + return ret; + + ret = dw_spi_ctrl_read(bank, offset, buffer, count, + driver->spi_flash->read_cmd); + dw_spi_master_ctrl_restore(bank); + return ret; +} + +/** + * @brief Flash bank erase check. + * + * @param[in] bank: Flash bank handle. + * @return Command execution status. + */ +static int +dw_spi_erase_check(struct flash_bank *bank) +{ + int ret = dw_spi_master_ctrl_configure(bank); + if (ret) + return ret; + + ret = dw_spi_blank_check(bank, bank->num_sectors, bank->erased_value); + + dw_spi_master_ctrl_restore(bank); + return ret; +} + +/** + * @brief Flash bank info. + * + * @param[in] bank: Flash bank handle. + * @param[in,out] cmd Command invocation. + * @return Command execution status. + */ +static int +dw_spi_info(struct flash_bank *bank, struct command_invocation *cmd) +{ + const struct dw_spi_driver *const driver = bank->driver_priv; + command_print(cmd, "model %s", driver->spi_flash->name); + command_print(cmd, "ID 0x%" PRIx32, driver->id); + command_print_sameline(cmd, "size 0x%" PRIx32, bank->size); + return ERROR_OK; +} + +/** + * @brief Autoprobe driver. + * + * @param[in] bank: Flash bank handle. + * @return Command execution status. + */ +static int +dw_spi_auto_probe(struct flash_bank *bank) +{ + struct dw_spi_driver *driver = bank->driver_priv; + if (!driver) + return ERROR_FAIL; + if (!driver->probed) + return dw_spi_probe(bank); + return ERROR_OK; +} + +/** + * @brief DW-SPI NOR flash functions. + */ +const struct flash_driver dw_spi_flash = { + .name = "dw-spi", + .flash_bank_command = dw_spi_flash_bank_command, + .erase = dw_spi_erase, + .write = dw_spi_write, + .read = dw_spi_read, + .probe = dw_spi_probe, + .auto_probe = dw_spi_auto_probe, + .erase_check = dw_spi_erase_check, + .info = dw_spi_info, + .verify = default_flash_verify, + .free_driver_priv = default_flash_free_driver_priv, +}; diff --git a/src/flash/nor/em357.c b/src/flash/nor/em357.c index 043494c..207346f 100644 --- a/src/flash/nor/em357.c +++ b/src/flash/nor/em357.c @@ -709,7 +709,7 @@ static int em357_probe(struct flash_bank *bank) em357_info->ppage_size = 4; - LOG_INFO("flash size = %d KiB", num_pages*page_size/1024); + LOG_INFO("flash size = %d KiB", num_pages * page_size / 1024); free(bank->sectors); diff --git a/src/flash/nor/fespi.c b/src/flash/nor/fespi.c index 9191764..395722c 100644 --- a/src/flash/nor/fespi.c +++ b/src/flash/nor/fespi.c @@ -531,7 +531,7 @@ static int fespi_write(struct flash_bank *bank, const uint8_t *buffer, bin_size = sizeof(riscv64_bin); } - unsigned data_wa_size = 0; + unsigned int data_wa_size = 0; if (target_alloc_working_area(target, bin_size, &algorithm_wa) == ERROR_OK) { retval = target_write_buffer(target, algorithm_wa->address, bin_size, bin); @@ -751,9 +751,9 @@ static int fespi_probe(struct flash_bank *bank) target_device->name, bank->base); } else { - LOG_DEBUG("Assuming FESPI as specified at address " TARGET_ADDR_FMT - " with ctrl at " TARGET_ADDR_FMT, fespi_info->ctrl_base, - bank->base); + LOG_DEBUG("Assuming FESPI as specified at address " TARGET_ADDR_FMT + " with ctrl at " TARGET_ADDR_FMT, fespi_info->ctrl_base, + bank->base); } /* read and decode flash ID; returns in SW mode */ diff --git a/src/flash/nor/fm4.c b/src/flash/nor/fm4.c index 979ae84..2db79ef 100644 --- a/src/flash/nor/fm4.c +++ b/src/flash/nor/fm4.c @@ -107,7 +107,7 @@ static int fm4_flash_erase(struct flash_bank *bank, unsigned int first, struct working_area *workarea; struct reg_param reg_params[4]; struct armv7m_algorithm armv7m_algo; - unsigned i; + unsigned int i; int retval; const uint8_t erase_sector_code[] = { #include "../../../contrib/loaders/flash/fm4/erase.inc" @@ -207,7 +207,7 @@ static int fm4_flash_write(struct flash_bank *bank, const uint8_t *buffer, struct armv7m_algorithm armv7m_algo; uint32_t halfword_count = DIV_ROUND_UP(byte_count, 2); uint32_t result; - unsigned i; + unsigned int i; int retval, retval2 = ERROR_OK; const uint8_t write_block_code[] = { #include "../../../contrib/loaders/flash/fm4/write.inc" diff --git a/src/flash/nor/kinetis.c b/src/flash/nor/kinetis.c index fee3644..85c306b 100644 --- a/src/flash/nor/kinetis.c +++ b/src/flash/nor/kinetis.c @@ -256,7 +256,7 @@ struct kinetis_flash_bank { struct kinetis_chip *k_chip; bool probed; - unsigned bank_number; /* bank number in particular chip */ + unsigned int bank_number; /* bank number in particular chip */ struct flash_bank *bank; uint32_t sector_size; @@ -285,9 +285,9 @@ struct kinetis_chip { uint32_t fcfg2_maxaddr0_shifted; uint32_t fcfg2_maxaddr1_shifted; - unsigned num_pflash_blocks, num_nvm_blocks; - unsigned pflash_sector_size, nvm_sector_size; - unsigned max_flash_prog_size; + unsigned int num_pflash_blocks, num_nvm_blocks; + unsigned int pflash_sector_size, nvm_sector_size; + unsigned int max_flash_prog_size; uint32_t pflash_base; uint32_t pflash_size; @@ -337,7 +337,7 @@ struct kinetis_chip { char name[40]; - unsigned num_banks; + unsigned int num_banks; struct kinetis_flash_bank banks[KINETIS_MAX_BANKS]; }; @@ -425,7 +425,7 @@ static int kinetis_probe_chip_s32k(struct kinetis_chip *k_chip); static int kinetis_auto_probe(struct flash_bank *bank); -static int kinetis_mdm_write_register(struct adiv5_dap *dap, unsigned reg, uint32_t value) +static int kinetis_mdm_write_register(struct adiv5_dap *dap, unsigned int reg, uint32_t value) { LOG_DEBUG("MDM_REG[0x%02x] <- %08" PRIX32, reg, value); @@ -453,7 +453,7 @@ static int kinetis_mdm_write_register(struct adiv5_dap *dap, unsigned reg, uint3 return ERROR_OK; } -static int kinetis_mdm_read_register(struct adiv5_dap *dap, unsigned reg, uint32_t *result) +static int kinetis_mdm_read_register(struct adiv5_dap *dap, unsigned int reg, uint32_t *result) { struct adiv5_ap *ap = dap_get_ap(dap, MDM_AP); if (!ap) { @@ -479,7 +479,7 @@ static int kinetis_mdm_read_register(struct adiv5_dap *dap, unsigned reg, uint32 return ERROR_OK; } -static int kinetis_mdm_poll_register(struct adiv5_dap *dap, unsigned reg, +static int kinetis_mdm_poll_register(struct adiv5_dap *dap, unsigned int reg, uint32_t mask, uint32_t value, uint32_t timeout_ms) { uint32_t val; @@ -977,7 +977,7 @@ static void kinetis_free_driver_priv(struct flash_bank *bank) static int kinetis_create_missing_banks(struct kinetis_chip *k_chip) { - unsigned num_blocks; + unsigned int num_blocks; struct kinetis_flash_bank *k_bank; struct flash_bank *bank; char base_name[69], name[87], num[11]; @@ -1038,6 +1038,7 @@ static int kinetis_create_missing_banks(struct kinetis_chip *k_chip) bank->target = k_chip->target; bank->driver = &kinetis_flash; bank->default_padded_value = bank->erased_value = 0xff; + bank->minimal_write_gap = FLASH_WRITE_GAP_SECTOR; snprintf(name, sizeof(name), "%s.%s%s", base_name, class, num); @@ -1462,7 +1463,7 @@ static int kinetis_fill_fcf(struct flash_bank *bank, uint8_t *fcf) uint32_t fprot = 0xffffffff; uint8_t fsec = 0xfe; /* set MCU unsecure */ uint8_t fdprot = 0xff; - unsigned num_blocks; + unsigned int num_blocks; uint32_t pflash_bit; uint8_t dflash_bit; struct flash_bank *bank_iter; @@ -1488,7 +1489,22 @@ static int kinetis_fill_fcf(struct flash_bank *bank, uint8_t *fcf) kinetis_auto_probe(bank_iter); - assert(bank_iter->prot_blocks); + if (bank_iter->num_prot_blocks == 0) { + if (k_bank->flash_class == FC_PFLASH) { + LOG_ERROR("BUG: PFLASH bank %u has no protection blocks", + bank_idx); + } else { + LOG_DEBUG("skipping FLEX_NVM bank %u with no prot blocks (EE bkp only)", + bank_idx); + } + continue; + } + + if (!bank_iter->prot_blocks) { + LOG_ERROR("BUG: bank %u has NULL protection blocks array", + bank_idx); + continue; + } if (k_bank->flash_class == FC_PFLASH) { for (unsigned int i = 0; i < bank_iter->num_prot_blocks; i++) { @@ -2268,12 +2284,12 @@ static int kinetis_probe_chip(struct kinetis_chip *k_chip) uint32_t ee_size = 0; uint32_t pflash_size_k, nvm_size_k, dflash_size_k; uint32_t pflash_size_m; - unsigned num_blocks = 0; - unsigned maxaddr_shift = 13; + unsigned int num_blocks = 0; + unsigned int maxaddr_shift = 13; struct target *target = k_chip->target; - unsigned familyid = 0, subfamid = 0; - unsigned cpu_mhz = 120; + unsigned int familyid = 0, subfamid = 0; + unsigned int cpu_mhz = 120; bool use_nvm_marking = false; char flash_marking[12], nvm_marking[2]; char name[40]; @@ -2894,7 +2910,7 @@ static int kinetis_probe(struct flash_bank *bank) { int result; uint8_t fcfg2_maxaddr0, fcfg2_pflsh, fcfg2_maxaddr1; - unsigned num_blocks, first_nvm_bank; + unsigned int num_blocks, first_nvm_bank; uint32_t size_k; struct kinetis_flash_bank *k_bank = bank->driver_priv; struct kinetis_chip *k_chip; @@ -2939,7 +2955,7 @@ static int kinetis_probe(struct flash_bank *bank) } else if (k_bank->bank_number < num_blocks) { /* nvm, banks start at address 0x10000000 */ - unsigned nvm_ord = k_bank->bank_number - first_nvm_bank; + unsigned int nvm_ord = k_bank->bank_number - first_nvm_bank; uint32_t limit; k_bank->flash_class = FC_FLEX_NVM; @@ -3138,8 +3154,8 @@ static int kinetis_blank_check(struct flash_bank *bank) COMMAND_HANDLER(kinetis_nvm_partition) { int result; - unsigned bank_idx; - unsigned num_blocks, first_nvm_bank; + unsigned int bank_idx; + unsigned int num_blocks, first_nvm_bank; unsigned long par, log2 = 0, ee1 = 0, ee2 = 0; enum { SHOW_INFO, DF_SIZE, EEBKP_SIZE } sz_type = SHOW_INFO; bool enable; diff --git a/src/flash/nor/kinetis_ke.c b/src/flash/nor/kinetis_ke.c index c069f3a..8207504 100644 --- a/src/flash/nor/kinetis_ke.c +++ b/src/flash/nor/kinetis_ke.c @@ -134,7 +134,7 @@ struct kinetis_ke_flash_bank { #define MDM_ACCESS_TIMEOUT 3000 /* iterations */ -static int kinetis_ke_mdm_write_register(struct adiv5_dap *dap, unsigned reg, uint32_t value) +static int kinetis_ke_mdm_write_register(struct adiv5_dap *dap, unsigned int reg, uint32_t value) { LOG_DEBUG("MDM_REG[0x%02x] <- %08" PRIX32, reg, value); @@ -161,7 +161,7 @@ static int kinetis_ke_mdm_write_register(struct adiv5_dap *dap, unsigned reg, ui return ERROR_OK; } -static int kinetis_ke_mdm_read_register(struct adiv5_dap *dap, unsigned reg, uint32_t *result) +static int kinetis_ke_mdm_read_register(struct adiv5_dap *dap, unsigned int reg, uint32_t *result) { struct adiv5_ap *ap = dap_get_ap(dap, 1); if (!ap) { @@ -187,7 +187,7 @@ static int kinetis_ke_mdm_read_register(struct adiv5_dap *dap, unsigned reg, uin return ERROR_OK; } -static int kinetis_ke_mdm_poll_register(struct adiv5_dap *dap, unsigned reg, uint32_t mask, uint32_t value) +static int kinetis_ke_mdm_poll_register(struct adiv5_dap *dap, unsigned int reg, uint32_t mask, uint32_t value) { uint32_t val; int retval; @@ -1005,7 +1005,7 @@ static int kinetis_ke_write(struct flash_bank *bank, const uint8_t *buffer, result = kinetis_ke_stop_watchdog(bank->target); if (result != ERROR_OK) - return result; + return result; result = kinetis_ke_prepare_flash(bank); if (result != ERROR_OK) diff --git a/src/flash/nor/lpc2000.c b/src/flash/nor/lpc2000.c index f12eef7..09d35f6 100644 --- a/src/flash/nor/lpc2000.c +++ b/src/flash/nor/lpc2000.c @@ -272,7 +272,7 @@ #define LPC11XX_REG_SECTORS 24 -typedef enum { +enum lpc2000_variant { LPC2000_V1, LPC2000_V2, LPC1700, @@ -282,10 +282,10 @@ typedef enum { LPC1500, LPC54100, LPC_AUTO, -} lpc2000_variant; +}; struct lpc2000_flash_bank { - lpc2000_variant variant; + enum lpc2000_variant variant; uint32_t cclk; int cmd51_dst_boundary; int calc_checksum; diff --git a/src/flash/nor/max32xxx.c b/src/flash/nor/max32xxx.c index 59a14af..267fd43 100644 --- a/src/flash/nor/max32xxx.c +++ b/src/flash/nor/max32xxx.c @@ -202,14 +202,14 @@ static int max32xxx_protect_check(struct flash_bank *bank) return ERROR_FLASH_BANK_NOT_PROBED; if (!info->max326xx) { - for (unsigned i = 0; i < bank->num_sectors; i++) + for (unsigned int i = 0; i < bank->num_sectors; i++) bank->sectors[i].is_protected = -1; return ERROR_FLASH_OPER_UNSUPPORTED; } /* Check the protection */ - for (unsigned i = 0; i < bank->num_sectors; i++) { + for (unsigned int i = 0; i < bank->num_sectors; i++) { if (i%32 == 0) target_read_u32(target, info->flc_base + FLSH_PROT + ((i/32)*4), &temp_reg); @@ -360,7 +360,7 @@ static int max32xxx_write_block(struct flash_bank *bank, const uint8_t *buffer, struct armv7m_algorithm armv7m_info; int retval = ERROR_OK; /* power of two, and multiple of word size */ - static const unsigned buf_min = 128; + static const unsigned int buf_min = 128; /* for small buffers it's faster not to download an algorithm */ if (wcount * 4 < buf_min) @@ -388,8 +388,8 @@ static int max32xxx_write_block(struct flash_bank *bank, const uint8_t *buffer, return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; } - LOG_DEBUG("retry target_alloc_working_area(%s, size=%u)", - target_name(target), (unsigned) buffer_size); + LOG_DEBUG("retry target_alloc_working_area(%s, size=%" PRIu32 ")", + target_name(target), buffer_size); } target_write_buffer(target, write_algorithm->address, sizeof(write_code), @@ -903,7 +903,7 @@ COMMAND_HANDLER(max32xxx_handle_protection_check_command) } LOG_WARNING("s:<sector number> a:<address> p:<protection bit>"); - for (unsigned i = 0; i < bank->num_sectors; i += 4) { + for (unsigned int i = 0; i < bank->num_sectors; i += 4) { LOG_WARNING("s:%03d a:0x%06x p:%d | s:%03d a:0x%06x p:%d | s:%03d a:0x%06x p:%d | s:%03d a:0x%06x p:%d", (i+0), (i+0)*info->sector_size, bank->sectors[(i+0)].is_protected, (i+1), (i+1)*info->sector_size, bank->sectors[(i+1)].is_protected, 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/niietcm4.c b/src/flash/nor/niietcm4.c index 0c36e2c..aaf0726 100644 --- a/src/flash/nor/niietcm4.c +++ b/src/flash/nor/niietcm4.c @@ -311,7 +311,7 @@ static int niietcm4_uflash_page_erase(struct flash_bank *bank, int page_num, int /* status check */ retval = niietcm4_uopstatus_check(bank); if (retval != ERROR_OK) - return retval; + return retval; return retval; } @@ -394,7 +394,7 @@ COMMAND_HANDLER(niietcm4_handle_uflash_read_byte_command) uint32_t uflash_data; if (strcmp("info", CMD_ARGV[0]) == 0) - uflash_cmd = UFMC_MAGIC_KEY | UFMC_READ_IFB; + uflash_cmd = UFMC_MAGIC_KEY | UFMC_READ_IFB; else if (strcmp("main", CMD_ARGV[0]) == 0) uflash_cmd = UFMC_MAGIC_KEY | UFMC_READ; else @@ -539,7 +539,7 @@ COMMAND_HANDLER(niietcm4_handle_uflash_erase_command) int mem_type; if (strcmp("info", CMD_ARGV[0]) == 0) - mem_type = 1; + mem_type = 1; else if (strcmp("main", CMD_ARGV[0]) == 0) mem_type = 0; else diff --git a/src/flash/nor/nrf5.c b/src/flash/nor/nrf5.c index f07433e..5cb552a 100644 --- a/src/flash/nor/nrf5.c +++ b/src/flash/nor/nrf5.c @@ -117,20 +117,24 @@ struct nrf5_map { struct nrf5_info { unsigned int refcount; + bool chip_probed; struct nrf5_bank { struct nrf5_info *chip; bool probed; } bank[2]; + struct target *target; - /* chip identification stored in nrf5_probe() for use in nrf5_info() */ + /* chip identification stored in nrf5_probe_chip() + * for use in nrf5_info() and nrf5_setup_bank() */ bool ficr_info_valid; struct nrf52_ficr_info ficr_info; const struct nrf5_device_spec *spec; uint16_t hwid; enum nrf5_features features; - unsigned int flash_size_kb; + uint32_t flash_page_size; + uint32_t flash_num_sectors; unsigned int ram_size_kb; const struct nrf5_map *map; @@ -341,16 +345,19 @@ const struct flash_driver nrf5_flash, nrf51_flash; static bool nrf5_bank_is_probed(const struct flash_bank *bank) { struct nrf5_bank *nbank = bank->driver_priv; - assert(nbank); - return nbank->probed; } -static bool nrf5_bank_is_uicr(const struct nrf5_bank *nbank) +static bool nrf5_chip_is_probed(const struct flash_bank *bank) { + struct nrf5_bank *nbank = bank->driver_priv; struct nrf5_info *chip = nbank->chip; - assert(chip); + return chip->chip_probed; +} +static bool nrf5_bank_is_uicr(const struct nrf5_bank *nbank) +{ + struct nrf5_info *chip = nbank->chip; return nbank == &chip->bank[1]; } @@ -470,9 +477,7 @@ static int nrf51_protect_check_clenr0(struct flash_bank *bank) uint32_t clenr0; struct nrf5_bank *nbank = bank->driver_priv; - assert(nbank); struct nrf5_info *chip = nbank->chip; - assert(chip); res = target_read_u32(chip->target, NRF51_FICR_CLENR0, &clenr0); @@ -501,9 +506,7 @@ static int nrf51_protect_check_clenr0(struct flash_bank *bank) static int nrf52_protect_check_bprot(struct flash_bank *bank) { struct nrf5_bank *nbank = bank->driver_priv; - assert(nbank); struct nrf5_info *chip = nbank->chip; - assert(chip); static uint32_t nrf5_bprot_offsets[4] = { 0x600, 0x604, 0x610, 0x614 }; uint32_t bprot_reg = 0; @@ -528,9 +531,7 @@ static int nrf52_protect_check_bprot(struct flash_bank *bank) static int nrf5_protect_check(struct flash_bank *bank) { struct nrf5_bank *nbank = bank->driver_priv; - assert(nbank); struct nrf5_info *chip = nbank->chip; - assert(chip); /* UICR cannot be write protected so just return early */ if (nrf5_bank_is_uicr(nbank)) @@ -554,9 +555,7 @@ static int nrf51_protect_clenr0(struct flash_bank *bank, int set, unsigned int f uint32_t clenr0, ppfc; struct nrf5_bank *nbank = bank->driver_priv; - assert(nbank); struct nrf5_info *chip = nbank->chip; - assert(chip); if (first != 0) { LOG_ERROR("Code region 0 must start at the beginning of the bank"); @@ -614,9 +613,7 @@ static int nrf5_protect(struct flash_bank *bank, int set, unsigned int first, unsigned int last) { struct nrf5_bank *nbank = bank->driver_priv; - assert(nbank); struct nrf5_info *chip = nbank->chip; - assert(chip); /* UICR cannot be write protected so just bail out early */ if (nrf5_bank_is_uicr(nbank)) { @@ -701,16 +698,15 @@ static int nrf5_get_chip_type_str(const struct nrf5_info *chip, char *buf, unsig static int nrf5_info(struct flash_bank *bank, struct command_invocation *cmd) { struct nrf5_bank *nbank = bank->driver_priv; - assert(nbank); struct nrf5_info *chip = nbank->chip; - assert(chip); char chip_type_str[256]; if (nrf5_get_chip_type_str(chip, chip_type_str, sizeof(chip_type_str)) != ERROR_OK) return ERROR_FAIL; + unsigned int flash_size_kb = chip->flash_num_sectors * chip->flash_page_size / 1024; command_print_sameline(cmd, "%s %ukB Flash, %ukB RAM", - chip_type_str, chip->flash_size_kb, chip->ram_size_kb); + chip_type_str, flash_size_kb, chip->ram_size_kb); return ERROR_OK; } @@ -838,14 +834,12 @@ static int nrf51_get_ram_size(struct target *target, uint32_t *ram_size) return res; } -static int nrf5_probe(struct flash_bank *bank) +static int nrf5_probe_chip(struct flash_bank *bank) { int res = ERROR_TARGET_RESOURCE_NOT_AVAILABLE; struct nrf5_bank *nbank = bank->driver_priv; - assert(nbank); struct nrf5_info *chip = nbank->chip; - assert(chip); struct target *target = chip->target; chip->spec = NULL; @@ -968,9 +962,8 @@ static int nrf5_probe(struct flash_bank *bank) } /* The value stored in FICR CODEPAGESIZE is the number of bytes in one page of FLASH. */ - uint32_t flash_page_size; res = target_read_u32(chip->target, ficr_base + ficr_offsets->codepagesize, - &flash_page_size); + &chip->flash_page_size); if (res != ERROR_OK) { LOG_ERROR("Couldn't read code page size"); return res; @@ -978,69 +971,93 @@ static int nrf5_probe(struct flash_bank *bank) /* Note the register name is misleading, * FICR CODESIZE is the number of pages in flash memory, not the number of bytes! */ - uint32_t num_sectors; res = target_read_u32(chip->target, ficr_base + ficr_offsets->codesize, - &num_sectors); + &chip->flash_num_sectors); if (res != ERROR_OK) { LOG_ERROR("Couldn't read code memory size"); return res; } - chip->flash_size_kb = num_sectors * flash_page_size / 1024; + char chip_type_str[256]; + if (nrf5_get_chip_type_str(chip, chip_type_str, sizeof(chip_type_str)) != ERROR_OK) + return ERROR_FAIL; - if (!chip->bank[0].probed && !chip->bank[1].probed) { - char chip_type_str[256]; - if (nrf5_get_chip_type_str(chip, chip_type_str, sizeof(chip_type_str)) != ERROR_OK) - return ERROR_FAIL; - const bool device_is_unknown = (!chip->spec && !chip->ficr_info_valid); - LOG_INFO("%s%s %ukB Flash, %ukB RAM", - device_is_unknown ? "Unknown device: " : "", - chip_type_str, - chip->flash_size_kb, - chip->ram_size_kb); - } + unsigned int flash_size_kb = chip->flash_num_sectors * chip->flash_page_size / 1024; + const bool device_is_unknown = (!chip->spec && !chip->ficr_info_valid); + LOG_INFO("%s%s %ukB Flash, %ukB RAM", + device_is_unknown ? "Unknown device: " : "", + chip_type_str, + flash_size_kb, + chip->ram_size_kb); - free(bank->sectors); + chip->chip_probed = true; + return ERROR_OK; +} + +static int nrf5_setup_bank(struct flash_bank *bank) +{ + struct nrf5_bank *nbank = bank->driver_priv; + struct nrf5_info *chip = nbank->chip; if (bank->base == chip->map->flash_base) { + unsigned int flash_size_kb = chip->flash_num_sectors * chip->flash_page_size / 1024; /* Sanity check */ - if (chip->spec && chip->flash_size_kb != chip->spec->flash_size_kb) + if (chip->spec && flash_size_kb != chip->spec->flash_size_kb) LOG_WARNING("Chip's reported Flash capacity does not match expected one"); - if (chip->ficr_info_valid && chip->flash_size_kb != chip->ficr_info.flash) + if (chip->ficr_info_valid && flash_size_kb != chip->ficr_info.flash) LOG_WARNING("Chip's reported Flash capacity does not match FICR INFO.FLASH"); - bank->num_sectors = num_sectors; - bank->size = num_sectors * flash_page_size; + bank->num_sectors = chip->flash_num_sectors; + bank->size = chip->flash_num_sectors * chip->flash_page_size; - bank->sectors = alloc_block_array(0, flash_page_size, num_sectors); + bank->sectors = alloc_block_array(0, chip->flash_page_size, bank->num_sectors); if (!bank->sectors) return ERROR_FAIL; chip->bank[0].probed = true; - } else { + } else if (bank->base == chip->map->uicr_base) { /* UICR bank */ bank->num_sectors = 1; - bank->size = flash_page_size; + bank->size = chip->flash_page_size; - bank->sectors = alloc_block_array(0, flash_page_size, num_sectors); + bank->sectors = alloc_block_array(0, chip->flash_page_size, bank->num_sectors); if (!bank->sectors) return ERROR_FAIL; bank->sectors[0].is_protected = 0; chip->bank[1].probed = true; + } else { + LOG_ERROR("Invalid nRF bank address " TARGET_ADDR_FMT, bank->base); + return ERROR_FLASH_BANK_INVALID; } return ERROR_OK; } +static int nrf5_probe(struct flash_bank *bank) +{ + /* probe always reads actual info from the device */ + int res = nrf5_probe_chip(bank); + if (res != ERROR_OK) + return res; + + return nrf5_setup_bank(bank); +} + static int nrf5_auto_probe(struct flash_bank *bank) { if (nrf5_bank_is_probed(bank)) return ERROR_OK; - return nrf5_probe(bank); + if (!nrf5_chip_is_probed(bank)) { + int res = nrf5_probe_chip(bank); + if (res != ERROR_OK) + return res; + } + + return nrf5_setup_bank(bank); } @@ -1214,9 +1231,7 @@ static int nrf5_write(struct flash_bank *bank, const uint8_t *buffer, } struct nrf5_bank *nbank = bank->driver_priv; - assert(nbank); struct nrf5_info *chip = nbank->chip; - assert(chip); assert(offset % 4 == 0); assert(count % 4 == 0); @@ -1276,9 +1291,7 @@ static int nrf5_erase(struct flash_bank *bank, unsigned int first, } struct nrf5_bank *nbank = bank->driver_priv; - assert(nbank); struct nrf5_info *chip = nbank->chip; - assert(chip); /* UICR CLENR0 based protection used on nRF51 prevents erase * absolutely silently. NVMC has no flag to indicate the protection @@ -1322,7 +1335,6 @@ error: static void nrf5_free_driver_priv(struct flash_bank *bank) { struct nrf5_bank *nbank = bank->driver_priv; - assert(nbank); struct nrf5_info *chip = nbank->chip; if (!chip) return; @@ -1372,8 +1384,8 @@ FLASH_BANK_COMMAND_HANDLER(nrf5_flash_bank_command) case NRF53NET_UICR_BASE: break; default: - LOG_ERROR("Invalid bank address " TARGET_ADDR_FMT, bank->base); - return ERROR_FAIL; + LOG_ERROR("Invalid nRF bank address " TARGET_ADDR_FMT, bank->base); + return ERROR_FLASH_BANK_INVALID; } chip = nrf5_get_chip(bank->target); @@ -1418,17 +1430,13 @@ COMMAND_HANDLER(nrf5_handle_mass_erase_command) if (res != ERROR_OK) return res; - assert(bank); - if (target->state != TARGET_HALTED) { LOG_ERROR("Target not halted"); return ERROR_TARGET_NOT_HALTED; } struct nrf5_bank *nbank = bank->driver_priv; - assert(nbank); struct nrf5_info *chip = nbank->chip; - assert(chip); if (chip->features & NRF5_FEATURE_SERIES_51) { uint32_t ppfc; diff --git a/src/flash/nor/ocl.c b/src/flash/nor/ocl.c index e00c365..61af908 100644 --- a/src/flash/nor/ocl.c +++ b/src/flash/nor/ocl.c @@ -160,7 +160,7 @@ static int ocl_write(struct flash_bank *bank, const uint8_t *buffer, uint32_t of retval = embeddedice_send(ocl->jtag_info, dcc_buffer, dcc_bufptr-dcc_buffer); if (retval != ERROR_OK) { free(dcc_buffer); - return retval; + return retval; } /* wait for response, fixed timeout of 1 s */ diff --git a/src/flash/nor/psoc4.c b/src/flash/nor/psoc4.c index 1064fa9..72cf0ee 100644 --- a/src/flash/nor/psoc4.c +++ b/src/flash/nor/psoc4.c @@ -384,15 +384,15 @@ static int psoc4_get_silicon_id(struct flash_bank *bank, uint32_t *silicon_id, u * bit 7..0 family ID (lowest 8 bits) */ if (silicon_id) - *silicon_id = ((part0 & 0x0000ffff) << 16) - | ((part0 & 0x00ff0000) >> 8) - | (part1 & 0x000000ff); + *silicon_id = ((part0 & 0x0000ffff) << 16) + | ((part0 & 0x00ff0000) >> 8) + | (part1 & 0x000000ff); if (family_id) - *family_id = part1 & 0x0fff; + *family_id = part1 & 0x0fff; if (protection) - *protection = (part1 >> 12) & 0x0f; + *protection = (part1 >> 12) & 0x0f; return ERROR_OK; } diff --git a/src/flash/nor/psoc5lp.c b/src/flash/nor/psoc5lp.c index 407efbc..e8c9019 100644 --- a/src/flash/nor/psoc5lp.c +++ b/src/flash/nor/psoc5lp.c @@ -102,10 +102,10 @@ struct psoc5lp_device { uint32_t id; - unsigned fam; - unsigned speed_mhz; - unsigned flash_kb; - unsigned eeprom_kb; + unsigned int fam; + unsigned int speed_mhz; + unsigned int flash_kb; + unsigned int eeprom_kb; }; /* @@ -245,7 +245,7 @@ static int psoc5lp_find_device(struct target *target, const struct psoc5lp_device **device) { uint32_t device_id; - unsigned i; + unsigned int i; int retval; *device = NULL; @@ -381,9 +381,9 @@ static int psoc5lp_spc_load_byte(struct target *target, } static int psoc5lp_spc_load_row(struct target *target, - uint8_t array_id, const uint8_t *data, unsigned row_size) + uint8_t array_id, const uint8_t *data, unsigned int row_size) { - unsigned i; + unsigned int i; int retval; retval = psoc5lp_spc_write_opcode(target, SPC_LOAD_ROW); @@ -853,7 +853,7 @@ static int psoc5lp_eeprom_write(struct flash_bank *bank, { struct target *target = bank->target; uint8_t temp[2]; - unsigned row; + unsigned int row; int retval; if (offset % EEPROM_ROW_SIZE != 0) { @@ -1124,7 +1124,7 @@ static int psoc5lp_write(struct flash_bank *bank, const uint8_t *buffer, struct working_area *code_area, *even_row_area, *odd_row_area; uint32_t row_size; uint8_t temp[2], buf[12], ecc_bytes[ROW_ECC_SIZE]; - unsigned array_id, row; + unsigned int array_id, row; int i, retval; if (offset + byte_count > bank->size) { @@ -1183,7 +1183,7 @@ static int psoc5lp_write(struct flash_bank *bank, const uint8_t *buffer, row < ROWS_PER_BLOCK && byte_count > 0; row++) { bool even_row = (row % 2 == 0); struct working_area *data_area = even_row ? even_row_area : odd_row_area; - unsigned len = MIN(ROW_SIZE, byte_count); + unsigned int len = MIN(ROW_SIZE, byte_count); LOG_DEBUG("Writing load command for array %u row %u at " TARGET_ADDR_FMT, array_id, row, data_area->address); @@ -1307,8 +1307,8 @@ static int psoc5lp_protect_check(struct flash_bank *bank) { struct psoc5lp_flash_bank *psoc_bank = bank->driver_priv; uint8_t row_data[ROW_SIZE]; - const unsigned protection_bytes_per_sector = ROWS_PER_SECTOR * 2 / 8; - unsigned i, k, num_sectors; + const unsigned int protection_bytes_per_sector = ROWS_PER_SECTOR * 2 / 8; + unsigned int i, k, num_sectors; int retval; if (bank->target->state != TARGET_HALTED) { diff --git a/src/flash/nor/psoc6.c b/src/flash/nor/psoc6.c index 859b3e9..662910a 100644 --- a/src/flash/nor/psoc6.c +++ b/src/flash/nor/psoc6.c @@ -223,6 +223,8 @@ static int ipc_poll_lock_stat(struct target *target, uint32_t ipc_id, bool lock_ { int hr; uint32_t reg_val; + struct armv7m_common *armv7m = target_to_armv7m(target); + bool is_cm0 = (armv7m->arm.arch == ARM_ARCH_V6M); struct timeout to; timeout_init(&to, IPC_TIMEOUT_MS); @@ -244,7 +246,7 @@ static int ipc_poll_lock_stat(struct target *target, uint32_t ipc_id, bool lock_ return ERROR_OK; } - if (target->coreid) { + if (!is_cm0) { LOG_WARNING("SROM API calls via CM4 target are supported on single-core PSoC6 devices only. " "Please perform all Flash-related operations via CM0+ target on dual-core devices."); } @@ -485,7 +487,7 @@ static int psoc6_get_info(struct flash_bank *bank, struct command_invocation *cm { struct psoc6_target_info *psoc6_info = bank->driver_priv; - if (psoc6_info->is_probed == false) + if (!psoc6_info->is_probed) return ERROR_FAIL; int hr = get_silicon_id(bank->target, &psoc6_info->silicon_id, &psoc6_info->protection); @@ -886,7 +888,8 @@ static int handle_reset_halt(struct target *target) { int hr; uint32_t reset_addr; - bool is_cm0 = (target->coreid == 0); + struct armv7m_common *armv7m = target_to_armv7m(target); + bool is_cm0 = (armv7m->arm.arch == ARM_ARCH_V6M); /* Halt target device */ if (target->state != TARGET_HALTED) { diff --git a/src/flash/nor/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/sfdp.c b/src/flash/nor/sfdp.c index 5bfb541..8e25ba6 100644 --- a/src/flash/nor/sfdp.c +++ b/src/flash/nor/sfdp.c @@ -12,7 +12,6 @@ #include "spi.h" #include "sfdp.h" -#define SFDP_MAGIC 0x50444653 #define SFDP_ACCESS_PROT 0xFF #define SFDP_BASIC_FLASH 0xFF00 #define SFDP_4BYTE_ADDR 0xFF84 @@ -100,11 +99,11 @@ int spi_sfdp(struct flash_bank *bank, struct flash_device *dev, goto err; for (k = 0; k < nph; k++) { - uint8_t words = (pheaders[k].revision >> 24) & 0xFF; + unsigned int words = (pheaders[k].revision >> 24) & 0xFF; uint16_t id = (((pheaders[k].ptr) >> 16) & 0xFF00) | (pheaders[k].revision & 0xFF); uint32_t ptr = pheaders[k].ptr & 0xFFFFFF; - LOG_DEBUG("pheader %d len=0x%02" PRIx8 " id=0x%04" PRIx16 + LOG_DEBUG("pheader %d len=0x%02x id=0x%04" PRIx16 " ptr=0x%06" PRIx32, k, words, id, ptr); /* retrieve parameter table */ diff --git a/src/flash/nor/sfdp.h b/src/flash/nor/sfdp.h index 1c9af32..0d43519 100644 --- a/src/flash/nor/sfdp.h +++ b/src/flash/nor/sfdp.h @@ -7,6 +7,8 @@ #ifndef OPENOCD_FLASH_NOR_SFDP_H #define OPENOCD_FLASH_NOR_SFDP_H +#define SFDP_MAGIC 0x50444653 + /* per JESD216D 'addr' is *byte* based but must be word aligned, * 'buffer' is word based, word aligned and always little-endian encoded, * in the flash, 'addr_len' is 3 or 4, 'dummy' ***usually*** 8 @@ -16,7 +18,7 @@ * * buffer contents is supposed to be returned in ***host*** endianness */ typedef int (*read_sfdp_block_t)(struct flash_bank *bank, uint32_t addr, - uint32_t words, uint32_t *buffer); + unsigned int words, uint32_t *buffer); extern int spi_sfdp(struct flash_bank *bank, struct flash_device *dev, read_sfdp_block_t read_sfdp_block); diff --git a/src/flash/nor/sim3x.c b/src/flash/nor/sim3x.c index 42550d0..58d7913 100644 --- a/src/flash/nor/sim3x.c +++ b/src/flash/nor/sim3x.c @@ -859,7 +859,7 @@ static int sim3x_flash_info(struct flash_bank *bank, struct command_invocation * * reg 3:2 - register * reg 1:0 - no effect */ -static int ap_write_register(struct adiv5_dap *dap, unsigned reg, uint32_t value) +static int ap_write_register(struct adiv5_dap *dap, unsigned int reg, uint32_t value) { LOG_DEBUG("DAP_REG[0x%02x] <- %08" PRIX32, reg, value); @@ -886,7 +886,7 @@ static int ap_write_register(struct adiv5_dap *dap, unsigned reg, uint32_t value return ERROR_OK; } -static int ap_read_register(struct adiv5_dap *dap, unsigned reg, uint32_t *result) +static int ap_read_register(struct adiv5_dap *dap, unsigned int reg, uint32_t *result) { struct adiv5_ap *ap = dap_get_ap(dap, SIM3X_AP); if (!ap) { @@ -912,7 +912,7 @@ static int ap_read_register(struct adiv5_dap *dap, unsigned reg, uint32_t *resul return ERROR_OK; } -static int ap_poll_register(struct adiv5_dap *dap, unsigned reg, uint32_t mask, uint32_t value, int timeout) +static int ap_poll_register(struct adiv5_dap *dap, unsigned int reg, uint32_t mask, uint32_t value, int timeout) { uint32_t val; int retval; diff --git a/src/flash/nor/stellaris.c b/src/flash/nor/stellaris.c index eab6244..1f53b2f 100644 --- a/src/flash/nor/stellaris.c +++ b/src/flash/nor/stellaris.c @@ -530,7 +530,7 @@ static void stellaris_set_flash_timing(struct flash_bank *bank) target_write_u32(target, SCB_BASE | USECRL, usecrl); } -static const unsigned rcc_xtal[32] = { +static const unsigned int rcc_xtal[32] = { [0x00] = 1000000, /* no pll */ [0x01] = 1843200, /* no pll */ [0x02] = 2000000, /* no pll */ @@ -569,7 +569,7 @@ static void stellaris_read_clock_info(struct flash_bank *bank) struct stellaris_flash_bank *stellaris_info = bank->driver_priv; struct target *target = bank->target; uint32_t rcc, rcc2, pllcfg, sysdiv, usesysdiv, bypass, oscsrc; - unsigned xtal; + unsigned int xtal; unsigned long mainfreq; target_read_u32(target, SCB_BASE | RCC, &rcc); @@ -1029,7 +1029,7 @@ static int stellaris_write_block(struct flash_bank *bank, int retval = ERROR_OK; /* power of two, and multiple of word size */ - static const unsigned buf_min = 128; + static const unsigned int buf_min = 128; /* for small buffers it's faster not to download an algorithm */ if (wcount * 4 < buf_min) @@ -1056,8 +1056,8 @@ static int stellaris_write_block(struct flash_bank *bank, target_free_working_area(target, write_algorithm); return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; } - LOG_DEBUG("retry target_alloc_working_area(%s, size=%u)", - target_name(target), (unsigned) buffer_size); + LOG_DEBUG("retry target_alloc_working_area(%s, size=%" PRIu32 ")", + target_name(target), buffer_size); } target_write_buffer(target, write_algorithm->address, diff --git a/src/flash/nor/stm32l4x.c b/src/flash/nor/stm32l4x.c index 0399385..fa57db8 100644 --- a/src/flash/nor/stm32l4x.c +++ b/src/flash/nor/stm32l4x.c @@ -120,6 +120,18 @@ * http://www.st.com/resource/en/reference_manual/dm00346336.pdf */ +/* STM32U0xxx series for reference. + * + * RM0503 (STM32U0xx) + * https://www.st.com/resource/en/reference_manual/rm0503-stm32u0-series-advanced-armbased-32bit-mcus-stmicroelectronics.pdf + */ + +/* STM32U5xxx series for reference. + * + * RM0456 (STM32U5xx) + * http://www.st.com/resource/en/reference_manual/dm00477635.pdf + */ + /* Erase time can be as high as 25ms, 10x this and assume it's toast... */ #define FLASH_ERASE_TIMEOUT 250 @@ -272,7 +284,7 @@ struct stm32l4_wrp { }; /* human readable list of families this drivers supports (sorted alphabetically) */ -static const char *device_families = "STM32C0/G0/G4/L4/L4+/L5/U5/WB/WL"; +static const char *device_families = "STM32C0/G0/G4/L4/L4+/L5/U0/U5/WB/WL"; static const struct stm32l4_rev stm32l47_l48xx_revs[] = { { 0x1000, "1" }, { 0x1001, "2" }, { 0x1003, "3" }, { 0x1007, "4" } @@ -291,6 +303,10 @@ static const struct stm32l4_rev stm32c03xx_revs[] = { { 0x1000, "A" }, { 0x1001, "Z" }, }; +static const struct stm32l4_rev stm32c071xx_revs[] = { + { 0x1001, "Z" }, +}; + static const struct stm32l4_rev stm32g05_g06xx_revs[] = { { 0x1000, "A" }, }; @@ -319,6 +335,10 @@ static const struct stm32l4_rev stm32g0b_g0cxx_revs[] = { { 0x1000, "A" }, }; +static const struct stm32l4_rev stm32u0xx_revs[] = { + { 0x1000, "A" }, +}; + static const struct stm32l4_rev stm32g43_g44xx_revs[] = { { 0x1000, "A" }, { 0x2000, "B" }, { 0x2001, "Z" }, }; @@ -344,9 +364,21 @@ static const struct stm32l4_rev stm32g49_g4axx_revs[] = { { 0x1000, "A" }, }; +static const struct stm32l4_rev stm32u53_u54xx_revs[] = { + { 0x1000, "A" }, { 0x1001, "Z" }, +}; + static const struct stm32l4_rev stm32u57_u58xx_revs[] = { { 0x1000, "A" }, { 0x1001, "Z" }, { 0x1003, "Y" }, { 0x2000, "B" }, - { 0x2001, "X" }, { 0x3000, "C" }, + { 0x2001, "X" }, { 0x3000, "C" }, { 0x3001, "W" }, { 0x3007, "U" }, +}; + +static const struct stm32l4_rev stm32u59_u5axx_revs[] = { + { 0x3001, "X" }, { 0x3002, "W" }, +}; + +static const struct stm32l4_rev stm32u5f_u5gxx_revs[] = { + { 0x1000, "A" }, { 0x1001, "Z" }, }; static const struct stm32l4_rev stm32wba5x_revs[] = { @@ -419,6 +451,30 @@ static const struct stm32l4_part_info stm32l4_parts[] = { .otp_size = 1024, }, { + .id = DEVID_STM32C071XX, + .revs = stm32c071xx_revs, + .num_revs = ARRAY_SIZE(stm32c071xx_revs), + .device_str = "STM32C071xx", + .max_flash_size_kb = 128, + .flags = F_NONE, + .flash_regs_base = 0x40022000, + .fsize_addr = 0x1FFF75A0, + .otp_base = 0x1FFF7000, + .otp_size = 1024, + }, + { + .id = DEVID_STM32U53_U54XX, + .revs = stm32u53_u54xx_revs, + .num_revs = ARRAY_SIZE(stm32u53_u54xx_revs), + .device_str = "STM32U535/U545", + .max_flash_size_kb = 512, + .flags = F_HAS_DUAL_BANK | F_QUAD_WORD_PROG | F_HAS_TZ | F_HAS_L5_FLASH_REGS, + .flash_regs_base = 0x40022000, + .fsize_addr = 0x0BFA07A0, + .otp_base = 0x0BFA0000, + .otp_size = 512, + }, + { .id = DEVID_STM32G05_G06XX, .revs = stm32g05_g06xx_revs, .num_revs = ARRAY_SIZE(stm32g05_g06xx_revs), @@ -575,6 +631,42 @@ static const struct stm32l4_part_info stm32l4_parts[] = { .otp_size = 1024, }, { + .id = DEVID_STM32U031XX, + .revs = stm32u0xx_revs, + .num_revs = ARRAY_SIZE(stm32u0xx_revs), + .device_str = "STM32U031xx", + .max_flash_size_kb = 64, + .flags = F_NONE, + .flash_regs_base = 0x40022000, + .fsize_addr = 0x1FFF3EA0, + .otp_base = 0x1FFF6800, + .otp_size = 1024, + }, + { + .id = DEVID_STM32U073_U083XX, + .revs = stm32u0xx_revs, + .num_revs = ARRAY_SIZE(stm32u0xx_revs), + .device_str = "STM32U073/U083xx", + .max_flash_size_kb = 256, + .flags = F_NONE, + .flash_regs_base = 0x40022000, + .fsize_addr = 0x1FFF6EA0, + .otp_base = 0x1FFF6800, + .otp_size = 1024, + }, + { + .id = DEVID_STM32U59_U5AXX, + .revs = stm32u59_u5axx_revs, + .num_revs = ARRAY_SIZE(stm32u59_u5axx_revs), + .device_str = "STM32U59/U5Axx", + .max_flash_size_kb = 4096, + .flags = F_HAS_DUAL_BANK | F_QUAD_WORD_PROG | F_HAS_TZ | F_HAS_L5_FLASH_REGS, + .flash_regs_base = 0x40022000, + .fsize_addr = 0x0BFA07A0, + .otp_base = 0x0BFA0000, + .otp_size = 512, + }, + { .id = DEVID_STM32U57_U58XX, .revs = stm32u57_u58xx_revs, .num_revs = ARRAY_SIZE(stm32u57_u58xx_revs), @@ -587,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), @@ -679,7 +783,8 @@ struct range { }; static void bitmap_to_ranges(unsigned long *bitmap, unsigned int nbits, - struct range *ranges, unsigned int *ranges_count) { + struct range *ranges, unsigned int *ranges_count) +{ *ranges_count = 0; bool last_bit = 0, cur_bit; for (unsigned int i = 0; i < nbits; i++) { @@ -1916,8 +2021,11 @@ static int stm32l4_probe(struct flash_bank *bank) case DEVID_STM32L43_L44XX: case DEVID_STM32C01XX: case DEVID_STM32C03XX: + case DEVID_STM32C071XX: case DEVID_STM32G05_G06XX: case DEVID_STM32G07_G08XX: + case DEVID_STM32U031XX: + case DEVID_STM32U073_U083XX: case DEVID_STM32L45_L46XX: case DEVID_STM32L41_L42XX: case DEVID_STM32G03_G04XX: @@ -2000,10 +2108,23 @@ static int stm32l4_probe(struct flash_bank *bank) stm32l4_info->bank1_sectors = num_pages / 2; } break; + case DEVID_STM32U53_U54XX: case DEVID_STM32U57_U58XX: - /* if flash size is max (2M) the device is always dual bank - * otherwise check DUALBANK + case DEVID_STM32U59_U5AXX: + 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 + * 256K and 128K variants can be in DUAL BANK mode if FLASH_OPTR:DUALBANK is set + * U57x/U58x have 2M max flash size: + * 2M variants are always in DUAL BANK mode + * 1M variants can be in DUAL BANK mode if FLASH_OPTR:DUALBANK is set + * U59x/U5Ax/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 */ + page_size_kb = 8; num_pages = flash_size_kb / page_size_kb; stm32l4_info->bank1_sectors = num_pages; @@ -2572,7 +2693,7 @@ static const struct command_registration stm32l4_exec_command_handlers[] = { .name = "option_write", .handler = stm32l4_handle_option_write_command, .mode = COMMAND_EXEC, - .usage = "bank_id reg_offset value mask", + .usage = "bank_id reg_offset value [mask]", .help = "Write device option bit fields with provided value.", }, { diff --git a/src/flash/nor/stm32l4x.h b/src/flash/nor/stm32l4x.h index 3dc0909..3199d4f 100644 --- a/src/flash/nor/stm32l4x.h +++ b/src/flash/nor/stm32l4x.h @@ -89,7 +89,9 @@ #define DEVID_STM32L43_L44XX 0x435 #define DEVID_STM32C01XX 0x443 #define DEVID_STM32C03XX 0x453 +#define DEVID_STM32U53_U54XX 0x455 #define DEVID_STM32G05_G06XX 0x456 +#define DEVID_STM32U031XX 0x459 #define DEVID_STM32G07_G08XX 0x460 #define DEVID_STM32L49_L4AXX 0x461 #define DEVID_STM32L45_L46XX 0x462 @@ -101,9 +103,13 @@ #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 +#define DEVID_STM32U073_U083XX 0x489 #define DEVID_STM32WBA5X 0x492 +#define DEVID_STM32C071XX 0x493 #define DEVID_STM32WB1XX 0x494 #define DEVID_STM32WB5XX 0x495 #define DEVID_STM32WB3XX 0x496 diff --git a/src/flash/nor/stmqspi.c b/src/flash/nor/stmqspi.c index a1e1d34..df58f6c 100644 --- a/src/flash/nor/stmqspi.c +++ b/src/flash/nor/stmqspi.c @@ -1807,7 +1807,7 @@ err: /* Read SFDP parameter block */ static int read_sfdp_block(struct flash_bank *bank, uint32_t addr, - uint32_t words, uint32_t *buffer) + unsigned int words, uint32_t *buffer) { struct target *target = bank->target; struct stmqspi_flash_bank *stmqspi_info = bank->driver_priv; @@ -1848,7 +1848,7 @@ static int read_sfdp_block(struct flash_bank *bank, uint32_t addr, } } - LOG_DEBUG("%s: addr=0x%08" PRIx32 " words=0x%08" PRIx32 " dummy=%u", + LOG_DEBUG("%s: addr=0x%08" PRIx32 " words=0x%08x dummy=%u", __func__, addr, words, *dummy); /* Abort any previous operation */ diff --git a/src/flash/nor/str9xpec.c b/src/flash/nor/str9xpec.c index c39eb3a..eff7df5 100644 --- a/src/flash/nor/str9xpec.c +++ b/src/flash/nor/str9xpec.c @@ -68,7 +68,7 @@ static int str9xpec_erase_area(struct flash_bank *bank, unsigned int first, static int str9xpec_set_address(struct flash_bank *bank, uint8_t sector); static int str9xpec_write_options(struct flash_bank *bank); -static int str9xpec_set_instr(struct jtag_tap *tap, uint32_t new_instr, tap_state_t end_state) +static int str9xpec_set_instr(struct jtag_tap *tap, uint32_t new_instr, enum tap_state end_state) { if (!tap) return ERROR_TARGET_INVALID; diff --git a/src/flash/nor/tcl.c b/src/flash/nor/tcl.c index 15edd1a..a19b1a6 100644 --- a/src/flash/nor/tcl.c +++ b/src/flash/nor/tcl.c @@ -36,7 +36,7 @@ COMMAND_HELPER(flash_command_get_bank_probe_optional, unsigned int name_index, if (*bank) return ERROR_OK; - unsigned bank_num; + unsigned int bank_num; COMMAND_PARSE_NUMBER(uint, name, bank_num); if (do_probe) { @@ -48,7 +48,7 @@ COMMAND_HELPER(flash_command_get_bank_probe_optional, unsigned int name_index, } } -COMMAND_HELPER(flash_command_get_bank, unsigned name_index, +COMMAND_HELPER(flash_command_get_bank, unsigned int name_index, struct flash_bank **bank) { return CALL_COMMAND_HANDLER(flash_command_get_bank_probe_optional, @@ -518,7 +518,7 @@ COMMAND_HANDLER(handle_flash_fill_command) uint64_t pattern; uint32_t count; struct target *target = get_current_target(CMD_CTX); - unsigned i; + unsigned int i; uint32_t wordsize; int retval; @@ -1317,7 +1317,7 @@ COMMAND_HANDLER(handle_flash_banks_command) if (CMD_ARGC != 0) return ERROR_COMMAND_SYNTAX_ERROR; - unsigned n = 0; + unsigned int n = 0; for (struct flash_bank *p = flash_bank_list(); p; p = p->next, n++) { command_print(CMD, "#%d : %s (%s) at " TARGET_ADDR_FMT ", size 0x%8.8" PRIx32 ", " "buswidth %u, chipwidth %u", p->bank_number, diff --git a/src/flash/nor/tms470.c b/src/flash/nor/tms470.c index e01d2df..00ee77b 100644 --- a/src/flash/nor/tms470.c +++ b/src/flash/nor/tms470.c @@ -16,7 +16,7 @@ * ---------------------------------------------------------------------- */ struct tms470_flash_bank { - unsigned ordinal; + unsigned int ordinal; /* device identification register */ uint32_t device_ident_reg; @@ -239,8 +239,8 @@ static int tms470_read_part_info(struct flash_bank *bank) break; default: - LOG_WARNING("Could not identify part 0x%02x as a member of the TMS470 family.", - (unsigned)part_number); + LOG_WARNING("Could not identify part 0x%02" PRIx32 " as a member of the TMS470 family.", + part_number); return ERROR_FLASH_OPERATION_FAILED; } @@ -391,7 +391,7 @@ static int tms470_try_flash_keys(struct target *target, const uint32_t *key_set) /* only perform the key match when 3VSTAT is clear */ target_read_u32(target, 0xFFE8BC0C, &fmmstat); if (!(fmmstat & 0x08)) { - unsigned i; + unsigned int i; uint32_t fmbptr, fmbac2, orig_fmregopt; target_write_u32(target, 0xFFE8BC04, fmmstat & ~0x07); @@ -455,7 +455,7 @@ static int tms470_unlock_flash(struct flash_bank *bank) { struct target *target = bank->target; const uint32_t *p_key_sets[5]; - unsigned i, key_set_count; + unsigned int i, key_set_count; if (keys_set) { key_set_count = 5; diff --git a/src/flash/nor/xcf.c b/src/flash/nor/xcf.c index 1d67b09..4011fa4 100644 --- a/src/flash/nor/xcf.c +++ b/src/flash/nor/xcf.c @@ -143,28 +143,27 @@ static int isc_enter(struct flash_bank *bank) struct xcf_status status = read_status(bank); - if (true == status.isc_mode) + if (status.isc_mode) return ERROR_OK; - else { - struct scan_field scan; - scan.check_mask = NULL; - scan.check_value = NULL; - scan.num_bits = 16; - scan.out_value = cmd_isc_enable; - scan.in_value = NULL; + struct scan_field scan; - jtag_add_ir_scan(bank->target->tap, &scan, TAP_IDLE); - jtag_execute_queue(); + scan.check_mask = NULL; + scan.check_value = NULL; + scan.num_bits = 16; + scan.out_value = cmd_isc_enable; + scan.in_value = NULL; - status = read_status(bank); - if (!status.isc_mode) { - LOG_ERROR("*** XCF: FAILED to enter ISC mode"); - return ERROR_FLASH_OPERATION_FAILED; - } + jtag_add_ir_scan(bank->target->tap, &scan, TAP_IDLE); + jtag_execute_queue(); - return ERROR_OK; + status = read_status(bank); + if (!status.isc_mode) { + LOG_ERROR("*** XCF: FAILED to enter ISC mode"); + return ERROR_FLASH_OPERATION_FAILED; } + + return ERROR_OK; } static int isc_leave(struct flash_bank *bank) @@ -174,27 +173,26 @@ static int isc_leave(struct flash_bank *bank) if (!status.isc_mode) return ERROR_OK; - else { - struct scan_field scan; - - scan.check_mask = NULL; - scan.check_value = NULL; - scan.num_bits = 16; - scan.out_value = cmd_isc_disable; - scan.in_value = NULL; - - jtag_add_ir_scan(bank->target->tap, &scan, TAP_IDLE); - jtag_execute_queue(); - alive_sleep(1); /* device needs 50 uS to leave ISC mode */ - - status = read_status(bank); - if (status.isc_mode) { - LOG_ERROR("*** XCF: FAILED to leave ISC mode"); - return ERROR_FLASH_OPERATION_FAILED; - } - return ERROR_OK; + struct scan_field scan; + + scan.check_mask = NULL; + scan.check_value = NULL; + scan.num_bits = 16; + scan.out_value = cmd_isc_disable; + scan.in_value = NULL; + + jtag_add_ir_scan(bank->target->tap, &scan, TAP_IDLE); + jtag_execute_queue(); + alive_sleep(1); /* device needs 50 uS to leave ISC mode */ + + status = read_status(bank); + if (status.isc_mode) { + LOG_ERROR("*** XCF: FAILED to leave ISC mode"); + return ERROR_FLASH_OPERATION_FAILED; } + + return ERROR_OK; } static int sector_state(uint8_t wrpt, int sector) diff --git a/src/flash/nor/xmc1xxx.c b/src/flash/nor/xmc1xxx.c index 6e30fc1..4aa97a9 100644 --- a/src/flash/nor/xmc1xxx.c +++ b/src/flash/nor/xmc1xxx.c @@ -84,7 +84,7 @@ static int xmc1xxx_erase(struct flash_bank *bank, unsigned int first, struct working_area *workarea; struct reg_param reg_params[3]; struct armv7m_algorithm armv7m_algo; - unsigned i; + unsigned int i; int retval; const uint8_t erase_code[] = { #include "../../../contrib/loaders/flash/xmc1xxx/erase.inc" @@ -159,7 +159,7 @@ static int xmc1xxx_erase_check(struct flash_bank *bank) struct reg_param reg_params[3]; struct armv7m_algorithm armv7m_algo; uint16_t val; - unsigned i; + unsigned int i; int retval; const uint8_t erase_check_code[] = { #include "../../../contrib/loaders/flash/xmc1xxx/erase_check.inc" @@ -245,7 +245,7 @@ static int xmc1xxx_write(struct flash_bank *bank, const uint8_t *buffer, struct reg_param reg_params[4]; struct armv7m_algorithm armv7m_algo; uint32_t block_count = DIV_ROUND_UP(byte_count, NVM_BLOCK_SIZE); - unsigned i; + unsigned int i; int retval; const uint8_t write_code[] = { #include "../../../contrib/loaders/flash/xmc1xxx/write.inc" diff --git a/src/flash/startup.tcl b/src/flash/startup.tcl index 654f201..0dd84ef 100644 --- a/src/flash/startup.tcl +++ b/src/flash/startup.tcl @@ -5,7 +5,7 @@ # # program utility proc # usage: program filename -# optional args: verify, reset, exit and address +# optional args: preverify, verify, reset, exit and address # lappend _telnet_autocomplete_skip program_error @@ -101,8 +101,8 @@ proc program {filename args} { return } -add_help_text program "write an image to flash, address is only required for binary images. verify, reset, exit are optional" -add_usage_text program "<filename> \[address\] \[pre-verify\] \[verify\] \[reset\] \[exit\]" +add_help_text program "write an image to flash, address is only required for binary images. preverify, verify, reset, exit are optional" +add_usage_text program "<filename> \[address\] \[preverify\] \[verify\] \[reset\] \[exit\]" # stm32[f0x|f3x] uses the same flash driver as the stm32f1x proc stm32f0x args { eval stm32f1x $args } diff --git a/src/helper/align.h b/src/helper/align.h index 935a6a3..d717006 100644 --- a/src/helper/align.h +++ b/src/helper/align.h @@ -24,7 +24,7 @@ #define IS_PWR_OF_2(x) \ ({ \ typeof(x) _x = (x); \ - _x == 0 || (_x & (_x - 1)) == 0; \ + _x != 0 && (_x & (_x - 1)) == 0; \ }) #endif /* OPENOCD_HELPER_ALIGN_H */ diff --git a/src/helper/binarybuffer.c b/src/helper/binarybuffer.c index 5f38b43..6fba86a 100644 --- a/src/helper/binarybuffer.c +++ b/src/helper/binarybuffer.c @@ -40,7 +40,7 @@ static const char hex_digits[] = { 'a', 'b', 'c', 'd', 'e', 'f' }; -void *buf_cpy(const void *from, void *_to, unsigned size) +void *buf_cpy(const void *from, void *_to, unsigned int size) { if (!from || !_to) return NULL; @@ -49,7 +49,7 @@ void *buf_cpy(const void *from, void *_to, unsigned size) memcpy(_to, from, DIV_ROUND_UP(size, 8)); /* mask out bits that don't belong to the buffer */ - unsigned trailing_bits = size % 8; + unsigned int trailing_bits = size % 8; if (trailing_bits) { uint8_t *to = _to; to[size / 8] &= (1 << trailing_bits) - 1; @@ -57,53 +57,52 @@ void *buf_cpy(const void *from, void *_to, unsigned size) return _to; } -static bool buf_cmp_masked(uint8_t a, uint8_t b, uint8_t m) +static bool buf_eq_masked(uint8_t a, uint8_t b, uint8_t m) { - return (a & m) != (b & m); + return (a & m) == (b & m); } -static bool buf_cmp_trailing(uint8_t a, uint8_t b, uint8_t m, unsigned trailing) +static bool buf_eq_trailing(uint8_t a, uint8_t b, uint8_t m, unsigned int trailing) { uint8_t mask = (1 << trailing) - 1; - return buf_cmp_masked(a, b, mask & m); + return buf_eq_masked(a, b, mask & m); } -bool buf_cmp(const void *_buf1, const void *_buf2, unsigned size) +bool buf_eq(const void *_buf1, const void *_buf2, unsigned int size) { if (!_buf1 || !_buf2) - return _buf1 != _buf2; + return _buf1 == _buf2; - unsigned last = size / 8; + unsigned int last = size / 8; if (memcmp(_buf1, _buf2, last) != 0) return false; - unsigned trailing = size % 8; + unsigned int trailing = size % 8; if (!trailing) - return false; + return true; const uint8_t *buf1 = _buf1, *buf2 = _buf2; - return buf_cmp_trailing(buf1[last], buf2[last], 0xff, trailing); + return buf_eq_trailing(buf1[last], buf2[last], 0xff, trailing); } -bool buf_cmp_mask(const void *_buf1, const void *_buf2, - const void *_mask, unsigned size) +bool buf_eq_mask(const void *_buf1, const void *_buf2, + const void *_mask, unsigned int size) { if (!_buf1 || !_buf2) - return _buf1 != _buf2 || _buf1 != _mask; + return _buf1 == _buf2 && _buf1 == _mask; const uint8_t *buf1 = _buf1, *buf2 = _buf2, *mask = _mask; - unsigned last = size / 8; - for (unsigned i = 0; i < last; i++) { - if (buf_cmp_masked(buf1[i], buf2[i], mask[i])) - return true; + unsigned int last = size / 8; + for (unsigned int i = 0; i < last; i++) { + if (!buf_eq_masked(buf1[i], buf2[i], mask[i])) + return false; } - unsigned trailing = size % 8; + unsigned int trailing = size % 8; if (!trailing) - return false; - return buf_cmp_trailing(buf1[last], buf2[last], mask[last], trailing); + return true; + return buf_eq_trailing(buf1[last], buf2[last], mask[last], trailing); } - -void *buf_set_ones(void *_buf, unsigned size) +void *buf_set_ones(void *_buf, unsigned int size) { uint8_t *buf = _buf; if (!buf) @@ -111,19 +110,19 @@ void *buf_set_ones(void *_buf, unsigned size) memset(buf, 0xff, size / 8); - unsigned trailing_bits = size % 8; + unsigned int trailing_bits = size % 8; if (trailing_bits) buf[size / 8] = (1 << trailing_bits) - 1; return buf; } -void *buf_set_buf(const void *_src, unsigned src_start, - void *_dst, unsigned dst_start, unsigned len) +void *buf_set_buf(const void *_src, unsigned int src_start, + void *_dst, unsigned int dst_start, unsigned int len) { const uint8_t *src = _src; uint8_t *dst = _dst; - unsigned i, sb, db, sq, dq, lb, lq; + unsigned int i, sb, db, sq, dq, lb, lq; sb = src_start / 8; db = dst_start / 8; @@ -176,26 +175,13 @@ uint32_t flip_u32(uint32_t value, unsigned int num) return c; } -static int ceil_f_to_u32(float x) +char *buf_to_hex_str(const void *_buf, unsigned int buf_len) { - if (x < 0) /* return zero for negative numbers */ - return 0; - - uint32_t y = x; /* cut off fraction */ - - if ((x - y) > 0.0) /* if there was a fractional part, increase by one */ - y++; - - return y; -} - -char *buf_to_hex_str(const void *_buf, unsigned buf_len) -{ - unsigned len_bytes = DIV_ROUND_UP(buf_len, 8); + unsigned int len_bytes = DIV_ROUND_UP(buf_len, 8); char *str = calloc(len_bytes * 2 + 1, 1); const uint8_t *buf = _buf; - for (unsigned i = 0; i < len_bytes; i++) { + for (unsigned int i = 0; i < len_bytes; i++) { uint8_t tmp = buf[len_bytes - i - 1]; if ((i == 0) && (buf_len % 8)) tmp &= (0xff >> (8 - (buf_len % 8))); @@ -206,94 +192,96 @@ char *buf_to_hex_str(const void *_buf, unsigned buf_len) return str; } -/** identify radix, and skip radix-prefix (0, 0x or 0X) */ -static void str_radix_guess(const char **_str, unsigned *_str_len, - unsigned *_radix) +/* + * TCL standard prefix is '0b', '0o', '0d' or '0x' respectively for binary, + * octal, decimal or hexadecimal. + * The prefix '0' is interpreted by TCL <= 8.6 as octal, but is ignored and + * interpreted as part of a decimal number by JimTCL and by TCL >= 9. + */ +int str_to_buf(const char *str, void *_buf, unsigned int buf_bitsize) { - unsigned radix = *_radix; - if (radix != 0) - return; - const char *str = *_str; - unsigned str_len = *_str_len; - if (str[0] == '0' && (str[1] == 'x' || str[1] == 'X')) { - radix = 16; - str += 2; - str_len -= 2; - } else if ((str[0] == '0') && (str_len != 1)) { - radix = 8; - str += 1; - str_len -= 1; - } else - radix = 10; - *_str = str; - *_str_len = str_len; - *_radix = radix; -} + assert(str); + assert(_buf); + assert(buf_bitsize > 0); -int str_to_buf(const char *str, unsigned str_len, - void *_buf, unsigned buf_len, unsigned radix) -{ - str_radix_guess(&str, &str_len, &radix); - - float factor; - if (radix == 16) - factor = 0.5; /* log(16) / log(256) = 0.5 */ - else if (radix == 10) - factor = 0.41524; /* log(10) / log(256) = 0.41524 */ - else if (radix == 8) - factor = 0.375; /* log(8) / log(256) = 0.375 */ - else - return 0; + uint8_t *buf = _buf; + unsigned int radix = 10; /* default when no prefix */ + + if (str[0] == '0') { + switch (str[1]) { + case 'b': + case 'B': + radix = 2; + str += 2; + break; + case 'o': + case 'O': + radix = 8; + str += 2; + break; + case 'd': + case 'D': + radix = 10; + str += 2; + break; + case 'x': + case 'X': + radix = 16; + str += 2; + break; + default: + break; + } + } - /* copy to zero-terminated buffer */ - char *charbuf = strndup(str, str_len); - - /* number of digits in base-256 notation */ - unsigned b256_len = ceil_f_to_u32(str_len * factor); - uint8_t *b256_buf = calloc(b256_len, 1); - - /* go through zero terminated buffer - * input digits (ASCII) */ - unsigned i; - for (i = 0; charbuf[i]; i++) { - uint32_t tmp = charbuf[i]; - if ((tmp >= '0') && (tmp <= '9')) - tmp = (tmp - '0'); - else if ((tmp >= 'a') && (tmp <= 'f')) - tmp = (tmp - 'a' + 10); - else if ((tmp >= 'A') && (tmp <= 'F')) - tmp = (tmp - 'A' + 10); - else - continue; /* skip characters other than [0-9,a-f,A-F] */ + const size_t str_len = strlen(str); + if (str_len == 0) + return ERROR_INVALID_NUMBER; + + const size_t buf_len = DIV_ROUND_UP(buf_bitsize, 8); + memset(buf, 0, buf_len); + + /* Go through the zero-terminated buffer + * of input digits (ASCII) */ + for (; *str; str++) { + unsigned int tmp; + const char c = *str; + + if ((c >= '0') && (c <= '9')) { + tmp = c - '0'; + } else if ((c >= 'a') && (c <= 'f')) { + tmp = c - 'a' + 10; + } else if ((c >= 'A') && (c <= 'F')) { + tmp = c - 'A' + 10; + } else { + /* Characters other than [0-9,a-f,A-F] are invalid */ + return ERROR_INVALID_NUMBER; + } + /* Error on invalid digit for current radix */ if (tmp >= radix) - continue; /* skip digits invalid for the current radix */ + return ERROR_INVALID_NUMBER; - /* base-256 digits */ - for (unsigned j = 0; j < b256_len; j++) { - tmp += (uint32_t)b256_buf[j] * radix; - b256_buf[j] = (uint8_t)(tmp & 0xFF); + /* Add the current digit (tmp) to the intermediate result in buf */ + for (unsigned int j = 0; j < buf_len; j++) { + tmp += buf[j] * radix; + buf[j] = tmp & 0xFFu; tmp >>= 8; } + /* buf should be large enough to contain the whole result. */ + if (tmp != 0) + return ERROR_NUMBER_EXCEEDS_BUFFER; } - uint8_t *buf = _buf; - for (unsigned j = 0; j < DIV_ROUND_UP(buf_len, 8); j++) { - if (j < b256_len) - buf[j] = b256_buf[j]; - else - buf[j] = 0; + /* Check the partial most significant byte */ + if (buf_bitsize % 8) { + const uint8_t mask = 0xFFu << (buf_bitsize % 8); + if ((buf[buf_len - 1] & mask) != 0x0) + return ERROR_NUMBER_EXCEEDS_BUFFER; } - /* mask out bits that don't belong to the buffer */ - if (buf_len % 8) - buf[(buf_len / 8)] &= 0xff >> (8 - (buf_len % 8)); - - free(b256_buf); - free(charbuf); - - return i; + return ERROR_OK; } void bit_copy_queue_init(struct bit_copy_queue *q) @@ -301,8 +289,8 @@ void bit_copy_queue_init(struct bit_copy_queue *q) INIT_LIST_HEAD(&q->list); } -int bit_copy_queued(struct bit_copy_queue *q, uint8_t *dst, unsigned dst_offset, const uint8_t *src, - unsigned src_offset, unsigned bit_count) +int bit_copy_queued(struct bit_copy_queue *q, uint8_t *dst, unsigned int dst_offset, const uint8_t *src, + unsigned int src_offset, unsigned int bit_count) { struct bit_copy_queue_entry *qe = malloc(sizeof(*qe)); if (!qe) @@ -407,12 +395,12 @@ size_t hexify(char *hex, const uint8_t *bin, size_t count, size_t length) return i; } -void buffer_shr(void *_buf, unsigned buf_len, unsigned count) +void buffer_shr(void *_buf, unsigned int buf_len, unsigned int count) { - unsigned i; + unsigned int i; unsigned char *buf = _buf; - unsigned bytes_to_remove; - unsigned shift; + unsigned int bytes_to_remove; + unsigned int shift; bytes_to_remove = count / 8; shift = count - (bytes_to_remove * 8); diff --git a/src/helper/binarybuffer.h b/src/helper/binarybuffer.h index 3446296..9913279 100644 --- a/src/helper/binarybuffer.h +++ b/src/helper/binarybuffer.h @@ -14,6 +14,9 @@ #include <helper/list.h> #include <helper/types.h> +#define ERROR_INVALID_NUMBER (-1700) +#define ERROR_NUMBER_EXCEEDS_BUFFER (-1701) + /** @file * Support functions to access arbitrary bits in a byte array */ @@ -29,8 +32,9 @@ * @param value Up to 32 bits that will be copied to _buffer. */ static inline void buf_set_u32(uint8_t *_buffer, - unsigned first, unsigned num, uint32_t value) + unsigned int first, unsigned int num, uint32_t value) { + assert(num >= 1 && num <= 32); uint8_t *buffer = _buffer; if ((num == 32) && (first == 0)) { @@ -39,7 +43,7 @@ static inline void buf_set_u32(uint8_t *_buffer, buffer[1] = (value >> 8) & 0xff; buffer[0] = (value >> 0) & 0xff; } else { - for (unsigned i = first; i < first + num; i++) { + for (unsigned int i = first; i < first + num; i++) { if (((value >> (i - first)) & 1) == 1) buffer[i / 8] |= 1 << (i % 8); else @@ -59,8 +63,9 @@ static inline void buf_set_u32(uint8_t *_buffer, * @param value Up to 64 bits that will be copied to _buffer. */ static inline void buf_set_u64(uint8_t *_buffer, - unsigned first, unsigned num, uint64_t value) + unsigned int first, unsigned int num, uint64_t value) { + assert(num >= 1 && num <= 64); uint8_t *buffer = _buffer; if ((num == 32) && (first == 0)) { @@ -78,7 +83,7 @@ static inline void buf_set_u64(uint8_t *_buffer, buffer[1] = (value >> 8) & 0xff; buffer[0] = (value >> 0) & 0xff; } else { - for (unsigned i = first; i < first + num; i++) { + for (unsigned int i = first; i < first + num; i++) { if (((value >> (i - first)) & 1) == 1) buffer[i / 8] |= 1 << (i % 8); else @@ -97,8 +102,9 @@ static inline void buf_set_u64(uint8_t *_buffer, * @returns Up to 32-bits that were read from @c _buffer. */ static inline uint32_t buf_get_u32(const uint8_t *_buffer, - unsigned first, unsigned num) + unsigned int first, unsigned int num) { + assert(num >= 1 && num <= 32); const uint8_t *buffer = _buffer; if ((num == 32) && (first == 0)) { @@ -108,7 +114,7 @@ static inline uint32_t buf_get_u32(const uint8_t *_buffer, (((uint32_t)buffer[0]) << 0); } else { uint32_t result = 0; - for (unsigned i = first; i < first + num; i++) { + for (unsigned int i = first; i < first + num; i++) { if (((buffer[i / 8] >> (i % 8)) & 1) == 1) result |= 1U << (i - first); } @@ -126,8 +132,9 @@ static inline uint32_t buf_get_u32(const uint8_t *_buffer, * @returns Up to 64-bits that were read from @c _buffer. */ static inline uint64_t buf_get_u64(const uint8_t *_buffer, - unsigned first, unsigned num) + unsigned int first, unsigned int num) { + assert(num >= 1 && num <= 64); const uint8_t *buffer = _buffer; if ((num == 32) && (first == 0)) { @@ -146,7 +153,7 @@ static inline uint64_t buf_get_u64(const uint8_t *_buffer, (((uint64_t)buffer[0]) << 0)); } else { uint64_t result = 0; - for (unsigned i = first; i < first + num; i++) { + for (unsigned int i = first; i < first + num; i++) { if (((buffer[i / 8] >> (i % 8)) & 1) == 1) result = result | ((uint64_t)1 << (uint64_t)(i - first)); } @@ -163,11 +170,11 @@ static inline uint64_t buf_get_u64(const uint8_t *_buffer, * @param width The number of bits in value (2-32). * @returns A 32-bit word with @c value in reversed bit-order. */ -uint32_t flip_u32(uint32_t value, unsigned width); +uint32_t flip_u32(uint32_t value, unsigned int width); -bool buf_cmp(const void *buf1, const void *buf2, unsigned size); -bool buf_cmp_mask(const void *buf1, const void *buf2, - const void *mask, unsigned size); +bool buf_eq(const void *buf1, const void *buf2, unsigned int size); +bool buf_eq_mask(const void *buf1, const void *buf2, + const void *mask, unsigned int size); /** * Copies @c size bits out of @c from and into @c to. Any extra @@ -176,7 +183,7 @@ bool buf_cmp_mask(const void *buf1, const void *buf2, * @param to The buffer that will receive the copy of @c from. * @param size The number of bits to copy. */ -void *buf_cpy(const void *from, void *to, unsigned size); +void *buf_cpy(const void *from, void *to, unsigned int size); /** * Set the contents of @c buf with @c count bits, all set to 1. @@ -184,14 +191,23 @@ void *buf_cpy(const void *from, void *to, unsigned size); * @param size The number of bits. * @returns The original buffer (@c buf). */ -void *buf_set_ones(void *buf, unsigned size); +void *buf_set_ones(void *buf, unsigned int size); + +void *buf_set_buf(const void *src, unsigned int src_start, + void *dst, unsigned int dst_start, unsigned int len); -void *buf_set_buf(const void *src, unsigned src_start, - void *dst, unsigned dst_start, unsigned len); +/** + * Parse an unsigned number (provided as a zero-terminated string) + * into a bit buffer whose size is buf_len bits. The base of the + * number is detected between decimal, hexadecimal and octal. + * @param str Input number, zero-terminated string + * @param _buf Output buffer, allocated by the caller + * @param buf_bitsize Output buffer size in bits + * @returns Error on invalid or overflowing number + */ +int str_to_buf(const char *str, void *_buf, unsigned int buf_bitsize); -int str_to_buf(const char *str, unsigned len, - void *bin_buf, unsigned buf_size, unsigned radix); -char *buf_to_hex_str(const void *buf, unsigned size); +char *buf_to_hex_str(const void *buf, unsigned int size); /* read a uint32_t from a buffer in target memory endianness */ static inline uint32_t fast_target_buffer_get_u32(const void *p, bool le) @@ -199,8 +215,8 @@ static inline uint32_t fast_target_buffer_get_u32(const void *p, bool le) return le ? le_to_h_u32(p) : be_to_h_u32(p); } -static inline void bit_copy(uint8_t *dst, unsigned dst_offset, const uint8_t *src, - unsigned src_offset, unsigned bit_count) +static inline void bit_copy(uint8_t *dst, unsigned int dst_offset, const uint8_t *src, + unsigned int src_offset, unsigned int bit_count) { buf_set_buf(src, src_offset, dst, dst_offset, bit_count); } @@ -211,16 +227,16 @@ struct bit_copy_queue { struct bit_copy_queue_entry { uint8_t *dst; - unsigned dst_offset; + unsigned int dst_offset; const uint8_t *src; - unsigned src_offset; - unsigned bit_count; + unsigned int src_offset; + unsigned int bit_count; struct list_head list; }; void bit_copy_queue_init(struct bit_copy_queue *q); -int bit_copy_queued(struct bit_copy_queue *q, uint8_t *dst, unsigned dst_offset, const uint8_t *src, - unsigned src_offset, unsigned bit_count); +int bit_copy_queued(struct bit_copy_queue *q, uint8_t *dst, unsigned int dst_offset, const uint8_t *src, + unsigned int src_offset, unsigned int bit_count); void bit_copy_execute(struct bit_copy_queue *q); void bit_copy_discard(struct bit_copy_queue *q); @@ -228,6 +244,6 @@ void bit_copy_discard(struct bit_copy_queue *q); * used in ti-icdi driver and gdb server */ size_t unhexify(uint8_t *bin, const char *hex, size_t count); size_t hexify(char *hex, const uint8_t *bin, size_t count, size_t out_maxlen); -void buffer_shr(void *_buf, unsigned buf_len, unsigned count); +void buffer_shr(void *_buf, unsigned int buf_len, unsigned int count); #endif /* OPENOCD_HELPER_BINARYBUFFER_H */ diff --git a/src/helper/command.c b/src/helper/command.c index a775c73..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) @@ -58,7 +59,7 @@ void *jimcmd_privdata(Jim_Cmd *cmd) return cmd->isproc ? NULL : cmd->u.native.privData; } -static void tcl_output(void *privData, const char *file, unsigned line, +static void tcl_output(void *privData, const char *file, unsigned int line, const char *function, const char *string) { struct log_capture_state *state = privData; @@ -144,7 +145,7 @@ static void script_debug(Jim_Interp *interp, unsigned int argc, Jim_Obj * const return; char *dbg = alloc_printf("command -"); - for (unsigned i = 0; i < argc; i++) { + for (unsigned int i = 0; i < argc; i++) { const char *w = Jim_GetString(argv[i], NULL); char *t = alloc_printf("%s %s", dbg, w); free(dbg); @@ -288,7 +289,7 @@ int __register_commands(struct command_context *cmd_ctx, const char *cmd_prefix, struct target *override_target) { int retval = ERROR_OK; - unsigned i; + unsigned int i; for (i = 0; cmds[i].name || cmds[i].chain; i++) { const struct command_registration *cr = cmds + i; @@ -323,7 +324,7 @@ int __register_commands(struct command_context *cmd_ctx, const char *cmd_prefix, } } if (retval != ERROR_OK) { - for (unsigned j = 0; j < i; j++) + for (unsigned int j = 0; j < i; j++) unregister_command(cmd_ctx, cmd_prefix, cmds[j].name); } return retval; @@ -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; @@ -728,12 +729,12 @@ static COMMAND_HELPER(command_help_show_list, bool show_help, const char *cmd_ma #define HELP_LINE_WIDTH(_n) (int)(76 - (2 * _n)) -static void command_help_show_indent(unsigned n) +static void command_help_show_indent(unsigned int n) { - for (unsigned i = 0; i < n; i++) + for (unsigned int i = 0; i < n; i++) LOG_USER_N(" "); } -static void command_help_show_wrap(const char *str, unsigned n, unsigned n2) +static void command_help_show_wrap(const char *str, unsigned int n, unsigned int n2) { const char *cp = str, *last = str; while (*cp) { @@ -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; @@ -1317,7 +1311,7 @@ DEFINE_PARSE_NUM_TYPE(_llong, long long, strtoll, LLONG_MIN, LLONG_MAX) #define DEFINE_PARSE_ULONGLONG(name, type, min, max) \ DEFINE_PARSE_WRAPPER(name, type, min, max, unsigned long long, _ullong) -DEFINE_PARSE_ULONGLONG(_uint, unsigned, 0, UINT_MAX) +DEFINE_PARSE_ULONGLONG(_uint, unsigned int, 0, UINT_MAX) DEFINE_PARSE_ULONGLONG(_u64, uint64_t, 0, UINT64_MAX) DEFINE_PARSE_ULONGLONG(_u32, uint32_t, 0, UINT32_MAX) DEFINE_PARSE_ULONGLONG(_u16, uint16_t, 0, UINT16_MAX) @@ -1360,6 +1354,27 @@ int command_parse_bool_arg(const char *in, bool *out) return ERROR_COMMAND_SYNTAX_ERROR; } +COMMAND_HELPER(command_parse_str_to_buf, const char *str, void *buf, unsigned int buf_len) +{ + assert(str); + assert(buf); + + int ret = str_to_buf(str, buf, buf_len); + if (ret == ERROR_OK) + return ret; + + /* Provide a clear error message to the user */ + if (ret == ERROR_INVALID_NUMBER) { + command_print(CMD, "'%s' is not a valid number", str); + } else if (ret == ERROR_NUMBER_EXCEEDS_BUFFER) { + command_print(CMD, "Number %s exceeds %u bits", str, buf_len); + } else { + command_print(CMD, "Could not parse number '%s'", str); + } + + return ERROR_COMMAND_ARGUMENT_INVALID; +} + COMMAND_HELPER(handle_command_parse_bool, bool *out, const char *label) { switch (CMD_ARGC) { diff --git a/src/helper/command.h b/src/helper/command.h index fc26dda..18fe561 100644 --- a/src/helper/command.h +++ b/src/helper/command.h @@ -77,7 +77,7 @@ struct command_invocation { struct command_context *ctx; struct command *current; const char *name; - unsigned argc; + unsigned int argc; const char **argv; Jim_Obj * const *jimtcl_argv; Jim_Obj *output; @@ -414,7 +414,7 @@ int parse_llong(const char *str, long long *ul); #define DECLARE_PARSE_WRAPPER(name, type) \ int parse ## name(const char *str, type * ul) -DECLARE_PARSE_WRAPPER(_uint, unsigned); +DECLARE_PARSE_WRAPPER(_uint, unsigned int); DECLARE_PARSE_WRAPPER(_u64, uint64_t); DECLARE_PARSE_WRAPPER(_u32, uint32_t); DECLARE_PARSE_WRAPPER(_u16, uint16_t); @@ -517,6 +517,15 @@ DECLARE_PARSE_WRAPPER(_target_addr, target_addr_t); int command_parse_bool_arg(const char *in, bool *out); COMMAND_HELPER(handle_command_parse_bool, bool *out, const char *label); +/** + * Parse a number (base 10, base 16 or base 8) and store the result + * into a bit buffer. Use the prefixes '0' and '0x' for base 8 and 16, + * otherwise defaults to base 10. + * + * In case of parsing error, a user-readable error message is produced. + */ +COMMAND_HELPER(command_parse_str_to_buf, const char *str, void *buf, unsigned int buf_len); + /** parses an on/off command argument */ #define COMMAND_PARSE_ON_OFF(in, out) \ COMMAND_PARSE_BOOL(in, out, "on", "off") diff --git a/src/helper/configuration.h b/src/helper/configuration.h index 295ea59..d646670 100644 --- a/src/helper/configuration.h +++ b/src/helper/configuration.h @@ -11,6 +11,7 @@ #ifndef OPENOCD_HELPER_CONFIGURATION_H #define OPENOCD_HELPER_CONFIGURATION_H +#include <stdio.h> #include <helper/command.h> int parse_cmdline_args(struct command_context *cmd_ctx, diff --git a/src/helper/jep106.inc b/src/helper/jep106.inc index 958dc4e..8bbaf4c 100644 --- a/src/helper/jep106.inc +++ b/src/helper/jep106.inc @@ -2,20 +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 JEP106BI January 2024. */ - -/* "NXP (Philips)" is reported below, while missing since JEP106BG */ +/* 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", @@ -30,7 +28,7 @@ [0][0x10 - 1] = "NEC", [0][0x11 - 1] = "RCA", [0][0x12 - 1] = "Raytheon", -[0][0x13 - 1] = "Conexant (Rockwell)", +[0][0x13 - 1] = "Synaptics", [0][0x14 - 1] = "Seeq", [0][0x15 - 1] = "NXP (Philips)", [0][0x16 - 1] = "Synertek", @@ -179,7 +177,7 @@ [1][0x27 - 1] = "Cabletron", [1][0x28 - 1] = "STEC (Silicon Tech)", [1][0x29 - 1] = "Vanguard", -[1][0x2a - 1] = "Hagiwara Sys-Com", +[1][0x2a - 1] = "Hagiwara Solutions Co Ltd", [1][0x2b - 1] = "Vantis", [1][0x2c - 1] = "Celestica", [1][0x2d - 1] = "Century", @@ -1045,7 +1043,7 @@ [8][0x17 - 1] = "Axell Corporation", [8][0x18 - 1] = "Essencore Limited", [8][0x19 - 1] = "Phytium", -[8][0x1a - 1] = "Xi'an UniIC Semiconductors Co Ltd", +[8][0x1a - 1] = "UniIC Semiconductors Co Ltd", [8][0x1b - 1] = "Ambiq Micro", [8][0x1c - 1] = "eveRAM Technology Inc", [8][0x1d - 1] = "Infomax", @@ -1375,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 Zuan Information Tech", +[10][0x68 - 1] = "Shanghai Ruixuan Information Tech", [10][0x69 - 1] = "Fraunhofer IIS", [10][0x6a - 1] = "Kandou Bus SA", [10][0x6b - 1] = "Acer", @@ -1452,7 +1450,7 @@ [11][0x34 - 1] = "Acacia Communications", [11][0x35 - 1] = "Beijinjinshengyihe Technology Co Ltd", [11][0x36 - 1] = "Zyzyx", -[11][0x37 - 1] = "T-HEAD Semiconductor Co Ltd", +[11][0x37 - 1] = "C-SKY Microsystems Co Ltd", [11][0x38 - 1] = "Shenzhen Hystou Technology Co Ltd", [11][0x39 - 1] = "Syzexion", [11][0x3a - 1] = "Kembona", @@ -1655,9 +1653,9 @@ [13][0x03 - 1] = "Shenzhen Feisrike Technology Co Ltd", [13][0x04 - 1] = "Shenzhen Sunhome Electronics Co Ltd", [13][0x05 - 1] = "Global Mixed-mode Technology Inc", -[13][0x06 - 1] = "Shenzhen Weien Electronics Co. Ltd.", +[13][0x06 - 1] = "Shenzhen Weien Electronics Co Ltd.", [13][0x07 - 1] = "Shenzhen Cooyes Technology Co Ltd", -[13][0x08 - 1] = "Keymos Electronics Co., Limited", +[13][0x08 - 1] = "ShenZhen ChaoYing ZhiNeng Technology", [13][0x09 - 1] = "E-Rockic Technology Company Limited", [13][0x0a - 1] = "Aerospace Science Memory Shenzhen", [13][0x0b - 1] = "Shenzhen Quanji Technology Co Ltd", @@ -1747,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.", @@ -1895,12 +1893,12 @@ [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", [14][0x7c - 1] = "ForwardEdge ASIC", -[14][0x7d - 1] = "Beijing Future Imprint Technology Co Ltd", +[14][0x7d - 1] = "Beijing Future Signet Technology Co Ltd", [14][0x7e - 1] = "Fine Made Microelectronics Group Co Ltd", [15][0x01 - 1] = "Changxin Memory Technology (Shanghai)", [15][0x02 - 1] = "Synconv", @@ -1918,16 +1916,16 @@ [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 Technologioes", +[15][0x14 - 1] = "Zilia Technologies", [15][0x15 - 1] = "Incore Semiconductors", [15][0x16 - 1] = "Kinetic Technologies", [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", @@ -1938,4 +1936,117 @@ [15][0x22 - 1] = "SkyeChip", [15][0x23 - 1] = "Guangzhou Kaishile Trading Co Ltd", [15][0x24 - 1] = "Jing Pai Digital Technology (Shenzhen) Co", +[15][0x25 - 1] = "Memoritek", +[15][0x26 - 1] = "Zhejiang Hikstor Technology Co Ltd", +[15][0x27 - 1] = "Memoritek PTE Ltd", +[15][0x28 - 1] = "Longsailing Semiconductor Co Ltd", +[15][0x29 - 1] = "LX Semicon", +[15][0x2a - 1] = "Shenzhen Techwinsemi Technology Co Ltd", +[15][0x2b - 1] = "AOC", +[15][0x2c - 1] = "GOEPEL Electronic GmbH", +[15][0x2d - 1] = "Shenzhen G-Bong Technology Co Ltd", +[15][0x2e - 1] = "Openedges Technology Inc", +[15][0x2f - 1] = "EA Semi Shangahi Limited", +[15][0x30 - 1] = "EMBCORF", +[15][0x31 - 1] = "Shenzhen MicroBT Electronics Technology", +[15][0x32 - 1] = "Shanghai Simor Chip Semiconductor Co", +[15][0x33 - 1] = "Xllbyte", +[15][0x34 - 1] = "Guangzhou Maidite Electronics Co Ltd.", +[15][0x35 - 1] = "Zhejiang Changchun Technology Co Ltd", +[15][0x36 - 1] = "Beijing Cloud Security Technology Co Ltd", +[15][0x37 - 1] = "SSTC Technology and Distribution Inc", +[15][0x38 - 1] = "Shenzhen Panmin Technology Co Ltd", +[15][0x39 - 1] = "ITE Tech Inc", +[15][0x3a - 1] = "Beijing Zettastone Technology Co Ltd", +[15][0x3b - 1] = "Powerchip Micro Device", +[15][0x3c - 1] = "Shenzhen Ysemi Computing Co Ltd", +[15][0x3d - 1] = "Shenzhen Titan Micro Electronics Co Ltd", +[15][0x3e - 1] = "Shenzhen Macroflash Technology Co Ltd", +[15][0x3f - 1] = "Advantech Group", +[15][0x40 - 1] = "Shenzhen Xingjiachen Electronics Co Ltd", +[15][0x41 - 1] = "CHUQI", +[15][0x42 - 1] = "Dongguan Liesun Trading Co Ltd", +[15][0x43 - 1] = "Shenzhen Miuman Technology Co Ltd", +[15][0x44 - 1] = "Shenzhen Techwinsemi Technology Twsc", +[15][0x45 - 1] = "Encharge AI Inc", +[15][0x46 - 1] = "Shenzhen Zhenchuang Electronics Co Ltd", +[15][0x47 - 1] = "Giant Chip Co. Ltd", +[15][0x48 - 1] = "Shenzhen Runner Semiconductor Co Ltd", +[15][0x49 - 1] = "Scalinx", +[15][0x4a - 1] = "Shenzhen Lanqi Electronics Co Ltd", +[15][0x4b - 1] = "CoreComm Technology Co Ltd", +[15][0x4c - 1] = "DLI Memory", +[15][0x4d - 1] = "Shenzhen Fidat Technology Co Ltd", +[15][0x4e - 1] = "Hubei Yangtze Mason Semiconductor Tech", +[15][0x4f - 1] = "Flastor", +[15][0x50 - 1] = "PIRATEMAN", +[15][0x51 - 1] = "Barrie Technologies Co Ltd", +[15][0x52 - 1] = "Dynacard Co Ltd", +[15][0x53 - 1] = "Rivian Automotive", +[15][0x54 - 1] = "Shenzhen Fidat Technology Co Ltd", +[15][0x55 - 1] = "Zhejang Weiming Semiconductor Co Ltd", +[15][0x56 - 1] = "Shenzhen Xinhua Micro Technology Co Ltd", +[15][0x57 - 1] = "Duvonn Electronic Technology Co Ltd", +[15][0x58 - 1] = "Shenzhen Xinchang Technology Co Ltd", +[15][0x59 - 1] = "Leidos", +[15][0x5a - 1] = "Keepixo", +[15][0x5b - 1] = "Applied Brain Research Inc", +[15][0x5c - 1] = "Maxio Technology (Hangzhou) Co Ltd", +[15][0x5d - 1] = "HK DCHIP Technology Limited", +[15][0x5e - 1] = "Hitachi-LG Data Storage", +[15][0x5f - 1] = "Shenzhen Huadian Communication Co Ltd", +[15][0x60 - 1] = "Achieve Memory Technology (Suzhou) Co", +[15][0x61 - 1] = "Shenzhen Think Future Semiconductor Co", +[15][0x62 - 1] = "Innosilicon", +[15][0x63 - 1] = "Shenzhen Weilida Technology Co Ltd", +[15][0x64 - 1] = "Agrade Storage (Shenzhen) Co Ltd", +[15][0x65 - 1] = "Shenzhen Worldshine Data Technology Co", +[15][0x66 - 1] = "Mindgrove Technologies", +[15][0x67 - 1] = "BYD Semiconductor Co Ltd", +[15][0x68 - 1] = "Chipsine Semiconductor (Suzhou) Co Ltd", +[15][0x69 - 1] = "Shen Zhen Shi Xun He Shi Ji Dian Zi You", +[15][0x6a - 1] = "Shenzhen Jindacheng Computer Co Ltd", +[15][0x6b - 1] = "Shenzhen Baina Haichuan Technology Co", +[15][0x6c - 1] = "Shanghai Hengshi Electronic Technology", +[15][0x6d - 1] = "Beijing Boyu Tuxian Technology Co Ltd", +[15][0x6e - 1] = "China Chips Star Semiconductor Co Ltd", +[15][0x6f - 1] = "Shenzhen Shenghuacan Technology Co", +[15][0x70 - 1] = "Kinara Inc", +[15][0x71 - 1] = "TRASNA Semiconductor", +[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/jim-nvp.c b/src/helper/jim-nvp.c index e1ab64a..cdd4d34 100644 --- a/src/helper/jim-nvp.c +++ b/src/helper/jim-nvp.c @@ -21,6 +21,7 @@ #endif #include "jim-nvp.h" +#include <stdio.h> #include <string.h> int jim_get_nvp(Jim_Interp *interp, diff --git a/src/helper/jim-nvp.h b/src/helper/jim-nvp.h index 11824ca..45af6c8 100644 --- a/src/helper/jim-nvp.h +++ b/src/helper/jim-nvp.h @@ -19,6 +19,7 @@ #ifndef OPENOCD_HELPER_JIM_NVP_H #define OPENOCD_HELPER_JIM_NVP_H +#include <stdbool.h> #include <jim.h> /** Name Value Pairs, aka: NVP @@ -136,7 +137,7 @@ struct jim_getopt_info { Jim_Interp *interp; int argc; Jim_Obj *const *argv; - int isconfigure; /* non-zero if configure */ + bool is_configure; }; /** GetOpt - how to. diff --git a/src/helper/list.h b/src/helper/list.h index 47290c2..ba07f15 100644 --- a/src/helper/list.h +++ b/src/helper/list.h @@ -46,7 +46,7 @@ struct list_head { #define LIST_HEAD_INIT(name) { &(name), &(name) } -#define LIST_HEAD(name) \ +#define OOCD_LIST_HEAD(name) \ struct list_head name = LIST_HEAD_INIT(name) static inline void diff --git a/src/helper/log.c b/src/helper/log.c index 471069a..8f7ab00 100644 --- a/src/helper/log.c +++ b/src/helper/log.c @@ -30,6 +30,18 @@ #else #error "malloc.h is required to use --enable-malloc-logging" #endif + +#ifdef __GLIBC__ +#if __GLIBC_PREREQ(2, 33) +#define FORDBLKS_FORMAT " %zu" +#else +/* glibc older than 2.33 (2021-02-01) use mallinfo(). Overwrite it */ +#define mallinfo2 mallinfo +#define FORDBLKS_FORMAT " %d" +#endif +#else +#error "GNU glibc is required to use --enable-malloc-logging" +#endif #endif int debug_level = LOG_LVL_INFO; @@ -53,7 +65,7 @@ static const char * const log_strings[6] = { static int count; /* forward the log to the listeners */ -static void log_forward(const char *file, unsigned line, const char *function, const char *string) +static void log_forward(const char *file, unsigned int line, const char *function, const char *string) { struct log_callback *cb, *next; cb = log_callbacks; @@ -105,12 +117,11 @@ static void log_puts(enum log_levels level, /* print with count and time information */ int64_t t = timeval_ms() - start; #ifdef _DEBUG_FREE_SPACE_ - struct mallinfo info; - info = mallinfo(); + struct mallinfo2 info = mallinfo2(); #endif fprintf(log_output, "%s%d %" PRId64 " %s:%d %s()" #ifdef _DEBUG_FREE_SPACE_ - " %d" + FORDBLKS_FORMAT #endif ": %s", log_strings[level + 1], count, t, file, line, function, #ifdef _DEBUG_FREE_SPACE_ @@ -133,7 +144,7 @@ static void log_puts(enum log_levels level, void log_printf(enum log_levels level, const char *file, - unsigned line, + unsigned int line, const char *function, const char *format, ...) @@ -156,7 +167,7 @@ void log_printf(enum log_levels level, va_end(ap); } -void log_vprintf_lf(enum log_levels level, const char *file, unsigned line, +void log_vprintf_lf(enum log_levels level, const char *file, unsigned int line, const char *function, const char *format, va_list args) { char *tmp; @@ -182,7 +193,7 @@ void log_vprintf_lf(enum log_levels level, const char *file, unsigned line, void log_printf_lf(enum log_levels level, const char *file, - unsigned line, + unsigned int line, const char *function, const char *format, ...) @@ -272,10 +283,10 @@ void log_init(void) if (debug_env) { int value; int retval = parse_int(debug_env, &value); - if (retval == ERROR_OK && - debug_level >= LOG_LVL_SILENT && - debug_level <= LOG_LVL_DEBUG_IO) - debug_level = value; + if (retval == ERROR_OK + && debug_level >= LOG_LVL_SILENT + && debug_level <= LOG_LVL_DEBUG_IO) + debug_level = value; } if (!log_output) @@ -505,7 +516,7 @@ void log_socket_error(const char *socket_desc) * Find the first non-printable character in the char buffer, return a pointer to it. * If no such character exists, return NULL. */ -char *find_nonprint_char(char *buf, unsigned buf_len) +const char *find_nonprint_char(const char *buf, unsigned int buf_len) { for (unsigned int i = 0; i < buf_len; i++) { if (!isprint(buf[i])) diff --git a/src/helper/log.h b/src/helper/log.h index d52c05f..ac24f8e 100644 --- a/src/helper/log.h +++ b/src/helper/log.h @@ -48,12 +48,12 @@ enum log_levels { LOG_LVL_DEBUG_IO = 4, }; -void log_printf(enum log_levels level, const char *file, unsigned line, +void log_printf(enum log_levels level, const char *file, unsigned int line, const char *function, const char *format, ...) __attribute__ ((format (PRINTF_ATTRIBUTE_FORMAT, 5, 6))); -void log_vprintf_lf(enum log_levels level, const char *file, unsigned line, +void log_vprintf_lf(enum log_levels level, const char *file, unsigned int line, const char *function, const char *format, va_list args); -void log_printf_lf(enum log_levels level, const char *file, unsigned line, +void log_printf_lf(enum log_levels level, const char *file, unsigned int line, const char *function, const char *format, ...) __attribute__ ((format (PRINTF_ATTRIBUTE_FORMAT, 5, 6))); @@ -73,7 +73,7 @@ void busy_sleep(uint64_t ms); void log_socket_error(const char *socket_desc); -typedef void (*log_callback_fn)(void *priv, const char *file, unsigned line, +typedef void (*log_callback_fn)(void *priv, const char *file, unsigned int line, const char *function, const char *string); struct log_callback { @@ -85,11 +85,12 @@ 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))); -char *find_nonprint_char(char *buf, unsigned buf_len); +const char *find_nonprint_char(const char *buf, unsigned int buf_len); extern int debug_level; @@ -152,6 +153,9 @@ extern int debug_level; #define LOG_TARGET_INFO(target, fmt_str, ...) \ LOG_INFO("[%s] " fmt_str, target_name(target), ##__VA_ARGS__) +#define LOG_TARGET_USER(target, fmt_str, ...) \ + LOG_USER("[%s] " fmt_str, target_name(target), ##__VA_ARGS__) + #define LOG_TARGET_WARNING(target, fmt_str, ...) \ LOG_WARNING("[%s] " fmt_str, target_name(target), ##__VA_ARGS__) diff --git a/src/helper/options.c b/src/helper/options.c index 61a1014..735b8af 100644 --- a/src/helper/options.c +++ b/src/helper/options.c @@ -303,12 +303,14 @@ int parse_cmdline_args(struct command_context *cmd_ctx, int argc, char *argv[]) break; } case 'l': /* --log_output | -l */ - if (optarg) - command_run_linef(cmd_ctx, "log_output %s", optarg); + { + int retval = command_run_linef(cmd_ctx, "log_output %s", optarg); + if (retval != ERROR_OK) + return retval; break; + } case 'c': /* --command | -c */ - if (optarg) - add_config_command(optarg); + add_config_command(optarg); break; default: /* '?' */ /* getopt will emit an error message, all we have to do is bail. */ @@ -332,7 +334,7 @@ int parse_cmdline_args(struct command_context *cmd_ctx, int argc, char *argv[]) LOG_OUTPUT(" | -d<n>\tset debug level to <level>\n"); LOG_OUTPUT("--log_output | -l\tredirect log output to file <name>\n"); LOG_OUTPUT("--command | -c\trun <command>\n"); - exit(-1); + exit(0); } if (version_flag) { diff --git a/src/helper/replacements.h b/src/helper/replacements.h index 6e30b62..ecc0e5e 100644 --- a/src/helper/replacements.h +++ b/src/helper/replacements.h @@ -111,7 +111,7 @@ size_t strnlen(const char *s, size_t maxlen); #ifndef HAVE_USLEEP #ifdef _WIN32 -static inline unsigned usleep(unsigned int usecs) +static inline unsigned int usleep(unsigned int usecs) { Sleep((usecs/1000)); return 0; diff --git a/src/jtag/adapter.c b/src/jtag/adapter.c index bbf1cb3..2fcbd60 100644 --- a/src/jtag/adapter.c +++ b/src/jtag/adapter.c @@ -66,6 +66,8 @@ static const struct gpio_map { [ADAPTER_GPIO_IDX_LED] = { "led", ADAPTER_GPIO_DIRECTION_OUTPUT, true, true, }, }; +static int adapter_config_khz(unsigned int khz); + bool is_adapter_initialized(void) { return adapter_config.adapter_initialized; @@ -245,7 +247,8 @@ static int adapter_set_speed(int speed) return is_adapter_initialized() ? adapter_driver->speed(speed) : ERROR_OK; } -int adapter_config_khz(unsigned int khz) +/** Attempt to configure the adapter for the specified kHz. */ +static int adapter_config_khz(unsigned int khz) { LOG_DEBUG("handle adapter khz"); adapter_config.clock_mode = CLOCK_MODE_KHZ; @@ -389,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 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 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) @@ -436,7 +424,7 @@ COMMAND_HANDLER(handle_adapter_driver_command) if (CMD_ARGC != 1 || CMD_ARGV[0][0] == '\0') return ERROR_COMMAND_SYNTAX_ERROR; - for (unsigned i = 0; adapter_drivers[i]; i++) { + for (unsigned int i = 0; adapter_drivers[i]; i++) { if (strcmp(CMD_ARGV[0], adapter_drivers[i]->name) != 0) continue; @@ -456,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; } @@ -684,7 +673,7 @@ COMMAND_HANDLER(handle_adapter_srst_delay_command) if (CMD_ARGC > 1) return ERROR_COMMAND_SYNTAX_ERROR; if (CMD_ARGC == 1) { - unsigned delay; + unsigned int delay; COMMAND_PARSE_NUMBER(uint, CMD_ARGV[0], delay); jtag_set_nsrst_delay(delay); @@ -698,7 +687,7 @@ COMMAND_HANDLER(handle_adapter_srst_pulse_width_command) if (CMD_ARGC > 1) return ERROR_COMMAND_SYNTAX_ERROR; if (CMD_ARGC == 1) { - unsigned width; + unsigned int width; COMMAND_PARSE_NUMBER(uint, CMD_ARGV[0], width); jtag_set_nsrst_assert_width(width); @@ -714,7 +703,7 @@ COMMAND_HANDLER(handle_adapter_speed_command) int retval = ERROR_OK; if (CMD_ARGC == 1) { - unsigned khz = 0; + unsigned int khz = 0; COMMAND_PARSE_NUMBER(uint, CMD_ARGV[0], khz); retval = adapter_config_khz(khz); @@ -1135,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/adapter.h b/src/jtag/adapter.h index 23ffe2c..556952f 100644 --- a/src/jtag/adapter.h +++ b/src/jtag/adapter.h @@ -97,9 +97,6 @@ int adapter_get_speed(int *speed); */ int adapter_get_speed_readable(int *speed); -/** Attempt to configure the adapter for the specified kHz. */ -int adapter_config_khz(unsigned int khz); - /** * Attempt to enable RTCK/RCLK. If that fails, fallback to the * specified frequency. diff --git a/src/jtag/commands.c b/src/jtag/commands.c index a60684c..1bca4e8 100644 --- a/src/jtag/commands.c +++ b/src/jtag/commands.c @@ -166,10 +166,9 @@ void jtag_scan_field_clone(struct scan_field *dst, const struct scan_field *src) enum scan_type jtag_scan_type(const struct scan_command *cmd) { - int i; int type = 0; - for (i = 0; i < cmd->num_fields; i++) { + for (unsigned int i = 0; i < cmd->num_fields; i++) { if (cmd->fields[i].in_value) type |= SCAN_IN; if (cmd->fields[i].out_value) @@ -179,13 +178,12 @@ enum scan_type jtag_scan_type(const struct scan_command *cmd) return type; } -int jtag_scan_size(const struct scan_command *cmd) +unsigned int jtag_scan_size(const struct scan_command *cmd) { - int bit_count = 0; - int i; + unsigned int bit_count = 0; /* count bits in scan command */ - for (i = 0; i < cmd->num_fields; i++) + for (unsigned int i = 0; i < cmd->num_fields; i++) bit_count += cmd->fields[i].num_bits; return bit_count; @@ -193,19 +191,16 @@ int jtag_scan_size(const struct scan_command *cmd) int jtag_build_buffer(const struct scan_command *cmd, uint8_t **buffer) { - int bit_count = 0; - int i; - - bit_count = jtag_scan_size(cmd); + unsigned int bit_count = jtag_scan_size(cmd); *buffer = calloc(1, DIV_ROUND_UP(bit_count, 8)); bit_count = 0; - LOG_DEBUG_IO("%s num_fields: %i", + LOG_DEBUG_IO("%s num_fields: %u", cmd->ir_scan ? "IRSCAN" : "DRSCAN", cmd->num_fields); - for (i = 0; i < cmd->num_fields; i++) { + for (unsigned int i = 0; i < cmd->num_fields; i++) { if (cmd->fields[i].out_value) { if (LOG_LEVEL_IS(LOG_LVL_DEBUG_IO)) { char *char_buf = buf_to_hex_str(cmd->fields[i].out_value, @@ -213,14 +208,14 @@ int jtag_build_buffer(const struct scan_command *cmd, uint8_t **buffer) ? DEBUG_JTAG_IOZ : cmd->fields[i].num_bits); - LOG_DEBUG("fields[%i].out_value[%i]: 0x%s", i, + LOG_DEBUG("fields[%u].out_value[%u]: 0x%s", i, cmd->fields[i].num_bits, char_buf); free(char_buf); } buf_set_buf(cmd->fields[i].out_value, 0, *buffer, bit_count, cmd->fields[i].num_bits); } else { - LOG_DEBUG_IO("fields[%i].out_value[%i]: NULL", + LOG_DEBUG_IO("fields[%u].out_value[%u]: NULL", i, cmd->fields[i].num_bits); } @@ -234,19 +229,18 @@ int jtag_build_buffer(const struct scan_command *cmd, uint8_t **buffer) int jtag_read_buffer(uint8_t *buffer, const struct scan_command *cmd) { - int i; int bit_count = 0; int retval; /* we return ERROR_OK, unless a check fails, or a handler reports a problem */ retval = ERROR_OK; - for (i = 0; i < cmd->num_fields; i++) { + for (unsigned int i = 0; i < cmd->num_fields; i++) { /* if neither in_value nor in_handler * are specified we don't have to examine this field */ if (cmd->fields[i].in_value) { - int num_bits = cmd->fields[i].num_bits; + const unsigned int num_bits = cmd->fields[i].num_bits; uint8_t *captured = buf_set_buf(buffer, bit_count, malloc(DIV_ROUND_UP(num_bits, 8)), 0, num_bits); @@ -256,7 +250,7 @@ int jtag_read_buffer(uint8_t *buffer, const struct scan_command *cmd) ? DEBUG_JTAG_IOZ : num_bits); - LOG_DEBUG("fields[%i].in_value[%i]: 0x%s", + LOG_DEBUG("fields[%u].in_value[%u]: 0x%s", i, num_bits, char_buf); free(char_buf); } diff --git a/src/jtag/commands.h b/src/jtag/commands.h index 8259077..2923df1 100644 --- a/src/jtag/commands.h +++ b/src/jtag/commands.h @@ -36,36 +36,36 @@ struct scan_command { /** instruction/not data scan */ bool ir_scan; /** number of fields in *fields array */ - int num_fields; + unsigned int num_fields; /** pointer to an array of data scan fields */ struct scan_field *fields; /** state in which JTAG commands should finish */ - tap_state_t end_state; + enum tap_state end_state; }; struct statemove_command { /** state in which JTAG commands should finish */ - tap_state_t end_state; + enum tap_state end_state; }; struct pathmove_command { /** number of states in *path */ - int num_states; + unsigned int num_states; /** states that have to be passed */ - tap_state_t *path; + enum tap_state *path; }; struct runtest_command { /** number of cycles to spend in Run-Test/Idle state */ - int num_cycles; + unsigned int num_cycles; /** state in which JTAG commands should finish */ - tap_state_t end_state; + enum tap_state end_state; }; struct stableclocks_command { /** number of clock cycles that should be sent */ - int num_cycles; + unsigned int num_cycles; }; @@ -78,7 +78,7 @@ struct reset_command { struct end_state_command { /** state in which JTAG commands should finish */ - tap_state_t end_state; + enum tap_state end_state; }; struct sleep_command { @@ -100,7 +100,7 @@ struct sleep_command { */ struct tms_command { /** How many bits should be clocked out. */ - unsigned num_bits; + unsigned int num_bits; /** The bits to clock out; the LSB is bit 0 of bits[0]. */ const uint8_t *bits; }; @@ -157,7 +157,7 @@ struct jtag_command *jtag_command_queue_get(void); void jtag_scan_field_clone(struct scan_field *dst, const struct scan_field *src); enum scan_type jtag_scan_type(const struct scan_command *cmd); -int jtag_scan_size(const struct scan_command *cmd); +unsigned int jtag_scan_size(const struct scan_command *cmd); int jtag_read_buffer(uint8_t *buffer, const struct scan_command *cmd); int jtag_build_buffer(const struct scan_command *cmd, uint8_t **buffer); diff --git a/src/jtag/core.c b/src/jtag/core.c index c84d5aa..030c173 100644 --- a/src/jtag/core.c +++ b/src/jtag/core.c @@ -39,7 +39,7 @@ #include "server/ipdbg.h" /** The number of JTAG queue flushes (for profiling and debugging purposes). */ -static int jtag_flush_queue_count; +static unsigned int jtag_flush_queue_count; /* Sleep this # of ms after flushing the queue */ static int jtag_flush_queue_sleep; @@ -48,8 +48,10 @@ static void jtag_add_scan_check(struct jtag_tap *active, void (*jtag_add_scan)(struct jtag_tap *active, int in_num_fields, const struct scan_field *in_fields, - tap_state_t state), - int in_num_fields, struct scan_field *in_fields, tap_state_t state); + enum tap_state state), + int in_num_fields, struct scan_field *in_fields, enum tap_state state); + +static int jtag_error_clear(void); /** * The jtag_error variable is set when an error occurs while executing @@ -85,17 +87,17 @@ static int jtag_srst = -1; static struct jtag_tap *__jtag_all_taps; static enum reset_types jtag_reset_config = RESET_NONE; -tap_state_t cmd_queue_cur_state = TAP_RESET; +enum tap_state cmd_queue_cur_state = TAP_RESET; static bool jtag_verify_capture_ir = true; -static int jtag_verify = 1; +static bool jtag_verify = true; /* how long the OpenOCD should wait before attempting JTAG communication after reset lines *deasserted (in ms) */ -static int adapter_nsrst_delay; /* default to no nSRST delay */ -static int jtag_ntrst_delay;/* default to no nTRST delay */ -static int adapter_nsrst_assert_width; /* width of assertion */ -static int jtag_ntrst_assert_width; /* width of assertion */ +static unsigned int adapter_nsrst_delay; /* default to no nSRST delay */ +static unsigned int jtag_ntrst_delay;/* default to no nTRST delay */ +static unsigned int adapter_nsrst_assert_width; /* width of assertion */ +static unsigned int jtag_ntrst_assert_width; /* width of assertion */ /** * Contains a single callback along with a pointer that will be passed @@ -127,7 +129,11 @@ void jtag_set_error(int error) jtag_error = error; } -int jtag_error_clear(void) +/** + * Resets jtag_error to ERROR_OK, returning its previous value. + * @returns The previous value of @c jtag_error. + */ +static int jtag_error_clear(void) { int temp = jtag_error; jtag_error = ERROR_OK; @@ -186,10 +192,10 @@ struct jtag_tap *jtag_all_taps(void) return __jtag_all_taps; }; -unsigned jtag_tap_count(void) +static unsigned int jtag_tap_count(void) { struct jtag_tap *t = jtag_all_taps(); - unsigned n = 0; + unsigned int n = 0; while (t) { n++; t = t->next_tap; @@ -197,10 +203,10 @@ unsigned jtag_tap_count(void) return n; } -unsigned jtag_tap_count_enabled(void) +unsigned int jtag_tap_count_enabled(void) { struct jtag_tap *t = jtag_all_taps(); - unsigned n = 0; + unsigned int n = 0; while (t) { if (t->enabled) n++; @@ -212,7 +218,7 @@ unsigned jtag_tap_count_enabled(void) /** Append a new TAP to the chain of all taps. */ static void jtag_tap_add(struct jtag_tap *t) { - unsigned jtag_num_taps = 0; + unsigned int jtag_num_taps = 0; struct jtag_tap **tap = &__jtag_all_taps; while (*tap) { @@ -224,7 +230,7 @@ static void jtag_tap_add(struct jtag_tap *t) } /* returns a pointer to the n-th device in the scan chain */ -struct jtag_tap *jtag_tap_by_position(unsigned n) +struct jtag_tap *jtag_tap_by_position(unsigned int n) { struct jtag_tap *t = jtag_all_taps(); @@ -246,7 +252,7 @@ struct jtag_tap *jtag_tap_by_string(const char *s) } /* no tap found by name, so try to parse the name as a number */ - unsigned n; + unsigned int n; if (parse_uint(s, &n) != ERROR_OK) return NULL; @@ -344,7 +350,7 @@ static void jtag_checks(void) assert(jtag_trst == 0); } -static void jtag_prelude(tap_state_t state) +static void jtag_prelude(enum tap_state state) { jtag_checks(); @@ -354,7 +360,7 @@ static void jtag_prelude(tap_state_t state) } void jtag_add_ir_scan_noverify(struct jtag_tap *active, const struct scan_field *in_fields, - tap_state_t state) + enum tap_state state) { jtag_prelude(state); @@ -365,13 +371,13 @@ void jtag_add_ir_scan_noverify(struct jtag_tap *active, const struct scan_field static void jtag_add_ir_scan_noverify_callback(struct jtag_tap *active, int dummy, const struct scan_field *in_fields, - tap_state_t state) + enum tap_state state) { jtag_add_ir_scan_noverify(active, in_fields, state); } /* If fields->in_value is filled out, then the captured IR value will be checked */ -void jtag_add_ir_scan(struct jtag_tap *active, struct scan_field *in_fields, tap_state_t state) +void jtag_add_ir_scan(struct jtag_tap *active, struct scan_field *in_fields, enum tap_state state) { assert(state != TAP_RESET); @@ -390,7 +396,7 @@ void jtag_add_ir_scan(struct jtag_tap *active, struct scan_field *in_fields, tap } void jtag_add_plain_ir_scan(int num_bits, const uint8_t *out_bits, uint8_t *in_bits, - tap_state_t state) + enum tap_state state) { assert(out_bits); assert(state != TAP_RESET); @@ -420,8 +426,8 @@ static void jtag_add_scan_check(struct jtag_tap *active, void (*jtag_add_scan)( struct jtag_tap *active, int in_num_fields, const struct scan_field *in_fields, - tap_state_t state), - int in_num_fields, struct scan_field *in_fields, tap_state_t state) + enum tap_state state), + int in_num_fields, struct scan_field *in_fields, enum tap_state state) { jtag_add_scan(active, in_num_fields, in_fields, state); @@ -439,7 +445,7 @@ static void jtag_add_scan_check(struct jtag_tap *active, void (*jtag_add_scan)( void jtag_add_dr_scan_check(struct jtag_tap *active, int in_num_fields, struct scan_field *in_fields, - tap_state_t state) + enum tap_state state) { if (jtag_verify) jtag_add_scan_check(active, jtag_add_dr_scan, in_num_fields, in_fields, state); @@ -451,7 +457,7 @@ void jtag_add_dr_scan_check(struct jtag_tap *active, void jtag_add_dr_scan(struct jtag_tap *active, int in_num_fields, const struct scan_field *in_fields, - tap_state_t state) + enum tap_state state) { assert(state != TAP_RESET); @@ -463,7 +469,7 @@ void jtag_add_dr_scan(struct jtag_tap *active, } void jtag_add_plain_dr_scan(int num_bits, const uint8_t *out_bits, uint8_t *in_bits, - tap_state_t state) + enum tap_state state) { assert(out_bits); assert(state != TAP_RESET); @@ -499,7 +505,7 @@ void jtag_add_tlr(void) * * @todo Update naming conventions to stop assuming everything is JTAG. */ -int jtag_add_tms_seq(unsigned nbits, const uint8_t *seq, enum tap_state state) +int jtag_add_tms_seq(unsigned int nbits, const uint8_t *seq, enum tap_state state) { int retval; @@ -514,9 +520,9 @@ int jtag_add_tms_seq(unsigned nbits, const uint8_t *seq, enum tap_state state) return retval; } -void jtag_add_pathmove(int num_states, const tap_state_t *path) +void jtag_add_pathmove(unsigned int num_states, const enum tap_state *path) { - tap_state_t cur_state = cmd_queue_cur_state; + enum tap_state cur_state = cmd_queue_cur_state; /* the last state has to be a stable state */ if (!tap_is_state_stable(path[num_states - 1])) { @@ -525,7 +531,7 @@ void jtag_add_pathmove(int num_states, const tap_state_t *path) return; } - for (int i = 0; i < num_states; i++) { + for (unsigned int i = 0; i < num_states; i++) { if (path[i] == TAP_RESET) { LOG_ERROR("BUG: TAP_RESET is not a valid state for pathmove sequences"); jtag_set_error(ERROR_JTAG_STATE_INVALID); @@ -548,9 +554,9 @@ void jtag_add_pathmove(int num_states, const tap_state_t *path) cmd_queue_cur_state = path[num_states - 1]; } -int jtag_add_statemove(tap_state_t goal_state) +int jtag_add_statemove(enum tap_state goal_state) { - tap_state_t cur_state = cmd_queue_cur_state; + enum tap_state cur_state = cmd_queue_cur_state; if (goal_state != cur_state) { LOG_DEBUG("cur_state=%s goal_state=%s", @@ -567,12 +573,12 @@ int jtag_add_statemove(tap_state_t goal_state) /* nothing to do */; else if (tap_is_state_stable(cur_state) && tap_is_state_stable(goal_state)) { - unsigned tms_bits = tap_get_tms_path(cur_state, goal_state); - unsigned tms_count = tap_get_tms_path_len(cur_state, goal_state); - tap_state_t moves[8]; + unsigned int tms_bits = tap_get_tms_path(cur_state, goal_state); + unsigned int tms_count = tap_get_tms_path_len(cur_state, goal_state); + enum tap_state moves[8]; assert(tms_count < ARRAY_SIZE(moves)); - for (unsigned i = 0; i < tms_count; i++, tms_bits >>= 1) { + for (unsigned int i = 0; i < tms_count; i++, tms_bits >>= 1) { bool bit = tms_bits & 1; cur_state = tap_state_transition(cur_state, bit); @@ -589,14 +595,14 @@ int jtag_add_statemove(tap_state_t goal_state) return ERROR_OK; } -void jtag_add_runtest(int num_cycles, tap_state_t state) +void jtag_add_runtest(unsigned int num_cycles, enum tap_state state) { jtag_prelude(state); jtag_set_error(interface_jtag_add_runtest(num_cycles, state)); } -void jtag_add_clocks(int num_cycles) +void jtag_add_clocks(unsigned int num_cycles) { if (!tap_is_state_stable(cmd_queue_cur_state)) { LOG_ERROR("jtag_add_clocks() called with TAP in unstable state \"%s\"", @@ -625,6 +631,13 @@ static int adapter_system_reset(int req_srst) /* Maybe change SRST signal state */ if (jtag_srst != req_srst) { + if (!adapter_driver->reset) { + if (req_srst) + LOG_ERROR("Adapter driver does not implement SRST handling"); + + return ERROR_NOT_IMPLEMENTED; + } + retval = adapter_driver->reset(0, req_srst); if (retval != ERROR_OK) { LOG_ERROR("SRST error"); @@ -881,9 +894,9 @@ static int jtag_check_value_inner(uint8_t *captured, uint8_t *in_check_value, int compare_failed; if (in_check_mask) - compare_failed = buf_cmp_mask(captured, in_check_value, in_check_mask, num_bits); + compare_failed = !buf_eq_mask(captured, in_check_value, in_check_mask, num_bits); else - compare_failed = buf_cmp(captured, in_check_value, num_bits); + compare_failed = !buf_eq(captured, in_check_value, num_bits); if (compare_failed) { char *captured_str, *in_check_value_str; @@ -960,16 +973,16 @@ int default_interface_jtag_execute_queue(void) LOG_DEBUG_IO("JTAG %s SCAN to %s", cmd->cmd.scan->ir_scan ? "IR" : "DR", tap_state_name(cmd->cmd.scan->end_state)); - for (int i = 0; i < cmd->cmd.scan->num_fields; i++) { + for (unsigned int i = 0; i < cmd->cmd.scan->num_fields; i++) { struct scan_field *field = cmd->cmd.scan->fields + i; if (field->out_value) { char *str = buf_to_hex_str(field->out_value, field->num_bits); - LOG_DEBUG_IO(" %db out: %s", field->num_bits, str); + LOG_DEBUG_IO(" %ub out: %s", field->num_bits, str); free(str); } if (field->in_value) { char *str = buf_to_hex_str(field->in_value, field->num_bits); - LOG_DEBUG_IO(" %db in: %s", field->num_bits, str); + LOG_DEBUG_IO(" %ub in: %s", field->num_bits, str); free(str); } } @@ -1029,7 +1042,7 @@ void jtag_execute_queue_noclear(void) } } -int jtag_get_flush_queue_count(void) +unsigned int jtag_get_flush_queue_count(void) { return jtag_flush_queue_count; } @@ -1081,7 +1094,7 @@ void jtag_sleep(uint32_t us) /* a larger IR length than we ever expect to autoprobe */ #define JTAG_IRLEN_MAX 60 -static int jtag_examine_chain_execute(uint8_t *idcode_buffer, unsigned num_idcode) +static int jtag_examine_chain_execute(uint8_t *idcode_buffer, unsigned int num_idcode) { struct scan_field field = { .num_bits = num_idcode * 32, @@ -1090,7 +1103,7 @@ static int jtag_examine_chain_execute(uint8_t *idcode_buffer, unsigned num_idcod }; /* initialize to the end of chain ID value */ - for (unsigned i = 0; i < num_idcode; i++) + for (unsigned int i = 0; i < num_idcode; i++) buf_set_u32(idcode_buffer, i * 32, 32, END_OF_CHAIN_FLAG); jtag_add_plain_dr_scan(field.num_bits, field.out_value, field.in_value, TAP_DRPAUSE); @@ -1098,12 +1111,12 @@ static int jtag_examine_chain_execute(uint8_t *idcode_buffer, unsigned num_idcod return jtag_execute_queue(); } -static bool jtag_examine_chain_check(uint8_t *idcodes, unsigned count) +static bool jtag_examine_chain_check(uint8_t *idcodes, unsigned int count) { uint8_t zero_check = 0x0; uint8_t one_check = 0xff; - for (unsigned i = 0; i < count * 4; i++) { + for (unsigned int i = 0; i < count * 4; i++) { zero_check |= idcodes[i]; one_check &= idcodes[i]; } @@ -1158,7 +1171,8 @@ static bool jtag_idcode_is_final(uint32_t idcode) * with the JTAG chain earlier, gives more helpful/explicit error messages. * Returns TRUE iff garbage was found. */ -static bool jtag_examine_chain_end(uint8_t *idcodes, unsigned count, unsigned max) +static bool jtag_examine_chain_end(uint8_t *idcodes, unsigned int count, + unsigned int max) { bool triggered = false; for (; count < max - 31; count += 32) { @@ -1185,26 +1199,26 @@ static bool jtag_examine_chain_match_tap(const struct jtag_tap *tap) uint32_t idcode = tap->idcode & mask; /* Loop over the expected identification codes and test for a match */ - for (unsigned ii = 0; ii < tap->expected_ids_cnt; ii++) { - uint32_t expected = tap->expected_ids[ii] & mask; + for (unsigned int i = 0; i < tap->expected_ids_cnt; i++) { + uint32_t expected = tap->expected_ids[i] & mask; if (idcode == expected) return true; /* treat "-expected-id 0" as a "don't-warn" wildcard */ - if (tap->expected_ids[ii] == 0) + if (tap->expected_ids[i] == 0) return true; } /* If none of the expected ids matched, warn */ jtag_examine_chain_display(LOG_LVL_WARNING, "UNEXPECTED", tap->dotted_name, tap->idcode); - for (unsigned ii = 0; ii < tap->expected_ids_cnt; ii++) { + for (unsigned int i = 0; i < tap->expected_ids_cnt; i++) { char msg[32]; - snprintf(msg, sizeof(msg), "expected %u of %u", ii + 1, tap->expected_ids_cnt); + snprintf(msg, sizeof(msg), "expected %u of %u", i + 1, tap->expected_ids_cnt); jtag_examine_chain_display(LOG_LVL_ERROR, msg, - tap->dotted_name, tap->expected_ids[ii]); + tap->dotted_name, tap->expected_ids[i]); } return false; } @@ -1215,7 +1229,7 @@ static bool jtag_examine_chain_match_tap(const struct jtag_tap *tap) static int jtag_examine_chain(void) { int retval; - unsigned max_taps = jtag_tap_count(); + unsigned int max_taps = jtag_tap_count(); /* Autoprobe up to this many. */ if (max_taps < JTAG_MAX_AUTO_TAPS) @@ -1243,9 +1257,9 @@ static int jtag_examine_chain(void) /* Point at the 1st predefined tap, if any */ struct jtag_tap *tap = jtag_tap_next_enabled(NULL); - unsigned bit_count = 0; - unsigned autocount = 0; - for (unsigned i = 0; i < max_taps; i++) { + unsigned int bit_count = 0; + unsigned int autocount = 0; + for (unsigned int i = 0; i < max_taps; i++) { assert(bit_count < max_taps * 32); uint32_t idcode = buf_get_u32(idcode_buffer, bit_count, 32); @@ -1337,7 +1351,7 @@ static int jtag_validate_ircapture(void) int retval; /* when autoprobing, accommodate huge IR lengths */ - int total_ir_length = 0; + unsigned int total_ir_length = 0; for (tap = jtag_tap_next_enabled(NULL); tap; tap = jtag_tap_next_enabled(tap)) { if (tap->ir_length == 0) total_ir_length += JTAG_IRLEN_MAX; @@ -1396,7 +1410,7 @@ static int jtag_validate_ircapture(void) && tap->ir_length < JTAG_IRLEN_MAX) { tap->ir_length++; } - LOG_WARNING("AUTO %s - use \"jtag newtap %s %s -irlen %d " + LOG_WARNING("AUTO %s - use \"jtag newtap %s %s -irlen %u " "-expected-id 0x%08" PRIx32 "\"", tap->dotted_name, tap->chip, tap->tapname, tap->ir_length, tap->idcode); } @@ -1445,8 +1459,8 @@ done: void jtag_tap_init(struct jtag_tap *tap) { - unsigned ir_len_bits; - unsigned ir_len_bytes; + unsigned int ir_len_bits; + unsigned int ir_len_bytes; /* if we're autoprobing, cope with potentially huge ir_length */ ir_len_bits = tap->ir_length ? tap->ir_length : JTAG_IRLEN_MAX; @@ -1471,11 +1485,10 @@ void jtag_tap_init(struct jtag_tap *tap) jtag_register_event_callback(&jtag_reset_callback, tap); jtag_tap_add(tap); - LOG_DEBUG("Created Tap: %s @ abs position %d, " - "irlen %d, capture: 0x%x mask: 0x%x", tap->dotted_name, + LOG_DEBUG("Created Tap: %s @ abs position %u, " + "irlen %u, capture: 0x%" PRIx32 " mask: 0x%" PRIx32, tap->dotted_name, tap->abs_chain_position, tap->ir_length, - (unsigned) tap->ir_capture_value, - (unsigned) tap->ir_capture_mask); + tap->ir_capture_value, tap->ir_capture_mask); } void jtag_tap_free(struct jtag_tap *tap) @@ -1749,37 +1762,36 @@ int jtag_get_srst(void) return jtag_srst == 1; } -void jtag_set_nsrst_delay(unsigned delay) +void jtag_set_nsrst_delay(unsigned int delay) { adapter_nsrst_delay = delay; } -unsigned jtag_get_nsrst_delay(void) +unsigned int jtag_get_nsrst_delay(void) { return adapter_nsrst_delay; } -void jtag_set_ntrst_delay(unsigned delay) +void jtag_set_ntrst_delay(unsigned int delay) { jtag_ntrst_delay = delay; } -unsigned jtag_get_ntrst_delay(void) +unsigned int jtag_get_ntrst_delay(void) { return jtag_ntrst_delay; } - -void jtag_set_nsrst_assert_width(unsigned delay) +void jtag_set_nsrst_assert_width(unsigned int delay) { adapter_nsrst_assert_width = delay; } -unsigned jtag_get_nsrst_assert_width(void) +unsigned int jtag_get_nsrst_assert_width(void) { return adapter_nsrst_assert_width; } -void jtag_set_ntrst_assert_width(unsigned delay) +void jtag_set_ntrst_assert_width(unsigned int delay) { jtag_ntrst_assert_width = delay; } -unsigned jtag_get_ntrst_assert_width(void) +unsigned int jtag_get_ntrst_assert_width(void) { return jtag_ntrst_assert_width; } diff --git a/src/jtag/drivers/Makefile.am b/src/jtag/drivers/Makefile.am index e404afe..b0dd8e3 100644 --- a/src/jtag/drivers/Makefile.am +++ b/src/jtag/drivers/Makefile.am @@ -10,10 +10,8 @@ noinst_LTLIBRARIES += %D%/libocdjtagdrivers.la %C%_libocdjtagdrivers_la_CPPFLAGS = $(AM_CPPFLAGS) ULINK_FIRMWARE = %D%/OpenULINK -ANGIE_FILES = %D%/angie EXTRA_DIST += $(ULINK_FIRMWARE) \ - $(ANGIE_FILES) \ %D%/usb_blaster/README.CheapClone \ %D%/Makefile.rlink \ %D%/rlink_call.m4 \ @@ -125,12 +123,17 @@ ulinkdir = $(pkgdatadir)/OpenULINK dist_ulink_DATA = $(ULINK_FIRMWARE)/ulink_firmware.hex %C%_libocdjtagdrivers_la_LIBADD += -lm endif + if ANGIE -DRIVERFILES += %D%/angie.c -angiedir = $(pkgdatadir)/angie -dist_angie_DATA = $(ANGIE_FILES)/angie_firmware.bin $(ANGIE_FILES)/angie_bitstream.bit -%C%_libocdjtagdrivers_la_LIBADD += -lm + angiedir = $(pkgdatadir)/angie + DRIVERFILES += %D%/angie.c + DRIVERFILES += %D%/angie/include/msgtypes.h + EXTRA_DIST += %D%/angie/README + dist_angie_DATA = %D%/angie/angie_firmware.bin + dist_angie_DATA += %D%/angie/angie_bitstream.bit + %C%_libocdjtagdrivers_la_LIBADD += -lm endif + if VSLLINK DRIVERFILES += %D%/versaloon/usbtoxxx/usbtogpio.c DRIVERFILES += %D%/versaloon/usbtoxxx/usbtojtagraw.c @@ -143,7 +146,7 @@ endif if ARMJTAGEW DRIVERFILES += %D%/arm-jtag-ew.c endif -if BUSPIRATE +if BUS_PIRATE DRIVERFILES += %D%/buspirate.c endif if REMOTE_BITBANG @@ -173,6 +176,9 @@ endif if SYSFSGPIO DRIVERFILES += %D%/sysfsgpio.c endif +if LINUXSPIDEV +DRIVERFILES += %D%/linuxspidev.c +endif if XLNX_PCIE_XVC DRIVERFILES += %D%/xlnx-pcie-xvc.c endif diff --git a/src/jtag/drivers/am335xgpio.c b/src/jtag/drivers/am335xgpio.c index cfe41c3..cacf4e7 100644 --- a/src/jtag/drivers/am335xgpio.c +++ b/src/jtag/drivers/am335xgpio.c @@ -206,7 +206,7 @@ static void restore_gpio(enum adapter_gpio_config_index idx) } } -static bb_value_t am335xgpio_read(void) +static enum bb_value am335xgpio_read(void) { return get_gpio_value(&adapter_gpio_config[ADAPTER_GPIO_IDX_TDO]) ? BB_HIGH : BB_LOW; } @@ -275,15 +275,15 @@ static int am335xgpio_swdio_read(void) return get_gpio_value(&adapter_gpio_config[ADAPTER_GPIO_IDX_SWDIO]); } -static int am335xgpio_blink(int on) +static int am335xgpio_blink(bool on) { if (is_gpio_config_valid(&adapter_gpio_config[ADAPTER_GPIO_IDX_LED])) - set_gpio_value(&adapter_gpio_config[ADAPTER_GPIO_IDX_LED], on); + set_gpio_value(&adapter_gpio_config[ADAPTER_GPIO_IDX_LED], on ? 1 : 0); return ERROR_OK; } -static struct bitbang_interface am335xgpio_bitbang = { +static const struct bitbang_interface am335xgpio_bitbang = { .read = am335xgpio_read, .write = am335xgpio_write, .swdio_read = am335xgpio_swdio_read, diff --git a/src/jtag/drivers/amt_jtagaccel.c b/src/jtag/drivers/amt_jtagaccel.c index b28ce62..80254ff 100644 --- a/src/jtag/drivers/amt_jtagaccel.c +++ b/src/jtag/drivers/amt_jtagaccel.c @@ -146,7 +146,7 @@ static int amt_jtagaccel_speed(int speed) return ERROR_OK; } -static void amt_jtagaccel_end_state(tap_state_t state) +static void amt_jtagaccel_end_state(enum tap_state state) { if (tap_is_state_stable(state)) tap_set_end_state(state); @@ -179,8 +179,8 @@ static void amt_jtagaccel_state_move(void) uint8_t aw_scan_tms_5; uint8_t tms_scan[2]; - tap_state_t cur_state = tap_get_state(); - tap_state_t end_state = tap_get_end_state(); + enum tap_state cur_state = tap_get_state(); + enum tap_state end_state = tap_get_end_state(); tms_scan[0] = amt_jtagaccel_tap_move[tap_move_ndx(cur_state)][tap_move_ndx(end_state)][0]; tms_scan[1] = amt_jtagaccel_tap_move[tap_move_ndx(cur_state)][tap_move_ndx(end_state)][1]; @@ -203,13 +203,13 @@ static void amt_jtagaccel_state_move(void) tap_set_state(end_state); } -static void amt_jtagaccel_runtest(int num_cycles) +static void amt_jtagaccel_runtest(unsigned int num_cycles) { int i = 0; uint8_t aw_scan_tms_5; uint8_t aw_scan_tms_1to4; - tap_state_t saved_end_state = tap_get_end_state(); + enum tap_state saved_end_state = tap_get_end_state(); /* only do a state_move when we're not already in IDLE */ if (tap_get_state() != TAP_IDLE) { @@ -237,7 +237,7 @@ static void amt_jtagaccel_scan(bool ir_scan, enum scan_type type, uint8_t *buffe { int bits_left = scan_size; int bit_count = 0; - tap_state_t saved_end_state = tap_get_end_state(); + enum tap_state saved_end_state = tap_get_end_state(); uint8_t aw_tdi_option; uint8_t dw_tdi_scan; uint8_t dr_tdo; diff --git a/src/jtag/drivers/angie.c b/src/jtag/drivers/angie.c index 81dd1af..46a4c82 100644 --- a/src/jtag/drivers/angie.c +++ b/src/jtag/drivers/angie.c @@ -219,7 +219,7 @@ static int angie_append_test_cmd(struct angie *device); static int angie_calculate_delay(enum angie_delay_type type, long f, int *delay); /* Interface between ANGIE and OpenOCD */ -static void angie_set_end_state(tap_state_t endstate); +static void angie_set_end_state(enum tap_state endstate); static int angie_queue_statemove(struct angie *device); static int angie_queue_scan(struct angie *device, struct jtag_command *cmd); @@ -1519,7 +1519,7 @@ static long angie_calculate_frequency(enum angie_delay_type type, int delay) * * @param endstate the state the end state follower should be set to. */ -static void angie_set_end_state(tap_state_t endstate) +static void angie_set_end_state(enum tap_state endstate) { if (tap_is_state_stable(endstate)) tap_set_end_state(endstate); @@ -1836,15 +1836,17 @@ static int angie_reset(int trst, int srst) */ static int angie_queue_pathmove(struct angie *device, struct jtag_command *cmd) { - int ret, i, num_states, batch_size, state_count; - tap_state_t *path; + int ret, state_count; + enum tap_state *path; uint8_t tms_sequence; - num_states = cmd->cmd.pathmove->num_states; + unsigned int num_states = cmd->cmd.pathmove->num_states; path = cmd->cmd.pathmove->path; state_count = 0; while (num_states > 0) { + unsigned int batch_size; + tms_sequence = 0; /* Determine batch size */ @@ -1853,7 +1855,7 @@ static int angie_queue_pathmove(struct angie *device, struct jtag_command *cmd) else batch_size = num_states; - for (i = 0; i < batch_size; i++) { + for (unsigned int i = 0; i < batch_size; i++) { if (tap_state_transition(tap_get_state(), false) == path[state_count]) { /* Append '0' transition: clear bit 'i' in tms_sequence */ buf_set_u32(&tms_sequence, i, 1, 0x0); @@ -1908,14 +1910,13 @@ static int angie_queue_sleep(struct angie *device, struct jtag_command *cmd) static int angie_queue_stableclocks(struct angie *device, struct jtag_command *cmd) { int ret; - unsigned int num_cycles; if (!tap_is_state_stable(tap_get_state())) { LOG_ERROR("JTAG_STABLECLOCKS: state not stable"); return ERROR_FAIL; } - num_cycles = cmd->cmd.stableclocks->num_cycles; + unsigned int num_cycles = cmd->cmd.stableclocks->num_cycles; /* TMS stays either high (Test Logic Reset state) or low (all other states) */ if (tap_get_state() == TAP_RESET) diff --git a/src/jtag/drivers/arm-jtag-ew.c b/src/jtag/drivers/arm-jtag-ew.c index 4c50c54..45e0384 100644 --- a/src/jtag/drivers/arm-jtag-ew.c +++ b/src/jtag/drivers/arm-jtag-ew.c @@ -42,10 +42,10 @@ static uint8_t usb_in_buffer[ARMJTAGEW_IN_BUFFER_SIZE]; static uint8_t usb_out_buffer[ARMJTAGEW_OUT_BUFFER_SIZE]; /* Queue command functions */ -static void armjtagew_end_state(tap_state_t state); +static void armjtagew_end_state(enum tap_state state); static void armjtagew_state_move(void); -static void armjtagew_path_move(int num_states, tap_state_t *path); -static void armjtagew_runtest(int num_cycles); +static void armjtagew_path_move(unsigned int num_states, enum tap_state *path); +static void armjtagew_runtest(unsigned int num_cycles); static void armjtagew_scan(bool ir_scan, enum scan_type type, uint8_t *buffer, @@ -95,7 +95,7 @@ static int armjtagew_execute_queue(struct jtag_command *cmd_queue) while (cmd) { switch (cmd->type) { case JTAG_RUNTEST: - LOG_DEBUG_IO("runtest %i cycles, end in %i", + LOG_DEBUG_IO("runtest %u cycles, end in %i", cmd->cmd.runtest->num_cycles, cmd->cmd.runtest->end_state); @@ -111,7 +111,7 @@ static int armjtagew_execute_queue(struct jtag_command *cmd_queue) break; case JTAG_PATHMOVE: - LOG_DEBUG_IO("pathmove: %i states, end in %i", + LOG_DEBUG_IO("pathmove: %u states, end in %i", cmd->cmd.pathmove->num_states, cmd->cmd.pathmove->path[cmd->cmd.pathmove->num_states - 1]); @@ -253,7 +253,7 @@ static int armjtagew_quit(void) /************************************************************************** * Queue command implementations */ -static void armjtagew_end_state(tap_state_t state) +static void armjtagew_end_state(enum tap_state state) { if (tap_is_state_stable(state)) tap_set_end_state(state); @@ -279,11 +279,9 @@ static void armjtagew_state_move(void) tap_set_state(tap_get_end_state()); } -static void armjtagew_path_move(int num_states, tap_state_t *path) +static void armjtagew_path_move(unsigned int num_states, enum tap_state *path) { - int i; - - for (i = 0; i < num_states; i++) { + for (unsigned int i = 0; i < num_states; i++) { /* * TODO: The ARM-JTAG-EW hardware delays TDI with 3 TCK cycles when in RTCK mode. * Either handle that here, or update the documentation with examples @@ -305,11 +303,9 @@ static void armjtagew_path_move(int num_states, tap_state_t *path) tap_set_end_state(tap_get_state()); } -static void armjtagew_runtest(int num_cycles) +static void armjtagew_runtest(unsigned int num_cycles) { - int i; - - tap_state_t saved_end_state = tap_get_end_state(); + enum tap_state saved_end_state = tap_get_end_state(); /* only do a state_move when we're not already in IDLE */ if (tap_get_state() != TAP_IDLE) { @@ -318,7 +314,7 @@ static void armjtagew_runtest(int num_cycles) } /* execute num_cycles */ - for (i = 0; i < num_cycles; i++) + for (unsigned int i = 0; i < num_cycles; i++) armjtagew_tap_append_step(0, 0); /* finish in end_state */ @@ -333,7 +329,7 @@ static void armjtagew_scan(bool ir_scan, int scan_size, struct scan_command *command) { - tap_state_t saved_end_state; + enum tap_state saved_end_state; armjtagew_tap_ensure_space(1, scan_size + 8); diff --git a/src/jtag/drivers/at91rm9200.c b/src/jtag/drivers/at91rm9200.c index ba9ee5e..a77e29a 100644 --- a/src/jtag/drivers/at91rm9200.c +++ b/src/jtag/drivers/at91rm9200.c @@ -98,19 +98,19 @@ static uint32_t *pio_base; /* low level command set */ -static bb_value_t at91rm9200_read(void); +static enum bb_value at91rm9200_read(void); static int at91rm9200_write(int tck, int tms, int tdi); static int at91rm9200_init(void); static int at91rm9200_quit(void); -static struct bitbang_interface at91rm9200_bitbang = { +static const struct bitbang_interface at91rm9200_bitbang = { .read = at91rm9200_read, .write = at91rm9200_write, .blink = NULL, }; -static bb_value_t at91rm9200_read(void) +static enum bb_value at91rm9200_read(void) { return (pio_base[device->TDO_PIO + PIO_PDSR] & device->TDO_MASK) ? BB_HIGH : BB_LOW; } diff --git a/src/jtag/drivers/bcm2835gpio.c b/src/jtag/drivers/bcm2835gpio.c index ff10b0a..e8689aa 100644 --- a/src/jtag/drivers/bcm2835gpio.c +++ b/src/jtag/drivers/bcm2835gpio.c @@ -31,16 +31,28 @@ static off_t bcm2835_peri_base = 0x20000000; #define BCM2835_GPIO_MODE_OUTPUT 1 /* GPIO setup macros */ -#define MODE_GPIO(g) (*(pio_base+((g)/10))>>(((g)%10)*3) & 7) -#define INP_GPIO(g) do { *(pio_base+((g)/10)) &= ~(7<<(((g)%10)*3)); } while (0) -#define SET_MODE_GPIO(g, m) do { /* clear the mode bits first, then set as necessary */ \ - INP_GPIO(g); \ - *(pio_base+((g)/10)) |= ((m)<<(((g)%10)*3)); } while (0) +#define MODE_GPIO(_g) ({ \ + typeof(_g) g = (_g); \ + *(pio_base + (g / 10)) >> ((g % 10) * 3) & 7; \ +}) + +#define INP_GPIO(_g) do { \ + typeof(_g) g1 = (_g); \ + *(pio_base + (g1 / 10)) &= ~(7 << ((g1 % 10) * 3)); \ +} while (0) + +#define SET_MODE_GPIO(_g, m) do { \ + typeof(_g) g = (_g); \ + /* clear the mode bits first, then set as necessary */ \ + INP_GPIO(g); \ + *(pio_base + (g / 10)) |= ((m) << ((g % 10) * 3)); \ +} while (0) + #define OUT_GPIO(g) SET_MODE_GPIO(g, BCM2835_GPIO_MODE_OUTPUT) -#define GPIO_SET (*(pio_base+7)) /* sets bits which are 1, ignores bits which are 0 */ -#define GPIO_CLR (*(pio_base+10)) /* clears bits which are 1, ignores bits which are 0 */ -#define GPIO_LEV (*(pio_base+13)) /* current level of the pin */ +#define GPIO_SET (*(pio_base + 7)) /* sets bits which are 1, ignores bits which are 0 */ +#define GPIO_CLR (*(pio_base + 10)) /* clears bits which are 1, ignores bits which are 0 */ +#define GPIO_LEV (*(pio_base + 13)) /* current level of the pin */ static int dev_mem_fd; static volatile uint32_t *pio_base = MAP_FAILED; @@ -170,12 +182,11 @@ static void initialize_gpio(enum adapter_gpio_config_index idx) bcm2835_gpio_synchronize(); } -static bb_value_t bcm2835gpio_read(void) +static enum bb_value bcm2835gpio_read(void) { unsigned int shift = adapter_gpio_config[ADAPTER_GPIO_IDX_TDO].gpio_num; uint32_t value = (GPIO_LEV >> shift) & 1; return value ^ (adapter_gpio_config[ADAPTER_GPIO_IDX_TDO].active_low ? BB_HIGH : BB_LOW); - } static int bcm2835gpio_write(int tck, int tms, int tdi) @@ -408,15 +419,15 @@ static void bcm2835gpio_munmap(void) } } -static int bcm2835gpio_blink(int on) +static int bcm2835gpio_blink(bool on) { if (is_gpio_config_valid(ADAPTER_GPIO_IDX_LED)) - set_gpio_value(&adapter_gpio_config[ADAPTER_GPIO_IDX_LED], on); + set_gpio_value(&adapter_gpio_config[ADAPTER_GPIO_IDX_LED], on ? 1 : 0); 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, @@ -425,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()) { @@ -498,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 @@ -518,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/bitbang.c b/src/jtag/drivers/bitbang.c index 3d839e6..c2e763d 100644 --- a/src/jtag/drivers/bitbang.c +++ b/src/jtag/drivers/bitbang.c @@ -33,11 +33,11 @@ * this function checks the current stable state to decide on the value of TMS * to use. */ -static int bitbang_stableclocks(int num_cycles); +static int bitbang_stableclocks(unsigned int num_cycles); static void bitbang_swd_write_reg(uint8_t cmd, uint32_t value, uint32_t ap_delay_clk); -struct bitbang_interface *bitbang_interface; +const struct bitbang_interface *bitbang_interface; /* DANGER!!!! clock absolutely *MUST* be 0 in idle or reset won't work! * @@ -60,7 +60,7 @@ struct bitbang_interface *bitbang_interface; #define CLOCK_IDLE() 0 /* The bitbang driver leaves the TCK 0 when in idle */ -static void bitbang_end_state(tap_state_t state) +static void bitbang_end_state(enum tap_state state) { assert(tap_is_state_stable(state)); tap_set_end_state(state); @@ -92,13 +92,13 @@ static int bitbang_state_move(int skip) */ static int bitbang_execute_tms(struct jtag_command *cmd) { - unsigned num_bits = cmd->cmd.tms->num_bits; + unsigned int num_bits = cmd->cmd.tms->num_bits; const uint8_t *bits = cmd->cmd.tms->bits; - LOG_DEBUG_IO("TMS: %d bits", num_bits); + LOG_DEBUG_IO("TMS: %u bits", num_bits); int tms = 0; - for (unsigned i = 0; i < num_bits; i++) { + for (unsigned int i = 0; i < num_bits; i++) { tms = ((bits[i/8] >> (i % 8)) & 1); if (bitbang_interface->write(0, tms, 0) != ERROR_OK) return ERROR_FAIL; @@ -113,7 +113,7 @@ static int bitbang_execute_tms(struct jtag_command *cmd) static int bitbang_path_move(struct pathmove_command *cmd) { - int num_states = cmd->num_states; + unsigned int num_states = cmd->num_states; int state_count; int tms = 0; @@ -147,11 +147,9 @@ static int bitbang_path_move(struct pathmove_command *cmd) return ERROR_OK; } -static int bitbang_runtest(int num_cycles) +static int bitbang_runtest(unsigned int num_cycles) { - int i; - - tap_state_t saved_end_state = tap_get_end_state(); + enum tap_state saved_end_state = tap_get_end_state(); /* only do a state_move when we're not already in IDLE */ if (tap_get_state() != TAP_IDLE) { @@ -161,7 +159,7 @@ static int bitbang_runtest(int num_cycles) } /* execute num_cycles */ - for (i = 0; i < num_cycles; i++) { + for (unsigned int i = 0; i < num_cycles; i++) { if (bitbang_interface->write(0, 0, 0) != ERROR_OK) return ERROR_FAIL; if (bitbang_interface->write(1, 0, 0) != ERROR_OK) @@ -179,13 +177,12 @@ static int bitbang_runtest(int num_cycles) return ERROR_OK; } -static int bitbang_stableclocks(int num_cycles) +static int bitbang_stableclocks(unsigned int num_cycles) { int tms = (tap_get_state() == TAP_RESET ? 1 : 0); - int i; /* send num_cycles clocks onto the cable */ - for (i = 0; i < num_cycles; i++) { + for (unsigned int i = 0; i < num_cycles; i++) { if (bitbang_interface->write(1, tms, 0) != ERROR_OK) return ERROR_FAIL; if (bitbang_interface->write(0, tms, 0) != ERROR_OK) @@ -196,10 +193,10 @@ static int bitbang_stableclocks(int num_cycles) } static int bitbang_scan(bool ir_scan, enum scan_type type, uint8_t *buffer, - unsigned scan_size) + unsigned int scan_size) { - tap_state_t saved_end_state = tap_get_end_state(); - unsigned bit_cnt; + enum tap_state saved_end_state = tap_get_end_state(); + unsigned int bit_cnt; if (!((!ir_scan && (tap_get_state() == TAP_DRSHIFT)) || @@ -257,7 +254,7 @@ static int bitbang_scan(bool ir_scan, enum scan_type type, uint8_t *buffer, if (type != SCAN_OUT && bitbang_interface->buf_size && (buffered == bitbang_interface->buf_size || bit_cnt == scan_size - 1)) { - for (unsigned i = bit_cnt + 1 - buffered; i <= bit_cnt; i++) { + for (unsigned int i = bit_cnt + 1 - buffered; i <= bit_cnt; i++) { switch (bitbang_interface->read_sample()) { case BB_LOW: buffer[i/8] &= ~(1 << (i % 8)); @@ -312,14 +309,14 @@ int bitbang_execute_queue(struct jtag_command *cmd_queue) retval = ERROR_OK; if (bitbang_interface->blink) { - if (bitbang_interface->blink(1) != ERROR_OK) + if (bitbang_interface->blink(true) != ERROR_OK) return ERROR_FAIL; } while (cmd) { switch (cmd->type) { case JTAG_RUNTEST: - LOG_DEBUG_IO("runtest %i cycles, end in %s", + LOG_DEBUG_IO("runtest %u cycles, end in %s", cmd->cmd.runtest->num_cycles, tap_state_name(cmd->cmd.runtest->end_state)); bitbang_end_state(cmd->cmd.runtest->end_state); @@ -343,7 +340,7 @@ int bitbang_execute_queue(struct jtag_command *cmd_queue) return ERROR_FAIL; break; case JTAG_PATHMOVE: - LOG_DEBUG_IO("pathmove: %i states, end in %s", + LOG_DEBUG_IO("pathmove: %u states, end in %s", cmd->cmd.pathmove->num_states, tap_state_name(cmd->cmd.pathmove->path[cmd->cmd.pathmove->num_states - 1])); if (bitbang_path_move(cmd->cmd.pathmove) != ERROR_OK) @@ -380,7 +377,7 @@ int bitbang_execute_queue(struct jtag_command *cmd_queue) cmd = cmd->next; } if (bitbang_interface->blink) { - if (bitbang_interface->blink(0) != ERROR_OK) + if (bitbang_interface->blink(false) != ERROR_OK) return ERROR_FAIL; } @@ -399,7 +396,7 @@ static void bitbang_swd_exchange(bool rnw, uint8_t buf[], unsigned int offset, u { if (bitbang_interface->blink) { /* FIXME: we should manage errors */ - bitbang_interface->blink(1); + bitbang_interface->blink(true); } for (unsigned int i = offset; i < bit_cnt + offset; i++) { @@ -421,7 +418,7 @@ static void bitbang_swd_exchange(bool rnw, uint8_t buf[], unsigned int offset, u if (bitbang_interface->blink) { /* FIXME: we should manage errors */ - bitbang_interface->blink(0); + bitbang_interface->blink(false); } } diff --git a/src/jtag/drivers/bitbang.h b/src/jtag/drivers/bitbang.h index dc94179..6afa409 100644 --- a/src/jtag/drivers/bitbang.h +++ b/src/jtag/drivers/bitbang.h @@ -14,11 +14,11 @@ #include <jtag/swd.h> #include <jtag/commands.h> -typedef enum { +enum bb_value { BB_LOW, BB_HIGH, BB_ERROR -} bb_value_t; +}; /** Low level callbacks (for bitbang). * @@ -29,7 +29,7 @@ typedef enum { * increase throughput. */ struct bitbang_interface { /** Sample TDO and return the value. */ - bb_value_t (*read)(void); + enum bb_value (*read)(void); /** The number of TDO samples that can be buffered up before the caller has * to call read_sample. */ @@ -39,13 +39,13 @@ struct bitbang_interface { int (*sample)(void); /** Return the next unread value from the buffer. */ - bb_value_t (*read_sample)(void); + enum bb_value (*read_sample)(void); /** Set TCK, TMS, and TDI to the given values. */ int (*write)(int tck, int tms, int tdi); /** Blink led (optional). */ - int (*blink)(int on); + int (*blink)(bool on); /** Sample SWDIO and return the value. */ int (*swdio_read)(void); @@ -67,6 +67,6 @@ extern const struct swd_driver bitbang_swd; int bitbang_execute_queue(struct jtag_command *cmd_queue); -extern struct bitbang_interface *bitbang_interface; +extern const struct bitbang_interface *bitbang_interface; #endif /* OPENOCD_JTAG_DRIVERS_BITBANG_H */ diff --git a/src/jtag/drivers/bitq.c b/src/jtag/drivers/bitq.c index 2e5cca2..84acff8 100644 --- a/src/jtag/drivers/bitq.c +++ b/src/jtag/drivers/bitq.c @@ -18,8 +18,8 @@ struct bitq_interface *bitq_interface; /* low level bit queue interface */ /* state of input queue */ struct bitq_state { struct jtag_command *cmd; /* command currently processed */ - int field_idx; /* index of field currently being processed */ - int bit_pos; /* position of bit currently being processed */ + unsigned int field_idx; /* index of field currently being processed */ + unsigned int bit_pos; /* position of bit currently being processed */ int status; /* processing status */ }; static struct bitq_state bitq_in_state; @@ -76,7 +76,7 @@ static void bitq_io(int tms, int tdi, int tdo_req) bitq_in_proc(); } -static void bitq_end_state(tap_state_t state) +static void bitq_end_state(enum tap_state state) { if (!tap_is_state_stable(state)) { LOG_ERROR("BUG: %i is not a valid end state", state); @@ -85,7 +85,7 @@ static void bitq_end_state(tap_state_t state) tap_set_end_state(state); } -static void bitq_state_move(tap_state_t new_state) +static void bitq_state_move(enum tap_state new_state) { int i = 0; uint8_t tms_scan; @@ -108,9 +108,7 @@ static void bitq_state_move(tap_state_t new_state) static void bitq_path_move(struct pathmove_command *cmd) { - int i; - - for (i = 0; i < cmd->num_states; i++) { + for (unsigned int i = 0; i < cmd->num_states; i++) { if (tap_state_transition(tap_get_state(), false) == cmd->path[i]) bitq_io(0, 0, 0); else if (tap_state_transition(tap_get_state(), true) == cmd->path[i]) @@ -127,16 +125,14 @@ static void bitq_path_move(struct pathmove_command *cmd) tap_set_end_state(tap_get_state()); } -static void bitq_runtest(int num_cycles) +static void bitq_runtest(unsigned int num_cycles) { - int i; - /* only do a state_move when we're not already in IDLE */ if (tap_get_state() != TAP_IDLE) bitq_state_move(TAP_IDLE); /* execute num_cycles */ - for (i = 0; i < num_cycles; i++) + for (unsigned int i = 0; i < num_cycles; i++) bitq_io(0, 0, 0); /* finish in end_state */ @@ -146,11 +142,10 @@ static void bitq_runtest(int num_cycles) static void bitq_scan_field(struct scan_field *field, int do_pause) { - int bit_cnt; int tdo_req; const uint8_t *out_ptr; - uint8_t out_mask; + uint8_t out_mask; if (field->in_value) tdo_req = 1; @@ -159,7 +154,7 @@ static void bitq_scan_field(struct scan_field *field, int do_pause) if (!field->out_value) { /* just send zeros and request data from TDO */ - for (bit_cnt = field->num_bits; bit_cnt > 1; bit_cnt--) + for (unsigned int i = 0; i < (field->num_bits - 1); i++) bitq_io(0, 0, tdo_req); bitq_io(do_pause, 0, tdo_req); @@ -167,7 +162,7 @@ static void bitq_scan_field(struct scan_field *field, int do_pause) /* send data, and optionally request TDO */ out_mask = 0x01; out_ptr = field->out_value; - for (bit_cnt = field->num_bits; bit_cnt > 1; bit_cnt--) { + for (unsigned int i = 0; i < (field->num_bits - 1); i++) { bitq_io(0, ((*out_ptr) & out_mask) != 0, tdo_req); if (out_mask == 0x80) { out_mask = 0x01; @@ -190,13 +185,12 @@ static void bitq_scan_field(struct scan_field *field, int do_pause) static void bitq_scan(struct scan_command *cmd) { - int i; - if (cmd->ir_scan) bitq_state_move(TAP_IRSHIFT); else bitq_state_move(TAP_DRSHIFT); + unsigned int i; for (i = 0; i < cmd->num_fields - 1; i++) bitq_scan_field(&cmd->fields[i], 0); @@ -226,7 +220,7 @@ int bitq_execute_queue(struct jtag_command *cmd_queue) break; case JTAG_RUNTEST: - LOG_DEBUG_IO("runtest %i cycles, end in %i", cmd->cmd.runtest->num_cycles, cmd->cmd.runtest->end_state); + LOG_DEBUG_IO("runtest %u cycles, end in %i", cmd->cmd.runtest->num_cycles, cmd->cmd.runtest->end_state); bitq_end_state(cmd->cmd.runtest->end_state); bitq_runtest(cmd->cmd.runtest->num_cycles); break; @@ -238,7 +232,7 @@ int bitq_execute_queue(struct jtag_command *cmd_queue) break; case JTAG_PATHMOVE: - LOG_DEBUG_IO("pathmove: %i states, end in %i", cmd->cmd.pathmove->num_states, + LOG_DEBUG_IO("pathmove: %u states, end in %i", cmd->cmd.pathmove->num_states, cmd->cmd.pathmove->path[cmd->cmd.pathmove->num_states - 1]); bitq_path_move(cmd->cmd.pathmove); break; diff --git a/src/jtag/drivers/buspirate.c b/src/jtag/drivers/buspirate.c index 3b03337..93f0ba3 100644 --- a/src/jtag/drivers/buspirate.c +++ b/src/jtag/drivers/buspirate.c @@ -25,13 +25,13 @@ static int buspirate_init(void); static int buspirate_quit(void); static int buspirate_reset(int trst, int srst); -static void buspirate_end_state(tap_state_t state); +static void buspirate_end_state(enum tap_state state); static void buspirate_state_move(void); -static void buspirate_path_move(int num_states, tap_state_t *path); -static void buspirate_runtest(int num_cycles); +static void buspirate_path_move(unsigned int num_states, enum tap_state *path); +static void buspirate_runtest(unsigned int num_cycles); static void buspirate_scan(bool ir_scan, enum scan_type type, uint8_t *buffer, int scan_size, struct scan_command *command); -static void buspirate_stableclocks(int num_cycles); +static void buspirate_stableclocks(unsigned int num_cycles); #define CMD_UNKNOWN 0x00 #define CMD_PORT_MODE 0x01 @@ -162,7 +162,7 @@ static int buspirate_execute_queue(struct jtag_command *cmd_queue) while (cmd) { switch (cmd->type) { case JTAG_RUNTEST: - LOG_DEBUG_IO("runtest %i cycles, end in %s", + LOG_DEBUG_IO("runtest %u cycles, end in %s", cmd->cmd.runtest->num_cycles, tap_state_name(cmd->cmd.runtest ->end_state)); @@ -180,7 +180,7 @@ static int buspirate_execute_queue(struct jtag_command *cmd_queue) buspirate_state_move(); break; case JTAG_PATHMOVE: - LOG_DEBUG_IO("pathmove: %i states, end in %s", + LOG_DEBUG_IO("pathmove: %u states, end in %s", cmd->cmd.pathmove->num_states, tap_state_name(cmd->cmd.pathmove ->path[cmd->cmd.pathmove @@ -210,7 +210,7 @@ static int buspirate_execute_queue(struct jtag_command *cmd_queue) jtag_sleep(cmd->cmd.sleep->us); break; case JTAG_STABLECLOCKS: - LOG_DEBUG_IO("stable clock %i cycles", cmd->cmd.stableclocks->num_cycles); + LOG_DEBUG_IO("stable clock %u cycles", cmd->cmd.stableclocks->num_cycles); buspirate_stableclocks(cmd->cmd.stableclocks->num_cycles); break; default: @@ -554,7 +554,7 @@ struct adapter_driver buspirate_adapter_driver = { }; /*************** jtag execute commands **********************/ -static void buspirate_end_state(tap_state_t state) +static void buspirate_end_state(enum tap_state state) { if (tap_is_state_stable(state)) tap_set_end_state(state); @@ -580,11 +580,9 @@ static void buspirate_state_move(void) tap_set_state(tap_get_end_state()); } -static void buspirate_path_move(int num_states, tap_state_t *path) +static void buspirate_path_move(unsigned int num_states, enum tap_state *path) { - int i; - - for (i = 0; i < num_states; i++) { + for (unsigned int i = 0; i < num_states; i++) { if (tap_state_transition(tap_get_state(), false) == path[i]) { buspirate_tap_append(0, 0); } else if (tap_state_transition(tap_get_state(), true) @@ -604,11 +602,9 @@ static void buspirate_path_move(int num_states, tap_state_t *path) tap_set_end_state(tap_get_state()); } -static void buspirate_runtest(int num_cycles) +static void buspirate_runtest(unsigned int num_cycles) { - int i; - - tap_state_t saved_end_state = tap_get_end_state(); + enum tap_state saved_end_state = tap_get_end_state(); /* only do a state_move when we're not already in IDLE */ if (tap_get_state() != TAP_IDLE) { @@ -616,7 +612,7 @@ static void buspirate_runtest(int num_cycles) buspirate_state_move(); } - for (i = 0; i < num_cycles; i++) + for (unsigned int i = 0; i < num_cycles; i++) buspirate_tap_append(0, 0); LOG_DEBUG_IO("runtest: cur_state %s end_state %s", @@ -632,7 +628,7 @@ static void buspirate_runtest(int num_cycles) static void buspirate_scan(bool ir_scan, enum scan_type type, uint8_t *buffer, int scan_size, struct scan_command *command) { - tap_state_t saved_end_state; + enum tap_state saved_end_state; buspirate_tap_make_space(1, scan_size+8); /* is 8 correct ? (2 moves = 16) */ @@ -658,14 +654,13 @@ static void buspirate_scan(bool ir_scan, enum scan_type type, buspirate_state_move(); } -static void buspirate_stableclocks(int num_cycles) +static void buspirate_stableclocks(unsigned int num_cycles) { - int i; int tms = (tap_get_state() == TAP_RESET ? 1 : 0); buspirate_tap_make_space(0, num_cycles); - for (i = 0; i < num_cycles; i++) + for (unsigned int i = 0; i < num_cycles; i++) buspirate_tap_append(tms, 0); } @@ -1447,7 +1442,7 @@ static void buspirate_swd_read_reg(uint8_t cmd, uint32_t *value, uint32_t ap_del data); switch (ack) { - case SWD_ACK_OK: + case SWD_ACK_OK: if (parity != parity_u32(data)) { LOG_DEBUG("Read data parity mismatch %x %x", parity, parity_u32(data)); queued_retval = ERROR_FAIL; @@ -1458,15 +1453,15 @@ static void buspirate_swd_read_reg(uint8_t cmd, uint32_t *value, uint32_t ap_del if (cmd & SWD_CMD_APNDP) buspirate_swd_idle_clocks(ap_delay_clk); return; - case SWD_ACK_WAIT: + case SWD_ACK_WAIT: LOG_DEBUG("SWD_ACK_WAIT"); buspirate_swd_clear_sticky_errors(); return; - case SWD_ACK_FAULT: + case SWD_ACK_FAULT: LOG_DEBUG("SWD_ACK_FAULT"); queued_retval = ack; return; - default: + default: LOG_DEBUG("No valid acknowledge: ack=%d", ack); queued_retval = ack; return; @@ -1505,19 +1500,19 @@ static void buspirate_swd_write_reg(uint8_t cmd, uint32_t value, uint32_t ap_del value); switch (ack) { - case SWD_ACK_OK: + case SWD_ACK_OK: if (cmd & SWD_CMD_APNDP) buspirate_swd_idle_clocks(ap_delay_clk); return; - case SWD_ACK_WAIT: + case SWD_ACK_WAIT: LOG_DEBUG("SWD_ACK_WAIT"); buspirate_swd_clear_sticky_errors(); return; - case SWD_ACK_FAULT: + case SWD_ACK_FAULT: LOG_DEBUG("SWD_ACK_FAULT"); queued_retval = ack; return; - default: + default: LOG_DEBUG("No valid acknowledge: ack=%d", ack); queued_retval = ack; return; diff --git a/src/jtag/drivers/cmsis_dap.c b/src/jtag/drivers/cmsis_dap.c index d7367d8..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 */ @@ -225,12 +233,6 @@ struct pending_scan_result { unsigned int buffer_offset; }; -/* Read mode */ -enum cmsis_dap_blocking { - CMSIS_DAP_NON_BLOCKING, - CMSIS_DAP_BLOCKING -}; - /* Each block in FIFO can contain up to pending_queue_len transfers */ static unsigned int pending_queue_len; static unsigned int tfer_max_command_size; @@ -267,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; @@ -299,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; } @@ -321,7 +330,7 @@ static void cmsis_dap_flush_read(struct cmsis_dap *dap) * USB close/open so we need to flush up to 64 old packets * to be sure all buffers are empty */ for (i = 0; i < 64; i++) { - int retval = dap->backend->read(dap, 10, NULL); + int retval = dap->backend->read(dap, 10, CMSIS_DAP_BLOCKING); if (retval == ERROR_TIMEOUT_REACHED) break; } @@ -338,7 +347,7 @@ static int cmsis_dap_xfer(struct cmsis_dap *dap, int txlen) if (dap->pending_fifo_block_count) { LOG_ERROR("pending %u blocks, flushing", dap->pending_fifo_block_count); while (dap->pending_fifo_block_count) { - dap->backend->read(dap, 10, NULL); + dap->backend->read(dap, 10, CMSIS_DAP_BLOCKING); dap->pending_fifo_block_count--; } dap->pending_fifo_put_idx = 0; @@ -351,7 +360,7 @@ static int cmsis_dap_xfer(struct cmsis_dap *dap, int txlen) return retval; /* get reply */ - retval = dap->backend->read(dap, LIBUSB_TIMEOUT_MS, NULL); + retval = dap->backend->read(dap, LIBUSB_TIMEOUT_MS, CMSIS_DAP_BLOCKING); if (retval < 0) return retval; @@ -563,7 +572,7 @@ static int cmsis_dap_cmd_dap_delay(uint16_t delay_us) static int cmsis_dap_metacmd_targetsel(uint32_t instance_id) { uint8_t *command = cmsis_dap_handle->command; - const uint32_t SEQ_RD = 0x80, SEQ_WR = 0x00; + const uint32_t seq_rd = 0x80, seq_wr = 0x00; /* SWD multi-drop requires a transfer ala CMD_DAP_TFER, but with no expectation of an SWD ACK response. In @@ -579,14 +588,14 @@ static int cmsis_dap_metacmd_targetsel(uint32_t instance_id) command[idx++] = 3; /* sequence count */ /* sequence 0: packet request for TARGETSEL */ - command[idx++] = SEQ_WR | 8; + command[idx++] = seq_wr | 8; command[idx++] = SWD_CMD_START | swd_cmd(false, false, DP_TARGETSEL) | SWD_CMD_STOP | SWD_CMD_PARK; /* sequence 1: read Trn ACK Trn, no expectation for target to ACK */ - command[idx++] = SEQ_RD | 5; + command[idx++] = seq_rd | 5; /* sequence 2: WDATA plus parity */ - command[idx++] = SEQ_WR | (32 + 1); + command[idx++] = seq_wr | (32 + 1); h_u32_to_le(command + idx, instance_id); idx += 4; command[idx++] = parity_u32(instance_id); @@ -885,7 +894,7 @@ static void cmsis_dap_swd_read_process(struct cmsis_dap *dap, enum cmsis_dap_blo if (queued_retval != ERROR_OK) { /* keep reading blocks until the pipeline is empty */ - retval = dap->backend->read(dap, 10, NULL); + retval = dap->backend->read(dap, 10, CMSIS_DAP_BLOCKING); if (retval == ERROR_TIMEOUT_REACHED || retval == 0) { /* timeout means that we flushed the pipeline, * we can safely discard remaining pending requests */ @@ -896,11 +905,7 @@ static void cmsis_dap_swd_read_process(struct cmsis_dap *dap, enum cmsis_dap_blo } /* get reply */ - struct timeval tv = { - .tv_sec = 0, - .tv_usec = 0 - }; - retval = dap->backend->read(dap, LIBUSB_TIMEOUT_MS, blocking ? NULL : &tv); + retval = dap->backend->read(dap, LIBUSB_TIMEOUT_MS, blocking); bool timeout = (retval == ERROR_TIMEOUT_REACHED || retval == 0); if (timeout && blocking == CMSIS_DAP_NON_BLOCKING) return; @@ -1512,7 +1517,7 @@ static int cmsis_dap_execute_tlr_reset(struct jtag_command *cmd) } /* Set new end state */ -static void cmsis_dap_end_state(tap_state_t state) +static void cmsis_dap_end_state(enum tap_state state) { if (tap_is_state_stable(state)) tap_set_end_state(state); @@ -1752,7 +1757,7 @@ static void cmsis_dap_execute_scan(struct jtag_command *cmd) LOG_DEBUG("discarding trailing empty field"); } - if (cmd->cmd.scan->num_fields == 0) { + if (!cmd->cmd.scan->num_fields) { LOG_DEBUG("empty scan, doing nothing"); return; } @@ -1772,11 +1777,11 @@ static void cmsis_dap_execute_scan(struct jtag_command *cmd) cmsis_dap_end_state(cmd->cmd.scan->end_state); struct scan_field *field = cmd->cmd.scan->fields; - unsigned scan_size = 0; + unsigned int scan_size = 0; - for (int i = 0; i < cmd->cmd.scan->num_fields; i++, field++) { + for (unsigned int i = 0; i < cmd->cmd.scan->num_fields; i++, field++) { scan_size += field->num_bits; - LOG_DEBUG_IO("%s%s field %d/%d %d bits", + LOG_DEBUG_IO("%s%s field %u/%u %u bits", field->in_value ? "in" : "", field->out_value ? "out" : "", i, @@ -1841,7 +1846,7 @@ static void cmsis_dap_execute_scan(struct jtag_command *cmd) tap_state_name(tap_get_end_state())); } -static void cmsis_dap_pathmove(int num_states, tap_state_t *path) +static void cmsis_dap_pathmove(int num_states, enum tap_state *path) { uint8_t tms0 = 0x00; uint8_t tms1 = 0xff; @@ -1872,18 +1877,18 @@ static void cmsis_dap_execute_pathmove(struct jtag_command *cmd) cmsis_dap_pathmove(cmd->cmd.pathmove->num_states, cmd->cmd.pathmove->path); } -static void cmsis_dap_stableclocks(int num_cycles) +static void cmsis_dap_stableclocks(unsigned int num_cycles) { uint8_t tms = tap_get_state() == TAP_RESET; /* TODO: Perform optimizations? */ /* Execute num_cycles. */ - for (int i = 0; i < num_cycles; i++) + for (unsigned int i = 0; i < num_cycles; i++) cmsis_dap_add_tms_sequence(&tms, 1); } -static void cmsis_dap_runtest(int num_cycles) +static void cmsis_dap_runtest(unsigned int num_cycles) { - tap_state_t saved_end_state = tap_get_end_state(); + enum tap_state saved_end_state = tap_get_end_state(); /* Only do a state_move when we're not already in IDLE. */ if (tap_get_state() != TAP_IDLE) { @@ -1901,7 +1906,7 @@ static void cmsis_dap_runtest(int num_cycles) static void cmsis_dap_execute_runtest(struct jtag_command *cmd) { - LOG_DEBUG_IO("runtest %i cycles, end in %i", cmd->cmd.runtest->num_cycles, + LOG_DEBUG_IO("runtest %u cycles, end in %i", cmd->cmd.runtest->num_cycles, cmd->cmd.runtest->end_state); cmsis_dap_end_state(cmd->cmd.runtest->end_state); @@ -1910,13 +1915,13 @@ static void cmsis_dap_execute_runtest(struct jtag_command *cmd) static void cmsis_dap_execute_stableclocks(struct jtag_command *cmd) { - LOG_DEBUG_IO("stableclocks %i cycles", cmd->cmd.runtest->num_cycles); + LOG_DEBUG_IO("stableclocks %u cycles", cmd->cmd.runtest->num_cycles); cmsis_dap_stableclocks(cmd->cmd.runtest->num_cycles); } static void cmsis_dap_execute_tms(struct jtag_command *cmd) { - LOG_DEBUG_IO("TMS: %d bits", cmd->cmd.tms->num_bits); + LOG_DEBUG_IO("TMS: %u bits", cmd->cmd.tms->num_bits); cmsis_dap_cmd_dap_swj_sequence(cmd->cmd.tms->num_bits, cmd->cmd.tms->bits); } @@ -2153,7 +2158,7 @@ COMMAND_HANDLER(cmsis_dap_handle_cmd_command) { uint8_t *command = cmsis_dap_handle->command; - for (unsigned i = 0; i < CMD_ARGC; i++) + for (unsigned int i = 0; i < CMD_ARGC; i++) COMMAND_PARSE_NUMBER(u8, CMD_ARGV[i], command[i]); int retval = cmsis_dap_xfer(cmsis_dap_handle, CMD_ARGC); @@ -2185,7 +2190,7 @@ COMMAND_HANDLER(cmsis_dap_handle_vid_pid_command) CMD_ARGC -= 1; } - unsigned i; + unsigned int i; for (i = 0; i < CMD_ARGC; i += 2) { COMMAND_PARSE_NUMBER(u16, CMD_ARGV[i], cmsis_dap_vid[i >> 1]); COMMAND_PARSE_NUMBER(u16, CMD_ARGV[i + 1], cmsis_dap_pid[i >> 1]); @@ -2202,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/cmsis_dap.h b/src/jtag/drivers/cmsis_dap.h index e47697d..aded0e5 100644 --- a/src/jtag/drivers/cmsis_dap.h +++ b/src/jtag/drivers/cmsis_dap.h @@ -58,12 +58,18 @@ struct cmsis_dap { bool trace_enabled; }; +/* Read mode */ +enum cmsis_dap_blocking { + CMSIS_DAP_NON_BLOCKING, + CMSIS_DAP_BLOCKING +}; + struct cmsis_dap_backend { const char *name; int (*open)(struct cmsis_dap *dap, uint16_t vids[], uint16_t pids[], const char *serial); void (*close)(struct cmsis_dap *dap); int (*read)(struct cmsis_dap *dap, int transfer_timeout_ms, - struct timeval *wait_timeout); + enum cmsis_dap_blocking blocking); int (*write)(struct cmsis_dap *dap, int len, int timeout_ms); int (*packet_buffer_alloc)(struct cmsis_dap *dap, unsigned int pkt_sz); void (*packet_buffer_free)(struct cmsis_dap *dap); diff --git a/src/jtag/drivers/cmsis_dap_usb_bulk.c b/src/jtag/drivers/cmsis_dap_usb_bulk.c index 8d0cb54..8fbcb02 100644 --- a/src/jtag/drivers/cmsis_dap_usb_bulk.c +++ b/src/jtag/drivers/cmsis_dap_usb_bulk.c @@ -441,7 +441,7 @@ static void LIBUSB_CALL cmsis_dap_usb_callback(struct libusb_transfer *transfer) } static int cmsis_dap_usb_read(struct cmsis_dap *dap, int transfer_timeout_ms, - struct timeval *wait_timeout) + enum cmsis_dap_blocking blocking) { int transferred = 0; int err; @@ -464,20 +464,23 @@ static int cmsis_dap_usb_read(struct cmsis_dap *dap, int transfer_timeout_ms, } } - struct timeval tv = { - .tv_sec = transfer_timeout_ms / 1000, - .tv_usec = transfer_timeout_ms % 1000 * 1000 - }; + struct timeval tv; + if (blocking == CMSIS_DAP_NON_BLOCKING) { + tv.tv_sec = 0; + tv.tv_usec = 0; + } else { + tv.tv_sec = transfer_timeout_ms / 1000; + tv.tv_usec = transfer_timeout_ms % 1000 * 1000; + } while (tr->status == CMSIS_DAP_TRANSFER_PENDING) { - err = libusb_handle_events_timeout_completed(dap->bdata->usb_ctx, - wait_timeout ? wait_timeout : &tv, + err = libusb_handle_events_timeout_completed(dap->bdata->usb_ctx, &tv, &tr->status); if (err) { LOG_ERROR("error handling USB events: %s", libusb_strerror(err)); return ERROR_FAIL; } - if (wait_timeout) + if (tv.tv_sec == 0 && tv.tv_usec == 0) break; } @@ -529,7 +532,7 @@ static int cmsis_dap_usb_write(struct cmsis_dap *dap, int txlen, int timeout_ms) tr = &dap->bdata->command_transfers[dap->pending_fifo_put_idx]; if (tr->status == CMSIS_DAP_TRANSFER_PENDING) { - LOG_ERROR("busy command USB transfer at %u", dap->pending_fifo_put_idx); + LOG_DEBUG_IO("busy command USB transfer at %u", dap->pending_fifo_put_idx); struct timeval tv = { .tv_sec = timeout_ms / 1000, .tv_usec = timeout_ms % 1000 * 1000 @@ -544,7 +547,7 @@ static int cmsis_dap_usb_write(struct cmsis_dap *dap, int txlen, int timeout_ms) tr->status = CMSIS_DAP_TRANSFER_IDLE; } if (tr->status == CMSIS_DAP_TRANSFER_COMPLETED) { - LOG_ERROR("USB write: late transfer competed"); + LOG_DEBUG_IO("USB write: late transfer competed"); tr->status = CMSIS_DAP_TRANSFER_IDLE; } if (tr->status != CMSIS_DAP_TRANSFER_IDLE) { diff --git a/src/jtag/drivers/cmsis_dap_usb_hid.c b/src/jtag/drivers/cmsis_dap_usb_hid.c index 98ccc3e..a4058ec 100644 --- a/src/jtag/drivers/cmsis_dap_usb_hid.c +++ b/src/jtag/drivers/cmsis_dap_usb_hid.c @@ -121,8 +121,12 @@ static int cmsis_dap_hid_open(struct cmsis_dap *dap, uint16_t vids[], uint16_t p break; if (cur_dev->serial_number) { - size_t len = (strlen(serial) + 1) * sizeof(wchar_t); - wchar_t *wserial = malloc(len); + size_t len = mbstowcs(NULL, serial, 0) + 1; + wchar_t *wserial = malloc(len * sizeof(wchar_t)); + if (!wserial) { + LOG_ERROR("unable to allocate serial number buffer"); + return ERROR_FAIL; + } mbstowcs(wserial, serial, len); if (wcscmp(wserial, cur_dev->serial_number) == 0) { @@ -202,17 +206,13 @@ static void cmsis_dap_hid_close(struct cmsis_dap *dap) } static int cmsis_dap_hid_read(struct cmsis_dap *dap, int transfer_timeout_ms, - struct timeval *wait_timeout) + enum cmsis_dap_blocking blocking) { - int timeout_ms; - if (wait_timeout) - timeout_ms = wait_timeout->tv_usec / 1000 + wait_timeout->tv_sec * 1000; - else - timeout_ms = transfer_timeout_ms; + int wait_ms = (blocking == CMSIS_DAP_NON_BLOCKING) ? 0 : transfer_timeout_ms; int retval = hid_read_timeout(dap->bdata->dev_handle, dap->packet_buffer, dap->packet_buffer_size, - timeout_ms); + wait_ms); if (retval == 0) { return ERROR_TIMEOUT_REACHED; } else if (retval == -1) { diff --git a/src/jtag/drivers/driver.c b/src/jtag/drivers/driver.c index e52816d..43101b8 100644 --- a/src/jtag/drivers/driver.c +++ b/src/jtag/drivers/driver.c @@ -49,7 +49,7 @@ static void jtag_callback_queue_reset(void) * */ int interface_jtag_add_ir_scan(struct jtag_tap *active, - const struct scan_field *in_fields, tap_state_t state) + const struct scan_field *in_fields, enum tap_state state) { size_t num_taps = jtag_tap_count_enabled(); @@ -111,7 +111,7 @@ int interface_jtag_add_ir_scan(struct jtag_tap *active, * */ int interface_jtag_add_dr_scan(struct jtag_tap *active, int in_num_fields, - const struct scan_field *in_fields, tap_state_t state) + const struct scan_field *in_fields, enum tap_state state) { /* count devices in bypass */ @@ -184,7 +184,7 @@ int interface_jtag_add_dr_scan(struct jtag_tap *active, int in_num_fields, } static int jtag_add_plain_scan(int num_bits, const uint8_t *out_bits, - uint8_t *in_bits, tap_state_t state, bool ir_scan) + uint8_t *in_bits, enum tap_state state, bool ir_scan) { struct jtag_command *cmd = cmd_queue_alloc(sizeof(struct jtag_command)); struct scan_command *scan = cmd_queue_alloc(sizeof(struct scan_command)); @@ -207,19 +207,19 @@ static int jtag_add_plain_scan(int num_bits, const uint8_t *out_bits, return ERROR_OK; } -int interface_jtag_add_plain_dr_scan(int num_bits, const uint8_t *out_bits, uint8_t *in_bits, tap_state_t state) +int interface_jtag_add_plain_dr_scan(int num_bits, const uint8_t *out_bits, uint8_t *in_bits, enum tap_state state) { return jtag_add_plain_scan(num_bits, out_bits, in_bits, state, false); } -int interface_jtag_add_plain_ir_scan(int num_bits, const uint8_t *out_bits, uint8_t *in_bits, tap_state_t state) +int interface_jtag_add_plain_ir_scan(int num_bits, const uint8_t *out_bits, uint8_t *in_bits, enum tap_state state) { return jtag_add_plain_scan(num_bits, out_bits, in_bits, state, true); } int interface_jtag_add_tlr(void) { - tap_state_t state = TAP_RESET; + enum tap_state state = TAP_RESET; /* allocate memory for a new list member */ struct jtag_command *cmd = cmd_queue_alloc(sizeof(struct jtag_command)); @@ -234,7 +234,7 @@ int interface_jtag_add_tlr(void) return ERROR_OK; } -int interface_add_tms_seq(unsigned num_bits, const uint8_t *seq, enum tap_state state) +int interface_add_tms_seq(unsigned int num_bits, const uint8_t *seq, enum tap_state state) { struct jtag_command *cmd; @@ -259,7 +259,7 @@ int interface_add_tms_seq(unsigned num_bits, const uint8_t *seq, enum tap_state return ERROR_OK; } -int interface_jtag_add_pathmove(int num_states, const tap_state_t *path) +int interface_jtag_add_pathmove(unsigned int num_states, const enum tap_state *path) { /* allocate memory for a new list member */ struct jtag_command *cmd = cmd_queue_alloc(sizeof(struct jtag_command)); @@ -270,15 +270,15 @@ int interface_jtag_add_pathmove(int num_states, const tap_state_t *path) cmd->cmd.pathmove = cmd_queue_alloc(sizeof(struct pathmove_command)); cmd->cmd.pathmove->num_states = num_states; - cmd->cmd.pathmove->path = cmd_queue_alloc(sizeof(tap_state_t) * num_states); + cmd->cmd.pathmove->path = cmd_queue_alloc(sizeof(enum tap_state) * num_states); - for (int i = 0; i < num_states; i++) + for (unsigned int i = 0; i < num_states; i++) cmd->cmd.pathmove->path[i] = path[i]; return ERROR_OK; } -int interface_jtag_add_runtest(int num_cycles, tap_state_t state) +int interface_jtag_add_runtest(unsigned int num_cycles, enum tap_state state) { /* allocate memory for a new list member */ struct jtag_command *cmd = cmd_queue_alloc(sizeof(struct jtag_command)); @@ -294,7 +294,7 @@ int interface_jtag_add_runtest(int num_cycles, tap_state_t state) return ERROR_OK; } -int interface_jtag_add_clocks(int num_cycles) +int interface_jtag_add_clocks(unsigned int num_cycles) { /* allocate memory for a new list member */ struct jtag_command *cmd = cmd_queue_alloc(sizeof(struct jtag_command)); @@ -341,7 +341,7 @@ int interface_jtag_add_sleep(uint32_t us) } /* add callback to end of queue */ -void interface_jtag_add_callback4(jtag_callback_t callback, +static void interface_jtag_add_callback4(jtag_callback_t callback, jtag_callback_data_t data0, jtag_callback_data_t data1, jtag_callback_data_t data2, jtag_callback_data_t data3) { @@ -395,7 +395,7 @@ static int jtag_convert_to_callback4(jtag_callback_data_t data0, return ERROR_OK; } -void interface_jtag_add_callback(jtag_callback1_t callback, jtag_callback_data_t data0) +static void interface_jtag_add_callback(jtag_callback1_t callback, jtag_callback_data_t data0) { jtag_add_callback4(jtag_convert_to_callback4, data0, (jtag_callback_data_t)callback, 0, 0); } diff --git a/src/jtag/drivers/dummy.c b/src/jtag/drivers/dummy.c index 1b1e573..79b29fb 100644 --- a/src/jtag/drivers/dummy.c +++ b/src/jtag/drivers/dummy.c @@ -14,7 +14,7 @@ #include "hello.h" /* my private tap controller state, which tracks state for calling code */ -static tap_state_t dummy_state = TAP_RESET; +static enum tap_state dummy_state = TAP_RESET; static int dummy_clock; /* edge detector */ @@ -22,7 +22,7 @@ static int clock_count; /* count clocks in any stable state, only stable states static uint32_t dummy_data; -static bb_value_t dummy_read(void) +static enum bb_value dummy_read(void) { int data = 1 & dummy_data; dummy_data = (dummy_data >> 1) | (1 << 31); @@ -34,7 +34,7 @@ static int dummy_write(int tck, int tms, int tdi) /* TAP standard: "state transitions occur on rising edge of clock" */ if (tck != dummy_clock) { if (tck) { - tap_state_t old_state = dummy_state; + enum tap_state old_state = dummy_state; dummy_state = tap_state_transition(old_state, tms); if (old_state != dummy_state) { @@ -72,12 +72,12 @@ static int dummy_reset(int trst, int srst) return ERROR_OK; } -static int dummy_led(int on) +static int dummy_led(bool on) { return ERROR_OK; } -static struct bitbang_interface dummy_bitbang = { +static const struct bitbang_interface dummy_bitbang = { .read = &dummy_read, .write = &dummy_write, .blink = &dummy_led, diff --git a/src/jtag/drivers/ep93xx.c b/src/jtag/drivers/ep93xx.c index c3e841d..ea9faf1 100644 --- a/src/jtag/drivers/ep93xx.c +++ b/src/jtag/drivers/ep93xx.c @@ -30,7 +30,7 @@ static volatile uint8_t *gpio_data_direction_register; /* low level command set */ -static bb_value_t ep93xx_read(void); +static enum bb_value ep93xx_read(void); static int ep93xx_write(int tck, int tms, int tdi); static int ep93xx_reset(int trst, int srst); @@ -55,13 +55,13 @@ struct adapter_driver ep93xx_adapter_driver = { .jtag_ops = &ep93xx_interface, }; -static struct bitbang_interface ep93xx_bitbang = { +static const struct bitbang_interface ep93xx_bitbang = { .read = ep93xx_read, .write = ep93xx_write, .blink = NULL, }; -static bb_value_t ep93xx_read(void) +static enum bb_value ep93xx_read(void) { return (*gpio_data_register & TDO_BIT) ? BB_HIGH : BB_LOW; } diff --git a/src/jtag/drivers/ft232r.c b/src/jtag/drivers/ft232r.c index 766f6dd..f4e5af4 100644 --- a/src/jtag/drivers/ft232r.c +++ b/src/jtag/drivers/ft232r.c @@ -177,7 +177,7 @@ static void ft232r_increase_buf_size(size_t new_buf_size) */ static void ft232r_write(int tck, int tms, int tdi) { - unsigned out_value = (1<<ntrst_gpio) | (1<<nsysrst_gpio); + unsigned int out_value = (1 << ntrst_gpio) | (1 << nsysrst_gpio); if (tck) out_value |= (1<<tck_gpio); if (tms) @@ -201,7 +201,7 @@ static void ft232r_write(int tck, int tms, int tdi) */ static void ft232r_reset(int trst, int srst) { - unsigned out_value = (1<<ntrst_gpio) | (1<<nsysrst_gpio); + unsigned int out_value = (1 << ntrst_gpio) | (1 << nsysrst_gpio); LOG_DEBUG("ft232r_reset(%d,%d)", trst, srst); if (trst == 1) @@ -281,7 +281,7 @@ static int ft232r_init(void) } /* Exactly 500 nsec between updates. */ - unsigned divisor = 1; + unsigned int divisor = 1; unsigned char latency_timer = 1; /* Frequency divisor is 14-bit non-zero value. */ @@ -622,7 +622,7 @@ static const struct command_registration ft232r_command_handlers[] = { * Synchronous bitbang protocol implementation. */ -static void syncbb_end_state(tap_state_t state) +static void syncbb_end_state(enum tap_state state) { if (tap_is_state_stable(state)) tap_set_end_state(state); @@ -654,13 +654,13 @@ static void syncbb_state_move(int skip) */ static int syncbb_execute_tms(struct jtag_command *cmd) { - unsigned num_bits = cmd->cmd.tms->num_bits; + unsigned int num_bits = cmd->cmd.tms->num_bits; const uint8_t *bits = cmd->cmd.tms->bits; - LOG_DEBUG_IO("TMS: %d bits", num_bits); + LOG_DEBUG_IO("TMS: %u bits", num_bits); int tms = 0; - for (unsigned i = 0; i < num_bits; i++) { + for (unsigned int i = 0; i < num_bits; i++) { tms = ((bits[i/8] >> (i % 8)) & 1); ft232r_write(0, tms, 0); ft232r_write(1, tms, 0); @@ -672,7 +672,7 @@ static int syncbb_execute_tms(struct jtag_command *cmd) static void syncbb_path_move(struct pathmove_command *cmd) { - int num_states = cmd->num_states; + unsigned int num_states = cmd->num_states; int state_count; int tms = 0; @@ -702,11 +702,10 @@ static void syncbb_path_move(struct pathmove_command *cmd) tap_set_end_state(tap_get_state()); } -static void syncbb_runtest(int num_cycles) +static void syncbb_runtest(unsigned int num_cycles) { - int i; - tap_state_t saved_end_state = tap_get_end_state(); + enum tap_state saved_end_state = tap_get_end_state(); /* only do a state_move when we're not already in IDLE */ if (tap_get_state() != TAP_IDLE) { @@ -715,7 +714,7 @@ static void syncbb_runtest(int num_cycles) } /* execute num_cycles */ - for (i = 0; i < num_cycles; i++) { + for (unsigned int i = 0; i < num_cycles; i++) { ft232r_write(0, 0, 0); ft232r_write(1, 0, 0); } @@ -735,13 +734,12 @@ static void syncbb_runtest(int num_cycles) * this function checks the current stable state to decide on the value of TMS * to use. */ -static void syncbb_stableclocks(int num_cycles) +static void syncbb_stableclocks(unsigned int num_cycles) { int tms = (tap_get_state() == TAP_RESET ? 1 : 0); - int i; /* send num_cycles clocks onto the cable */ - for (i = 0; i < num_cycles; i++) { + for (unsigned int i = 0; i < num_cycles; i++) { ft232r_write(1, tms, 0); ft232r_write(0, tms, 0); } @@ -749,7 +747,7 @@ static void syncbb_stableclocks(int num_cycles) static void syncbb_scan(bool ir_scan, enum scan_type type, uint8_t *buffer, int scan_size) { - tap_state_t saved_end_state = tap_get_end_state(); + enum tap_state saved_end_state = tap_get_end_state(); int bit_cnt, bit0_index; if (!((!ir_scan && (tap_get_state() == TAP_DRSHIFT)) || (ir_scan && (tap_get_state() == TAP_IRSHIFT)))) { @@ -832,7 +830,7 @@ static int syncbb_execute_queue(struct jtag_command *cmd_queue) break; case JTAG_RUNTEST: - LOG_DEBUG_IO("runtest %i cycles, end in %s", cmd->cmd.runtest->num_cycles, + LOG_DEBUG_IO("runtest %u cycles, end in %s", cmd->cmd.runtest->num_cycles, tap_state_name(cmd->cmd.runtest->end_state)); syncbb_end_state(cmd->cmd.runtest->end_state); @@ -854,7 +852,7 @@ static int syncbb_execute_queue(struct jtag_command *cmd_queue) break; case JTAG_PATHMOVE: - LOG_DEBUG_IO("pathmove: %i states, end in %s", cmd->cmd.pathmove->num_states, + LOG_DEBUG_IO("pathmove: %u states, end in %s", cmd->cmd.pathmove->num_states, tap_state_name(cmd->cmd.pathmove->path[cmd->cmd.pathmove->num_states - 1])); syncbb_path_move(cmd->cmd.pathmove); diff --git a/src/jtag/drivers/ftdi.c b/src/jtag/drivers/ftdi.c index 1793cbf..f56a517 100644 --- a/src/jtag/drivers/ftdi.c +++ b/src/jtag/drivers/ftdi.c @@ -310,9 +310,9 @@ static void clock_tms_cs_out(struct mpsse_ctx *ctx, const uint8_t *out, unsigned * * @param goal_state is the destination state for the move. */ -static void move_to_state(tap_state_t goal_state) +static void move_to_state(enum tap_state goal_state) { - tap_state_t start_state = tap_get_state(); + enum tap_state start_state = tap_get_state(); /* goal_state is 1/2 of a tuple/pair of states which allow convenient lookup of the required TMS pattern to move to this state from the @@ -371,7 +371,7 @@ static int ftdi_khz(int khz, int *jtag_speed) return ERROR_OK; } -static void ftdi_end_state(tap_state_t state) +static void ftdi_end_state(enum tap_state state) { if (tap_is_state_stable(state)) tap_set_end_state(state); @@ -383,10 +383,9 @@ static void ftdi_end_state(tap_state_t state) static void ftdi_execute_runtest(struct jtag_command *cmd) { - int i; - static const uint8_t zero; + uint8_t zero = 0; - LOG_DEBUG_IO("runtest %i cycles, end in %s", + LOG_DEBUG_IO("runtest %u cycles, end in %s", cmd->cmd.runtest->num_cycles, tap_state_name(cmd->cmd.runtest->end_state)); @@ -394,10 +393,10 @@ static void ftdi_execute_runtest(struct jtag_command *cmd) move_to_state(TAP_IDLE); /* TODO: Reuse ftdi_execute_stableclocks */ - i = cmd->cmd.runtest->num_cycles; + unsigned int i = cmd->cmd.runtest->num_cycles; while (i > 0) { /* there are no state transitions in this code, so omit state tracking */ - unsigned this_len = i > 7 ? 7 : i; + unsigned int this_len = i > 7 ? 7 : i; DO_CLOCK_TMS_CS_OUT(mpsse_ctx, &zero, 0, this_len, false, ftdi_jtag_mode); i -= this_len; } @@ -407,7 +406,7 @@ static void ftdi_execute_runtest(struct jtag_command *cmd) if (tap_get_state() != tap_get_end_state()) move_to_state(tap_get_end_state()); - LOG_DEBUG_IO("runtest: %i, end in %s", + LOG_DEBUG_IO("runtest: %u, end in %s", cmd->cmd.runtest->num_cycles, tap_state_name(tap_get_end_state())); } @@ -430,7 +429,7 @@ static void ftdi_execute_statemove(struct jtag_command *cmd) */ static void ftdi_execute_tms(struct jtag_command *cmd) { - LOG_DEBUG_IO("TMS: %d bits", cmd->cmd.tms->num_bits); + LOG_DEBUG_IO("TMS: %u bits", cmd->cmd.tms->num_bits); /* TODO: Missing tap state tracking, also missing from ft2232.c! */ DO_CLOCK_TMS_CS_OUT(mpsse_ctx, @@ -443,15 +442,15 @@ static void ftdi_execute_tms(struct jtag_command *cmd) static void ftdi_execute_pathmove(struct jtag_command *cmd) { - tap_state_t *path = cmd->cmd.pathmove->path; - int num_states = cmd->cmd.pathmove->num_states; + enum tap_state *path = cmd->cmd.pathmove->path; + unsigned int num_states = cmd->cmd.pathmove->num_states; - LOG_DEBUG_IO("pathmove: %i states, current: %s end: %s", num_states, + LOG_DEBUG_IO("pathmove: %u states, current: %s end: %s", num_states, tap_state_name(tap_get_state()), tap_state_name(path[num_states-1])); int state_count = 0; - unsigned bit_count = 0; + unsigned int bit_count = 0; uint8_t tms_byte = 0; LOG_DEBUG_IO("-"); @@ -504,7 +503,7 @@ static void ftdi_execute_scan(struct jtag_command *cmd) LOG_DEBUG_IO("discarding trailing empty field"); } - if (cmd->cmd.scan->num_fields == 0) { + if (!cmd->cmd.scan->num_fields) { LOG_DEBUG_IO("empty scan, doing nothing"); return; } @@ -520,11 +519,11 @@ static void ftdi_execute_scan(struct jtag_command *cmd) ftdi_end_state(cmd->cmd.scan->end_state); struct scan_field *field = cmd->cmd.scan->fields; - unsigned scan_size = 0; + unsigned int scan_size = 0; - for (int i = 0; i < cmd->cmd.scan->num_fields; i++, field++) { + for (unsigned int i = 0; i < cmd->cmd.scan->num_fields; i++, field++) { scan_size += field->num_bits; - LOG_DEBUG_IO("%s%s field %d/%d %d bits", + LOG_DEBUG_IO("%s%s field %u/%u %u bits", field->in_value ? "in" : "", field->out_value ? "out" : "", i, @@ -644,7 +643,7 @@ static void ftdi_execute_stableclocks(struct jtag_command *cmd) /* this is only allowed while in a stable state. A check for a stable * state was done in jtag_add_clocks() */ - int num_cycles = cmd->cmd.stableclocks->num_cycles; + unsigned int num_cycles = cmd->cmd.stableclocks->num_cycles; /* 7 bits of either ones or zeros. */ uint8_t tms = tap_get_state() == TAP_RESET ? 0x7f : 0x00; @@ -653,12 +652,12 @@ static void ftdi_execute_stableclocks(struct jtag_command *cmd) * the correct level and remain there during the scan */ while (num_cycles > 0) { /* there are no state transitions in this code, so omit state tracking */ - unsigned this_len = num_cycles > 7 ? 7 : num_cycles; + unsigned int this_len = num_cycles > 7 ? 7 : num_cycles; DO_CLOCK_TMS_CS_OUT(mpsse_ctx, &tms, 0, this_len, false, ftdi_jtag_mode); num_cycles -= this_len; } - LOG_DEBUG_IO("clocks %i while in %s", + LOG_DEBUG_IO("clocks %u while in %s", cmd->cmd.stableclocks->num_cycles, tap_state_name(tap_get_state())); } @@ -1127,7 +1126,7 @@ COMMAND_HANDLER(ftdi_handle_layout_signal_command) uint16_t input_mask = 0; bool invert_oe = false; uint16_t oe_mask = 0; - for (unsigned i = 1; i < CMD_ARGC; i += 2) { + for (unsigned int i = 1; i < CMD_ARGC; i += 2) { if (strcmp("-data", CMD_ARGV[i]) == 0) { invert_data = false; COMMAND_PARSE_NUMBER(u16, CMD_ARGV[i + 1], data_mask); @@ -1256,7 +1255,7 @@ COMMAND_HANDLER(ftdi_handle_vid_pid_command) CMD_ARGC -= 1; } - unsigned i; + unsigned int i; for (i = 0; i < CMD_ARGC; i += 2) { COMMAND_PARSE_NUMBER(u16, CMD_ARGV[i], ftdi_vid[i >> 1]); COMMAND_PARSE_NUMBER(u16, CMD_ARGV[i + 1], ftdi_pid[i >> 1]); diff --git a/src/jtag/drivers/gw16012.c b/src/jtag/drivers/gw16012.c index a4c6fd0..7200e75 100644 --- a/src/jtag/drivers/gw16012.c +++ b/src/jtag/drivers/gw16012.c @@ -133,7 +133,7 @@ static void gw16012_reset(int trst, int srst) gw16012_control(0x0b); } -static void gw16012_end_state(tap_state_t state) +static void gw16012_end_state(enum tap_state state) { if (tap_is_state_stable(state)) tap_set_end_state(state); @@ -185,10 +185,9 @@ static void gw16012_path_move(struct pathmove_command *cmd) tap_set_end_state(tap_get_state()); } -static void gw16012_runtest(int num_cycles) +static void gw16012_runtest(unsigned int num_cycles) { - tap_state_t saved_end_state = tap_get_end_state(); - int i; + enum tap_state saved_end_state = tap_get_end_state(); /* only do a state_move when we're not already in IDLE */ if (tap_get_state() != TAP_IDLE) { @@ -196,7 +195,7 @@ static void gw16012_runtest(int num_cycles) gw16012_state_move(); } - for (i = 0; i < num_cycles; i++) { + for (unsigned int i = 0; i < num_cycles; i++) { gw16012_control(0x0); /* single-bit mode */ gw16012_data(0x0); /* TMS cycle with TMS low */ } @@ -210,7 +209,7 @@ static void gw16012_scan(bool ir_scan, enum scan_type type, uint8_t *buffer, int { int bits_left = scan_size; int bit_count = 0; - tap_state_t saved_end_state = tap_get_end_state(); + enum tap_state saved_end_state = tap_get_end_state(); uint8_t scan_out, scan_in; /* only if we're not already in the correct Shift state */ @@ -292,7 +291,7 @@ static int gw16012_execute_queue(struct jtag_command *cmd_queue) gw16012_reset(cmd->cmd.reset->trst, cmd->cmd.reset->srst); break; case JTAG_RUNTEST: - LOG_DEBUG_IO("runtest %i cycles, end in %i", cmd->cmd.runtest->num_cycles, + LOG_DEBUG_IO("runtest %u cycles, end in %i", cmd->cmd.runtest->num_cycles, cmd->cmd.runtest->end_state); gw16012_end_state(cmd->cmd.runtest->end_state); gw16012_runtest(cmd->cmd.runtest->num_cycles); diff --git a/src/jtag/drivers/imx_gpio.c b/src/jtag/drivers/imx_gpio.c index d44b127..18dc2dd 100644 --- a/src/jtag/drivers/imx_gpio.c +++ b/src/jtag/drivers/imx_gpio.c @@ -72,7 +72,7 @@ static inline bool gpio_level(int g) return pio_base[g / 32].dr >> (g & 0x1F) & 1; } -static bb_value_t imx_gpio_read(void); +static enum bb_value imx_gpio_read(void); static int imx_gpio_write(int tck, int tms, int tdi); static int imx_gpio_swdio_read(void); @@ -82,7 +82,7 @@ static int imx_gpio_swd_write(int swclk, int swdio); static int imx_gpio_init(void); static int imx_gpio_quit(void); -static struct bitbang_interface imx_gpio_bitbang = { +static const struct bitbang_interface imx_gpio_bitbang = { .read = imx_gpio_read, .write = imx_gpio_write, .swdio_read = imx_gpio_swdio_read, @@ -118,7 +118,7 @@ static int speed_coeff = 50000; static int speed_offset = 100; static unsigned int jtag_delay; -static bb_value_t imx_gpio_read(void) +static enum bb_value imx_gpio_read(void) { return gpio_level(tdo_gpio) ? BB_HIGH : BB_LOW; } diff --git a/src/jtag/drivers/jlink.c b/src/jtag/drivers/jlink.c index 1874557..4d15cf5 100644 --- a/src/jtag/drivers/jlink.c +++ b/src/jtag/drivers/jlink.c @@ -78,11 +78,11 @@ static struct device_config config; static struct device_config tmp_config; /* Queue command functions */ -static void jlink_end_state(tap_state_t state); +static void jlink_end_state(enum tap_state state); static void jlink_state_move(void); -static void jlink_path_move(int num_states, tap_state_t *path); -static void jlink_stableclocks(int num_cycles); -static void jlink_runtest(int num_cycles); +static void jlink_path_move(unsigned int num_states, enum tap_state *path); +static void jlink_stableclocks(unsigned int num_cycles); +static void jlink_runtest(unsigned int num_cycles); static void jlink_reset(int trst, int srst); static int jlink_reset_safe(int trst, int srst); static int jlink_swd_run_queue(void); @@ -104,10 +104,10 @@ static int jlink_flush(void); * @param in_offset A bit offset for TDO data. * @param length Amount of bits to transfer out and in. */ -static void jlink_clock_data(const uint8_t *out, unsigned out_offset, - const uint8_t *tms_out, unsigned tms_offset, - uint8_t *in, unsigned in_offset, - unsigned length); +static void jlink_clock_data(const uint8_t *out, unsigned int out_offset, + const uint8_t *tms_out, unsigned int tms_offset, + uint8_t *in, unsigned int in_offset, + unsigned int length); static enum tap_state jlink_last_state = TAP_RESET; static int queued_retval; @@ -140,7 +140,7 @@ static void jlink_execute_statemove(struct jtag_command *cmd) static void jlink_execute_pathmove(struct jtag_command *cmd) { - LOG_DEBUG_IO("pathmove: %i states, end in %i", + LOG_DEBUG_IO("pathmove: %u states, end in %i", cmd->cmd.pathmove->num_states, cmd->cmd.pathmove->path[cmd->cmd.pathmove->num_states - 1]); @@ -159,7 +159,7 @@ static void jlink_execute_scan(struct jtag_command *cmd) LOG_DEBUG("discarding trailing empty field"); } - if (cmd->cmd.scan->num_fields == 0) { + if (!cmd->cmd.scan->num_fields) { LOG_DEBUG("empty scan, doing nothing"); return; } @@ -179,11 +179,11 @@ static void jlink_execute_scan(struct jtag_command *cmd) jlink_end_state(cmd->cmd.scan->end_state); struct scan_field *field = cmd->cmd.scan->fields; - unsigned scan_size = 0; + unsigned int scan_size = 0; - for (int i = 0; i < cmd->cmd.scan->num_fields; i++, field++) { + for (unsigned int i = 0; i < cmd->cmd.scan->num_fields; i++, field++) { scan_size += field->num_bits; - LOG_DEBUG_IO("%s%s field %d/%d %d bits", + LOG_DEBUG_IO("%s%s field %u/%u %u bits", field->in_value ? "in" : "", field->out_value ? "out" : "", i, @@ -564,6 +564,20 @@ static int jlink_open_device(uint32_t ifaces, bool *found_device) if (!use_serial_number && !use_usb_address && !use_usb_location && num_devices > 1) { LOG_ERROR("Multiple devices found, specify the desired device"); + LOG_INFO("Found devices:"); + for (size_t i = 0; devs[i]; i++) { + uint32_t serial; + ret = jaylink_device_get_serial_number(devs[i], &serial); + if (ret == JAYLINK_ERR_NOT_AVAILABLE) { + continue; + } else if (ret != JAYLINK_OK) { + LOG_WARNING("jaylink_device_get_serial_number() failed: %s", + jaylink_strerror(ret)); + continue; + } + LOG_INFO("Device %zu serial: %" PRIu32, i, serial); + } + jaylink_free_devices(devs, true); jaylink_exit(jayctx); return ERROR_JTAG_INIT_FAILED; @@ -861,7 +875,7 @@ static int jlink_quit(void) /***************************************************************************/ /* Queue command implementations */ -static void jlink_end_state(tap_state_t state) +static void jlink_end_state(enum tap_state state) { if (tap_is_state_stable(state)) tap_set_end_state(state); @@ -885,12 +899,11 @@ static void jlink_state_move(void) tap_set_state(tap_get_end_state()); } -static void jlink_path_move(int num_states, tap_state_t *path) +static void jlink_path_move(unsigned int num_states, enum tap_state *path) { - int i; uint8_t tms = 0xff; - for (i = 0; i < num_states; i++) { + for (unsigned int i = 0; i < num_states; i++) { if (path[i] == tap_state_transition(tap_get_state(), false)) jlink_clock_data(NULL, 0, NULL, 0, NULL, 0, 1); else if (path[i] == tap_state_transition(tap_get_state(), true)) @@ -907,19 +920,17 @@ static void jlink_path_move(int num_states, tap_state_t *path) tap_set_end_state(tap_get_state()); } -static void jlink_stableclocks(int num_cycles) +static void jlink_stableclocks(unsigned int num_cycles) { - int i; - uint8_t tms = tap_get_state() == TAP_RESET; /* Execute num_cycles. */ - for (i = 0; i < num_cycles; i++) + for (unsigned int i = 0; i < num_cycles; i++) jlink_clock_data(NULL, 0, &tms, 0, NULL, 0, 1); } -static void jlink_runtest(int num_cycles) +static void jlink_runtest(unsigned int num_cycles) { - tap_state_t saved_end_state = tap_get_end_state(); + enum tap_state saved_end_state = tap_get_end_state(); /* Only do a state_move when we're not already in IDLE. */ if (tap_get_state() != TAP_IDLE) { @@ -964,23 +975,18 @@ static int jlink_reset_safe(int trst, int srst) COMMAND_HANDLER(jlink_usb_command) { - int tmp; - if (CMD_ARGC != 1) return ERROR_COMMAND_SYNTAX_ERROR; - if (sscanf(CMD_ARGV[0], "%i", &tmp) != 1) { - command_print(CMD, "Invalid USB address: %s", CMD_ARGV[0]); - return ERROR_COMMAND_ARGUMENT_INVALID; - } + unsigned int tmp; + COMMAND_PARSE_NUMBER(uint, CMD_ARGV[0], tmp); - if (tmp < JAYLINK_USB_ADDRESS_0 || tmp > JAYLINK_USB_ADDRESS_3) { + if (tmp > JAYLINK_USB_ADDRESS_3) { command_print(CMD, "Invalid USB address: %s", CMD_ARGV[0]); return ERROR_COMMAND_ARGUMENT_INVALID; } usb_address = tmp; - use_usb_address = true; return ERROR_OK; @@ -1038,38 +1044,35 @@ COMMAND_HANDLER(jlink_handle_free_memory_command) COMMAND_HANDLER(jlink_handle_jlink_jtag_command) { - int tmp; - int version; - if (!CMD_ARGC) { + unsigned int version; + switch (jtag_command_version) { - case JAYLINK_JTAG_VERSION_2: - version = 2; - break; - case JAYLINK_JTAG_VERSION_3: - version = 3; - break; - default: - return ERROR_FAIL; + case JAYLINK_JTAG_VERSION_2: + version = 2; + break; + case JAYLINK_JTAG_VERSION_3: + version = 3; + break; + default: + return ERROR_FAIL; } - command_print(CMD, "JTAG command version: %i", version); + command_print(CMD, "JTAG command version: %u", version); } else if (CMD_ARGC == 1) { - if (sscanf(CMD_ARGV[0], "%i", &tmp) != 1) { - command_print(CMD, "Invalid argument: %s", CMD_ARGV[0]); - return ERROR_COMMAND_ARGUMENT_INVALID; - } + uint8_t tmp; + COMMAND_PARSE_NUMBER(u8, CMD_ARGV[0], tmp); switch (tmp) { - case 2: - jtag_command_version = JAYLINK_JTAG_VERSION_2; - break; - case 3: - jtag_command_version = JAYLINK_JTAG_VERSION_3; - break; - default: - command_print(CMD, "Invalid argument: %s", CMD_ARGV[0]); - return ERROR_COMMAND_ARGUMENT_INVALID; + case 2: + jtag_command_version = JAYLINK_JTAG_VERSION_2; + break; + case 3: + jtag_command_version = JAYLINK_JTAG_VERSION_3; + break; + default: + command_print(CMD, "Invalid argument: %s", CMD_ARGV[0]); + return ERROR_COMMAND_ARGUMENT_INVALID; } } else { return ERROR_COMMAND_SYNTAX_ERROR; @@ -1080,10 +1083,7 @@ COMMAND_HANDLER(jlink_handle_jlink_jtag_command) COMMAND_HANDLER(jlink_handle_target_power_command) { - int ret; - int enable; - - if (CMD_ARGC != 1) + if (CMD_ARGC > 1) return ERROR_COMMAND_SYNTAX_ERROR; if (!jaylink_has_cap(caps, JAYLINK_DEV_CAP_SET_TARGET_POWER)) { @@ -1092,16 +1092,24 @@ COMMAND_HANDLER(jlink_handle_target_power_command) return ERROR_OK; } - if (!strcmp(CMD_ARGV[0], "on")) { - enable = true; - } else if (!strcmp(CMD_ARGV[0], "off")) { - enable = false; - } else { - command_print(CMD, "Invalid argument: %s", CMD_ARGV[0]); - return ERROR_FAIL; + if (!CMD_ARGC) { + uint32_t state; + int ret = jaylink_get_hardware_info(devh, JAYLINK_HW_INFO_TARGET_POWER, + &state); + + if (ret != JAYLINK_OK) { + command_print(CMD, "Failed to retrieve target power state"); + return ERROR_FAIL; + } + + command_print(CMD, "%d", (bool)state); + return ERROR_OK; } - ret = jaylink_set_target_power(devh, enable); + bool enable; + COMMAND_PARSE_ON_OFF(CMD_ARGV[0], enable); + + int ret = jaylink_set_target_power(devh, enable); if (ret != JAYLINK_OK) { command_print(CMD, "jaylink_set_target_power() failed: %s", @@ -1410,8 +1418,6 @@ static int config_trace(bool enabled, enum tpiu_pin_protocol pin_protocol, COMMAND_HANDLER(jlink_handle_config_usb_address_command) { - uint8_t tmp; - if (!jaylink_has_cap(caps, JAYLINK_DEV_CAP_READ_CONFIG)) { command_print(CMD, "Reading configuration is not supported by the " "device"); @@ -1421,10 +1427,8 @@ COMMAND_HANDLER(jlink_handle_config_usb_address_command) if (!CMD_ARGC) { show_config_usb_address(CMD); } else if (CMD_ARGC == 1) { - if (sscanf(CMD_ARGV[0], "%" SCNd8, &tmp) != 1) { - command_print(CMD, "Invalid USB address: %s", CMD_ARGV[0]); - return ERROR_COMMAND_ARGUMENT_INVALID; - } + uint8_t tmp; + COMMAND_PARSE_NUMBER(u8, CMD_ARGV[0], tmp); if (tmp > JAYLINK_USB_ADDRESS_3) { command_print(CMD, "Invalid USB address: %u", tmp); @@ -1883,7 +1887,7 @@ static const struct command_registration jlink_subcommand_handlers[] = { .handler = &jlink_handle_target_power_command, .mode = COMMAND_EXEC, .help = "set the target power supply", - .usage = "<on|off>" + .usage = "[0|1|on|off]" }, { .name = "freemem", @@ -1958,7 +1962,7 @@ static void jlink_swd_read_reg(uint8_t cmd, uint32_t *value, uint32_t ap_delay_c /***************************************************************************/ /* J-Link tap functions */ -static unsigned tap_length; +static unsigned int tap_length; /* In SWD mode use tms buffer for direction control */ static uint8_t tms_buffer[JLINK_TAP_BUFFER_SIZE]; static uint8_t tdi_buffer[JLINK_TAP_BUFFER_SIZE]; @@ -1966,13 +1970,13 @@ static uint8_t tdo_buffer[JLINK_TAP_BUFFER_SIZE]; struct pending_scan_result { /** First bit position in tdo_buffer to read. */ - unsigned first; + unsigned int first; /** Number of bits to read. */ - unsigned length; + unsigned int length; /** Location to store the result */ void *buffer; /** Offset in the destination buffer */ - unsigned buffer_offset; + unsigned int buffer_offset; /** SWD command */ uint8_t swd_cmd; }; @@ -1990,13 +1994,13 @@ static void jlink_tap_init(void) memset(tdi_buffer, 0, sizeof(tdi_buffer)); } -static void jlink_clock_data(const uint8_t *out, unsigned out_offset, - const uint8_t *tms_out, unsigned tms_offset, - uint8_t *in, unsigned in_offset, - unsigned length) +static void jlink_clock_data(const uint8_t *out, unsigned int out_offset, + const uint8_t *tms_out, unsigned int tms_offset, + uint8_t *in, unsigned int in_offset, + unsigned int length) { do { - unsigned available_length = JLINK_TAP_BUFFER_SIZE - tap_length / 8; + unsigned int available_length = JLINK_TAP_BUFFER_SIZE - tap_length / 8; if (!available_length || (in && pending_scan_results_length == MAX_PENDING_SCAN_RESULTS)) { @@ -2008,7 +2012,7 @@ static void jlink_clock_data(const uint8_t *out, unsigned out_offset, struct pending_scan_result *pending_scan_result = &pending_scan_results_buffer[pending_scan_results_length]; - unsigned scan_length = length > available_length ? + unsigned int scan_length = length > available_length ? available_length : length; if (out) diff --git a/src/jtag/drivers/jtag_dpi.c b/src/jtag/drivers/jtag_dpi.c index 285f96e..046186a 100644 --- a/src/jtag/drivers/jtag_dpi.c +++ b/src/jtag/drivers/jtag_dpi.c @@ -163,7 +163,7 @@ out: return ret; } -static int jtag_dpi_runtest(int cycles) +static int jtag_dpi_runtest(unsigned int num_cycles) { char buf[20]; uint8_t *data_buf = last_ir_buf, *read_scan; @@ -189,7 +189,7 @@ static int jtag_dpi_runtest(int cycles) return ERROR_FAIL; } snprintf(buf, sizeof(buf), "ib %d\n", num_bits); - while (cycles > 0) { + while (num_cycles > 0) { ret = write_sock(buf, strlen(buf)); if (ret != ERROR_OK) { LOG_ERROR("write_sock() fail, file %s, line %d", @@ -209,7 +209,7 @@ static int jtag_dpi_runtest(int cycles) goto out; } - cycles -= num_bits + 6; + num_cycles -= num_bits + 6; } out: @@ -217,9 +217,9 @@ out: return ret; } -static int jtag_dpi_stableclocks(int cycles) +static int jtag_dpi_stableclocks(unsigned int num_cycles) { - return jtag_dpi_runtest(cycles); + return jtag_dpi_runtest(num_cycles); } static int jtag_dpi_execute_queue(struct jtag_command *cmd_queue) diff --git a/src/jtag/drivers/jtag_vpi.c b/src/jtag/drivers/jtag_vpi.c index 9dec0d1..f6cb3de 100644 --- a/src/jtag/drivers/jtag_vpi.c +++ b/src/jtag/drivers/jtag_vpi.c @@ -158,7 +158,7 @@ retry_write: static int jtag_vpi_receive_cmd(struct vpi_cmd *vpi) { - unsigned bytes_buffered = 0; + unsigned int bytes_buffered = 0; while (bytes_buffered < sizeof(struct vpi_cmd)) { int bytes_to_receive = sizeof(struct vpi_cmd) - bytes_buffered; int retval = read_socket(sockfd, ((char *)vpi) + bytes_buffered, bytes_to_receive); @@ -254,7 +254,7 @@ static int jtag_vpi_path_move(struct pathmove_command *cmd) memset(trans, 0, DIV_ROUND_UP(cmd->num_states, 8)); - for (int i = 0; i < cmd->num_states; i++) { + for (unsigned int i = 0; i < cmd->num_states; i++) { if (tap_state_transition(tap_get_state(), true) == cmd->path[i]) buf_set_u32(trans, i, 1, 1); tap_set_state(cmd->path[i]); @@ -272,7 +272,7 @@ static int jtag_vpi_tms(struct tms_command *cmd) return jtag_vpi_tms_seq(cmd->bits, cmd->num_bits); } -static int jtag_vpi_state_move(tap_state_t state) +static int jtag_vpi_state_move(enum tap_state state) { if (tap_get_state() == state) return ERROR_OK; @@ -440,7 +440,7 @@ static int jtag_vpi_scan(struct scan_command *cmd) return ERROR_OK; } -static int jtag_vpi_runtest(int cycles, tap_state_t state) +static int jtag_vpi_runtest(unsigned int num_cycles, enum tap_state state) { int retval; @@ -448,29 +448,27 @@ static int jtag_vpi_runtest(int cycles, tap_state_t state) if (retval != ERROR_OK) return retval; - retval = jtag_vpi_queue_tdi(NULL, cycles, NO_TAP_SHIFT); + retval = jtag_vpi_queue_tdi(NULL, num_cycles, NO_TAP_SHIFT); if (retval != ERROR_OK) return retval; return jtag_vpi_state_move(state); } -static int jtag_vpi_stableclocks(int cycles) +static int jtag_vpi_stableclocks(unsigned int num_cycles) { uint8_t tms_bits[4]; - int cycles_remain = cycles; + unsigned int cycles_remain = num_cycles; int nb_bits; int retval; - const int CYCLES_ONE_BATCH = sizeof(tms_bits) * 8; - - assert(cycles >= 0); + const unsigned int cycles_one_batch = sizeof(tms_bits) * 8; /* use TMS=1 in TAP RESET state, TMS=0 in all other stable states */ memset(&tms_bits, (tap_get_state() == TAP_RESET) ? 0xff : 0x00, sizeof(tms_bits)); /* send the TMS bits */ while (cycles_remain > 0) { - nb_bits = (cycles_remain < CYCLES_ONE_BATCH) ? cycles_remain : CYCLES_ONE_BATCH; + nb_bits = (cycles_remain < cycles_one_batch) ? cycles_remain : cycles_one_batch; retval = jtag_vpi_tms_seq(tms_bits, nb_bits); if (retval != ERROR_OK) return retval; diff --git a/src/jtag/drivers/libusb_helper.c b/src/jtag/drivers/libusb_helper.c index 57ea8cd..ee90e78 100644 --- a/src/jtag/drivers/libusb_helper.c +++ b/src/jtag/drivers/libusb_helper.c @@ -53,7 +53,7 @@ static int jtag_libusb_error(int err) bool jtag_libusb_match_ids(struct libusb_device_descriptor *dev_desc, const uint16_t vids[], const uint16_t pids[]) { - for (unsigned i = 0; vids[i]; i++) { + for (unsigned int i = 0; vids[i]; i++) { if (dev_desc->idVendor == vids[i] && dev_desc->idProduct == pids[i]) { return true; diff --git a/src/jtag/drivers/linuxgpiod.c b/src/jtag/drivers/linuxgpiod.c index 1926ed9..eda7b1a 100644 --- a/src/jtag/drivers/linuxgpiod.c +++ b/src/jtag/drivers/linuxgpiod.c @@ -42,7 +42,7 @@ static bool is_gpio_config_valid(enum adapter_gpio_config_index idx) } /* Bitbang interface read of TDO */ -static bb_value_t linuxgpiod_read(void) +static enum bb_value linuxgpiod_read(void) { int retval; @@ -178,20 +178,20 @@ static int linuxgpiod_swd_write(int swclk, int swdio) return ERROR_OK; } -static int linuxgpiod_blink(int on) +static int linuxgpiod_blink(bool on) { int retval; if (!is_gpio_config_valid(ADAPTER_GPIO_IDX_LED)) return ERROR_OK; - retval = gpiod_line_set_value(gpiod_line[ADAPTER_GPIO_IDX_LED], on); + retval = gpiod_line_set_value(gpiod_line[ADAPTER_GPIO_IDX_LED], on ? 1 : 0); if (retval < 0) LOG_WARNING("Fail set led"); return retval; } -static struct bitbang_interface linuxgpiod_bitbang = { +static const struct bitbang_interface linuxgpiod_bitbang = { .read = linuxgpiod_read, .write = linuxgpiod_write, .swdio_read = linuxgpiod_swdio_read, diff --git a/src/jtag/drivers/linuxspidev.c b/src/jtag/drivers/linuxspidev.c new file mode 100644 index 0000000..18abdc7 --- /dev/null +++ b/src/jtag/drivers/linuxspidev.c @@ -0,0 +1,634 @@ +// SPDX-License-Identifier: GPL-2.0-or-later + +/* Copyright (C) 2020 by Lup Yuen Lee <luppy@appkaki.com> + * Copyright (C) 2024 by Richard Pasek <rpasek@google.com> + */ + +/** + * @file + * Implementation of SWD protocol with a Linux SPI device. + */ + +/* Uncomment to log SPI exchanges (very verbose, slows things down a lot) + * + * A quick note on interpreting SPI exchange messages: + * + * This implementation works by performing SPI exchanges with MOSI and MISO + * tied together with a 1K resistor. This combined signal becomes SWDIO. + * + * Since we are performing SPI exchanges, (reading and writing at the same + * time) this means when the target isn't driving SWDIO, what is written by + * the host should also be read by the host. + * + * On SWD writes: + * The TX and RX data should match except for the ACK bits from the target + * swd write reg exchange: len=6 + * tx_buf=C5 02 40 00 02 2C + * rx_buf=C5 42 40 00 02 2C + * ^ + * | + * ACK from target + * + * On SWD reads: + * Only the command byte should match + * swd read reg exchange: len=6 + * tx_buf=B1 00 00 00 00 00 + * rx_buf=B1 40 20 00 00 F8 + * ^^ + * || + * Command packet from host + * + */ +// #define LOG_SPI_EXCHANGE + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <stdint.h> +#include <unistd.h> +#include <stdlib.h> +#include <string.h> +#include <fcntl.h> +#include <sys/ioctl.h> +#include <linux/spi/spidev.h> +#include <jtag/adapter.h> +#include <jtag/swd.h> +#include <jtag/interface.h> +#include <jtag/commands.h> + +// Number of bits per SPI exchange +#define SPI_BITS 8 + +// Time in uS after the last bit of transfer before deselecting the device +#define SPI_DESELECT_DELAY 0 + +// Maximum number of SWD transactions to queue together in a SPI exchange +#define MAX_QUEUE_ENTRIES 64 + +#define CMD_BITS 8 +#define TURN_BITS 1 +#define ACK_BITS 3 +#define DATA_BITS 32 +#define PARITY_BITS 1 + +#define SWD_WR_BITS (CMD_BITS + TURN_BITS + ACK_BITS + TURN_BITS + DATA_BITS + PARITY_BITS) +#define SWD_RD_BITS (CMD_BITS + TURN_BITS + ACK_BITS + DATA_BITS + PARITY_BITS + TURN_BITS) +#define SWD_OP_BITS (MAX(SWD_WR_BITS, SWD_RD_BITS)) +#define SWD_OP_BYTES (DIV_ROUND_UP(SWD_OP_BITS, SPI_BITS)) + +#define AP_DELAY_CLOCKS 8 +#define AP_DELAY_BYTES (DIV_ROUND_UP(AP_DELAY_CLOCKS, SPI_BITS)) + +#define END_IDLE_CLOCKS 8 +#define END_IDLE_BYTES (DIV_ROUND_UP(END_IDLE_CLOCKS, SPI_BITS)) + +// File descriptor for SPI device +static int spi_fd = -1; + +// SPI Configuration +static char *spi_path; +static uint32_t spi_mode = SPI_MODE_3; // Note: SPI in LSB mode is not often supported. We'll flip LSB to MSB ourselves. +static uint32_t spi_speed; + +struct queue_info { + unsigned int buf_idx; + uint32_t *rx_ptr; +}; + +static int queue_retval; +static unsigned int max_queue_entries; +static unsigned int queue_fill; +static unsigned int queue_buf_fill; +static unsigned int queue_buf_size; +static struct queue_info *queue_infos; +static uint8_t *queue_tx_buf; +static uint8_t *queue_rx_buf; +static uint8_t *tx_flip_buf; + +static int spidev_swd_switch_seq(enum swd_special_seq seq); +static void spidev_swd_write_reg(uint8_t cmd, uint32_t value, uint32_t ap_delay_clk); + +static void spi_exchange(const uint8_t *tx_data, uint8_t *rx_data, unsigned int len) +{ +#ifdef LOG_SPI_EXCHANGE + LOG_OUTPUT("exchange: len=%u\n", len); +#endif // LOG_SPI_EXCHANGE + + if (len == 0) { + LOG_DEBUG("exchange with no length"); + return; + } + + if (!tx_data && !rx_data) { + LOG_DEBUG("exchange with no valid tx or rx pointers"); + return; + } + + if (len > queue_buf_size) { + LOG_ERROR("exchange too large len=%u ", len); + return; + } + + if (tx_data) { + // Reverse LSB to MSB + for (unsigned int i = 0; i < len; i++) + tx_flip_buf[i] = flip_u32(tx_data[i], 8); + +#ifdef LOG_SPI_EXCHANGE + if (len != 0) { + LOG_OUTPUT(" tx_buf="); + for (unsigned int i = 0; i < len; i++) + LOG_OUTPUT("%.2" PRIx8 " ", tx_flip_buf[i]); + } + LOG_OUTPUT("\n"); +#endif // LOG_SPI_EXCHANGE + } + // Transmit the MSB buffer to SPI device. + struct spi_ioc_transfer tr = { + /* The following must be cast to unsigned long to compile correctly on + * 32 and 64 bit machines (as is done in the spidev examples in Linux + * kernel code in tools/spi/). + */ + .tx_buf = (unsigned long)(tx_data ? tx_flip_buf : NULL), + .rx_buf = (unsigned long)rx_data, + .len = len, + .delay_usecs = SPI_DESELECT_DELAY, + .speed_hz = spi_speed, + .bits_per_word = SPI_BITS, + }; + int ret = ioctl(spi_fd, SPI_IOC_MESSAGE(1), &tr); + + if (ret < 1) { + LOG_ERROR("exchange failed"); + return; + } + + if (rx_data) { +#ifdef LOG_SPI_EXCHANGE + if (len != 0) { + LOG_OUTPUT(" rx_buf="); + for (unsigned int i = 0; i < len; i++) + LOG_OUTPUT("%.2" PRIx8 " ", rx_data[i]); + } + LOG_OUTPUT("\n"); +#endif // LOG_SPI_EXCHANGE + + // Reverse MSB to LSB + for (unsigned int i = 0; i < len; i++) + rx_data[i] = flip_u32(rx_data[i], 8); + } +} + +static int spidev_speed(int speed) +{ + uint32_t tmp_speed = speed; + + int ret = ioctl(spi_fd, SPI_IOC_WR_MAX_SPEED_HZ, &tmp_speed); + if (ret == -1) { + LOG_ERROR("Failed to set SPI %d speed", speed); + return ERROR_FAIL; + } + + spi_speed = speed; + + return ERROR_OK; +} + +static int spidev_speed_div(int speed, int *khz) +{ + *khz = speed / 1000; + return ERROR_OK; +} + +static int spidev_khz(int khz, int *jtag_speed) +{ + if (khz == 0) { + LOG_DEBUG("RCLK not supported"); + return ERROR_FAIL; + } + + *jtag_speed = khz * 1000; + return ERROR_OK; +} + +static void spidev_free_queue(void) +{ + max_queue_entries = 0; + queue_buf_size = 0; + + free(queue_infos); + queue_infos = NULL; + + free(queue_tx_buf); + queue_tx_buf = NULL; + + free(queue_rx_buf); + queue_rx_buf = NULL; + + free(tx_flip_buf); + tx_flip_buf = NULL; +} + +static void spidev_clear_queue(void) +{ + queue_fill = 0; + queue_buf_fill = 0; + + memset(queue_infos, 0, sizeof(struct queue_info) * max_queue_entries); + memset(queue_tx_buf, 0, queue_buf_size); + memset(queue_rx_buf, 0, queue_buf_size); + memset(tx_flip_buf, 0, queue_buf_size); +} + +static int spidev_alloc_queue(unsigned int new_queue_entries) +{ + if (queue_fill || queue_buf_fill) { + LOG_ERROR("Can't realloc queue when queue is in use"); + return ERROR_FAIL; + } + + unsigned int new_queue_buf_size = + (new_queue_entries * (SWD_OP_BYTES + AP_DELAY_BYTES)) + END_IDLE_BYTES; + + queue_infos = realloc(queue_infos, sizeof(struct queue_info) * new_queue_entries); + if (!queue_infos) + goto realloc_fail; + + queue_tx_buf = realloc(queue_tx_buf, new_queue_buf_size); + if (!queue_tx_buf) + goto realloc_fail; + + queue_rx_buf = realloc(queue_rx_buf, new_queue_buf_size); + if (!queue_rx_buf) + goto realloc_fail; + + tx_flip_buf = realloc(tx_flip_buf, new_queue_buf_size); + if (!tx_flip_buf) + goto realloc_fail; + + max_queue_entries = new_queue_entries; + queue_buf_size = new_queue_buf_size; + + spidev_clear_queue(); + + LOG_DEBUG("Set queue entries to %u (buffers %u bytes)", max_queue_entries, queue_buf_size); + + return ERROR_OK; + +realloc_fail: + spidev_free_queue(); + + LOG_ERROR("Couldn't allocate queue. Out of memory."); + return ERROR_FAIL; +} + +static int spidev_init(void) +{ + LOG_INFO("SPI SWD driver"); + + if (spi_fd >= 0) + return ERROR_OK; + + if (!spi_path) { + LOG_ERROR("Path to spidev not set"); + return ERROR_JTAG_INIT_FAILED; + } + + // Open SPI device. + spi_fd = open(spi_path, O_RDWR); + if (spi_fd < 0) { + LOG_ERROR("Failed to open SPI port at %s", spi_path); + return ERROR_JTAG_INIT_FAILED; + } + + int ret; + // Set 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; + } + + // Set SPI bits per word. + uint32_t spi_bits = SPI_BITS; + ret = ioctl(spi_fd, SPI_IOC_WR_BITS_PER_WORD, &spi_bits); + if (ret == -1) { + LOG_ERROR("Failed to set SPI %" PRIu8 " bits per transfer", spi_bits); + return ERROR_JTAG_INIT_FAILED; + } + + LOG_INFO("Opened SPI device at %s in mode 0x%" PRIx32 " with %" PRIu8 " bits ", + spi_path, spi_mode, spi_bits); + + if (max_queue_entries == 0) { + ret = spidev_alloc_queue(MAX_QUEUE_ENTRIES); + if (ret != ERROR_OK) + return ERROR_JTAG_INIT_FAILED; + } + + return ERROR_OK; +} + +static int spidev_quit(void) +{ + spidev_free_queue(); + + if (spi_fd < 0) + return ERROR_OK; + + close(spi_fd); + spi_fd = -1; + + free(spi_path); + spi_path = NULL; + + return ERROR_OK; +} + +static int spidev_swd_init(void) +{ + LOG_DEBUG("spidev_swd_init"); + return ERROR_OK; +} + +static int spidev_swd_execute_queue(unsigned int end_idle_bytes) +{ + LOG_DEBUG_IO("Executing %u queued transactions", queue_fill); + + if (queue_retval != ERROR_OK) { + LOG_DEBUG_IO("Skipping due to previous errors: %d", queue_retval); + goto skip; + } + + /* A transaction must be followed by another transaction or at least 8 idle + * cycles to ensure that data is clocked through the AP. Since the tx + * buffer is zeroed after each queue run, every byte added to the buffer + * fill will add on an additional 8 idle cycles. + */ + queue_buf_fill += end_idle_bytes; + + spi_exchange(queue_tx_buf, queue_rx_buf, queue_buf_fill); + + for (unsigned int queue_idx = 0; queue_idx < queue_fill; queue_idx++) { + unsigned int buf_idx = queue_infos[queue_idx].buf_idx; + uint8_t *tx_ptr = &queue_tx_buf[buf_idx]; + uint8_t *rx_ptr = &queue_rx_buf[buf_idx]; + uint8_t cmd = buf_get_u32(tx_ptr, 0, CMD_BITS); + bool read = cmd & SWD_CMD_RNW ? true : false; + int ack = buf_get_u32(rx_ptr, CMD_BITS + TURN_BITS, ACK_BITS); + uint32_t data = read ? + buf_get_u32(rx_ptr, CMD_BITS + TURN_BITS + ACK_BITS, DATA_BITS) : + buf_get_u32(tx_ptr, CMD_BITS + TURN_BITS + ACK_BITS + TURN_BITS, DATA_BITS); + + // Devices do not reply to DP_TARGETSEL write cmd, ignore received ack + bool check_ack = swd_cmd_returns_ack(cmd); + + LOG_CUSTOM_LEVEL((check_ack && ack != SWD_ACK_OK) ? LOG_LVL_DEBUG : LOG_LVL_DEBUG_IO, + "%s%s %s %s reg %X = %08" PRIx32, + check_ack ? "" : "ack ignored ", + ack == SWD_ACK_OK ? "OK" : + ack == SWD_ACK_WAIT ? "WAIT" : + ack == SWD_ACK_FAULT ? "FAULT" : "JUNK", + cmd & SWD_CMD_APNDP ? "AP" : "DP", + read ? "read" : "write", + (cmd & SWD_CMD_A32) >> 1, + data); + + if (ack != SWD_ACK_OK && check_ack) { + queue_retval = swd_ack_to_error_code(ack); + goto skip; + + } else if (read) { + int parity = buf_get_u32(rx_ptr, CMD_BITS + TURN_BITS + ACK_BITS + DATA_BITS, PARITY_BITS); + + if (parity != parity_u32(data)) { + LOG_ERROR("SWD Read data parity mismatch"); + queue_retval = ERROR_FAIL; + goto skip; + } + + if (queue_infos[queue_idx].rx_ptr) + *queue_infos[queue_idx].rx_ptr = data; + } + } + +skip: + spidev_clear_queue(); + + int retval = queue_retval; + queue_retval = ERROR_OK; + + return retval; +} + +static int spidev_swd_run_queue(void) +{ + /* Since we are unsure if another SWD transaction will follow the + * transactions we are just about to execute, we need to add on 8 idle + * cycles. + */ + return spidev_swd_execute_queue(END_IDLE_BYTES); +} + +static void spidev_swd_queue_cmd(uint8_t cmd, uint32_t *dst, uint32_t data, uint32_t ap_delay_clk) +{ + unsigned int swd_op_bytes = DIV_ROUND_UP(SWD_OP_BITS + ap_delay_clk, SPI_BITS); + + if (queue_fill >= max_queue_entries || + queue_buf_fill + swd_op_bytes + END_IDLE_BYTES > queue_buf_size) { + /* Not enough room in the queue. Run the queue. No idle bytes are + * needed because we are going to execute transactions right after + * the queue is emptied. + */ + queue_retval = spidev_swd_execute_queue(0); + } + + if (queue_retval != ERROR_OK) + return; + + uint8_t *tx_ptr = &queue_tx_buf[queue_buf_fill]; + + cmd |= SWD_CMD_START | SWD_CMD_PARK; + + buf_set_u32(tx_ptr, 0, CMD_BITS, cmd); + + if (cmd & SWD_CMD_RNW) { + // Queue a read transaction + queue_infos[queue_fill].rx_ptr = dst; + } else { + // Queue a write transaction + buf_set_u32(tx_ptr, + CMD_BITS + TURN_BITS + ACK_BITS + TURN_BITS, DATA_BITS, data); + buf_set_u32(tx_ptr, + CMD_BITS + TURN_BITS + ACK_BITS + TURN_BITS + DATA_BITS, PARITY_BITS, parity_u32(data)); + } + + queue_infos[queue_fill].buf_idx = queue_buf_fill; + + /* Add idle cycles after AP accesses to avoid WAIT. Buffer is already + * zeroed so we just need to advance the pointer to add idle cycles. + */ + queue_buf_fill += swd_op_bytes; + + queue_fill++; +} + +static void spidev_swd_read_reg(uint8_t cmd, uint32_t *value, uint32_t ap_delay_clk) +{ + assert(cmd & SWD_CMD_RNW); + spidev_swd_queue_cmd(cmd, value, 0, ap_delay_clk); +} + +static void spidev_swd_write_reg(uint8_t cmd, uint32_t value, uint32_t ap_delay_clk) +{ + assert(!(cmd & SWD_CMD_RNW)); + spidev_swd_queue_cmd(cmd, NULL, value, ap_delay_clk); +} + +static int spidev_swd_switch_seq(enum swd_special_seq seq) +{ + switch (seq) { + case LINE_RESET: + LOG_DEBUG_IO("SWD line reset"); + spi_exchange(swd_seq_line_reset, NULL, swd_seq_line_reset_len / SPI_BITS); + break; + case JTAG_TO_SWD: + LOG_DEBUG("JTAG-to-SWD"); + spi_exchange(swd_seq_jtag_to_swd, NULL, swd_seq_jtag_to_swd_len / SPI_BITS); + break; + case JTAG_TO_DORMANT: + LOG_DEBUG("JTAG-to-DORMANT"); + spi_exchange(swd_seq_jtag_to_dormant, NULL, swd_seq_jtag_to_dormant_len / SPI_BITS); + break; + case SWD_TO_JTAG: + LOG_DEBUG("SWD-to-JTAG"); + spi_exchange(swd_seq_swd_to_jtag, NULL, swd_seq_swd_to_jtag_len / SPI_BITS); + break; + case SWD_TO_DORMANT: + LOG_DEBUG("SWD-to-DORMANT"); + spi_exchange(swd_seq_swd_to_dormant, NULL, swd_seq_swd_to_dormant_len / SPI_BITS); + break; + case DORMANT_TO_SWD: + LOG_DEBUG("DORMANT-to-SWD"); + spi_exchange(swd_seq_dormant_to_swd, NULL, swd_seq_dormant_to_swd_len / SPI_BITS); + break; + case DORMANT_TO_JTAG: + LOG_DEBUG("DORMANT-to-JTAG"); + spi_exchange(swd_seq_dormant_to_jtag, NULL, swd_seq_dormant_to_jtag_len / SPI_BITS); + break; + default: + LOG_ERROR("Sequence %d not supported", seq); + return ERROR_FAIL; + } + + return ERROR_OK; +} + +COMMAND_HANDLER(spidev_handle_path_command) +{ + if (CMD_ARGC != 1) + return ERROR_COMMAND_SYNTAX_ERROR; + + free(spi_path); + spi_path = strdup(CMD_ARGV[0]); + if (!spi_path) { + LOG_ERROR("Out of memory"); + return ERROR_FAIL; + } + + return ERROR_OK; +} + +COMMAND_HANDLER(spidev_handle_mode_command) +{ + if (CMD_ARGC != 1) + return ERROR_COMMAND_SYNTAX_ERROR; + + COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], spi_mode); + return ERROR_OK; +} + +COMMAND_HANDLER(spidev_handle_queue_entries_command) +{ + uint32_t new_queue_entries; + + if (CMD_ARGC != 1) + return ERROR_COMMAND_SYNTAX_ERROR; + + COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], new_queue_entries); + + return spidev_alloc_queue(new_queue_entries); +} + +const struct swd_driver spidev_swd = { + .init = spidev_swd_init, + .switch_seq = spidev_swd_switch_seq, + .read_reg = spidev_swd_read_reg, + .write_reg = spidev_swd_write_reg, + .run = spidev_swd_run_queue, +}; + +static const struct command_registration spidev_subcommand_handlers[] = { + { + .name = "path", + .handler = &spidev_handle_path_command, + .mode = COMMAND_CONFIG, + .help = "set the path to the spidev device", + .usage = "path_to_spidev", + }, + { + .name = "mode", + .handler = &spidev_handle_mode_command, + .mode = COMMAND_CONFIG, + .help = "set the mode of the spi port with optional bit flags (default=3)", + .usage = "mode", + }, + { + .name = "queue_entries", + .handler = &spidev_handle_queue_entries_command, + .mode = COMMAND_CONFIG, + .help = "set the queue entry size (default=64)", + .usage = "queue_entries", + }, + COMMAND_REGISTRATION_DONE +}; + +static const struct command_registration spidev_command_handlers[] = { + { + .name = "spidev", + .mode = COMMAND_ANY, + .help = "perform spidev management", + .chain = spidev_subcommand_handlers, + .usage = "", + }, + COMMAND_REGISTRATION_DONE +}; + +// Only SWD transport supported +static const char *const spidev_transports[] = { "swd", NULL }; + +struct adapter_driver linuxspidev_adapter_driver = { + .name = "linuxspidev", + .transports = spidev_transports, + .commands = spidev_command_handlers, + + .init = spidev_init, + .quit = spidev_quit, + .speed = spidev_speed, + .khz = spidev_khz, + .speed_div = spidev_speed_div, + + .swd_ops = &spidev_swd, +}; diff --git a/src/jtag/drivers/minidriver_imp.h b/src/jtag/drivers/minidriver_imp.h index 7afb463..f3582f6 100644 --- a/src/jtag/drivers/minidriver_imp.h +++ b/src/jtag/drivers/minidriver_imp.h @@ -13,16 +13,10 @@ static inline void interface_jtag_add_scan_check_alloc(struct scan_field *field) { - unsigned num_bytes = DIV_ROUND_UP(field->num_bits, 8); + unsigned int num_bytes = DIV_ROUND_UP(field->num_bits, 8); field->in_value = cmd_queue_alloc(num_bytes); } -void interface_jtag_add_callback(jtag_callback1_t f, jtag_callback_data_t data0); - -void interface_jtag_add_callback4(jtag_callback_t f, jtag_callback_data_t data0, - jtag_callback_data_t data1, jtag_callback_data_t data2, - jtag_callback_data_t data3); - void jtag_add_callback4(jtag_callback_t f, jtag_callback_data_t data0, jtag_callback_data_t data1, jtag_callback_data_t data2, jtag_callback_data_t data3); diff --git a/src/jtag/drivers/mpsse.c b/src/jtag/drivers/mpsse.c index f3499e3..38393ad 100644 --- a/src/jtag/drivers/mpsse.c +++ b/src/jtag/drivers/mpsse.c @@ -64,17 +64,19 @@ struct mpsse_ctx { uint8_t interface; enum ftdi_chip_type type; uint8_t *write_buffer; - unsigned write_size; - unsigned write_count; + unsigned int write_size; + unsigned int write_count; uint8_t *read_buffer; - unsigned read_size; - unsigned read_count; + unsigned int read_size; + unsigned int read_count; uint8_t *read_chunk; - unsigned read_chunk_size; + unsigned int read_chunk_size; struct bit_copy_queue read_queue; int retval; }; +static void mpsse_purge(struct mpsse_ctx *ctx); + /* Returns true if the string descriptor indexed by str_index in device matches string */ static bool string_descriptor_equal(struct libusb_device_handle *device, uint8_t str_index, const char *string) @@ -283,6 +285,9 @@ static bool open_matching_device(struct mpsse_ctx *ctx, const uint16_t vids[], c case 0x3300: ctx->type = TYPE_FT232HP; break; + case 0x3600: + ctx->type = TYPE_FT4232HA; + break; default: LOG_ERROR("unsupported FTDI chip type: 0x%04x", desc.bcdDevice); goto error; @@ -418,7 +423,7 @@ bool mpsse_is_high_speed(struct mpsse_ctx *ctx) return ctx->type != TYPE_FT2232C; } -void mpsse_purge(struct mpsse_ctx *ctx) +static void mpsse_purge(struct mpsse_ctx *ctx) { int err; LOG_DEBUG("-"); @@ -441,13 +446,13 @@ void mpsse_purge(struct mpsse_ctx *ctx) } } -static unsigned buffer_write_space(struct mpsse_ctx *ctx) +static unsigned int buffer_write_space(struct mpsse_ctx *ctx) { /* Reserve one byte for SEND_IMMEDIATE */ return ctx->write_size - ctx->write_count - 1; } -static unsigned buffer_read_space(struct mpsse_ctx *ctx) +static unsigned int buffer_read_space(struct mpsse_ctx *ctx) { return ctx->read_size - ctx->read_count; } @@ -459,8 +464,8 @@ static void buffer_write_byte(struct mpsse_ctx *ctx, uint8_t data) ctx->write_buffer[ctx->write_count++] = data; } -static unsigned buffer_write(struct mpsse_ctx *ctx, const uint8_t *out, unsigned out_offset, - unsigned bit_count) +static unsigned int buffer_write(struct mpsse_ctx *ctx, const uint8_t *out, unsigned int out_offset, + unsigned int bit_count) { LOG_DEBUG_IO("%d bits", bit_count); assert(ctx->write_count + DIV_ROUND_UP(bit_count, 8) <= ctx->write_size); @@ -469,8 +474,8 @@ static unsigned buffer_write(struct mpsse_ctx *ctx, const uint8_t *out, unsigned return bit_count; } -static unsigned buffer_add_read(struct mpsse_ctx *ctx, uint8_t *in, unsigned in_offset, - unsigned bit_count, unsigned offset) +static unsigned int buffer_add_read(struct mpsse_ctx *ctx, uint8_t *in, unsigned int in_offset, + unsigned int bit_count, unsigned int offset) { LOG_DEBUG_IO("%d bits, offset %d", bit_count, offset); assert(ctx->read_count + DIV_ROUND_UP(bit_count, 8) <= ctx->read_size); @@ -480,20 +485,20 @@ static unsigned buffer_add_read(struct mpsse_ctx *ctx, uint8_t *in, unsigned in_ return bit_count; } -void mpsse_clock_data_out(struct mpsse_ctx *ctx, const uint8_t *out, unsigned out_offset, - unsigned length, uint8_t mode) +void mpsse_clock_data_out(struct mpsse_ctx *ctx, const uint8_t *out, unsigned int out_offset, + unsigned int length, uint8_t mode) { mpsse_clock_data(ctx, out, out_offset, NULL, 0, length, mode); } -void mpsse_clock_data_in(struct mpsse_ctx *ctx, uint8_t *in, unsigned in_offset, unsigned length, +void mpsse_clock_data_in(struct mpsse_ctx *ctx, uint8_t *in, unsigned int in_offset, unsigned int length, uint8_t mode) { mpsse_clock_data(ctx, NULL, 0, in, in_offset, length, mode); } -void mpsse_clock_data(struct mpsse_ctx *ctx, const uint8_t *out, unsigned out_offset, uint8_t *in, - unsigned in_offset, unsigned length, uint8_t mode) +void mpsse_clock_data(struct mpsse_ctx *ctx, const uint8_t *out, unsigned int out_offset, uint8_t *in, + unsigned int in_offset, unsigned int length, uint8_t mode) { /* TODO: Fix MSB first modes */ LOG_DEBUG_IO("%s%s %d bits", in ? "in" : "", out ? "out" : "", length); @@ -528,7 +533,7 @@ void mpsse_clock_data(struct mpsse_ctx *ctx, const uint8_t *out, unsigned out_of length = 0; } else { /* Byte transfer */ - unsigned this_bytes = length / 8; + unsigned int this_bytes = length / 8; /* MPSSE command limit */ if (this_bytes > 65536) this_bytes = 65536; @@ -555,7 +560,7 @@ void mpsse_clock_data(struct mpsse_ctx *ctx, const uint8_t *out, unsigned out_of this_bytes * 8, 0); if (!out && !in) - for (unsigned n = 0; n < this_bytes; n++) + for (unsigned int n = 0; n < this_bytes; n++) buffer_write_byte(ctx, 0x00); length -= this_bytes * 8; } @@ -563,14 +568,14 @@ void mpsse_clock_data(struct mpsse_ctx *ctx, const uint8_t *out, unsigned out_of } } -void mpsse_clock_tms_cs_out(struct mpsse_ctx *ctx, const uint8_t *out, unsigned out_offset, - unsigned length, bool tdi, uint8_t mode) +void mpsse_clock_tms_cs_out(struct mpsse_ctx *ctx, const uint8_t *out, unsigned int out_offset, + unsigned int length, bool tdi, uint8_t mode) { mpsse_clock_tms_cs(ctx, out, out_offset, NULL, 0, length, tdi, mode); } -void mpsse_clock_tms_cs(struct mpsse_ctx *ctx, const uint8_t *out, unsigned out_offset, uint8_t *in, - unsigned in_offset, unsigned length, bool tdi, uint8_t mode) +void mpsse_clock_tms_cs(struct mpsse_ctx *ctx, const uint8_t *out, unsigned int out_offset, uint8_t *in, + unsigned int in_offset, unsigned int length, bool tdi, uint8_t mode) { LOG_DEBUG_IO("%sout %d bits, tdi=%d", in ? "in" : "", length, tdi); assert(out); @@ -590,7 +595,7 @@ void mpsse_clock_tms_cs(struct mpsse_ctx *ctx, const uint8_t *out, unsigned out_ ctx->retval = mpsse_flush(ctx); /* Byte transfer */ - unsigned this_bits = length; + unsigned int this_bits = length; /* MPSSE command limit */ /* NOTE: there's a report of an FT2232 bug in this area, where shifting * exactly 7 bits can make problems with TMS signaling for the last @@ -706,7 +711,7 @@ void mpsse_loopback_config(struct mpsse_ctx *ctx, bool enable) single_byte_boolean_helper(ctx, enable, 0x84, 0x85); } -void mpsse_set_divisor(struct mpsse_ctx *ctx, uint16_t divisor) +static void mpsse_set_divisor(struct mpsse_ctx *ctx, uint16_t divisor) { LOG_DEBUG("%d", divisor); @@ -723,7 +728,7 @@ void mpsse_set_divisor(struct mpsse_ctx *ctx, uint16_t divisor) buffer_write_byte(ctx, divisor >> 8); } -int mpsse_divide_by_5_config(struct mpsse_ctx *ctx, bool enable) +static int mpsse_divide_by_5_config(struct mpsse_ctx *ctx, bool enable) { if (!mpsse_is_high_speed(ctx)) return ERROR_FAIL; @@ -734,7 +739,7 @@ int mpsse_divide_by_5_config(struct mpsse_ctx *ctx, bool enable) return ERROR_OK; } -int mpsse_rtck_config(struct mpsse_ctx *ctx, bool enable) +static int mpsse_rtck_config(struct mpsse_ctx *ctx, bool enable) { if (!mpsse_is_high_speed(ctx)) return ERROR_FAIL; @@ -780,7 +785,7 @@ int mpsse_set_frequency(struct mpsse_ctx *ctx, int frequency) struct transfer_result { struct mpsse_ctx *ctx; bool done; - unsigned transferred; + unsigned int transferred; }; static LIBUSB_CALL void read_cb(struct libusb_transfer *transfer) @@ -788,16 +793,16 @@ static LIBUSB_CALL void read_cb(struct libusb_transfer *transfer) struct transfer_result *res = transfer->user_data; struct mpsse_ctx *ctx = res->ctx; - unsigned packet_size = ctx->max_packet_size; + unsigned int packet_size = ctx->max_packet_size; DEBUG_PRINT_BUF(transfer->buffer, transfer->actual_length); /* Strip the two status bytes sent at the beginning of each USB packet * while copying the chunk buffer to the read buffer */ - unsigned num_packets = DIV_ROUND_UP(transfer->actual_length, packet_size); - unsigned chunk_remains = transfer->actual_length; - for (unsigned i = 0; i < num_packets && chunk_remains > 2; i++) { - unsigned this_size = packet_size - 2; + unsigned int num_packets = DIV_ROUND_UP(transfer->actual_length, packet_size); + unsigned int chunk_remains = transfer->actual_length; + for (unsigned int i = 0; i < num_packets && chunk_remains > 2; i++) { + unsigned int this_size = packet_size - 2; if (this_size > chunk_remains - 2) this_size = chunk_remains - 2; if (this_size > ctx->read_count - res->transferred) diff --git a/src/jtag/drivers/mpsse.h b/src/jtag/drivers/mpsse.h index e92a9bb..e95f842 100644 --- a/src/jtag/drivers/mpsse.h +++ b/src/jtag/drivers/mpsse.h @@ -30,6 +30,7 @@ enum ftdi_chip_type { TYPE_FT4232HP, TYPE_FT233HP, TYPE_FT232HP, + TYPE_FT4232HA, }; struct mpsse_ctx; @@ -43,24 +44,21 @@ bool mpsse_is_high_speed(struct mpsse_ctx *ctx); /* Command queuing. These correspond to the MPSSE commands with the same names, but no need to care * about bit/byte transfer or data length limitation. Read data is guaranteed to be available only * after the following mpsse_flush(). */ -void mpsse_clock_data_out(struct mpsse_ctx *ctx, const uint8_t *out, unsigned out_offset, - unsigned length, uint8_t mode); -void mpsse_clock_data_in(struct mpsse_ctx *ctx, uint8_t *in, unsigned in_offset, unsigned length, +void mpsse_clock_data_out(struct mpsse_ctx *ctx, const uint8_t *out, unsigned int out_offset, + unsigned int length, uint8_t mode); +void mpsse_clock_data_in(struct mpsse_ctx *ctx, uint8_t *in, unsigned int in_offset, unsigned int length, uint8_t mode); -void mpsse_clock_data(struct mpsse_ctx *ctx, const uint8_t *out, unsigned out_offset, uint8_t *in, - unsigned in_offset, unsigned length, uint8_t mode); -void mpsse_clock_tms_cs_out(struct mpsse_ctx *ctx, const uint8_t *out, unsigned out_offset, - unsigned length, bool tdi, uint8_t mode); -void mpsse_clock_tms_cs(struct mpsse_ctx *ctx, const uint8_t *out, unsigned out_offset, uint8_t *in, - unsigned in_offset, unsigned length, bool tdi, uint8_t mode); +void mpsse_clock_data(struct mpsse_ctx *ctx, const uint8_t *out, unsigned int out_offset, uint8_t *in, + unsigned int in_offset, unsigned int length, uint8_t mode); +void mpsse_clock_tms_cs_out(struct mpsse_ctx *ctx, const uint8_t *out, unsigned int out_offset, + unsigned int length, bool tdi, uint8_t mode); +void mpsse_clock_tms_cs(struct mpsse_ctx *ctx, const uint8_t *out, unsigned int out_offset, uint8_t *in, + unsigned int in_offset, unsigned int length, bool tdi, uint8_t mode); void mpsse_set_data_bits_low_byte(struct mpsse_ctx *ctx, uint8_t data, uint8_t dir); void mpsse_set_data_bits_high_byte(struct mpsse_ctx *ctx, uint8_t data, uint8_t dir); void mpsse_read_data_bits_low_byte(struct mpsse_ctx *ctx, uint8_t *data); void mpsse_read_data_bits_high_byte(struct mpsse_ctx *ctx, uint8_t *data); void mpsse_loopback_config(struct mpsse_ctx *ctx, bool enable); -void mpsse_set_divisor(struct mpsse_ctx *ctx, uint16_t divisor); -int mpsse_divide_by_5_config(struct mpsse_ctx *ctx, bool enable); -int mpsse_rtck_config(struct mpsse_ctx *ctx, bool enable); /* Helper to set frequency in Hertz. Returns actual realizable frequency or negative error. * Frequency 0 means RTCK. */ @@ -68,6 +66,5 @@ int mpsse_set_frequency(struct mpsse_ctx *ctx, int frequency); /* Queue handling */ int mpsse_flush(struct mpsse_ctx *ctx); -void mpsse_purge(struct mpsse_ctx *ctx); #endif /* OPENOCD_JTAG_DRIVERS_MPSSE_H */ diff --git a/src/jtag/drivers/opendous.c b/src/jtag/drivers/opendous.c index 81b74d4..999afb3 100644 --- a/src/jtag/drivers/opendous.c +++ b/src/jtag/drivers/opendous.c @@ -104,10 +104,10 @@ static int opendous_init(void); static int opendous_quit(void); /* Queue command functions */ -static void opendous_end_state(tap_state_t state); +static void opendous_end_state(enum tap_state state); static void opendous_state_move(void); -static void opendous_path_move(int num_states, tap_state_t *path); -static void opendous_runtest(int num_cycles); +static void opendous_path_move(unsigned int num_states, enum tap_state *path); +static void opendous_runtest(unsigned int num_cycles); static void opendous_scan(int ir_scan, enum scan_type type, uint8_t *buffer, int scan_size, struct scan_command *command); static void opendous_reset(int trst, int srst); @@ -248,7 +248,7 @@ static int opendous_execute_queue(struct jtag_command *cmd_queue) while (cmd) { switch (cmd->type) { case JTAG_RUNTEST: - LOG_DEBUG_IO("runtest %i cycles, end in %i", cmd->cmd.runtest->num_cycles, + LOG_DEBUG_IO("runtest %u cycles, end in %i", cmd->cmd.runtest->num_cycles, cmd->cmd.runtest->end_state); if (cmd->cmd.runtest->end_state != -1) @@ -265,7 +265,7 @@ static int opendous_execute_queue(struct jtag_command *cmd_queue) break; case JTAG_PATHMOVE: - LOG_DEBUG_IO("pathmove: %i states, end in %i", + LOG_DEBUG_IO("pathmove: %u states, end in %i", cmd->cmd.pathmove->num_states, cmd->cmd.pathmove->path[cmd->cmd.pathmove->num_states - 1]); @@ -393,7 +393,7 @@ static int opendous_quit(void) /***************************************************************************/ /* Queue command implementations */ -void opendous_end_state(tap_state_t state) +void opendous_end_state(enum tap_state state) { if (tap_is_state_stable(state)) tap_set_end_state(state); @@ -419,11 +419,9 @@ void opendous_state_move(void) tap_set_state(tap_get_end_state()); } -void opendous_path_move(int num_states, tap_state_t *path) +void opendous_path_move(unsigned int num_states, enum tap_state *path) { - int i; - - for (i = 0; i < num_states; i++) { + for (unsigned int i = 0; i < num_states; i++) { if (path[i] == tap_state_transition(tap_get_state(), false)) opendous_tap_append_step(0, 0); else if (path[i] == tap_state_transition(tap_get_state(), true)) @@ -440,11 +438,9 @@ void opendous_path_move(int num_states, tap_state_t *path) tap_set_end_state(tap_get_state()); } -void opendous_runtest(int num_cycles) +void opendous_runtest(unsigned int num_cycles) { - int i; - - tap_state_t saved_end_state = tap_get_end_state(); + enum tap_state saved_end_state = tap_get_end_state(); /* only do a state_move when we're not already in IDLE */ if (tap_get_state() != TAP_IDLE) { @@ -453,7 +449,7 @@ void opendous_runtest(int num_cycles) } /* execute num_cycles */ - for (i = 0; i < num_cycles; i++) + for (unsigned int i = 0; i < num_cycles; i++) opendous_tap_append_step(0, 0); /* finish in end_state */ @@ -464,7 +460,7 @@ void opendous_runtest(int num_cycles) void opendous_scan(int ir_scan, enum scan_type type, uint8_t *buffer, int scan_size, struct scan_command *command) { - tap_state_t saved_end_state; + enum tap_state saved_end_state; opendous_tap_ensure_space(1, scan_size + 8); diff --git a/src/jtag/drivers/openjtag.c b/src/jtag/drivers/openjtag.c index ea78ca8..14bcc17 100644 --- a/src/jtag/drivers/openjtag.c +++ b/src/jtag/drivers/openjtag.c @@ -50,7 +50,7 @@ static const char * const openjtag_variant_names[] = { /* * OpenJTAG-OpenOCD state conversion */ -typedef enum openjtag_tap_state { +enum openjtag_tap_state { OPENJTAG_TAP_INVALID = -1, OPENJTAG_TAP_RESET = 0, OPENJTAG_TAP_IDLE = 1, @@ -68,7 +68,7 @@ typedef enum openjtag_tap_state { OPENJTAG_TAP_PAUSE_IR = 13, OPENJTAG_TAP_EXIT2_IR = 14, OPENJTAG_TAP_UPDATE_IR = 15, -} openjtag_tap_state_t; +}; /* OPENJTAG access library includes */ #include "libftdi_helper.h" @@ -748,7 +748,7 @@ static void openjtag_execute_scan(struct jtag_command *cmd) static void openjtag_execute_runtest(struct jtag_command *cmd) { - tap_state_t end_state = cmd->cmd.runtest->end_state; + enum tap_state end_state = cmd->cmd.runtest->end_state; tap_set_end_state(end_state); /* only do a state_move when we're not already in IDLE */ @@ -760,15 +760,17 @@ static void openjtag_execute_runtest(struct jtag_command *cmd) if (openjtag_variant != OPENJTAG_VARIANT_CY7C65215 || cmd->cmd.runtest->num_cycles) { uint8_t command; - int cycles = cmd->cmd.runtest->num_cycles; + unsigned int num_cycles = cmd->cmd.runtest->num_cycles; do { + const unsigned int num_cycles_cmd = MIN(num_cycles, 16); + command = 7; - command |= (((cycles > 16 ? 16 : cycles) - 1) & 0x0F) << 4; + command |= ((num_cycles_cmd - 1) & 0x0F) << 4; openjtag_add_byte(command); - cycles -= 16; - } while (cycles > 0); + num_cycles -= num_cycles_cmd; + } while (num_cycles > 0); } tap_set_end_state(end_state); diff --git a/src/jtag/drivers/osbdm.c b/src/jtag/drivers/osbdm.c index 8d4fc90..80f66d1 100644 --- a/src/jtag/drivers/osbdm.c +++ b/src/jtag/drivers/osbdm.c @@ -380,8 +380,8 @@ static int osbdm_quit(void) static int osbdm_add_pathmove( struct queue *queue, - tap_state_t *path, - int num_states) + enum tap_state *path, + unsigned int num_states) { assert(num_states <= 32); @@ -392,7 +392,7 @@ static int osbdm_add_pathmove( } uint32_t tms = 0; - for (int i = 0; i < num_states; i++) { + for (unsigned int i = 0; i < num_states; i++) { if (tap_state_transition(tap_get_state(), 1) == path[i]) { tms |= (1 << i); } else if (tap_state_transition(tap_get_state(), 0) == path[i]) { @@ -415,7 +415,7 @@ static int osbdm_add_pathmove( static int osbdm_add_statemove( struct queue *queue, - tap_state_t new_state, + enum tap_state new_state, int skip_first) { int len = 0; @@ -451,7 +451,7 @@ static int osbdm_add_statemove( static int osbdm_add_stableclocks( struct queue *queue, - int count) + unsigned int count) { if (!tap_is_state_stable(tap_get_state())) { LOG_ERROR("BUG: current state (%s) is not stable", @@ -489,8 +489,8 @@ static int osbdm_add_tms( static int osbdm_add_scan( struct queue *queue, struct scan_field *fields, - int num_fields, - tap_state_t end_state, + unsigned int num_fields, + enum tap_state end_state, bool ir_scan) { /* Move to desired shift state */ @@ -508,7 +508,7 @@ static int osbdm_add_scan( /* Add scan */ tap_set_end_state(end_state); - for (int idx = 0; idx < num_fields; idx++) { + for (unsigned int idx = 0; idx < num_fields; idx++) { struct sequence *next = queue_add_tail(queue, fields[idx].num_bits); if (!next) { LOG_ERROR("Can't allocate bit sequence"); @@ -536,8 +536,8 @@ static int osbdm_add_scan( static int osbdm_add_runtest( struct queue *queue, - int num_cycles, - tap_state_t end_state) + unsigned int num_cycles, + enum tap_state end_state) { if (osbdm_add_statemove(queue, TAP_IDLE, 0) != ERROR_OK) return ERROR_FAIL; diff --git a/src/jtag/drivers/parport.c b/src/jtag/drivers/parport.c index d26a510..3b20fe2 100644 --- a/src/jtag/drivers/parport.c +++ b/src/jtag/drivers/parport.c @@ -45,21 +45,31 @@ #include <windows.h> #endif -/* parallel port cable description - */ +// Parallel port cable description. struct cable { const char *name; - uint8_t TDO_MASK; /* status port bit containing current TDO value */ - uint8_t TRST_MASK; /* data port bit for TRST */ - uint8_t TMS_MASK; /* data port bit for TMS */ - uint8_t TCK_MASK; /* data port bit for TCK */ - uint8_t TDI_MASK; /* data port bit for TDI */ - uint8_t SRST_MASK; /* data port bit for SRST */ - uint8_t OUTPUT_INVERT; /* data port bits that should be inverted */ - uint8_t INPUT_INVERT; /* status port that should be inverted */ - uint8_t PORT_INIT; /* initialize data port with this value */ - uint8_t PORT_EXIT; /* de-initialize data port with this value */ - uint8_t LED_MASK; /* data port bit for LED */ + // Status port bit containing current TDO value. + uint8_t tdo_mask; + // Data port bit for TRST. + uint8_t trst_mask; + // Data port bit for TMD. + uint8_t tms_mask; + // Data port bit for TCK. + uint8_t tck_mask; + // Data port bit for TDI. + uint8_t tdi_mask; + // Data port bit for SRST. + uint8_t srst_mask; + // Data port bits that should be inverted. + uint8_t output_invert; + // Status port that should be inverted. + uint8_t input_invert; + // Initialize data port with this value. + uint8_t port_init; + // De-initialize data port with this value. + uint8_t port_exit; + // Data port bit for LED. + uint8_t led_mask; }; static const struct cable cables[] = { @@ -87,15 +97,14 @@ static const struct cable cables[] = { { NULL, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }; -/* configuration */ +// Configuration variables. static char *parport_cable; static uint16_t parport_port; static bool parport_exit; static uint32_t parport_toggling_time_ns = 1000; static int wait_states; -/* interface variables - */ +// Interface variables. static const struct cable *cable; static uint8_t dataport_value; @@ -106,7 +115,7 @@ static unsigned long dataport; static unsigned long statusport; #endif -static bb_value_t parport_read(void) +static enum bb_value parport_read(void) { int data = 0; @@ -116,7 +125,7 @@ static bb_value_t parport_read(void) data = inb(statusport); #endif - if ((data ^ cable->INPUT_INVERT) & cable->TDO_MASK) + if ((data ^ cable->input_invert) & cable->tdo_mask) return BB_HIGH; else return BB_LOW; @@ -125,7 +134,7 @@ static bb_value_t parport_read(void) static inline void parport_write_data(void) { uint8_t output; - output = dataport_value ^ cable->OUTPUT_INVERT; + output = dataport_value ^ cable->output_invert; #if PARPORT_USE_PPDEV == 1 ioctl(device_handle, PPWDATA, &output); @@ -143,19 +152,19 @@ static int parport_write(int tck, int tms, int tdi) int i = wait_states + 1; if (tck) - dataport_value |= cable->TCK_MASK; + dataport_value |= cable->tck_mask; else - dataport_value &= ~cable->TCK_MASK; + dataport_value &= ~cable->tck_mask; if (tms) - dataport_value |= cable->TMS_MASK; + dataport_value |= cable->tms_mask; else - dataport_value &= ~cable->TMS_MASK; + dataport_value &= ~cable->tms_mask; if (tdi) - dataport_value |= cable->TDI_MASK; + dataport_value |= cable->tdi_mask; else - dataport_value &= ~cable->TDI_MASK; + dataport_value &= ~cable->tdi_mask; while (i-- > 0) parport_write_data(); @@ -163,33 +172,32 @@ static int parport_write(int tck, int tms, int tdi) return ERROR_OK; } -/* (1) assert or (0) deassert reset lines */ +// (1) assert or (0) deassert reset lines. static int parport_reset(int trst, int srst) { LOG_DEBUG("trst: %i, srst: %i", trst, srst); if (trst == 0) - dataport_value |= cable->TRST_MASK; + dataport_value |= cable->trst_mask; else if (trst == 1) - dataport_value &= ~cable->TRST_MASK; + dataport_value &= ~cable->trst_mask; if (srst == 0) - dataport_value |= cable->SRST_MASK; + dataport_value |= cable->srst_mask; else if (srst == 1) - dataport_value &= ~cable->SRST_MASK; + dataport_value &= ~cable->srst_mask; parport_write_data(); return ERROR_OK; } -/* turn LED on parport adapter on (1) or off (0) */ -static int parport_led(int on) +static int parport_led(bool on) { if (on) - dataport_value |= cable->LED_MASK; + dataport_value |= cable->led_mask; else - dataport_value &= ~cable->LED_MASK; + dataport_value &= ~cable->led_mask; parport_write_data(); @@ -204,7 +212,7 @@ static int parport_speed(int speed) static int parport_khz(int khz, int *jtag_speed) { - if (khz == 0) { + if (!khz) { LOG_DEBUG("RCLK not supported"); return ERROR_FAIL; } @@ -247,11 +255,11 @@ static int parport_get_giveio_access(void) } #endif -static struct bitbang_interface parport_bitbang = { - .read = &parport_read, - .write = &parport_write, - .blink = &parport_led, - }; +static const struct bitbang_interface parport_bitbang = { + .read = &parport_read, + .write = &parport_write, + .blink = &parport_led, +}; static int parport_init(void) { @@ -268,7 +276,7 @@ static int parport_init(void) } while (cur_cable->name) { - if (strcmp(cur_cable->name, parport_cable) == 0) { + if (!strcmp(cur_cable->name, parport_cable)) { cable = cur_cable; break; } @@ -280,7 +288,7 @@ static int parport_init(void) return ERROR_JTAG_INIT_FAILED; } - dataport_value = cable->PORT_INIT; + dataport_value = cable->port_init; #if PARPORT_USE_PPDEV == 1 if (device_handle > 0) { @@ -332,7 +340,7 @@ static int parport_init(void) #endif /* not __FreeBSD__, __FreeBSD_kernel__ */ #else /* not PARPORT_USE_PPDEV */ - if (parport_port == 0) { + if (!parport_port) { parport_port = 0x378; LOG_WARNING("No parport port specified, using default '0x378' (LPT1)"); } @@ -351,7 +359,7 @@ static int parport_init(void) } LOG_DEBUG("...privileges granted"); - /* make sure parallel port is in right mode (clear tristate and interrupt */ + // Make sure parallel port is in right mode (clear tristate and interrupt. #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) outb(parport_port + 2, 0x0); #else @@ -364,7 +372,7 @@ static int parport_init(void) return ERROR_FAIL; if (parport_write(0, 0, 0) != ERROR_OK) return ERROR_FAIL; - if (parport_led(1) != ERROR_OK) + if (parport_led(true) != ERROR_OK) return ERROR_FAIL; bitbang_interface = &parport_bitbang; @@ -374,11 +382,11 @@ static int parport_init(void) static int parport_quit(void) { - if (parport_led(0) != ERROR_OK) + if (parport_led(false) != ERROR_OK) return ERROR_FAIL; if (parport_exit) { - dataport_value = cable->PORT_EXIT; + dataport_value = cable->port_exit; parport_write_data(); } @@ -388,13 +396,13 @@ static int parport_quit(void) return ERROR_OK; } -COMMAND_HANDLER(parport_handle_parport_port_command) +COMMAND_HANDLER(parport_handle_port_command) { if (CMD_ARGC == 1) { - /* only if the port wasn't overwritten by cmdline */ - if (parport_port == 0) + // Only if the port wasn't overwritten by cmdline. + if (!parport_port) { COMMAND_PARSE_NUMBER(u16, CMD_ARGV[0], parport_port); - else { + } else { LOG_ERROR("The parport port was already configured!"); return ERROR_FAIL; } @@ -405,14 +413,14 @@ COMMAND_HANDLER(parport_handle_parport_port_command) return ERROR_OK; } -COMMAND_HANDLER(parport_handle_parport_cable_command) +COMMAND_HANDLER(parport_handle_cable_command) { - if (CMD_ARGC == 0) + if (!CMD_ARGC) return ERROR_OK; - /* only if the cable name wasn't overwritten by cmdline */ + // Only if the cable name wasn't overwritten by cmdline. if (!parport_cable) { - /* REVISIT first verify that it's listed in cables[] ... */ + // TODO: REVISIT first verify that it's listed in cables[]. parport_cable = malloc(strlen(CMD_ARGV[0]) + sizeof(char)); if (!parport_cable) { LOG_ERROR("Out of memory"); @@ -421,7 +429,7 @@ COMMAND_HANDLER(parport_handle_parport_cable_command) strcpy(parport_cable, CMD_ARGV[0]); } - /* REVISIT it's probably worth returning the current value ... */ + // TODO: REVISIT it's probably worth returning the current value. return ERROR_OK; } @@ -436,7 +444,7 @@ COMMAND_HANDLER(parport_handle_write_on_exit_command) return ERROR_OK; } -COMMAND_HANDLER(parport_handle_parport_toggling_time_command) +COMMAND_HANDLER(parport_handle_toggling_time_command) { if (CMD_ARGC == 1) { uint32_t ns; @@ -445,7 +453,7 @@ COMMAND_HANDLER(parport_handle_parport_toggling_time_command) if (retval != ERROR_OK) return retval; - if (ns == 0) { + if (!ns) { LOG_ERROR("0 ns is not a valid parport toggling time"); return ERROR_FAIL; } @@ -453,9 +461,11 @@ COMMAND_HANDLER(parport_handle_parport_toggling_time_command) parport_toggling_time_ns = ns; retval = adapter_get_speed(&wait_states); if (retval != ERROR_OK) { - /* if adapter_get_speed fails then the clock_mode - * has not been configured, this happens if parport_toggling_time is - * called before the adapter speed is set */ + /* + * If adapter_get_speed fails then the clock_mode has + * not been configured, this happens if toggling_time is + * called before the adapter speed is set. + */ LOG_INFO("no parport speed set - defaulting to zero wait states"); wait_states = 0; } @@ -470,7 +480,7 @@ COMMAND_HANDLER(parport_handle_parport_toggling_time_command) static const struct command_registration parport_subcommand_handlers[] = { { .name = "port", - .handler = parport_handle_parport_port_command, + .handler = parport_handle_port_command, .mode = COMMAND_CONFIG, .help = "Display the address of the I/O port (e.g. 0x378) " "or the number of the '/dev/parport' device used. " @@ -479,11 +489,11 @@ static const struct command_registration parport_subcommand_handlers[] = { }, { .name = "cable", - .handler = parport_handle_parport_cable_command, + .handler = parport_handle_cable_command, .mode = COMMAND_CONFIG, .help = "Set the layout of the parallel port cable " "used to connect to the target.", - /* REVISIT there's no way to list layouts we know ... */ + // TODO: REVISIT there's no way to list layouts we know. .usage = "[layout]", }, { @@ -496,7 +506,7 @@ static const struct command_registration parport_subcommand_handlers[] = { }, { .name = "toggling_time", - .handler = parport_handle_parport_toggling_time_command, + .handler = parport_handle_toggling_time_command, .mode = COMMAND_CONFIG, .help = "Displays or assigns how many nanoseconds it " "takes for the hardware to toggle TCK.", diff --git a/src/jtag/drivers/remote_bitbang.c b/src/jtag/drivers/remote_bitbang.c index edd36f2..bb608ba 100644 --- a/src/jtag/drivers/remote_bitbang.c +++ b/src/jtag/drivers/remote_bitbang.c @@ -145,12 +145,12 @@ static int remote_bitbang_fill_buf(enum block_bool block) return ERROR_OK; } -typedef enum { +enum flush_bool { NO_FLUSH, FLUSH_SEND_BUF -} flush_bool_t; +}; -static int remote_bitbang_queue(int c, flush_bool_t flush) +static int remote_bitbang_queue(int c, enum flush_bool flush) { remote_bitbang_send_buf[remote_bitbang_send_buf_used++] = c; if (flush == FLUSH_SEND_BUF || @@ -176,7 +176,7 @@ static int remote_bitbang_quit(void) return ERROR_OK; } -static bb_value_t char_to_int(int c) +static enum bb_value char_to_int(int c) { switch (c) { case '0': @@ -198,7 +198,7 @@ static int remote_bitbang_sample(void) return remote_bitbang_queue('R', NO_FLUSH); } -static bb_value_t remote_bitbang_read_sample(void) +static enum bb_value remote_bitbang_read_sample(void) { if (remote_bitbang_recv_buf_empty()) { if (remote_bitbang_fill_buf(BLOCK) != ERROR_OK) @@ -251,7 +251,7 @@ static int remote_bitbang_sleep(unsigned int microseconds) return remote_bitbang_flush(); } -static int remote_bitbang_blink(int on) +static int remote_bitbang_blink(bool on) { char c = on ? 'B' : 'b'; return remote_bitbang_queue(c, FLUSH_SEND_BUF); @@ -278,7 +278,7 @@ static int remote_bitbang_swd_write(int swclk, int swdio) return remote_bitbang_queue(c, NO_FLUSH); } -static struct bitbang_interface remote_bitbang_bitbang = { +static const struct bitbang_interface remote_bitbang_bitbang = { .buf_size = sizeof(remote_bitbang_recv_buf) - 1, .sample = &remote_bitbang_sample, .read_sample = &remote_bitbang_read_sample, diff --git a/src/jtag/drivers/rlink.c b/src/jtag/drivers/rlink.c index afdf16e..6ea3729 100644 --- a/src/jtag/drivers/rlink.c +++ b/src/jtag/drivers/rlink.c @@ -842,7 +842,7 @@ static int tap_state_queue_append(uint8_t tms) return 0; } -static void rlink_end_state(tap_state_t state) +static void rlink_end_state(enum tap_state state) { if (tap_is_state_stable(state)) tap_set_end_state(state); @@ -869,7 +869,7 @@ static void rlink_state_move(void) static void rlink_path_move(struct pathmove_command *cmd) { - int num_states = cmd->num_states; + unsigned int num_states = cmd->num_states; int state_count; int tms = 0; @@ -896,11 +896,9 @@ static void rlink_path_move(struct pathmove_command *cmd) tap_set_end_state(tap_get_state()); } -static void rlink_runtest(int num_cycles) +static void rlink_runtest(unsigned int num_cycles) { - int i; - - tap_state_t saved_end_state = tap_get_end_state(); + enum tap_state saved_end_state = tap_get_end_state(); /* only do a state_move when we're not already in RTI */ if (tap_get_state() != TAP_IDLE) { @@ -909,7 +907,7 @@ static void rlink_runtest(int num_cycles) } /* execute num_cycles */ - for (i = 0; i < num_cycles; i++) + for (unsigned int i = 0; i < num_cycles; i++) tap_state_queue_append(0); /* finish in end_state */ @@ -1021,7 +1019,7 @@ static int rlink_scan(struct jtag_command *cmd, enum scan_type type, uint8_t *buffer, int scan_size) { bool ir_scan; - tap_state_t saved_end_state; + enum tap_state saved_end_state; int byte_bits; int extra_bits; int chunk_bits; @@ -1323,7 +1321,7 @@ static int rlink_execute_queue(struct jtag_command *cmd_queue) rlink_state_move(); break; case JTAG_PATHMOVE: - LOG_DEBUG_IO("pathmove: %i states, end in %i", + LOG_DEBUG_IO("pathmove: %u states, end in %i", cmd->cmd.pathmove->num_states, cmd->cmd.pathmove->path[cmd->cmd.pathmove->num_states - 1]); rlink_path_move(cmd->cmd.pathmove); diff --git a/src/jtag/drivers/rshim.c b/src/jtag/drivers/rshim.c index 21fc7fd..b37fe8c 100644 --- a/src/jtag/drivers/rshim.c +++ b/src/jtag/drivers/rshim.c @@ -60,14 +60,14 @@ #ifdef HAVE_SYS_IOCTL_H /* Message used to program rshim via ioctl(). */ -typedef struct { +struct rshim_ioctl_msg { uint32_t addr; uint64_t data; -} __attribute__((packed)) rshim_ioctl_msg; +} __attribute__((packed)); enum { - RSH_IOC_READ = _IOWR('R', 0, rshim_ioctl_msg), - RSH_IOC_WRITE = _IOWR('R', 1, rshim_ioctl_msg), + RSH_IOC_READ = _IOWR('R', 0, struct rshim_ioctl_msg), + RSH_IOC_WRITE = _IOWR('R', 1, struct rshim_ioctl_msg), }; #endif @@ -104,7 +104,7 @@ static int rshim_dev_read(int chan, int addr, uint64_t *value) #ifdef HAVE_SYS_IOCTL_H if (rc < 0 && errno == ENOSYS) { - rshim_ioctl_msg msg; + struct rshim_ioctl_msg msg; msg.addr = addr; msg.data = 0; @@ -126,7 +126,7 @@ static int rshim_dev_write(int chan, int addr, uint64_t value) #ifdef HAVE_SYS_IOCTL_H if (rc < 0 && errno == ENOSYS) { - rshim_ioctl_msg msg; + struct rshim_ioctl_msg msg; msg.addr = addr; msg.data = value; diff --git a/src/jtag/drivers/stlink_usb.c b/src/jtag/drivers/stlink_usb.c index 8cf3b0c..d77f28b 100644 --- a/src/jtag/drivers/stlink_usb.c +++ b/src/jtag/drivers/stlink_usb.c @@ -2754,7 +2754,7 @@ static int stlink_usb_read_mem32_noaddrinc(void *handle, uint8_t ap_num, uint32_ { struct stlink_usb_handle *h = handle; - assert(handle != NULL); + assert(handle); if (!(h->version.flags & STLINK_F_HAS_MEM_RD_NO_INC)) return ERROR_COMMAND_NOTFOUND; @@ -2796,7 +2796,7 @@ static int stlink_usb_write_mem32_noaddrinc(void *handle, uint8_t ap_num, uint32 { struct stlink_usb_handle *h = handle; - assert(handle != NULL); + assert(handle); if (!(h->version.flags & STLINK_F_HAS_MEM_WR_NO_INC)) return ERROR_COMMAND_NOTFOUND; @@ -3740,7 +3740,7 @@ static int stlink_open(struct hl_interface_param *param, enum stlink_mode mode, h->st_mode = mode; - for (unsigned i = 0; param->vid[i]; i++) { + for (unsigned int i = 0; param->vid[i]; i++) { LOG_DEBUG("transport: %d vid: 0x%04x pid: 0x%04x serial: %s", h->st_mode, param->vid[i], param->pid[i], adapter_get_required_serial() ? adapter_get_required_serial() : ""); @@ -3781,7 +3781,7 @@ static int stlink_open(struct hl_interface_param *param, enum stlink_mode mode, } /* initialize the debug hardware */ - err = stlink_usb_init_mode(h, param->connect_under_reset, param->initial_interface_speed); + err = stlink_usb_init_mode(h, param->connect_under_reset, adapter_get_speed_khz()); if (err != ERROR_OK) { LOG_ERROR("init mode failed (unable to connect to the target)"); @@ -3947,7 +3947,7 @@ static int stlink_usb_rw_misc_out(void *handle, uint32_t items, const uint8_t *b LOG_DEBUG_IO("%s(%" PRIu32 ")", __func__, items); - assert(handle != NULL); + assert(handle); if (!(h->version.flags & STLINK_F_HAS_RW_MISC)) return ERROR_COMMAND_NOTFOUND; @@ -3968,7 +3968,7 @@ static int stlink_usb_rw_misc_in(void *handle, uint32_t items, uint8_t *buffer) LOG_DEBUG_IO("%s(%" PRIu32 ")", __func__, items); - assert(handle != NULL); + assert(handle); if (!(h->version.flags & STLINK_F_HAS_RW_MISC)) return ERROR_COMMAND_NOTFOUND; @@ -5174,7 +5174,6 @@ static int stlink_dap_speed(int speed) return ERROR_JTAG_NOT_IMPLEMENTED; } - stlink_dap_param.initial_interface_speed = speed; stlink_speed(stlink_dap_handle, speed, false); return ERROR_OK; } diff --git a/src/jtag/drivers/sysfsgpio.c b/src/jtag/drivers/sysfsgpio.c index a5f5fd3..ccd3974 100644 --- a/src/jtag/drivers/sysfsgpio.c +++ b/src/jtag/drivers/sysfsgpio.c @@ -255,7 +255,7 @@ static int sysfsgpio_swd_write(int swclk, int swdio) * The sysfs value will read back either '0' or '1'. The trick here is to call * lseek to bypass buffering in the sysfs kernel driver. */ -static bb_value_t sysfsgpio_read(void) +static enum bb_value sysfsgpio_read(void) { char buf[1]; @@ -565,7 +565,7 @@ struct adapter_driver sysfsgpio_adapter_driver = { .swd_ops = &bitbang_swd, }; -static struct bitbang_interface sysfsgpio_bitbang = { +static const struct bitbang_interface sysfsgpio_bitbang = { .read = sysfsgpio_read, .write = sysfsgpio_write, .swdio_read = sysfsgpio_swdio_read, diff --git a/src/jtag/drivers/ulink.c b/src/jtag/drivers/ulink.c index 0fe8989..0a13bf6 100644 --- a/src/jtag/drivers/ulink.c +++ b/src/jtag/drivers/ulink.c @@ -212,7 +212,7 @@ static int ulink_append_test_cmd(struct ulink *device); static int ulink_calculate_delay(enum ulink_delay_type type, long f, int *delay); /* Interface between OpenULINK and OpenOCD */ -static void ulink_set_end_state(tap_state_t endstate); +static void ulink_set_end_state(enum tap_state endstate); static int ulink_queue_statemove(struct ulink *device); static int ulink_queue_scan(struct ulink *device, struct jtag_command *cmd); @@ -606,7 +606,7 @@ static void ulink_clear_queue(struct ulink *device) /* IN payload MUST be freed ONLY if no other commands use the * payload_in_start buffer */ - if (current->free_payload_in_start == true) { + if (current->free_payload_in_start) { free(current->payload_in_start); current->payload_in_start = NULL; current->payload_in = NULL; @@ -1393,7 +1393,7 @@ static long ulink_calculate_frequency(enum ulink_delay_type type, int delay) * * @param endstate the state the end state follower should be set to. */ -static void ulink_set_end_state(tap_state_t endstate) +static void ulink_set_end_state(enum tap_state endstate) { if (tap_is_state_stable(endstate)) tap_set_end_state(endstate); @@ -1701,15 +1701,17 @@ static int ulink_queue_reset(struct ulink *device, struct jtag_command *cmd) */ static int ulink_queue_pathmove(struct ulink *device, struct jtag_command *cmd) { - int ret, i, num_states, batch_size, state_count; - tap_state_t *path; + int ret, state_count; + enum tap_state *path; uint8_t tms_sequence; - num_states = cmd->cmd.pathmove->num_states; + unsigned int num_states = cmd->cmd.pathmove->num_states; path = cmd->cmd.pathmove->path; state_count = 0; while (num_states > 0) { + unsigned int batch_size; + tms_sequence = 0; /* Determine batch size */ @@ -1718,7 +1720,7 @@ static int ulink_queue_pathmove(struct ulink *device, struct jtag_command *cmd) else batch_size = num_states; - for (i = 0; i < batch_size; i++) { + for (unsigned int i = 0; i < batch_size; i++) { if (tap_state_transition(tap_get_state(), false) == path[state_count]) { /* Append '0' transition: clear bit 'i' in tms_sequence */ buf_set_u32(&tms_sequence, i, 1, 0x0); @@ -1774,14 +1776,13 @@ static int ulink_queue_sleep(struct ulink *device, struct jtag_command *cmd) static int ulink_queue_stableclocks(struct ulink *device, struct jtag_command *cmd) { int ret; - unsigned num_cycles; if (!tap_is_state_stable(tap_get_state())) { LOG_ERROR("JTAG_STABLECLOCKS: state not stable"); return ERROR_FAIL; } - num_cycles = cmd->cmd.stableclocks->num_cycles; + unsigned int num_cycles = cmd->cmd.stableclocks->num_cycles; /* TMS stays either high (Test Logic Reset state) or low (all other states) */ if (tap_get_state() == TAP_RESET) @@ -1860,7 +1861,7 @@ static int ulink_post_process_queue(struct ulink *device) /* Check if a corresponding OpenOCD command is stored for this * OpenULINK command */ - if ((current->needs_postprocessing == true) && (openocd_cmd)) { + if (current->needs_postprocessing && openocd_cmd) { switch (openocd_cmd->type) { case JTAG_SCAN: ret = ulink_post_process_scan(current); @@ -2130,7 +2131,7 @@ static int ulink_init(void) download_firmware = true; } - if (download_firmware == true) { + if (download_firmware) { LOG_INFO("Loading OpenULINK firmware. This is reversible by power-cycling" " ULINK device."); ret = ulink_load_firmware_and_renumerate(&ulink_handle, diff --git a/src/jtag/drivers/usb_blaster/ublast2_access_libusb.c b/src/jtag/drivers/usb_blaster/ublast2_access_libusb.c index de0d2d8..8f0ed96 100644 --- a/src/jtag/drivers/usb_blaster/ublast2_access_libusb.c +++ b/src/jtag/drivers/usb_blaster/ublast2_access_libusb.c @@ -30,7 +30,7 @@ #define SECTION_BUFFERSIZE 16384 static int ublast2_libusb_read(struct ublast_lowlevel *low, uint8_t *buf, - unsigned size, uint32_t *bytes_read) + unsigned int size, uint32_t *bytes_read) { int ret, tmp = 0; @@ -215,7 +215,7 @@ static int ublast2_libusb_init(struct ublast_lowlevel *low) const uint16_t vids_renum[] = { low->ublast_vid, 0 }; const uint16_t pids_renum[] = { low->ublast_pid, 0 }; - if (renumeration == false) { + if (!renumeration) { if (jtag_libusb_open(vids_renum, pids_renum, NULL, &low->libusb_dev, NULL) != ERROR_OK) { LOG_ERROR("Altera USB-Blaster II not found"); return ERROR_FAIL; diff --git a/src/jtag/drivers/usb_blaster/ublast_access.h b/src/jtag/drivers/usb_blaster/ublast_access.h index 3e138bd..e9c9268 100644 --- a/src/jtag/drivers/usb_blaster/ublast_access.h +++ b/src/jtag/drivers/usb_blaster/ublast_access.h @@ -30,7 +30,7 @@ struct ublast_lowlevel { int (*write)(struct ublast_lowlevel *low, uint8_t *buf, int size, uint32_t *bytes_written); - int (*read)(struct ublast_lowlevel *low, uint8_t *buf, unsigned size, + int (*read)(struct ublast_lowlevel *low, uint8_t *buf, unsigned int size, uint32_t *bytes_read); int (*open)(struct ublast_lowlevel *low); int (*close)(struct ublast_lowlevel *low); diff --git a/src/jtag/drivers/usb_blaster/ublast_access_ftdi.c b/src/jtag/drivers/usb_blaster/ublast_access_ftdi.c index eb312ef..9647f2b 100644 --- a/src/jtag/drivers/usb_blaster/ublast_access_ftdi.c +++ b/src/jtag/drivers/usb_blaster/ublast_access_ftdi.c @@ -28,7 +28,7 @@ static struct ftdi_context *ublast_getftdic(struct ublast_lowlevel *low) } static int ublast_ftdi_read(struct ublast_lowlevel *low, uint8_t *buf, - unsigned size, uint32_t *bytes_read) + unsigned int size, uint32_t *bytes_read) { int retval; int timeout = 100; diff --git a/src/jtag/drivers/usb_blaster/usb_blaster.c b/src/jtag/drivers/usb_blaster/usb_blaster.c index c84055c..1782cc4 100644 --- a/src/jtag/drivers/usb_blaster/usb_blaster.c +++ b/src/jtag/drivers/usb_blaster/usb_blaster.c @@ -158,7 +158,7 @@ static char *hexdump(uint8_t *buf, unsigned int size) return str; } -static int ublast_buf_read(uint8_t *buf, unsigned size, uint32_t *bytes_read) +static int ublast_buf_read(uint8_t *buf, unsigned int size, uint32_t *bytes_read) { int ret = info.drv->read(info.drv, buf, size, bytes_read); char *str = hexdump(buf, *bytes_read); @@ -474,11 +474,9 @@ static void ublast_tms(struct tms_command *cmd) */ static void ublast_path_move(struct pathmove_command *cmd) { - int i; - - LOG_DEBUG_IO("(num_states=%d, last_state=%d)", + LOG_DEBUG_IO("(num_states=%u, last_state=%d)", cmd->num_states, cmd->path[cmd->num_states - 1]); - for (i = 0; i < cmd->num_states; i++) { + for (unsigned int i = 0; i < cmd->num_states; i++) { if (tap_state_transition(tap_get_state(), false) == cmd->path[i]) ublast_clock_tms(0); if (tap_state_transition(tap_get_state(), true) == cmd->path[i]) @@ -496,7 +494,7 @@ static void ublast_path_move(struct pathmove_command *cmd) * Input the correct TMS sequence to the JTAG TAP so that we end up in the * target state. This assumes the current state (tap_get_state()) is correct. */ -static void ublast_state_move(tap_state_t state, int skip) +static void ublast_state_move(enum tap_state state, int skip) { uint8_t tms_scan; int tms_len; @@ -675,19 +673,19 @@ static void ublast_queue_tdi(uint8_t *bits, int nb_bits, enum scan_type scan) ublast_idle_clock(); } -static void ublast_runtest(int cycles, tap_state_t state) +static void ublast_runtest(unsigned int num_cycles, enum tap_state state) { - LOG_DEBUG_IO("%s(cycles=%i, end_state=%d)", __func__, cycles, state); + LOG_DEBUG_IO("%s(cycles=%u, end_state=%d)", __func__, num_cycles, state); ublast_state_move(TAP_IDLE, 0); - ublast_queue_tdi(NULL, cycles, SCAN_OUT); + ublast_queue_tdi(NULL, num_cycles, SCAN_OUT); ublast_state_move(state, 0); } -static void ublast_stableclocks(int cycles) +static void ublast_stableclocks(unsigned int num_cycles) { - LOG_DEBUG_IO("%s(cycles=%i)", __func__, cycles); - ublast_queue_tdi(NULL, cycles, SCAN_OUT); + LOG_DEBUG_IO("%s(cycles=%u)", __func__, num_cycles); + ublast_queue_tdi(NULL, num_cycles, SCAN_OUT); } /** diff --git a/src/jtag/drivers/usbprog.c b/src/jtag/drivers/usbprog.c index 2d666d0..24407f0 100644 --- a/src/jtag/drivers/usbprog.c +++ b/src/jtag/drivers/usbprog.c @@ -34,10 +34,10 @@ #define TCK_BIT 2 #define TMS_BIT 1 -static void usbprog_end_state(tap_state_t state); +static void usbprog_end_state(enum tap_state state); static void usbprog_state_move(void); static void usbprog_path_move(struct pathmove_command *cmd); -static void usbprog_runtest(int num_cycles); +static void usbprog_runtest(unsigned int num_cycles); static void usbprog_scan(bool ir_scan, enum scan_type type, uint8_t *buffer, int scan_size); #define UNKNOWN_COMMAND 0x00 @@ -101,7 +101,7 @@ static int usbprog_execute_queue(struct jtag_command *cmd_queue) usbprog_reset(cmd->cmd.reset->trst, cmd->cmd.reset->srst); break; case JTAG_RUNTEST: - LOG_DEBUG_IO("runtest %i cycles, end in %i", + LOG_DEBUG_IO("runtest %u cycles, end in %i", cmd->cmd.runtest->num_cycles, cmd->cmd.runtest->end_state); usbprog_end_state(cmd->cmd.runtest->end_state); @@ -113,7 +113,7 @@ static int usbprog_execute_queue(struct jtag_command *cmd_queue) usbprog_state_move(); break; case JTAG_PATHMOVE: - LOG_DEBUG_IO("pathmove: %i states, end in %i", + LOG_DEBUG_IO("pathmove: %u states, end in %i", cmd->cmd.pathmove->num_states, cmd->cmd.pathmove->path[cmd->cmd.pathmove->num_states - 1]); usbprog_path_move(cmd->cmd.pathmove); @@ -168,7 +168,7 @@ static int usbprog_quit(void) } /*************** jtag execute commands **********************/ -static void usbprog_end_state(tap_state_t state) +static void usbprog_end_state(enum tap_state state) { if (tap_is_state_stable(state)) tap_set_end_state(state); @@ -189,7 +189,7 @@ static void usbprog_state_move(void) static void usbprog_path_move(struct pathmove_command *cmd) { - int num_states = cmd->num_states; + unsigned int num_states = cmd->num_states; int state_count; /* There may be queued transitions, and before following a specified @@ -222,10 +222,8 @@ static void usbprog_path_move(struct pathmove_command *cmd) tap_set_end_state(tap_get_state()); } -static void usbprog_runtest(int num_cycles) +static void usbprog_runtest(unsigned int num_cycles) { - int i; - /* only do a state_move when we're not already in IDLE */ if (tap_get_state() != TAP_IDLE) { usbprog_end_state(TAP_IDLE); @@ -241,7 +239,7 @@ static void usbprog_runtest(int num_cycles) /* LOG_INFO("NUM CYCLES %i",num_cycles); */ } - for (i = 0; i < num_cycles; i++) { + for (unsigned int i = 0; i < num_cycles; i++) { usbprog_write(1, 0, 0); usbprog_write(0, 0, 0); } @@ -259,7 +257,7 @@ static void usbprog_runtest(int num_cycles) static void usbprog_scan(bool ir_scan, enum scan_type type, uint8_t *buffer, int scan_size) { - tap_state_t saved_end_state = tap_get_end_state(); + enum tap_state saved_end_state = tap_get_end_state(); if (ir_scan) usbprog_end_state(TAP_IRSHIFT); diff --git a/src/jtag/drivers/vdebug.c b/src/jtag/drivers/vdebug.c index f1fc453..fd1e6a7 100644 --- a/src/jtag/drivers/vdebug.c +++ b/src/jtag/drivers/vdebug.c @@ -252,7 +252,7 @@ static int vdebug_socket_open(char *server_addr, uint32_t port) #ifdef _WIN32 hsock = socket(AF_INET, SOCK_STREAM, IPPROTO_IP); - if (hsock == INVALID_SOCKET) + if (hsock < 0) rc = vdebug_socket_error(); #elif defined __CYGWIN__ /* SO_RCVLOWAT unsupported on CYGWIN */ @@ -931,11 +931,11 @@ static int vdebug_jtag_tms_seq(const uint8_t *tms, int num, uint8_t f_flush) static int vdebug_jtag_path_move(struct pathmove_command *cmd, uint8_t f_flush) { uint8_t tms[DIV_ROUND_UP(cmd->num_states, 8)]; - LOG_DEBUG_IO("path num states %d", cmd->num_states); + LOG_DEBUG_IO("path num states %u", cmd->num_states); memset(tms, 0, DIV_ROUND_UP(cmd->num_states, 8)); - for (uint8_t i = 0; i < cmd->num_states; i++) { + for (unsigned int i = 0; i < cmd->num_states; i++) { if (tap_state_transition(tap_get_state(), true) == cmd->path[i]) buf_set_u32(tms, i, 1, 1); tap_set_state(cmd->path[i]); @@ -944,11 +944,11 @@ static int vdebug_jtag_path_move(struct pathmove_command *cmd, uint8_t f_flush) return vdebug_jtag_tms_seq(tms, cmd->num_states, f_flush); } -static int vdebug_jtag_tlr(tap_state_t state, uint8_t f_flush) +static int vdebug_jtag_tlr(enum tap_state state, uint8_t f_flush) { int rc = ERROR_OK; - tap_state_t cur = tap_get_state(); + enum tap_state cur = tap_get_state(); uint8_t tms_pre = tap_get_tms_path(cur, state); uint8_t num_pre = tap_get_tms_path_len(cur, state); LOG_DEBUG_IO("tlr from %x to %x", cur, state); @@ -964,16 +964,16 @@ static int vdebug_jtag_scan(struct scan_command *cmd, uint8_t f_flush) { int rc = ERROR_OK; - tap_state_t cur = tap_get_state(); + enum tap_state cur = tap_get_state(); uint8_t state = cmd->ir_scan ? TAP_IRSHIFT : TAP_DRSHIFT; uint8_t tms_pre = tap_get_tms_path(cur, state); uint8_t num_pre = tap_get_tms_path_len(cur, state); uint8_t tms_post = tap_get_tms_path(state, cmd->end_state); uint8_t num_post = tap_get_tms_path_len(state, cmd->end_state); - int num_bits = jtag_scan_size(cmd); - LOG_DEBUG_IO("scan len:%d fields:%d ir/!dr:%d state cur:%x end:%x", + const unsigned int num_bits = jtag_scan_size(cmd); + LOG_DEBUG_IO("scan len:%u fields:%u ir/!dr:%d state cur:%x end:%x", num_bits, cmd->num_fields, cmd->ir_scan, cur, cmd->end_state); - for (int i = 0; i < cmd->num_fields; i++) { + for (unsigned int i = 0; i < cmd->num_fields; i++) { uint8_t cur_num_pre = i == 0 ? num_pre : 0; uint8_t cur_tms_pre = i == 0 ? tms_pre : 0; uint8_t cur_num_post = i == cmd->num_fields - 1 ? num_post : 0; @@ -992,24 +992,24 @@ static int vdebug_jtag_scan(struct scan_command *cmd, uint8_t f_flush) return rc; } -static int vdebug_jtag_runtest(int cycles, tap_state_t state, uint8_t f_flush) +static int vdebug_jtag_runtest(unsigned int num_cycles, enum tap_state state, uint8_t f_flush) { - tap_state_t cur = tap_get_state(); + enum tap_state cur = tap_get_state(); uint8_t tms_pre = tap_get_tms_path(cur, state); uint8_t num_pre = tap_get_tms_path_len(cur, state); - LOG_DEBUG_IO("idle len:%d state cur:%x end:%x", cycles, cur, state); - int rc = vdebug_jtag_shift_tap(vdc.hsocket, pbuf, num_pre, tms_pre, cycles, NULL, 0, 0, NULL, f_flush); + LOG_DEBUG_IO("idle len:%u state cur:%x end:%x", num_cycles, cur, state); + int rc = vdebug_jtag_shift_tap(vdc.hsocket, pbuf, num_pre, tms_pre, num_cycles, NULL, 0, 0, NULL, f_flush); if (cur != state) tap_set_state(state); return rc; } -static int vdebug_jtag_stableclocks(int num, uint8_t f_flush) +static int vdebug_jtag_stableclocks(unsigned int num_cycles, uint8_t f_flush) { - LOG_DEBUG("stab len:%d state cur:%x", num, tap_get_state()); + LOG_DEBUG("stab len:%u state cur:%x", num_cycles, tap_get_state()); - return vdebug_jtag_shift_tap(vdc.hsocket, pbuf, 0, 0, num, NULL, 0, 0, NULL, f_flush); + return vdebug_jtag_shift_tap(vdc.hsocket, pbuf, 0, 0, num_cycles, NULL, 0, 0, NULL, f_flush); } static int vdebug_sleep(int us) diff --git a/src/jtag/drivers/vsllink.c b/src/jtag/drivers/vsllink.c index 34525d5..c10ed13 100644 --- a/src/jtag/drivers/vsllink.c +++ b/src/jtag/drivers/vsllink.c @@ -41,12 +41,12 @@ static struct pending_scan_result pending_scan_results_buffer[MAX_PENDING_SCAN_RESULTS]; /* Queue command functions */ -static void vsllink_end_state(tap_state_t state); +static void vsllink_end_state(enum tap_state state); static void vsllink_state_move(void); -static void vsllink_path_move(int num_states, tap_state_t *path); +static void vsllink_path_move(unsigned int num_states, enum tap_state *path); static void vsllink_tms(int num_bits, const uint8_t *bits); -static void vsllink_runtest(int num_cycles); -static void vsllink_stableclocks(int num_cycles, int tms); +static void vsllink_runtest(unsigned int num_cycles); +static void vsllink_stableclocks(unsigned int num_cycles, int tms); static void vsllink_scan(bool ir_scan, enum scan_type type, uint8_t *buffer, int scan_size, struct scan_command *command); static int vsllink_reset(int trst, int srst); @@ -98,7 +98,7 @@ static int vsllink_execute_queue(struct jtag_command *cmd_queue) while (cmd) { switch (cmd->type) { case JTAG_RUNTEST: - LOG_DEBUG_IO("runtest %i cycles, end in %s", + LOG_DEBUG_IO("runtest %u cycles, end in %s", cmd->cmd.runtest->num_cycles, tap_state_name(cmd->cmd.runtest->end_state)); @@ -115,7 +115,7 @@ static int vsllink_execute_queue(struct jtag_command *cmd_queue) break; case JTAG_PATHMOVE: - LOG_DEBUG_IO("pathmove: %i states, end in %s", + LOG_DEBUG_IO("pathmove: %u states, end in %s", cmd->cmd.pathmove->num_states, tap_state_name(cmd->cmd.pathmove->path[cmd->cmd.pathmove->num_states - 1])); @@ -161,7 +161,7 @@ static int vsllink_execute_queue(struct jtag_command *cmd_queue) break; case JTAG_STABLECLOCKS: - LOG_DEBUG_IO("add %d clocks", + LOG_DEBUG_IO("add %u clocks", cmd->cmd.stableclocks->num_cycles); switch (tap_get_state()) { @@ -346,7 +346,7 @@ static int vsllink_init(void) /************************************************************************** * Queue command implementations */ -static void vsllink_end_state(tap_state_t state) +static void vsllink_end_state(enum tap_state state) { if (tap_is_state_stable(state)) tap_set_end_state(state); @@ -371,9 +371,9 @@ static void vsllink_state_move(void) tap_set_state(tap_get_end_state()); } -static void vsllink_path_move(int num_states, tap_state_t *path) +static void vsllink_path_move(unsigned int num_states, enum tap_state *path) { - for (int i = 0; i < num_states; i++) { + for (unsigned int i = 0; i < num_states; i++) { if (path[i] == tap_state_transition(tap_get_state(), false)) vsllink_tap_append_step(0, 0); else if (path[i] == tap_state_transition(tap_get_state(), true)) @@ -397,7 +397,7 @@ static void vsllink_tms(int num_bits, const uint8_t *bits) vsllink_tap_append_step((bits[i / 8] >> (i % 8)) & 1, 0); } -static void vsllink_stableclocks(int num_cycles, int tms) +static void vsllink_stableclocks(unsigned int num_cycles, int tms) { while (num_cycles > 0) { vsllink_tap_append_step(tms, 0); @@ -405,9 +405,9 @@ static void vsllink_stableclocks(int num_cycles, int tms) } } -static void vsllink_runtest(int num_cycles) +static void vsllink_runtest(unsigned int num_cycles) { - tap_state_t saved_end_state = tap_get_end_state(); + enum tap_state saved_end_state = tap_get_end_state(); if (tap_get_state() != TAP_IDLE) { /* enter IDLE state */ @@ -427,7 +427,7 @@ static void vsllink_runtest(int num_cycles) static void vsllink_scan(bool ir_scan, enum scan_type type, uint8_t *buffer, int scan_size, struct scan_command *command) { - tap_state_t saved_end_state; + enum tap_state saved_end_state; saved_end_state = tap_get_end_state(); diff --git a/src/jtag/drivers/xds110.c b/src/jtag/drivers/xds110.c index 11fbaaa..c843710 100644 --- a/src/jtag/drivers/xds110.c +++ b/src/jtag/drivers/xds110.c @@ -172,7 +172,7 @@ #define CMD_RUNTEST 3 #define CMD_STABLECLOCKS 4 -/* Array to convert from OpenOCD tap_state_t to XDS JTAG state */ +/* Array to convert from OpenOCD enum tap_state to XDS JTAG state */ static const uint32_t xds_jtag_state[] = { XDS_JTAG_STATE_EXIT2_DR, /* TAP_DREXIT2 = 0x0 */ XDS_JTAG_STATE_EXIT1_DR, /* TAP_DREXIT1 = 0x1 */ @@ -1669,7 +1669,6 @@ static void xds110_execute_tlr_reset(struct jtag_command *cmd) static void xds110_execute_pathmove(struct jtag_command *cmd) { - uint32_t i; uint32_t num_states; uint8_t *path; @@ -1685,7 +1684,7 @@ static void xds110_execute_pathmove(struct jtag_command *cmd) } /* Convert requested path states into XDS API states */ - for (i = 0; i < num_states; i++) + for (unsigned int i = 0; i < num_states; i++) path[i] = (uint8_t)xds_jtag_state[cmd->cmd.pathmove->path[i]]; if (xds110.firmware >= OCD_FIRMWARE_VERSION) { @@ -1704,7 +1703,6 @@ static void xds110_execute_pathmove(struct jtag_command *cmd) static void xds110_queue_scan(struct jtag_command *cmd) { - int i; uint32_t offset; uint32_t total_fields; uint32_t total_bits; @@ -1715,7 +1713,7 @@ static void xds110_queue_scan(struct jtag_command *cmd) /* Calculate the total number of bits to scan */ total_bits = 0; total_fields = 0; - for (i = 0; i < cmd->cmd.scan->num_fields; i++) { + for (unsigned int i = 0; i < cmd->cmd.scan->num_fields; i++) { total_fields++; total_bits += (uint32_t)cmd->cmd.scan->fields[i].num_bits; } @@ -1756,7 +1754,7 @@ static void xds110_queue_scan(struct jtag_command *cmd) buffer = &xds110.txn_requests[xds110.txn_request_size]; /* Clear data out buffer to default value of all zeros */ memset((void *)buffer, 0x00, total_bytes); - for (i = 0; i < cmd->cmd.scan->num_fields; i++) { + for (unsigned int i = 0; i < cmd->cmd.scan->num_fields; i++) { if (cmd->cmd.scan->fields[i].out_value) { /* Copy over data to scan out into request buffer */ bit_copy(buffer, offset, cmd->cmd.scan->fields[i].out_value, 0, @@ -1775,7 +1773,7 @@ static void xds110_queue_scan(struct jtag_command *cmd) static void xds110_queue_runtest(struct jtag_command *cmd) { - uint32_t clocks = (uint32_t)cmd->cmd.stableclocks->num_cycles; + uint32_t clocks = cmd->cmd.stableclocks->num_cycles; uint8_t end_state = (uint8_t)xds_jtag_state[cmd->cmd.runtest->end_state]; /* Check if new request would be too large to fit */ @@ -1794,7 +1792,7 @@ static void xds110_queue_runtest(struct jtag_command *cmd) static void xds110_queue_stableclocks(struct jtag_command *cmd) { - uint32_t clocks = (uint32_t)cmd->cmd.stableclocks->num_cycles; + uint32_t clocks = cmd->cmd.stableclocks->num_cycles; /* Check if new request would be too large to fit */ if ((xds110.txn_request_size + 1 + sizeof(clocks) + 1) > MAX_DATA_BLOCK) @@ -1889,7 +1887,7 @@ static int xds110_speed(int speed) } else { - const double XDS110_TCK_PULSE_INCREMENT = 66.0; + const double xds110_tck_pulse_increment = 66.0; freq_to_use = speed * 1000; /* Hz */ delay_count = 0; @@ -1910,7 +1908,7 @@ static int xds110_speed(int speed) double current_value = max_freq_pulse_duration; while (current_value < freq_to_pulse_width_in_ns) { - current_value += XDS110_TCK_PULSE_INCREMENT; + current_value += xds110_tck_pulse_increment; ++delay_count; } @@ -1921,9 +1919,9 @@ static int xds110_speed(int speed) if (delay_count) { double diff_freq_1 = freq_to_use - (one_giga / (max_freq_pulse_duration + - (XDS110_TCK_PULSE_INCREMENT * delay_count))); + (xds110_tck_pulse_increment * delay_count))); double diff_freq_2 = (one_giga / (max_freq_pulse_duration + - (XDS110_TCK_PULSE_INCREMENT * (delay_count - 1)))) - + (xds110_tck_pulse_increment * (delay_count - 1)))) - freq_to_use; /* One less count value yields a better match */ diff --git a/src/jtag/drivers/xlnx-pcie-xvc.c b/src/jtag/drivers/xlnx-pcie-xvc.c index 233ade3..37c6777 100644 --- a/src/jtag/drivers/xlnx-pcie-xvc.c +++ b/src/jtag/drivers/xlnx-pcie-xvc.c @@ -43,7 +43,7 @@ struct xlnx_pcie_xvc { int fd; - unsigned offset; + unsigned int offset; char *device; }; @@ -128,7 +128,7 @@ static int xlnx_pcie_xvc_execute_stableclocks(struct jtag_command *cmd) size_t write; int err; - LOG_DEBUG("stableclocks %i cycles", cmd->cmd.runtest->num_cycles); + LOG_DEBUG("stableclocks %u cycles", cmd->cmd.runtest->num_cycles); while (left) { write = MIN(XLNX_XVC_MAX_BITS, left); @@ -167,11 +167,11 @@ static int xlnx_pcie_xvc_execute_runtest(struct jtag_command *cmd) { int err = ERROR_OK; - LOG_DEBUG("runtest %i cycles, end in %i", + LOG_DEBUG("runtest %u cycles, end in %i", cmd->cmd.runtest->num_cycles, cmd->cmd.runtest->end_state); - tap_state_t tmp_state = tap_get_end_state(); + enum tap_state tmp_state = tap_get_end_state(); if (tap_get_state() != TAP_IDLE) { tap_set_end_state(TAP_IDLE); @@ -200,16 +200,15 @@ static int xlnx_pcie_xvc_execute_runtest(struct jtag_command *cmd) static int xlnx_pcie_xvc_execute_pathmove(struct jtag_command *cmd) { - size_t num_states = cmd->cmd.pathmove->num_states; - tap_state_t *path = cmd->cmd.pathmove->path; + unsigned int num_states = cmd->cmd.pathmove->num_states; + enum tap_state *path = cmd->cmd.pathmove->path; int err = ERROR_OK; - size_t i; - LOG_DEBUG("pathmove: %i states, end in %i", + LOG_DEBUG("pathmove: %u states, end in %i", cmd->cmd.pathmove->num_states, cmd->cmd.pathmove->path[cmd->cmd.pathmove->num_states - 1]); - for (i = 0; i < num_states; i++) { + for (unsigned int i = 0; i < num_states; i++) { if (path[i] == tap_state_transition(tap_get_state(), false)) { err = xlnx_pcie_xvc_transact(1, 1, 0, NULL); } else if (path[i] == tap_state_transition(tap_get_state(), true)) { @@ -233,7 +232,7 @@ static int xlnx_pcie_xvc_execute_pathmove(struct jtag_command *cmd) static int xlnx_pcie_xvc_execute_scan(struct jtag_command *cmd) { enum scan_type type = jtag_scan_type(cmd->cmd.scan); - tap_state_t saved_end_state = cmd->cmd.scan->end_state; + enum tap_state saved_end_state = cmd->cmd.scan->end_state; bool ir_scan = cmd->cmd.scan->ir_scan; uint32_t tdi, tms, tdo; uint8_t *buf, *rd_ptr; diff --git a/src/jtag/hla/hla_interface.c b/src/jtag/hla/hla_interface.c index 6ac6801..96862b0 100644 --- a/src/jtag/hla/hla_interface.c +++ b/src/jtag/hla/hla_interface.c @@ -30,7 +30,6 @@ static struct hl_interface hl_if = { .pid = { 0 }, .transport = HL_TRANSPORT_UNKNOWN, .connect_under_reset = false, - .initial_interface_speed = -1, .use_stlink_tcp = false, .stlink_tcp_port = 7184, }, @@ -76,7 +75,7 @@ int hl_interface_init_target(struct target *t) if (res != ERROR_OK) return res; - unsigned ii, limit = t->tap->expected_ids_cnt; + unsigned int ii, limit = t->tap->expected_ids_cnt; int found = 0; for (ii = 0; ii < limit; ii++) { @@ -165,11 +164,8 @@ static int hl_interface_speed(int speed) if (!hl_if.layout->api->speed) return ERROR_OK; - if (!hl_if.handle) { - /* pass speed as initial param as interface not open yet */ - hl_if.param.initial_interface_speed = speed; + if (!hl_if.handle) return ERROR_OK; - } hl_if.layout->api->speed(hl_if.handle, speed, false); @@ -264,7 +260,7 @@ COMMAND_HANDLER(hl_interface_handle_vid_pid_command) return ERROR_COMMAND_SYNTAX_ERROR; } - unsigned i; + unsigned int i; for (i = 0; i < CMD_ARGC; i += 2) { COMMAND_PARSE_NUMBER(u16, CMD_ARGV[i], hl_if.param.vid[i / 2]); COMMAND_PARSE_NUMBER(u16, CMD_ARGV[i + 1], hl_if.param.pid[i / 2]); @@ -319,37 +315,37 @@ COMMAND_HANDLER(interface_handle_hla_command) return ERROR_OK; } -static const struct command_registration hl_interface_command_handlers[] = { +static const struct command_registration hl_interface_subcommand_handlers[] = { { - .name = "hla_device_desc", + .name = "device_desc", .handler = &hl_interface_handle_device_desc_command, .mode = COMMAND_CONFIG, .help = "set the device description of the adapter", .usage = "description_string", }, { - .name = "hla_layout", + .name = "layout", .handler = &hl_interface_handle_layout_command, .mode = COMMAND_CONFIG, .help = "set the layout of the adapter", .usage = "layout_name", }, { - .name = "hla_vid_pid", + .name = "vid_pid", .handler = &hl_interface_handle_vid_pid_command, .mode = COMMAND_CONFIG, .help = "the vendor and product ID of the adapter", .usage = "(vid pid)*", }, { - .name = "hla_stlink_backend", + .name = "stlink_backend", .handler = &hl_interface_handle_stlink_backend_command, .mode = COMMAND_CONFIG, .help = "select which ST-Link backend to use", .usage = "usb | tcp [port]", }, - { - .name = "hla_command", + { + .name = "command", .handler = &interface_handle_hla_command, .mode = COMMAND_EXEC, .help = "execute a custom adapter-specific command", @@ -358,6 +354,17 @@ static const struct command_registration hl_interface_command_handlers[] = { COMMAND_REGISTRATION_DONE }; +static const struct command_registration hl_interface_command_handlers[] = { + { + .name = "hla", + .mode = COMMAND_ANY, + .help = "perform hla management", + .chain = hl_interface_subcommand_handlers, + .usage = "", + }, + COMMAND_REGISTRATION_DONE +}; + struct adapter_driver hl_adapter_driver = { .name = "hla", .transports = hl_transports, diff --git a/src/jtag/hla/hla_interface.h b/src/jtag/hla/hla_interface.h index c95638b..f1550d9 100644 --- a/src/jtag/hla/hla_interface.h +++ b/src/jtag/hla/hla_interface.h @@ -31,8 +31,6 @@ struct hl_interface_param { enum hl_transports transport; /** */ bool connect_under_reset; - /** Initial interface clock clock speed */ - int initial_interface_speed; /** */ bool use_stlink_tcp; /** */ diff --git a/src/jtag/interface.c b/src/jtag/interface.c index 1230bb1..92c88ca 100644 --- a/src/jtag/interface.c +++ b/src/jtag/interface.c @@ -26,15 +26,15 @@ * @see tap_set_state() and tap_get_state() accessors. * Actual name is not important since accessors hide it. */ -static tap_state_t state_follower = TAP_RESET; +static enum tap_state state_follower = TAP_RESET; -void tap_set_state_impl(tap_state_t new_state) +void tap_set_state_impl(enum tap_state new_state) { /* this is the state we think the TAPs are in now, was cur_state */ state_follower = new_state; } -tap_state_t tap_get_state(void) +enum tap_state tap_get_state(void) { return state_follower; } @@ -43,9 +43,9 @@ tap_state_t tap_get_state(void) * @see tap_set_end_state() and tap_get_end_state() accessors. * Actual name is not important because accessors hide it. */ -static tap_state_t end_state_follower = TAP_RESET; +static enum tap_state end_state_follower = TAP_RESET; -void tap_set_end_state(tap_state_t new_end_state) +void tap_set_end_state(enum tap_state new_end_state) { /* this is the state we think the TAPs will be in at completion of the * current TAP operation, was end_state @@ -53,12 +53,12 @@ void tap_set_end_state(tap_state_t new_end_state) end_state_follower = new_end_state; } -tap_state_t tap_get_end_state(void) +enum tap_state tap_get_end_state(void) { return end_state_follower; } -int tap_move_ndx(tap_state_t astate) +int tap_move_ndx(enum tap_state astate) { /* given a stable state, return the index into the tms_seqs[] * array within tap_get_tms_path() @@ -187,17 +187,17 @@ typedef const struct tms_sequences tms_table[6][6]; static tms_table *tms_seqs = &short_tms_seqs; -int tap_get_tms_path(tap_state_t from, tap_state_t to) +int tap_get_tms_path(enum tap_state from, enum tap_state to) { return (*tms_seqs)[tap_move_ndx(from)][tap_move_ndx(to)].bits; } -int tap_get_tms_path_len(tap_state_t from, tap_state_t to) +int tap_get_tms_path_len(enum tap_state from, enum tap_state to) { return (*tms_seqs)[tap_move_ndx(from)][tap_move_ndx(to)].bit_count; } -bool tap_is_state_stable(tap_state_t astate) +bool tap_is_state_stable(enum tap_state astate) { bool is_stable; @@ -220,9 +220,9 @@ bool tap_is_state_stable(tap_state_t astate) return is_stable; } -tap_state_t tap_state_transition(tap_state_t cur_state, bool tms) +enum tap_state tap_state_transition(enum tap_state cur_state, bool tms) { - tap_state_t new_state; + enum tap_state new_state; /* A switch is used because it is symbol dependent and not value dependent * like an array. Also it can check for out of range conditions. @@ -341,9 +341,9 @@ static const struct name_mapping { { TAP_IDLE, "IDLE", }, }; -const char *tap_state_name(tap_state_t state) +const char *tap_state_name(enum tap_state state) { - unsigned i; + unsigned int i; for (i = 0; i < ARRAY_SIZE(tap_name_mapping); i++) { if (tap_name_mapping[i].symbol == state) @@ -352,9 +352,9 @@ const char *tap_state_name(tap_state_t state) return "???"; } -tap_state_t tap_state_by_name(const char *name) +enum tap_state tap_state_by_name(const char *name) { - unsigned i; + unsigned int i; for (i = 0; i < ARRAY_SIZE(tap_name_mapping); i++) { /* be nice to the human */ @@ -371,20 +371,20 @@ tap_state_t tap_state_by_name(const char *name) LOG_DEBUG_IO("TAP/SM: %9s -> %5s\tTMS: %s\tTDI: %s", \ tap_state_name(a), tap_state_name(b), astr, bstr) -tap_state_t jtag_debug_state_machine_(const void *tms_buf, const void *tdi_buf, - unsigned int tap_bits, tap_state_t next_state) +enum tap_state jtag_debug_state_machine_(const void *tms_buf, const void *tdi_buf, + unsigned int tap_bits, enum tap_state next_state) { const uint8_t *tms_buffer; const uint8_t *tdi_buffer; - unsigned tap_bytes; - unsigned cur_byte; - unsigned cur_bit; + unsigned int tap_bytes; + unsigned int cur_byte; + unsigned int cur_bit; - unsigned tap_out_bits; + unsigned int tap_out_bits; char tms_str[33]; char tdi_str[33]; - tap_state_t last_state; + enum tap_state last_state; /* set startstate (and possibly last, if tap_bits == 0) */ last_state = next_state; @@ -400,7 +400,7 @@ tap_state_t jtag_debug_state_machine_(const void *tms_buf, const void *tdi_buf, for (cur_byte = 0; cur_byte < tap_bytes; cur_byte++) { for (cur_bit = 0; cur_bit < 8; cur_bit++) { /* make sure we do not run off the end of the buffers */ - unsigned tap_bit = cur_byte * 8 + cur_bit; + unsigned int tap_bit = cur_byte * 8 + cur_bit; if (tap_bit == tap_bits) break; diff --git a/src/jtag/interface.h b/src/jtag/interface.h index 28c1458..b2d7123 100644 --- a/src/jtag/interface.h +++ b/src/jtag/interface.h @@ -28,7 +28,7 @@ /** implementation of wrapper function tap_set_state() */ -void tap_set_state_impl(tap_state_t new_state); +void tap_set_state_impl(enum tap_state new_state); /** * This function sets the state of a "state follower" which tracks the @@ -55,9 +55,9 @@ void tap_set_state_impl(tap_state_t new_state); /** * This function gets the state of the "state follower" which tracks the * state of the TAPs connected to the cable. @see tap_set_state @return - * tap_state_t The state the TAPs are in now. + * enum tap_state The state the TAPs are in now. */ -tap_state_t tap_get_state(void); +enum tap_state tap_get_state(void); /** * This function sets the state of an "end state follower" which tracks @@ -70,13 +70,13 @@ tap_state_t tap_get_state(void); * @param new_end_state The state the TAPs should enter at completion of * a pending TAP operation. */ -void tap_set_end_state(tap_state_t new_end_state); +void tap_set_end_state(enum tap_state new_end_state); /** * For more information, @see tap_set_end_state - * @return tap_state_t - The state the TAPs should be in at completion of the current TAP operation. + * @return enum tap_state - The state the TAPs should be in at completion of the current TAP operation. */ -tap_state_t tap_get_end_state(void); +enum tap_state tap_get_end_state(void); /** * This function provides a "bit sequence" indicating what has to be @@ -91,7 +91,7 @@ tap_state_t tap_get_end_state(void); * @return int The required TMS bit sequence, with the first bit in the * sequence at bit 0. */ -int tap_get_tms_path(tap_state_t from, tap_state_t to); +int tap_get_tms_path(enum tap_state from, enum tap_state to); /** * Function int tap_get_tms_path_len @@ -109,7 +109,7 @@ int tap_get_tms_path(tap_state_t from, tap_state_t to); * @param to is the resultant or final state * @return int - the total number of bits in a transition. */ -int tap_get_tms_path_len(tap_state_t from, tap_state_t to); +int tap_get_tms_path_len(enum tap_state from, enum tap_state to); /** @@ -125,30 +125,30 @@ int tap_get_tms_path_len(tap_state_t from, tap_state_t to); * and terminate. * @return int - the array (or sequence) index as described above */ -int tap_move_ndx(tap_state_t astate); +int tap_move_ndx(enum tap_state astate); /** * Function tap_is_state_stable * returns true if the \a astate is stable. */ -bool tap_is_state_stable(tap_state_t astate); +bool tap_is_state_stable(enum tap_state astate); /** * Function tap_state_transition * takes a current TAP state and returns the next state according to the tms value. * @param current_state is the state of a TAP currently. * @param tms is either zero or non-zero, just like a real TMS line in a jtag interface. - * @return tap_state_t - the next state a TAP would enter. + * @return enum tap_state - the next state a TAP would enter. */ -tap_state_t tap_state_transition(tap_state_t current_state, bool tms); +enum tap_state tap_state_transition(enum tap_state current_state, bool tms); /** Allow switching between old and new TMS tables. @see tap_get_tms_path */ void tap_use_new_tms_table(bool use_new); /** @returns True if new TMS table is active; false otherwise. */ bool tap_uses_new_tms_table(void); -tap_state_t jtag_debug_state_machine_(const void *tms_buf, const void *tdi_buf, - unsigned int tap_len, tap_state_t start_tap_state); +enum tap_state jtag_debug_state_machine_(const void *tms_buf, const void *tdi_buf, + unsigned int tap_len, enum tap_state start_tap_state); /** * @brief Prints verbose TAP state transitions for the given TMS/TDI buffers. @@ -158,8 +158,8 @@ tap_state_t jtag_debug_state_machine_(const void *tms_buf, const void *tdi_buf, * @param start_tap_state must specify the current TAP state. * @returns the final TAP state; pass as @a start_tap_state in following call. */ -static inline tap_state_t jtag_debug_state_machine(const void *tms_buf, - const void *tdi_buf, unsigned tap_len, tap_state_t start_tap_state) +static inline enum tap_state jtag_debug_state_machine(const void *tms_buf, + const void *tdi_buf, unsigned int tap_len, enum tap_state start_tap_state) { if (LOG_LEVEL_IS(LOG_LVL_DEBUG_IO)) return jtag_debug_state_machine_(tms_buf, tdi_buf, tap_len, start_tap_state); @@ -183,7 +183,7 @@ struct jtag_interface { /** * Bit vector listing capabilities exposed by this driver. */ - unsigned supported; + unsigned int supported; #define DEBUG_CAP_TMS_SEQ (1 << 0) /** @@ -386,6 +386,7 @@ extern struct adapter_driver jtag_dpi_adapter_driver; extern struct adapter_driver jtag_vpi_adapter_driver; extern struct adapter_driver kitprog_adapter_driver; extern struct adapter_driver linuxgpiod_adapter_driver; +extern struct adapter_driver linuxspidev_adapter_driver; extern struct adapter_driver opendous_adapter_driver; extern struct adapter_driver openjtag_adapter_driver; extern struct adapter_driver osbdm_adapter_driver; diff --git a/src/jtag/interfaces.c b/src/jtag/interfaces.c index c24ead8..e49bd9e 100644 --- a/src/jtag/interfaces.c +++ b/src/jtag/interfaces.c @@ -102,7 +102,7 @@ struct adapter_driver *adapter_drivers[] = { #if BUILD_ARMJTAGEW == 1 &armjtagew_adapter_driver, #endif -#if BUILD_BUSPIRATE == 1 +#if BUILD_BUS_PIRATE == 1 &buspirate_adapter_driver, #endif #if BUILD_REMOTE_BITBANG == 1 @@ -123,6 +123,9 @@ struct adapter_driver *adapter_drivers[] = { #if BUILD_LINUXGPIOD == 1 &linuxgpiod_adapter_driver, #endif +#if BUILD_LINUXSPIDEV == 1 + &linuxspidev_adapter_driver, +#endif #if BUILD_XLNX_PCIE_XVC == 1 &xlnx_pcie_xvc_adapter_driver, #endif diff --git a/src/jtag/jtag.h b/src/jtag/jtag.h index 470ae18..81fcc7c 100644 --- a/src/jtag/jtag.h +++ b/src/jtag/jtag.h @@ -34,7 +34,7 @@ * Fix those drivers to map as appropriate ... then pick some * sane set of numbers here (where 0/uninitialized == INVALID). */ -typedef enum tap_state { +enum tap_state { TAP_INVALID = -1, /* Proper ARM recommended numbers */ @@ -54,7 +54,7 @@ typedef enum tap_state { TAP_IRUPDATE = 0xd, TAP_IRCAPTURE = 0xe, TAP_RESET = 0x0f, -} tap_state_t; +}; /** * Defines arguments for reset functions @@ -68,13 +68,13 @@ typedef enum tap_state { * Function tap_state_name * Returns a string suitable for display representing the JTAG tap_state */ -const char *tap_state_name(tap_state_t state); +const char *tap_state_name(enum tap_state state); /** Provides user-friendly name lookup of TAP states. */ -tap_state_t tap_state_by_name(const char *name); +enum tap_state tap_state_by_name(const char *name); /** The current TAP state of the pending JTAG command queue. */ -extern tap_state_t cmd_queue_cur_state; +extern enum tap_state cmd_queue_cur_state; /** * This structure defines a single scan field in the scan. It provides @@ -86,7 +86,7 @@ extern tap_state_t cmd_queue_cur_state; */ struct scan_field { /** The number of bits this field specifies */ - int num_bits; + unsigned int num_bits; /** A pointer to value to be scanned into the device */ const uint8_t *out_value; /** A pointer to a 32-bit memory location for data scanned out */ @@ -102,12 +102,12 @@ struct jtag_tap { char *chip; char *tapname; char *dotted_name; - int abs_chain_position; + unsigned int abs_chain_position; /** Is this TAP disabled after JTAG reset? */ bool disabled_after_reset; /** Is this TAP currently enabled? */ bool enabled; - int ir_length; /**< size of instruction register */ + unsigned int ir_length; /**< size of instruction register */ uint32_t ir_capture_value; uint8_t *expected; /**< Capture-IR expected value */ uint32_t ir_capture_mask; @@ -150,10 +150,10 @@ struct jtag_tap *jtag_all_taps(void); const char *jtag_tap_name(const struct jtag_tap *tap); struct jtag_tap *jtag_tap_by_string(const char *dotted_name); struct jtag_tap *jtag_tap_by_jim_obj(Jim_Interp *interp, Jim_Obj *obj); -struct jtag_tap *jtag_tap_by_position(unsigned abs_position); +struct jtag_tap *jtag_tap_by_position(unsigned int abs_position); +/* FIXME: "jtag_tap_next_enabled()" should accept a const pointer. */ struct jtag_tap *jtag_tap_next_enabled(struct jtag_tap *p); -unsigned jtag_tap_count_enabled(void); -unsigned jtag_tap_count(void); +unsigned int jtag_tap_count_enabled(void); /* * - TRST_ASSERTED triggers two sets of callbacks, after operations to @@ -229,17 +229,17 @@ enum reset_types { enum reset_types jtag_get_reset_config(void); void jtag_set_reset_config(enum reset_types type); -void jtag_set_nsrst_delay(unsigned delay); -unsigned jtag_get_nsrst_delay(void); +void jtag_set_nsrst_delay(unsigned int delay); +unsigned int jtag_get_nsrst_delay(void); -void jtag_set_ntrst_delay(unsigned delay); -unsigned jtag_get_ntrst_delay(void); +void jtag_set_ntrst_delay(unsigned int delay); +unsigned int jtag_get_ntrst_delay(void); -void jtag_set_nsrst_assert_width(unsigned delay); -unsigned jtag_get_nsrst_assert_width(void); +void jtag_set_nsrst_assert_width(unsigned int delay); +unsigned int jtag_get_nsrst_assert_width(void); -void jtag_set_ntrst_assert_width(unsigned delay); -unsigned jtag_get_ntrst_assert_width(void); +void jtag_set_ntrst_assert_width(unsigned int delay); +unsigned int jtag_get_ntrst_assert_width(void); /** @returns The current state of TRST. */ int jtag_get_trst(void); @@ -296,20 +296,20 @@ int jtag_init_inner(struct command_context *cmd_ctx); * */ void jtag_add_ir_scan(struct jtag_tap *tap, - struct scan_field *fields, tap_state_t endstate); + struct scan_field *fields, enum tap_state endstate); /** * The same as jtag_add_ir_scan except no verification is performed out * the output values. */ void jtag_add_ir_scan_noverify(struct jtag_tap *tap, - const struct scan_field *fields, tap_state_t state); + const struct scan_field *fields, enum tap_state state); /** * Scan out the bits in ir scan mode. * * If in_bits == NULL, discard incoming bits. */ void jtag_add_plain_ir_scan(int num_bits, const uint8_t *out_bits, uint8_t *in_bits, - tap_state_t endstate); + enum tap_state endstate); /** * Generate a DR SCAN using the fields passed to the function. @@ -318,17 +318,17 @@ void jtag_add_plain_ir_scan(int num_bits, const uint8_t *out_bits, uint8_t *in_b * 1-bit field. The bypass status of TAPs is set by jtag_add_ir_scan(). */ void jtag_add_dr_scan(struct jtag_tap *tap, int num_fields, - const struct scan_field *fields, tap_state_t endstate); + const struct scan_field *fields, enum tap_state endstate); /** A version of jtag_add_dr_scan() that uses the check_value/mask fields */ void jtag_add_dr_scan_check(struct jtag_tap *tap, int num_fields, - struct scan_field *fields, tap_state_t endstate); + struct scan_field *fields, enum tap_state endstate); /** * Scan out the bits in ir scan mode. * * If in_bits == NULL, discard incoming bits. */ void jtag_add_plain_dr_scan(int num_bits, - const uint8_t *out_bits, uint8_t *in_bits, tap_state_t endstate); + const uint8_t *out_bits, uint8_t *in_bits, enum tap_state endstate); /** * Defines the type of data passed to the jtag_callback_t interface. @@ -436,7 +436,7 @@ void jtag_add_tlr(void); * - ERROR_JTAG_TRANSITION_INVALID -- The path includes invalid * state transitions. */ -void jtag_add_pathmove(int num_states, const tap_state_t *path); +void jtag_add_pathmove(unsigned int num_states, const enum tap_state *path); /** * jtag_add_statemove() moves from the current state to @a goal_state. @@ -447,7 +447,7 @@ void jtag_add_pathmove(int num_states, const tap_state_t *path); * Moves from the current state to the goal \a state. * Both states must be stable. */ -int jtag_add_statemove(tap_state_t goal_state); +int jtag_add_statemove(enum tap_state goal_state); /** * Goes to TAP_IDLE (if we're not already there), cycle @@ -459,7 +459,7 @@ int jtag_add_statemove(tap_state_t goal_state); * via TAP_IDLE. * @param endstate The final state. */ -void jtag_add_runtest(int num_cycles, tap_state_t endstate); +void jtag_add_runtest(unsigned int num_cycles, enum tap_state endstate); /** * A reset of the TAP state machine can be requested. @@ -488,14 +488,14 @@ void jtag_add_reset(int req_tlr_or_trst, int srst); void jtag_add_sleep(uint32_t us); -int jtag_add_tms_seq(unsigned nbits, const uint8_t *seq, enum tap_state t); +int jtag_add_tms_seq(unsigned int nbits, const uint8_t *seq, enum tap_state t); /** * Function jtag_add_clocks * first checks that the state in which the clocks are to be issued is * stable, then queues up num_cycles clocks for transmission. */ -void jtag_add_clocks(int num_cycles); +void jtag_add_clocks(unsigned int num_cycles); /** * For software FIFO implementations, the queued commands can be executed @@ -523,7 +523,7 @@ int jtag_execute_queue(void); void jtag_execute_queue_noclear(void); /** @returns the number of times the scan queue has been flushed */ -int jtag_get_flush_queue_count(void); +unsigned int jtag_get_flush_queue_count(void); /** Report Tcl event to all TAPs */ void jtag_notify_event(enum jtag_event); @@ -568,11 +568,6 @@ void jtag_sleep(uint32_t us); * called with a non-zero error code. */ void jtag_set_error(int error); -/** - * Resets jtag_error to ERROR_OK, returning its previous value. - * @returns The previous value of @c jtag_error. - */ -int jtag_error_clear(void); /** * Return true if it's safe for a background polling task to access the diff --git a/src/jtag/minidriver.h b/src/jtag/minidriver.h index a40cffa..4b61bf1 100644 --- a/src/jtag/minidriver.h +++ b/src/jtag/minidriver.h @@ -38,23 +38,23 @@ int interface_jtag_add_ir_scan(struct jtag_tap *active, const struct scan_field *fields, - tap_state_t endstate); + enum tap_state endstate); int interface_jtag_add_plain_ir_scan( int num_bits, const uint8_t *out_bits, uint8_t *in_bits, - tap_state_t endstate); + enum tap_state endstate); int interface_jtag_add_dr_scan(struct jtag_tap *active, int num_fields, const struct scan_field *fields, - tap_state_t endstate); + enum tap_state endstate); int interface_jtag_add_plain_dr_scan( int num_bits, const uint8_t *out_bits, uint8_t *in_bits, - tap_state_t endstate); + enum tap_state endstate); int interface_jtag_add_tlr(void); -int interface_jtag_add_pathmove(int num_states, const tap_state_t *path); -int interface_jtag_add_runtest(int num_cycles, tap_state_t endstate); +int interface_jtag_add_pathmove(unsigned int num_states, const enum tap_state *path); +int interface_jtag_add_runtest(unsigned int num_cycles, enum tap_state endstate); -int interface_add_tms_seq(unsigned num_bits, +int interface_add_tms_seq(unsigned int num_bits, const uint8_t *bits, enum tap_state state); /** @@ -67,7 +67,7 @@ int interface_add_tms_seq(unsigned num_bits, */ int interface_jtag_add_reset(int trst, int srst); int interface_jtag_add_sleep(uint32_t us); -int interface_jtag_add_clocks(int num_cycles); +int interface_jtag_add_clocks(unsigned int num_cycles); int interface_jtag_execute_queue(void); /** diff --git a/src/jtag/startup.tcl b/src/jtag/startup.tcl index 41db38e..2d8ebf0 100644 --- a/src/jtag/startup.tcl +++ b/src/jtag/startup.tcl @@ -1126,6 +1126,36 @@ proc "cmsis_dap_usb" {args} { eval cmsis-dap usb $args } +lappend _telnet_autocomplete_skip "hla_layout" +proc "hla_layout" {layout} { + echo "DEPRECATED! use 'hla layout', not 'hla_layout'" + eval hla layout $layout +} + +lappend _telnet_autocomplete_skip "hla_device_desc" +proc "hla_device_desc" {desc} { + echo "DEPRECATED! use 'hla device_desc', not 'hla_device_desc'" + eval hla device_desc $desc +} + +lappend _telnet_autocomplete_skip "hla_vid_pid" +proc "hla_vid_pid" {args} { + echo "DEPRECATED! use 'hla vid_pid', not 'hla_vid_pid'" + eval hla vid_pid $args +} + +lappend _telnet_autocomplete_skip "hla_command" +proc "hla_command" {command} { + echo "DEPRECATED! use 'hla command', not 'hla_command'" + eval hla command $command +} + +lappend _telnet_autocomplete_skip "hla_stlink_backend" +proc "hla_stlink_backend" {args} { + echo "DEPRECATED! use 'hla stlink_backend', not 'hla_stlink_backend'" + eval hla stlink_backend $args +} + lappend _telnet_autocomplete_skip "kitprog_init_acquire_psoc" proc "kitprog_init_acquire_psoc" {} { echo "DEPRECATED! use 'kitprog init_acquire_psoc', not 'kitprog_init_acquire_psoc'" diff --git a/src/jtag/swd.h b/src/jtag/swd.h index 5f626c1..3fe1365 100644 --- a/src/jtag/swd.h +++ b/src/jtag/swd.h @@ -101,7 +101,7 @@ static const uint8_t swd_seq_line_reset[] = { /* At least 2 idle (low) cycles */ 0x00, }; -static const unsigned swd_seq_line_reset_len = 64; +static const unsigned int swd_seq_line_reset_len = 64; /** * JTAG-to-SWD sequence. @@ -122,7 +122,7 @@ static const uint8_t swd_seq_jtag_to_swd[] = { /* At least 2 idle (low) cycles */ 0x00, }; -static const unsigned swd_seq_jtag_to_swd_len = 136; +static const unsigned int swd_seq_jtag_to_swd_len = 136; /** * SWD-to-JTAG sequence. @@ -141,7 +141,7 @@ static const uint8_t swd_seq_swd_to_jtag[] = { /* At least 5 TCK/SWCLK cycles with TMS/SWDIO high */ 0xff, }; -static const unsigned swd_seq_swd_to_jtag_len = 80; +static const unsigned int swd_seq_swd_to_jtag_len = 80; /** * SWD-to-dormant sequence. @@ -156,7 +156,7 @@ static const uint8_t swd_seq_swd_to_dormant[] = { /* Switching sequence from SWD to dormant */ 0xbc, 0xe3, }; -static const unsigned swd_seq_swd_to_dormant_len = 72; +static const unsigned int swd_seq_swd_to_dormant_len = 72; /** * Dormant-to-SWD sequence. @@ -187,7 +187,7 @@ static const uint8_t swd_seq_dormant_to_swd[] = { /* At least 2 idle (low) cycles */ 0x00, }; -static const unsigned swd_seq_dormant_to_swd_len = 224; +static const unsigned int swd_seq_dormant_to_swd_len = 224; /** * JTAG-to-dormant sequence. @@ -208,7 +208,7 @@ static const uint8_t swd_seq_jtag_to_dormant[] = { 0x77, /* ((0xbb >> 7) & GENMASK(0, 0)) | ((0xbb << 1) & GENMASK(7, 1)) */ 0x67, /* ((0xbb >> 7) & GENMASK(0, 0)) | ((0x33 << 1) & GENMASK(7, 1)) */ }; -static const unsigned swd_seq_jtag_to_dormant_len = 40; +static const unsigned int swd_seq_jtag_to_dormant_len = 40; /** * Dormant-to-JTAG sequence. @@ -241,7 +241,7 @@ static const uint8_t swd_seq_dormant_to_jtag[] = { /* put the TAP in Run/Test Idle */ 0x00, }; -static const unsigned swd_seq_dormant_to_jtag_len = 160; +static const unsigned int swd_seq_dormant_to_jtag_len = 160; struct swd_driver { /** diff --git a/src/jtag/tcl.c b/src/jtag/tcl.c index 1a4c4b7..8b0bc7a 100644 --- a/src/jtag/tcl.c +++ b/src/jtag/tcl.c @@ -61,7 +61,7 @@ struct jtag_tap *jtag_tap_by_jim_obj(Jim_Interp *interp, Jim_Obj *o) return t; } -static bool scan_is_safe(tap_state_t state) +static bool scan_is_safe(enum tap_state state) { switch (state) { case TAP_RESET: @@ -87,8 +87,11 @@ static COMMAND_HELPER(handle_jtag_command_drscan_fields, struct scan_field *fiel LOG_ERROR("Out of memory"); return ERROR_FAIL; } + fields[field_count].out_value = t; - str_to_buf(CMD_ARGV[i + 1], strlen(CMD_ARGV[i + 1]), t, bits, 0); + int ret = CALL_COMMAND_HANDLER(command_parse_str_to_buf, CMD_ARGV[i + 1], t, bits); + if (ret != ERROR_OK) + return ret; fields[field_count].in_value = t; field_count++; } @@ -123,7 +126,7 @@ COMMAND_HANDLER(handle_jtag_command_drscan) return ERROR_FAIL; } - tap_state_t endstate = TAP_IDLE; + enum tap_state endstate = TAP_IDLE; if (CMD_ARGC > 3 && !strcmp("-endstate", CMD_ARGV[CMD_ARGC - 2])) { const char *state_name = CMD_ARGV[CMD_ARGC - 1]; endstate = tap_state_by_name(state_name); @@ -173,7 +176,7 @@ fail: COMMAND_HANDLER(handle_jtag_command_pathmove) { - tap_state_t states[8]; + enum tap_state states[8]; if (CMD_ARGC < 1 || CMD_ARGC > ARRAY_SIZE(states)) return ERROR_COMMAND_SYNTAX_ERROR; @@ -209,8 +212,8 @@ COMMAND_HANDLER(handle_jtag_flush_count) if (CMD_ARGC != 0) return ERROR_COMMAND_SYNTAX_ERROR; - int count = jtag_get_flush_queue_count(); - command_print_sameline(CMD, "%d", count); + const unsigned int count = jtag_get_flush_queue_count(); + command_print_sameline(CMD, "%u", count); return ERROR_OK; } @@ -445,11 +448,11 @@ static COMMAND_HELPER(handle_jtag_newtap_args, struct jtag_tap *tap) if (!CMD_ARGC) return ERROR_COMMAND_ARGUMENT_INVALID; - COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], tap->ir_length); + COMMAND_PARSE_NUMBER(uint, CMD_ARGV[0], tap->ir_length); CMD_ARGC--; CMD_ARGV++; - if (tap->ir_length > (int)(8 * sizeof(tap->ir_capture_value))) - LOG_WARNING("%s: huge IR length %d", tap->dotted_name, tap->ir_length); + if (tap->ir_length > (8 * sizeof(tap->ir_capture_value))) + LOG_WARNING("%s: huge IR length %u", tap->dotted_name, tap->ir_length); break; case NTAP_OPT_IRMASK: @@ -800,10 +803,8 @@ COMMAND_HANDLER(handle_scan_chain_command) while (tap) { uint32_t expected, expected_mask, ii; - snprintf(expected_id, sizeof(expected_id), "0x%08x", - (unsigned)((tap->expected_ids_cnt > 0) - ? tap->expected_ids[0] - : 0)); + snprintf(expected_id, sizeof(expected_id), "0x%08" PRIx32, + (tap->expected_ids_cnt > 0) ? tap->expected_ids[0] : 0); if (tap->ignore_version) expected_id[2] = '*'; @@ -811,19 +812,18 @@ COMMAND_HANDLER(handle_scan_chain_command) expected_mask = buf_get_u32(tap->expected_mask, 0, tap->ir_length); command_print(CMD, - "%2d %-18s %c 0x%08x %s %5d 0x%02x 0x%02x", + "%2u %-18s %c 0x%08x %s %5u 0x%02x 0x%02x", tap->abs_chain_position, tap->dotted_name, tap->enabled ? 'Y' : 'n', (unsigned int)(tap->idcode), expected_id, - (unsigned int)(tap->ir_length), + tap->ir_length, (unsigned int)(expected), (unsigned int)(expected_mask)); for (ii = 1; ii < tap->expected_ids_cnt; ii++) { - snprintf(expected_id, sizeof(expected_id), "0x%08x", - (unsigned) tap->expected_ids[ii]); + snprintf(expected_id, sizeof(expected_id), "0x%08" PRIx32, tap->expected_ids[ii]); if (tap->ignore_version) expected_id[2] = '*'; @@ -843,7 +843,7 @@ COMMAND_HANDLER(handle_jtag_ntrst_delay_command) if (CMD_ARGC > 1) return ERROR_COMMAND_SYNTAX_ERROR; if (CMD_ARGC == 1) { - unsigned delay; + unsigned int delay; COMMAND_PARSE_NUMBER(uint, CMD_ARGV[0], delay); jtag_set_ntrst_delay(delay); @@ -857,7 +857,7 @@ COMMAND_HANDLER(handle_jtag_ntrst_assert_width_command) if (CMD_ARGC > 1) return ERROR_COMMAND_SYNTAX_ERROR; if (CMD_ARGC == 1) { - unsigned delay; + unsigned int delay; COMMAND_PARSE_NUMBER(uint, CMD_ARGV[0], delay); jtag_set_ntrst_assert_width(delay); @@ -873,7 +873,7 @@ COMMAND_HANDLER(handle_jtag_rclk_command) int retval = ERROR_OK; if (CMD_ARGC == 1) { - unsigned khz = 0; + unsigned int khz = 0; COMMAND_PARSE_NUMBER(uint, CMD_ARGV[0], khz); retval = adapter_config_rclk(khz); @@ -899,7 +899,7 @@ COMMAND_HANDLER(handle_runtest_command) if (CMD_ARGC != 1) return ERROR_COMMAND_SYNTAX_ERROR; - unsigned num_clocks; + unsigned int num_clocks; COMMAND_PARSE_NUMBER(uint, CMD_ARGV[0], num_clocks); jtag_add_runtest(num_clocks, TAP_IDLE); @@ -919,7 +919,7 @@ COMMAND_HANDLER(handle_irscan_command) int i; struct scan_field *fields; struct jtag_tap *tap = NULL; - tap_state_t endstate; + enum tap_state endstate; if ((CMD_ARGC < 2) || (CMD_ARGC % 2)) return ERROR_COMMAND_SYNTAX_ERROR; @@ -969,7 +969,7 @@ COMMAND_HANDLER(handle_irscan_command) if (retval != ERROR_OK) goto error_return; - int field_size = tap->ir_length; + unsigned int field_size = tap->ir_length; fields[i].num_bits = field_size; uint8_t *v = calloc(1, DIV_ROUND_UP(field_size, 8)); if (!v) { diff --git a/src/openocd.c b/src/openocd.c index 54c5eb3..3fbece3 100644 --- a/src/openocd.c +++ b/src/openocd.c @@ -232,6 +232,23 @@ static int openocd_register_commands(struct command_context *cmd_ctx) struct command_context *global_cmd_ctx; +static int (* const command_registrants[])(struct command_context *cmd_ctx_value) = { + openocd_register_commands, + server_register_commands, + gdb_register_commands, + log_register_commands, + rtt_server_register_commands, + transport_register_commands, + adapter_register_commands, + target_register_commands, + flash_register_commands, + nand_register_commands, + pld_register_commands, + cti_register_commands, + dap_register_commands, + arm_tpiu_swo_register_commands, +}; + static struct command_context *setup_command_handler(Jim_Interp *interp) { log_init(); @@ -240,25 +257,7 @@ static struct command_context *setup_command_handler(Jim_Interp *interp) struct command_context *cmd_ctx = command_init(openocd_startup_tcl, interp); /* register subsystem commands */ - typedef int (*command_registrant_t)(struct command_context *cmd_ctx_value); - static const command_registrant_t command_registrants[] = { - &openocd_register_commands, - &server_register_commands, - &gdb_register_commands, - &log_register_commands, - &rtt_server_register_commands, - &transport_register_commands, - &adapter_register_commands, - &target_register_commands, - &flash_register_commands, - &nand_register_commands, - &pld_register_commands, - &cti_register_commands, - &dap_register_commands, - &arm_tpiu_swo_register_commands, - NULL - }; - for (unsigned i = 0; command_registrants[i]; i++) { + for (unsigned int i = 0; i < ARRAY_SIZE(command_registrants); i++) { int retval = (*command_registrants[i])(cmd_ctx); if (retval != ERROR_OK) { command_done(cmd_ctx); @@ -375,6 +374,13 @@ int openocd_main(int argc, char *argv[]) log_exit(); +#if USE_GCOV + /* Always explicitly dump coverage data before terminating. + * Otherwise coverage would not be dumped when exit_on_signal occurs. */ + void __gcov_dump(void); + __gcov_dump(); +#endif + if (ret == ERROR_FAIL) return EXIT_FAILURE; else if (ret != ERROR_OK) diff --git a/src/pld/lattice.c b/src/pld/lattice.c index 2997cdc..93ef356 100644 --- a/src/pld/lattice.c +++ b/src/pld/lattice.c @@ -59,7 +59,7 @@ static const struct lattice_devices_elem lattice_devices[] = { {0x010f4043, 362, LATTICE_CERTUS /* LFCPNX-100 */}, }; -int lattice_set_instr(struct jtag_tap *tap, uint8_t new_instr, tap_state_t endstate) +int lattice_set_instr(struct jtag_tap *tap, uint8_t new_instr, enum tap_state endstate) { struct scan_field field; field.num_bits = tap->ir_length; diff --git a/src/pld/lattice.h b/src/pld/lattice.h index 9a76a4e..c215989 100644 --- a/src/pld/lattice.h +++ b/src/pld/lattice.h @@ -20,7 +20,7 @@ struct lattice_pld_device { enum lattice_family_e family; }; -int lattice_set_instr(struct jtag_tap *tap, uint8_t new_instr, tap_state_t endstate); +int lattice_set_instr(struct jtag_tap *tap, uint8_t new_instr, enum tap_state endstate); int lattice_read_u32_register(struct jtag_tap *tap, uint8_t cmd, uint32_t *in_val, uint32_t out_val, bool do_idle); int lattice_read_u64_register(struct jtag_tap *tap, uint8_t cmd, uint64_t *in_val, diff --git a/src/pld/pld.c b/src/pld/pld.c index 81fb0c4..edd7796 100644 --- a/src/pld/pld.c +++ b/src/pld/pld.c @@ -28,7 +28,7 @@ static struct pld_driver *pld_drivers[] = { static struct pld_device *pld_devices; -struct pld_device *get_pld_device_by_num(int num) +static struct pld_device *get_pld_device_by_num(int num) { struct pld_device *p; int i = 0; diff --git a/src/pld/pld.h b/src/pld/pld.h index 5e2fcd2..a6e2e0f 100644 --- a/src/pld/pld.h +++ b/src/pld/pld.h @@ -54,7 +54,6 @@ struct pld_device { int pld_register_commands(struct command_context *cmd_ctx); -struct pld_device *get_pld_device_by_num(int num); struct pld_device *get_pld_device_by_name(const char *name); struct pld_device *get_pld_device_by_name_or_numstr(const char *str); 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/chibios.c b/src/rtos/chibios.c index c1e4e84..af590c2 100644 --- a/src/rtos/chibios.c +++ b/src/rtos/chibios.c @@ -31,7 +31,7 @@ struct chibios_chdebug { char ch_identifier[4]; /**< @brief Always set to "main". */ uint8_t ch_zero; /**< @brief Must be zero. */ uint8_t ch_size; /**< @brief Size of this structure. */ - uint16_t ch_version; /**< @brief Encoded ChibiOS/RT version. */ + uint8_t ch_version[2]; /**< @brief Encoded ChibiOS/RT version. */ uint8_t ch_ptrsize; /**< @brief Size of a pointer. */ uint8_t ch_timesize; /**< @brief Size of a @p systime_t. */ uint8_t ch_threadsize; /**< @brief Size of a @p Thread struct. */ @@ -171,13 +171,7 @@ static int chibios_update_memory_signature(struct rtos *rtos) " expected. Assuming compatibility..."); } - /* Convert endianness of version field */ - const uint8_t *versiontarget = (const uint8_t *) - &signature->ch_version; - signature->ch_version = rtos->target->endianness == TARGET_LITTLE_ENDIAN ? - le_to_h_u32(versiontarget) : be_to_h_u32(versiontarget); - - const uint16_t ch_version = signature->ch_version; + const uint16_t ch_version = target_buffer_get_u16(rtos->target, signature->ch_version); LOG_INFO("Successfully loaded memory map of ChibiOS/RT target " "running version %i.%i.%i", GET_CH_KERNEL_MAJOR(ch_version), GET_CH_KERNEL_MINOR(ch_version), GET_CH_KERNEL_PATCH(ch_version)); @@ -427,9 +421,11 @@ static int chibios_update_threads(struct rtos *rtos) else state_desc = "Unknown"; - curr_thrd_details->extra_info_str = malloc(strlen( - state_desc)+8); - sprintf(curr_thrd_details->extra_info_str, "State: %s", state_desc); + curr_thrd_details->extra_info_str = alloc_printf("State: %s", state_desc); + if (!curr_thrd_details->extra_info_str) { + LOG_ERROR("Could not allocate space for thread state description"); + return -1; + } curr_thrd_details->exists = true; 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/hwthread.c b/src/rtos/hwthread.c index f256bc2..3e4a4ec 100644 --- a/src/rtos/hwthread.c +++ b/src/rtos/hwthread.c @@ -36,7 +36,18 @@ struct target *hwthread_swbp_target(struct rtos *rtos, target_addr_t address, static inline threadid_t threadid_from_target(const struct target *target) { - return target->coreid + 1; + if (!target->smp) + return 1; + + threadid_t threadid = 1; + struct target_list *head; + foreach_smp_target(head, target->smp_targets) { + if (target == head->target) + return threadid; + ++threadid; + } + assert(0 && "Target is not found in it's own SMP group!"); + return -1; } const struct rtos_type hwthread_rtos = { @@ -59,14 +70,13 @@ struct hwthread_params { int dummy_param; }; -static int hwthread_fill_thread(struct rtos *rtos, struct target *curr, int thread_num) +static int hwthread_fill_thread(struct rtos *rtos, struct target *curr, int thread_num, threadid_t tid) { char tmp_str[HW_THREAD_NAME_STR_SIZE]; - threadid_t tid = threadid_from_target(curr); memset(tmp_str, 0, HW_THREAD_NAME_STR_SIZE); - /* thread-id is the core-id of this core inside the SMP group plus 1 */ + /* thread-id is the index of this core inside the SMP group plus 1 */ rtos->thread_details[thread_num].threadid = tid; /* create the thread name */ rtos->thread_details[thread_num].exists = true; @@ -115,7 +125,7 @@ static int hwthread_update_threads(struct rtos *rtos) if (current_threadid <= thread_list_size) rtos->current_threadid = current_threadid; else - LOG_WARNING("SMP node change, disconnect GDB from core/thread %" PRId64, + LOG_TARGET_WARNING(target, "SMP node change, disconnect GDB from core/thread %" PRId64, current_threadid); /* create space for new thread details */ @@ -131,8 +141,7 @@ static int hwthread_update_threads(struct rtos *rtos) continue; threadid_t tid = threadid_from_target(curr); - - hwthread_fill_thread(rtos, curr, threads_found); + hwthread_fill_thread(rtos, curr, threads_found, tid); /* find an interesting thread to set as current */ switch (current_reason) { @@ -152,9 +161,8 @@ static int hwthread_update_threads(struct rtos *rtos) if (curr->debug_reason == DBG_REASON_SINGLESTEP) { current_reason = curr->debug_reason; current_thread = tid; - } else - /* multiple breakpoints, prefer gdbs' threadid */ - if (curr->debug_reason == DBG_REASON_BREAKPOINT) { + } else if (curr->debug_reason == DBG_REASON_BREAKPOINT) { + /* multiple breakpoints, prefer gdbs' threadid */ if (tid == rtos->current_threadid) current_thread = tid; } @@ -174,8 +182,7 @@ static int hwthread_update_threads(struct rtos *rtos) curr->debug_reason == DBG_REASON_BREAKPOINT) { current_reason = curr->debug_reason; current_thread = tid; - } else - if (curr->debug_reason == DBG_REASON_DBGRQ) { + } else if (curr->debug_reason == DBG_REASON_DBGRQ) { if (tid == rtos->current_threadid) current_thread = tid; } @@ -189,8 +196,8 @@ static int hwthread_update_threads(struct rtos *rtos) threads_found++; } } else { - hwthread_fill_thread(rtos, target, threads_found); - current_thread = threadid_from_target(target); + current_thread = 1; + hwthread_fill_thread(rtos, target, threads_found, current_thread); threads_found++; } @@ -204,7 +211,8 @@ static int hwthread_update_threads(struct rtos *rtos) else rtos->current_thread = threadid_from_target(target); - LOG_DEBUG("current_thread=%i, threads_found=%d", (int)rtos->current_thread, threads_found); + LOG_TARGET_DEBUG(target, "current_thread=%i, threads_found=%d", + (int)rtos->current_thread, threads_found); return 0; } @@ -213,19 +221,17 @@ static int hwthread_smp_init(struct target *target) return hwthread_update_threads(target->rtos); } -static struct target *hwthread_find_thread(struct target *target, int64_t thread_id) +static struct target *hwthread_find_thread(struct target *target, threadid_t thread_id) { - /* Find the thread with that thread_id */ - if (!target) - return NULL; - if (target->smp) { - struct target_list *head; - foreach_smp_target(head, target->smp_targets) { - if (thread_id == threadid_from_target(head->target)) - return head->target; - } - } else if (thread_id == threadid_from_target(target)) { + /* Find the thread with that thread_id (index in SMP group plus 1)*/ + if (!(target && target->smp)) return target; + struct target_list *head; + threadid_t tid = 1; + foreach_smp_target(head, target->smp_targets) { + if (thread_id == tid) + return head->target; + ++tid; } return NULL; } @@ -254,7 +260,7 @@ static int hwthread_get_thread_reg_list(struct rtos *rtos, int64_t thread_id, int j = 0; for (int i = 0; i < reg_list_size; i++) { - if (!reg_list[i] || reg_list[i]->exist == false || reg_list[i]->hidden) + if (!reg_list[i] || !reg_list[i]->exist || reg_list[i]->hidden) continue; j++; } @@ -267,12 +273,13 @@ static int hwthread_get_thread_reg_list(struct rtos *rtos, int64_t thread_id, j = 0; for (int i = 0; i < reg_list_size; i++) { - if (!reg_list[i] || reg_list[i]->exist == false || reg_list[i]->hidden) + if (!reg_list[i] || !reg_list[i]->exist || reg_list[i]->hidden) continue; if (!reg_list[i]->valid) { retval = reg_list[i]->type->get(reg_list[i]); if (retval != ERROR_OK) { - LOG_ERROR("Couldn't get register %s.", reg_list[i]->name); + LOG_TARGET_ERROR(curr, "Couldn't get register %s", + reg_list[i]->name); free(reg_list); free(*rtos_reg_list); return retval; @@ -299,19 +306,20 @@ static int hwthread_get_thread_reg_value(struct rtos *rtos, int64_t thread_id, struct target *curr = hwthread_find_thread(target, thread_id); if (!curr) { - LOG_ERROR("Couldn't find RTOS thread for id %" PRId64 ".", thread_id); + LOG_TARGET_ERROR(target, "Couldn't find RTOS thread for id %" PRId64, + thread_id); return ERROR_FAIL; } if (!target_was_examined(curr)) { - LOG_ERROR("Target %d hasn't been examined yet.", curr->coreid); + LOG_TARGET_ERROR(curr, "Target hasn't been examined yet."); return ERROR_FAIL; } struct reg *reg = register_get_by_number(curr->reg_cache, reg_num, true); if (!reg) { - LOG_ERROR("Couldn't find register %" PRIu32 " in thread %" PRId64 ".", reg_num, - thread_id); + LOG_TARGET_ERROR(curr, "Couldn't find register %" PRIu32 " in thread %" PRId64, + reg_num, thread_id); return ERROR_FAIL; } @@ -319,7 +327,7 @@ static int hwthread_get_thread_reg_value(struct rtos *rtos, int64_t thread_id, return ERROR_FAIL; *size = reg->size; - unsigned bytes = DIV_ROUND_UP(reg->size, 8); + unsigned int bytes = DIV_ROUND_UP(reg->size, 8); *value = malloc(bytes); if (!*value) { LOG_ERROR("Failed to allocate memory for %d-bit register.", reg->size); @@ -377,24 +385,24 @@ static bool hwthread_detect_rtos(struct target *target) static int hwthread_thread_packet(struct connection *connection, const char *packet, int packet_size) { - struct target *target = get_target_from_connection(connection); - - struct target *curr = NULL; - int64_t current_threadid; - if (packet[0] == 'H' && packet[1] == 'g') { + int64_t current_threadid; sscanf(packet, "Hg%16" SCNx64, ¤t_threadid); + struct target *target = get_target_from_connection(connection); + if (current_threadid > 0) { + struct target *curr = NULL; if (hwthread_target_for_threadid(connection, current_threadid, &curr) != ERROR_OK) { - LOG_ERROR("hwthread: cannot find thread id %"PRId64, current_threadid); + LOG_TARGET_ERROR(target, "hwthread: cannot find thread id %" PRId64, + current_threadid); gdb_put_packet(connection, "E01", 3); return ERROR_FAIL; } target->rtos->current_thread = current_threadid; - } else - if (current_threadid == 0 || current_threadid == -1) + } else if (current_threadid == 0 || current_threadid == -1) { target->rtos->current_thread = threadid_from_target(target); + } target->rtos->current_threadid = current_threadid; @@ -407,7 +415,7 @@ static int hwthread_thread_packet(struct connection *connection, const char *pac static int hwthread_create(struct target *target) { - LOG_INFO("Hardware thread awareness created"); + LOG_TARGET_INFO(target, "Hardware thread awareness created"); target->rtos->rtos_specific_params = NULL; target->rtos->current_thread = 0; diff --git a/src/rtos/linux.c b/src/rtos/linux.c index 7517ec7..5efdc9f 100644 --- a/src/rtos/linux.c +++ b/src/rtos/linux.c @@ -624,7 +624,7 @@ static struct threads *liste_add_task(struct threads *task_list, struct threads { t->next = NULL; - if (!*last) + if (!*last) { if (!task_list) { task_list = t; return task_list; @@ -637,7 +637,8 @@ static struct threads *liste_add_task(struct threads *task_list, struct threads temp->next = t; *last = t; return task_list; - } else { + } + } else { (*last)->next = t; *last = t; return task_list; @@ -1039,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; @@ -1115,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/mqx.c b/src/rtos/mqx.c index b4a1821..017fd2b 100644 --- a/src/rtos/mqx.c +++ b/src/rtos/mqx.c @@ -319,7 +319,7 @@ static int mqx_update_threads( i < (uint32_t)rtos->thread_count; i++ ) { - uint8_t task_name[MQX_THREAD_NAME_LENGTH + 1]; + char task_name[MQX_THREAD_NAME_LENGTH + 1]; uint32_t task_addr = 0, task_template = 0, task_state = 0; uint32_t task_name_addr = 0, task_id = 0, task_errno = 0; uint32_t state_index = 0; @@ -380,10 +380,9 @@ static int mqx_update_threads( rtos->thread_details[i].threadid = task_id; rtos->thread_details[i].exists = true; /* set thread name */ - rtos->thread_details[i].thread_name_str = malloc(strlen((void *)task_name) + 1); + rtos->thread_details[i].thread_name_str = strdup(task_name); if (!rtos->thread_details[i].thread_name_str) return ERROR_FAIL; - strcpy(rtos->thread_details[i].thread_name_str, (void *)task_name); /* set thread extra info * - task state * - task address diff --git a/src/rtos/nuttx.c b/src/rtos/nuttx.c index 9100148..821e550 100644 --- a/src/rtos/nuttx.c +++ b/src/rtos/nuttx.c @@ -32,7 +32,6 @@ struct nuttx_params { const char *target_name; const struct rtos_register_stacking *stacking; - const struct rtos_register_stacking *(*select_stackinfo)(struct target *target); }; /* @@ -56,19 +55,12 @@ struct symbols { bool optional; }; -/* Used to index the list of retrieved symbols. See nuttx_symbol_list for the order. */ -enum nuttx_symbol_vals { - NX_SYM_READYTORUN = 0, - NX_SYM_PIDHASH, - NX_SYM_NPIDHASH, - NX_SYM_TCB_INFO, -}; - static const struct symbols nuttx_symbol_list[] = { { "g_readytorun", false }, { "g_pidhash", false }, { "g_npidhash", false }, { "g_tcbinfo", false }, + { "g_reg_offs", false}, { NULL, false } }; @@ -86,18 +78,14 @@ static char *task_state_str[] = { "STOPPED", }; -static const struct rtos_register_stacking *cortexm_select_stackinfo(struct target *target); - static const struct nuttx_params nuttx_params_list[] = { { .target_name = "cortex_m", - .stacking = NULL, - .select_stackinfo = cortexm_select_stackinfo, + .stacking = &nuttx_stacking_cortex_m, }, { .target_name = "hla_target", - .stacking = NULL, - .select_stackinfo = cortexm_select_stackinfo, + .stacking = &nuttx_stacking_cortex_m, }, { .target_name = "esp32", @@ -117,28 +105,6 @@ static const struct nuttx_params nuttx_params_list[] = { }, }; -static bool cortexm_hasfpu(struct target *target) -{ - uint32_t cpacr; - struct armv7m_common *armv7m_target = target_to_armv7m(target); - - if (!is_armv7m(armv7m_target) || armv7m_target->fp_feature == FP_NONE) - return false; - - int retval = target_read_u32(target, FPU_CPACR, &cpacr); - if (retval != ERROR_OK) { - LOG_ERROR("Could not read CPACR register to check FPU state"); - return false; - } - - return cpacr & 0x00F00000; -} - -static const struct rtos_register_stacking *cortexm_select_stackinfo(struct target *target) -{ - return cortexm_hasfpu(target) ? &nuttx_stacking_cortex_m_fpu : &nuttx_stacking_cortex_m; -} - static bool nuttx_detect_rtos(struct target *target) { if (target->rtos->symbols && @@ -371,29 +337,25 @@ static int nuttx_getreg_current_thread(struct rtos *rtos, static int nuttx_getregs_fromstack(struct rtos *rtos, int64_t thread_id, struct rtos_reg **reg_list, int *num_regs) { - uint16_t xcpreg_off; + uint16_t regs_off; uint32_t regsaddr; const struct nuttx_params *priv = rtos->rtos_specific_params; const struct rtos_register_stacking *stacking = priv->stacking; if (!stacking) { - if (priv->select_stackinfo) { - stacking = priv->select_stackinfo(rtos->target); - } else { - LOG_ERROR("Can't find a way to get stacking info"); - return ERROR_FAIL; - } + LOG_ERROR("Can't find a way to get stacking info"); + return ERROR_FAIL; } int ret = target_read_u16(rtos->target, rtos->symbols[NX_SYM_TCB_INFO].address + offsetof(struct tcbinfo, regs_off), - &xcpreg_off); + ®s_off); if (ret != ERROR_OK) { LOG_ERROR("Failed to read registers' offset: ret = %d", ret); return ERROR_FAIL; } - ret = target_read_u32(rtos->target, thread_id + xcpreg_off, ®saddr); + ret = target_read_u32(rtos->target, thread_id + regs_off, ®saddr); if (ret != ERROR_OK) { LOG_ERROR("Failed to read registers' address: ret = %d", ret); return ERROR_FAIL; diff --git a/src/rtos/rtos.c b/src/rtos/rtos.c index b5e8e9a..e87e51c 100644 --- a/src/rtos/rtos.c +++ b/src/rtos/rtos.c @@ -109,7 +109,7 @@ int rtos_create(struct jim_getopt_info *goi, struct target *target) Jim_Obj *res; int e; - if (!goi->isconfigure && goi->argc != 0) { + if (!goi->is_configure && goi->argc != 0) { Jim_WrongNumArgs(goi->interp, goi->argc, goi->argv, "NO PARAMS"); return JIM_ERR; } @@ -317,7 +317,7 @@ int rtos_qsymbol(struct connection *connection, char const *packet, int packet_s reply_len += 2 * strlen(next_suffix); /* hexify(..., next_suffix, ...) */ reply_len += 1; /* Terminating NUL */ if (reply_len > sizeof(reply)) { - LOG_ERROR("ERROR: RTOS symbol '%s%s' name is too long for GDB!", next_sym->symbol_name, next_suffix); + LOG_ERROR("RTOS symbol '%s%s' name is too long for GDB", next_sym->symbol_name, next_suffix); goto done; } @@ -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) @@ -397,7 +401,7 @@ int rtos_thread_packet(struct connection *connection, char const *packet, int pa return ERROR_OK; } else if (strncmp(packet, "qSymbol", 7) == 0) { if (rtos_qsymbol(connection, packet, packet_size) == 1) { - if (target->rtos_auto_detect == true) { + if (target->rtos_auto_detect) { target->rtos_auto_detect = false; target->rtos->type->create(target); } @@ -635,7 +639,7 @@ int rtos_generic_stack_read(struct target *target, int retval; if (stack_ptr == 0) { - LOG_ERROR("Error: null stack pointer in thread"); + LOG_ERROR("null stack pointer in thread"); return -5; } /* Read the stack */ diff --git a/src/rtos/rtos_nuttx_stackings.c b/src/rtos/rtos_nuttx_stackings.c index b70cccb..6faa56a 100644 --- a/src/rtos/rtos_nuttx_stackings.c +++ b/src/rtos/rtos_nuttx_stackings.c @@ -9,60 +9,100 @@ #include "rtos_nuttx_stackings.h" #include "rtos_standard_stackings.h" #include <target/riscv/riscv.h> +#include <helper/bits.h> -/* see arch/arm/include/armv7-m/irq_cmnvector.h */ +/* The cortex_m target uses nuttx_tcbinfo_stack_read which uses a symbol + * provided by Nuttx to read the registers from memory and place them directly + * in the order we need. This is because the register offsets change with + * different versions of Nuttx, FPU vs non-FPU and ARMv7 vs ARMv8. + * This allows a single function to work with many versions. + */ static const struct stack_register_offset nuttx_stack_offsets_cortex_m[] = { - { ARMV7M_R0, 0x28, 32 }, /* r0 */ - { ARMV7M_R1, 0x2c, 32 }, /* r1 */ - { ARMV7M_R2, 0x30, 32 }, /* r2 */ - { ARMV7M_R3, 0x34, 32 }, /* r3 */ - { ARMV7M_R4, 0x08, 32 }, /* r4 */ - { ARMV7M_R5, 0x0c, 32 }, /* r5 */ - { ARMV7M_R6, 0x10, 32 }, /* r6 */ - { ARMV7M_R7, 0x14, 32 }, /* r7 */ - { ARMV7M_R8, 0x18, 32 }, /* r8 */ - { ARMV7M_R9, 0x1c, 32 }, /* r9 */ - { ARMV7M_R10, 0x20, 32 }, /* r10 */ - { ARMV7M_R11, 0x24, 32 }, /* r11 */ - { ARMV7M_R12, 0x38, 32 }, /* r12 */ - { ARMV7M_R13, 0, 32 }, /* sp */ - { ARMV7M_R14, 0x3c, 32 }, /* lr */ - { ARMV7M_PC, 0x40, 32 }, /* pc */ - { ARMV7M_XPSR, 0x44, 32 }, /* xPSR */ + { ARMV7M_R0, 0, 32 }, /* r0 */ + { ARMV7M_R1, 4, 32 }, /* r1 */ + { ARMV7M_R2, 8, 32 }, /* r2 */ + { ARMV7M_R3, 12, 32 }, /* r3 */ + { ARMV7M_R4, 16, 32 }, /* r4 */ + { ARMV7M_R5, 20, 32 }, /* r5 */ + { ARMV7M_R6, 24, 32 }, /* r6 */ + { ARMV7M_R7, 28, 32 }, /* r7 */ + { ARMV7M_R8, 32, 32 }, /* r8 */ + { ARMV7M_R9, 36, 32 }, /* r9 */ + { ARMV7M_R10, 40, 32 }, /* r10 */ + { ARMV7M_R11, 44, 32 }, /* r11 */ + { ARMV7M_R12, 48, 32 }, /* r12 */ + { ARMV7M_R13, 52, 32 }, /* sp */ + { ARMV7M_R14, 56, 32 }, /* lr */ + { ARMV7M_PC, 60, 32 }, /* pc */ + { ARMV7M_XPSR, 64, 32 }, /* xPSR */ }; -const struct rtos_register_stacking nuttx_stacking_cortex_m = { - .stack_registers_size = 0x48, - .stack_growth_direction = -1, - .num_output_registers = 17, - .register_offsets = nuttx_stack_offsets_cortex_m, -}; +/* The Nuttx stack frame for most architectures has some registers placed + * by hardware and some by software. The hardware register order and number does not change + * but the software registers may change with different versions of Nuttx. + * For example with ARMv7, nuttx-12.3.0 added a new register which changed all + * the offsets. We can either create separate offset tables for each version of Nuttx + * which will break again in the future, or read the offsets from the TCB info. + * Nuttx provides a symbol (g_reg_offs) which holds all the offsets for each stored register. + * This offset table is stored in GDB org.gnu.gdb.xxx feature order. + * The same order we need. + * Please refer: + * https://sourceware.org/gdb/current/onlinedocs/gdb/ARM-Features.html + * https://sourceware.org/gdb/current/onlinedocs/gdb/RISC_002dV-Features.html + */ +static int nuttx_cortex_m_tcbinfo_stack_read(struct target *target, + int64_t stack_ptr, const struct rtos_register_stacking *stacking, + uint8_t *stack_data) +{ + struct rtos *rtos = target->rtos; + target_addr_t xcpreg_off = rtos->symbols[NX_SYM_REG_OFFSETS].address; -static const struct stack_register_offset nuttx_stack_offsets_cortex_m_fpu[] = { - { ARMV7M_R0, 0x6c, 32 }, /* r0 */ - { ARMV7M_R1, 0x70, 32 }, /* r1 */ - { ARMV7M_R2, 0x74, 32 }, /* r2 */ - { ARMV7M_R3, 0x78, 32 }, /* r3 */ - { ARMV7M_R4, 0x08, 32 }, /* r4 */ - { ARMV7M_R5, 0x0c, 32 }, /* r5 */ - { ARMV7M_R6, 0x10, 32 }, /* r6 */ - { ARMV7M_R7, 0x14, 32 }, /* r7 */ - { ARMV7M_R8, 0x18, 32 }, /* r8 */ - { ARMV7M_R9, 0x1c, 32 }, /* r9 */ - { ARMV7M_R10, 0x20, 32 }, /* r10 */ - { ARMV7M_R11, 0x24, 32 }, /* r11 */ - { ARMV7M_R12, 0x7c, 32 }, /* r12 */ - { ARMV7M_R13, 0, 32 }, /* sp */ - { ARMV7M_R14, 0x80, 32 }, /* lr */ - { ARMV7M_PC, 0x84, 32 }, /* pc */ - { ARMV7M_XPSR, 0x88, 32 }, /* xPSR */ -}; + for (int i = 0; i < stacking->num_output_registers; ++i) { + uint16_t stack_reg_offset; + int ret = target_read_u16(rtos->target, xcpreg_off + 2 * i, &stack_reg_offset); + if (ret != ERROR_OK) { + LOG_ERROR("Failed to read stack_reg_offset: ret = %d", ret); + return ret; + } + if (stack_reg_offset != UINT16_MAX && stacking->register_offsets[i].offset >= 0) { + ret = target_read_buffer(target, + stack_ptr + stack_reg_offset, + stacking->register_offsets[i].width_bits / 8, + &stack_data[stacking->register_offsets[i].offset]); + if (ret != ERROR_OK) { + LOG_ERROR("Failed to read register: ret = %d", ret); + return ret; + } + } + } + + /* Offset match nuttx_stack_offsets_cortex_m */ + const int XPSR_OFFSET = 64; + const int SP_OFFSET = 52; + /* Nuttx stack frames (produced in exception_common) store the SP of the ISR minus + * the hardware stack frame size. This SP may include an additional 4 byte alignment + * depending in xPSR[9]. The Nuttx stack frame stores post alignment since the + * hardware will add/remove automatically on both enter/exit. + * We need to adjust the SP to get the real SP of the stack. + * See Arm Reference manual "Stack alignment on exception entry" + */ + uint32_t xpsr = target_buffer_get_u32(target, &stack_data[XPSR_OFFSET]); + if (xpsr & BIT(9)) { + uint32_t sp = target_buffer_get_u32(target, &stack_data[SP_OFFSET]); + target_buffer_set_u32(target, &stack_data[SP_OFFSET], sp - 4 * stacking->stack_growth_direction); + } -const struct rtos_register_stacking nuttx_stacking_cortex_m_fpu = { - .stack_registers_size = 0x8c, + return ERROR_OK; +} + +const struct rtos_register_stacking nuttx_stacking_cortex_m = { + /* nuttx_tcbinfo_stack_read transforms the stack into just output registers */ + .stack_registers_size = ARRAY_SIZE(nuttx_stack_offsets_cortex_m) * 4, .stack_growth_direction = -1, - .num_output_registers = 17, - .register_offsets = nuttx_stack_offsets_cortex_m_fpu, + .num_output_registers = ARRAY_SIZE(nuttx_stack_offsets_cortex_m), + .read_stack = nuttx_cortex_m_tcbinfo_stack_read, + .calculate_process_stack = NULL, /* Stack alignment done in nuttx_cortex_m_tcbinfo_stack_read */ + .register_offsets = nuttx_stack_offsets_cortex_m, }; static const struct stack_register_offset nuttx_stack_offsets_riscv[] = { diff --git a/src/rtos/rtos_nuttx_stackings.h b/src/rtos/rtos_nuttx_stackings.h index 213a060..5d55e75 100644 --- a/src/rtos/rtos_nuttx_stackings.h +++ b/src/rtos/rtos_nuttx_stackings.h @@ -5,6 +5,15 @@ #include "rtos.h" +/* Used to index the list of retrieved symbols. See nuttx_symbol_list for the order. */ +enum nuttx_symbol_vals { + NX_SYM_READYTORUN = 0, + NX_SYM_PIDHASH, + NX_SYM_NPIDHASH, + NX_SYM_TCB_INFO, + NX_SYM_REG_OFFSETS, +}; + extern const struct rtos_register_stacking nuttx_stacking_cortex_m; extern const struct rtos_register_stacking nuttx_stacking_cortex_m_fpu; extern const struct rtos_register_stacking nuttx_riscv_stacking; diff --git a/src/rtos/rtos_standard_stackings.c b/src/rtos/rtos_standard_stackings.c index 0ca664f..360ae9b 100644 --- a/src/rtos/rtos_standard_stackings.c +++ b/src/rtos/rtos_standard_stackings.c @@ -327,9 +327,7 @@ target_addr_t rtos_cortex_m_stack_align(struct target *target, new_stack_ptr = stack_ptr - stacking->stack_growth_direction * stacking->stack_registers_size; - xpsr = (target->endianness == TARGET_LITTLE_ENDIAN) ? - le_to_h_u32(&stack_data[xpsr_offset]) : - be_to_h_u32(&stack_data[xpsr_offset]); + xpsr = target_buffer_get_u32(target, &stack_data[xpsr_offset]); if ((xpsr & ALIGN_NEEDED) != 0) { LOG_DEBUG("XPSR(0x%08" PRIx32 ") indicated stack alignment was necessary\r\n", xpsr); diff --git a/src/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 e31e754..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; } } @@ -297,11 +297,6 @@ int rtt_write_channel(unsigned int channel_index, const uint8_t *buffer, length, NULL); } -bool rtt_started(void) -{ - return rtt.started; -} - bool rtt_configured(void) { return rtt.configured; diff --git a/src/rtt/rtt.h b/src/rtt/rtt.h index a5630a9..d84fdb4 100644 --- a/src/rtt/rtt.h +++ b/src/rtt/rtt.h @@ -95,35 +95,27 @@ enum rtt_channel_type { RTT_CHANNEL_TYPE_DOWN }; -typedef int (*rtt_source_find_ctrl_block)(struct target *target, +/** RTT source. */ +struct rtt_source { + int (*find_cb)(struct target *target, target_addr_t *address, size_t size, const char *id, bool *found, void *user_data); -typedef int (*rtt_source_read_ctrl_block)(struct target *target, + int (*read_cb)(struct target *target, target_addr_t address, struct rtt_control *ctrl_block, void *user_data); -typedef int (*rtt_source_read_channel_info)(struct target *target, + int (*read_channel_info)(struct target *target, const struct rtt_control *ctrl, unsigned int channel, enum rtt_channel_type type, struct rtt_channel_info *info, void *user_data); -typedef int (*rtt_source_start)(struct target *target, + int (*start)(struct target *target, const struct rtt_control *ctrl, void *user_data); -typedef int (*rtt_source_stop)(struct target *target, void *user_data); -typedef int (*rtt_source_read)(struct target *target, + int (*stop)(struct target *target, void *user_data); + int (*read)(struct target *target, const struct rtt_control *ctrl, struct rtt_sink_list **sinks, size_t num_channels, void *user_data); -typedef int (*rtt_source_write)(struct target *target, + int (*write)(struct target *target, struct rtt_control *ctrl, unsigned int channel, const uint8_t *buffer, size_t *length, void *user_data); - -/** RTT source. */ -struct rtt_source { - rtt_source_find_ctrl_block find_cb; - rtt_source_read_ctrl_block read_cb; - rtt_source_read_channel_info read_channel_info; - rtt_source_start start; - rtt_source_stop stop; - rtt_source_read read; - rtt_source_write write; }; /** @@ -195,13 +187,6 @@ int rtt_get_polling_interval(unsigned int *interval); int rtt_set_polling_interval(unsigned int interval); /** - * Get whether RTT is started. - * - * @returns Whether RTT is started. - */ -bool rtt_started(void); - -/** * Get whether RTT is configured. * * @returns Whether RTT is configured. diff --git a/src/rtt/tcl.c b/src/rtt/tcl.c index 2b8822f..bae71b6 100644 --- a/src/rtt/tcl.c +++ b/src/rtt/tcl.c @@ -19,8 +19,14 @@ COMMAND_HANDLER(handle_rtt_setup_command) { struct rtt_source source; - if (CMD_ARGC != 3) + const char *DEFAULT_ID = "SEGGER RTT"; + const char *selected_id; + if (CMD_ARGC < 2 || CMD_ARGC > 3) return ERROR_COMMAND_SYNTAX_ERROR; + if (CMD_ARGC == 2) + selected_id = DEFAULT_ID; + else + selected_id = CMD_ARGV[2]; source.find_cb = &target_rtt_find_control_block; source.read_cb = &target_rtt_read_control_block; @@ -38,7 +44,7 @@ COMMAND_HANDLER(handle_rtt_setup_command) rtt_register_source(source, get_current_target(CMD_CTX)); - if (rtt_setup(address, size, CMD_ARGV[2]) != ERROR_OK) + if (rtt_setup(address, size, selected_id) != ERROR_OK) return ERROR_FAIL; return ERROR_OK; @@ -218,7 +224,7 @@ static const struct command_registration rtt_subcommand_handlers[] = { .handler = handle_rtt_setup_command, .mode = COMMAND_ANY, .help = "setup RTT", - .usage = "<address> <size> <ID>" + .usage = "<address> <size> [ID]" }, { .name = "start", diff --git a/src/server/gdb_server.c b/src/server/gdb_server.c index f4ce5df..d9825c5 100644 --- a/src/server/gdb_server.c +++ b/src/server/gdb_server.c @@ -116,7 +116,7 @@ static int gdb_error(struct connection *connection, int retval); static char *gdb_port; static char *gdb_port_next; -static void gdb_log_callback(void *priv, const char *file, unsigned line, +static void gdb_log_callback(void *priv, const char *file, unsigned int line, const char *function, const char *string); static void gdb_sig_halted(struct connection *connection); @@ -376,7 +376,7 @@ static int gdb_putback_char(struct connection *connection, int last_char) /* The only way we can detect that the socket is closed is the first time * we write to it, we will fail. Subsequent write operations will * succeed. Shudder! */ -static int gdb_write(struct connection *connection, void *data, int len) +static int gdb_write(struct connection *connection, const void *data, int len) { struct gdb_connection *gdb_con = connection->priv; if (gdb_con->closed) { @@ -392,7 +392,7 @@ static int gdb_write(struct connection *connection, void *data, int len) return ERROR_SERVER_REMOTE_CLOSED; } -static void gdb_log_incoming_packet(struct connection *connection, char *packet) +static void gdb_log_incoming_packet(struct connection *connection, const char *packet) { if (!LOG_LEVEL_IS(LOG_LVL_DEBUG)) return; @@ -401,7 +401,7 @@ static void gdb_log_incoming_packet(struct connection *connection, char *packet) struct gdb_connection *gdb_connection = connection->priv; /* Avoid dumping non-printable characters to the terminal */ - const unsigned packet_len = strlen(packet); + const unsigned int packet_len = strlen(packet); const char *nonprint = find_nonprint_char(packet, packet_len); if (nonprint) { /* Does packet at least have a prefix that is printable? @@ -425,7 +425,7 @@ static void gdb_log_incoming_packet(struct connection *connection, char *packet) } } -static void gdb_log_outgoing_packet(struct connection *connection, char *packet_buf, +static void gdb_log_outgoing_packet(struct connection *connection, const char *packet_buf, unsigned int packet_len, unsigned char checksum) { if (!LOG_LEVEL_IS(LOG_LVL_DEBUG)) @@ -443,7 +443,7 @@ static void gdb_log_outgoing_packet(struct connection *connection, char *packet_ } static int gdb_put_packet_inner(struct connection *connection, - char *buffer, int len) + const char *buffer, int len) { int i; unsigned char my_checksum = 0; @@ -565,7 +565,7 @@ static int gdb_put_packet_inner(struct connection *connection, return ERROR_OK; } -int gdb_put_packet(struct connection *connection, char *buffer, int len) +int gdb_put_packet(struct connection *connection, const char *buffer, int len) { struct gdb_connection *gdb_con = connection->priv; gdb_con->busy = true; @@ -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); @@ -1249,7 +1249,7 @@ static void gdb_target_to_reg(struct target *target, int i; for (i = 0; i < str_len; i += 2) { - unsigned t; + unsigned int t; if (sscanf(tstr + i, "%02x", &t) != 1) { LOG_ERROR("BUG: unable to convert register value"); exit(-1); @@ -1308,7 +1308,7 @@ static int gdb_get_registers_packet(struct connection *connection, return gdb_error(connection, retval); for (i = 0; i < reg_list_size; i++) { - if (!reg_list[i] || reg_list[i]->exist == false || reg_list[i]->hidden) + if (!reg_list[i] || !reg_list[i]->exist || reg_list[i]->hidden) continue; reg_packet_size += DIV_ROUND_UP(reg_list[i]->size, 8) * 2; } @@ -1322,7 +1322,7 @@ static int gdb_get_registers_packet(struct connection *connection, reg_packet_p = reg_packet; for (i = 0; i < reg_list_size; i++) { - if (!reg_list[i] || reg_list[i]->exist == false || reg_list[i]->hidden) + if (!reg_list[i] || !reg_list[i]->exist || reg_list[i]->hidden) continue; retval = gdb_get_reg_value_as_str(target, reg_packet_p, reg_list[i]); if (retval != ERROR_OK && gdb_report_register_access_error) { @@ -1599,7 +1599,7 @@ static int gdb_read_memory_packet(struct connection *connection, * cmd = view%20audit-trail&database = gdb&pr = 2395 * * For now, the default is to fix up things to make current GDB versions work. - * This can be overwritten using the gdb_report_data_abort <'enable'|'disable'> command. + * This can be overwritten using the "gdb report_data_abort <'enable'|'disable'>" command. */ memset(buffer, 0, len); retval = ERROR_OK; @@ -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; } @@ -1838,18 +1838,9 @@ static int gdb_breakpoint_watchpoint_packet(struct connection *connection, return ERROR_FAIL; } retval = breakpoint_add(target, address, size, bp_type); - if (retval == ERROR_NOT_IMPLEMENTED) { - /* Send empty reply to report that breakpoints of this type are not supported */ - gdb_put_packet(connection, "", 0); - } else if (retval != ERROR_OK) { - retval = gdb_error(connection, retval); - if (retval != ERROR_OK) - return retval; - } else - gdb_put_packet(connection, "OK", 2); } else { - breakpoint_remove(target, address); - gdb_put_packet(connection, "OK", 2); + assert(packet[0] == 'z'); + retval = breakpoint_remove(target, address); } break; case 2: @@ -1858,26 +1849,26 @@ static int gdb_breakpoint_watchpoint_packet(struct connection *connection, { if (packet[0] == 'Z') { retval = watchpoint_add(target, address, size, wp_type, 0, WATCHPOINT_IGNORE_DATA_VALUE_MASK); - if (retval == ERROR_NOT_IMPLEMENTED) { - /* Send empty reply to report that watchpoints of this type are not supported */ - gdb_put_packet(connection, "", 0); - } else if (retval != ERROR_OK) { - retval = gdb_error(connection, retval); - if (retval != ERROR_OK) - return retval; - } else - gdb_put_packet(connection, "OK", 2); } else { - watchpoint_remove(target, address); - gdb_put_packet(connection, "OK", 2); + assert(packet[0] == 'z'); + retval = watchpoint_remove(target, address); } break; } default: + { + retval = ERROR_NOT_IMPLEMENTED; break; + } } - return ERROR_OK; + if (retval == ERROR_NOT_IMPLEMENTED) { + /* Send empty reply to report that watchpoints of this type are not supported */ + return gdb_put_packet(connection, "", 0); + } + if (retval != ERROR_OK) + return gdb_error(connection, retval); + return gdb_put_packet(connection, "OK", 2); } /* print out a string and allocate more space as needed, @@ -2014,8 +2005,8 @@ static int gdb_memory_map(struct connection *connection, compare_bank); for (unsigned int i = 0; i < target_flash_banks; i++) { - unsigned sector_size = 0; - unsigned group_len = 0; + unsigned int sector_size = 0; + unsigned int group_len = 0; p = banks[i]; @@ -2320,7 +2311,7 @@ static int get_reg_features_list(struct target *target, char const **feature_lis *feature_list = calloc(1, sizeof(char *)); for (int i = 0; i < reg_list_size; i++) { - if (reg_list[i]->exist == false || reg_list[i]->hidden) + if (!reg_list[i]->exist || reg_list[i]->hidden) continue; if (reg_list[i]->feature @@ -2530,7 +2521,7 @@ static int gdb_generate_target_description(struct target *target, char **tdesc_o int i; for (i = 0; i < reg_list_size; i++) { - if (reg_list[i]->exist == false || reg_list[i]->hidden) + if (!reg_list[i]->exist || reg_list[i]->hidden) continue; if (strcmp(reg_list[i]->feature->name, features[current_feature])) @@ -3089,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"); @@ -3117,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] == ':') { @@ -3231,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"); } @@ -3560,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; @@ -3572,7 +3563,7 @@ static int gdb_fileio_response_packet(struct connection *connection, return ERROR_OK; } -static void gdb_log_callback(void *priv, const char *file, unsigned line, +static void gdb_log_callback(void *priv, const char *file, unsigned int line, const char *function, const char *string) { struct connection *connection = priv; @@ -4003,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; @@ -4034,7 +4026,7 @@ COMMAND_HANDLER(handle_gdb_sync_command) if (!current_gdb_connection) { command_print(CMD, - "gdb_sync command can only be run from within gdb using \"monitor gdb_sync\""); + "gdb sync command can only be run from within gdb using \"monitor gdb sync\""); return ERROR_FAIL; } @@ -4043,7 +4035,6 @@ COMMAND_HANDLER(handle_gdb_sync_command) return ERROR_OK; } -/* daemon configuration command gdb_port */ COMMAND_HANDLER(handle_gdb_port_command) { int retval = CALL_COMMAND_HANDLER(server_pipe_command, &gdb_port); @@ -4090,7 +4081,6 @@ COMMAND_HANDLER(handle_gdb_report_register_access_error) return ERROR_OK; } -/* gdb_breakpoint_override */ COMMAND_HANDLER(handle_gdb_breakpoint_override_command) { if (CMD_ARGC == 0) { @@ -4167,9 +4157,9 @@ out: return retval; } -static const struct command_registration gdb_command_handlers[] = { +static const struct command_registration gdb_subcommand_handlers[] = { { - .name = "gdb_sync", + .name = "sync", .handler = handle_gdb_sync_command, .mode = COMMAND_ANY, .help = "next stepi will return immediately allowing " @@ -4178,7 +4168,7 @@ static const struct command_registration gdb_command_handlers[] = { .usage = "" }, { - .name = "gdb_port", + .name = "port", .handler = handle_gdb_port_command, .mode = COMMAND_CONFIG, .help = "Normally gdb listens to a TCP/IP port. Each subsequent GDB " @@ -4191,35 +4181,35 @@ static const struct command_registration gdb_command_handlers[] = { .usage = "[port_num]", }, { - .name = "gdb_memory_map", + .name = "memory_map", .handler = handle_gdb_memory_map_command, .mode = COMMAND_CONFIG, .help = "enable or disable memory map", .usage = "('enable'|'disable')" }, { - .name = "gdb_flash_program", + .name = "flash_program", .handler = handle_gdb_flash_program_command, .mode = COMMAND_CONFIG, .help = "enable or disable flash program", .usage = "('enable'|'disable')" }, { - .name = "gdb_report_data_abort", + .name = "report_data_abort", .handler = handle_gdb_report_data_abort_command, .mode = COMMAND_CONFIG, .help = "enable or disable reporting data aborts", .usage = "('enable'|'disable')" }, { - .name = "gdb_report_register_access_error", + .name = "report_register_access_error", .handler = handle_gdb_report_register_access_error, .mode = COMMAND_CONFIG, .help = "enable or disable reporting register access errors", .usage = "('enable'|'disable')" }, { - .name = "gdb_breakpoint_override", + .name = "breakpoint_override", .handler = handle_gdb_breakpoint_override_command, .mode = COMMAND_ANY, .help = "Display or specify type of breakpoint " @@ -4227,14 +4217,14 @@ static const struct command_registration gdb_command_handlers[] = { .usage = "('hard'|'soft'|'disable')" }, { - .name = "gdb_target_description", + .name = "target_description", .handler = handle_gdb_target_description_command, .mode = COMMAND_CONFIG, .help = "enable or disable target description", .usage = "('enable'|'disable')" }, { - .name = "gdb_save_tdesc", + .name = "save_tdesc", .handler = handle_gdb_save_tdesc_command, .mode = COMMAND_EXEC, .help = "Save the target description file", @@ -4243,6 +4233,17 @@ static const struct command_registration gdb_command_handlers[] = { COMMAND_REGISTRATION_DONE }; +static const struct command_registration gdb_command_handlers[] = { + { + .name = "gdb", + .mode = COMMAND_ANY, + .help = "GDB commands", + .chain = gdb_subcommand_handlers, + .usage = "", + }, + COMMAND_REGISTRATION_DONE +}; + int gdb_register_commands(struct command_context *cmd_ctx) { gdb_port = strdup("3333"); diff --git a/src/server/gdb_server.h b/src/server/gdb_server.h index 4288ceb..1a626eb 100644 --- a/src/server/gdb_server.h +++ b/src/server/gdb_server.h @@ -28,7 +28,7 @@ int gdb_target_add_all(struct target *target); int gdb_register_commands(struct command_context *command_context); void gdb_service_free(void); -int gdb_put_packet(struct connection *connection, char *buffer, int len); +int gdb_put_packet(struct connection *connection, const char *buffer, int len); int gdb_get_actual_connections(void); diff --git a/src/server/rtt_server.c b/src/server/rtt_server.c index 9769153..b44101c 100644 --- a/src/server/rtt_server.c +++ b/src/server/rtt_server.c @@ -28,6 +28,12 @@ struct rtt_service { char *hello_message; }; +struct rtt_connection_data { + unsigned char buffer[64]; + unsigned int length; + unsigned int offset; +}; + static int read_callback(unsigned int channel, const uint8_t *buffer, size_t length, void *user_data) { @@ -56,7 +62,16 @@ static int rtt_new_connection(struct connection *connection) { int ret; struct rtt_service *service; + struct rtt_connection_data *data; + + data = calloc(1, sizeof(struct rtt_connection_data)); + if (!data) { + LOG_ERROR("Out of memory"); + return ERROR_FAIL; + } + + connection->priv = data; service = connection->service->priv; LOG_DEBUG("rtt: New connection for channel %u", service->channel); @@ -79,31 +94,53 @@ static int rtt_connection_closed(struct connection *connection) service = (struct rtt_service *)connection->service->priv; rtt_unregister_sink(service->channel, &read_callback, connection); - LOG_DEBUG("rtt: Connection for channel %u closed", service->channel); + free(connection->priv); + LOG_DEBUG("rtt: Connection for channel %u closed", service->channel); return ERROR_OK; } static int rtt_input(struct connection *connection) { - int bytes_read; - unsigned char buffer[1024]; struct rtt_service *service; - size_t length; + struct rtt_connection_data *data; - service = (struct rtt_service *)connection->service->priv; - bytes_read = connection_read(connection, buffer, sizeof(buffer)); + data = connection->priv; + service = connection->service->priv; - if (!bytes_read) - return ERROR_SERVER_REMOTE_CLOSED; - else if (bytes_read < 0) { - LOG_ERROR("error during read: %s", strerror(errno)); - return ERROR_SERVER_REMOTE_CLOSED; - } + if (!connection->input_pending) { + int bytes_read; - length = bytes_read; - rtt_write_channel(service->channel, buffer, &length); + bytes_read = connection_read(connection, data->buffer, sizeof(data->buffer)); + + if (!bytes_read) { + return ERROR_SERVER_REMOTE_CLOSED; + } else if (bytes_read < 0) { + LOG_ERROR("error during read: %s", strerror(errno)); + return ERROR_SERVER_REMOTE_CLOSED; + } + data->length = bytes_read; + data->offset = 0; + } + if (data->length > 0) { + unsigned char *ptr; + size_t length, to_write; + + ptr = data->buffer + data->offset; + length = data->length - data->offset; + to_write = length; + rtt_write_channel(service->channel, ptr, &length); + + if (length < to_write) { + data->offset += length; + connection->input_pending = true; + } else { + data->offset = 0; + data->length = 0; + connection->input_pending = false; + } + } return ERROR_OK; } @@ -126,8 +163,10 @@ COMMAND_HANDLER(handle_rtt_start_command) service = calloc(1, sizeof(struct rtt_service)); - if (!service) + if (!service) { + LOG_ERROR("Out of memory"); return ERROR_FAIL; + } COMMAND_PARSE_NUMBER(uint, CMD_ARGV[1], service->channel); diff --git a/src/server/startup.tcl b/src/server/startup.tcl index 1d30b1d..cf3eca3 100644 --- a/src/server/startup.tcl +++ b/src/server/startup.tcl @@ -41,3 +41,81 @@ proc _telnet_autocomplete_helper pattern { return [lsort $cmds] } + +lappend _telnet_autocomplete_skip "gdb_sync" +proc "gdb_sync" {} { + echo "DEPRECATED! use 'gdb sync', not 'gdb_sync'" + eval gdb sync +} + +lappend _telnet_autocomplete_skip "gdb_port" +proc "gdb_port" {args} { + echo "DEPRECATED! use 'gdb port', not 'gdb_port'" + eval gdb port $args +} + +lappend _telnet_autocomplete_skip "gdb_memory_map" +proc "gdb_memory_map" {state} { + echo "DEPRECATED! use 'gdb memory_map', not 'gdb_memory_map'" + eval gdb memory_map $state +} + +lappend _telnet_autocomplete_skip "gdb_flash_program" +proc "gdb_flash_program" {state} { + echo "DEPRECATED! use 'gdb flash_program', not 'gdb_flash_program'" + eval gdb flash_program $state +} + +lappend _telnet_autocomplete_skip "gdb_report_data_abort" +proc "gdb_report_data_abort" {state} { + echo "DEPRECATED! use 'gdb report_data_abort', not 'gdb_report_data_abort'" + eval gdb report_data_abort $state +} + +lappend _telnet_autocomplete_skip "gdb_report_register_access_error" +proc "gdb_report_register_access_error" {state} { + echo "DEPRECATED! use 'gdb report_register_access_error', not 'gdb_report_register_access_error'" + eval gdb report_register_access_error $state +} + +lappend _telnet_autocomplete_skip "gdb_breakpoint_override" +proc "gdb_breakpoint_override" {override} { + echo "DEPRECATED! use 'gdb breakpoint_override', not 'gdb_breakpoint_override'" + eval gdb breakpoint_override $override +} + +lappend _telnet_autocomplete_skip "gdb_target_description" +proc "gdb_target_description" {state} { + echo "DEPRECATED! use 'gdb target_description', not 'gdb_target_description'" + eval gdb target_description $state +} + +lappend _telnet_autocomplete_skip "gdb_save_tdesc" +proc "gdb_save_tdesc" {} { + echo "DEPRECATED! use 'gdb save_tdesc', not 'gdb_save_tdesc'" + eval gdb save_tdesc +} + +lappend _telnet_autocomplete_skip "tcl_port" +proc "tcl_port" {args} { + echo "DEPRECATED! use 'tcl port' not 'tcl_port'" + eval tcl port $args +} + +lappend _telnet_autocomplete_skip "tcl_notifications" +proc "tcl_notifications" {state} { + echo "DEPRECATED! use 'tcl notifications' not 'tcl_notifications'" + eval tcl notifications $state +} + +lappend _telnet_autocomplete_skip "tcl_trace" +proc "tcl_trace" {state} { + echo "DEPRECATED! use 'tcl trace' not 'tcl_trace'" + eval tcl trace $state +} + +lappend _telnet_autocomplete_skip "telnet_port" +proc "telnet_port" {args} { + echo "DEPRECATED! use 'telnet port', not 'telnet_port'" + eval telnet port $args +} diff --git a/src/server/tcl_server.c b/src/server/tcl_server.c index 16cbedc..16cc55e 100644 --- a/src/server/tcl_server.c +++ b/src/server/tcl_server.c @@ -323,25 +323,25 @@ COMMAND_HANDLER(handle_tcl_trace_command) } } -static const struct command_registration tcl_command_handlers[] = { +static const struct command_registration tcl_subcommand_handlers[] = { { - .name = "tcl_port", + .name = "port", .handler = handle_tcl_port_command, .mode = COMMAND_CONFIG, .help = "Specify port on which to listen " "for incoming Tcl syntax. " - "Read help on 'gdb_port'.", + "Read help on 'gdb port'.", .usage = "[port_num]", }, { - .name = "tcl_notifications", + .name = "notifications", .handler = handle_tcl_notifications_command, .mode = COMMAND_EXEC, .help = "Target Notification output", .usage = "[on|off]", }, { - .name = "tcl_trace", + .name = "trace", .handler = handle_tcl_trace_command, .mode = COMMAND_EXEC, .help = "Target trace output", @@ -350,6 +350,17 @@ static const struct command_registration tcl_command_handlers[] = { COMMAND_REGISTRATION_DONE }; +static const struct command_registration tcl_command_handlers[] = { + { + .name = "tcl", + .mode = COMMAND_ANY, + .help = "tcl command group", + .usage = "", + .chain = tcl_subcommand_handlers, + }, + COMMAND_REGISTRATION_DONE +}; + int tcl_register_commands(struct command_context *cmd_ctx) { tcl_port = strdup("6666"); diff --git a/src/server/telnet_server.c b/src/server/telnet_server.c index 938bc5b..2c3f769 100644 --- a/src/server/telnet_server.c +++ b/src/server/telnet_server.c @@ -93,7 +93,7 @@ static int telnet_output(struct command_context *cmd_ctx, const char *line) return telnet_outputline(connection, line); } -static void telnet_log_callback(void *priv, const char *file, unsigned line, +static void telnet_log_callback(void *priv, const char *file, unsigned int line, const char *function, const char *string) { struct connection *connection = priv; @@ -570,7 +570,7 @@ static void telnet_auto_complete(struct connection *connection) struct list_head lh; }; - LIST_HEAD(matches); + OOCD_LIST_HEAD(matches); /* - user command sequence, either at line beginning * or we start over after these characters ';', '[', '{' @@ -967,7 +967,6 @@ int telnet_init(char *banner) return ERROR_OK; } -/* daemon configuration command telnet_port */ COMMAND_HANDLER(handle_telnet_port_command) { return CALL_COMMAND_HANDLER(server_pipe_command, &telnet_port); @@ -978,22 +977,33 @@ COMMAND_HANDLER(handle_exit_command) return ERROR_COMMAND_CLOSE_CONNECTION; } +static const struct command_registration telnet_subcommand_handlers[] = { + { + .name = "port", + .handler = handle_telnet_port_command, + .mode = COMMAND_CONFIG, + .help = "Specify port on which to listen " + "for incoming telnet connections. " + "Read help on 'gdb port'.", + .usage = "[port_num]", + }, + COMMAND_REGISTRATION_DONE +}; + static const struct command_registration telnet_command_handlers[] = { { .name = "exit", .handler = handle_exit_command, - .mode = COMMAND_EXEC, + .mode = COMMAND_ANY, .usage = "", .help = "exit telnet session", }, { - .name = "telnet_port", - .handler = handle_telnet_port_command, + .name = "telnet", + .chain = telnet_subcommand_handlers, .mode = COMMAND_CONFIG, - .help = "Specify port on which to listen " - "for incoming telnet connections. " - "Read help on 'gdb_port'.", - .usage = "[port_num]", + .help = "telnet commands", + .usage = "", }, COMMAND_REGISTRATION_DONE }; diff --git a/src/svf/svf.c b/src/svf/svf.c index dd3d517..ce99468 100644 --- a/src/svf/svf.c +++ b/src/svf/svf.c @@ -75,10 +75,10 @@ static const char *svf_trst_mode_name[4] = { }; struct svf_statemove { - tap_state_t from; - tap_state_t to; + enum tap_state from; + enum tap_state to; uint32_t num_of_moves; - tap_state_t paths[8]; + enum tap_state paths[8]; }; /* @@ -155,10 +155,10 @@ struct svf_xxr_para { struct svf_para { float frequency; - tap_state_t ir_end_state; - tap_state_t dr_end_state; - tap_state_t runtest_run_state; - tap_state_t runtest_end_state; + enum tap_state ir_end_state; + enum tap_state dr_end_state; + enum tap_state runtest_run_state; + enum tap_state runtest_end_state; enum trst_mode trst_mode; struct svf_xxr_para hir_para; @@ -245,7 +245,7 @@ static int svf_last_printed_percentage = -1; #define SVF_BUF_LOG(_lvl, _buf, _nbits, _desc) \ svf_hexbuf_print(LOG_LVL_##_lvl, __FILE__, __LINE__, __func__, _buf, _nbits, _desc) -static void svf_hexbuf_print(int dbg_lvl, const char *file, unsigned line, +static void svf_hexbuf_print(int dbg_lvl, const char *file, unsigned int line, const char *function, const uint8_t *buf, int bit_len, const char *desc) { @@ -313,10 +313,10 @@ static void svf_free_xxd_para(struct svf_xxr_para *para) } } -int svf_add_statemove(tap_state_t state_to) +int svf_add_statemove(enum tap_state state_to) { - tap_state_t state_from = cmd_queue_cur_state; - unsigned index_var; + enum tap_state state_from = cmd_queue_cur_state; + unsigned int index_var; /* when resetting, be paranoid and ignore current state */ if (state_to == TAP_RESET) { @@ -816,7 +816,7 @@ parse_char: return ERROR_OK; } -bool svf_tap_state_is_stable(tap_state_t state) +bool svf_tap_state_is_stable(enum tap_state state) { return (state == TAP_RESET) || (state == TAP_IDLE) || (state == TAP_DRPAUSE) || (state == TAP_IRPAUSE); @@ -932,7 +932,7 @@ static int svf_check_tdo(void) index_var = svf_check_tdo_para[i].buffer_offset; len = svf_check_tdo_para[i].bit_len; if ((svf_check_tdo_para[i].enabled) - && buf_cmp_mask(&svf_tdi_buffer[index_var], &svf_tdo_buffer[index_var], + && !buf_eq_mask(&svf_tdi_buffer[index_var], &svf_tdo_buffer[index_var], &svf_mask_buffer[index_var], len)) { LOG_ERROR("tdo check error at line %d", svf_check_tdo_para[i].line_num); @@ -995,7 +995,7 @@ static int svf_run_command(struct command_context *cmd_ctx, char *cmd_str) uint8_t **pbuffer_tmp; struct scan_field field; /* for STATE */ - tap_state_t *path = NULL, state; + enum tap_state *path = NULL, state; /* flag padding commands skipped due to -tap command */ int padding_command_skipped = 0; @@ -1498,7 +1498,7 @@ xxr_common: } if (num_of_argu > 2) { /* STATE pathstate1 ... stable_state */ - path = malloc((num_of_argu - 1) * sizeof(tap_state_t)); + path = malloc((num_of_argu - 1) * sizeof(enum tap_state)); if (!path) { LOG_ERROR("not enough memory"); return ERROR_FAIL; diff --git a/src/svf/svf.h b/src/svf/svf.h index 74f7d9c..77a0e0d 100644 --- a/src/svf/svf.h +++ b/src/svf/svf.h @@ -23,7 +23,7 @@ int svf_register_commands(struct command_context *cmd_ctx); * SVF specification for single-argument STATE commands (and also used * for various other state transitions). */ -int svf_add_statemove(tap_state_t goal_state); +int svf_add_statemove(enum tap_state goal_state); /** * svf_tap_state_is_stable() returns true for stable non-SHIFT states @@ -31,6 +31,6 @@ int svf_add_statemove(tap_state_t goal_state); * @param state The TAP state in question * @return true iff the state is stable and not a SHIFT state. */ -bool svf_tap_state_is_stable(tap_state_t state); +bool svf_tap_state_is_stable(enum tap_state state); #endif /* OPENOCD_SVF_SVF_H */ diff --git a/src/target/aarch64.c b/src/target/aarch64.c index 6a70b2d..ce7808e 100644 --- a/src/target/aarch64.c +++ b/src/target/aarch64.c @@ -193,6 +193,20 @@ static int aarch64_mmu_modify(struct target *target, int enable) return retval; } +static int aarch64_read_prsr(struct target *target, uint32_t *prsr) +{ + struct armv8_common *armv8 = target_to_armv8(target); + int retval; + + retval = mem_ap_read_atomic_u32(armv8->debug_ap, + armv8->debug_base + CPUV8_DBG_PRSR, prsr); + if (retval != ERROR_OK) + return retval; + + armv8->sticky_reset |= *prsr & PRSR_SR; + return ERROR_OK; +} + /* * Basic debug access, very low level assumes state is saved */ @@ -213,8 +227,7 @@ static int aarch64_init_debug_access(struct target *target) /* Clear Sticky Power Down status Bit in PRSR to enable access to the registers in the Core Power Domain */ - retval = mem_ap_read_atomic_u32(armv8->debug_ap, - armv8->debug_base + CPUV8_DBG_PRSR, &dummy); + retval = aarch64_read_prsr(target, &dummy); if (retval != ERROR_OK) return retval; @@ -281,12 +294,10 @@ static int aarch64_set_dscr_bits(struct target *target, unsigned long bit_mask, static int aarch64_check_state_one(struct target *target, uint32_t mask, uint32_t val, int *p_result, uint32_t *p_prsr) { - struct armv8_common *armv8 = target_to_armv8(target); uint32_t prsr; int retval; - retval = mem_ap_read_atomic_u32(armv8->debug_ap, - armv8->debug_base + CPUV8_DBG_PRSR, &prsr); + retval = aarch64_read_prsr(target, &prsr); if (retval != ERROR_OK) return retval; @@ -506,16 +517,28 @@ static int update_halt_gdb(struct target *target, enum target_debug_reason debug static int aarch64_poll(struct target *target) { + struct armv8_common *armv8 = target_to_armv8(target); enum target_state prev_target_state; int retval = ERROR_OK; - int halted; + uint32_t prsr; - retval = aarch64_check_state_one(target, - PRSR_HALT, PRSR_HALT, &halted, NULL); + retval = aarch64_read_prsr(target, &prsr); if (retval != ERROR_OK) return retval; - if (halted) { + if (armv8->sticky_reset) { + armv8->sticky_reset = false; + if (target->state != TARGET_RESET) { + target->state = TARGET_RESET; + LOG_TARGET_INFO(target, "external reset detected"); + if (armv8->arm.core_cache) { + register_cache_invalidate(armv8->arm.core_cache); + register_cache_invalidate(armv8->arm.core_cache->next); + } + } + } + + if (prsr & PRSR_HALT) { prev_target_state = target->state; if (prev_target_state != TARGET_HALTED) { enum target_debug_reason debug_reason = target->debug_reason; @@ -546,8 +569,11 @@ static int aarch64_poll(struct target *target) break; } } - } else + } else if (prsr & PRSR_RESET) { + target->state = TARGET_RESET; + } else { target->state = TARGET_RUNNING; + } return retval; } @@ -563,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; @@ -576,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; @@ -663,8 +689,7 @@ static int aarch64_prepare_restart_one(struct target *target) if (retval == ERROR_OK) { /* clear sticky bits in PRSR, SDR is now 0 */ - retval = mem_ap_read_atomic_u32(armv8->debug_ap, - armv8->debug_base + CPUV8_DBG_PRSR, &tmp); + retval = aarch64_read_prsr(target, &tmp); } return retval; @@ -728,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; @@ -747,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) { @@ -774,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; @@ -839,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; @@ -1088,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); @@ -1122,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 @@ -1139,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); @@ -2830,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); @@ -2883,9 +2918,9 @@ static int aarch64_jim_configure(struct target *target, struct jim_getopt_info * pc = (struct aarch64_private_config *)target->private_config; if (!pc) { - pc = calloc(1, sizeof(struct aarch64_private_config)); - pc->adiv5_config.ap_num = DP_APSEL_INVALID; - target->private_config = pc; + pc = calloc(1, sizeof(struct aarch64_private_config)); + pc->adiv5_config.ap_num = DP_APSEL_INVALID; + target->private_config = pc; } /* @@ -2915,7 +2950,7 @@ static int aarch64_jim_configure(struct target *target, struct jim_getopt_info * switch (n->value) { case CFG_CTI: { - if (goi->isconfigure) { + if (goi->is_configure) { Jim_Obj *o_cti; struct arm_cti *cti; e = jim_getopt_obj(goi, &o_cti); diff --git a/src/target/adi_v5_jtag.c b/src/target/adi_v5_jtag.c index 8d54a50..c9ed5b9 100644 --- a/src/target/adi_v5_jtag.c +++ b/src/target/adi_v5_jtag.c @@ -431,7 +431,7 @@ static int jtagdp_overrun_check(struct adiv5_dap *dap) struct dap_cmd *el, *tmp, *prev = NULL; int found_wait = 0; int64_t time_now; - LIST_HEAD(replay_list); + OOCD_LIST_HEAD(replay_list); /* make sure all queued transactions are complete */ retval = jtag_execute_queue(); @@ -736,7 +736,7 @@ static int jtag_send_sequence(struct adiv5_dap *dap, enum swd_special_seq seq) return retval; } -static int jtag_dp_q_read(struct adiv5_dap *dap, unsigned reg, +static int jtag_dp_q_read(struct adiv5_dap *dap, unsigned int reg, uint32_t *data) { int retval = jtag_limit_queue_size(dap); @@ -749,7 +749,7 @@ static int jtag_dp_q_read(struct adiv5_dap *dap, unsigned reg, return retval; } -static int jtag_dp_q_write(struct adiv5_dap *dap, unsigned reg, +static int jtag_dp_q_write(struct adiv5_dap *dap, unsigned int reg, uint32_t data) { int retval = jtag_limit_queue_size(dap); @@ -763,7 +763,7 @@ static int jtag_dp_q_write(struct adiv5_dap *dap, unsigned reg, } /** Select the AP register bank */ -static int jtag_ap_q_bankselect(struct adiv5_ap *ap, unsigned reg) +static int jtag_ap_q_bankselect(struct adiv5_ap *ap, unsigned int reg) { int retval; struct adiv5_dap *dap = ap->dap; @@ -818,7 +818,7 @@ static int jtag_ap_q_bankselect(struct adiv5_ap *ap, unsigned reg) return ERROR_OK; } -static int jtag_ap_q_read(struct adiv5_ap *ap, unsigned reg, +static int jtag_ap_q_read(struct adiv5_ap *ap, unsigned int reg, uint32_t *data) { int retval = jtag_limit_queue_size(ap->dap); @@ -840,7 +840,7 @@ static int jtag_ap_q_read(struct adiv5_ap *ap, unsigned reg, return retval; } -static int jtag_ap_q_write(struct adiv5_ap *ap, unsigned reg, +static int jtag_ap_q_write(struct adiv5_ap *ap, unsigned int reg, uint32_t data) { int retval = jtag_limit_queue_size(ap->dap); diff --git a/src/target/adi_v5_swd.c b/src/target/adi_v5_swd.c index 1231005..e50f8f1 100644 --- a/src/target/adi_v5_swd.c +++ b/src/target/adi_v5_swd.c @@ -485,7 +485,7 @@ static int swd_queue_ap_abort(struct adiv5_dap *dap, uint8_t *ack) return check_sync(dap); } -static int swd_queue_dp_read(struct adiv5_dap *dap, unsigned reg, +static int swd_queue_dp_read(struct adiv5_dap *dap, unsigned int reg, uint32_t *data) { int retval = swd_check_reconnect(dap); @@ -499,12 +499,9 @@ static int swd_queue_dp_read(struct adiv5_dap *dap, unsigned reg, return swd_queue_dp_read_inner(dap, reg, data); } -static int swd_queue_dp_write(struct adiv5_dap *dap, unsigned 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; @@ -517,7 +514,7 @@ static int swd_queue_dp_write(struct adiv5_dap *dap, unsigned reg, } /** Select the AP register bank */ -static int swd_queue_ap_bankselect(struct adiv5_ap *ap, unsigned reg) +static int swd_queue_ap_bankselect(struct adiv5_ap *ap, unsigned int reg) { int retval; struct adiv5_dap *dap = ap->dap; @@ -567,7 +564,7 @@ static int swd_queue_ap_bankselect(struct adiv5_ap *ap, unsigned reg) return ERROR_OK; } -static int swd_queue_ap_read(struct adiv5_ap *ap, unsigned reg, +static int swd_queue_ap_read(struct adiv5_ap *ap, unsigned int reg, uint32_t *data) { struct adiv5_dap *dap = ap->dap; @@ -592,7 +589,7 @@ static int swd_queue_ap_read(struct adiv5_ap *ap, unsigned reg, return check_sync(dap); } -static int swd_queue_ap_write(struct adiv5_ap *ap, unsigned reg, +static int swd_queue_ap_write(struct adiv5_ap *ap, unsigned int reg, uint32_t data) { struct adiv5_dap *dap = ap->dap; 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 72e4d91..8757caf 100644 --- a/src/target/arc.c +++ b/src/target/arc.c @@ -61,7 +61,7 @@ static int arc_single_step_core(struct target *target); void arc_reg_data_type_add(struct target *target, struct arc_reg_data_type *data_type) { - LOG_DEBUG("Adding %s reg_data_type", data_type->data_type.id); + LOG_TARGET_DEBUG(target, "Adding %s reg_data_type", data_type->data_type.id); struct arc_common *arc = target_to_arc(target); assert(arc); @@ -104,7 +104,7 @@ static int arc_reset_caches_states(struct target *target) { struct arc_common *arc = target_to_arc(target); - LOG_DEBUG("Resetting internal variables of caches states"); + LOG_TARGET_DEBUG(target, "Resetting internal variables of caches states"); /* Reset caches states. */ arc->dcache_flushed = false; @@ -127,7 +127,7 @@ static int arc_init_arch_info(struct target *target, struct arc_common *arc, /* The only allowed ir_length is 4 for ARC jtag. */ if (tap->ir_length != 4) { - LOG_ERROR("ARC jtag instruction length should be equal to 4"); + LOG_TARGET_ERROR(target, "ARC jtag instruction length should be equal to 4"); return ERROR_FAIL; } @@ -146,7 +146,7 @@ static int arc_init_arch_info(struct target *target, struct arc_common *arc, sizeof(*std_types)); if (!std_types) { - LOG_ERROR("Unable to allocate memory"); + LOG_TARGET_ERROR(target, "Unable to allocate memory"); return ERROR_FAIL; } @@ -205,7 +205,7 @@ int arc_reg_add(struct target *target, struct arc_reg_desc *arc_reg, } arc->num_regs += 1; - LOG_DEBUG( + LOG_TARGET_DEBUG(target, "added register {name=%s, num=0x%" PRIx32 ", type=%s%s%s%s}", arc_reg->name, arc_reg->arch_num, arc_reg->data_type->id, arc_reg->is_core ? ", core" : "", arc_reg->is_bcr ? ", bcr" : "", @@ -227,7 +227,7 @@ static int arc_get_register(struct reg *reg) uint32_t value; if (reg->valid) { - LOG_DEBUG("Get register (cached) gdb_num=%" PRIu32 ", name=%s, value=0x%" PRIx32, + LOG_TARGET_DEBUG(target, "Get register (cached) gdb_num=%" PRIu32 ", name=%s, value=0x%" PRIx32, reg->number, desc->name, target_buffer_get_u32(target, reg->value)); return ERROR_OK; } @@ -235,7 +235,7 @@ static int arc_get_register(struct reg *reg) if (desc->is_core) { /* Accessing to R61/R62 registers causes Jtag hang */ if (desc->arch_num == ARC_R61 || desc->arch_num == ARC_R62) { - LOG_ERROR("It is forbidden to read core registers 61 and 62."); + LOG_TARGET_ERROR(target, "It is forbidden to read core registers 61 and 62"); return ERROR_FAIL; } CHECK_RETVAL(arc_jtag_read_core_reg_one(&arc->jtag_info, desc->arch_num, @@ -255,7 +255,7 @@ static int arc_get_register(struct reg *reg) reg->dirty = false; - LOG_DEBUG("Get register gdb_num=%" PRIu32 ", name=%s, value=0x%" PRIx32, + LOG_TARGET_DEBUG(target, "Get register gdb_num=%" PRIu32 ", name=%s, value=0x%" PRIx32, reg->number, desc->name, value); @@ -276,12 +276,12 @@ static int arc_set_register(struct reg *reg, uint8_t *buf) /* Accessing to R61/R62 registers causes Jtag hang */ if (desc->is_core && (desc->arch_num == ARC_R61 || desc->arch_num == ARC_R62)) { - LOG_ERROR("It is forbidden to write core registers 61 and 62."); + LOG_TARGET_ERROR(target, "It is forbidden to write core registers 61 and 62"); return ERROR_FAIL; } target_buffer_set_u32(target, reg->value, value); - LOG_DEBUG("Set register gdb_num=%" PRIu32 ", name=%s, value=0x%08" PRIx32, + LOG_TARGET_DEBUG(target, "Set register gdb_num=%" PRIu32 ", name=%s, value=0x%08" PRIx32, reg->number, desc->name, value); reg->valid = true; @@ -355,7 +355,7 @@ static int arc_build_reg_cache(struct target *target) struct reg *reg_list = calloc(num_regs, sizeof(*reg_list)); if (!cache || !reg_list) { - LOG_ERROR("Not enough memory"); + LOG_TARGET_ERROR(target, "Not enough memory"); goto fail; } @@ -368,14 +368,14 @@ static int arc_build_reg_cache(struct target *target) (*cache_p) = cache; if (list_empty(&arc->core_reg_descriptions)) { - LOG_ERROR("No core registers were defined"); + LOG_TARGET_ERROR(target, "No core registers were defined"); goto fail; } list_for_each_entry(reg_desc, &arc->core_reg_descriptions, list) { CHECK_RETVAL(arc_init_reg(target, ®_list[i], reg_desc, i)); - LOG_DEBUG("reg n=%3li name=%3s group=%s feature=%s", i, + LOG_TARGET_DEBUG(target, "reg n=%3li name=%3s group=%s feature=%s", i, reg_list[i].name, reg_list[i].group, reg_list[i].feature->name); @@ -383,27 +383,27 @@ static int arc_build_reg_cache(struct target *target) } if (list_empty(&arc->aux_reg_descriptions)) { - LOG_ERROR("No aux registers were defined"); + LOG_TARGET_ERROR(target, "No aux registers were defined"); goto fail; } list_for_each_entry(reg_desc, &arc->aux_reg_descriptions, list) { - CHECK_RETVAL(arc_init_reg(target, ®_list[i], reg_desc, i)); + CHECK_RETVAL(arc_init_reg(target, ®_list[i], reg_desc, i)); - LOG_DEBUG("reg n=%3li name=%3s group=%s feature=%s", i, + LOG_TARGET_DEBUG(target, "reg n=%3li name=%3s group=%s feature=%s", i, reg_list[i].name, reg_list[i].group, reg_list[i].feature->name); /* PC and DEBUG are essential so we search for them. */ if (!strcmp("pc", reg_desc->name)) { if (arc->pc_index_in_cache != ULONG_MAX) { - LOG_ERROR("Double definition of PC in configuration"); + LOG_TARGET_ERROR(target, "Double definition of PC in configuration"); goto fail; } arc->pc_index_in_cache = i; } else if (!strcmp("debug", reg_desc->name)) { if (arc->debug_index_in_cache != ULONG_MAX) { - LOG_ERROR("Double definition of DEBUG in configuration"); + LOG_TARGET_ERROR(target, "Double definition of DEBUG in configuration"); goto fail; } arc->debug_index_in_cache = i; @@ -413,7 +413,7 @@ static int arc_build_reg_cache(struct target *target) if (arc->pc_index_in_cache == ULONG_MAX || arc->debug_index_in_cache == ULONG_MAX) { - LOG_ERROR("`pc' and `debug' registers must be present in target description."); + LOG_TARGET_ERROR(target, "`pc' and `debug' registers must be present in target description"); goto fail; } @@ -446,7 +446,7 @@ static int arc_build_bcr_reg_cache(struct target *target) unsigned long gdb_regnum = arc->core_and_aux_cache->num_regs; if (!cache || !reg_list) { - LOG_ERROR("Unable to allocate memory"); + LOG_TARGET_ERROR(target, "Unable to allocate memory"); goto fail; } @@ -459,17 +459,17 @@ static int arc_build_bcr_reg_cache(struct target *target) (*cache_p) = cache; if (list_empty(&arc->bcr_reg_descriptions)) { - LOG_ERROR("No BCR registers are defined"); + LOG_TARGET_ERROR(target, "No BCR registers are defined"); goto fail; } list_for_each_entry(reg_desc, &arc->bcr_reg_descriptions, list) { - CHECK_RETVAL(arc_init_reg(target, ®_list[i], reg_desc, gdb_regnum)); + CHECK_RETVAL(arc_init_reg(target, ®_list[i], reg_desc, gdb_regnum)); /* BCRs always semantically, they are just read-as-zero, if there is * not real register. */ reg_list[i].exist = true; - LOG_DEBUG("reg n=%3li name=%3s group=%s feature=%s", i, + LOG_TARGET_DEBUG(target, "reg n=%3li name=%3s group=%s feature=%s", i, reg_list[i].name, reg_list[i].group, reg_list[i].feature->name); i += 1; @@ -501,7 +501,7 @@ static int arc_get_gdb_reg_list(struct target *target, struct reg **reg_list[], *reg_list = calloc(*reg_list_size, sizeof(struct reg *)); if (!*reg_list) { - LOG_ERROR("Unable to allocate memory"); + LOG_TARGET_ERROR(target, "Unable to allocate memory"); return ERROR_FAIL; } @@ -516,18 +516,18 @@ static int arc_get_gdb_reg_list(struct target *target, struct reg **reg_list[], unsigned long i = 0; struct reg_cache *reg_cache = target->reg_cache; while (reg_cache) { - for (unsigned j = 0; j < reg_cache->num_regs; j++, i++) + for (unsigned int j = 0; j < reg_cache->num_regs; j++, i++) (*reg_list)[i] = ®_cache->reg_list[j]; reg_cache = reg_cache->next; } assert(i == arc->num_regs); - LOG_DEBUG("REG_CLASS_ALL: number of regs=%i", *reg_list_size); + LOG_TARGET_DEBUG(target, "REG_CLASS_ALL: number of regs=%i", *reg_list_size); } else { unsigned long i = 0; unsigned long gdb_reg_number = 0; struct reg_cache *reg_cache = target->reg_cache; while (reg_cache) { - for (unsigned j = 0; + for (unsigned int j = 0; j < reg_cache->num_regs && gdb_reg_number <= arc->last_general_reg; j++) { if (reg_cache->reg_list[j].exist) { @@ -539,7 +539,7 @@ static int arc_get_gdb_reg_list(struct target *target, struct reg **reg_list[], reg_cache = reg_cache->next; } *reg_list_size = i; - LOG_DEBUG("REG_CLASS_GENERAL: number of regs=%i", *reg_list_size); + LOG_TARGET_DEBUG(target, "REG_CLASS_GENERAL: number of regs=%i", *reg_list_size); } return ERROR_OK; @@ -551,13 +551,13 @@ int arc_reg_get_field(struct target *target, const char *reg_name, { struct reg_data_type_struct_field *field; - LOG_DEBUG("getting register field (reg_name=%s, field_name=%s)", reg_name, field_name); + LOG_TARGET_DEBUG(target, "getting register field (reg_name=%s, field_name=%s)", reg_name, field_name); /* Get register */ struct reg *reg = arc_reg_get_by_name(target->reg_cache, reg_name, true); if (!reg) { - LOG_ERROR("Requested register `%s' doesn't exist.", reg_name); + LOG_TARGET_ERROR(target, "Requested register `%s' doesn't exist", reg_name); return ERROR_ARC_REGISTER_NOT_FOUND; } @@ -597,7 +597,7 @@ int arc_reg_get_field(struct target *target, const char *reg_name, static int arc_get_register_value(struct target *target, const char *reg_name, uint32_t *value_ptr) { - LOG_DEBUG("reg_name=%s", reg_name); + LOG_TARGET_DEBUG(target, "reg_name=%s", reg_name); struct reg *reg = arc_reg_get_by_name(target->reg_cache, reg_name, true); @@ -615,10 +615,10 @@ static int arc_get_register_value(struct target *target, const char *reg_name, static int arc_set_register_value(struct target *target, const char *reg_name, uint32_t value) { - LOG_DEBUG("reg_name=%s value=0x%08" PRIx32, reg_name, value); + LOG_TARGET_DEBUG(target, "reg_name=%s value=0x%08" PRIx32, reg_name, value); if (!(target && reg_name)) { - LOG_ERROR("Arguments cannot be NULL."); + LOG_TARGET_ERROR(target, "Arguments cannot be NULL"); return ERROR_FAIL; } @@ -655,7 +655,7 @@ static int arc_configure_dccm(struct target *target) if (dccm_build_size0 == 0xF) dccm_size <<= dccm_build_size1; arc->dccm_end = arc->dccm_start + dccm_size; - LOG_DEBUG("DCCM detected start=0x%" PRIx32 " end=0x%" PRIx32, + LOG_TARGET_DEBUG(target, "DCCM detected start=0x%" PRIx32 " end=0x%" PRIx32, arc->dccm_start, arc->dccm_end); } @@ -687,7 +687,7 @@ static int arc_configure_iccm(struct target *target) /* iccm0 start is located in highest 4 bits of aux_iccm */ arc->iccm0_start = aux_iccm & 0xF0000000; arc->iccm0_end = arc->iccm0_start + iccm0_size; - LOG_DEBUG("ICCM0 detected start=0x%" PRIx32 " end=0x%" PRIx32, + LOG_TARGET_DEBUG(target, "ICCM0 detected start=0x%" PRIx32 " end=0x%" PRIx32, arc->iccm0_start, arc->iccm0_end); } @@ -707,7 +707,7 @@ static int arc_configure_iccm(struct target *target) iccm1_size <<= iccm_build_size11; arc->iccm1_start = aux_iccm & 0x0F000000; arc->iccm1_end = arc->iccm1_start + iccm1_size; - LOG_DEBUG("ICCM1 detected start=0x%" PRIx32 " end=0x%" PRIx32, + LOG_TARGET_DEBUG(target, "ICCM1 detected start=0x%" PRIx32 " end=0x%" PRIx32, arc->iccm1_start, arc->iccm1_end); } return ERROR_OK; @@ -716,17 +716,17 @@ static int arc_configure_iccm(struct target *target) /* Configure some core features, depending on BCRs. */ static int arc_configure(struct target *target) { - LOG_DEBUG("Configuring ARC ICCM and DCCM"); + LOG_TARGET_DEBUG(target, "Configuring ARC ICCM and DCCM"); /* Configuring DCCM if DCCM_BUILD and AUX_DCCM are known registers. */ - if (arc_reg_get_by_name(target->reg_cache, "dccm_build", true) && - arc_reg_get_by_name(target->reg_cache, "aux_dccm", true)) - CHECK_RETVAL(arc_configure_dccm(target)); + if (arc_reg_get_by_name(target->reg_cache, "dccm_build", true) + && arc_reg_get_by_name(target->reg_cache, "aux_dccm", true)) + CHECK_RETVAL(arc_configure_dccm(target)); /* Configuring ICCM if ICCM_BUILD and AUX_ICCM are known registers. */ - if (arc_reg_get_by_name(target->reg_cache, "iccm_build", true) && - arc_reg_get_by_name(target->reg_cache, "aux_iccm", true)) - CHECK_RETVAL(arc_configure_iccm(target)); + if (arc_reg_get_by_name(target->reg_cache, "iccm_build", true) + && arc_reg_get_by_name(target->reg_cache, "aux_iccm", true)) + CHECK_RETVAL(arc_configure_iccm(target)); return ERROR_OK; } @@ -770,9 +770,9 @@ static int arc_exit_debug(struct target *target) CHECK_RETVAL(target_call_event_callbacks(target, TARGET_EVENT_HALTED)); if (debug_level >= LOG_LVL_DEBUG) { - LOG_DEBUG("core stopped (halted) debug-reg: 0x%08" PRIx32, value); + LOG_TARGET_DEBUG(target, "core stopped (halted) debug-reg: 0x%08" PRIx32, value); CHECK_RETVAL(arc_jtag_read_aux_reg_one(&arc->jtag_info, AUX_STATUS32_REG, &value)); - LOG_DEBUG("core STATUS32: 0x%08" PRIx32, value); + LOG_TARGET_DEBUG(target, "core STATUS32: 0x%08" PRIx32, value); } return ERROR_OK; @@ -783,19 +783,19 @@ static int arc_halt(struct target *target) uint32_t value, irq_state; struct arc_common *arc = target_to_arc(target); - LOG_DEBUG("target->state: %s", target_state_name(target)); + LOG_TARGET_DEBUG(target, "target->state: %s", target_state_name(target)); if (target->state == TARGET_HALTED) { - LOG_DEBUG("target was already halted"); + LOG_TARGET_DEBUG(target, "target was already halted"); return ERROR_OK; } if (target->state == TARGET_UNKNOWN) - LOG_WARNING("target was in unknown state when halt was requested"); + LOG_TARGET_WARNING(target, "target was in unknown state when halt was requested"); if (target->state == TARGET_RESET) { if ((jtag_get_reset_config() & RESET_SRST_PULLS_TRST) && jtag_get_srst()) { - LOG_ERROR("can't request a halt while in reset if nSRST pulls nTRST"); + LOG_TARGET_ERROR(target, "can't request a halt while in reset if nSRST pulls nTRST"); return ERROR_TARGET_FAILURE; } else { target->debug_reason = DBG_REASON_DBGRQ; @@ -825,9 +825,9 @@ static int arc_halt(struct target *target) /* some more debug information */ if (debug_level >= LOG_LVL_DEBUG) { - LOG_DEBUG("core stopped (halted) DEGUB-REG: 0x%08" PRIx32, value); + LOG_TARGET_DEBUG(target, "core stopped (halted) DEGUB-REG: 0x%08" PRIx32, value); CHECK_RETVAL(arc_get_register_value(target, "status32", &value)); - LOG_DEBUG("core STATUS32: 0x%08" PRIx32, value); + LOG_TARGET_DEBUG(target, "core STATUS32: 0x%08" PRIx32, value); } return ERROR_OK; @@ -846,7 +846,7 @@ static int arc_save_context(struct target *target) struct arc_common *arc = target_to_arc(target); struct reg *reg_list = arc->core_and_aux_cache->reg_list; - LOG_DEBUG("Saving aux and core registers values"); + LOG_TARGET_DEBUG(target, "Saving aux and core registers values"); assert(reg_list); /* It is assumed that there is at least one AUX register in the list, for @@ -865,7 +865,7 @@ static int arc_save_context(struct target *target) unsigned int aux_cnt = 0; if (!core_values || !core_addrs || !aux_values || !aux_addrs) { - LOG_ERROR("Unable to allocate memory"); + LOG_TARGET_ERROR(target, "Unable to allocate memory"); retval = ERROR_FAIL; goto exit; } @@ -893,7 +893,7 @@ static int arc_save_context(struct target *target) if (core_cnt > 0) { retval = arc_jtag_read_core_reg(&arc->jtag_info, core_addrs, core_cnt, core_values); if (retval != ERROR_OK) { - LOG_ERROR("Attempt to read core registers failed."); + LOG_TARGET_ERROR(target, "Attempt to read core registers failed"); retval = ERROR_FAIL; goto exit; } @@ -901,7 +901,7 @@ static int arc_save_context(struct target *target) if (aux_cnt > 0) { retval = arc_jtag_read_aux_reg(&arc->jtag_info, aux_addrs, aux_cnt, aux_values); if (retval != ERROR_OK) { - LOG_ERROR("Attempt to read aux registers failed."); + LOG_TARGET_ERROR(target, "Attempt to read aux registers failed"); retval = ERROR_FAIL; goto exit; } @@ -916,7 +916,7 @@ static int arc_save_context(struct target *target) target_buffer_set_u32(target, reg->value, core_values[core_cnt]); reg->valid = true; reg->dirty = false; - LOG_DEBUG("Get core register regnum=%u, name=%s, value=0x%08" PRIx32, + LOG_TARGET_DEBUG(target, "Get core register regnum=%u, name=%s, value=0x%08" PRIx32, i, arc_reg->name, core_values[core_cnt]); core_cnt++; } @@ -931,7 +931,7 @@ static int arc_save_context(struct target *target) target_buffer_set_u32(target, reg->value, aux_values[aux_cnt]); reg->valid = true; reg->dirty = false; - LOG_DEBUG("Get aux register regnum=%u, name=%s, value=0x%08" PRIx32, + LOG_TARGET_DEBUG(target, "Get aux register regnum=%u, name=%s, value=0x%08" PRIx32, i, arc_reg->name, aux_values[aux_cnt]); aux_cnt++; } @@ -1009,14 +1009,14 @@ static int arc_examine_debug_reason(struct target *target) if (actionpoint) { if (!actionpoint->used) - LOG_WARNING("Target halted by an unused actionpoint."); + LOG_TARGET_WARNING(target, "Target halted by an unused actionpoint"); if (actionpoint->type == ARC_AP_BREAKPOINT) target->debug_reason = DBG_REASON_BREAKPOINT; else if (actionpoint->type == ARC_AP_WATCHPOINT) target->debug_reason = DBG_REASON_WATCHPOINT; else - LOG_WARNING("Unknown type of actionpoint."); + LOG_TARGET_WARNING(target, "Unknown type of actionpoint"); } } @@ -1046,7 +1046,7 @@ static int arc_poll(struct target *target) /* check for processor halted */ if (status & ARC_JTAG_STAT_RU) { if (target->state != TARGET_RUNNING) { - LOG_WARNING("target is still running!"); + LOG_TARGET_WARNING(target, "target is still running"); target->state = TARGET_RUNNING; } return ERROR_OK; @@ -1057,21 +1057,19 @@ static int arc_poll(struct target *target) if ((target->state == TARGET_RUNNING) || (target->state == TARGET_RESET)) { CHECK_RETVAL(arc_get_register_value(target, "status32", &value)); if (value & AUX_STATUS32_REG_HALT_BIT) { - LOG_DEBUG("ARC core in halt or reset state."); + LOG_TARGET_DEBUG(target, "ARC core in halt or reset state"); /* Save context if target was not in reset state */ if (target->state == TARGET_RUNNING) CHECK_RETVAL(arc_debug_entry(target)); target->state = TARGET_HALTED; CHECK_RETVAL(target_call_event_callbacks(target, TARGET_EVENT_HALTED)); } else { - LOG_DEBUG("Discrepancy of STATUS32[0] HALT bit and ARC_JTAG_STAT_RU, " + LOG_TARGET_DEBUG(target, "Discrepancy of STATUS32[0] HALT bit and ARC_JTAG_STAT_RU, " "target is still running"); } - } else if (target->state == TARGET_DEBUG_RUNNING) { - target->state = TARGET_HALTED; - LOG_DEBUG("ARC core is in debug running mode"); + LOG_TARGET_DEBUG(target, "ARC core is in debug running mode"); CHECK_RETVAL(arc_debug_entry(target)); @@ -1087,7 +1085,7 @@ static int arc_assert_reset(struct target *target) enum reset_types jtag_reset_config = jtag_get_reset_config(); bool srst_asserted = false; - LOG_DEBUG("target->state: %s", target_state_name(target)); + LOG_TARGET_DEBUG(target, "target->state: %s", target_state_name(target)); if (target_has_event_action(target, TARGET_EVENT_RESET_ASSERT)) { /* allow scripts to override the reset event */ @@ -1101,8 +1099,8 @@ static int arc_assert_reset(struct target *target) if (target->state == TARGET_HALTED && !target->reset_halt) { /* Resume the target and continue from the current * PC register value. */ - LOG_DEBUG("Starting CPU execution after reset"); - CHECK_RETVAL(target_resume(target, 1, 0, 0, 0)); + LOG_TARGET_DEBUG(target, "Starting CPU execution after reset"); + CHECK_RETVAL(target_resume(target, true, 0, false, false)); } target->state = TARGET_RESET; @@ -1138,7 +1136,7 @@ static int arc_assert_reset(struct target *target) static int arc_deassert_reset(struct target *target) { - LOG_DEBUG("target->state: %s", target_state_name(target)); + LOG_TARGET_DEBUG(target, "target->state: %s", target_state_name(target)); /* deassert reset lines */ jtag_add_reset(0, 0); @@ -1155,7 +1153,7 @@ static int arc_arch_state(struct target *target) CHECK_RETVAL(arc_get_register_value(target, "pc", &pc_value)); - LOG_DEBUG("target state: %s; PC at: 0x%08" PRIx32, + LOG_TARGET_DEBUG(target, "target state: %s; PC at: 0x%08" PRIx32, target_state_name(target), pc_value); @@ -1174,7 +1172,7 @@ static int arc_restore_context(struct target *target) struct arc_common *arc = target_to_arc(target); struct reg *reg_list = arc->core_and_aux_cache->reg_list; - LOG_DEBUG("Restoring registers values"); + LOG_TARGET_DEBUG(target, "Restoring registers values"); assert(reg_list); const uint32_t core_regs_size = arc->num_core_regs * sizeof(uint32_t); @@ -1187,7 +1185,7 @@ static int arc_restore_context(struct target *target) unsigned int aux_cnt = 0; if (!core_values || !core_addrs || !aux_values || !aux_addrs) { - LOG_ERROR("Unable to allocate memory"); + LOG_TARGET_ERROR(target, "Unable to allocate memory"); retval = ERROR_FAIL; goto exit; } @@ -1201,7 +1199,7 @@ static int arc_restore_context(struct target *target) struct reg *reg = &(reg_list[i]); struct arc_reg_desc *arc_reg = reg->arch_info; if (reg->valid && reg->exist && reg->dirty) { - LOG_DEBUG("Will write regnum=%u", i); + LOG_TARGET_DEBUG(target, "Will write regnum=%u", i); core_addrs[core_cnt] = arc_reg->arch_num; core_values[core_cnt] = target_buffer_get_u32(target, reg->value); core_cnt += 1; @@ -1212,7 +1210,7 @@ static int arc_restore_context(struct target *target) struct reg *reg = &(reg_list[arc->num_core_regs + i]); struct arc_reg_desc *arc_reg = reg->arch_info; if (reg->valid && reg->exist && reg->dirty) { - LOG_DEBUG("Will write regnum=%lu", arc->num_core_regs + i); + LOG_TARGET_DEBUG(target, "Will write regnum=%lu", arc->num_core_regs + i); aux_addrs[aux_cnt] = arc_reg->arch_num; aux_values[aux_cnt] = target_buffer_get_u32(target, reg->value); aux_cnt += 1; @@ -1224,7 +1222,7 @@ static int arc_restore_context(struct target *target) if (core_cnt > 0) { retval = arc_jtag_write_core_reg(&arc->jtag_info, core_addrs, core_cnt, core_values); if (retval != ERROR_OK) { - LOG_ERROR("Attempt to write to core registers failed."); + LOG_TARGET_ERROR(target, "Attempt to write to core registers failed"); retval = ERROR_FAIL; goto exit; } @@ -1233,7 +1231,7 @@ static int arc_restore_context(struct target *target) if (aux_cnt > 0) { retval = arc_jtag_write_aux_reg(&arc->jtag_info, aux_addrs, aux_cnt, aux_values); if (retval != ERROR_OK) { - LOG_ERROR("Attempt to write to aux registers failed."); + LOG_TARGET_ERROR(target, "Attempt to write to aux registers failed"); retval = ERROR_FAIL; goto exit; } @@ -1248,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; @@ -1260,26 +1258,26 @@ static int arc_enable_interrupts(struct target *target, int enable) /* enable interrupts */ value |= SET_CORE_ENABLE_INTERRUPTS; CHECK_RETVAL(arc_jtag_write_aux_reg_one(&arc->jtag_info, AUX_STATUS32_REG, value)); - LOG_DEBUG("interrupts enabled"); + LOG_TARGET_DEBUG(target, "interrupts enabled"); } else { /* disable interrupts */ value &= ~SET_CORE_ENABLE_INTERRUPTS; CHECK_RETVAL(arc_jtag_write_aux_reg_one(&arc->jtag_info, AUX_STATUS32_REG, value)); - LOG_DEBUG("interrupts disabled"); + LOG_TARGET_DEBUG(target, "interrupts disabled"); } 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; uint32_t value; struct reg *pc = &arc->core_and_aux_cache->reg_list[arc->pc_index_in_cache]; - LOG_DEBUG("current:%i, address:0x%08" TARGET_PRIxADDR ", handle_breakpoints:%i," + LOG_TARGET_DEBUG(target, "current:%i, address:0x%08" TARGET_PRIxADDR ", handle_breakpoints:%i," " debug_execution:%i", current, address, handle_breakpoints, debug_execution); /* We need to reset ARC cache variables so caches @@ -1299,12 +1297,12 @@ 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; pc->valid = true; - LOG_DEBUG("Changing the value of current PC to 0x%08" TARGET_PRIxADDR, address); + LOG_TARGET_DEBUG(target, "Changing the value of current PC to 0x%08" TARGET_PRIxADDR, address); } if (!current) @@ -1314,13 +1312,13 @@ static int arc_resume(struct target *target, int current, target_addr_t address, CHECK_RETVAL(arc_restore_context(target)); - LOG_DEBUG("Target resumes from PC=0x%" PRIx32 ", pc.dirty=%i, pc.valid=%i", + LOG_TARGET_DEBUG(target, "Target resumes from PC=0x%" PRIx32 ", pc.dirty=%i, pc.valid=%i", resume_pc, pc->dirty, pc->valid); /* check if GDB tells to set our PC where to continue from */ if (pc->valid && resume_pc == target_buffer_get_u32(target, pc->value)) { value = target_buffer_get_u32(target, pc->value); - LOG_DEBUG("resume Core (when start-core) with PC @:0x%08" PRIx32, value); + LOG_TARGET_DEBUG(target, "resume Core (when start-core) with PC @:0x%08" PRIx32, value); CHECK_RETVAL(arc_jtag_write_aux_reg_one(&arc->jtag_info, AUX_PC_REG, value)); } @@ -1329,7 +1327,7 @@ static int arc_resume(struct target *target, int current, target_addr_t address, /* Single step past breakpoint at current address */ struct breakpoint *breakpoint = breakpoint_find(target, resume_pc); if (breakpoint) { - LOG_DEBUG("skipping past breakpoint at 0x%08" TARGET_PRIxADDR, + LOG_TARGET_DEBUG(target, "skipping past breakpoint at 0x%08" TARGET_PRIxADDR, breakpoint->address); CHECK_RETVAL(arc_unset_breakpoint(target, breakpoint)); CHECK_RETVAL(arc_single_step_core(target)); @@ -1350,7 +1348,7 @@ static int arc_resume(struct target *target, int current, target_addr_t address, CHECK_RETVAL(arc_jtag_read_aux_reg_one(&arc->jtag_info, AUX_STATUS32_REG, &value)); value &= ~SET_CORE_HALT_BIT; /* clear the HALT bit */ CHECK_RETVAL(arc_jtag_write_aux_reg_one(&arc->jtag_info, AUX_STATUS32_REG, value)); - LOG_DEBUG("Core started to run"); + LOG_TARGET_DEBUG(target, "Core started to run"); /* registers are now invalid */ register_cache_invalidate(arc->core_and_aux_cache); @@ -1358,11 +1356,11 @@ static int arc_resume(struct target *target, int current, target_addr_t address, if (!debug_execution) { target->state = TARGET_RUNNING; CHECK_RETVAL(target_call_event_callbacks(target, TARGET_EVENT_RESUMED)); - LOG_DEBUG("target resumed at 0x%08" PRIx32, resume_pc); + LOG_TARGET_DEBUG(target, "target resumed at 0x%08" PRIx32, resume_pc); } else { target->state = TARGET_DEBUG_RUNNING; CHECK_RETVAL(target_call_event_callbacks(target, TARGET_EVENT_DEBUG_RESUMED)); - LOG_DEBUG("target debug resumed at 0x%08" PRIx32, resume_pc); + LOG_TARGET_DEBUG(target, "target debug resumed at 0x%08" PRIx32, resume_pc); } return ERROR_OK; @@ -1386,7 +1384,7 @@ static void arc_deinit_target(struct target *target) { struct arc_common *arc = target_to_arc(target); - LOG_DEBUG("deinitialization of target"); + LOG_TARGET_DEBUG(target, "deinitialization of target"); if (arc->core_aux_cache_built) arc_free_reg_cache(arc->core_and_aux_cache); if (arc->bcr_cache_built) @@ -1431,11 +1429,11 @@ static int arc_target_create(struct target *target, Jim_Interp *interp) struct arc_common *arc = calloc(1, sizeof(*arc)); if (!arc) { - LOG_ERROR("Unable to allocate memory"); + LOG_TARGET_ERROR(target, "Unable to allocate memory"); return ERROR_FAIL; } - LOG_DEBUG("Entering"); + LOG_TARGET_DEBUG(target, "Entering"); CHECK_RETVAL(arc_init_arch_info(target, arc, target->tap)); return ERROR_OK; @@ -1452,11 +1450,11 @@ static int arc_write_instruction_u32(struct target *target, uint32_t address, { uint8_t value_buf[4]; if (!target_was_examined(target)) { - LOG_ERROR("Target not examined yet"); + LOG_TARGET_ERROR(target, "Target not examined yet"); return ERROR_FAIL; } - LOG_DEBUG("Address: 0x%08" PRIx32 ", value: 0x%08" PRIx32, address, + LOG_TARGET_DEBUG(target, "Address: 0x%08" PRIx32 ", value: 0x%08" PRIx32, address, instr); if (target->endianness == TARGET_LITTLE_ENDIAN) @@ -1480,7 +1478,7 @@ static int arc_read_instruction_u32(struct target *target, uint32_t address, uint8_t value_buf[4]; if (!target_was_examined(target)) { - LOG_ERROR("Target not examined yet"); + LOG_TARGET_ERROR(target, "Target not examined yet"); return ERROR_FAIL; } @@ -1492,7 +1490,7 @@ static int arc_read_instruction_u32(struct target *target, uint32_t address, else *value = be_to_h_u32(value_buf); - LOG_DEBUG("Address: 0x%08" PRIx32 ", value: 0x%08" PRIx32, address, + LOG_TARGET_DEBUG(target, "Address: 0x%08" PRIx32 ", value: 0x%08" PRIx32, address, *value); return ERROR_OK; @@ -1513,7 +1511,7 @@ static int arc_configure_actionpoint(struct target *target, uint32_t ap_num, if (control_tt != AP_AC_TT_DISABLE) { if (arc->actionpoints_num_avail < 1) { - LOG_ERROR("No free actionpoints, maximum amount is %u", + LOG_TARGET_ERROR(target, "No free actionpoints, maximum amount is %u", arc->actionpoints_num); return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; } @@ -1547,12 +1545,12 @@ static int arc_set_breakpoint(struct target *target, struct breakpoint *breakpoint) { if (breakpoint->is_set) { - LOG_WARNING("breakpoint already set"); + LOG_TARGET_WARNING(target, "breakpoint already set"); return ERROR_OK; } if (breakpoint->type == BKPT_SOFT) { - LOG_DEBUG("bpid: %" PRIu32, breakpoint->unique_id); + LOG_TARGET_DEBUG(target, "bpid: %" PRIu32, breakpoint->unique_id); if (breakpoint->length == 4) { uint32_t verify = 0xffffffff; @@ -1566,7 +1564,7 @@ static int arc_set_breakpoint(struct target *target, CHECK_RETVAL(arc_read_instruction_u32(target, breakpoint->address, &verify)); if (verify != ARC_SDBBP_32) { - LOG_ERROR("Unable to set 32bit breakpoint at address @0x%" TARGET_PRIxADDR + LOG_TARGET_ERROR(target, "Unable to set 32bit breakpoint at address @0x%" TARGET_PRIxADDR " - check that memory is read/writable", breakpoint->address); return ERROR_FAIL; } @@ -1579,12 +1577,12 @@ static int arc_set_breakpoint(struct target *target, CHECK_RETVAL(target_read_u16(target, breakpoint->address, &verify)); if (verify != ARC_SDBBP_16) { - LOG_ERROR("Unable to set 16bit breakpoint at address @0x%" TARGET_PRIxADDR + LOG_TARGET_ERROR(target, "Unable to set 16bit breakpoint at address @0x%" TARGET_PRIxADDR " - check that memory is read/writable", breakpoint->address); return ERROR_FAIL; } } else { - LOG_ERROR("Invalid breakpoint length: target supports only 2 or 4"); + LOG_TARGET_ERROR(target, "Invalid breakpoint length: target supports only 2 or 4"); return ERROR_COMMAND_ARGUMENT_INVALID; } @@ -1600,7 +1598,7 @@ static int arc_set_breakpoint(struct target *target, } if (bp_num >= arc->actionpoints_num) { - LOG_ERROR("No free actionpoints, maximum amount is %u", + LOG_TARGET_ERROR(target, "No free actionpoints, maximum amount is %u", arc->actionpoints_num); return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; } @@ -1614,12 +1612,12 @@ static int arc_set_breakpoint(struct target *target, ap_list[bp_num].bp_value = breakpoint->address; ap_list[bp_num].type = ARC_AP_BREAKPOINT; - LOG_DEBUG("bpid: %" PRIu32 ", bp_num %u bp_value 0x%" PRIx32, + LOG_TARGET_DEBUG(target, "bpid: %" PRIu32 ", bp_num %u bp_value 0x%" PRIx32, breakpoint->unique_id, bp_num, ap_list[bp_num].bp_value); } } else { - LOG_DEBUG("ERROR: setting unknown breakpoint type"); + LOG_TARGET_ERROR(target, "setting unknown breakpoint type"); return ERROR_FAIL; } @@ -1632,13 +1630,13 @@ static int arc_unset_breakpoint(struct target *target, int retval = ERROR_OK; if (!breakpoint->is_set) { - LOG_WARNING("breakpoint not set"); + LOG_TARGET_WARNING(target, "breakpoint not set"); return ERROR_OK; } if (breakpoint->type == BKPT_SOFT) { /* restore original instruction (kept in target endianness) */ - LOG_DEBUG("bpid: %" PRIu32, breakpoint->unique_id); + LOG_TARGET_DEBUG(target, "bpid: %" PRIu32, breakpoint->unique_id); if (breakpoint->length == 4) { uint32_t current_instr; @@ -1651,7 +1649,7 @@ static int arc_unset_breakpoint(struct target *target, if (retval != ERROR_OK) return retval; } else { - LOG_WARNING("Software breakpoint @0x%" TARGET_PRIxADDR + LOG_TARGET_WARNING(target, "Software breakpoint @0x%" TARGET_PRIxADDR " has been overwritten outside of debugger." "Expected: @0x%x, got: @0x%" PRIx32, breakpoint->address, ARC_SDBBP_32, current_instr); @@ -1667,24 +1665,24 @@ static int arc_unset_breakpoint(struct target *target, if (retval != ERROR_OK) return retval; } else { - LOG_WARNING("Software breakpoint @0x%" TARGET_PRIxADDR + LOG_TARGET_WARNING(target, "Software breakpoint @0x%" TARGET_PRIxADDR " has been overwritten outside of debugger. " "Expected: 0x%04x, got: 0x%04" PRIx16, breakpoint->address, ARC_SDBBP_16, current_instr); } } else { - LOG_ERROR("Invalid breakpoint length: target supports only 2 or 4"); + LOG_TARGET_ERROR(target, "Invalid breakpoint length: target supports only 2 or 4"); return ERROR_COMMAND_ARGUMENT_INVALID; } breakpoint->is_set = false; - } else if (breakpoint->type == BKPT_HARD) { + } else if (breakpoint->type == BKPT_HARD) { struct arc_common *arc = target_to_arc(target); struct arc_actionpoint *ap_list = arc->actionpoints_list; unsigned int bp_num = breakpoint->number; if (bp_num >= arc->actionpoints_num) { - LOG_DEBUG("Invalid actionpoint ID: %u in breakpoint: %" PRIu32, + LOG_TARGET_DEBUG(target, "Invalid actionpoint ID: %u in breakpoint: %" PRIu32, bp_num, breakpoint->unique_id); return ERROR_OK; } @@ -1697,12 +1695,12 @@ static int arc_unset_breakpoint(struct target *target, ap_list[bp_num].used = 0; ap_list[bp_num].bp_value = 0; - LOG_DEBUG("bpid: %" PRIu32 " - released actionpoint ID: %u", + LOG_TARGET_DEBUG(target, "bpid: %" PRIu32 " - released actionpoint ID: %u", breakpoint->unique_id, bp_num); } } else { - LOG_DEBUG("ERROR: unsetting unknown breakpoint type"); - return ERROR_FAIL; + LOG_TARGET_ERROR(target, "unsetting unknown breakpoint type"); + return ERROR_FAIL; } return retval; @@ -1775,7 +1773,7 @@ static void arc_reset_actionpoints(struct target *target) int arc_set_actionpoints_num(struct target *target, uint32_t ap_num) { - LOG_DEBUG("target=%s actionpoints=%" PRIu32, target_name(target), ap_num); + LOG_TARGET_DEBUG(target, "actionpoints=%" PRIu32, ap_num); struct arc_common *arc = target_to_arc(target); /* Make sure that there are no enabled actionpoints in target. */ @@ -1790,7 +1788,7 @@ int arc_set_actionpoints_num(struct target *target, uint32_t ap_num) arc->actionpoints_list = calloc(ap_num, sizeof(struct arc_actionpoint)); if (!arc->actionpoints_list) { - LOG_ERROR("Unable to allocate memory"); + LOG_TARGET_ERROR(target, "Unable to allocate memory"); return ERROR_FAIL; } return ERROR_OK; @@ -1813,7 +1811,7 @@ int arc_add_auxreg_actionpoint(struct target *target, ap_num++; if (ap_num >= arc->actionpoints_num) { - LOG_ERROR("No actionpoint free, maximum amount is %u", + LOG_TARGET_ERROR(target, "No actionpoint free, maximum amount is %u", arc->actionpoints_num); return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; } @@ -1858,7 +1856,7 @@ int arc_remove_auxreg_actionpoint(struct target *target, uint32_t auxreg_addr) ap_list[ap_num].bp_value = 0; } } else { - LOG_ERROR("Register actionpoint not found"); + LOG_TARGET_ERROR(target, "Register actionpoint not found"); } return retval; } @@ -1872,7 +1870,7 @@ static int arc_set_watchpoint(struct target *target, struct arc_actionpoint *ap_list = arc->actionpoints_list; if (watchpoint->is_set) { - LOG_WARNING("watchpoint already set"); + LOG_TARGET_WARNING(target, "watchpoint already set"); return ERROR_OK; } @@ -1882,13 +1880,13 @@ static int arc_set_watchpoint(struct target *target, } if (wp_num >= arc->actionpoints_num) { - LOG_ERROR("No free actionpoints, maximum amount is %u", + LOG_TARGET_ERROR(target, "No free actionpoints, maximum amount is %u", arc->actionpoints_num); return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; } if (watchpoint->length != 4) { - LOG_ERROR("Only watchpoints of length 4 are supported"); + LOG_TARGET_ERROR(target, "Only watchpoints of length 4 are supported"); return ERROR_TARGET_UNALIGNED_ACCESS; } @@ -1904,7 +1902,7 @@ static int arc_set_watchpoint(struct target *target, enable = AP_AC_TT_READWRITE; break; default: - LOG_ERROR("BUG: watchpoint->rw neither read, write nor access"); + LOG_TARGET_ERROR(target, "BUG: watchpoint->rw neither read, write nor access"); return ERROR_FAIL; } @@ -1917,7 +1915,7 @@ static int arc_set_watchpoint(struct target *target, ap_list[wp_num].bp_value = watchpoint->address; ap_list[wp_num].type = ARC_AP_WATCHPOINT; - LOG_DEBUG("wpid: %" PRIu32 ", wp_num %u wp_value 0x%" PRIx32, + LOG_TARGET_DEBUG(target, "wpid: %" PRIu32 ", wp_num %u wp_value 0x%" PRIx32, watchpoint->unique_id, wp_num, ap_list[wp_num].bp_value); } @@ -1932,13 +1930,13 @@ static int arc_unset_watchpoint(struct target *target, struct arc_actionpoint *ap_list = arc->actionpoints_list; if (!watchpoint->is_set) { - LOG_WARNING("watchpoint not set"); + LOG_TARGET_WARNING(target, "watchpoint not set"); return ERROR_OK; } unsigned int wp_num = watchpoint->number; if (wp_num >= arc->actionpoints_num) { - LOG_DEBUG("Invalid actionpoint ID: %u in watchpoint: %" PRIu32, + LOG_TARGET_DEBUG(target, "Invalid actionpoint ID: %u in watchpoint: %" PRIu32, wp_num, watchpoint->unique_id); return ERROR_OK; } @@ -1951,7 +1949,7 @@ static int arc_unset_watchpoint(struct target *target, ap_list[wp_num].used = 0; ap_list[wp_num].bp_value = 0; - LOG_DEBUG("wpid: %" PRIu32 " - releasing actionpoint ID: %u", + LOG_TARGET_DEBUG(target, "wpid: %" PRIu32 " - releasing actionpoint ID: %u", watchpoint->unique_id, wp_num); } @@ -2009,18 +2007,18 @@ static int arc_hit_watchpoint(struct target *target, struct watchpoint **hit_wat if (actionpoint) { if (!actionpoint->used) - LOG_WARNING("Target halted by unused actionpoint."); + LOG_TARGET_WARNING(target, "Target halted by unused actionpoint"); /* If this check fails - that is some sort of an error in OpenOCD. */ if (actionpoint->type != ARC_AP_WATCHPOINT) - LOG_WARNING("Target halted by breakpoint, but is treated as a watchpoint."); + LOG_TARGET_WARNING(target, "Target halted by breakpoint, but is treated as a watchpoint"); for (struct watchpoint *watchpoint = target->watchpoints; watchpoint; watchpoint = watchpoint->next) { if (actionpoint->bp_value == watchpoint->address) { *hit_watchpoint = watchpoint; - LOG_DEBUG("Hit watchpoint, wpid: %" PRIu32 ", watchpoint num: %u", + LOG_TARGET_DEBUG(target, "Hit watchpoint, wpid: %" PRIu32 ", watchpoint num: %u", watchpoint->unique_id, watchpoint->number); return ERROR_OK; } @@ -2032,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; @@ -2045,7 +2043,7 @@ static int arc_config_step(struct target *target, int enable_step) value &= ~SET_CORE_AE_BIT; /* clear the AE bit */ CHECK_RETVAL(arc_jtag_write_aux_reg_one(&arc->jtag_info, AUX_STATUS32_REG, value)); - LOG_DEBUG(" [status32:0x%08" PRIx32 "]", value); + LOG_TARGET_DEBUG(target, " [status32:0x%08" PRIx32 "]", value); /* Doing read-modify-write, because DEBUG might contain manually set * bits like UB or ED, which should be preserved. */ @@ -2054,7 +2052,7 @@ static int arc_config_step(struct target *target, int enable_step) value |= SET_CORE_SINGLE_INSTR_STEP; /* set the IS bit */ CHECK_RETVAL(arc_jtag_write_aux_reg_one(&arc->jtag_info, AUX_DEBUG_REG, value)); - LOG_DEBUG("core debug step mode enabled [debug-reg:0x%08" PRIx32 "]", value); + LOG_TARGET_DEBUG(target, "core debug step mode enabled [debug-reg:0x%08" PRIx32 "]", value); } else { /* disable core debug step mode */ CHECK_RETVAL(arc_jtag_read_aux_reg_one(&arc->jtag_info, AUX_DEBUG_REG, @@ -2062,7 +2060,7 @@ static int arc_config_step(struct target *target, int enable_step) value &= ~SET_CORE_SINGLE_INSTR_STEP; /* clear the IS bit */ CHECK_RETVAL(arc_jtag_write_aux_reg_one(&arc->jtag_info, AUX_DEBUG_REG, value)); - LOG_DEBUG("core debug step mode disabled"); + LOG_TARGET_DEBUG(target, "core debug step mode disabled"); } return ERROR_OK; @@ -2073,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)); @@ -2084,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); @@ -2097,14 +2095,14 @@ 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; pc->valid = true; } - LOG_DEBUG("Target steps one instruction from PC=0x%" PRIx32, + LOG_TARGET_DEBUG(target, "Target steps one instruction from PC=0x%" PRIx32, buf_get_u32(pc->value, 0, 32)); /* the front-end may request us not to handle breakpoints */ @@ -2122,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); @@ -2136,7 +2134,7 @@ static int arc_step(struct target *target, int current, target_addr_t address, if (breakpoint) CHECK_RETVAL(arc_set_breakpoint(target, breakpoint)); - LOG_DEBUG("target stepped "); + LOG_TARGET_DEBUG(target, "target stepped"); target->state = TARGET_HALTED; @@ -2159,7 +2157,7 @@ static int arc_icache_invalidate(struct target *target) if (!arc->has_icache || arc->icache_invalidated) return ERROR_OK; - LOG_DEBUG("Invalidating I$."); + LOG_TARGET_DEBUG(target, "Invalidating I$"); value = IC_IVIC_INVALIDATE; /* invalidate I$ */ CHECK_RETVAL(arc_jtag_write_aux_reg_one(&arc->jtag_info, AUX_IC_IVIC_REG, value)); @@ -2179,7 +2177,7 @@ static int arc_dcache_invalidate(struct target *target) if (!arc->has_dcache || arc->dcache_invalidated) return ERROR_OK; - LOG_DEBUG("Invalidating D$."); + LOG_TARGET_DEBUG(target, "Invalidating D$"); CHECK_RETVAL(arc_jtag_read_aux_reg_one(&arc->jtag_info, AUX_DC_CTRL_REG, &value)); dc_ctrl_value = value; @@ -2208,7 +2206,7 @@ static int arc_l2cache_invalidate(struct target *target) if (!arc->has_l2cache || arc->l2cache_invalidated) return ERROR_OK; - LOG_DEBUG("Invalidating L2$."); + LOG_TARGET_DEBUG(target, "Invalidating L2$"); CHECK_RETVAL(arc_jtag_read_aux_reg_one(&arc->jtag_info, SLC_AUX_CACHE_CTRL, &value)); slc_ctrl_value = value; @@ -2221,7 +2219,7 @@ static int arc_l2cache_invalidate(struct target *target) /* Wait until invalidate operation ends */ do { - LOG_DEBUG("Waiting for invalidation end."); + LOG_TARGET_DEBUG(target, "Waiting for invalidation end"); CHECK_RETVAL(arc_jtag_read_aux_reg_one(&arc->jtag_info, SLC_AUX_CACHE_CTRL, &value)); } while (value & L2_CTRL_BS); @@ -2259,7 +2257,7 @@ static int arc_dcache_flush(struct target *target) if (!arc->has_dcache || arc->dcache_flushed) return ERROR_OK; - LOG_DEBUG("Flushing D$."); + LOG_TARGET_DEBUG(target, "Flushing D$"); /* Store current value of DC_CTRL */ CHECK_RETVAL(arc_jtag_read_aux_reg_one(&arc->jtag_info, AUX_DC_CTRL_REG, &dc_ctrl_value)); @@ -2295,14 +2293,14 @@ static int arc_l2cache_flush(struct target *target) if (!arc->has_l2cache || arc->l2cache_flushed) return ERROR_OK; - LOG_DEBUG("Flushing L2$."); + LOG_TARGET_DEBUG(target, "Flushing L2$"); /* Flush L2 cache */ CHECK_RETVAL(arc_jtag_write_aux_reg_one(&arc->jtag_info, SLC_AUX_CACHE_FLUSH, L2_FLUSH_FL)); /* Wait until flush operation ends */ do { - LOG_DEBUG("Waiting for flushing end."); + LOG_TARGET_DEBUG(target, "Waiting for flushing end"); CHECK_RETVAL(arc_jtag_read_aux_reg_one(&arc->jtag_info, SLC_AUX_CACHE_CTRL, &value)); } while (value & L2_CTRL_BS); diff --git a/src/target/arc.h b/src/target/arc.h index a351802..4255840 100644 --- a/src/target/arc.h +++ b/src/target/arc.h @@ -22,6 +22,7 @@ #include "target_request.h" #include "target_type.h" #include "helper/bits.h" +#include "rtt/rtt.h" #include "arc_jtag.h" #include "arc_cmd.h" diff --git a/src/target/arc_cmd.c b/src/target/arc_cmd.c index e7760b0..bf8a8aa 100644 --- a/src/target/arc_cmd.c +++ b/src/target/arc_cmd.c @@ -906,5 +906,8 @@ const struct command_registration arc_monitor_command_handlers[] = { .usage = "", .chain = arc_core_command_handlers, }, + { + .chain = rtt_target_command_handlers, + }, COMMAND_REGISTRATION_DONE }; diff --git a/src/target/arc_jtag.c b/src/target/arc_jtag.c index a186709..c2bc5aa 100644 --- a/src/target/arc_jtag.c +++ b/src/target/arc_jtag.c @@ -66,7 +66,7 @@ static void arc_jtag_enque_write_ir(struct arc_jtag *jtag_info, uint32_t * @param end_state End state after reading. */ static void arc_jtag_enque_read_dr(struct arc_jtag *jtag_info, uint8_t *data, - tap_state_t end_state) + enum tap_state end_state) { assert(jtag_info); @@ -88,7 +88,7 @@ static void arc_jtag_enque_read_dr(struct arc_jtag *jtag_info, uint8_t *data, * @param end_state End state after writing. */ static void arc_jtag_enque_write_dr(struct arc_jtag *jtag_info, uint32_t data, - tap_state_t end_state) + enum tap_state end_state) { uint8_t out_value[sizeof(uint32_t)] = {0}; @@ -116,7 +116,7 @@ static void arc_jtag_enque_write_dr(struct arc_jtag *jtag_info, uint32_t data, * @param end_state End state after writing. */ static void arc_jtag_enque_set_transaction(struct arc_jtag *jtag_info, - uint32_t new_trans, tap_state_t end_state) + uint32_t new_trans, enum tap_state end_state) { uint8_t out_value[sizeof(uint32_t)] = {0}; diff --git a/src/target/arc_mem.c b/src/target/arc_mem.c index 3264b66..5132aca 100644 --- a/src/target/arc_mem.c +++ b/src/target/arc_mem.c @@ -35,7 +35,7 @@ static int arc_mem_write_block32(struct target *target, uint32_t addr, { struct arc_common *arc = target_to_arc(target); - LOG_DEBUG("Write 4-byte memory block: addr=0x%08" PRIx32 ", count=%" PRIu32, + LOG_TARGET_DEBUG(target, "Write 4-byte memory block: addr=0x%08" PRIx32 ", count=%" PRIu32, addr, count); /* Check arguments */ @@ -66,7 +66,7 @@ static int arc_mem_write_block16(struct target *target, uint32_t addr, uint8_t buffer_te[sizeof(uint32_t)]; uint8_t halfword_te[sizeof(uint16_t)]; - LOG_DEBUG("Write 2-byte memory block: addr=0x%08" PRIx32 ", count=%" PRIu32, + LOG_TARGET_DEBUG(target, "Write 2-byte memory block: addr=0x%08" PRIx32 ", count=%" PRIu32, addr, count); /* Check arguments */ @@ -124,7 +124,7 @@ static int arc_mem_write_block8(struct target *target, uint32_t addr, uint8_t buffer_te[sizeof(uint32_t)]; - LOG_DEBUG("Write 1-byte memory block: addr=0x%08" PRIx32 ", count=%" PRIu32, + LOG_TARGET_DEBUG(target, "Write 1-byte memory block: addr=0x%08" PRIx32 ", count=%" PRIu32, addr, count); /* We will read data from memory, so we need to flush the cache. */ @@ -158,14 +158,9 @@ int arc_mem_write(struct target *target, target_addr_t address, uint32_t size, int retval = ERROR_OK; void *tunnel = NULL; - LOG_DEBUG("address: 0x%08" TARGET_PRIxADDR ", size: %" PRIu32 ", count: %" PRIu32, + LOG_TARGET_DEBUG(target, "address: 0x%08" TARGET_PRIxADDR ", size: %" PRIu32 ", count: %" PRIu32, address, size, count); - if (target->state != TARGET_HALTED) { - LOG_TARGET_ERROR(target, "not halted"); - return ERROR_TARGET_NOT_HALTED; - } - /* sanitize arguments */ if (((size != 4) && (size != 2) && (size != 1)) || !(count) || !(buffer)) return ERROR_COMMAND_SYNTAX_ERROR; @@ -182,7 +177,7 @@ int arc_mem_write(struct target *target, target_addr_t address, uint32_t size, tunnel = calloc(1, count * size * sizeof(uint8_t)); if (!tunnel) { - LOG_ERROR("Unable to allocate memory"); + LOG_TARGET_ERROR(target, "Unable to allocate memory"); return ERROR_FAIL; } @@ -220,7 +215,7 @@ static int arc_mem_read_block(struct target *target, target_addr_t addr, { struct arc_common *arc = target_to_arc(target); - LOG_DEBUG("Read memory: addr=0x%08" TARGET_PRIxADDR ", size=%" PRIu32 + LOG_TARGET_DEBUG(target, "Read memory: addr=0x%08" TARGET_PRIxADDR ", size=%" PRIu32 ", count=%" PRIu32, addr, size, count); assert(!(addr & 3)); assert(size == 4); @@ -243,14 +238,9 @@ int arc_mem_read(struct target *target, target_addr_t address, uint32_t size, uint32_t words_to_read, bytes_to_read; - LOG_DEBUG("Read memory: addr=0x%08" TARGET_PRIxADDR ", size=%" PRIu32 + LOG_TARGET_DEBUG(target, "Read memory: addr=0x%08" TARGET_PRIxADDR ", size=%" PRIu32 ", count=%" PRIu32, address, size, count); - if (target->state != TARGET_HALTED) { - LOG_WARNING("target not halted"); - return ERROR_TARGET_NOT_HALTED; - } - /* Sanitize arguments */ if (((size != 4) && (size != 2) && (size != 1)) || !(count) || !(buffer)) return ERROR_COMMAND_SYNTAX_ERROR; @@ -268,7 +258,7 @@ int arc_mem_read(struct target *target, target_addr_t address, uint32_t size, tunnel_te = calloc(1, bytes_to_read); if (!tunnel_he || !tunnel_te) { - LOG_ERROR("Unable to allocate memory"); + LOG_TARGET_ERROR(target, "Unable to allocate memory"); free(tunnel_he); free(tunnel_te); return ERROR_FAIL; diff --git a/src/target/arm.h b/src/target/arm.h index 486666b..79ec99d 100644 --- a/src/target/arm.h +++ b/src/target/arm.h @@ -58,11 +58,12 @@ enum arm_arch { ARM_ARCH_V8M, }; -/** Known ARM implementor IDs */ -enum arm_implementor { - ARM_IMPLEMENTOR_ARM = 0x41, - ARM_IMPLEMENTOR_INFINEON = 0x49, - ARM_IMPLEMENTOR_REALTEK = 0x72, +/** Known ARM implementer IDs */ +enum arm_implementer { + ARM_IMPLEMENTER_ARM = 0x41, + ARM_IMPLEMENTER_INFINEON = 0x49, + ARM_IMPLEMENTER_ARM_CHINA = 0x63, + ARM_IMPLEMENTER_REALTEK = 0x72, }; /** @@ -142,8 +143,8 @@ enum { ARM_VFP_V3_FPSCR, }; -const char *arm_mode_name(unsigned psr_mode); -bool is_arm_mode(unsigned psr_mode); +const char *arm_mode_name(unsigned int psr_mode); +bool is_arm_mode(unsigned int psr_mode); /** The PSR "T" and "J" bits define the mode of "classic ARM" cores. */ enum arm_state { @@ -324,7 +325,7 @@ int arm_blank_check_memory(struct target *target, struct target_memory_check_block *blocks, int num_blocks, uint8_t erased_value); void arm_set_cpsr(struct arm *arm, uint32_t cpsr); -struct reg *arm_reg_current(struct arm *arm, unsigned regnum); -struct reg *armv8_reg_current(struct arm *arm, unsigned regnum); +struct reg *arm_reg_current(struct arm *arm, unsigned int regnum); +struct reg *armv8_reg_current(struct arm *arm, unsigned int regnum); #endif /* OPENOCD_TARGET_ARM_H */ diff --git a/src/target/arm11.c b/src/target/arm11.c index 50aaa86..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 @@ -43,7 +43,7 @@ static int arm11_check_init(struct arm11_common *arm11) CHECK_RETVAL(arm11_read_dscr(arm11)); if (!(arm11->dscr & DSCR_HALT_DBG_MODE)) { - LOG_DEBUG("DSCR %08x", (unsigned) arm11->dscr); + LOG_DEBUG("DSCR %08" PRIx32, arm11->dscr); LOG_DEBUG("Bringing target into debug mode"); arm11->dscr |= DSCR_HALT_DBG_MODE; @@ -241,8 +241,7 @@ static int arm11_leave_debug_state(struct arm11_common *arm11, bool bpwp) registers hold data that was written by one side (CPU or JTAG) and not read out by the other side. */ - LOG_ERROR("wDTR/rDTR inconsistent (DSCR %08x)", - (unsigned) arm11->dscr); + LOG_ERROR("wDTR/rDTR inconsistent (DSCR %08" PRIx32 ")", arm11->dscr); return ERROR_FAIL; } } @@ -402,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; @@ -436,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); */ @@ -470,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; } } @@ -479,7 +479,7 @@ static int arm11_resume(struct target *target, int current, /* activate all breakpoints */ if (true) { struct breakpoint *bp; - unsigned brp_num = 0; + unsigned int brp_num = 0; for (bp = target->breakpoints; bp; bp = bp->next) { struct arm11_sc7_action brp[2]; @@ -516,7 +516,7 @@ static int arm11_resume(struct target *target, int current, while (1) { CHECK_RETVAL(arm11_read_dscr(arm11)); - LOG_DEBUG("DSCR %08x", (unsigned) arm11->dscr); + LOG_DEBUG("DSCR %08" PRIx32, arm11->dscr); if (arm11->dscr & DSCR_CORE_RESTARTED) break; @@ -544,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)); @@ -570,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 */ @@ -662,7 +662,7 @@ static int arm11_step(struct target *target, int current, | DSCR_CORE_HALTED; CHECK_RETVAL(arm11_read_dscr(arm11)); - LOG_DEBUG("DSCR %08x e", (unsigned) arm11->dscr); + LOG_DEBUG("DSCR %08" PRIx32 " e", arm11->dscr); if ((arm11->dscr & mask) == mask) break; @@ -1012,10 +1012,8 @@ static int arm11_write_memory_inner(struct target *target, return retval; if (address + size * count != r0) { - LOG_ERROR("Data transfer failed. Expected end " - "address 0x%08x, got 0x%08x", - (unsigned) (address + size * count), - (unsigned) r0); + LOG_ERROR("Data transfer failed. Expected end address 0x%08" PRIx32 ", got 0x%08" PRIx32, + address + size * count, r0); if (burst) LOG_ERROR( diff --git a/src/target/arm11.h b/src/target/arm11.h index 1f56f7b..40a3f90 100644 --- a/src/target/arm11.h +++ b/src/target/arm11.h @@ -39,7 +39,7 @@ struct arm11_common { /** Debug module state. */ struct arm_dpm dpm; struct arm11_sc7_action *bpwp_actions; - unsigned bpwp_n; + unsigned int bpwp_n; size_t brp; /**< Number of Breakpoint Register Pairs from DIDR */ size_t free_brps; /**< Number of breakpoints allocated */ diff --git a/src/target/arm11_dbgtap.c b/src/target/arm11_dbgtap.c index b670bd7..4c72113 100644 --- a/src/target/arm11_dbgtap.c +++ b/src/target/arm11_dbgtap.c @@ -31,13 +31,13 @@ behavior of the FTDI driver IIRC was to go via RTI. Conversely there may be other places in this code where the ARM11 code relies on the driver to hit through RTI when coming from Update-?R. */ -static const tap_state_t arm11_move_pi_to_si_via_ci[] = { +static const enum tap_state arm11_move_pi_to_si_via_ci[] = { TAP_IREXIT2, TAP_IRUPDATE, TAP_DRSELECT, TAP_IRSELECT, TAP_IRCAPTURE, TAP_IRSHIFT }; /* REVISIT no error handling here! */ static void arm11_add_ir_scan_vc(struct jtag_tap *tap, struct scan_field *fields, - tap_state_t state) + enum tap_state state) { if (cmd_queue_cur_state == TAP_IRPAUSE) jtag_add_pathmove(ARRAY_SIZE(arm11_move_pi_to_si_via_ci), @@ -46,13 +46,13 @@ static void arm11_add_ir_scan_vc(struct jtag_tap *tap, struct scan_field *fields jtag_add_ir_scan(tap, fields, state); } -static const tap_state_t arm11_move_pd_to_sd_via_cd[] = { +static const enum tap_state arm11_move_pd_to_sd_via_cd[] = { TAP_DREXIT2, TAP_DRUPDATE, TAP_DRSELECT, TAP_DRCAPTURE, TAP_DRSHIFT }; /* REVISIT no error handling here! */ void arm11_add_dr_scan_vc(struct jtag_tap *tap, int num_fields, struct scan_field *fields, - tap_state_t state) + enum tap_state state) { if (cmd_queue_cur_state == TAP_DRPAUSE) jtag_add_pathmove(ARRAY_SIZE(arm11_move_pd_to_sd_via_cd), @@ -121,7 +121,7 @@ static const char *arm11_ir_to_string(uint8_t ir) * * \remarks This adds to the JTAG command queue but does \em not execute it. */ -void arm11_add_ir(struct arm11_common *arm11, uint8_t instr, tap_state_t state) +void arm11_add_ir(struct arm11_common *arm11, uint8_t instr, enum tap_state state) { struct jtag_tap *tap = arm11->arm.target->tap; @@ -181,7 +181,7 @@ static void arm11_in_handler_scan_n(uint8_t *in_value) */ int arm11_add_debug_scan_n(struct arm11_common *arm11, - uint8_t chain, tap_state_t state) + uint8_t chain, enum tap_state state) { /* Don't needlessly switch the scan chain. * NOTE: the ITRSEL instruction fakes SCREG changing; @@ -240,9 +240,9 @@ int arm11_add_debug_scan_n(struct arm11_common *arm11, * to ensure that the rDTR is ready before that Run-Test/Idle state. */ static void arm11_add_debug_inst(struct arm11_common *arm11, - uint32_t inst, uint8_t *flag, tap_state_t state) + uint32_t inst, uint8_t *flag, enum tap_state state) { - JTAG_DEBUG("INST <= 0x%08x", (unsigned) inst); + JTAG_DEBUG("INST <= 0x%08" PRIx32, inst); struct scan_field itr[2]; @@ -282,9 +282,7 @@ int arm11_read_dscr(struct arm11_common *arm11) CHECK_RETVAL(jtag_execute_queue()); if (arm11->dscr != dscr) - JTAG_DEBUG("DSCR = %08x (OLD %08x)", - (unsigned) dscr, - (unsigned) arm11->dscr); + JTAG_DEBUG("DSCR = %08" PRIx32 " (OLD %08" PRIx32 ")", dscr, arm11->dscr); arm11->dscr = dscr; @@ -317,9 +315,7 @@ int arm11_write_dscr(struct arm11_common *arm11, uint32_t dscr) CHECK_RETVAL(jtag_execute_queue()); - JTAG_DEBUG("DSCR <= %08x (OLD %08x)", - (unsigned) dscr, - (unsigned) arm11->dscr); + JTAG_DEBUG("DSCR <= %08" PRIx32 " (OLD %08" PRIx32 ")", dscr, arm11->dscr); arm11->dscr = dscr; @@ -509,8 +505,8 @@ int arm11_run_instr_data_to_core(struct arm11_common *arm11, CHECK_RETVAL(jtag_execute_queue()); - JTAG_DEBUG("DTR _data %08x ready %d n_retry %d", - (unsigned) _data, ready, n_retry); + JTAG_DEBUG("DTR _data %08" PRIx32 " ready %d n_retry %d", + _data, ready, n_retry); int64_t then = 0; @@ -546,7 +542,7 @@ int arm11_run_instr_data_to_core(struct arm11_common *arm11, * https://lists.berlios.de/pipermail/openocd-development/2009-July/009698.html * https://lists.berlios.de/pipermail/openocd-development/2009-August/009865.html */ -static const tap_state_t arm11_move_drpause_idle_drpause_with_delay[] = { +static const enum tap_state arm11_move_drpause_idle_drpause_with_delay[] = { TAP_DREXIT2, TAP_DRUPDATE, TAP_IDLE, TAP_IDLE, TAP_IDLE, TAP_DRSELECT, TAP_DRCAPTURE, TAP_DRSHIFT }; @@ -571,8 +567,8 @@ static int arm11_run_instr_data_to_core_noack_inner(struct jtag_tap *tap, chain5_fields[2].in_value = NULL; uint8_t *readies; - unsigned readies_num = count; - unsigned bytes = sizeof(*readies)*readies_num; + unsigned int readies_num = count; + unsigned int bytes = sizeof(*readies) * readies_num; readies = malloc(bytes); if (!readies) { @@ -596,7 +592,7 @@ static int arm11_run_instr_data_to_core_noack_inner(struct jtag_tap *tap, int retval = jtag_execute_queue(); if (retval == ERROR_OK) { - unsigned error_count = 0; + unsigned int error_count = 0; for (size_t i = 0; i < readies_num; i++) { if (readies[i] != 1) @@ -754,8 +750,8 @@ int arm11_run_instr_data_from_core(struct arm11_common *arm11, CHECK_RETVAL(jtag_execute_queue()); - JTAG_DEBUG("DTR _data %08x ready %d n_retry %d", - (unsigned) _data, ready, n_retry); + JTAG_DEBUG("DTR _data %08" PRIx32 " ready %d n_retry %d", + _data, ready, n_retry); int64_t then = 0; @@ -878,9 +874,8 @@ int arm11_sc7_run(struct arm11_common *arm11, struct arm11_sc7_action *actions, /* Timeout here so we don't get stuck. */ int i_n = 0; while (1) { - JTAG_DEBUG("SC7 <= c%-3d Data %08x %s", - (unsigned) address_out, - (unsigned) data_out, + JTAG_DEBUG("SC7 <= c%-3" PRIu8 " Data %08" PRIx32 " %s", + address_out, data_out, n_rw ? "write" : "read"); arm11_add_dr_scan_vc(arm11->arm.target->tap, ARRAY_SIZE(chain7_fields), @@ -908,7 +903,7 @@ int arm11_sc7_run(struct arm11_common *arm11, struct arm11_sc7_action *actions, } if (!n_rw) - JTAG_DEBUG("SC7 => Data %08x", (unsigned) data_in); + JTAG_DEBUG("SC7 => Data %08" PRIx32, data_in); if (i > 0) { if (actions[i - 1].address != address_in) @@ -1047,7 +1042,7 @@ static int arm11_dpm_instr_read_data_r0(struct arm_dpm *dpm, * and watchpoint operations instead of running them right away. Since we * pre-allocated our vector, we don't need to worry about space. */ -static int arm11_bpwp_enable(struct arm_dpm *dpm, unsigned index_t, +static int arm11_bpwp_enable(struct arm_dpm *dpm, unsigned int index_t, uint32_t addr, uint32_t control) { struct arm11_common *arm11 = dpm_to_arm11(dpm); @@ -1084,7 +1079,7 @@ static int arm11_bpwp_enable(struct arm_dpm *dpm, unsigned index_t, return ERROR_OK; } -static int arm11_bpwp_disable(struct arm_dpm *dpm, unsigned index_t) +static int arm11_bpwp_disable(struct arm_dpm *dpm, unsigned int index_t) { struct arm11_common *arm11 = dpm_to_arm11(dpm); struct arm11_sc7_action *action; diff --git a/src/target/arm11_dbgtap.h b/src/target/arm11_dbgtap.h index eeb174a..74dda6e 100644 --- a/src/target/arm11_dbgtap.h +++ b/src/target/arm11_dbgtap.h @@ -17,9 +17,9 @@ void arm11_setup_field(struct arm11_common *arm11, int num_bits, void *in_data, void *out_data, struct scan_field *field); void arm11_add_ir(struct arm11_common *arm11, - uint8_t instr, tap_state_t state); + uint8_t instr, enum tap_state state); int arm11_add_debug_scan_n(struct arm11_common *arm11, - uint8_t chain, tap_state_t state); + uint8_t chain, enum tap_state state); int arm11_read_dscr(struct arm11_common *arm11); int arm11_write_dscr(struct arm11_common *arm11, uint32_t dscr); @@ -40,7 +40,7 @@ int arm11_run_instr_data_to_core_via_r0(struct arm11_common *arm11, uint32_t opcode, uint32_t data); void arm11_add_dr_scan_vc(struct jtag_tap *tap, int num_fields, struct scan_field *fields, - tap_state_t state); + enum tap_state state); /** * Used with arm11_sc7_run to make a list of read/write commands for 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/arm9tdmi.c b/src/target/arm9tdmi.c index 3bacfae..7e31306 100644 --- a/src/target/arm9tdmi.c +++ b/src/target/arm9tdmi.c @@ -821,9 +821,9 @@ COMMAND_HANDLER(handle_arm9tdmi_catch_vectors_command) else if (strcmp(CMD_ARGV[0], "none") == 0) { /* do nothing */ } else { - for (unsigned i = 0; i < CMD_ARGC; i++) { + for (unsigned int i = 0; i < CMD_ARGC; i++) { /* go through list of vectors */ - unsigned j; + unsigned int j; for (j = 0; arm9tdmi_vectors[j].name; j++) { if (strcmp(CMD_ARGV[i], arm9tdmi_vectors[j].name) == 0) { vector_catch_value |= arm9tdmi_vectors[j].value; @@ -850,7 +850,7 @@ COMMAND_HANDLER(handle_arm9tdmi_catch_vectors_command) } /* output current settings */ - for (unsigned i = 0; arm9tdmi_vectors[i].name; i++) { + for (unsigned int i = 0; arm9tdmi_vectors[i].name; i++) { command_print(CMD, "%s: %s", arm9tdmi_vectors[i].name, (vector_catch_value & arm9tdmi_vectors[i].value) ? "catch" : "don't catch"); diff --git a/src/target/arm_adi_v5.c b/src/target/arm_adi_v5.c index 9129ace..df897b8 100644 --- a/src/target/arm_adi_v5.c +++ b/src/target/arm_adi_v5.c @@ -795,11 +795,12 @@ int dap_dp_init(struct adiv5_dap *dap) dap->dp_ctrl_stat = CDBGPWRUPREQ | CSYSPWRUPREQ; /* - * This write operation clears the sticky error bit in jtag mode only and - * is ignored in swd mode. It also powers-up system and debug domains in - * both jtag and swd modes, if not done before. + * This write operation clears the sticky error and overrun bits in jtag + * mode only and is ignored in swd mode. It also powers-up system and + * debug domains in both jtag and swd modes, if not done before. */ - retval = dap_queue_dp_write(dap, DP_CTRL_STAT, dap->dp_ctrl_stat | SSTICKYERR); + retval = dap_queue_dp_write(dap, DP_CTRL_STAT, + dap->dp_ctrl_stat | SSTICKYERR | SSTICKYORUN); if (retval != ERROR_OK) return retval; @@ -1453,11 +1454,13 @@ static const struct dap_part_nums { { ARM_ID, 0x4af, "Cortex-A15 ROM", "(ROM Table)", }, { ARM_ID, 0x4b5, "Cortex-R5 ROM", "(ROM Table)", }, { ARM_ID, 0x4b8, "Cortex-R52 ROM", "(ROM Table)", }, + { ARM_ID, 0x4bd, "Cortex-R52+ ROM", "(ROM Table)", }, { ARM_ID, 0x4c0, "Cortex-M0+ ROM", "(ROM Table)", }, { ARM_ID, 0x4c3, "Cortex-M3 ROM", "(ROM Table)", }, { ARM_ID, 0x4c4, "Cortex-M4 ROM", "(ROM Table)", }, { ARM_ID, 0x4c7, "Cortex-M7 PPB ROM", "(Private Peripheral Bus ROM Table)", }, { ARM_ID, 0x4c8, "Cortex-M7 ROM", "(ROM Table)", }, + { ARM_ID, 0x4c9, "STAR ROM", "(ROM Table)", }, { ARM_ID, 0x4e0, "Cortex-A35 ROM", "(v7 Memory Map ROM Table)", }, { ARM_ID, 0x4e4, "Cortex-A76 ROM", "(ROM Table)", }, { ARM_ID, 0x906, "CoreSight CTI", "(Cross Trigger)", }, @@ -1499,6 +1502,7 @@ static const struct dap_part_nums { { ARM_ID, 0x9ae, "Cortex-A17 PMU", "(Performance Monitor Unit)", }, { ARM_ID, 0x9af, "Cortex-A15 PMU", "(Performance Monitor Unit)", }, { ARM_ID, 0x9b6, "Cortex-R52 PMU/CTI/ETM", "(Performance Monitor Unit/Cross Trigger/ETM)", }, + { ARM_ID, 0x9bb, "Cortex-R52+ PMU/CTI/ETM", "(Performance Monitor Unit/Cross Trigger/ETM)", }, { ARM_ID, 0x9b7, "Cortex-R7 PMU", "(Performance Monitor Unit)", }, { ARM_ID, 0x9d3, "Cortex-A53 PMU", "(Performance Monitor Unit)", }, { ARM_ID, 0x9d7, "Cortex-A57 PMU", "(Performance Monitor Unit)", }, @@ -1528,11 +1532,16 @@ static const struct dap_part_nums { { ARM_ID, 0xc17, "Cortex-R7 Debug", "(Debug Unit)", }, { ARM_ID, 0xd03, "Cortex-A53 Debug", "(Debug Unit)", }, { ARM_ID, 0xd04, "Cortex-A35 Debug", "(Debug Unit)", }, + { ARM_ID, 0xd05, "Cortex-A55 Debug", "(Debug Unit)", }, { ARM_ID, 0xd07, "Cortex-A57 Debug", "(Debug Unit)", }, { ARM_ID, 0xd08, "Cortex-A72 Debug", "(Debug Unit)", }, { ARM_ID, 0xd0b, "Cortex-A76 Debug", "(Debug Unit)", }, { ARM_ID, 0xd0c, "Neoverse N1", "(Debug Unit)", }, { ARM_ID, 0xd13, "Cortex-R52 Debug", "(Debug Unit)", }, + { ARM_ID, 0xd16, "Cortex-R52+ Debug", "(Debug Unit)", }, + { ARM_ID, 0xd21, "STAR Debug", "(Debug Unit)", }, + { ARM_ID, 0xd22, "Cortex-M55 Debug", "(Debug Unit)", }, + { ARM_ID, 0xd43, "Cortex-A65AE Debug", "(Debug Unit)", }, { ARM_ID, 0xd49, "Neoverse N2", "(Debug Unit)", }, { 0x017, 0x120, "TI SDTI", "(System Debug Trace Interface)", }, /* from OMAP3 memmap */ { 0x017, 0x343, "TI DAPCTL", "", }, /* from OMAP3 memmap */ @@ -1552,6 +1561,9 @@ static const struct dap_part_nums { { 0x1eb, 0x211, "Tegra 210 ROM", "(ROM Table)", }, { 0x1eb, 0x302, "Denver Debug", "(Debug Unit)", }, { 0x1eb, 0x402, "Denver PMU", "(Performance Monitor Unit)", }, + { 0x575, 0x132, "STAR SCS", "(System Control Space)", }, + { 0x575, 0x4d2, "Cortex-M52 ROM", "(ROM Table)", }, + { 0x575, 0xd24, "Cortex-M52 Debug", "(Debug Unit)", }, }; static const struct dap_part_nums *pidr_to_part_num(unsigned int designer_id, unsigned int part_num) @@ -2347,7 +2359,7 @@ static int adiv5_jim_spot_configure(struct jim_getopt_info *goi, switch (n->value) { case CFG_DAP: - if (goi->isconfigure) { + if (goi->is_configure) { Jim_Obj *o_t; struct adiv5_dap *dap; e = jim_getopt_obj(goi, &o_t); @@ -2355,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) { @@ -2376,7 +2390,7 @@ static int adiv5_jim_spot_configure(struct jim_getopt_info *goi, break; case CFG_AP_NUM: - if (goi->isconfigure) { + if (goi->is_configure) { /* jim_wide is a signed 64 bits int, ap_num is unsigned with max 52 bits */ jim_wide ap_num; e = jim_getopt_wide(goi, &ap_num); @@ -2403,7 +2417,7 @@ static int adiv5_jim_spot_configure(struct jim_getopt_info *goi, LOG_WARNING("DEPRECATED! use \'-baseaddr' not \'-ctibase\'"); /* fall through */ case CFG_BASEADDR: - if (goi->isconfigure) { + if (goi->is_configure) { jim_wide base; e = jim_getopt_wide(goi, &base); if (e != JIM_OK) diff --git a/src/target/arm_adi_v5.h b/src/target/arm_adi_v5.h index 92c3dbc..ebd2752 100644 --- a/src/target/arm_adi_v5.h +++ b/src/target/arm_adi_v5.h @@ -454,17 +454,17 @@ struct dap_ops { int (*send_sequence)(struct adiv5_dap *dap, enum swd_special_seq seq); /** DP register read. */ - int (*queue_dp_read)(struct adiv5_dap *dap, unsigned reg, + int (*queue_dp_read)(struct adiv5_dap *dap, unsigned int reg, uint32_t *data); /** DP register write. */ - int (*queue_dp_write)(struct adiv5_dap *dap, unsigned reg, + int (*queue_dp_write)(struct adiv5_dap *dap, unsigned int reg, uint32_t data); /** AP register read. */ - int (*queue_ap_read)(struct adiv5_ap *ap, unsigned reg, + int (*queue_ap_read)(struct adiv5_ap *ap, unsigned int reg, uint32_t *data); /** AP register write. */ - int (*queue_ap_write)(struct adiv5_ap *ap, unsigned reg, + int (*queue_ap_write)(struct adiv5_ap *ap, unsigned int reg, uint32_t data); /** AP operation abort. */ @@ -553,7 +553,7 @@ static inline int dap_send_sequence(struct adiv5_dap *dap, * @return ERROR_OK for success, else a fault code. */ static inline int dap_queue_dp_read(struct adiv5_dap *dap, - unsigned reg, uint32_t *data) + unsigned int reg, uint32_t *data) { assert(dap->ops); return dap->ops->queue_dp_read(dap, reg, data); @@ -571,7 +571,7 @@ static inline int dap_queue_dp_read(struct adiv5_dap *dap, * @return ERROR_OK for success, else a fault code. */ static inline int dap_queue_dp_write(struct adiv5_dap *dap, - unsigned reg, uint32_t data) + unsigned int reg, uint32_t data) { assert(dap->ops); return dap->ops->queue_dp_write(dap, reg, data); @@ -588,7 +588,7 @@ static inline int dap_queue_dp_write(struct adiv5_dap *dap, * @return ERROR_OK for success, else a fault code. */ static inline int dap_queue_ap_read(struct adiv5_ap *ap, - unsigned reg, uint32_t *data) + unsigned int reg, uint32_t *data) { assert(ap->dap->ops); if (ap->refcount == 0) { @@ -608,7 +608,7 @@ static inline int dap_queue_ap_read(struct adiv5_ap *ap, * @return ERROR_OK for success, else a fault code. */ static inline int dap_queue_ap_write(struct adiv5_ap *ap, - unsigned reg, uint32_t data) + unsigned int reg, uint32_t data) { assert(ap->dap->ops); if (ap->refcount == 0) { @@ -659,7 +659,7 @@ static inline int dap_sync(struct adiv5_dap *dap) return ERROR_OK; } -static inline int dap_dp_read_atomic(struct adiv5_dap *dap, unsigned reg, +static inline int dap_dp_read_atomic(struct adiv5_dap *dap, unsigned int reg, uint32_t *value) { int retval; @@ -671,7 +671,7 @@ static inline int dap_dp_read_atomic(struct adiv5_dap *dap, unsigned reg, return dap_run(dap); } -static inline int dap_dp_poll_register(struct adiv5_dap *dap, unsigned reg, +static inline int dap_dp_poll_register(struct adiv5_dap *dap, unsigned int reg, uint32_t mask, uint32_t value, int timeout) { assert(timeout > 0); diff --git a/src/target/arm_cti.c b/src/target/arm_cti.c index 7637ad0..b2f78ee 100644 --- a/src/target/arm_cti.c +++ b/src/target/arm_cti.c @@ -25,7 +25,7 @@ struct arm_cti { struct adiv5_ap *ap; }; -static LIST_HEAD(all_cti); +static OOCD_LIST_HEAD(all_cti); const char *arm_cti_name(struct arm_cti *self) { @@ -157,48 +157,44 @@ int arm_cti_clear_channel(struct arm_cti *self, uint32_t channel) return arm_cti_write_reg(self, CTI_APPCLEAR, CTI_CHNL(channel)); } -static uint32_t cti_regs[28]; - static const struct { uint32_t offset; const char *label; - uint32_t *p_val; } cti_names[] = { - { CTI_CTR, "CTR", &cti_regs[0] }, - { CTI_GATE, "GATE", &cti_regs[1] }, - { CTI_INEN0, "INEN0", &cti_regs[2] }, - { CTI_INEN1, "INEN1", &cti_regs[3] }, - { CTI_INEN2, "INEN2", &cti_regs[4] }, - { CTI_INEN3, "INEN3", &cti_regs[5] }, - { CTI_INEN4, "INEN4", &cti_regs[6] }, - { CTI_INEN5, "INEN5", &cti_regs[7] }, - { CTI_INEN6, "INEN6", &cti_regs[8] }, - { CTI_INEN7, "INEN7", &cti_regs[9] }, - { CTI_INEN8, "INEN8", &cti_regs[10] }, - { CTI_OUTEN0, "OUTEN0", &cti_regs[11] }, - { CTI_OUTEN1, "OUTEN1", &cti_regs[12] }, - { CTI_OUTEN2, "OUTEN2", &cti_regs[13] }, - { CTI_OUTEN3, "OUTEN3", &cti_regs[14] }, - { CTI_OUTEN4, "OUTEN4", &cti_regs[15] }, - { CTI_OUTEN5, "OUTEN5", &cti_regs[16] }, - { CTI_OUTEN6, "OUTEN6", &cti_regs[17] }, - { CTI_OUTEN7, "OUTEN7", &cti_regs[18] }, - { CTI_OUTEN8, "OUTEN8", &cti_regs[19] }, - { CTI_TRIN_STATUS, "TRIN", &cti_regs[20] }, - { CTI_TROUT_STATUS, "TROUT", &cti_regs[21] }, - { CTI_CHIN_STATUS, "CHIN", &cti_regs[22] }, - { CTI_CHOU_STATUS, "CHOUT", &cti_regs[23] }, - { CTI_APPSET, "APPSET", &cti_regs[24] }, - { CTI_APPCLEAR, "APPCLR", &cti_regs[25] }, - { CTI_APPPULSE, "APPPULSE", &cti_regs[26] }, - { CTI_INACK, "INACK", &cti_regs[27] }, + { CTI_CTR, "CTR" }, + { CTI_GATE, "GATE" }, + { CTI_INEN0, "INEN0" }, + { CTI_INEN1, "INEN1" }, + { CTI_INEN2, "INEN2" }, + { CTI_INEN3, "INEN3" }, + { CTI_INEN4, "INEN4" }, + { CTI_INEN5, "INEN5" }, + { CTI_INEN6, "INEN6" }, + { CTI_INEN7, "INEN7" }, + { CTI_INEN8, "INEN8" }, + { CTI_OUTEN0, "OUTEN0" }, + { CTI_OUTEN1, "OUTEN1" }, + { CTI_OUTEN2, "OUTEN2" }, + { CTI_OUTEN3, "OUTEN3" }, + { CTI_OUTEN4, "OUTEN4" }, + { CTI_OUTEN5, "OUTEN5" }, + { CTI_OUTEN6, "OUTEN6" }, + { CTI_OUTEN7, "OUTEN7" }, + { CTI_OUTEN8, "OUTEN8" }, + { CTI_TRIN_STATUS, "TRIN" }, + { CTI_TROUT_STATUS, "TROUT" }, + { CTI_CHIN_STATUS, "CHIN" }, + { CTI_CHOU_STATUS, "CHOUT" }, + { CTI_APPSET, "APPSET" }, + { CTI_APPCLEAR, "APPCLR" }, + { CTI_APPPULSE, "APPPULSE" }, + { CTI_INACK, "INACK" }, + { CTI_DEVCTL, "DEVCTL" }, }; static int cti_find_reg_offset(const char *name) { - unsigned int i; - - for (i = 0; i < ARRAY_SIZE(cti_names); i++) { + for (size_t i = 0; i < ARRAY_SIZE(cti_names); i++) { if (!strcmp(name, cti_names[i].label)) return cti_names[i].offset; } @@ -226,10 +222,11 @@ COMMAND_HANDLER(handle_cti_dump) struct arm_cti *cti = CMD_DATA; struct adiv5_ap *ap = cti->ap; int retval = ERROR_OK; + uint32_t values[ARRAY_SIZE(cti_names)]; - for (int i = 0; (retval == ERROR_OK) && (i < (int)ARRAY_SIZE(cti_names)); i++) + for (size_t i = 0; (retval == ERROR_OK) && (i < ARRAY_SIZE(cti_names)); i++) retval = mem_ap_read_u32(ap, - cti->spot.base + cti_names[i].offset, cti_names[i].p_val); + cti->spot.base + cti_names[i].offset, &values[i]); if (retval == ERROR_OK) retval = dap_run(ap->dap); @@ -237,9 +234,9 @@ COMMAND_HANDLER(handle_cti_dump) if (retval != ERROR_OK) return JIM_ERR; - for (int i = 0; i < (int)ARRAY_SIZE(cti_names); i++) + for (size_t i = 0; i < ARRAY_SIZE(cti_names); i++) command_print(CMD, "%8.8s (0x%04"PRIx32") 0x%08"PRIx32, - cti_names[i].label, cti_names[i].offset, *cti_names[i].p_val); + cti_names[i].label, cti_names[i].offset, values[i]); return JIM_OK; } @@ -323,7 +320,6 @@ COMMAND_HANDLER(handle_cti_ack) int retval = arm_cti_ack_events(cti, 1 << event); - if (retval != ERROR_OK) return retval; @@ -437,6 +433,7 @@ static int cti_configure(struct jim_getopt_info *goi, struct arm_cti *cti) return JIM_OK; } + static int cti_create(struct jim_getopt_info *goi) { struct command_context *cmd_ctx; @@ -471,7 +468,7 @@ static int cti_create(struct jim_getopt_info *goi) adiv5_mem_ap_spot_init(&cti->spot); /* Do the rest as "configure" options */ - goi->isconfigure = 1; + goi->is_configure = true; e = cti_configure(goi, cti); if (e != JIM_OK) { free(cti); @@ -538,7 +535,6 @@ COMMAND_HANDLER(cti_handle_names) return ERROR_OK; } - static const struct command_registration cti_subcommand_handlers[] = { { .name = "create", diff --git a/src/target/arm_cti.h b/src/target/arm_cti.h index cfcde65..1513f02 100644 --- a/src/target/arm_cti.h +++ b/src/target/arm_cti.h @@ -39,6 +39,7 @@ #define CTI_CHIN_STATUS 0x138 #define CTI_CHOU_STATUS 0x13C #define CTI_GATE 0x140 +#define CTI_DEVCTL 0x150 #define CTI_UNLOCK 0xFB0 #define CTI_CHNL(x) (1 << x) diff --git a/src/target/arm_dap.c b/src/target/arm_dap.c index 9f4afae..c5bd6cc 100644 --- a/src/target/arm_dap.c +++ b/src/target/arm_dap.c @@ -18,7 +18,7 @@ #include "transport/transport.h" #include "jtag/interface.h" -static LIST_HEAD(all_dap); +static OOCD_LIST_HEAD(all_dap); extern struct adapter_driver *adapter_driver; diff --git a/src/target/arm_disassembler.c b/src/target/arm_disassembler.c index 749274f..8619f8f 100644 --- a/src/target/arm_disassembler.c +++ b/src/target/arm_disassembler.c @@ -114,7 +114,7 @@ static int evaluate_pld(uint32_t opcode, if ((opcode & 0x0d30f000) == 0x0510f000) { uint8_t rn; uint8_t u; - unsigned offset; + unsigned int offset; instruction->type = ARM_PLD; rn = (opcode & 0xf0000) >> 16; @@ -266,18 +266,18 @@ static int evaluate_srs(uint32_t opcode, case 0x08400000: snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 - "\tSRS%s\tSP%s, #%d", + "\tSRS%s\tSP%s, #%" PRIu32, address, opcode, mode, wback, - (unsigned)(opcode & 0x1f)); + opcode & 0x1f); break; case 0x08100000: snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 - "\tRFE%s\tr%d%s", + "\tRFE%s\tr%" PRIu32 "%s", address, opcode, mode, - (unsigned)((opcode >> 16) & 0xf), wback); + (opcode >> 16) & 0xf, wback); break; default: return evaluate_unknown(opcode, address, instruction); @@ -701,9 +701,9 @@ static int evaluate_load_store(uint32_t opcode, static int evaluate_extend(uint32_t opcode, uint32_t address, char *cp) { - unsigned rm = (opcode >> 0) & 0xf; - unsigned rd = (opcode >> 12) & 0xf; - unsigned rn = (opcode >> 16) & 0xf; + unsigned int rm = (opcode >> 0) & 0xf; + unsigned int rd = (opcode >> 12) & 0xf; + unsigned int rn = (opcode >> 16) & 0xf; char *type, *rot; switch ((opcode >> 24) & 0x3) { @@ -842,7 +842,7 @@ static int evaluate_media(uint32_t opcode, uint32_t address, /* halfword pack */ if ((opcode & 0x01f00020) == 0x00800000) { char *type, *shift; - unsigned imm = (unsigned) (opcode >> 7) & 0x1f; + unsigned int imm = (opcode >> 7) & 0x1f; if (opcode & (1 << 6)) { type = "TB"; @@ -865,7 +865,7 @@ static int evaluate_media(uint32_t opcode, uint32_t address, /* word saturate */ if ((opcode & 0x01a00020) == 0x00a00000) { char *shift; - unsigned imm = (unsigned) (opcode >> 7) & 0x1f; + unsigned int imm = (opcode >> 7) & 0x1f; if (opcode & (1 << 6)) { shift = "ASR"; @@ -892,7 +892,7 @@ static int evaluate_media(uint32_t opcode, uint32_t address, /* multiplies */ if ((opcode & 0x01f00080) == 0x01000000) { - unsigned rn = (opcode >> 12) & 0xf; + unsigned int rn = (opcode >> 12) & 0xf; if (rn != 0xf) sprintf(cp, "SML%cD%s%s\tr%d, r%d, r%d, r%d", @@ -925,7 +925,7 @@ static int evaluate_media(uint32_t opcode, uint32_t address, return ERROR_OK; } if ((opcode & 0x01f00000) == 0x01500000) { - unsigned rn = (opcode >> 12) & 0xf; + unsigned int rn = (opcode >> 12) & 0xf; switch (opcode & 0xc0) { case 3: @@ -1001,8 +1001,8 @@ static int evaluate_media(uint32_t opcode, uint32_t address, return ERROR_OK; } if (mnemonic) { - unsigned rm = (opcode >> 0) & 0xf; - unsigned rd = (opcode >> 12) & 0xf; + unsigned int rm = (opcode >> 0) & 0xf; + unsigned int rd = (opcode >> 12) & 0xf; sprintf(cp, "%s%s\tr%d, r%d", mnemonic, COND(opcode), rm, rd); return ERROR_OK; @@ -2046,8 +2046,7 @@ int arm_evaluate_opcode(uint32_t opcode, uint32_t address, return evaluate_cdp_mcr_mrc(opcode, address, instruction); } - LOG_ERROR("ARM: should never reach this point (opcode=%08x)", - (unsigned) opcode); + LOG_ERROR("ARM: should never reach this point (opcode=%08" PRIx32 ")", opcode); return -1; } @@ -2748,7 +2747,7 @@ static int evaluate_cond_branch_thumb(uint16_t opcode, static int evaluate_cb_thumb(uint16_t opcode, uint32_t address, struct arm_instruction *instruction) { - unsigned offset; + unsigned int offset; /* added in Thumb2 */ offset = (opcode >> 3) & 0x1f; @@ -2859,7 +2858,7 @@ static int evaluate_hint_thumb(uint16_t opcode, uint32_t address, static int evaluate_ifthen_thumb(uint16_t opcode, uint32_t address, struct arm_instruction *instruction) { - unsigned cond = (opcode >> 4) & 0x0f; + unsigned int cond = (opcode >> 4) & 0x0f; char *x = "", *y = "", *z = ""; if (opcode & 0x01) diff --git a/src/target/arm_disassembler.h b/src/target/arm_disassembler.h index 1be5674..8317da9 100644 --- a/src/target/arm_disassembler.h +++ b/src/target/arm_disassembler.h @@ -171,7 +171,7 @@ struct arm_instruction { uint32_t opcode; /* return value ... Thumb-2 sizes vary */ - unsigned instruction_size; + unsigned int instruction_size; union { struct arm_b_bl_bx_blx_instr b_bl_bx_blx; diff --git a/src/target/arm_dpm.c b/src/target/arm_dpm.c index 9f3a444..0b2db77 100644 --- a/src/target/arm_dpm.c +++ b/src/target/arm_dpm.c @@ -59,7 +59,7 @@ static int dpm_mrc(struct target *target, int cpnum, ARMV4_5_MRC(cpnum, op1, 0, crn, crm, op2), value); - /* (void) */ dpm->finish(dpm); + dpm->finish(dpm); return retval; } @@ -82,7 +82,7 @@ static int dpm_mrrc(struct target *target, int cpnum, ARMV5_T_MRRC(cpnum, op, 0, 1, crm), value); - /* (void) */ dpm->finish(dpm); + dpm->finish(dpm); return retval; } @@ -107,7 +107,7 @@ static int dpm_mcr(struct target *target, int cpnum, ARMV4_5_MCR(cpnum, op1, 0, crn, crm, op2), value); - /* (void) */ dpm->finish(dpm); + dpm->finish(dpm); return retval; } @@ -129,7 +129,7 @@ static int dpm_mcrr(struct target *target, int cpnum, retval = dpm->instr_write_data_r0_r1(dpm, ARMV5_T_MCRR(cpnum, op, 0, 1, crm), value); - /* (void) */ dpm->finish(dpm); + dpm->finish(dpm); return retval; } @@ -167,7 +167,7 @@ int arm_dpm_modeswitch(struct arm_dpm *dpm, enum arm_mode mode) } /* Read 64bit VFP registers */ -static int dpm_read_reg_u64(struct arm_dpm *dpm, struct reg *r, unsigned regnum) +static int dpm_read_reg_u64(struct arm_dpm *dpm, struct reg *r, unsigned int regnum) { int retval = ERROR_FAIL; uint32_t value_r0, value_r1; @@ -198,15 +198,14 @@ static int dpm_read_reg_u64(struct arm_dpm *dpm, struct reg *r, unsigned regnum) buf_set_u32(r->value + 4, 0, 32, value_r1); r->valid = true; r->dirty = false; - LOG_DEBUG("READ: %s, %8.8x, %8.8x", r->name, - (unsigned) value_r0, (unsigned) value_r1); + LOG_DEBUG("READ: %s, %8.8" PRIx32 ", %8.8" PRIx32, r->name, value_r0, value_r1); } return retval; } /* just read the register -- rely on the core mode being right */ -int arm_dpm_read_reg(struct arm_dpm *dpm, struct reg *r, unsigned regnum) +int arm_dpm_read_reg(struct arm_dpm *dpm, struct reg *r, unsigned int regnum) { uint32_t value; int retval; @@ -266,14 +265,14 @@ int arm_dpm_read_reg(struct arm_dpm *dpm, struct reg *r, unsigned regnum) buf_set_u32(r->value, 0, 32, value); r->valid = true; r->dirty = false; - LOG_DEBUG("READ: %s, %8.8x", r->name, (unsigned) value); + LOG_DEBUG("READ: %s, %8.8" PRIx32, r->name, value); } return retval; } /* Write 64bit VFP registers */ -static int dpm_write_reg_u64(struct arm_dpm *dpm, struct reg *r, unsigned regnum) +static int dpm_write_reg_u64(struct arm_dpm *dpm, struct reg *r, unsigned int regnum) { int retval = ERROR_FAIL; uint32_t value_r0 = buf_get_u32(r->value, 0, 32); @@ -302,15 +301,14 @@ static int dpm_write_reg_u64(struct arm_dpm *dpm, struct reg *r, unsigned regnum if (retval == ERROR_OK) { r->dirty = false; - LOG_DEBUG("WRITE: %s, %8.8x, %8.8x", r->name, - (unsigned) value_r0, (unsigned) value_r1); + LOG_DEBUG("WRITE: %s, %8.8" PRIx32 ", %8.8" PRIx32, r->name, value_r0, value_r1); } return retval; } /* just write the register -- rely on the core mode being right */ -static int dpm_write_reg(struct arm_dpm *dpm, struct reg *r, unsigned regnum) +static int dpm_write_reg(struct arm_dpm *dpm, struct reg *r, unsigned int regnum) { int retval; uint32_t value = buf_get_u32(r->value, 0, 32); @@ -351,7 +349,7 @@ static int dpm_write_reg(struct arm_dpm *dpm, struct reg *r, unsigned regnum) if (retval == ERROR_OK) { r->dirty = false; - LOG_DEBUG("WRITE: %s, %8.8x", r->name, (unsigned) value); + LOG_DEBUG("WRITE: %s, %8.8" PRIx32, r->name, value); } return retval; @@ -388,7 +386,7 @@ int arm_dpm_read_current_registers(struct arm_dpm *dpm) return retval; /* read R0 and R1 first (it's used for scratch), then CPSR */ - for (unsigned i = 0; i < 2; i++) { + for (unsigned int i = 0; i < 2; i++) { r = arm->core_cache->reg_list + i; if (!r->valid) { retval = arm_dpm_read_reg(dpm, r, i); @@ -406,7 +404,7 @@ int arm_dpm_read_current_registers(struct arm_dpm *dpm) arm_set_cpsr(arm, cpsr); /* REVISIT we can probably avoid reading R1..R14, saving time... */ - for (unsigned i = 2; i < 16; i++) { + for (unsigned int i = 2; i < 16; i++) { r = arm_reg_current(arm, i); if (r->valid) continue; @@ -424,7 +422,7 @@ int arm_dpm_read_current_registers(struct arm_dpm *dpm) */ fail: - /* (void) */ dpm->finish(dpm); + dpm->finish(dpm); return retval; } @@ -503,7 +501,7 @@ int arm_dpm_write_dirty_registers(struct arm_dpm *dpm, bool bpwp) * cope with the hand-crafted breakpoint code. */ if (arm->target->type->add_breakpoint == dpm_add_breakpoint) { - for (unsigned i = 0; i < dpm->nbp; i++) { + for (unsigned int i = 0; i < dpm->nbp; i++) { struct dpm_bp *dbp = dpm->dbp + i; struct breakpoint *bp = dbp->bp; @@ -515,7 +513,7 @@ int arm_dpm_write_dirty_registers(struct arm_dpm *dpm, bool bpwp) } /* enable/disable watchpoints */ - for (unsigned i = 0; i < dpm->nwp; i++) { + for (unsigned int i = 0; i < dpm->nwp; i++) { struct dpm_wp *dwp = dpm->dwp + i; struct watchpoint *wp = dwp->wp; @@ -540,9 +538,9 @@ int arm_dpm_write_dirty_registers(struct arm_dpm *dpm, bool bpwp) did_write = false; /* check everything except our scratch registers R0 and R1 */ - for (unsigned i = 2; i < cache->num_regs; i++) { + for (unsigned int i = 2; i < cache->num_regs; i++) { struct arm_reg *r; - unsigned regnum; + unsigned int regnum; /* also skip PC, CPSR, and non-dirty */ if (i == 15) @@ -627,14 +625,14 @@ int arm_dpm_write_dirty_registers(struct arm_dpm *dpm, bool bpwp) arm->pc->dirty = false; /* flush R0 and R1 (our scratch registers) */ - for (unsigned i = 0; i < 2; i++) { + for (unsigned int i = 0; i < 2; i++) { retval = dpm_write_reg(dpm, &cache->reg_list[i], i); if (retval != ERROR_OK) goto done; cache->reg_list[i].dirty = false; } - /* (void) */ dpm->finish(dpm); + dpm->finish(dpm); done: return retval; } @@ -645,7 +643,7 @@ done: * or MODE_ANY. */ static enum arm_mode dpm_mapmode(struct arm *arm, - unsigned num, enum arm_mode mode) + unsigned int num, enum arm_mode mode) { enum arm_mode amode = arm->core_mode; @@ -721,10 +719,10 @@ static int arm_dpm_read_core_reg(struct target *target, struct reg *r, /* always clean up, regardless of error */ if (mode != ARM_MODE_ANY) - /* (void) */ arm_dpm_modeswitch(dpm, ARM_MODE_ANY); + arm_dpm_modeswitch(dpm, ARM_MODE_ANY); fail: - /* (void) */ dpm->finish(dpm); + dpm->finish(dpm); return retval; } @@ -763,10 +761,10 @@ static int arm_dpm_write_core_reg(struct target *target, struct reg *r, /* always clean up, regardless of error */ if (mode != ARM_MODE_ANY) - /* (void) */ arm_dpm_modeswitch(dpm, ARM_MODE_ANY); + arm_dpm_modeswitch(dpm, ARM_MODE_ANY); fail: - /* (void) */ dpm->finish(dpm); + dpm->finish(dpm); return retval; } @@ -795,7 +793,7 @@ static int arm_dpm_full_context(struct target *target) * Pick some mode with unread registers and read them all. * Repeat until done. */ - for (unsigned i = 0; i < cache->num_regs; i++) { + for (unsigned int i = 0; i < cache->num_regs; i++) { struct arm_reg *r; if (!cache->reg_list[i].exist || cache->reg_list[i].valid) @@ -833,7 +831,7 @@ static int arm_dpm_full_context(struct target *target) } while (did_read); retval = arm_dpm_modeswitch(dpm, ARM_MODE_ANY); - /* (void) */ dpm->finish(dpm); + dpm->finish(dpm); done: return retval; } @@ -923,7 +921,7 @@ static int dpm_add_breakpoint(struct target *target, struct breakpoint *bp) if (bp->type == BKPT_SOFT) LOG_DEBUG("using HW bkpt, not SW..."); - for (unsigned i = 0; i < dpm->nbp; i++) { + for (unsigned int i = 0; i < dpm->nbp; i++) { if (!dpm->dbp[i].bp) { retval = dpm_bpwp_setup(dpm, &dpm->dbp[i].bpwp, bp->address, bp->length); @@ -942,7 +940,7 @@ static int dpm_remove_breakpoint(struct target *target, struct breakpoint *bp) struct arm_dpm *dpm = arm->dpm; int retval = ERROR_COMMAND_SYNTAX_ERROR; - for (unsigned i = 0; i < dpm->nbp; i++) { + for (unsigned int i = 0; i < dpm->nbp; i++) { if (dpm->dbp[i].bp == bp) { dpm->dbp[i].bp = NULL; dpm->dbp[i].bpwp.dirty = true; @@ -956,7 +954,7 @@ static int dpm_remove_breakpoint(struct target *target, struct breakpoint *bp) return retval; } -static int dpm_watchpoint_setup(struct arm_dpm *dpm, unsigned index_t, +static int dpm_watchpoint_setup(struct arm_dpm *dpm, unsigned int index_t, struct watchpoint *wp) { int retval; @@ -999,7 +997,7 @@ static int dpm_add_watchpoint(struct target *target, struct watchpoint *wp) int retval = ERROR_TARGET_RESOURCE_NOT_AVAILABLE; if (dpm->bpwp_enable) { - for (unsigned i = 0; i < dpm->nwp; i++) { + for (unsigned int i = 0; i < dpm->nwp; i++) { if (!dpm->dwp[i].wp) { retval = dpm_watchpoint_setup(dpm, i, wp); break; @@ -1016,7 +1014,7 @@ static int dpm_remove_watchpoint(struct target *target, struct watchpoint *wp) struct arm_dpm *dpm = arm->dpm; int retval = ERROR_COMMAND_SYNTAX_ERROR; - for (unsigned i = 0; i < dpm->nwp; i++) { + for (unsigned int i = 0; i < dpm->nwp; i++) { if (dpm->dwp[i].wp == wp) { dpm->dwp[i].wp = NULL; dpm->dwp[i].bpwp.dirty = true; @@ -1163,7 +1161,7 @@ int arm_dpm_initialize(struct arm_dpm *dpm) { /* Disable all breakpoints and watchpoints at startup. */ if (dpm->bpwp_disable) { - unsigned i; + unsigned int i; for (i = 0; i < dpm->nbp; i++) { dpm->dbp[i].bpwp.number = i; diff --git a/src/target/arm_dpm.h b/src/target/arm_dpm.h index 2da4631..16c801e 100644 --- a/src/target/arm_dpm.h +++ b/src/target/arm_dpm.h @@ -19,7 +19,7 @@ */ struct dpm_bpwp { - unsigned number; + unsigned int number; uint32_t address; uint32_t control; /* true if hardware state needs flushing */ @@ -109,7 +109,7 @@ struct arm_dpm { uint32_t opcode, uint64_t *data); struct reg *(*arm_reg_current)(struct arm *arm, - unsigned regnum); + unsigned int regnum); /* BREAKPOINT/WATCHPOINT SUPPORT */ @@ -119,7 +119,7 @@ struct arm_dpm { * must currently be disabled. Indices 0..15 are used for * breakpoints; indices 16..31 are for watchpoints. */ - int (*bpwp_enable)(struct arm_dpm *dpm, unsigned index_value, + int (*bpwp_enable)(struct arm_dpm *dpm, unsigned int index_value, uint32_t addr, uint32_t control); /** @@ -127,15 +127,15 @@ struct arm_dpm { * hardware control registers. Indices are the same ones * accepted by bpwp_enable(). */ - int (*bpwp_disable)(struct arm_dpm *dpm, unsigned index_value); + int (*bpwp_disable)(struct arm_dpm *dpm, unsigned int index_value); /* The breakpoint and watchpoint arrays are private to the * DPM infrastructure. There are nbp indices in the dbp * array. There are nwp indices in the dwp array. */ - unsigned nbp; - unsigned nwp; + unsigned int nbp; + unsigned int nwp; struct dpm_bp *dbp; struct dpm_wp *dwp; @@ -158,7 +158,7 @@ struct arm_dpm { int arm_dpm_setup(struct arm_dpm *dpm); int arm_dpm_initialize(struct arm_dpm *dpm); -int arm_dpm_read_reg(struct arm_dpm *dpm, struct reg *r, unsigned regnum); +int arm_dpm_read_reg(struct arm_dpm *dpm, struct reg *r, unsigned int regnum); int arm_dpm_read_current_registers(struct arm_dpm *dpm); int arm_dpm_modeswitch(struct arm_dpm *dpm, enum arm_mode mode); diff --git a/src/target/arm_jtag.c b/src/target/arm_jtag.c index c1ec473..e553ec8 100644 --- a/src/target/arm_jtag.c +++ b/src/target/arm_jtag.c @@ -19,7 +19,7 @@ #endif int arm_jtag_set_instr_inner(struct jtag_tap *tap, - uint32_t new_instr, void *no_verify_capture, tap_state_t end_state) + uint32_t new_instr, void *no_verify_capture, enum tap_state end_state) { struct scan_field field; uint8_t t[4] = { 0 }; @@ -41,7 +41,7 @@ int arm_jtag_set_instr_inner(struct jtag_tap *tap, return ERROR_OK; } -int arm_jtag_scann_inner(struct arm_jtag *jtag_info, uint32_t new_scan_chain, tap_state_t end_state) +int arm_jtag_scann_inner(struct arm_jtag *jtag_info, uint32_t new_scan_chain, enum tap_state end_state) { int retval = ERROR_OK; diff --git a/src/target/arm_jtag.h b/src/target/arm_jtag.h index 11b7c3e..5356bcf 100644 --- a/src/target/arm_jtag.h +++ b/src/target/arm_jtag.h @@ -26,10 +26,10 @@ struct arm_jtag { int arm_jtag_set_instr_inner(struct jtag_tap *tap, uint32_t new_instr, void *no_verify_capture, - tap_state_t end_state); + enum tap_state end_state); static inline int arm_jtag_set_instr(struct jtag_tap *tap, - uint32_t new_instr, void *no_verify_capture, tap_state_t end_state) + uint32_t new_instr, void *no_verify_capture, enum tap_state end_state) { /* inline most common code path */ if (buf_get_u32(tap->cur_instr, 0, tap->ir_length) != (new_instr & (BIT(tap->ir_length) - 1))) @@ -39,8 +39,8 @@ static inline int arm_jtag_set_instr(struct jtag_tap *tap, } -int arm_jtag_scann_inner(struct arm_jtag *jtag_info, uint32_t new_scan_chain, tap_state_t end_state); -static inline int arm_jtag_scann(struct arm_jtag *jtag_info, uint32_t new_scan_chain, tap_state_t end_state) +int arm_jtag_scann_inner(struct arm_jtag *jtag_info, uint32_t new_scan_chain, enum tap_state end_state); +static inline int arm_jtag_scann(struct arm_jtag *jtag_info, uint32_t new_scan_chain, enum tap_state end_state) { /* inline most common code path */ int retval = ERROR_OK; 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/arm_tpiu_swo.c b/src/target/arm_tpiu_swo.c index 55a9778..e20cd59 100644 --- a/src/target/arm_tpiu_swo.c +++ b/src/target/arm_tpiu_swo.c @@ -126,7 +126,7 @@ struct arm_tpiu_swo_priv_connection { struct arm_tpiu_swo_object *obj; }; -static LIST_HEAD(all_tpiu_swo); +static OOCD_LIST_HEAD(all_tpiu_swo); #define ARM_TPIU_SWO_TRACE_BUF_SIZE 4096 @@ -358,7 +358,7 @@ static int arm_tpiu_swo_configure(struct jim_getopt_info *goi, struct arm_tpiu_s { assert(obj); - if (goi->isconfigure && obj->enabled) { + if (goi->is_configure && obj->enabled) { Jim_SetResultFormatted(goi->interp, "Cannot configure TPIU/SWO; %s is enabled!", obj->name); return JIM_ERR; } @@ -382,7 +382,7 @@ static int arm_tpiu_swo_configure(struct jim_getopt_info *goi, struct arm_tpiu_s switch (n->value) { case CFG_PORT_WIDTH: - if (goi->isconfigure) { + if (goi->is_configure) { jim_wide port_width; e = jim_getopt_wide(goi, &port_width); if (e != JIM_OK) @@ -399,7 +399,7 @@ static int arm_tpiu_swo_configure(struct jim_getopt_info *goi, struct arm_tpiu_s } break; case CFG_PROTOCOL: - if (goi->isconfigure) { + if (goi->is_configure) { struct jim_nvp *p; e = jim_getopt_nvp(goi, nvp_arm_tpiu_swo_protocol_opts, &p); if (e != JIM_OK) @@ -418,7 +418,7 @@ static int arm_tpiu_swo_configure(struct jim_getopt_info *goi, struct arm_tpiu_s } break; case CFG_FORMATTER: - if (goi->isconfigure) { + if (goi->is_configure) { struct jim_nvp *p; e = jim_getopt_nvp(goi, nvp_arm_tpiu_swo_bool_opts, &p); if (e != JIM_OK) @@ -437,7 +437,7 @@ static int arm_tpiu_swo_configure(struct jim_getopt_info *goi, struct arm_tpiu_s } break; case CFG_TRACECLKIN: - if (goi->isconfigure) { + if (goi->is_configure) { jim_wide clk; e = jim_getopt_wide(goi, &clk); if (e != JIM_OK) @@ -450,7 +450,7 @@ static int arm_tpiu_swo_configure(struct jim_getopt_info *goi, struct arm_tpiu_s } break; case CFG_BITRATE: - if (goi->isconfigure) { + if (goi->is_configure) { jim_wide clk; e = jim_getopt_wide(goi, &clk); if (e != JIM_OK) @@ -463,7 +463,7 @@ static int arm_tpiu_swo_configure(struct jim_getopt_info *goi, struct arm_tpiu_s } break; case CFG_OUTFILE: - if (goi->isconfigure) { + if (goi->is_configure) { const char *s; e = jim_getopt_string(goi, &s, NULL); if (e != JIM_OK) @@ -491,7 +491,7 @@ static int arm_tpiu_swo_configure(struct jim_getopt_info *goi, struct arm_tpiu_s } break; case CFG_EVENT: - if (goi->isconfigure) { + if (goi->is_configure) { if (goi->argc < 2) { Jim_WrongNumArgs(goi->interp, goi->argc, goi->argv, "-event ?event-name? ?EVENT-BODY?"); return JIM_ERR; @@ -521,7 +521,7 @@ static int arm_tpiu_swo_configure(struct jim_getopt_info *goi, struct arm_tpiu_s ea = ea->next; } - if (goi->isconfigure) { + if (goi->is_configure) { if (!ea) { ea = calloc(1, sizeof(*ea)); if (!ea) { @@ -560,7 +560,7 @@ static int jim_arm_tpiu_swo_configure(Jim_Interp *interp, int argc, Jim_Obj * co struct jim_getopt_info goi; jim_getopt_setup(&goi, interp, argc - 1, argv + 1); - goi.isconfigure = !strcmp(c->name, "configure"); + goi.is_configure = !strcmp(c->name, "configure"); if (goi.argc < 1) { Jim_WrongNumArgs(goi.interp, goi.argc, goi.argv, "missing: -option ..."); @@ -977,7 +977,7 @@ static int jim_arm_tpiu_swo_create(Jim_Interp *interp, int argc, Jim_Obj *const } /* Do the rest as "configure" options */ - goi.isconfigure = 1; + goi.is_configure = true; int e = arm_tpiu_swo_configure(&goi, obj); if (e != JIM_OK) goto err_exit; diff --git a/src/target/armv4_5.c b/src/target/armv4_5.c index 1886d5e..597dc89 100644 --- a/src/target/armv4_5.c +++ b/src/target/armv4_5.c @@ -168,9 +168,9 @@ static const struct { }; /** Map PSR mode bits to the name of an ARM processor operating mode. */ -const char *arm_mode_name(unsigned psr_mode) +const char *arm_mode_name(unsigned int psr_mode) { - for (unsigned i = 0; i < ARRAY_SIZE(arm_mode_data); i++) { + for (unsigned int i = 0; i < ARRAY_SIZE(arm_mode_data); i++) { if (arm_mode_data[i].psr == psr_mode) return arm_mode_data[i].name; } @@ -179,9 +179,9 @@ const char *arm_mode_name(unsigned psr_mode) } /** Return true iff the parameter denotes a valid ARM processor mode. */ -bool is_arm_mode(unsigned psr_mode) +bool is_arm_mode(unsigned int psr_mode) { - for (unsigned i = 0; i < ARRAY_SIZE(arm_mode_data); i++) { + for (unsigned int i = 0; i < ARRAY_SIZE(arm_mode_data); i++) { if (arm_mode_data[i].psr == psr_mode) return true; } @@ -248,7 +248,11 @@ enum arm_mode armv4_5_number_to_mode(int number) } static const char *arm_state_strings[] = { - "ARM", "Thumb", "Jazelle", "ThumbEE", + [ARM_STATE_ARM] = "ARM", + [ARM_STATE_THUMB] = "Thumb", + [ARM_STATE_JAZELLE] = "Jazelle", + [ARM_STATE_THUMB_EE] = "ThumbEE", + [ARM_STATE_AARCH64] = "AArch64", }; /* Templates for ARM core registers. @@ -272,8 +276,8 @@ static const struct { * CPSR -or- SPSR depending on whether 'mode' is MODE_ANY. * (Exception modes have both CPSR and SPSR registers ...) */ - unsigned cookie; - unsigned gdb_index; + unsigned int cookie; + unsigned int gdb_index; enum arm_mode mode; } arm_core_regs[] = { /* IMPORTANT: we guarantee that the first eight cached registers @@ -430,6 +434,16 @@ const int armv4_5_core_reg_map[9][17] = { } }; +static const char *arm_core_state_string(struct arm *arm) +{ + if (arm->core_state > ARRAY_SIZE(arm_state_strings)) { + LOG_ERROR("core_state exceeds table size"); + return "Unknown"; + } + + return arm_state_strings[arm->core_state]; +} + /** * Configures host-side ARM records to reflect the specified CPSR. * Later, code can use arm_reg_current() to map register numbers @@ -482,9 +496,9 @@ void arm_set_cpsr(struct arm *arm, uint32_t cpsr) } arm->core_state = state; - LOG_DEBUG("set CPSR %#8.8x: %s mode, %s state", (unsigned) cpsr, + LOG_DEBUG("set CPSR %#8.8" PRIx32 ": %s mode, %s state", cpsr, arm_mode_name(mode), - arm_state_strings[arm->core_state]); + arm_core_state_string(arm)); } /** @@ -499,7 +513,7 @@ void arm_set_cpsr(struct arm *arm, uint32_t cpsr) * However, R8..R14, and SPSR (arm->spsr) *must* be mapped. * CPSR (arm->cpsr) is also not mapped. */ -struct reg *arm_reg_current(struct arm *arm, unsigned regnum) +struct reg *arm_reg_current(struct arm *arm, unsigned int regnum) { struct reg *r; @@ -794,7 +808,7 @@ int arm_arch_state(struct target *target) LOG_USER("target halted in %s state due to %s, current mode: %s\n" "cpsr: 0x%8.8" PRIx32 " pc: 0x%8.8" PRIx32 "%s%s", - arm_state_strings[arm->core_state], + arm_core_state_string(arm), debug_reason_name(target), arm_mode_name(arm->core_mode), buf_get_u32(arm->cpsr->value, 0, 32), @@ -840,7 +854,7 @@ COMMAND_HANDLER(handle_armv4_5_reg_command) regs = arm->core_cache->reg_list; - for (unsigned mode = 0; mode < ARRAY_SIZE(arm_mode_data); mode++) { + for (unsigned int mode = 0; mode < ARRAY_SIZE(arm_mode_data); mode++) { const char *name; char *sep = "\n"; char *shadow = ""; @@ -875,11 +889,11 @@ COMMAND_HANDLER(handle_armv4_5_reg_command) sep, name, shadow); /* display N rows of up to 4 registers each */ - for (unsigned i = 0; i < arm_mode_data[mode].n_indices; ) { + for (unsigned int i = 0; i < arm_mode_data[mode].n_indices; ) { char output[80]; int output_len = 0; - for (unsigned j = 0; j < 4; j++, i++) { + for (unsigned int j = 0; j < 4; j++, i++) { uint32_t value; struct reg *reg = regs; @@ -929,7 +943,7 @@ COMMAND_HANDLER(handle_arm_core_state_command) arm->core_state = ARM_STATE_THUMB; } - command_print(CMD, "core state: %s", arm_state_strings[arm->core_state]); + command_print(CMD, "core state: %s", arm_core_state_string(arm)); return ret; } @@ -1287,11 +1301,11 @@ int arm_get_gdb_reg_list(struct target *target, *reg_list = malloc(sizeof(struct reg *) * (*reg_list_size)); for (i = 0; i < 16; i++) - (*reg_list)[i] = arm_reg_current(arm, i); + (*reg_list)[i] = arm_reg_current(arm, i); /* For GDB compatibility, take FPA registers size into account and zero-fill it*/ for (i = 16; i < 24; i++) - (*reg_list)[i] = &arm_gdb_dummy_fp_reg; + (*reg_list)[i] = &arm_gdb_dummy_fp_reg; (*reg_list)[24] = &arm_gdb_dummy_fps_reg; (*reg_list)[25] = arm->cpsr; @@ -1316,25 +1330,25 @@ int arm_get_gdb_reg_list(struct target *target, *reg_list = malloc(sizeof(struct reg *) * (*reg_list_size)); for (i = 0; i < 16; i++) - (*reg_list)[i] = arm_reg_current(arm, i); + (*reg_list)[i] = arm_reg_current(arm, i); for (i = 13; i < ARRAY_SIZE(arm_core_regs); i++) { - int reg_index = arm->core_cache->reg_list[i].number; + int reg_index = arm->core_cache->reg_list[i].number; - if (arm_core_regs[i].mode == ARM_MODE_MON + if (arm_core_regs[i].mode == ARM_MODE_MON && arm->core_type != ARM_CORE_TYPE_SEC_EXT && arm->core_type != ARM_CORE_TYPE_VIRT_EXT) - continue; - if (arm_core_regs[i].mode == ARM_MODE_HYP + continue; + if (arm_core_regs[i].mode == ARM_MODE_HYP && arm->core_type != ARM_CORE_TYPE_VIRT_EXT) - continue; - (*reg_list)[reg_index] = &(arm->core_cache->reg_list[i]); + continue; + (*reg_list)[reg_index] = &arm->core_cache->reg_list[i]; } /* When we supply the target description, there is no need for fake FPA */ for (i = 16; i < 24; i++) { - (*reg_list)[i] = &arm_gdb_dummy_fp_reg; - (*reg_list)[i]->size = 0; + (*reg_list)[i] = &arm_gdb_dummy_fp_reg; + (*reg_list)[i]->size = 0; } (*reg_list)[24] = &arm_gdb_dummy_fps_reg; (*reg_list)[24]->size = 0; @@ -1500,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); @@ -1750,7 +1764,7 @@ cleanup: static int arm_full_context(struct target *target) { struct arm *arm = target_to_arm(target); - unsigned num_regs = arm->core_cache->num_regs; + unsigned int num_regs = arm->core_cache->num_regs; struct reg *reg = arm->core_cache->reg_list; int retval = ERROR_OK; diff --git a/src/target/armv7a.c b/src/target/armv7a.c index dc3752e..c14155e 100644 --- a/src/target/armv7a.c +++ b/src/target/armv7a.c @@ -74,7 +74,7 @@ static void armv7a_show_fault_registers(struct target *target) ", IFAR: %8.8" PRIx32, ifsr, ifar); done: - /* (void) */ dpm->finish(dpm); + dpm->finish(dpm); } @@ -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/armv7a_cache_l2x.h b/src/target/armv7a_cache_l2x.h index d5f1a6f..ea726ec 100644 --- a/src/target/armv7a_cache_l2x.h +++ b/src/target/armv7a_cache_l2x.h @@ -122,16 +122,16 @@ struct outer_cache_fns { void (*resume)(void); /* This is an ARM L2C thing */ - void (*write_sec)(unsigned long, unsigned); + void (*write_sec)(unsigned long, unsigned int); void (*configure)(const struct l2x0_regs *); }; struct l2c_init_data { const char *type; - unsigned way_size_0; - unsigned num_lock; + unsigned int way_size_0; + unsigned int num_lock; - void (*enable)(uint32_t, uint32_t, unsigned); + void (*enable)(uint32_t, uint32_t, unsigned int); void (*fixup)(uint32_t, uint32_t, struct outer_cache_fns *); void (*save)(uint32_t); void (*configure)(uint32_t); diff --git a/src/target/armv7a_mmu.c b/src/target/armv7a_mmu.c index c4d294e..43b5dae 100644 --- a/src/target/armv7a_mmu.c +++ b/src/target/armv7a_mmu.c @@ -260,8 +260,7 @@ COMMAND_HANDLER(armv7a_mmu_dump_table) /* skip empty entries in the first level table */ if ((first_lvl_descriptor & 3) == 0) { pt_idx++; - } else - if ((first_lvl_descriptor & 0x40002) == 2) { + } else if ((first_lvl_descriptor & 0x40002) == 2) { /* section descriptor */ uint32_t va_range = 1024*1024-1; /* 1MB range */ uint32_t va_start = pt_idx << 20; @@ -273,8 +272,7 @@ COMMAND_HANDLER(armv7a_mmu_dump_table) LOG_USER("SECT: VA[%8.8"PRIx32" -- %8.8"PRIx32"]: PA[%8.8"PRIx32" -- %8.8"PRIx32"] %s", va_start, va_end, pa_start, pa_end, l1_desc_bits_to_string(first_lvl_descriptor, afe)); pt_idx++; - } else - if ((first_lvl_descriptor & 0x40002) == 0x40002) { + } else if ((first_lvl_descriptor & 0x40002) == 0x40002) { /* supersection descriptor */ uint32_t va_range = 16*1024*1024-1; /* 16MB range */ uint32_t va_start = pt_idx << 20; @@ -310,8 +308,7 @@ COMMAND_HANDLER(armv7a_mmu_dump_table) if ((second_lvl_descriptor & 3) == 0) { /* skip entry */ pt2_idx++; - } else - if ((second_lvl_descriptor & 3) == 1) { + } else if ((second_lvl_descriptor & 3) == 1) { /* large page */ uint32_t va_range = 64*1024-1; /* 64KB range */ uint32_t va_start = (pt_idx << 20) + (pt2_idx << 12); diff --git a/src/target/armv7m.c b/src/target/armv7m.c index d508af7..dc2d84f 100644 --- a/src/target/armv7m.c +++ b/src/target/armv7m.c @@ -65,6 +65,28 @@ const int armv7m_msp_reg_map[ARMV7M_NUM_CORE_REGS] = { ARMV7M_XPSR, }; +static struct reg_data_type_bitfield armv8m_vpr_bits[] = { + { 0, 15, REG_TYPE_UINT }, + { 16, 19, REG_TYPE_UINT }, + { 20, 23, REG_TYPE_UINT }, +}; + +static struct reg_data_type_flags_field armv8m_vpr_fields[] = { + { "P0", armv8m_vpr_bits + 0, armv8m_vpr_fields + 1, }, + { "MASK01", armv8m_vpr_bits + 1, armv8m_vpr_fields + 2, }, + { "MASK23", armv8m_vpr_bits + 2, NULL }, +}; + +static struct reg_data_type_flags armv8m_vpr_flags[] = { + { 4, armv8m_vpr_fields }, +}; + +static struct reg_data_type armv8m_flags_vpr[] = { + { REG_TYPE_ARCH_DEFINED, "vpr_reg", REG_TYPE_CLASS_FLAGS, + { .reg_type_flags = armv8m_vpr_flags }, + }, +}; + /* * These registers are not memory-mapped. The ARMv7-M profile includes * memory mapped registers too, such as for the NVIC (interrupt controller) @@ -74,36 +96,37 @@ const int armv7m_msp_reg_map[ARMV7M_NUM_CORE_REGS] = { * doesn't include basepri or faultmask registers. */ static const struct { - unsigned id; + unsigned int id; const char *name; - unsigned bits; + unsigned int bits; enum reg_type type; const char *group; const char *feature; + struct reg_data_type *data_type; } armv7m_regs[] = { - { ARMV7M_R0, "r0", 32, REG_TYPE_INT, "general", "org.gnu.gdb.arm.m-profile" }, - { ARMV7M_R1, "r1", 32, REG_TYPE_INT, "general", "org.gnu.gdb.arm.m-profile" }, - { ARMV7M_R2, "r2", 32, REG_TYPE_INT, "general", "org.gnu.gdb.arm.m-profile" }, - { ARMV7M_R3, "r3", 32, REG_TYPE_INT, "general", "org.gnu.gdb.arm.m-profile" }, - { ARMV7M_R4, "r4", 32, REG_TYPE_INT, "general", "org.gnu.gdb.arm.m-profile" }, - { ARMV7M_R5, "r5", 32, REG_TYPE_INT, "general", "org.gnu.gdb.arm.m-profile" }, - { ARMV7M_R6, "r6", 32, REG_TYPE_INT, "general", "org.gnu.gdb.arm.m-profile" }, - { ARMV7M_R7, "r7", 32, REG_TYPE_INT, "general", "org.gnu.gdb.arm.m-profile" }, - { ARMV7M_R8, "r8", 32, REG_TYPE_INT, "general", "org.gnu.gdb.arm.m-profile" }, - { ARMV7M_R9, "r9", 32, REG_TYPE_INT, "general", "org.gnu.gdb.arm.m-profile" }, - { ARMV7M_R10, "r10", 32, REG_TYPE_INT, "general", "org.gnu.gdb.arm.m-profile" }, - { ARMV7M_R11, "r11", 32, REG_TYPE_INT, "general", "org.gnu.gdb.arm.m-profile" }, - { ARMV7M_R12, "r12", 32, REG_TYPE_INT, "general", "org.gnu.gdb.arm.m-profile" }, - { ARMV7M_R13, "sp", 32, REG_TYPE_DATA_PTR, "general", "org.gnu.gdb.arm.m-profile" }, - { ARMV7M_R14, "lr", 32, REG_TYPE_INT, "general", "org.gnu.gdb.arm.m-profile" }, - { ARMV7M_PC, "pc", 32, REG_TYPE_CODE_PTR, "general", "org.gnu.gdb.arm.m-profile" }, - { ARMV7M_XPSR, "xpsr", 32, REG_TYPE_INT, "general", "org.gnu.gdb.arm.m-profile" }, - - { ARMV7M_MSP, "msp", 32, REG_TYPE_DATA_PTR, "system", "org.gnu.gdb.arm.m-system" }, - { ARMV7M_PSP, "psp", 32, REG_TYPE_DATA_PTR, "system", "org.gnu.gdb.arm.m-system" }, + { ARMV7M_R0, "r0", 32, REG_TYPE_INT, "general", "org.gnu.gdb.arm.m-profile", NULL, }, + { ARMV7M_R1, "r1", 32, REG_TYPE_INT, "general", "org.gnu.gdb.arm.m-profile", NULL, }, + { ARMV7M_R2, "r2", 32, REG_TYPE_INT, "general", "org.gnu.gdb.arm.m-profile", NULL, }, + { ARMV7M_R3, "r3", 32, REG_TYPE_INT, "general", "org.gnu.gdb.arm.m-profile", NULL, }, + { ARMV7M_R4, "r4", 32, REG_TYPE_INT, "general", "org.gnu.gdb.arm.m-profile", NULL, }, + { ARMV7M_R5, "r5", 32, REG_TYPE_INT, "general", "org.gnu.gdb.arm.m-profile", NULL, }, + { ARMV7M_R6, "r6", 32, REG_TYPE_INT, "general", "org.gnu.gdb.arm.m-profile", NULL, }, + { ARMV7M_R7, "r7", 32, REG_TYPE_INT, "general", "org.gnu.gdb.arm.m-profile", NULL, }, + { ARMV7M_R8, "r8", 32, REG_TYPE_INT, "general", "org.gnu.gdb.arm.m-profile", NULL, }, + { ARMV7M_R9, "r9", 32, REG_TYPE_INT, "general", "org.gnu.gdb.arm.m-profile", NULL, }, + { ARMV7M_R10, "r10", 32, REG_TYPE_INT, "general", "org.gnu.gdb.arm.m-profile", NULL, }, + { ARMV7M_R11, "r11", 32, REG_TYPE_INT, "general", "org.gnu.gdb.arm.m-profile", NULL, }, + { ARMV7M_R12, "r12", 32, REG_TYPE_INT, "general", "org.gnu.gdb.arm.m-profile", NULL, }, + { ARMV7M_R13, "sp", 32, REG_TYPE_DATA_PTR, "general", "org.gnu.gdb.arm.m-profile", NULL, }, + { ARMV7M_R14, "lr", 32, REG_TYPE_INT, "general", "org.gnu.gdb.arm.m-profile", NULL, }, + { ARMV7M_PC, "pc", 32, REG_TYPE_CODE_PTR, "general", "org.gnu.gdb.arm.m-profile", NULL, }, + { ARMV7M_XPSR, "xpsr", 32, REG_TYPE_INT, "general", "org.gnu.gdb.arm.m-profile", NULL, }, + + { ARMV7M_MSP, "msp", 32, REG_TYPE_DATA_PTR, "system", "org.gnu.gdb.arm.m-system", NULL, }, + { ARMV7M_PSP, "psp", 32, REG_TYPE_DATA_PTR, "system", "org.gnu.gdb.arm.m-system", NULL, }, /* A working register for packing/unpacking special regs, hidden from gdb */ - { ARMV7M_PMSK_BPRI_FLTMSK_CTRL, "pmsk_bpri_fltmsk_ctrl", 32, REG_TYPE_INT, NULL, NULL }, + { ARMV7M_PMSK_BPRI_FLTMSK_CTRL, "pmsk_bpri_fltmsk_ctrl", 32, REG_TYPE_INT, NULL, NULL, NULL }, /* WARNING: If you use armv7m_write_core_reg() on one of 4 following * special registers, the new data go to ARMV7M_PMSK_BPRI_FLTMSK_CTRL @@ -111,52 +134,54 @@ static const struct { * To trigger write to CPU HW register, add * armv7m_write_core_reg(,,ARMV7M_PMSK_BPRI_FLTMSK_CTRL,); */ - { ARMV7M_PRIMASK, "primask", 1, REG_TYPE_INT8, "system", "org.gnu.gdb.arm.m-system" }, - { ARMV7M_BASEPRI, "basepri", 8, REG_TYPE_INT8, "system", "org.gnu.gdb.arm.m-system" }, - { ARMV7M_FAULTMASK, "faultmask", 1, REG_TYPE_INT8, "system", "org.gnu.gdb.arm.m-system" }, - { ARMV7M_CONTROL, "control", 3, REG_TYPE_INT8, "system", "org.gnu.gdb.arm.m-system" }, + { ARMV7M_PRIMASK, "primask", 1, REG_TYPE_INT8, "system", "org.gnu.gdb.arm.m-system", NULL, }, + { ARMV7M_BASEPRI, "basepri", 8, REG_TYPE_INT8, "system", "org.gnu.gdb.arm.m-system", NULL, }, + { ARMV7M_FAULTMASK, "faultmask", 1, REG_TYPE_INT8, "system", "org.gnu.gdb.arm.m-system", NULL, }, + { ARMV7M_CONTROL, "control", 3, REG_TYPE_INT8, "system", "org.gnu.gdb.arm.m-system", NULL, }, /* ARMv8-M security extension (TrustZone) specific registers */ - { ARMV8M_MSP_NS, "msp_ns", 32, REG_TYPE_DATA_PTR, "stack", "org.gnu.gdb.arm.secext" }, - { ARMV8M_PSP_NS, "psp_ns", 32, REG_TYPE_DATA_PTR, "stack", "org.gnu.gdb.arm.secext" }, - { ARMV8M_MSP_S, "msp_s", 32, REG_TYPE_DATA_PTR, "stack", "org.gnu.gdb.arm.secext" }, - { ARMV8M_PSP_S, "psp_s", 32, REG_TYPE_DATA_PTR, "stack", "org.gnu.gdb.arm.secext" }, - { ARMV8M_MSPLIM_S, "msplim_s", 32, REG_TYPE_DATA_PTR, "stack", "org.gnu.gdb.arm.secext" }, - { ARMV8M_PSPLIM_S, "psplim_s", 32, REG_TYPE_DATA_PTR, "stack", "org.gnu.gdb.arm.secext" }, - { ARMV8M_MSPLIM_NS, "msplim_ns", 32, REG_TYPE_DATA_PTR, "stack", "org.gnu.gdb.arm.secext" }, - { ARMV8M_PSPLIM_NS, "psplim_ns", 32, REG_TYPE_DATA_PTR, "stack", "org.gnu.gdb.arm.secext" }, - - { ARMV8M_PMSK_BPRI_FLTMSK_CTRL_S, "pmsk_bpri_fltmsk_ctrl_s", 32, REG_TYPE_INT, NULL, NULL }, - { ARMV8M_PRIMASK_S, "primask_s", 1, REG_TYPE_INT8, "system", "org.gnu.gdb.arm.secext" }, - { ARMV8M_BASEPRI_S, "basepri_s", 8, REG_TYPE_INT8, "system", "org.gnu.gdb.arm.secext" }, - { ARMV8M_FAULTMASK_S, "faultmask_s", 1, REG_TYPE_INT8, "system", "org.gnu.gdb.arm.secext" }, - { ARMV8M_CONTROL_S, "control_s", 3, REG_TYPE_INT8, "system", "org.gnu.gdb.arm.secext" }, - - { ARMV8M_PMSK_BPRI_FLTMSK_CTRL_NS, "pmsk_bpri_fltmsk_ctrl_ns", 32, REG_TYPE_INT, NULL, NULL }, - { ARMV8M_PRIMASK_NS, "primask_ns", 1, REG_TYPE_INT8, "system", "org.gnu.gdb.arm.secext" }, - { ARMV8M_BASEPRI_NS, "basepri_ns", 8, REG_TYPE_INT8, "system", "org.gnu.gdb.arm.secext" }, - { ARMV8M_FAULTMASK_NS, "faultmask_ns", 1, REG_TYPE_INT8, "system", "org.gnu.gdb.arm.secext" }, - { ARMV8M_CONTROL_NS, "control_ns", 3, REG_TYPE_INT8, "system", "org.gnu.gdb.arm.secext" }, + { ARMV8M_MSP_NS, "msp_ns", 32, REG_TYPE_DATA_PTR, "stack", "org.gnu.gdb.arm.secext", NULL, }, + { ARMV8M_PSP_NS, "psp_ns", 32, REG_TYPE_DATA_PTR, "stack", "org.gnu.gdb.arm.secext", NULL, }, + { ARMV8M_MSP_S, "msp_s", 32, REG_TYPE_DATA_PTR, "stack", "org.gnu.gdb.arm.secext", NULL, }, + { ARMV8M_PSP_S, "psp_s", 32, REG_TYPE_DATA_PTR, "stack", "org.gnu.gdb.arm.secext", NULL, }, + { ARMV8M_MSPLIM_S, "msplim_s", 32, REG_TYPE_DATA_PTR, "stack", "org.gnu.gdb.arm.secext", NULL, }, + { ARMV8M_PSPLIM_S, "psplim_s", 32, REG_TYPE_DATA_PTR, "stack", "org.gnu.gdb.arm.secext", NULL, }, + { ARMV8M_MSPLIM_NS, "msplim_ns", 32, REG_TYPE_DATA_PTR, "stack", "org.gnu.gdb.arm.secext", NULL, }, + { ARMV8M_PSPLIM_NS, "psplim_ns", 32, REG_TYPE_DATA_PTR, "stack", "org.gnu.gdb.arm.secext", NULL, }, + + { ARMV8M_PMSK_BPRI_FLTMSK_CTRL_S, "pmsk_bpri_fltmsk_ctrl_s", 32, REG_TYPE_INT, NULL, NULL, NULL, }, + { ARMV8M_PRIMASK_S, "primask_s", 1, REG_TYPE_INT8, "system", "org.gnu.gdb.arm.secext", NULL, }, + { ARMV8M_BASEPRI_S, "basepri_s", 8, REG_TYPE_INT8, "system", "org.gnu.gdb.arm.secext", NULL, }, + { ARMV8M_FAULTMASK_S, "faultmask_s", 1, REG_TYPE_INT8, "system", "org.gnu.gdb.arm.secext", NULL, }, + { ARMV8M_CONTROL_S, "control_s", 3, REG_TYPE_INT8, "system", "org.gnu.gdb.arm.secext", NULL, }, + + { ARMV8M_PMSK_BPRI_FLTMSK_CTRL_NS, "pmsk_bpri_fltmsk_ctrl_ns", 32, REG_TYPE_INT, NULL, NULL, NULL, }, + { ARMV8M_PRIMASK_NS, "primask_ns", 1, REG_TYPE_INT8, "system", "org.gnu.gdb.arm.secext", NULL, }, + { ARMV8M_BASEPRI_NS, "basepri_ns", 8, REG_TYPE_INT8, "system", "org.gnu.gdb.arm.secext", NULL, }, + { ARMV8M_FAULTMASK_NS, "faultmask_ns", 1, REG_TYPE_INT8, "system", "org.gnu.gdb.arm.secext", NULL, }, + { ARMV8M_CONTROL_NS, "control_ns", 3, REG_TYPE_INT8, "system", "org.gnu.gdb.arm.secext", NULL, }, /* FPU registers */ - { ARMV7M_D0, "d0", 64, REG_TYPE_IEEE_DOUBLE, "float", "org.gnu.gdb.arm.vfp" }, - { ARMV7M_D1, "d1", 64, REG_TYPE_IEEE_DOUBLE, "float", "org.gnu.gdb.arm.vfp" }, - { ARMV7M_D2, "d2", 64, REG_TYPE_IEEE_DOUBLE, "float", "org.gnu.gdb.arm.vfp" }, - { ARMV7M_D3, "d3", 64, REG_TYPE_IEEE_DOUBLE, "float", "org.gnu.gdb.arm.vfp" }, - { ARMV7M_D4, "d4", 64, REG_TYPE_IEEE_DOUBLE, "float", "org.gnu.gdb.arm.vfp" }, - { ARMV7M_D5, "d5", 64, REG_TYPE_IEEE_DOUBLE, "float", "org.gnu.gdb.arm.vfp" }, - { ARMV7M_D6, "d6", 64, REG_TYPE_IEEE_DOUBLE, "float", "org.gnu.gdb.arm.vfp" }, - { ARMV7M_D7, "d7", 64, REG_TYPE_IEEE_DOUBLE, "float", "org.gnu.gdb.arm.vfp" }, - { ARMV7M_D8, "d8", 64, REG_TYPE_IEEE_DOUBLE, "float", "org.gnu.gdb.arm.vfp" }, - { ARMV7M_D9, "d9", 64, REG_TYPE_IEEE_DOUBLE, "float", "org.gnu.gdb.arm.vfp" }, - { ARMV7M_D10, "d10", 64, REG_TYPE_IEEE_DOUBLE, "float", "org.gnu.gdb.arm.vfp" }, - { ARMV7M_D11, "d11", 64, REG_TYPE_IEEE_DOUBLE, "float", "org.gnu.gdb.arm.vfp" }, - { ARMV7M_D12, "d12", 64, REG_TYPE_IEEE_DOUBLE, "float", "org.gnu.gdb.arm.vfp" }, - { ARMV7M_D13, "d13", 64, REG_TYPE_IEEE_DOUBLE, "float", "org.gnu.gdb.arm.vfp" }, - { ARMV7M_D14, "d14", 64, REG_TYPE_IEEE_DOUBLE, "float", "org.gnu.gdb.arm.vfp" }, - { ARMV7M_D15, "d15", 64, REG_TYPE_IEEE_DOUBLE, "float", "org.gnu.gdb.arm.vfp" }, - - { ARMV7M_FPSCR, "fpscr", 32, REG_TYPE_INT, "float", "org.gnu.gdb.arm.vfp" }, + { ARMV7M_D0, "d0", 64, REG_TYPE_IEEE_DOUBLE, "float", "org.gnu.gdb.arm.vfp", NULL, }, + { ARMV7M_D1, "d1", 64, REG_TYPE_IEEE_DOUBLE, "float", "org.gnu.gdb.arm.vfp", NULL, }, + { ARMV7M_D2, "d2", 64, REG_TYPE_IEEE_DOUBLE, "float", "org.gnu.gdb.arm.vfp", NULL, }, + { ARMV7M_D3, "d3", 64, REG_TYPE_IEEE_DOUBLE, "float", "org.gnu.gdb.arm.vfp", NULL, }, + { ARMV7M_D4, "d4", 64, REG_TYPE_IEEE_DOUBLE, "float", "org.gnu.gdb.arm.vfp", NULL, }, + { ARMV7M_D5, "d5", 64, REG_TYPE_IEEE_DOUBLE, "float", "org.gnu.gdb.arm.vfp", NULL, }, + { ARMV7M_D6, "d6", 64, REG_TYPE_IEEE_DOUBLE, "float", "org.gnu.gdb.arm.vfp", NULL, }, + { ARMV7M_D7, "d7", 64, REG_TYPE_IEEE_DOUBLE, "float", "org.gnu.gdb.arm.vfp", NULL, }, + { ARMV7M_D8, "d8", 64, REG_TYPE_IEEE_DOUBLE, "float", "org.gnu.gdb.arm.vfp", NULL, }, + { ARMV7M_D9, "d9", 64, REG_TYPE_IEEE_DOUBLE, "float", "org.gnu.gdb.arm.vfp", NULL, }, + { ARMV7M_D10, "d10", 64, REG_TYPE_IEEE_DOUBLE, "float", "org.gnu.gdb.arm.vfp", NULL, }, + { ARMV7M_D11, "d11", 64, REG_TYPE_IEEE_DOUBLE, "float", "org.gnu.gdb.arm.vfp", NULL, }, + { ARMV7M_D12, "d12", 64, REG_TYPE_IEEE_DOUBLE, "float", "org.gnu.gdb.arm.vfp", NULL, }, + { ARMV7M_D13, "d13", 64, REG_TYPE_IEEE_DOUBLE, "float", "org.gnu.gdb.arm.vfp", NULL, }, + { ARMV7M_D14, "d14", 64, REG_TYPE_IEEE_DOUBLE, "float", "org.gnu.gdb.arm.vfp", NULL, }, + { ARMV7M_D15, "d15", 64, REG_TYPE_IEEE_DOUBLE, "float", "org.gnu.gdb.arm.vfp", NULL, }, + + { ARMV7M_FPSCR, "fpscr", 32, REG_TYPE_INT, "float", "org.gnu.gdb.arm.vfp", NULL, }, + + { ARMV8M_VPR, "vpr", 32, REG_TYPE_INT, "float", "org.gnu.gdb.arm.m-profile-mve", armv8m_flags_vpr, }, }; #define ARMV7M_NUM_REGS ARRAY_SIZE(armv7m_regs) @@ -171,7 +196,7 @@ int armv7m_restore_context(struct target *target) struct armv7m_common *armv7m = target_to_armv7m(target); struct reg_cache *cache = armv7m->arm.core_cache; - LOG_DEBUG(" "); + LOG_TARGET_DEBUG(target, " "); if (armv7m->pre_restore_context) armv7m->pre_restore_context(target); @@ -272,6 +297,9 @@ uint32_t armv7m_map_id_to_regsel(unsigned int arm_reg_id) case ARMV7M_FPSCR: return ARMV7M_REGSEL_FPSCR; + case ARMV8M_VPR: + return ARMV8M_REGSEL_VPR; + case ARMV7M_D0 ... ARMV7M_D15: return ARMV7M_REGSEL_S0 + 2 * (arm_reg_id - ARMV7M_D0); @@ -366,9 +394,9 @@ static int armv7m_read_core_reg(struct target *target, struct reg *r, buf_set_u32(r->value + 4, 0, 32, reg_value); uint64_t q = buf_get_u64(r->value, 0, 64); - LOG_DEBUG("read %s value 0x%016" PRIx64, r->name, q); + LOG_TARGET_DEBUG(target, "read %s value 0x%016" PRIx64, r->name, q); } else { - LOG_DEBUG("read %s value 0x%08" PRIx32, r->name, reg_value); + LOG_TARGET_DEBUG(target, "read %s value 0x%08" PRIx32, r->name, reg_value); } } @@ -436,9 +464,9 @@ static int armv7m_write_core_reg(struct target *target, struct reg *r, goto out_error; uint64_t q = buf_get_u64(value, 0, 64); - LOG_DEBUG("write %s value 0x%016" PRIx64, r->name, q); + LOG_TARGET_DEBUG(target, "write %s value 0x%016" PRIx64, r->name, q); } else { - LOG_DEBUG("write %s value 0x%08" PRIx32, r->name, t); + LOG_TARGET_DEBUG(target, "write %s value 0x%08" PRIx32, r->name, t); } } @@ -449,7 +477,7 @@ static int armv7m_write_core_reg(struct target *target, struct reg *r, out_error: r->dirty = true; - LOG_ERROR("Error setting register %s", r->name); + LOG_TARGET_ERROR(target, "Error setting register %s", r->name); return retval; } @@ -520,7 +548,7 @@ int armv7m_start_algorithm(struct target *target, * at the exit point */ if (armv7m_algorithm_info->common_magic != ARMV7M_COMMON_MAGIC) { - LOG_ERROR("current target isn't an ARMV7M target"); + LOG_TARGET_ERROR(target, "current target isn't an ARMV7M target"); return ERROR_TARGET_INVALID; } @@ -530,7 +558,7 @@ int armv7m_start_algorithm(struct target *target, } /* Store all non-debug execution registers to armv7m_algorithm_info context */ - for (unsigned i = 0; i < armv7m->arm.core_cache->num_regs; i++) { + for (unsigned int i = 0; i < armv7m->arm.core_cache->num_regs; i++) { struct reg *reg = &armv7m->arm.core_cache->reg_list[i]; if (!reg->exist) continue; @@ -563,12 +591,12 @@ int armv7m_start_algorithm(struct target *target, /* uint32_t regvalue; */ if (!reg) { - LOG_ERROR("BUG: register '%s' not found", reg_params[i].reg_name); + LOG_TARGET_ERROR(target, "BUG: register '%s' not found", reg_params[i].reg_name); return ERROR_COMMAND_SYNTAX_ERROR; } if (reg->size != reg_params[i].size) { - LOG_ERROR("BUG: register '%s' size doesn't match reg_params[i].size", + LOG_TARGET_ERROR(target, "BUG: register '%s' size doesn't match reg_params[i].size", reg_params[i].reg_name); return ERROR_COMMAND_SYNTAX_ERROR; } @@ -600,10 +628,11 @@ int armv7m_start_algorithm(struct target *target, /* we cannot set ARM_MODE_HANDLER, so use ARM_MODE_THREAD instead */ if (armv7m_algorithm_info->core_mode == ARM_MODE_HANDLER) { armv7m_algorithm_info->core_mode = ARM_MODE_THREAD; - LOG_INFO("ARM_MODE_HANDLER not currently supported, using ARM_MODE_THREAD instead"); + LOG_TARGET_INFO(target, "ARM_MODE_HANDLER not currently supported, using ARM_MODE_THREAD instead"); } - LOG_DEBUG("setting core_mode: 0x%2.2x", armv7m_algorithm_info->core_mode); + LOG_TARGET_DEBUG(target, "setting core_mode: 0x%2.2x", + armv7m_algorithm_info->core_mode); buf_set_u32(armv7m->arm.core_cache->reg_list[ARMV7M_CONTROL].value, 0, 1, armv7m_algorithm_info->core_mode); armv7m->arm.core_cache->reg_list[ARMV7M_CONTROL].dirty = true; @@ -613,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; } @@ -633,7 +662,7 @@ int armv7m_wait_algorithm(struct target *target, * at the exit point */ if (armv7m_algorithm_info->common_magic != ARMV7M_COMMON_MAGIC) { - LOG_ERROR("current target isn't an ARMV7M target"); + LOG_TARGET_ERROR(target, "current target isn't an ARMV7M target"); return ERROR_TARGET_INVALID; } @@ -653,7 +682,7 @@ int armv7m_wait_algorithm(struct target *target, /* PC value has been cached in cortex_m_debug_entry() */ uint32_t pc = buf_get_u32(armv7m->arm.pc->value, 0, 32); if (pc != exit_point) { - LOG_DEBUG("failed algorithm halted at 0x%" PRIx32 ", expected 0x%" TARGET_PRIxADDR, + LOG_TARGET_DEBUG(target, "failed algorithm halted at 0x%" PRIx32 ", expected 0x%" TARGET_PRIxADDR, pc, exit_point); return ERROR_TARGET_ALGO_EXIT; } @@ -678,12 +707,13 @@ int armv7m_wait_algorithm(struct target *target, false); if (!reg) { - LOG_ERROR("BUG: register '%s' not found", reg_params[i].reg_name); + LOG_TARGET_ERROR(target, "BUG: register '%s' not found", + reg_params[i].reg_name); return ERROR_COMMAND_SYNTAX_ERROR; } if (reg->size != reg_params[i].size) { - LOG_ERROR( + LOG_TARGET_ERROR(target, "BUG: register '%s' size doesn't match reg_params[i].size", reg_params[i].reg_name); return ERROR_COMMAND_SYNTAX_ERROR; @@ -701,7 +731,7 @@ int armv7m_wait_algorithm(struct target *target, uint32_t regvalue; regvalue = buf_get_u32(reg->value, 0, 32); if (regvalue != armv7m_algorithm_info->context[i]) { - LOG_DEBUG("restoring register %s with value 0x%8.8" PRIx32, + LOG_TARGET_DEBUG(target, "restoring register %s with value 0x%8.8" PRIx32, reg->name, armv7m_algorithm_info->context[i]); buf_set_u32(reg->value, 0, 32, armv7m_algorithm_info->context[i]); @@ -712,7 +742,7 @@ int armv7m_wait_algorithm(struct target *target, /* restore previous core mode */ if (armv7m_algorithm_info->core_mode != armv7m->arm.core_mode) { - LOG_DEBUG("restoring core_mode: 0x%2.2x", armv7m_algorithm_info->core_mode); + LOG_TARGET_DEBUG(target, "restoring core_mode: 0x%2.2x", armv7m_algorithm_info->core_mode); buf_set_u32(armv7m->arm.core_cache->reg_list[ARMV7M_CONTROL].value, 0, 1, armv7m_algorithm_info->core_mode); armv7m->arm.core_cache->reg_list[ARMV7M_CONTROL].dirty = true; @@ -738,9 +768,8 @@ int armv7m_arch_state(struct target *target) ctrl = buf_get_u32(arm->core_cache->reg_list[ARMV7M_CONTROL].value, 0, 32); sp = buf_get_u32(arm->core_cache->reg_list[ARMV7M_R13].value, 0, 32); - LOG_USER("[%s] halted due to %s, current mode: %s %s\n" + LOG_TARGET_USER(target, "halted due to %s, current mode: %s %s\n" "xPSR: %#8.8" PRIx32 " pc: %#8.8" PRIx32 " %csp: %#8.8" PRIx32 "%s%s", - target_name(target), debug_reason_name(target), arm_mode_name(arm->core_mode), armv7m_exception_string(armv7m->exception_number), @@ -807,13 +836,17 @@ struct reg_cache *armv7m_build_reg_cache(struct target *target) feature->name = armv7m_regs[i].feature; reg_list[i].feature = feature; } else - LOG_ERROR("unable to allocate feature list"); + LOG_TARGET_ERROR(target, "unable to allocate feature list"); reg_list[i].reg_data_type = calloc(1, sizeof(struct reg_data_type)); - if (reg_list[i].reg_data_type) - reg_list[i].reg_data_type->type = armv7m_regs[i].type; - else - LOG_ERROR("unable to allocate reg type list"); + if (reg_list[i].reg_data_type) { + if (armv7m_regs[i].data_type) + *reg_list[i].reg_data_type = *armv7m_regs[i].data_type; + else + reg_list[i].reg_data_type->type = armv7m_regs[i].type; + } else { + LOG_TARGET_ERROR(target, "unable to allocate reg type list"); + } } arm->cpsr = reg_list + ARMV7M_XPSR; @@ -918,7 +951,7 @@ int armv7m_checksum_memory(struct target *target, if (retval == ERROR_OK) *checksum = buf_get_u32(reg_params[0].value, 0, 32); else - LOG_ERROR("error executing cortex_m crc algorithm"); + LOG_TARGET_ERROR(target, "error executing cortex_m crc algorithm"); destroy_reg_param(®_params[0]); destroy_reg_param(®_params[1]); @@ -1003,7 +1036,7 @@ int armv7m_blank_check_memory(struct target *target, uint32_t erased_word = erased_value | (erased_value << 8) | (erased_value << 16) | (erased_value << 24); - LOG_DEBUG("Starting erase check of %d blocks, parameters@" + LOG_TARGET_DEBUG(target, "Starting erase check of %d blocks, parameters@" TARGET_ADDR_FMT, blocks_to_check, erase_check_params->address); armv7m_info.common_magic = ARMV7M_COMMON_MAGIC; @@ -1044,7 +1077,8 @@ int armv7m_blank_check_memory(struct target *target, blocks[i].result = result; } if (i && timed_out) - LOG_INFO("Slow CPU clock: %d blocks checked, %d remain. Continuing...", i, num_blocks-i); + LOG_TARGET_INFO(target, "Slow CPU clock: %d blocks checked, %d remain. Continuing...", + i, num_blocks - i); retval = i; /* return number of blocks really checked */ @@ -1085,7 +1119,7 @@ int armv7m_maybe_skip_bkpt_inst(struct target *target, bool *inst_found) r->dirty = true; r->valid = true; result = true; - LOG_DEBUG("Skipping over BKPT instruction"); + LOG_TARGET_DEBUG(target, "Skipping over BKPT instruction"); } } } diff --git a/src/target/armv7m.h b/src/target/armv7m.h index 2878dd1..86c45f7 100644 --- a/src/target/armv7m.h +++ b/src/target/armv7m.h @@ -62,6 +62,7 @@ enum { ARMV7M_REGSEL_PMSK_BPRI_FLTMSK_CTRL = 0x14, ARMV8M_REGSEL_PMSK_BPRI_FLTMSK_CTRL_S = 0x22, ARMV8M_REGSEL_PMSK_BPRI_FLTMSK_CTRL_NS = 0x23, + ARMV8M_REGSEL_VPR = 0x24, ARMV7M_REGSEL_FPSCR = 0x21, /* 32bit Floating-point registers */ @@ -196,12 +197,15 @@ enum { /* Floating-point status register */ ARMV7M_FPSCR, + /* Vector Predication Status and Control Register */ + ARMV8M_VPR, + /* for convenience add registers' block delimiters */ ARMV7M_LAST_REG, ARMV7M_CORE_FIRST_REG = ARMV7M_R0, ARMV7M_CORE_LAST_REG = ARMV7M_XPSR, ARMV7M_FPU_FIRST_REG = ARMV7M_D0, - ARMV7M_FPU_LAST_REG = ARMV7M_FPSCR, + ARMV7M_FPU_LAST_REG = ARMV8M_VPR, ARMV8M_FIRST_REG = ARMV8M_MSP_NS, ARMV8M_LAST_REG = ARMV8M_CONTROL_NS, }; diff --git a/src/target/armv8.c b/src/target/armv8.c index b54ef13..4039073 100644 --- a/src/target/armv8.c +++ b/src/target/armv8.c @@ -36,7 +36,7 @@ static const char * const armv8_state_strings[] = { static const struct { const char *name; - unsigned psr; + unsigned int psr; } armv8_mode_data[] = { { .name = "USR", @@ -105,9 +105,9 @@ static const struct { }; /** Map PSR mode bits to the name of an ARM processor operating mode. */ -const char *armv8_mode_name(unsigned psr_mode) +const char *armv8_mode_name(unsigned int psr_mode) { - for (unsigned i = 0; i < ARRAY_SIZE(armv8_mode_data); i++) { + for (unsigned int i = 0; i < ARRAY_SIZE(armv8_mode_data); i++) { if (armv8_mode_data[i].psr == psr_mode) return armv8_mode_data[i].name; } @@ -683,7 +683,7 @@ static int armv8_read_reg_simdfp_aarch32(struct armv8_common *armv8, int regnum, struct arm_dpm *dpm = &armv8->dpm; struct reg *reg_r1 = dpm->arm->core_cache->reg_list + ARMV8_R1; uint32_t value_r0 = 0, value_r1 = 0; - unsigned num = (regnum - ARMV8_V0) << 1; + unsigned int num = (regnum - ARMV8_V0) << 1; switch (regnum) { case ARMV8_V0 ... ARMV8_V15: @@ -817,7 +817,7 @@ static int armv8_write_reg_simdfp_aarch32(struct armv8_common *armv8, int regnum struct arm_dpm *dpm = &armv8->dpm; struct reg *reg_r1 = dpm->arm->core_cache->reg_list + ARMV8_R1; uint32_t value_r0 = 0, value_r1 = 0; - unsigned num = (regnum - ARMV8_V0) << 1; + unsigned int num = (regnum - ARMV8_V0) << 1; switch (regnum) { case ARMV8_V0 ... ARMV8_V15: @@ -961,7 +961,7 @@ void armv8_set_cpsr(struct arm *arm, uint32_t cpsr) arm->core_state = state; arm->core_mode = mode; - LOG_DEBUG("set CPSR %#8.8x: %s mode, %s state", (unsigned) cpsr, + LOG_DEBUG("set CPSR %#8.8" PRIx32 ": %s mode, %s state", cpsr, armv8_mode_name(arm->core_mode), armv8_state_strings[arm->core_state]); } @@ -1010,7 +1010,7 @@ static void armv8_show_fault_registers32(struct armv8_common *armv8) ", IFAR: %8.8" PRIx32, ifsr, ifar); done: - /* (void) */ dpm->finish(dpm); + dpm->finish(dpm); } static __attribute__((unused)) void armv8_show_fault_registers(struct target *target) @@ -1021,12 +1021,6 @@ static __attribute__((unused)) void armv8_show_fault_registers(struct target *ta armv8_show_fault_registers32(armv8); } -/* method adapted to cortex A : reused arm v4 v5 method*/ -int armv8_mmu_translate_va(struct target *target, target_addr_t va, target_addr_t *val) -{ - return ERROR_OK; -} - static void armv8_decode_cacheability(int attr) { if (attr == 0) { @@ -1506,9 +1500,9 @@ static struct reg_data_type aarch64_flags_cpsr[] = { }; static const struct { - unsigned id; + unsigned int id; const char *name; - unsigned bits; + unsigned int bits; enum arm_mode mode; enum reg_type type; const char *group; @@ -1611,10 +1605,10 @@ static const struct { }; static const struct { - unsigned id; - unsigned mapping; + unsigned int id; + unsigned int mapping; const char *name; - unsigned bits; + unsigned int bits; enum arm_mode mode; enum reg_type type; const char *group; @@ -1692,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 { @@ -1705,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); @@ -1881,7 +1876,7 @@ struct reg_cache *armv8_build_reg_cache(struct target *target) return cache; } -struct reg *armv8_reg_current(struct arm *arm, unsigned regnum) +struct reg *armv8_reg_current(struct arm *arm, unsigned int regnum) { struct reg *r; @@ -1972,7 +1967,7 @@ int armv8_get_gdb_reg_list(struct target *target, *reg_list = malloc(sizeof(struct reg *) * (*reg_list_size)); for (i = 0; i < *reg_list_size; i++) - (*reg_list)[i] = armv8_reg_current(arm, i); + (*reg_list)[i] = armv8_reg_current(arm, i); return ERROR_OK; case REG_CLASS_ALL: @@ -1980,7 +1975,7 @@ int armv8_get_gdb_reg_list(struct target *target, *reg_list = malloc(sizeof(struct reg *) * (*reg_list_size)); for (i = 0; i < *reg_list_size; i++) - (*reg_list)[i] = armv8_reg_current(arm, i); + (*reg_list)[i] = armv8_reg_current(arm, i); return ERROR_OK; diff --git a/src/target/armv8.h b/src/target/armv8.h index f5aa211..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); }; @@ -213,6 +214,8 @@ struct armv8_common { /* True if OpenOCD provides pointer auth related info to GDB */ bool enable_pauth; + bool sticky_reset; + /* last run-control command issued to this target (resume, halt, step) */ enum run_control_op last_run_control_op; @@ -296,7 +299,6 @@ int armv8_identify_cache(struct armv8_common *armv8); int armv8_init_arch_info(struct target *target, struct armv8_common *armv8); int armv8_mmu_translate_va_pa(struct target *target, target_addr_t va, target_addr_t *val, int meminfo); -int armv8_mmu_translate_va(struct target *target, target_addr_t va, target_addr_t *val); int armv8_handle_cache_info_command(struct command_invocation *cmd, struct armv8_cache_common *armv8_cache); @@ -327,7 +329,7 @@ static inline unsigned int armv8_curel_from_core_mode(enum arm_mode core_mode) } } -const char *armv8_mode_name(unsigned psr_mode); +const char *armv8_mode_name(unsigned int psr_mode); void armv8_select_reg_access(struct armv8_common *armv8, bool is_aarch64); int armv8_set_dbgreg_bits(struct armv8_common *armv8, unsigned int reg, unsigned long mask, unsigned long value); 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_dpm.c b/src/target/armv8_dpm.c index 271bd91..d1cee8a 100644 --- a/src/target/armv8_dpm.c +++ b/src/target/armv8_dpm.c @@ -417,7 +417,7 @@ static int dpmv8_instr_read_data_r0_64(struct arm_dpm *dpm, } #if 0 -static int dpmv8_bpwp_enable(struct arm_dpm *dpm, unsigned index_t, +static int dpmv8_bpwp_enable(struct arm_dpm *dpm, unsigned int index_t, target_addr_t addr, uint32_t control) { struct armv8_common *armv8 = dpm->arm->arch_info; @@ -441,8 +441,7 @@ static int dpmv8_bpwp_enable(struct arm_dpm *dpm, unsigned index_t, vr += 16 * index_t; cr += 16 * index_t; - LOG_DEBUG("A8: bpwp enable, vr %08x cr %08x", - (unsigned) vr, (unsigned) cr); + LOG_DEBUG("A8: bpwp enable, vr %08" PRIx32 " cr %08" PRIx32, vr, cr); retval = mem_ap_write_atomic_u32(armv8->debug_ap, vr, addr); if (retval != ERROR_OK) @@ -451,7 +450,7 @@ static int dpmv8_bpwp_enable(struct arm_dpm *dpm, unsigned index_t, } #endif -static int dpmv8_bpwp_disable(struct arm_dpm *dpm, unsigned index_t) +static int dpmv8_bpwp_disable(struct arm_dpm *dpm, unsigned int index_t) { struct armv8_common *armv8 = dpm->arm->arch_info; uint32_t cr; @@ -469,7 +468,7 @@ static int dpmv8_bpwp_disable(struct arm_dpm *dpm, unsigned index_t) } cr += 16 * index_t; - LOG_DEBUG("A: bpwp disable, cr %08x", (unsigned) cr); + LOG_DEBUG("A: bpwp disable, cr %08" PRIx32, cr); /* clear control register */ return mem_ap_write_atomic_u32(armv8->debug_ap, cr, 0); @@ -501,7 +500,7 @@ static int dpmv8_mrc(struct target *target, int cpnum, ARMV4_5_MRC(cpnum, op1, 0, crn, crm, op2), value); - /* (void) */ dpm->finish(dpm); + dpm->finish(dpm); return retval; } @@ -526,7 +525,7 @@ static int dpmv8_mcr(struct target *target, int cpnum, ARMV4_5_MCR(cpnum, op1, 0, crn, crm, op2), value); - /* (void) */ dpm->finish(dpm); + dpm->finish(dpm); return retval; } @@ -642,7 +641,7 @@ int armv8_dpm_modeswitch(struct arm_dpm *dpm, enum arm_mode mode) /* * Common register read, relies on armv8_select_reg_access() having been called. */ -static int dpmv8_read_reg(struct arm_dpm *dpm, struct reg *r, unsigned regnum) +static int dpmv8_read_reg(struct arm_dpm *dpm, struct reg *r, unsigned int regnum) { struct armv8_common *armv8 = dpm->arm->arch_info; int retval = ERROR_FAIL; @@ -685,7 +684,7 @@ static int dpmv8_read_reg(struct arm_dpm *dpm, struct reg *r, unsigned regnum) /* * Common register write, relies on armv8_select_reg_access() having been called. */ -static int dpmv8_write_reg(struct arm_dpm *dpm, struct reg *r, unsigned regnum) +static int dpmv8_write_reg(struct arm_dpm *dpm, struct reg *r, unsigned int regnum) { struct armv8_common *armv8 = dpm->arm->arch_info; int retval = ERROR_FAIL; @@ -888,7 +887,7 @@ int armv8_dpm_write_dirty_registers(struct arm_dpm *dpm, bool bpwp) * cope with the hand-crafted breakpoint code. */ if (arm->target->type->add_breakpoint == dpmv8_add_breakpoint) { - for (unsigned i = 0; i < dpm->nbp; i++) { + for (unsigned int i = 0; i < dpm->nbp; i++) { struct dpm_bp *dbp = dpm->dbp + i; struct breakpoint *bp = dbp->bp; @@ -900,7 +899,7 @@ int armv8_dpm_write_dirty_registers(struct arm_dpm *dpm, bool bpwp) } /* enable/disable watchpoints */ - for (unsigned i = 0; i < dpm->nwp; i++) { + for (unsigned int i = 0; i < dpm->nwp; i++) { struct dpm_wp *dwp = dpm->dwp + i; struct watchpoint *wp = dwp->wp; @@ -920,7 +919,7 @@ int armv8_dpm_write_dirty_registers(struct arm_dpm *dpm, bool bpwp) goto done; /* check everything except our scratch register R0 */ - for (unsigned i = 1; i < cache->num_regs; i++) { + for (unsigned int i = 1; i < cache->num_regs; i++) { struct arm_reg *r; /* skip non-existent */ @@ -992,7 +991,7 @@ static int armv8_dpm_read_core_reg(struct target *target, struct reg *r, goto fail; fail: - /* (void) */ dpm->finish(dpm); + dpm->finish(dpm); return retval; } @@ -1048,7 +1047,7 @@ static int armv8_dpm_full_context(struct target *target) * Pick some mode with unread registers and read them all. * Repeat until done. */ - for (unsigned i = 0; i < cache->num_regs; i++) { + for (unsigned int i = 0; i < cache->num_regs; i++) { struct arm_reg *r; if (!cache->reg_list[i].exist || cache->reg_list[i].valid) @@ -1086,7 +1085,7 @@ static int armv8_dpm_full_context(struct target *target) } while (did_read); retval = armv8_dpm_modeswitch(dpm, ARM_MODE_ANY); - /* (void) */ dpm->finish(dpm); + dpm->finish(dpm); done: return retval; } @@ -1176,7 +1175,7 @@ static int dpmv8_add_breakpoint(struct target *target, struct breakpoint *bp) if (bp->type == BKPT_SOFT) LOG_DEBUG("using HW bkpt, not SW..."); - for (unsigned i = 0; i < dpm->nbp; i++) { + for (unsigned int i = 0; i < dpm->nbp; i++) { if (!dpm->dbp[i].bp) { retval = dpmv8_bpwp_setup(dpm, &dpm->dbp[i].bpwp, bp->address, bp->length); @@ -1195,7 +1194,7 @@ static int dpmv8_remove_breakpoint(struct target *target, struct breakpoint *bp) struct arm_dpm *dpm = arm->dpm; int retval = ERROR_COMMAND_SYNTAX_ERROR; - for (unsigned i = 0; i < dpm->nbp; i++) { + for (unsigned int i = 0; i < dpm->nbp; i++) { if (dpm->dbp[i].bp == bp) { dpm->dbp[i].bp = NULL; dpm->dbp[i].bpwp.dirty = true; @@ -1209,7 +1208,7 @@ static int dpmv8_remove_breakpoint(struct target *target, struct breakpoint *bp) return retval; } -static int dpmv8_watchpoint_setup(struct arm_dpm *dpm, unsigned index_t, +static int dpmv8_watchpoint_setup(struct arm_dpm *dpm, unsigned int index_t, struct watchpoint *wp) { int retval; @@ -1252,7 +1251,7 @@ static int dpmv8_add_watchpoint(struct target *target, struct watchpoint *wp) int retval = ERROR_TARGET_RESOURCE_NOT_AVAILABLE; if (dpm->bpwp_enable) { - for (unsigned i = 0; i < dpm->nwp; i++) { + for (unsigned int i = 0; i < dpm->nwp; i++) { if (!dpm->dwp[i].wp) { retval = dpmv8_watchpoint_setup(dpm, i, wp); break; @@ -1269,7 +1268,7 @@ static int dpmv8_remove_watchpoint(struct target *target, struct watchpoint *wp) struct arm_dpm *dpm = arm->dpm; int retval = ERROR_COMMAND_SYNTAX_ERROR; - for (unsigned i = 0; i < dpm->nwp; i++) { + for (unsigned int i = 0; i < dpm->nwp; i++) { if (dpm->dwp[i].wp == wp) { dpm->dwp[i].wp = NULL; dpm->dwp[i].bpwp.dirty = true; @@ -1485,7 +1484,7 @@ int armv8_dpm_initialize(struct arm_dpm *dpm) { /* Disable all breakpoints and watchpoints at startup. */ if (dpm->bpwp_disable) { - unsigned i; + unsigned int i; for (i = 0; i < dpm->nbp; i++) { dpm->dbp[i].bpwp.number = i; 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 61bef32..3afe320 100644 --- a/src/target/avrt.c +++ b/src/target/avrt.c @@ -22,19 +22,19 @@ 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); /* IR and DR functions */ -static int mcu_write_ir(struct jtag_tap *tap, uint8_t *ir_in, uint8_t *ir_out, int ir_len, int rti); -static int mcu_write_dr(struct jtag_tap *tap, uint8_t *dr_in, uint8_t *dr_out, int dr_len, int rti); -static int mcu_write_ir_u8(struct jtag_tap *tap, uint8_t *ir_in, uint8_t ir_out, int ir_len, int rti); -static int mcu_write_dr_u32(struct jtag_tap *tap, uint32_t *ir_in, uint32_t ir_out, int dr_len, int rti); +static int mcu_write_ir(struct jtag_tap *tap, uint8_t *ir_in, uint8_t *ir_out, int ir_len); +static int mcu_write_dr(struct jtag_tap *tap, uint8_t *dr_in, uint8_t *dr_out, int dr_len); +static int mcu_write_ir_u8(struct jtag_tap *tap, uint8_t *ir_in, uint8_t ir_out, int ir_len); +static int mcu_write_dr_u32(struct jtag_tap *tap, uint32_t *ir_in, uint32_t ir_out, int dr_len); struct target_type avr_target = { .name = "avr", @@ -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; @@ -137,23 +138,23 @@ static int avr_deassert_reset(struct target *target) int avr_jtag_senddat(struct jtag_tap *tap, uint32_t *dr_in, uint32_t dr_out, int len) { - return mcu_write_dr_u32(tap, dr_in, dr_out, len, 1); + return mcu_write_dr_u32(tap, dr_in, dr_out, len); } int avr_jtag_sendinstr(struct jtag_tap *tap, uint8_t *ir_in, uint8_t ir_out) { - return mcu_write_ir_u8(tap, ir_in, ir_out, AVR_JTAG_INS_LEN, 1); + return mcu_write_ir_u8(tap, ir_in, ir_out, AVR_JTAG_INS_LEN); } /* IR and DR functions */ static int mcu_write_ir(struct jtag_tap *tap, uint8_t *ir_in, uint8_t *ir_out, - int ir_len, int rti) + int ir_len) { if (!tap) { LOG_ERROR("invalid tap"); return ERROR_FAIL; } - if (ir_len != tap->ir_length) { + if ((unsigned int)ir_len != tap->ir_length) { LOG_ERROR("invalid ir_len"); return ERROR_FAIL; } @@ -166,7 +167,7 @@ static int mcu_write_ir(struct jtag_tap *tap, uint8_t *ir_in, uint8_t *ir_out, } static int mcu_write_dr(struct jtag_tap *tap, uint8_t *dr_in, uint8_t *dr_out, - int dr_len, int rti) + int dr_len) { if (!tap) { LOG_ERROR("invalid tap"); @@ -181,27 +182,27 @@ static int mcu_write_dr(struct jtag_tap *tap, uint8_t *dr_in, uint8_t *dr_out, } static int mcu_write_ir_u8(struct jtag_tap *tap, uint8_t *ir_in, - uint8_t ir_out, int ir_len, int rti) + uint8_t ir_out, int ir_len) { if (ir_len > 8) { LOG_ERROR("ir_len overflow, maximum is 8"); return ERROR_FAIL; } - mcu_write_ir(tap, ir_in, &ir_out, ir_len, rti); + mcu_write_ir(tap, ir_in, &ir_out, ir_len); return ERROR_OK; } static int mcu_write_dr_u32(struct jtag_tap *tap, uint32_t *dr_in, - uint32_t dr_out, int dr_len, int rti) + uint32_t dr_out, int dr_len) { if (dr_len > 32) { LOG_ERROR("dr_len overflow, maximum is 32"); return ERROR_FAIL; } - mcu_write_dr(tap, (uint8_t *)dr_in, (uint8_t *)&dr_out, dr_len, rti); + mcu_write_dr(tap, (uint8_t *)dr_in, (uint8_t *)&dr_out, dr_len); return ERROR_OK; } diff --git a/src/target/breakpoints.c b/src/target/breakpoints.c index 77f7673..0e9ae6e 100644 --- a/src/target/breakpoints.c +++ b/src/target/breakpoints.c @@ -39,7 +39,7 @@ static int bpwp_unique_id; static int breakpoint_add_internal(struct target *target, target_addr_t address, - uint32_t length, + unsigned int length, enum breakpoint_type type) { struct breakpoint *breakpoint = target->breakpoints; @@ -102,7 +102,7 @@ fail: static int context_breakpoint_add_internal(struct target *target, uint32_t asid, - uint32_t length, + unsigned int length, enum breakpoint_type type) { struct breakpoint *breakpoint = target->breakpoints; @@ -115,7 +115,7 @@ static int context_breakpoint_add_internal(struct target *target, * breakpoint" ... check all the parameters before * succeeding. */ - LOG_ERROR("Duplicate Breakpoint asid: 0x%08" PRIx32 " (BP %" PRIu32 ")", + LOG_TARGET_ERROR(target, "Duplicate Breakpoint asid: 0x%08" PRIx32 " (BP %" PRIu32 ")", asid, breakpoint->unique_id); return ERROR_TARGET_DUPLICATE_BREAKPOINT; } @@ -152,7 +152,7 @@ static int context_breakpoint_add_internal(struct target *target, static int hybrid_breakpoint_add_internal(struct target *target, target_addr_t address, uint32_t asid, - uint32_t length, + unsigned int length, enum breakpoint_type type) { struct breakpoint *breakpoint = target->breakpoints; @@ -208,7 +208,7 @@ static int hybrid_breakpoint_add_internal(struct target *target, int breakpoint_add(struct target *target, target_addr_t address, - uint32_t length, + unsigned int length, enum breakpoint_type type) { if (target->smp && type == BKPT_HARD) { @@ -232,7 +232,7 @@ int breakpoint_add(struct target *target, int context_breakpoint_add(struct target *target, uint32_t asid, - uint32_t length, + unsigned int length, enum breakpoint_type type) { if (target->smp) { @@ -256,7 +256,7 @@ int context_breakpoint_add(struct target *target, int hybrid_breakpoint_add(struct target *target, target_addr_t address, uint32_t asid, - uint32_t length, + unsigned int length, enum breakpoint_type type) { if (target->smp) { @@ -542,7 +542,7 @@ struct breakpoint *breakpoint_find(struct target *target, target_addr_t address) } static int watchpoint_add_internal(struct target *target, target_addr_t address, - uint32_t length, enum watchpoint_rw rw, uint64_t value, uint64_t mask) + unsigned int length, enum watchpoint_rw rw, uint64_t value, uint64_t mask) { struct watchpoint *watchpoint = target->watchpoints; struct watchpoint **watchpoint_p = &target->watchpoints; @@ -598,7 +598,7 @@ bye: } LOG_TARGET_DEBUG(target, "added %s watchpoint at " TARGET_ADDR_FMT - " of length 0x%8.8" PRIx32 " (WPID: %d)", + " of length 0x%8.8x (WPID: %d)", watchpoint_rw_strings[(*watchpoint_p)->rw], (*watchpoint_p)->address, (*watchpoint_p)->length, @@ -608,7 +608,7 @@ bye: } int watchpoint_add(struct target *target, target_addr_t address, - uint32_t length, enum watchpoint_rw rw, uint64_t value, uint64_t mask) + unsigned int length, enum watchpoint_rw rw, uint64_t value, uint64_t mask) { if (target->smp) { struct target_list *head; @@ -687,8 +687,7 @@ int watchpoint_remove(struct target *target, target_addr_t address) int watchpoint_clear_target(struct target *target) { - LOG_DEBUG("Delete all watchpoints for target: %s", - target_name(target)); + LOG_TARGET_DEBUG(target, "Delete all watchpoints"); struct watchpoint *watchpoint = target->watchpoints; int retval = ERROR_OK; diff --git a/src/target/breakpoints.h b/src/target/breakpoints.h index 0ec65de..ac5d701 100644 --- a/src/target/breakpoints.h +++ b/src/target/breakpoints.h @@ -26,7 +26,7 @@ enum watchpoint_rw { struct breakpoint { target_addr_t address; uint32_t asid; - int length; + unsigned int length; enum breakpoint_type type; bool is_set; unsigned int number; @@ -40,7 +40,7 @@ struct breakpoint { struct watchpoint { target_addr_t address; - uint32_t length; + unsigned int length; uint64_t mask; uint64_t value; enum watchpoint_rw rw; @@ -52,11 +52,12 @@ struct watchpoint { int breakpoint_clear_target(struct target *target); int breakpoint_add(struct target *target, - target_addr_t address, uint32_t length, enum breakpoint_type type); + target_addr_t address, unsigned int length, enum breakpoint_type type); int context_breakpoint_add(struct target *target, - uint32_t asid, uint32_t length, enum breakpoint_type type); + uint32_t asid, unsigned int length, enum breakpoint_type type); int hybrid_breakpoint_add(struct target *target, - target_addr_t address, uint32_t asid, uint32_t length, enum breakpoint_type type); + target_addr_t address, uint32_t asid, unsigned int length, + enum breakpoint_type type); int breakpoint_remove(struct target *target, target_addr_t address); int breakpoint_remove_all(struct target *target); @@ -70,7 +71,7 @@ static inline void breakpoint_hw_set(struct breakpoint *breakpoint, unsigned int int watchpoint_clear_target(struct target *target); int watchpoint_add(struct target *target, - target_addr_t address, uint32_t length, + target_addr_t address, unsigned int length, enum watchpoint_rw rw, uint64_t value, uint64_t mask); int watchpoint_remove(struct target *target, target_addr_t address); int watchpoint_remove_all(struct target *target); diff --git a/src/target/cortex_a.c b/src/target/cortex_a.c index 2de77c9..9c60645 100644 --- a/src/target/cortex_a.c +++ b/src/target/cortex_a.c @@ -571,7 +571,7 @@ static int cortex_a_instr_read_data_r0_r1(struct arm_dpm *dpm, return retval; } -static int cortex_a_bpwp_enable(struct arm_dpm *dpm, unsigned index_t, +static int cortex_a_bpwp_enable(struct arm_dpm *dpm, unsigned int index_t, uint32_t addr, uint32_t control) { struct cortex_a_common *a = dpm_to_a(dpm); @@ -595,8 +595,7 @@ static int cortex_a_bpwp_enable(struct arm_dpm *dpm, unsigned index_t, vr += 4 * index_t; cr += 4 * index_t; - LOG_DEBUG("A: bpwp enable, vr %08x cr %08x", - (unsigned) vr, (unsigned) cr); + LOG_DEBUG("A: bpwp enable, vr %08" PRIx32 " cr %08" PRIx32, vr, cr); retval = mem_ap_write_atomic_u32(a->armv7a_common.debug_ap, vr, addr); @@ -607,7 +606,7 @@ static int cortex_a_bpwp_enable(struct arm_dpm *dpm, unsigned index_t, return retval; } -static int cortex_a_bpwp_disable(struct arm_dpm *dpm, unsigned index_t) +static int cortex_a_bpwp_disable(struct arm_dpm *dpm, unsigned int index_t) { struct cortex_a_common *a = dpm_to_a(dpm); uint32_t cr; @@ -625,7 +624,7 @@ static int cortex_a_bpwp_disable(struct arm_dpm *dpm, unsigned index_t) } cr += 4 * index_t; - LOG_DEBUG("A: bpwp disable, cr %08x", (unsigned) cr); + LOG_DEBUG("A: bpwp disable, cr %08" PRIx32, cr); /* clear control register */ return mem_ap_write_atomic_u32(a->armv7a_common.debug_ap, cr, 0); @@ -818,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; @@ -850,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; @@ -966,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; @@ -977,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 */ @@ -998,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); @@ -1169,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); @@ -1185,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); @@ -1196,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) @@ -1223,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; @@ -1325,21 +1325,21 @@ static int cortex_a_set_breakpoint(struct target *target, brp_list[brp_i].value); } else if (breakpoint->type == BKPT_SOFT) { uint8_t code[4]; - /* length == 2: Thumb breakpoint */ - if (breakpoint->length == 2) + if (breakpoint->length == 2) { + /* length == 2: Thumb breakpoint */ buf_set_u32(code, 0, 32, ARMV5_T_BKPT(0x11)); - else - /* length == 3: Thumb-2 breakpoint, actual encoding is - * a regular Thumb BKPT instruction but we replace a - * 32bit Thumb-2 instruction, so fix-up the breakpoint - * length - */ - if (breakpoint->length == 3) { + } else if (breakpoint->length == 3) { + /* length == 3: Thumb-2 breakpoint, actual encoding is + * a regular Thumb BKPT instruction but we replace a + * 32bit Thumb-2 instruction, so fix-up the breakpoint + * length + */ buf_set_u32(code, 0, 32, ARMV5_T_BKPT(0x11)); breakpoint->length = 4; - } else + } else { /* length == 4, normal ARM breakpoint */ buf_set_u32(code, 0, 32, ARMV5_BKPT(0x11)); + } retval = target_read_memory(target, breakpoint->address & 0xFFFFFFFE, @@ -1349,8 +1349,7 @@ static int cortex_a_set_breakpoint(struct target *target, return retval; /* make sure data cache is cleaned & invalidated down to PoC */ - armv7a_cache_flush_virt(target, breakpoint->address, - breakpoint->length); + armv7a_cache_flush_virt(target, breakpoint->address, breakpoint->length); retval = target_write_memory(target, breakpoint->address & 0xFFFFFFFE, @@ -1359,10 +1358,8 @@ static int cortex_a_set_breakpoint(struct target *target, return retval; /* update i-cache at breakpoint location */ - armv7a_l1_d_cache_inval_virt(target, breakpoint->address, - breakpoint->length); - armv7a_l1_i_cache_inval_virt(target, breakpoint->address, - breakpoint->length); + armv7a_l1_d_cache_inval_virt(target, breakpoint->address, breakpoint->length); + armv7a_l1_i_cache_inval_virt(target, breakpoint->address, breakpoint->length); breakpoint->is_set = true; } @@ -2926,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, @@ -2942,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 34c7cd4..e17f23c 100644 --- a/src/target/cortex_m.c +++ b/src/target/cortex_m.c @@ -100,6 +100,12 @@ static const struct cortex_m_part_info cortex_m_parts[] = { .flags = CORTEX_M_F_HAS_FPV5, }, { + .impl_part = CORTEX_M52_PARTNO, + .name = "Cortex-M52", + .arch = ARM_ARCH_V8M, + .flags = CORTEX_M_F_HAS_FPV5, + }, + { .impl_part = CORTEX_M55_PARTNO, .name = "Cortex-M55", .arch = ARM_ARCH_V8M, @@ -273,7 +279,8 @@ static int cortex_m_fast_read_all_regs(struct target *target) /* because the DCB_DCRDR is used for the emulated dcc channel * we have to save/restore the DCB_DCRDR when used */ - if (target->dbg_msg_enabled) { + bool dbg_msg_enabled = target->dbg_msg_enabled; + if (dbg_msg_enabled) { retval = mem_ap_read_u32(armv7m->debug_ap, DCB_DCRDR, &dcrdr); if (retval != ERROR_OK) return retval; @@ -326,7 +333,7 @@ static int cortex_m_fast_read_all_regs(struct target *target) if (retval != ERROR_OK) return retval; - if (target->dbg_msg_enabled) { + if (dbg_msg_enabled) { /* restore DCB_DCRDR - this needs to be in a separate * transaction otherwise the emulated DCC channel breaks */ retval = mem_ap_write_atomic_u32(armv7m->debug_ap, DCB_DCRDR, dcrdr); @@ -797,6 +804,42 @@ static int cortex_m_examine_exception_reason(struct target *target) return retval; } +/* Errata 3092511 workaround + * Cortex-M7 can halt in an incorrect address when breakpoint + * and exception occurs simultaneously */ +static int cortex_m_erratum_check_breakpoint(struct target *target) +{ + struct cortex_m_common *cortex_m = target_to_cm(target); + struct armv7m_common *armv7m = &cortex_m->armv7m; + struct arm *arm = &armv7m->arm; + + uint32_t pc = buf_get_u32(arm->pc->value, 0, 32); + + /* To reduce the workaround processing cost we assume FPB is in sync + * with OpenOCD breakpoints. If the target app writes to FPB + * OpenOCD will resume after the break set by app */ + struct breakpoint *bkpt = breakpoint_find(target, pc); + if (bkpt) { + LOG_TARGET_DEBUG(target, "Erratum 3092511: breakpoint confirmed"); + return ERROR_OK; + } + if (pc >= 0xe0000000u) + /* not executable area, do not read instruction @ pc */ + return ERROR_OK; + + uint16_t insn; + int retval = target_read_u16(target, pc, &insn); + if (retval != ERROR_OK) + return ERROR_OK; /* do not propagate the error, just avoid workaround */ + + if ((insn & 0xff00) == (ARMV5_T_BKPT(0) & 0xff00)) { + LOG_TARGET_DEBUG(target, "Erratum 3092511: breakpoint embedded in code confirmed"); + return ERROR_OK; + } + LOG_TARGET_DEBUG(target, "Erratum 3092511: breakpoint not found, proceed with resume"); + return ERROR_TARGET_HALTED_DO_RESUME; +} + static int cortex_m_debug_entry(struct target *target) { uint32_t xpsr; @@ -855,7 +898,7 @@ static int cortex_m_debug_entry(struct target *target) arm->core_mode = ARM_MODE_HANDLER; arm->map = armv7m_msp_reg_map; } else { - unsigned control = buf_get_u32(arm->core_cache + unsigned int control = buf_get_u32(arm->core_cache ->reg_list[ARMV7M_CONTROL].value, 0, 3); /* is this thread privileged? */ @@ -883,6 +926,17 @@ static int cortex_m_debug_entry(struct target *target) secure_state ? "Secure" : "Non-Secure", target_state_name(target)); + /* Errata 3092511 workaround + * Cortex-M7 can halt in an incorrect address when breakpoint + * and exception occurs simultaneously */ + if (cortex_m->incorrect_halt_erratum + && armv7m->exception_number + && cortex_m->nvic_dfsr == (DFSR_BKPT | DFSR_HALTED)) { + retval = cortex_m_erratum_check_breakpoint(target); + if (retval != ERROR_OK) + return retval; + } + if (armv7m->post_debug_entry) { retval = armv7m->post_debug_entry(target); if (retval != ERROR_OK) @@ -935,6 +989,18 @@ static int cortex_m_poll_one(struct target *target) * and keep it until the next poll to allow its detection */ return ERROR_OK; } + + /* refresh status bits */ + retval = cortex_m_read_dhcsr_atomic_sticky(target); + if (retval != ERROR_OK) + return retval; + + /* If still under reset, quit and re-check at next poll */ + if (cortex_m->dcb_dhcsr_cumulated_sticky & S_RESET_ST) { + cortex_m->dcb_dhcsr_cumulated_sticky &= ~S_RESET_ST; + return ERROR_OK; + } + /* S_RESET_ST was expected (in a reset command). Continue processing * to quickly get out of TARGET_RESET state */ } @@ -960,6 +1026,28 @@ static int cortex_m_poll_one(struct target *target) if ((prev_target_state == TARGET_RUNNING) || (prev_target_state == TARGET_RESET)) { retval = cortex_m_debug_entry(target); + /* Errata 3092511 workaround + * Cortex-M7 can halt in an incorrect address when breakpoint + * and exception occurs simultaneously */ + if (retval == ERROR_TARGET_HALTED_DO_RESUME) { + struct arm *arm = &armv7m->arm; + LOG_TARGET_INFO(target, "Resuming after incorrect halt @ PC 0x%08" PRIx32 + ", ARM Cortex-M7 erratum 3092511", + buf_get_u32(arm->pc->value, 0, 32)); + /* We don't need to restore registers, just restart the core */ + cortex_m_set_maskints_for_run(target); + retval = cortex_m_write_debug_halt_mask(target, 0, C_HALT); + if (retval != ERROR_OK) + return retval; + + target->debug_reason = DBG_REASON_NOTHALTED; + /* registers are now invalid */ + register_cache_invalidate(armv7m->arm.core_cache); + + target->state = TARGET_RUNNING; + return ERROR_OK; + } + /* arm_semihosting needs to know registers, don't run if debug entry returned error */ if (retval == ERROR_OK && arm_semihosting(target, &retval) != 0) return retval; @@ -1271,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); @@ -1356,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; @@ -1369,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_WARNING("resume of a SMP target failed, trying to resume current one"); + 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; @@ -1397,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; @@ -1418,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; @@ -1445,7 +1534,7 @@ static int cortex_m_step(struct target *target, int current, /* if no bkpt instruction is found at pc then we can perform * a normal step, otherwise we have to manually step over the bkpt * instruction - as such simulate a step */ - if (bkpt_inst_found == false) { + if (!bkpt_inst_found) { if (cortex_m->isrmasking_mode != CORTEX_M_ISRMASK_AUTO) { /* Automatic ISR masking mode off: Just step over the next * instruction, with interrupts on or off as appropriate. */ @@ -1582,7 +1671,7 @@ static int cortex_m_step(struct target *target, int current, cortex_m->dcb_dhcsr, cortex_m->nvic_icsr); retval = cortex_m_debug_entry(target); - if (retval != ERROR_OK) + if (retval != ERROR_OK && retval != ERROR_TARGET_HALTED_DO_RESUME) return retval; target_call_event_callbacks(target, TARGET_EVENT_HALTED); @@ -1761,10 +1850,12 @@ static int cortex_m_deassert_reset(struct target *target) target_state_name(target), target_was_examined(target) ? "" : " not"); + enum reset_types jtag_reset_config = jtag_get_reset_config(); + /* deassert reset lines */ - adapter_deassert_reset(); + if (jtag_reset_config & RESET_HAS_SRST) + adapter_deassert_reset(); - enum reset_types jtag_reset_config = jtag_get_reset_config(); if ((jtag_reset_config & RESET_HAS_SRST) && !(jtag_reset_config & RESET_SRST_NO_GATING) && @@ -2005,11 +2096,9 @@ static int cortex_m_set_watchpoint(struct target *target, struct watchpoint *wat target_write_u32(target, comparator->dwt_comparator_address + 8, comparator->function); - LOG_TARGET_DEBUG(target, "Watchpoint (ID %d) DWT%d 0x%08x 0x%x 0x%05x", + LOG_TARGET_DEBUG(target, "Watchpoint (ID %d) DWT%d 0x%08" PRIx32 " 0x%" PRIx32 " 0x%05" PRIx32, watchpoint->unique_id, dwt_num, - (unsigned) comparator->comp, - (unsigned) comparator->mask, - (unsigned) comparator->function); + comparator->comp, comparator->mask, comparator->function); return ERROR_OK; } @@ -2026,9 +2115,9 @@ static int cortex_m_unset_watchpoint(struct target *target, struct watchpoint *w unsigned int dwt_num = watchpoint->number; - LOG_TARGET_DEBUG(target, "Watchpoint (ID %d) DWT%u address: 0x%08x clear", + LOG_TARGET_DEBUG(target, "Watchpoint (ID %d) DWT%u address: " TARGET_ADDR_FMT " clear", watchpoint->unique_id, dwt_num, - (unsigned) watchpoint->address); + watchpoint->address); if (dwt_num >= cortex_m->dwt_num_comp) { LOG_TARGET_DEBUG(target, "Invalid DWT Comparator number in watchpoint"); @@ -2068,7 +2157,7 @@ int cortex_m_add_watchpoint(struct target *target, struct watchpoint *watchpoint } /* hardware allows address masks of up to 32K */ - unsigned mask; + unsigned int mask; for (mask = 0; mask < 16; mask++) { if ((1u << mask) == watchpoint->length) @@ -2228,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"); @@ -2304,7 +2393,7 @@ static int cortex_m_dwt_set_reg(struct reg *reg, uint8_t *buf) struct dwt_reg { uint32_t addr; const char *name; - unsigned size; + unsigned int size; }; static const struct dwt_reg dwt_base_regs[] = { @@ -2467,7 +2556,7 @@ static bool cortex_m_has_tz(struct target *target) int retval = target_read_u32(target, DAUTHSTATUS, &dauthstatus); if (retval != ERROR_OK) { - LOG_WARNING("Error reading DAUTHSTATUS register"); + LOG_TARGET_WARNING(target, "Error reading DAUTHSTATUS register"); return false; } return (dauthstatus & DAUTHSTATUS_SID_MASK) != 0; @@ -2516,7 +2605,7 @@ int cortex_m_examine(struct target *target) } else { armv7m->debug_ap = dap_get_ap(swjdp, cortex_m->apsel); if (!armv7m->debug_ap) { - LOG_ERROR("Cannot get AP"); + LOG_TARGET_ERROR(target, "Cannot get AP"); return ERROR_FAIL; } } @@ -2537,8 +2626,8 @@ int cortex_m_examine(struct target *target) if (retval != ERROR_OK) return retval; - /* Inspect implementor/part to look for recognized cores */ - unsigned int impl_part = cpuid & (ARM_CPUID_IMPLEMENTOR_MASK | ARM_CPUID_PARTNO_MASK); + /* Inspect implementer/part to look for recognized cores */ + unsigned int impl_part = cpuid & (ARM_CPUID_IMPLEMENTER_MASK | ARM_CPUID_PARTNO_MASK); for (unsigned int n = 0; n < ARRAY_SIZE(cortex_m_parts); n++) { if (impl_part == cortex_m_parts[n].impl_part) { @@ -2560,14 +2649,22 @@ int cortex_m_examine(struct target *target) (uint8_t)((cpuid >> 0) & 0xf)); cortex_m->maskints_erratum = false; + cortex_m->incorrect_halt_erratum = false; if (impl_part == CORTEX_M7_PARTNO) { uint8_t rev, patch; rev = (cpuid >> 20) & 0xf; patch = (cpuid >> 0) & 0xf; if ((rev == 0) && (patch < 2)) { - LOG_TARGET_WARNING(target, "Silicon bug: single stepping may enter pending exception handler!"); + LOG_TARGET_WARNING(target, "Erratum 702596: single stepping may enter pending exception handler!"); cortex_m->maskints_erratum = true; } + /* TODO: add revision check when a Cortex-M7 revision with fixed 3092511 is out */ + LOG_TARGET_WARNING(target, "Erratum 3092511: Cortex-M7 can halt in an incorrect address when breakpoint and exception occurs simultaneously"); + cortex_m->incorrect_halt_erratum = true; + if (armv7m->is_hla_target) + LOG_TARGET_WARNING(target, "No erratum 3092511 workaround on hla adapter"); + else + LOG_TARGET_INFO(target, "The erratum 3092511 workaround will resume after an incorrect halt"); } LOG_TARGET_DEBUG(target, "cpuid: 0x%8.8" PRIx32 "", cpuid); @@ -2614,6 +2711,10 @@ int cortex_m_examine(struct target *target) for (size_t idx = ARMV7M_FPU_FIRST_REG; idx <= ARMV7M_FPU_LAST_REG; idx++) armv7m->arm.core_cache->reg_list[idx].exist = false; + /* TODO: MVE can be present without floating points. Revisit this test */ + if (armv7m->fp_feature != FPV5_MVE_F && armv7m->fp_feature != FPV5_MVE_I) + armv7m->arm.core_cache->reg_list[ARMV8M_VPR].exist = false; + if (!cortex_m_has_tz(target)) for (size_t idx = ARMV8M_FIRST_REG; idx <= ARMV8M_LAST_REG; idx++) armv7m->arm.core_cache->reg_list[idx].exist = false; @@ -2864,7 +2965,7 @@ COMMAND_HANDLER(handle_cortex_m_vector_catch_command) static const struct { char name[10]; - unsigned mask; + unsigned int mask; } vec_ids[] = { { "hard_err", VC_HARDERR, }, { "int_err", VC_INTERR, }, @@ -2890,7 +2991,7 @@ COMMAND_HANDLER(handle_cortex_m_vector_catch_command) return retval; if (CMD_ARGC > 0) { - unsigned catch = 0; + unsigned int catch = 0; if (CMD_ARGC == 1) { if (strcmp(CMD_ARGV[0], "all") == 0) { @@ -2902,7 +3003,7 @@ COMMAND_HANDLER(handle_cortex_m_vector_catch_command) goto write; } while (CMD_ARGC-- > 0) { - unsigned i; + unsigned int i; for (i = 0; i < ARRAY_SIZE(vec_ids); i++) { if (strcmp(CMD_ARGV[CMD_ARGC], vec_ids[i].name) != 0) continue; @@ -2935,7 +3036,7 @@ write: */ } - for (unsigned i = 0; i < ARRAY_SIZE(vec_ids); i++) { + for (unsigned int i = 0; i < ARRAY_SIZE(vec_ids); i++) { command_print(CMD, "%9s: %s", vec_ids[i].name, (demcr & vec_ids[i].mask) ? "catch" : "ignore"); } diff --git a/src/target/cortex_m.h b/src/target/cortex_m.h index a585b78..144f245 100644 --- a/src/target/cortex_m.h +++ b/src/target/cortex_m.h @@ -31,35 +31,36 @@ #define CPUID 0xE000ED00 -#define ARM_CPUID_IMPLEMENTOR_POS 24 -#define ARM_CPUID_IMPLEMENTOR_MASK (0xFF << ARM_CPUID_IMPLEMENTOR_POS) +#define ARM_CPUID_IMPLEMENTER_POS 24 +#define ARM_CPUID_IMPLEMENTER_MASK (0xFF << ARM_CPUID_IMPLEMENTER_POS) #define ARM_CPUID_PARTNO_POS 4 #define ARM_CPUID_PARTNO_MASK (0xFFF << ARM_CPUID_PARTNO_POS) -#define ARM_MAKE_CPUID(impl, partno) ((((impl) << ARM_CPUID_IMPLEMENTOR_POS) & ARM_CPUID_IMPLEMENTOR_MASK) | \ +#define ARM_MAKE_CPUID(impl, partno) ((((impl) << ARM_CPUID_IMPLEMENTER_POS) & ARM_CPUID_IMPLEMENTER_MASK) | \ (((partno) << ARM_CPUID_PARTNO_POS) & ARM_CPUID_PARTNO_MASK)) /** Known Arm Cortex masked CPU Ids - * This includes the implementor and part number, but _not_ the revision or + * This includes the implementer and part number, but _not_ the revision or * patch fields. */ enum cortex_m_impl_part { CORTEX_M_PARTNO_INVALID, - STAR_MC1_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTOR_ARM, 0x132), /* FIXME - confirm implementor! */ - CORTEX_M0_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTOR_ARM, 0xC20), - CORTEX_M1_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTOR_ARM, 0xC21), - CORTEX_M3_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTOR_ARM, 0xC23), - CORTEX_M4_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTOR_ARM, 0xC24), - CORTEX_M7_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTOR_ARM, 0xC27), - CORTEX_M0P_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTOR_ARM, 0xC60), - CORTEX_M23_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTOR_ARM, 0xD20), - CORTEX_M33_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTOR_ARM, 0xD21), - CORTEX_M35P_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTOR_ARM, 0xD31), - CORTEX_M55_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTOR_ARM, 0xD22), - CORTEX_M85_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTOR_ARM, 0xD23), - INFINEON_SLX2_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTOR_INFINEON, 0xDB0), - REALTEK_M200_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTOR_REALTEK, 0xd20), - REALTEK_M300_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTOR_REALTEK, 0xd22), + STAR_MC1_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTER_ARM_CHINA, 0x132), + CORTEX_M0_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTER_ARM, 0xC20), + CORTEX_M1_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTER_ARM, 0xC21), + CORTEX_M3_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTER_ARM, 0xC23), + CORTEX_M4_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTER_ARM, 0xC24), + CORTEX_M7_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTER_ARM, 0xC27), + CORTEX_M0P_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTER_ARM, 0xC60), + CORTEX_M23_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTER_ARM, 0xD20), + CORTEX_M33_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTER_ARM, 0xD21), + CORTEX_M35P_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTER_ARM, 0xD31), + CORTEX_M52_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTER_ARM_CHINA, 0xD24), + CORTEX_M55_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTER_ARM, 0xD22), + CORTEX_M85_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTER_ARM, 0xD23), + INFINEON_SLX2_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTER_INFINEON, 0xDB0), + REALTEK_M200_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTER_REALTEK, 0xd20), + REALTEK_M300_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTER_REALTEK, 0xd22), }; /* Relevant Cortex-M flags, used in struct cortex_m_part_info.flags */ @@ -149,6 +150,7 @@ struct cortex_m_part_info { #define VC_CORERESET BIT(0) /* DCB_DSCSR bit and field definitions */ +#define DSCSR_CDSKEY BIT(17) #define DSCSR_CDS BIT(16) /* NVIC registers */ @@ -256,6 +258,10 @@ struct cortex_m_common { /* Whether this target has the erratum that makes C_MASKINTS not apply to * already pending interrupts */ bool maskints_erratum; + + /* Errata 3092511 Cortex-M7 can halt in an incorrect address when breakpoint + * and exception occurs simultaneously */ + bool incorrect_halt_erratum; }; static inline bool is_cortex_m_or_hla(const struct cortex_m_common *cortex_m) diff --git a/src/target/dsp563xx.c b/src/target/dsp563xx.c index 1e71803..629056f 100644 --- a/src/target/dsp563xx.c +++ b/src/target/dsp563xx.c @@ -220,9 +220,9 @@ enum dsp563xx_reg_idx { }; static const struct { - unsigned id; + unsigned int id; const char *name; - unsigned bits; + unsigned int bits; /* effective addressing mode encoding */ uint8_t eame; uint32_t instr_mask; @@ -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,10 +1132,10 @@ 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 %08X", __func__, current, (unsigned) address); + LOG_DEBUG("%s %08X %08" TARGET_PRIXADDR, __func__, current, address); err = dsp563xx_restore_context(target); if (err != ERROR_OK) @@ -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,10 +1196,10 @@ 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 %08X", __func__, current, (unsigned) address); + LOG_DEBUG("%s %08X %08" PRIX32, __func__, current, address); err = dsp563xx_jtag_debug_request(target); if (err != ERROR_OK) @@ -1260,15 +1260,15 @@ static int dsp563xx_step_ex(struct target *target, err = dsp563xx_once_reg_read(target->tap, 1, DSP563XX_ONCE_OPABFR, &dr_in); if (err != ERROR_OK) return err; - LOG_DEBUG("fetch: %08X", (unsigned) dr_in&0x00ffffff); + LOG_DEBUG("fetch: %08" PRIX32, dr_in & 0x00ffffff); err = dsp563xx_once_reg_read(target->tap, 1, DSP563XX_ONCE_OPABDR, &dr_in); if (err != ERROR_OK) return err; - LOG_DEBUG("decode: %08X", (unsigned) dr_in&0x00ffffff); + LOG_DEBUG("decode: %08" PRIX32, dr_in & 0x00ffffff); err = dsp563xx_once_reg_read(target->tap, 1, DSP563XX_ONCE_OPABEX, &dr_in); if (err != ERROR_OK) return err; - LOG_DEBUG("execute: %08X", (unsigned) dr_in&0x00ffffff); + LOG_DEBUG("execute: %08" PRIX32, dr_in & 0x00ffffff); /* reset trace mode */ err = dsp563xx_once_reg_write(target->tap, 1, DSP563XX_ONCE_OSCR, 0x000000); @@ -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/dsp563xx_once.c b/src/target/dsp563xx_once.c index 866f331..bb41ae8 100644 --- a/src/target/dsp563xx_once.c +++ b/src/target/dsp563xx_once.c @@ -34,6 +34,8 @@ #define JTAG_INSTR_DEBUG_REQUEST 0x07 #define JTAG_INSTR_BYPASS 0x0F +static int dsp563xx_once_reg_read_ex(struct jtag_tap *tap, int flush, uint8_t reg, uint8_t len, uint32_t *data); + /** */ static inline int dsp563xx_write_dr(struct jtag_tap *tap, uint8_t *dr_in, uint8_t *dr_out, int dr_len, int rti) { @@ -185,7 +187,7 @@ int dsp563xx_once_read_register(struct jtag_tap *tap, int flush, struct once_reg } /** once read register with register len */ -int dsp563xx_once_reg_read_ex(struct jtag_tap *tap, int flush, uint8_t reg, uint8_t len, uint32_t *data) +static int dsp563xx_once_reg_read_ex(struct jtag_tap *tap, int flush, uint8_t reg, uint8_t len, uint32_t *data) { int err; diff --git a/src/target/dsp563xx_once.h b/src/target/dsp563xx_once.h index 8715488..4f27e1d 100644 --- a/src/target/dsp563xx_once.h +++ b/src/target/dsp563xx_once.h @@ -65,8 +65,6 @@ int dsp563xx_once_target_status(struct jtag_tap *tap); /** once read registers */ int dsp563xx_once_read_register(struct jtag_tap *tap, int flush, struct once_reg *regs, int len); /** once read register */ -int dsp563xx_once_reg_read_ex(struct jtag_tap *tap, int flush, uint8_t reg, uint8_t len, uint32_t *data); -/** once read register */ int dsp563xx_once_reg_read(struct jtag_tap *tap, int flush, uint8_t reg, uint32_t *data); /** once write register */ int dsp563xx_once_reg_write(struct jtag_tap *tap, int flush, uint8_t reg, uint32_t data); diff --git a/src/target/dsp5680xx.c b/src/target/dsp5680xx.c index c90bca3..3f9a674 100644 --- a/src/target/dsp5680xx.c +++ b/src/target/dsp5680xx.c @@ -44,7 +44,7 @@ static int reset_jtag(void) { int retval; - tap_state_t states[2]; + enum tap_state states[2]; const char *cp = "RESET"; @@ -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."); @@ -1172,7 +1172,7 @@ static int dsp5680xx_read(struct target *t, target_addr_t a, uint32_t size, dsp5680xx_context.flush = 0; int counter = FLUSH_COUNT_READ_WRITE; - for (unsigned i = 0; i < count; i++) { + for (unsigned int i = 0; i < count; i++) { if (--counter == 0) { dsp5680xx_context.flush = 1; counter = FLUSH_COUNT_READ_WRITE; @@ -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 0f76b59..da40928 100644 --- a/src/target/esirisc.c +++ b/src/target/esirisc.c @@ -160,11 +160,11 @@ static int esirisc_disable_interrupts(struct target *target) uint32_t etc; int retval; - LOG_DEBUG("-"); + LOG_TARGET_DEBUG(target, "-"); retval = esirisc_jtag_read_csr(jtag_info, CSR_THREAD, CSR_THREAD_ETC, &etc); if (retval != ERROR_OK) { - LOG_ERROR("%s: failed to read Thread CSR: ETC", target_name(target)); + LOG_TARGET_ERROR(target, "failed to read Thread CSR: ETC"); return retval; } @@ -172,7 +172,7 @@ static int esirisc_disable_interrupts(struct target *target) retval = esirisc_jtag_write_csr(jtag_info, CSR_THREAD, CSR_THREAD_ETC, etc); if (retval != ERROR_OK) { - LOG_ERROR("%s: failed to write Thread CSR: ETC", target_name(target)); + LOG_TARGET_ERROR(target, "failed to write Thread CSR: ETC"); return retval; } @@ -187,11 +187,11 @@ static int esirisc_enable_interrupts(struct target *target) uint32_t etc; int retval; - LOG_DEBUG("-"); + LOG_TARGET_DEBUG(target, "-"); retval = esirisc_jtag_read_csr(jtag_info, CSR_THREAD, CSR_THREAD_ETC, &etc); if (retval != ERROR_OK) { - LOG_ERROR("%s: failed to read Thread CSR: ETC", target_name(target)); + LOG_TARGET_ERROR(target, "failed to read Thread CSR: ETC"); return retval; } @@ -199,7 +199,7 @@ static int esirisc_enable_interrupts(struct target *target) retval = esirisc_jtag_write_csr(jtag_info, CSR_THREAD, CSR_THREAD_ETC, etc); if (retval != ERROR_OK) { - LOG_ERROR("%s: failed to write Thread CSR: ETC", target_name(target)); + LOG_TARGET_ERROR(target, "failed to write Thread CSR: ETC"); return retval; } @@ -212,12 +212,12 @@ static int esirisc_save_interrupts(struct target *target) struct esirisc_common *esirisc = target_to_esirisc(target); struct esirisc_jtag *jtag_info = &esirisc->jtag_info; - LOG_DEBUG("-"); + LOG_TARGET_DEBUG(target, "-"); int retval = esirisc_jtag_read_csr(jtag_info, CSR_THREAD, CSR_THREAD_ETC, &esirisc->etc_save); if (retval != ERROR_OK) { - LOG_ERROR("%s: failed to read Thread CSR: ETC", target_name(target)); + LOG_TARGET_ERROR(target, "failed to read Thread CSR: ETC"); return retval; } @@ -229,12 +229,12 @@ static int esirisc_restore_interrupts(struct target *target) struct esirisc_common *esirisc = target_to_esirisc(target); struct esirisc_jtag *jtag_info = &esirisc->jtag_info; - LOG_DEBUG("-"); + LOG_TARGET_DEBUG(target, "-"); int retval = esirisc_jtag_write_csr(jtag_info, CSR_THREAD, CSR_THREAD_ETC, esirisc->etc_save); if (retval != ERROR_OK) { - LOG_ERROR("%s: failed to write Thread CSR: ETC", target_name(target)); + LOG_TARGET_ERROR(target, "failed to write Thread CSR: ETC"); return retval; } @@ -247,12 +247,12 @@ static int esirisc_save_hwdc(struct target *target) struct esirisc_common *esirisc = target_to_esirisc(target); struct esirisc_jtag *jtag_info = &esirisc->jtag_info; - LOG_DEBUG("-"); + LOG_TARGET_DEBUG(target, "-"); int retval = esirisc_jtag_read_csr(jtag_info, CSR_DEBUG, CSR_DEBUG_HWDC, &esirisc->hwdc_save); if (retval != ERROR_OK) { - LOG_ERROR("%s: failed to read Thread CSR: HWDC", target_name(target)); + LOG_TARGET_ERROR(target, "failed to read Thread CSR: HWDC"); return retval; } @@ -265,12 +265,12 @@ static int esirisc_restore_hwdc(struct target *target) struct esirisc_common *esirisc = target_to_esirisc(target); struct esirisc_jtag *jtag_info = &esirisc->jtag_info; - LOG_DEBUG("-"); + LOG_TARGET_DEBUG(target, "-"); int retval = esirisc_jtag_write_csr(jtag_info, CSR_DEBUG, CSR_DEBUG_HWDC, esirisc->hwdc_save); if (retval != ERROR_OK) { - LOG_ERROR("%s: failed to write Debug CSR: HWDC", target_name(target)); + LOG_TARGET_ERROR(target, "failed to write Debug CSR: HWDC"); return retval; } @@ -281,9 +281,9 @@ static int esirisc_save_context(struct target *target) { struct esirisc_common *esirisc = target_to_esirisc(target); - LOG_DEBUG("-"); + LOG_TARGET_DEBUG(target, "-"); - for (unsigned i = 0; i < esirisc->reg_cache->num_regs; ++i) { + for (unsigned int i = 0; i < esirisc->reg_cache->num_regs; ++i) { struct reg *reg = esirisc->reg_cache->reg_list + i; struct esirisc_reg *reg_info = reg->arch_info; @@ -298,9 +298,9 @@ static int esirisc_restore_context(struct target *target) { struct esirisc_common *esirisc = target_to_esirisc(target); - LOG_DEBUG("-"); + LOG_TARGET_DEBUG(target, "-"); - for (unsigned i = 0; i < esirisc->reg_cache->num_regs; ++i) { + for (unsigned int i = 0; i < esirisc->reg_cache->num_regs; ++i) { struct reg *reg = esirisc->reg_cache->reg_list + i; struct esirisc_reg *reg_info = reg->arch_info; @@ -316,7 +316,7 @@ static int esirisc_flush_caches(struct target *target) struct esirisc_common *esirisc = target_to_esirisc(target); struct esirisc_jtag *jtag_info = &esirisc->jtag_info; - LOG_DEBUG("-"); + LOG_TARGET_DEBUG(target, "-"); if (target->state != TARGET_HALTED) { LOG_TARGET_ERROR(target, "not halted"); @@ -325,7 +325,7 @@ static int esirisc_flush_caches(struct target *target) int retval = esirisc_jtag_flush_caches(jtag_info); if (retval != ERROR_OK) { - LOG_ERROR("%s: failed to flush caches", target_name(target)); + LOG_TARGET_ERROR(target, "failed to flush caches"); return retval; } @@ -337,7 +337,7 @@ static int esirisc_wait_debug_active(struct esirisc_common *esirisc, int ms) struct esirisc_jtag *jtag_info = &esirisc->jtag_info; int64_t t; - LOG_DEBUG("-"); + LOG_TARGET_DEBUG(esirisc->target, "-"); t = timeval_ms(); for (;;) { @@ -359,7 +359,7 @@ static int esirisc_read_memory(struct target *target, target_addr_t address, struct esirisc_jtag *jtag_info = &esirisc->jtag_info; int retval; - LOG_DEBUG("-"); + LOG_TARGET_DEBUG(target, "-"); int num_bits = 8 * size; for (uint32_t i = 0; i < count; ++i) { @@ -383,12 +383,12 @@ static int esirisc_read_memory(struct target *target, target_addr_t address, break; default: - LOG_ERROR("%s: unsupported size: %" PRIu32, target_name(target), size); + LOG_TARGET_ERROR(target, "unsupported size: %" PRIu32, size); return ERROR_FAIL; } if (retval != ERROR_OK) { - LOG_ERROR("%s: failed to read address: 0x%" TARGET_PRIxADDR, target_name(target), + LOG_TARGET_ERROR(target, "failed to read address: 0x%" TARGET_PRIxADDR, address); return retval; } @@ -408,7 +408,7 @@ static int esirisc_write_memory(struct target *target, target_addr_t address, struct esirisc_jtag *jtag_info = &esirisc->jtag_info; int retval; - LOG_DEBUG("-"); + LOG_TARGET_DEBUG(target, "-"); int num_bits = 8 * size; for (uint32_t i = 0; i < count; ++i) { @@ -431,12 +431,12 @@ static int esirisc_write_memory(struct target *target, target_addr_t address, break; default: - LOG_ERROR("%s: unsupported size: %" PRIu32, target_name(target), size); + LOG_TARGET_ERROR(target, "unsupported size: %" PRIu32, size); return ERROR_FAIL; } if (retval != ERROR_OK) { - LOG_ERROR("%s: failed to write address: 0x%" TARGET_PRIxADDR, target_name(target), + LOG_TARGET_ERROR(target, "failed to write address: 0x%" TARGET_PRIxADDR, address); return retval; } @@ -460,7 +460,7 @@ static int esirisc_next_breakpoint(struct target *target) struct breakpoint **breakpoints_p = esirisc->breakpoints_p; struct breakpoint **breakpoints_e = breakpoints_p + esirisc->num_breakpoints; - LOG_DEBUG("-"); + LOG_TARGET_DEBUG(target, "-"); for (int bp_index = 0; breakpoints_p < breakpoints_e; ++breakpoints_p, ++bp_index) if (!*breakpoints_p) @@ -477,13 +477,13 @@ static int esirisc_add_breakpoint(struct target *target, struct breakpoint *brea uint32_t ibc; int retval; - LOG_DEBUG("-"); + LOG_TARGET_DEBUG(target, "-"); /* * The default linker scripts provided by the eSi-RISC toolchain do * not specify attributes on memory regions, which results in * incorrect application of software breakpoints by GDB. Targets - * must be configured with `gdb_breakpoint_override hard` as + * must be configured with `gdb breakpoint_override hard` as * software breakpoints are not supported. */ if (breakpoint->type != BKPT_HARD) @@ -491,7 +491,7 @@ static int esirisc_add_breakpoint(struct target *target, struct breakpoint *brea bp_index = esirisc_next_breakpoint(target); if (bp_index < 0) { - LOG_ERROR("%s: out of hardware breakpoints", target_name(target)); + LOG_TARGET_ERROR(target, "out of hardware breakpoints"); return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; } @@ -502,14 +502,14 @@ static int esirisc_add_breakpoint(struct target *target, struct breakpoint *brea retval = esirisc_jtag_write_csr(jtag_info, CSR_DEBUG, CSR_DEBUG_IBA_N + bp_index, breakpoint->address); if (retval != ERROR_OK) { - LOG_ERROR("%s: failed to write Debug CSR: IBA", target_name(target)); + LOG_TARGET_ERROR(target, "failed to write Debug CSR: IBA"); return retval; } /* enable instruction breakpoint */ retval = esirisc_jtag_read_csr(jtag_info, CSR_DEBUG, CSR_DEBUG_IBC, &ibc); if (retval != ERROR_OK) { - LOG_ERROR("%s: failed to read Debug CSR: IBC", target_name(target)); + LOG_TARGET_ERROR(target, "failed to read Debug CSR: IBC"); return retval; } @@ -517,7 +517,7 @@ static int esirisc_add_breakpoint(struct target *target, struct breakpoint *brea retval = esirisc_jtag_write_csr(jtag_info, CSR_DEBUG, CSR_DEBUG_IBC, ibc); if (retval != ERROR_OK) { - LOG_ERROR("%s: failed to write Debug CSR: IBC", target_name(target)); + LOG_TARGET_ERROR(target, "failed to write Debug CSR: IBC"); return retval; } @@ -528,7 +528,7 @@ static int esirisc_add_breakpoints(struct target *target) { struct breakpoint *breakpoint = target->breakpoints; - LOG_DEBUG("-"); + LOG_TARGET_DEBUG(target, "-"); while (breakpoint) { if (!breakpoint->is_set) @@ -548,12 +548,12 @@ static int esirisc_remove_breakpoint(struct target *target, struct breakpoint *b uint32_t ibc; int retval; - LOG_DEBUG("-"); + LOG_TARGET_DEBUG(target, "-"); /* disable instruction breakpoint */ retval = esirisc_jtag_read_csr(jtag_info, CSR_DEBUG, CSR_DEBUG_IBC, &ibc); if (retval != ERROR_OK) { - LOG_ERROR("%s: failed to read Debug CSR: IBC", target_name(target)); + LOG_TARGET_ERROR(target, "failed to read Debug CSR: IBC"); return retval; } @@ -561,7 +561,7 @@ static int esirisc_remove_breakpoint(struct target *target, struct breakpoint *b retval = esirisc_jtag_write_csr(jtag_info, CSR_DEBUG, CSR_DEBUG_IBC, ibc); if (retval != ERROR_OK) { - LOG_ERROR("%s: failed to write Debug CSR: IBC", target_name(target)); + LOG_TARGET_ERROR(target, "failed to write Debug CSR: IBC"); return retval; } @@ -576,12 +576,12 @@ static int esirisc_remove_breakpoints(struct target *target) struct esirisc_common *esirisc = target_to_esirisc(target); struct esirisc_jtag *jtag_info = &esirisc->jtag_info; - LOG_DEBUG("-"); + LOG_TARGET_DEBUG(target, "-"); /* clear instruction breakpoints */ int retval = esirisc_jtag_write_csr(jtag_info, CSR_DEBUG, CSR_DEBUG_IBC, 0); if (retval != ERROR_OK) { - LOG_ERROR("%s: failed to write Debug CSR: IBC", target_name(target)); + LOG_TARGET_ERROR(target, "failed to write Debug CSR: IBC"); return retval; } @@ -596,7 +596,7 @@ static int esirisc_next_watchpoint(struct target *target) struct watchpoint **watchpoints_p = esirisc->watchpoints_p; struct watchpoint **watchpoints_e = watchpoints_p + esirisc->num_watchpoints; - LOG_DEBUG("-"); + LOG_TARGET_DEBUG(target, "-"); for (int wp_index = 0; watchpoints_p < watchpoints_e; ++watchpoints_p, ++wp_index) if (!*watchpoints_p) @@ -613,11 +613,11 @@ static int esirisc_add_watchpoint(struct target *target, struct watchpoint *watc uint32_t dbs, dbc; int retval; - LOG_DEBUG("-"); + LOG_TARGET_DEBUG(target, "-"); wp_index = esirisc_next_watchpoint(target); if (wp_index < 0) { - LOG_ERROR("%s: out of hardware watchpoints", target_name(target)); + LOG_TARGET_ERROR(target, "out of hardware watchpoints"); return ERROR_FAIL; } @@ -628,14 +628,14 @@ static int esirisc_add_watchpoint(struct target *target, struct watchpoint *watc retval = esirisc_jtag_write_csr(jtag_info, CSR_DEBUG, CSR_DEBUG_DBA_N + wp_index, watchpoint->address); if (retval != ERROR_OK) { - LOG_ERROR("%s: failed to write Debug CSR: DBA", target_name(target)); + LOG_TARGET_ERROR(target, "failed to write Debug CSR: DBA"); return retval; } /* specify data breakpoint size */ retval = esirisc_jtag_read_csr(jtag_info, CSR_DEBUG, CSR_DEBUG_DBS, &dbs); if (retval != ERROR_OK) { - LOG_ERROR("%s: failed to read Debug CSR: DBS", target_name(target)); + LOG_TARGET_ERROR(target, "failed to read Debug CSR: DBS"); return retval; } @@ -657,7 +657,7 @@ static int esirisc_add_watchpoint(struct target *target, struct watchpoint *watc break; default: - LOG_ERROR("%s: unsupported length: %" PRIu32, target_name(target), + LOG_TARGET_ERROR(target, "unsupported length: %" PRIu32, watchpoint->length); return ERROR_FAIL; } @@ -666,14 +666,14 @@ static int esirisc_add_watchpoint(struct target *target, struct watchpoint *watc retval = esirisc_jtag_write_csr(jtag_info, CSR_DEBUG, CSR_DEBUG_DBS, dbs); if (retval != ERROR_OK) { - LOG_ERROR("%s: failed to write Debug CSR: DBS", target_name(target)); + LOG_TARGET_ERROR(target, "failed to write Debug CSR: DBS"); return retval; } /* enable data breakpoint */ retval = esirisc_jtag_read_csr(jtag_info, CSR_DEBUG, CSR_DEBUG_DBC, &dbc); if (retval != ERROR_OK) { - LOG_ERROR("%s: failed to read Debug CSR: DBC", target_name(target)); + LOG_TARGET_ERROR(target, "failed to read Debug CSR: DBC"); return retval; } @@ -692,8 +692,7 @@ static int esirisc_add_watchpoint(struct target *target, struct watchpoint *watc break; default: - LOG_ERROR("%s: unsupported rw: %" PRId32, target_name(target), - watchpoint->rw); + LOG_TARGET_ERROR(target, "unsupported rw: %" PRId32, watchpoint->rw); return ERROR_FAIL; } @@ -701,7 +700,7 @@ static int esirisc_add_watchpoint(struct target *target, struct watchpoint *watc retval = esirisc_jtag_write_csr(jtag_info, CSR_DEBUG, CSR_DEBUG_DBC, dbc); if (retval != ERROR_OK) { - LOG_ERROR("%s: failed to write Debug CSR: DBC", target_name(target)); + LOG_TARGET_ERROR(target, "failed to write Debug CSR: DBC"); return retval; } @@ -712,7 +711,7 @@ static int esirisc_add_watchpoints(struct target *target) { struct watchpoint *watchpoint = target->watchpoints; - LOG_DEBUG("-"); + LOG_TARGET_DEBUG(target, "-"); while (watchpoint) { if (!watchpoint->is_set) @@ -732,12 +731,12 @@ static int esirisc_remove_watchpoint(struct target *target, struct watchpoint *w uint32_t dbc; int retval; - LOG_DEBUG("-"); + LOG_TARGET_DEBUG(target, "-"); /* disable data breakpoint */ retval = esirisc_jtag_read_csr(jtag_info, CSR_DEBUG, CSR_DEBUG_DBC, &dbc); if (retval != ERROR_OK) { - LOG_ERROR("%s: failed to read Debug CSR: DBC", target_name(target)); + LOG_TARGET_ERROR(target, "failed to read Debug CSR: DBC"); return retval; } @@ -745,7 +744,7 @@ static int esirisc_remove_watchpoint(struct target *target, struct watchpoint *w retval = esirisc_jtag_write_csr(jtag_info, CSR_DEBUG, CSR_DEBUG_DBC, dbc); if (retval != ERROR_OK) { - LOG_ERROR("%s: failed to write Debug CSR: DBC", target_name(target)); + LOG_TARGET_ERROR(target, "failed to write Debug CSR: DBC"); return retval; } @@ -760,12 +759,12 @@ static int esirisc_remove_watchpoints(struct target *target) struct esirisc_common *esirisc = target_to_esirisc(target); struct esirisc_jtag *jtag_info = &esirisc->jtag_info; - LOG_DEBUG("-"); + LOG_TARGET_DEBUG(target, "-"); /* clear data breakpoints */ int retval = esirisc_jtag_write_csr(jtag_info, CSR_DEBUG, CSR_DEBUG_DBC, 0); if (retval != ERROR_OK) { - LOG_ERROR("%s: failed to write Debug CSR: DBC", target_name(target)); + LOG_TARGET_ERROR(target, "failed to write Debug CSR: DBC"); return retval; } @@ -779,14 +778,14 @@ static int esirisc_halt(struct target *target) struct esirisc_common *esirisc = target_to_esirisc(target); struct esirisc_jtag *jtag_info = &esirisc->jtag_info; - LOG_DEBUG("-"); + LOG_TARGET_DEBUG(target, "-"); if (target->state == TARGET_HALTED) return ERROR_OK; int retval = esirisc_jtag_break(jtag_info); if (retval != ERROR_OK) { - LOG_ERROR("%s: failed to halt target", target_name(target)); + LOG_TARGET_ERROR(target, "failed to halt target"); return retval; } @@ -802,11 +801,11 @@ static int esirisc_disable_step(struct target *target) uint32_t dc; int retval; - LOG_DEBUG("-"); + LOG_TARGET_DEBUG(target, "-"); retval = esirisc_jtag_read_csr(jtag_info, CSR_DEBUG, CSR_DEBUG_DC, &dc); if (retval != ERROR_OK) { - LOG_ERROR("%s: failed to read Debug CSR: DC", target_name(target)); + LOG_TARGET_ERROR(target, "failed to read Debug CSR: DC"); return retval; } @@ -814,7 +813,7 @@ static int esirisc_disable_step(struct target *target) retval = esirisc_jtag_write_csr(jtag_info, CSR_DEBUG, CSR_DEBUG_DC, dc); if (retval != ERROR_OK) { - LOG_ERROR("%s: failed to write Debug CSR: DC", target_name(target)); + LOG_TARGET_ERROR(target, "failed to write Debug CSR: DC"); return retval; } @@ -828,11 +827,11 @@ static int esirisc_enable_step(struct target *target) uint32_t dc; int retval; - LOG_DEBUG("-"); + LOG_TARGET_DEBUG(target, "-"); retval = esirisc_jtag_read_csr(jtag_info, CSR_DEBUG, CSR_DEBUG_DC, &dc); if (retval != ERROR_OK) { - LOG_ERROR("%s: failed to read Debug CSR: DC", target_name(target)); + LOG_TARGET_ERROR(target, "failed to read Debug CSR: DC"); return retval; } @@ -840,22 +839,23 @@ static int esirisc_enable_step(struct target *target) retval = esirisc_jtag_write_csr(jtag_info, CSR_DEBUG, CSR_DEBUG_DC, dc); if (retval != ERROR_OK) { - LOG_ERROR("%s: failed to write Debug CSR: DC", target_name(target)); + LOG_TARGET_ERROR(target, "failed to write Debug CSR: DC"); return retval; } 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; struct breakpoint *breakpoint = NULL; int retval; - LOG_DEBUG("-"); + LOG_TARGET_DEBUG(target, "-"); if (target->state != TARGET_HALTED) { LOG_TARGET_ERROR(target, "not halted"); @@ -901,7 +901,7 @@ static int esirisc_resume_or_step(struct target *target, int current, target_add retval = esirisc_jtag_continue(jtag_info); if (retval != ERROR_OK) { - LOG_ERROR("%s: failed to resume target", target_name(target)); + LOG_TARGET_ERROR(target, "failed to resume target"); return retval; } @@ -918,22 +918,22 @@ 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_DEBUG("-"); + LOG_TARGET_DEBUG(target, "-"); return esirisc_resume_or_step(target, current, address, 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_DEBUG("-"); + 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) @@ -942,20 +942,20 @@ static int esirisc_debug_step(struct target *target) struct esirisc_jtag *jtag_info = &esirisc->jtag_info; int retval; - LOG_DEBUG("-"); + LOG_TARGET_DEBUG(target, "-"); esirisc_disable_interrupts(target); esirisc_enable_step(target); retval = esirisc_jtag_continue(jtag_info); if (retval != ERROR_OK) { - LOG_ERROR("%s: failed to resume target", target_name(target)); + LOG_TARGET_ERROR(target, "failed to resume target"); return retval; } retval = esirisc_wait_debug_active(esirisc, STEP_TIMEOUT); if (retval != ERROR_OK) { - LOG_ERROR("%s: step timed out", target_name(target)); + LOG_TARGET_ERROR(target, "step timed out"); return retval; } @@ -971,23 +971,23 @@ static int esirisc_debug_reset(struct target *target) struct esirisc_jtag *jtag_info = &esirisc->jtag_info; int retval; - LOG_DEBUG("-"); + LOG_TARGET_DEBUG(target, "-"); retval = esirisc_jtag_assert_reset(jtag_info); if (retval != ERROR_OK) { - LOG_ERROR("%s: failed to assert reset", target_name(target)); + LOG_TARGET_ERROR(target, "failed to assert reset"); return retval; } retval = esirisc_jtag_deassert_reset(jtag_info); if (retval != ERROR_OK) { - LOG_ERROR("%s: failed to deassert reset", target_name(target)); + LOG_TARGET_ERROR(target, "failed to deassert reset"); return retval; } retval = esirisc_wait_debug_active(esirisc, RESET_TIMEOUT); if (retval != ERROR_OK) { - LOG_ERROR("%s: reset timed out", target_name(target)); + LOG_TARGET_ERROR(target, "reset timed out"); return retval; } @@ -1000,11 +1000,11 @@ static int esirisc_debug_enable(struct target *target) struct esirisc_jtag *jtag_info = &esirisc->jtag_info; int retval; - LOG_DEBUG("-"); + LOG_TARGET_DEBUG(target, "-"); retval = esirisc_jtag_enable_debug(jtag_info); if (retval != ERROR_OK) { - LOG_ERROR("%s: failed to enable debug mode", target_name(target)); + LOG_TARGET_ERROR(target, "failed to enable debug mode"); return retval; } @@ -1015,13 +1015,13 @@ static int esirisc_debug_enable(struct target *target) * targets, which will respond with all ones and appear active. */ if (esirisc_jtag_is_stopped(jtag_info)) { - LOG_INFO("%s: debug clock inactive; attempting debug reset", target_name(target)); + LOG_TARGET_INFO(target, "debug clock inactive; attempting debug reset"); retval = esirisc_debug_reset(target); if (retval != ERROR_OK) return retval; if (esirisc_jtag_is_stopped(jtag_info)) { - LOG_ERROR("%s: target unresponsive; giving up", target_name(target)); + LOG_TARGET_ERROR(target, "target unresponsive; giving up"); return ERROR_FAIL; } } @@ -1034,7 +1034,7 @@ static int esirisc_debug_entry(struct target *target) struct esirisc_common *esirisc = target_to_esirisc(target); struct breakpoint *breakpoint; - LOG_DEBUG("-"); + LOG_TARGET_DEBUG(target, "-"); esirisc_save_context(target); @@ -1087,12 +1087,12 @@ static int esirisc_poll(struct target *target) retval = esirisc_jtag_enable_debug(jtag_info); if (retval != ERROR_OK) { - LOG_ERROR("%s: failed to poll target", target_name(target)); + LOG_TARGET_ERROR(target, "failed to poll target"); return retval; } if (esirisc_jtag_is_stopped(jtag_info)) { - LOG_ERROR("%s: target has stopped; reset required", target_name(target)); + LOG_TARGET_ERROR(target, "target has stopped; reset required"); target->state = TARGET_UNKNOWN; return ERROR_TARGET_FAILURE; } @@ -1122,7 +1122,7 @@ static int esirisc_assert_reset(struct target *target) struct esirisc_jtag *jtag_info = &esirisc->jtag_info; int retval; - LOG_DEBUG("-"); + LOG_TARGET_DEBUG(target, "-"); if (jtag_get_reset_config() & RESET_HAS_SRST) { jtag_add_reset(1, 1); @@ -1134,7 +1134,7 @@ static int esirisc_assert_reset(struct target *target) retval = esirisc_jtag_assert_reset(jtag_info); if (retval != ERROR_OK) { - LOG_ERROR("%s: failed to assert reset", target_name(target)); + LOG_TARGET_ERROR(target, "failed to assert reset"); return retval; } } @@ -1153,19 +1153,19 @@ static int esirisc_reset_entry(struct target *target) uint32_t eta, epc; int retval; - LOG_DEBUG("-"); + LOG_TARGET_DEBUG(target, "-"); /* read exception table address */ retval = esirisc_jtag_read_csr(jtag_info, CSR_THREAD, CSR_THREAD_ETA, &eta); if (retval != ERROR_OK) { - LOG_ERROR("%s: failed to read Thread CSR: ETA", target_name(target)); + LOG_TARGET_ERROR(target, "failed to read Thread CSR: ETA"); return retval; } /* read reset entry point */ retval = esirisc_jtag_read_word(jtag_info, eta + ENTRY_RESET, &epc); if (retval != ERROR_OK) { - LOG_ERROR("%s: failed to read address: 0x%" TARGET_PRIxADDR, target_name(target), + LOG_TARGET_ERROR(target, "failed to read address: 0x%" TARGET_PRIxADDR, (target_addr_t)epc); return retval; } @@ -1173,7 +1173,7 @@ static int esirisc_reset_entry(struct target *target) /* write reset entry point */ retval = esirisc_jtag_write_csr(jtag_info, CSR_THREAD, CSR_THREAD_EPC, epc); if (retval != ERROR_OK) { - LOG_ERROR("%s: failed to write Thread CSR: EPC", target_name(target)); + LOG_TARGET_ERROR(target, "failed to write Thread CSR: EPC"); return retval; } @@ -1186,7 +1186,7 @@ static int esirisc_deassert_reset(struct target *target) struct esirisc_jtag *jtag_info = &esirisc->jtag_info; int retval; - LOG_DEBUG("-"); + LOG_TARGET_DEBUG(target, "-"); if (jtag_get_reset_config() & RESET_HAS_SRST) { jtag_add_reset(0, 0); @@ -1202,14 +1202,14 @@ static int esirisc_deassert_reset(struct target *target) } else { retval = esirisc_jtag_deassert_reset(jtag_info); if (retval != ERROR_OK) { - LOG_ERROR("%s: failed to deassert reset", target_name(target)); + LOG_TARGET_ERROR(target, "failed to deassert reset"); return retval; } } retval = esirisc_wait_debug_active(esirisc, RESET_TIMEOUT); if (retval != ERROR_OK) { - LOG_ERROR("%s: reset timed out", target_name(target)); + LOG_TARGET_ERROR(target, "reset timed out"); return retval; } @@ -1225,7 +1225,7 @@ static int esirisc_deassert_reset(struct target *target) if (!target->reset_halt) { retval = esirisc_jtag_continue(jtag_info); if (retval != ERROR_OK) { - LOG_ERROR("%s: failed to resume target", target_name(target)); + LOG_TARGET_ERROR(target, "failed to resume target"); return retval; } } @@ -1241,7 +1241,7 @@ static int esirisc_arch_state(struct target *target) uint32_t eid = buf_get_u32(esirisc->eid->value, 0, esirisc->eid->size); uint32_t ed = buf_get_u32(esirisc->ed->value, 0, esirisc->ed->size); - LOG_USER("target halted due to %s, exception: %s\n" + LOG_TARGET_USER(target, "target halted due to %s, exception: %s\n" "EPC: 0x%" PRIx32 ", ECAS: 0x%" PRIx32 ", EID: 0x%" PRIx32 ", ED: 0x%" PRIx32, debug_reason_name(target), esirisc_exception_strings[eid], epc, ecas, eid, ed); @@ -1252,7 +1252,7 @@ static const char *esirisc_get_gdb_arch(const struct target *target) { struct esirisc_common *esirisc = target_to_esirisc(target); - LOG_DEBUG("-"); + LOG_TARGET_DEBUG(target, "-"); /* * Targets with the UNIFIED_ADDRESS_SPACE option disabled employ a @@ -1272,7 +1272,7 @@ static int esirisc_get_gdb_reg_list(struct target *target, struct reg **reg_list { struct esirisc_common *esirisc = target_to_esirisc(target); - LOG_DEBUG("-"); + LOG_TARGET_DEBUG(target, "-"); *reg_list_size = ESIRISC_NUM_REGS; @@ -1302,11 +1302,11 @@ static int esirisc_read_reg(struct reg *reg) struct target *target = esirisc->target; uint32_t data; - LOG_DEBUG("-"); + LOG_TARGET_DEBUG(target, "-"); int retval = esirisc_jtag_read_reg(jtag_info, reg->number, &data); if (retval != ERROR_OK) { - LOG_ERROR("%s: failed to read register: %s", target_name(target), reg->name); + LOG_TARGET_ERROR(target, "failed to read register: %s", reg->name); return retval; } @@ -1325,11 +1325,11 @@ static int esirisc_write_reg(struct reg *reg) struct target *target = esirisc->target; uint32_t data = buf_get_u32(reg->value, 0, reg->size); - LOG_DEBUG("-"); + LOG_TARGET_DEBUG(target, "-"); int retval = esirisc_jtag_write_reg(jtag_info, reg->number, data); if (retval != ERROR_OK) { - LOG_ERROR("%s: failed to write register: %s", target_name(target), reg->name); + LOG_TARGET_ERROR(target, "failed to write register: %s", reg->name); return retval; } @@ -1347,11 +1347,11 @@ static int esirisc_read_csr(struct reg *reg) struct target *target = esirisc->target; uint32_t data; - LOG_DEBUG("-"); + LOG_TARGET_DEBUG(target, "-"); int retval = esirisc_jtag_read_csr(jtag_info, reg_info->bank, reg_info->csr, &data); if (retval != ERROR_OK) { - LOG_ERROR("%s: failed to read CSR: %s", target_name(target), reg->name); + LOG_TARGET_ERROR(target, "failed to read CSR: %s", reg->name); return retval; } @@ -1370,11 +1370,11 @@ static int esirisc_write_csr(struct reg *reg) struct target *target = esirisc->target; uint32_t data = buf_get_u32(reg->value, 0, reg->size); - LOG_DEBUG("-"); + LOG_TARGET_DEBUG(target, "-"); int retval = esirisc_jtag_write_csr(jtag_info, reg_info->bank, reg_info->csr, data); if (retval != ERROR_OK) { - LOG_ERROR("%s: failed to write CSR: %s", target_name(target), reg->name); + LOG_TARGET_ERROR(target, "failed to write CSR: %s", reg->name); return retval; } @@ -1390,7 +1390,7 @@ static int esirisc_get_reg(struct reg *reg) struct esirisc_common *esirisc = reg_info->esirisc; struct target *target = esirisc->target; - LOG_DEBUG("-"); + LOG_TARGET_DEBUG(target, "-"); if (target->state != TARGET_HALTED) return ERROR_TARGET_NOT_HALTED; @@ -1405,7 +1405,7 @@ static int esirisc_set_reg(struct reg *reg, uint8_t *buf) struct target *target = esirisc->target; uint32_t value = buf_get_u32(buf, 0, reg->size); - LOG_DEBUG("-"); + LOG_TARGET_DEBUG(target, "-"); if (target->state != TARGET_HALTED) return ERROR_TARGET_NOT_HALTED; @@ -1429,7 +1429,7 @@ static struct reg_cache *esirisc_build_reg_cache(struct target *target) struct reg_cache *cache = malloc(sizeof(struct reg_cache)); struct reg *reg_list = calloc(ESIRISC_NUM_REGS, sizeof(struct reg)); - LOG_DEBUG("-"); + LOG_TARGET_DEBUG(target, "-"); cache->name = "eSi-RISC registers"; cache->next = NULL; @@ -1519,11 +1519,11 @@ static int esirisc_identify(struct target *target) uint32_t csr; int retval; - LOG_DEBUG("-"); + LOG_TARGET_DEBUG(target, "-"); retval = esirisc_jtag_read_csr(jtag_info, CSR_CONFIG, CSR_CONFIG_ARCH0, &csr); if (retval != ERROR_OK) { - LOG_ERROR("%s: failed to read Configuration CSR: ARCH0", target_name(target)); + LOG_TARGET_ERROR(target, "failed to read Configuration CSR: ARCH0"); return retval; } @@ -1532,7 +1532,7 @@ static int esirisc_identify(struct target *target) retval = esirisc_jtag_read_csr(jtag_info, CSR_CONFIG, CSR_CONFIG_MEM, &csr); if (retval != ERROR_OK) { - LOG_ERROR("%s: failed to read Configuration CSR: MEM", target_name(target)); + LOG_TARGET_ERROR(target, "failed to read Configuration CSR: MEM"); return retval; } @@ -1541,7 +1541,7 @@ static int esirisc_identify(struct target *target) retval = esirisc_jtag_read_csr(jtag_info, CSR_CONFIG, CSR_CONFIG_IC, &csr); if (retval != ERROR_OK) { - LOG_ERROR("%s: failed to read Configuration CSR: IC", target_name(target)); + LOG_TARGET_ERROR(target, "failed to read Configuration CSR: IC"); return retval; } @@ -1549,7 +1549,7 @@ static int esirisc_identify(struct target *target) retval = esirisc_jtag_read_csr(jtag_info, CSR_CONFIG, CSR_CONFIG_DC, &csr); if (retval != ERROR_OK) { - LOG_ERROR("%s: failed to read Configuration CSR: DC", target_name(target)); + LOG_TARGET_ERROR(target, "failed to read Configuration CSR: DC"); return retval; } @@ -1557,7 +1557,7 @@ static int esirisc_identify(struct target *target) retval = esirisc_jtag_read_csr(jtag_info, CSR_CONFIG, CSR_CONFIG_DBG, &csr); if (retval != ERROR_OK) { - LOG_ERROR("%s: failed to read Configuration CSR: DBG", target_name(target)); + LOG_TARGET_ERROR(target, "failed to read Configuration CSR: DBG"); return retval; } @@ -1566,7 +1566,7 @@ static int esirisc_identify(struct target *target) retval = esirisc_jtag_read_csr(jtag_info, CSR_CONFIG, CSR_CONFIG_TRACE, &csr); if (retval != ERROR_OK) { - LOG_ERROR("%s: failed to read Configuration CSR: TRACE", target_name(target)); + LOG_TARGET_ERROR(target, "failed to read Configuration CSR: TRACE"); return retval; } @@ -1584,8 +1584,7 @@ static int esirisc_target_create(struct target *target, Jim_Interp *interp) return ERROR_FAIL; if (tap->ir_length != INSTR_LENGTH) { - LOG_ERROR("%s: invalid IR length; expected %d", target_name(target), - INSTR_LENGTH); + LOG_TARGET_ERROR(target, "invalid IR length; expected %d", INSTR_LENGTH); return ERROR_FAIL; } @@ -1629,7 +1628,7 @@ static int esirisc_examine(struct target *target) struct esirisc_jtag *jtag_info = &esirisc->jtag_info; int retval; - LOG_DEBUG("-"); + LOG_TARGET_DEBUG(target, "-"); if (!target_was_examined(target)) { retval = esirisc_debug_enable(target); @@ -1649,7 +1648,7 @@ static int esirisc_examine(struct target *target) } else { retval = esirisc_jtag_break(jtag_info); if (retval != ERROR_OK) { - LOG_ERROR("%s: failed to halt target", target_name(target)); + LOG_TARGET_ERROR(target, "failed to halt target"); return retval; } @@ -1658,7 +1657,7 @@ static int esirisc_examine(struct target *target) retval = esirisc_identify(target); if (retval != ERROR_OK) { - LOG_ERROR("%s: failed to identify target", target_name(target)); + LOG_TARGET_ERROR(target, "failed to identify target"); return retval; } @@ -1675,20 +1674,20 @@ static int esirisc_examine(struct target *target) else { retval = esirisc_jtag_continue(jtag_info); if (retval != ERROR_OK) { - LOG_ERROR("%s: failed to resume target", target_name(target)); + LOG_TARGET_ERROR(target, "failed to resume target"); return retval; } } target_set_examined(target); - LOG_INFO("%s: %d bit, %d registers, %s%s%s", target_name(target), + LOG_TARGET_INFO(target, "%d bit, %d registers, %s%s%s", esirisc->num_bits, esirisc->num_regs, target_endianness(target), esirisc->has_icache ? ", icache" : "", esirisc->has_dcache ? ", dcache" : ""); - LOG_INFO("%s: hardware has %d breakpoints, %d watchpoints%s", target_name(target), + LOG_TARGET_INFO(target, "hardware has %d breakpoints, %d watchpoints%s", esirisc->num_breakpoints, esirisc->num_watchpoints, esirisc->has_trace ? ", trace" : ""); } @@ -1707,7 +1706,7 @@ COMMAND_HANDLER(handle_esirisc_cache_arch_command) else if (strcmp(*CMD_ARGV, "von_neumann") == 0) esirisc->cache_arch = ESIRISC_CACHE_VON_NEUMANN; else { - LOG_ERROR("invalid cache_arch: %s", *CMD_ARGV); + LOG_TARGET_ERROR(target, "invalid cache_arch: %s", *CMD_ARGV); return ERROR_COMMAND_SYNTAX_ERROR; } } @@ -1724,7 +1723,7 @@ COMMAND_HANDLER(handle_esirisc_flush_caches_command) int retval; if (!esirisc_has_cache(esirisc)) { - LOG_ERROR("target does not support caching"); + LOG_TARGET_ERROR(target, "target does not support caching"); return ERROR_FAIL; } @@ -1770,7 +1769,7 @@ COMMAND_HANDLER(handle_esirisc_hwdc_command) while (CMD_ARGC-- > 0) { int mask = esirisc_find_hwdc_mask(CMD_ARGV[CMD_ARGC]); if (mask < 0) { - LOG_ERROR("invalid mask: %s", CMD_ARGV[CMD_ARGC]); + LOG_TARGET_ERROR(target, "invalid mask: %s", CMD_ARGV[CMD_ARGC]); return ERROR_COMMAND_SYNTAX_ERROR; } esirisc->hwdc_save |= mask; diff --git a/src/target/esirisc_jtag.c b/src/target/esirisc_jtag.c index 1ec1726..ad2bef5 100644 --- a/src/target/esirisc_jtag.c +++ b/src/target/esirisc_jtag.c @@ -19,6 +19,8 @@ #include "esirisc_jtag.h" +static uint8_t esirisc_jtag_get_eid(struct esirisc_jtag *jtag_info); + static void esirisc_jtag_set_instr(struct esirisc_jtag *jtag_info, uint32_t new_instr) { struct jtag_tap *tap = jtag_info->tap; @@ -58,11 +60,12 @@ static int esirisc_jtag_get_padding(void) return padding; } -static int esirisc_jtag_count_bits(int num_fields, struct scan_field *fields) +static int esirisc_jtag_count_bits(unsigned int num_fields, + struct scan_field *fields) { int bit_count = 0; - for (int i = 0; i < num_fields; ++i) + for (unsigned int i = 0; i < num_fields; ++i) bit_count += fields[i].num_bits; return bit_count; @@ -220,7 +223,7 @@ bool esirisc_jtag_is_stopped(struct esirisc_jtag *jtag_info) return !!(jtag_info->status & 1<<6); /* S */ } -uint8_t esirisc_jtag_get_eid(struct esirisc_jtag *jtag_info) +static uint8_t esirisc_jtag_get_eid(struct esirisc_jtag *jtag_info) { return jtag_info->status & 0x3f; /* EID */ } @@ -489,7 +492,7 @@ int esirisc_jtag_enable_debug(struct esirisc_jtag *jtag_info) return esirisc_jtag_send_ctrl(jtag_info, DEBUG_ENABLE_DEBUG); } -int esirisc_jtag_disable_debug(struct esirisc_jtag *jtag_info) +static __attribute__((unused)) int esirisc_jtag_disable_debug(struct esirisc_jtag *jtag_info) { return esirisc_jtag_send_ctrl(jtag_info, DEBUG_DISABLE_DEBUG); } diff --git a/src/target/esirisc_jtag.h b/src/target/esirisc_jtag.h index 98ec8af..d59b75f 100644 --- a/src/target/esirisc_jtag.h +++ b/src/target/esirisc_jtag.h @@ -54,7 +54,6 @@ struct esirisc_jtag { bool esirisc_jtag_is_debug_active(struct esirisc_jtag *jtag_info); bool esirisc_jtag_is_stopped(struct esirisc_jtag *jtag_info); -uint8_t esirisc_jtag_get_eid(struct esirisc_jtag *jtag_info); int esirisc_jtag_read_byte(struct esirisc_jtag *jtag_info, uint32_t address, uint8_t *data); @@ -81,7 +80,6 @@ int esirisc_jtag_write_csr(struct esirisc_jtag *jtag_info, uint8_t bank, uint8_t csr, uint32_t data); int esirisc_jtag_enable_debug(struct esirisc_jtag *jtag_info); -int esirisc_jtag_disable_debug(struct esirisc_jtag *jtag_info); int esirisc_jtag_assert_reset(struct esirisc_jtag *jtag_info); int esirisc_jtag_deassert_reset(struct esirisc_jtag *jtag_info); diff --git a/src/target/esirisc_trace.c b/src/target/esirisc_trace.c index 376ea1d..a1d92d1 100644 --- a/src/target/esirisc_trace.c +++ b/src/target/esirisc_trace.c @@ -85,7 +85,7 @@ static int esirisc_trace_clear_status(struct target *target) retval = esirisc_jtag_write_csr(jtag_info, CSR_TRACE, CSR_TRACE_STATUS, ~0); if (retval != ERROR_OK) { - LOG_ERROR("%s: failed to write Trace CSR: Status", target_name(target)); + LOG_TARGET_ERROR(target, "failed to write Trace CSR: Status"); return retval; } @@ -102,7 +102,7 @@ static int esirisc_trace_get_status(struct target *target, uint32_t *status) int retval = esirisc_jtag_read_csr(jtag_info, CSR_TRACE, CSR_TRACE_STATUS, status); if (retval != ERROR_OK) { - LOG_ERROR("%s: failed to read Trace CSR: Status", target_name(target)); + LOG_TARGET_ERROR(target, "failed to read Trace CSR: Status"); return retval; } @@ -121,7 +121,7 @@ static int esirisc_trace_start(struct target *target) retval = esirisc_jtag_read_csr(jtag_info, CSR_TRACE, CSR_TRACE_CONTROL, &control); if (retval != ERROR_OK) { - LOG_ERROR("%s: failed to read Trace CSR: Control", target_name(target)); + LOG_TARGET_ERROR(target, "failed to read Trace CSR: Control"); return retval; } @@ -129,7 +129,7 @@ static int esirisc_trace_start(struct target *target) retval = esirisc_jtag_write_csr(jtag_info, CSR_TRACE, CSR_TRACE_CONTROL, control); if (retval != ERROR_OK) { - LOG_ERROR("%s: failed to write Trace CSR: Control", target_name(target)); + LOG_TARGET_ERROR(target, "failed to write Trace CSR: Control"); return retval; } @@ -148,7 +148,7 @@ static int esirisc_trace_stop(struct target *target) retval = esirisc_jtag_read_csr(jtag_info, CSR_TRACE, CSR_TRACE_CONTROL, &control); if (retval != ERROR_OK) { - LOG_ERROR("%s: failed to read Trace CSR: Control", target_name(target)); + LOG_TARGET_ERROR(target, "failed to read Trace CSR: Control"); return retval; } @@ -156,7 +156,7 @@ static int esirisc_trace_stop(struct target *target) retval = esirisc_jtag_write_csr(jtag_info, CSR_TRACE, CSR_TRACE_CONTROL, control); if (retval != ERROR_OK) { - LOG_ERROR("%s: failed to write Trace CSR: Control", target_name(target)); + LOG_TARGET_ERROR(target, "failed to write Trace CSR: Control"); return retval; } @@ -195,7 +195,7 @@ static int esirisc_trace_init(struct target *target) retval = esirisc_jtag_write_csr(jtag_info, CSR_TRACE, CSR_TRACE_CONTROL, control); if (retval != ERROR_OK) { - LOG_ERROR("%s: failed to write Trace CSR: Control", target_name(target)); + LOG_TARGET_ERROR(target, "failed to write Trace CSR: Control"); return retval; } @@ -203,14 +203,14 @@ static int esirisc_trace_init(struct target *target) retval = esirisc_jtag_write_csr(jtag_info, CSR_TRACE, CSR_TRACE_BUFFER_START, trace_info->buffer_start); if (retval != ERROR_OK) { - LOG_ERROR("%s: failed to write Trace CSR: BufferStart", target_name(target)); + LOG_TARGET_ERROR(target, "failed to write Trace CSR: BufferStart"); return retval; } retval = esirisc_jtag_write_csr(jtag_info, CSR_TRACE, CSR_TRACE_BUFFER_END, trace_info->buffer_end); if (retval != ERROR_OK) { - LOG_ERROR("%s: failed to write Trace CSR: BufferEnd", target_name(target)); + LOG_TARGET_ERROR(target, "failed to write Trace CSR: BufferEnd"); return retval; } @@ -221,7 +221,7 @@ static int esirisc_trace_init(struct target *target) retval = esirisc_jtag_write_csr(jtag_info, CSR_TRACE, CSR_TRACE_BUFFER_CUR, trace_info->buffer_start); if (retval != ERROR_OK) { - LOG_ERROR("%s: failed to write Trace CSR: BufferCurrent", target_name(target)); + LOG_TARGET_ERROR(target, "failed to write Trace CSR: BufferCurrent"); return retval; } @@ -241,7 +241,7 @@ static int esirisc_trace_init(struct target *target) retval = esirisc_jtag_write_csr(jtag_info, CSR_TRACE, CSR_TRACE_TRIGGER, trigger); if (retval != ERROR_OK) { - LOG_ERROR("%s: failed to write Trace CSR: Trigger", target_name(target)); + LOG_TARGET_ERROR(target, "failed to write Trace CSR: Trigger"); return retval; } @@ -249,14 +249,14 @@ static int esirisc_trace_init(struct target *target) retval = esirisc_jtag_write_csr(jtag_info, CSR_TRACE, CSR_TRACE_START_DATA, trace_info->start_data); if (retval != ERROR_OK) { - LOG_ERROR("%s: failed to write Trace CSR: StartData", target_name(target)); + LOG_TARGET_ERROR(target, "failed to write Trace CSR: StartData"); return retval; } retval = esirisc_jtag_write_csr(jtag_info, CSR_TRACE, CSR_TRACE_START_MASK, trace_info->start_mask); if (retval != ERROR_OK) { - LOG_ERROR("%s: failed to write Trace CSR: StartMask", target_name(target)); + LOG_TARGET_ERROR(target, "failed to write Trace CSR: StartMask"); return retval; } @@ -264,14 +264,14 @@ static int esirisc_trace_init(struct target *target) retval = esirisc_jtag_write_csr(jtag_info, CSR_TRACE, CSR_TRACE_STOP_DATA, trace_info->stop_data); if (retval != ERROR_OK) { - LOG_ERROR("%s: failed to write Trace CSR: StopData", target_name(target)); + LOG_TARGET_ERROR(target, "failed to write Trace CSR: StopData"); return retval; } retval = esirisc_jtag_write_csr(jtag_info, CSR_TRACE, CSR_TRACE_STOP_MASK, trace_info->stop_mask); if (retval != ERROR_OK) { - LOG_ERROR("%s: failed to write Trace CSR: StopMask", target_name(target)); + LOG_TARGET_ERROR(target, "failed to write Trace CSR: StopMask"); return retval; } @@ -279,7 +279,7 @@ static int esirisc_trace_init(struct target *target) retval = esirisc_jtag_write_csr(jtag_info, CSR_TRACE, CSR_TRACE_DELAY, trace_info->delay_cycles); if (retval != ERROR_OK) { - LOG_ERROR("%s: failed to write Trace CSR: Delay", target_name(target)); + LOG_TARGET_ERROR(target, "failed to write Trace CSR: Delay"); return retval; } @@ -287,9 +287,9 @@ static int esirisc_trace_init(struct target *target) } static int esirisc_trace_buf_get_u32(uint8_t *buffer, uint32_t size, - unsigned *pos, unsigned count, uint32_t *value) + unsigned int *pos, unsigned int count, uint32_t *value) { - const unsigned num_bits = size * 8; + const unsigned int num_bits = size * 8; if (*pos+count > num_bits) return ERROR_FAIL; @@ -301,7 +301,7 @@ static int esirisc_trace_buf_get_u32(uint8_t *buffer, uint32_t size, } static int esirisc_trace_buf_get_pc(struct target *target, uint8_t *buffer, uint32_t size, - unsigned *pos, uint32_t *value) + unsigned int *pos, uint32_t *value) { struct esirisc_common *esirisc = target_to_esirisc(target); struct esirisc_trace *trace_info = &esirisc->trace_info; @@ -326,7 +326,7 @@ static int esirisc_trace_read_memory(struct target *target, target_addr_t addres retval = target_read_memory(target, address, 1, size, buffer); if (retval != ERROR_OK) { - LOG_ERROR("%s: failed to read trace data", target_name(target)); + LOG_TARGET_ERROR(target, "failed to read trace data"); return retval; } @@ -346,7 +346,7 @@ static int esirisc_trace_read_buffer(struct target *target, uint8_t *buffer) retval = esirisc_jtag_read_csr(jtag_info, CSR_TRACE, CSR_TRACE_BUFFER_CUR, &buffer_cur); if (retval != ERROR_OK) { - LOG_ERROR("%s: failed to read Trace CSR: BufferCurrent", target_name(target)); + LOG_TARGET_ERROR(target, "failed to read Trace CSR: BufferCurrent"); return retval; } @@ -380,7 +380,7 @@ static int esirisc_trace_analyze_full(struct command_invocation *cmd, uint8_t *b const uint32_t num_bits = size * 8; int retval; - unsigned pos = 0; + unsigned int pos = 0; while (pos < num_bits) { uint32_t id; @@ -484,7 +484,7 @@ static int esirisc_trace_analyze_simple(struct command_invocation *cmd, uint8_t const uint32_t num_bits = size * 8; int retval; - unsigned pos = 0; + unsigned int pos = 0; while (pos < num_bits) { uint32_t pc; 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 22e1630..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); @@ -421,4 +422,5 @@ struct target_type esp32s3_target = { .deinit_target = esp_xtensa_target_deinit, .commands = esp32s3_command_handlers, + .profiling = esp_xtensa_profiling, }; diff --git a/src/target/espressif/esp_algorithm.h b/src/target/espressif/esp_algorithm.h index 11d2757..185234f 100644 --- a/src/target/espressif/esp_algorithm.h +++ b/src/target/espressif/esp_algorithm.h @@ -36,11 +36,13 @@ * Procedure of executing stub on target includes: * 1) User prepares struct esp_algorithm_run_data and calls one of algorithm_run_xxx() functions. * 2) Routine allocates all necessary stub code and data sections. - * 3) If a user specifies an initializer func esp_algorithm_usr_func_init_t it is called just before the stub starts. - * 4) If user specifies stub communication func esp_algorithm_usr_func_t (@see esp_flash_write/read in ESP flash driver) + * 3) If a user specifies an initializer func esp_algorithm_run_data::usr_func_init + * it is called just before the stub starts. + * 4) If user specifies stub communication func esp_algorithm_run_data::usr_func + * (@see esp_flash_write/read in ESP flash driver) * it is called just after the stub starts. When communication with stub is finished this function must return. * 5) OpenOCD waits for the stub to finish (hit exit breakpoint). - * 6) If the user specified arguments cleanup func esp_algorithm_usr_func_done_t, + * 6) If the user specified arguments cleanup func esp_algorithm_run_data::usr_func_done, * it is called just after the stub finishes. * * There are two options to run code on target under OpenOCD control: @@ -190,60 +192,6 @@ struct esp_algorithm_reg_args { struct esp_algorithm_run_data; -/** - * @brief Algorithm run function. - * - * @param target Pointer to target. - * @param run Pointer to algo run data. - * @param arg Function specific argument. - * - * @return ERROR_OK on success, otherwise ERROR_XXX. - */ -typedef int (*esp_algorithm_func_t)(struct target *target, struct esp_algorithm_run_data *run, void *arg); - -/** - * @brief Host part of algorithm. - * This function will be called while stub is running on target. - * It can be used for communication with stub. - * - * @param target Pointer to target. - * @param usr_arg Function specific argument. - * - * @return ERROR_OK on success, otherwise ERROR_XXX. - */ -typedef int (*esp_algorithm_usr_func_t)(struct target *target, void *usr_arg); - -/** - * @brief Algorithm's arguments setup function. - * This function will be called just before stub start. - * It must return when all operations with running stub are completed. - * It can be used to prepare stub memory parameters. - * - * @param target Pointer to target. - * @param run Pointer to algo run data. - * @param usr_arg Function specific argument. The same as for esp_algorithm_usr_func_t. - * - * @return ERROR_OK on success, otherwise ERROR_XXX. - */ -typedef int (*esp_algorithm_usr_func_init_t)(struct target *target, - struct esp_algorithm_run_data *run, - void *usr_arg); - -/** - * @brief Algorithm's arguments cleanup function. - * This function will be called just after stub exit. - * It can be used to cleanup stub memory parameters. - * - * @param target Pointer to target. - * @param run Pointer to algo run data. - * @param usr_arg Function specific argument. The same as for esp_algorithm_usr_func_t. - * - * @return ERROR_OK on success, otherwise ERROR_XXX. - */ -typedef void (*esp_algorithm_usr_func_done_t)(struct target *target, - struct esp_algorithm_run_data *run, - void *usr_arg); - struct esp_algorithm_hw { int (*algo_init)(struct target *target, struct esp_algorithm_run_data *run, uint32_t num_args, va_list ap); int (*algo_cleanup)(struct target *target, struct esp_algorithm_run_data *run); @@ -283,14 +231,61 @@ struct esp_algorithm_run_data { }; /** Host side algorithm function argument. */ void *usr_func_arg; - /** Host side algorithm function. */ - esp_algorithm_usr_func_t usr_func; - /** Host side algorithm function setup routine. */ - esp_algorithm_usr_func_init_t usr_func_init; - /** Host side algorithm function cleanup routine. */ - esp_algorithm_usr_func_done_t usr_func_done; - /** Algorithm run function: see algorithm_run_xxx for example. */ - esp_algorithm_func_t algo_func; + + /** + * @brief Host part of algorithm. + * This function will be called while stub is running on target. + * It can be used for communication with stub. + * + * @param target Pointer to target. + * @param usr_arg Function specific argument. + * + * @return ERROR_OK on success, otherwise ERROR_XXX. + */ + int (*usr_func)(struct target *target, void *usr_arg); + + /** + * @brief Algorithm's arguments setup function. + * This function will be called just before stub start. + * It must return when all operations with running stub are completed. + * It can be used to prepare stub memory parameters. + * + * @param target Pointer to target. + * @param run Pointer to algo run data. + * @param usr_arg Function specific argument. The same as for usr_func. + * + * @return ERROR_OK on success, otherwise ERROR_XXX. + */ + int (*usr_func_init)(struct target *target, + struct esp_algorithm_run_data *run, + void *usr_arg); + + /** + * @brief Algorithm's arguments cleanup function. + * This function will be called just after stub exit. + * It can be used to cleanup stub memory parameters. + * + * @param target Pointer to target. + * @param run Pointer to algo run data. + * @param usr_arg Function specific argument. The same as for usr_func. + * + * @return ERROR_OK on success, otherwise ERROR_XXX. + */ + void (*usr_func_done)(struct target *target, + struct esp_algorithm_run_data *run, + void *usr_arg); + + /** + * @brief Algorithm run function. + * + * @param target Pointer to target. + * @param run Pointer to algo run data. + * @param arg Function specific argument. + * + * @return ERROR_OK on success, otherwise ERROR_XXX. + */ + int (*algo_func)(struct target *target, struct esp_algorithm_run_data *run, void *arg); + /** HW specific API */ const struct esp_algorithm_hw *hw; }; diff --git a/src/target/espressif/esp_xtensa.c b/src/target/espressif/esp_xtensa.c index 11895d2..4cadcb3 100644 --- a/src/target/espressif/esp_xtensa.c +++ b/src/target/espressif/esp_xtensa.c @@ -179,3 +179,75 @@ int esp_xtensa_breakpoint_remove(struct target *target, struct breakpoint *break return xtensa_breakpoint_remove(target, breakpoint); /* flash breakpoints will be handled in another patch */ } + +int esp_xtensa_profiling(struct target *target, uint32_t *samples, + uint32_t max_num_samples, uint32_t *num_samples, uint32_t seconds) +{ + struct timeval timeout, now; + struct xtensa *xtensa = target_to_xtensa(target); + int retval = ERROR_OK; + int res; + + /* Vary samples per pass to avoid sampling a periodic function periodically */ + #define MIN_PASS 200 + #define MAX_PASS 1000 + + gettimeofday(&timeout, NULL); + timeval_add_time(&timeout, seconds, 0); + + uint8_t buf[sizeof(uint32_t) * MAX_PASS]; + + /* Capture one sample to verify the register is present and working */ + xtensa_queue_dbg_reg_read(xtensa, XDMREG_DEBUGPC, buf); + res = xtensa_dm_queue_execute(&xtensa->dbg_mod); + if (res != ERROR_OK) { + LOG_TARGET_INFO(target, "Failed to read DEBUGPC, fallback to stop-and-go"); + return target_profiling_default(target, samples, max_num_samples, num_samples, seconds); + } else if (buf[0] == 0 && buf[1] == 0 && buf[2] == 0 && buf[3] == 0) { + LOG_TARGET_INFO(target, "NULL DEBUGPC, fallback to stop-and-go"); + return target_profiling_default(target, samples, max_num_samples, num_samples, seconds); + } + + LOG_TARGET_INFO(target, "Starting XTENSA DEBUGPC profiling. Sampling as fast as we can..."); + + /* Make sure the target is running */ + target_poll(target); + if (target->state == TARGET_HALTED) + retval = target_resume(target, true, 0, false, false); + + if (retval != ERROR_OK) { + LOG_TARGET_ERROR(target, "Error while resuming target"); + return retval; + } + + uint32_t sample_count = 0; + + for (;;) { + uint32_t remaining = max_num_samples - sample_count; + uint32_t this_pass = rand() % (MAX_PASS - MIN_PASS) + MIN_PASS; + this_pass = this_pass > remaining ? remaining : this_pass; + for (uint32_t i = 0; i < this_pass; ++i) + xtensa_queue_dbg_reg_read(xtensa, XDMREG_DEBUGPC, buf + i * sizeof(uint32_t)); + res = xtensa_dm_queue_execute(&xtensa->dbg_mod); + if (res != ERROR_OK) { + LOG_TARGET_ERROR(target, "Failed to read DEBUGPC!"); + return res; + } + + for (uint32_t i = 0; i < this_pass; ++i) { + uint32_t sample32 = buf_get_u32(buf + i * sizeof(uint32_t), 0, 32); + samples[sample_count++] = sample32; + } + gettimeofday(&now, NULL); + if (sample_count >= max_num_samples || timeval_compare(&now, &timeout) > 0) { + LOG_TARGET_INFO(target, "Profiling completed. %" PRIu32 " samples.", sample_count); + break; + } + } + + *num_samples = sample_count; + return retval; + + #undef MIN_PASS + #undef MAX_PASS +} diff --git a/src/target/espressif/esp_xtensa.h b/src/target/espressif/esp_xtensa.h index 00f67a3..56c903f 100644 --- a/src/target/espressif/esp_xtensa.h +++ b/src/target/espressif/esp_xtensa.h @@ -37,6 +37,9 @@ void esp_xtensa_queue_tdi_idle(struct target *target); int esp_xtensa_breakpoint_add(struct target *target, struct breakpoint *breakpoint); int esp_xtensa_breakpoint_remove(struct target *target, struct breakpoint *breakpoint); int esp_xtensa_poll(struct target *target); +int esp_xtensa_profiling(struct target *target, uint32_t *samples, + uint32_t max_num_samples, uint32_t *num_samples, uint32_t seconds); + int esp_xtensa_on_halt(struct target *target); #endif /* OPENOCD_TARGET_ESP_XTENSA_H */ diff --git a/src/target/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/etb.c b/src/target/etb.c index 3b9004b..fb3112d 100644 --- a/src/target/etb.c +++ b/src/target/etb.c @@ -454,12 +454,12 @@ static int etb_init(struct etm_context *etm_ctx) return ERROR_OK; } -static trace_status_t etb_status(struct etm_context *etm_ctx) +static enum trace_status etb_status(struct etm_context *etm_ctx) { struct etb *etb = etm_ctx->capture_driver_priv; struct reg *control = &etb->reg_cache->reg_list[ETB_CTRL]; struct reg *status = &etb->reg_cache->reg_list[ETB_STATUS]; - trace_status_t retval = 0; + enum trace_status retval = 0; int etb_timeout = 100; etb->etm_ctx = etm_ctx; diff --git a/src/target/etb.h b/src/target/etb.h index fa75600..1d0c08b 100644 --- a/src/target/etb.h +++ b/src/target/etb.h @@ -32,7 +32,7 @@ struct etb { uint32_t ram_width; /** how much trace buffer to fill after trigger */ - unsigned trigger_percent; + unsigned int trigger_percent; }; struct etb_reg { diff --git a/src/target/etm.c b/src/target/etm.c index d083017..d9a3cdc 100644 --- a/src/target/etm.c +++ b/src/target/etm.c @@ -220,10 +220,10 @@ static const struct reg_arch_type etm_scan6_type = { /* Look up register by ID ... most ETM instances only * support a subset of the possible registers. */ -static struct reg *etm_reg_lookup(struct etm_context *etm_ctx, unsigned id) +static struct reg *etm_reg_lookup(struct etm_context *etm_ctx, unsigned int id) { struct reg_cache *cache = etm_ctx->reg_cache; - unsigned i; + unsigned int i; for (i = 0; i < cache->num_regs; i++) { struct etm_reg *reg = cache->reg_list[i].arch_info; @@ -238,9 +238,9 @@ static struct reg *etm_reg_lookup(struct etm_context *etm_ctx, unsigned id) return NULL; } -static void etm_reg_add(unsigned bcd_vers, struct arm_jtag *jtag_info, +static void etm_reg_add(unsigned int bcd_vers, struct arm_jtag *jtag_info, struct reg_cache *cache, struct etm_reg *ereg, - const struct etm_reg_info *r, unsigned nreg) + const struct etm_reg_info *r, unsigned int nreg) { struct reg *reg = cache->reg_list; @@ -281,7 +281,7 @@ struct reg_cache *etm_build_reg_cache(struct target *target, struct reg_cache *reg_cache = malloc(sizeof(struct reg_cache)); struct reg *reg_list = NULL; struct etm_reg *arch_info = NULL; - unsigned bcd_vers, config; + unsigned int bcd_vers, config; /* the actual registers are kept in two arrays */ reg_list = calloc(128, sizeof(struct reg)); @@ -320,9 +320,8 @@ struct reg_cache *etm_build_reg_cache(struct target *target, etm_reg_add(0x20, jtag_info, reg_cache, arch_info, etm_core + 1, 1); etm_get_reg(reg_list + 1); - etm_ctx->id = buf_get_u32( - arch_info[1].value, 0, 32); - LOG_DEBUG("ETM ID: %08x", (unsigned) etm_ctx->id); + etm_ctx->id = buf_get_u32(arch_info[1].value, 0, 32); + LOG_DEBUG("ETM ID: %08" PRIx32, etm_ctx->id); bcd_vers = 0x10 + (((etm_ctx->id) >> 4) & 0xff); } else { @@ -1495,7 +1494,7 @@ COMMAND_HANDLER(handle_etm_info_command) etm_get_reg(etm_sys_config_reg); config = buf_get_u32(etm_sys_config_reg->value, 0, 32); - LOG_DEBUG("ETM SYS CONFIG %08x", (unsigned) config); + LOG_DEBUG("ETM SYS CONFIG %08" PRIx32, config); max_port_size = config & 0x7; if (etm->bcd_vers >= 0x30) @@ -1568,7 +1567,7 @@ COMMAND_HANDLER(handle_etm_status_command) struct target *target; struct arm *arm; struct etm_context *etm; - trace_status_t trace_status; + enum trace_status trace_status; target = get_current_target(CMD_CTX); arm = target_to_arm(target); @@ -1591,7 +1590,7 @@ COMMAND_HANDLER(handle_etm_status_command) if (!reg) return ERROR_FAIL; if (etm_get_reg(reg) == ERROR_OK) { - unsigned s = buf_get_u32(reg->value, 0, reg->size); + unsigned int s = buf_get_u32(reg->value, 0, reg->size); command_print(CMD, "etm: %s%s%s%s", /* bit(1) == progbit */ diff --git a/src/target/etm.h b/src/target/etm.h index be5f2c7..e18549d 100644 --- a/src/target/etm.h +++ b/src/target/etm.h @@ -126,7 +126,7 @@ struct etm_capture_driver { const char *name; const struct command_registration *commands; int (*init)(struct etm_context *etm_ctx); - trace_status_t (*status)(struct etm_context *etm_ctx); + enum trace_status (*status)(struct etm_context *etm_ctx); int (*read_trace)(struct etm_context *etm_ctx); int (*start_capture)(struct etm_context *etm_ctx); int (*stop_capture)(struct etm_context *etm_ctx); @@ -153,7 +153,7 @@ struct etm_context { struct reg_cache *reg_cache; /* ETM register cache */ struct etm_capture_driver *capture_driver; /* driver used to access ETM data */ void *capture_driver_priv; /* capture driver private data */ - trace_status_t capture_status; /* current state of capture run */ + enum trace_status capture_status; /* current state of capture run */ struct etmv1_trace_data *trace_data; /* trace data */ uint32_t trace_depth; /* number of cycles to be analyzed, 0 if no data available */ uint32_t control; /* shadow of ETM_CTRL */ @@ -175,7 +175,7 @@ struct etm_context { }; /* PIPESTAT values */ -typedef enum { +enum etmv1_pipestat { STAT_IE = 0x0, STAT_ID = 0x1, STAT_IN = 0x2, @@ -184,10 +184,10 @@ typedef enum { STAT_BD = 0x5, STAT_TR = 0x6, STAT_TD = 0x7 -} etmv1_pipestat_t; +}; /* branch reason values */ -typedef enum { +enum etmv1_branch_reason { BR_NORMAL = 0x0, /* Normal PC change : periodic synchro (ETMv1.1) */ BR_ENABLE = 0x1, /* Trace has been enabled */ BR_RESTART = 0x2, /* Trace restarted after a FIFO overflow */ @@ -196,7 +196,7 @@ typedef enum { BR_RSVD5 = 0x5, /* reserved */ BR_RSVD6 = 0x6, /* reserved */ BR_RSVD7 = 0x7, /* reserved */ -} etmv1_branch_reason_t; +}; struct reg_cache *etm_build_reg_cache(struct target *target, struct arm_jtag *jtag_info, struct etm_context *etm_ctx); diff --git a/src/target/etm_dummy.c b/src/target/etm_dummy.c index 8deccf5..2709b6e 100644 --- a/src/target/etm_dummy.c +++ b/src/target/etm_dummy.c @@ -65,7 +65,7 @@ static int etm_dummy_init(struct etm_context *etm_ctx) return ERROR_OK; } -static trace_status_t etm_dummy_status(struct etm_context *etm_ctx) +static enum trace_status etm_dummy_status(struct etm_context *etm_ctx) { return TRACE_IDLE; } 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 d6f2afb..ef05df2 100644 --- a/src/target/hla_target.c +++ b/src/target/hla_target.c @@ -258,7 +258,7 @@ static int adapter_debug_entry(struct target *target) arm->core_mode = ARM_MODE_HANDLER; arm->map = armv7m_msp_reg_map; } else { - unsigned control = buf_get_u32(arm->core_cache + unsigned int control = buf_get_u32(arm->core_cache ->reg_list[ARMV7M_CONTROL].value, 0, 3); /* is this thread privileged? */ @@ -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/image.c b/src/target/image.c index 9175c20..6864e4e 100644 --- a/src/target/image.c +++ b/src/target/image.c @@ -194,7 +194,7 @@ static int image_ihex_buffer_complete_inner(struct image *image, } while (count-- > 0) { - unsigned value; + unsigned int value; sscanf(&lpsz_line[bytes_read], "%2x", &value); ihex->buffer[cooked_bytes] = (uint8_t)value; cal_checksum += (uint8_t)ihex->buffer[cooked_bytes]; @@ -863,7 +863,7 @@ static int image_mot_buffer_complete_inner(struct image *image, } while (count-- > 0) { - unsigned value; + unsigned int value; sscanf(&lpsz_line[bytes_read], "%2x", &value); mot->buffer[cooked_bytes] = (uint8_t)value; cal_checksum += (uint8_t)mot->buffer[cooked_bytes]; diff --git a/src/target/lakemont.c b/src/target/lakemont.c index 6c0964b..39a50c7 100644 --- a/src/target/lakemont.c +++ b/src/target/lakemont.c @@ -67,7 +67,7 @@ static const struct { const char *name; uint64_t op; uint8_t pm_idx; - unsigned bits; + unsigned int bits; enum reg_type type; const char *group; const char *feature; @@ -224,10 +224,10 @@ static int irscan(struct target *t, uint8_t *out, if (ir_len != t->tap->ir_length) { retval = ERROR_FAIL; if (t->tap->enabled) - LOG_ERROR("%s tap enabled but tap irlen=%d", + LOG_ERROR("%s tap enabled but tap irlen=%u", __func__, t->tap->ir_length); else - LOG_ERROR("%s tap not enabled and irlen=%d", + LOG_ERROR("%s tap not enabled and irlen=%u", __func__, t->tap->ir_length); return retval; } @@ -597,7 +597,7 @@ static int read_all_core_hw_regs(struct target *t) { int err; uint32_t regval; - unsigned i; + unsigned int i; struct x86_32_common *x86_32 = target_to_x86_32(t); for (i = 0; i < (x86_32->cache->num_regs); i++) { if (regs[i].pm_idx == NOT_AVAIL_REG) @@ -616,7 +616,7 @@ static int read_all_core_hw_regs(struct target *t) static int write_all_core_hw_regs(struct target *t) { int err; - unsigned i; + unsigned int i; struct x86_32_common *x86_32 = target_to_x86_32(t); for (i = 0; i < (x86_32->cache->num_regs); i++) { if (regs[i].pm_idx == NOT_AVAIL_REG) @@ -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 61a9475..fdc52c3 100644 --- a/src/target/mem_ap.c +++ b/src/target/mem_ap.c @@ -34,13 +34,13 @@ static int mem_ap_target_create(struct target *target, Jim_Interp *interp) return ERROR_FAIL; if (pc->ap_num == DP_APSEL_INVALID) { - LOG_ERROR("AP number not specified"); + LOG_TARGET_ERROR(target, "AP number not specified"); return ERROR_FAIL; } mem_ap = calloc(1, sizeof(struct mem_ap)); if (!mem_ap) { - LOG_ERROR("Out of memory"); + LOG_TARGET_ERROR(target, "Out of memory"); return ERROR_FAIL; } @@ -58,7 +58,7 @@ static int mem_ap_target_create(struct target *target, Jim_Interp *interp) static int mem_ap_init_target(struct command_context *cmd_ctx, struct target *target) { - LOG_DEBUG("%s", __func__); + LOG_TARGET_DEBUG(target, "%s", __func__); target->state = TARGET_UNKNOWN; target->debug_reason = DBG_REASON_UNDEFINED; return ERROR_OK; @@ -68,19 +68,18 @@ static void mem_ap_deinit_target(struct target *target) { struct mem_ap *mem_ap = target->arch_info; - LOG_DEBUG("%s", __func__); + LOG_TARGET_DEBUG(target, "%s", __func__); if (mem_ap->ap) dap_put_ap(mem_ap->ap); free(target->private_config); free(target->arch_info); - return; } static int mem_ap_arch_state(struct target *target) { - LOG_DEBUG("%s", __func__); + LOG_TARGET_DEBUG(target, "%s", __func__); return ERROR_OK; } @@ -96,26 +95,27 @@ static int mem_ap_poll(struct target *target) static int mem_ap_halt(struct target *target) { - LOG_DEBUG("%s", __func__); + LOG_TARGET_DEBUG(target, "%s", __func__); target->state = TARGET_HALTED; target->debug_reason = DBG_REASON_DBGRQ; target_call_event_callbacks(target, TARGET_EVENT_HALTED); 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_DEBUG("%s", __func__); + LOG_TARGET_DEBUG(target, "%s", __func__); target->state = TARGET_RUNNING; target->debug_reason = DBG_REASON_NOTHALTED; 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_DEBUG("%s", __func__); + LOG_TARGET_DEBUG(target, "%s", __func__); target->state = TARGET_HALTED; target->debug_reason = DBG_REASON_DBGRQ; target_call_event_callbacks(target, TARGET_EVENT_HALTED); @@ -127,7 +127,7 @@ static int mem_ap_assert_reset(struct target *target) target->state = TARGET_RESET; target->debug_reason = DBG_REASON_UNDEFINED; - LOG_DEBUG("%s", __func__); + LOG_TARGET_DEBUG(target, "%s", __func__); return ERROR_OK; } @@ -139,7 +139,7 @@ static int mem_ap_examine(struct target *target) if (!mem_ap->ap) { mem_ap->ap = dap_get_ap(mem_ap->dap, mem_ap->ap_num); if (!mem_ap->ap) { - LOG_ERROR("Cannot get AP"); + LOG_TARGET_ERROR(target, "Cannot get AP"); return ERROR_FAIL; } } @@ -163,7 +163,7 @@ static int mem_ap_deassert_reset(struct target *target) target->debug_reason = DBG_REASON_NOTHALTED; } - LOG_DEBUG("%s", __func__); + LOG_TARGET_DEBUG(target, "%s", __func__); return ERROR_OK; } @@ -213,7 +213,7 @@ static int mem_ap_get_gdb_reg_list(struct target *target, struct reg **reg_list[ { struct mem_ap_alloc_reg_list *mem_ap_alloc = calloc(1, sizeof(struct mem_ap_alloc_reg_list)); if (!mem_ap_alloc) { - LOG_ERROR("Out of memory"); + LOG_TARGET_ERROR(target, "Out of memory"); return ERROR_FAIL; } @@ -238,7 +238,7 @@ static int mem_ap_read_memory(struct target *target, target_addr_t address, { struct mem_ap *mem_ap = target->arch_info; - LOG_DEBUG("Reading memory at physical address " TARGET_ADDR_FMT + LOG_TARGET_DEBUG(target, "Reading memory at physical address " TARGET_ADDR_FMT "; size %" PRIu32 "; count %" PRIu32, address, size, count); if (count == 0 || !buffer) @@ -253,7 +253,7 @@ static int mem_ap_write_memory(struct target *target, target_addr_t address, { struct mem_ap *mem_ap = target->arch_info; - LOG_DEBUG("Writing memory at physical address " TARGET_ADDR_FMT + LOG_TARGET_DEBUG(target, "Writing memory at physical address " TARGET_ADDR_FMT "; size %" PRIu32 "; count %" PRIu32, address, size, count); if (count == 0 || !buffer) diff --git a/src/target/mips32.c b/src/target/mips32.c index 81faab7..4527c5f 100644 --- a/src/target/mips32.c +++ b/src/target/mips32.c @@ -31,10 +31,10 @@ static const char *mips_isa_strings[] = { /* * GDB registers - * based on gdb-7.6.2/gdb/features/mips-{fpu,cp0,cpu}.xml + * based on gdb-7.6.2/gdb/features/mips-{fpu,cp0,cpu,dsp}.xml */ static const struct { - unsigned id; + unsigned int id; const char *name; enum reg_type type; const char *group; @@ -156,6 +156,22 @@ static const struct { "org.gnu.gdb.mips.cpu", 0 }, { MIPS32_REGLIST_C0_GUESTCTL1_INDEX, "guestCtl1", REG_TYPE_INT, NULL, "org.gnu.gdb.mips.cp0", 0 }, + + { MIPS32_REGLIST_DSP_INDEX + 0, "hi1", REG_TYPE_INT, NULL, + "org.gnu.gdb.mips.dsp", 0 }, + { MIPS32_REGLIST_DSP_INDEX + 1, "lo1", REG_TYPE_INT, NULL, + "org.gnu.gdb.mips.dsp", 0 }, + { MIPS32_REGLIST_DSP_INDEX + 2, "hi2", REG_TYPE_INT, NULL, + "org.gnu.gdb.mips.dsp", 0 }, + { MIPS32_REGLIST_DSP_INDEX + 3, "lo2", REG_TYPE_INT, NULL, + "org.gnu.gdb.mips.dsp", 0 }, + { MIPS32_REGLIST_DSP_INDEX + 4, "hi3", REG_TYPE_INT, NULL, + "org.gnu.gdb.mips.dsp", 0 }, + { MIPS32_REGLIST_DSP_INDEX + 5, "lo3", REG_TYPE_INT, NULL, + "org.gnu.gdb.mips.dsp", 0 }, + + { MIPS32_REGLIST_DSP_DSPCTL_INDEX, "dspctl", REG_TYPE_INT, NULL, + "org.gnu.gdb.mips.dsp", 0 }, }; #define MIPS32_NUM_REGS ARRAY_SIZE(mips32_regs) @@ -211,13 +227,11 @@ static const struct { static const struct { const char *name; } mips32_dsp_regs[MIPS32NUMDSPREGS] = { - { "hi0"}, { "hi1"}, - { "hi2"}, - { "hi3"}, - { "lo0"}, { "lo1"}, + { "hi2"}, { "lo2"}, + { "hi3"}, { "lo3"}, { "control"}, }; @@ -328,7 +342,12 @@ static int mips32_read_core_reg(struct target *target, unsigned int num) if (num >= MIPS32_NUM_REGS) return ERROR_COMMAND_SYNTAX_ERROR; - if (num >= MIPS32_REGLIST_C0_INDEX) { + if (num >= MIPS32_REGLIST_DSP_INDEX) { + /* DSP */ + cnum = num - MIPS32_REGLIST_DSP_INDEX; + reg_value = mips32->core_regs.dsp[cnum]; + buf_set_u32(mips32->core_cache->reg_list[num].value, 0, 32, reg_value); + } else if (num >= MIPS32_REGLIST_C0_INDEX) { /* CP0 */ cnum = num - MIPS32_REGLIST_C0_INDEX; reg_value = mips32->core_regs.cp0[cnum]; @@ -371,7 +390,12 @@ static int mips32_write_core_reg(struct target *target, unsigned int num) if (num >= MIPS32_NUM_REGS) return ERROR_COMMAND_SYNTAX_ERROR; - if (num >= MIPS32_REGLIST_C0_INDEX) { + if (num >= MIPS32_REGLIST_DSP_INDEX) { + /* DSP */ + cnum = num - MIPS32_REGLIST_DSP_INDEX; + reg_value = buf_get_u32(mips32->core_cache->reg_list[num].value, 0, 32); + mips32->core_regs.dsp[cnum] = (uint32_t)reg_value; + } else if (num >= MIPS32_REGLIST_C0_INDEX) { /* CP0 */ cnum = num - MIPS32_REGLIST_C0_INDEX; reg_value = buf_get_u32(mips32->core_cache->reg_list[num].value, 0, 32); @@ -564,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; @@ -1026,10 +1050,20 @@ int mips32_cpu_probe(struct target *target) /* reads dsp implementation info from CP0 Config3 register {DSPP, DSPREV}*/ static void mips32_read_config_dsp(struct mips32_common *mips32, struct mips_ejtag *ejtag_info) { - uint32_t dsp_present = ((ejtag_info->config[3] & MIPS32_CONFIG3_DSPP_MASK) >> MIPS32_CONFIG3_DSPP_SHIFT); + uint32_t retval, status_value, dsp_present; + bool dsp_enabled; + + retval = mips32_cp0_read(ejtag_info, &status_value, MIPS32_C0_STATUS, 0); + if (retval != ERROR_OK) { + LOG_ERROR("Failed to read cp0 status register"); + return; + } + + dsp_present = ((ejtag_info->config[3] & MIPS32_CONFIG3_DSPP_MASK) >> MIPS32_CONFIG3_DSPP_SHIFT); + dsp_enabled = (status_value & BIT(MIPS32_CP0_STATUS_MX_SHIFT)) != 0; if (dsp_present) { mips32->dsp_imp = ((ejtag_info->config[3] & MIPS32_CONFIG3_DSPREV_MASK) >> MIPS32_CONFIG3_DSPREV_SHIFT) + 1; - LOG_USER("DSP implemented: %s, rev %d", "yes", mips32->dsp_imp); + LOG_USER("DSP implemented: rev %d, %s", mips32->dsp_imp, dsp_enabled ? "enabled" : "disabled"); } else { LOG_USER("DSP implemented: %s", "no"); } @@ -1153,7 +1187,7 @@ int mips32_read_config_regs(struct target *target) mips32->isa_imp = MIPS32_MIPS16; LOG_USER("ISA implemented: %s%s", "MIPS32, MIPS16", buf); } else if (ejtag_info->config_regs >= 4) { /* config3 implemented */ - unsigned isa_imp = (ejtag_info->config[3] & MIPS32_CONFIG3_ISA_MASK) >> MIPS32_CONFIG3_ISA_SHIFT; + unsigned int isa_imp = (ejtag_info->config[3] & MIPS32_CONFIG3_ISA_MASK) >> MIPS32_CONFIG3_ISA_SHIFT; if (isa_imp == 1) { mips32->isa_imp = MMIPS32_ONLY; LOG_USER("ISA implemented: %s%s", "microMIPS32", buf); @@ -1747,13 +1781,11 @@ static int mips32_pracc_read_dsp_reg(struct mips_ejtag *ejtag_info, uint32_t *va }; uint32_t dsp_read_code[] = { - MIPS32_MFHI(isa, t0), /* mfhi t0 ($ac0) - OPCODE - 0x00004010 */ MIPS32_DSP_MFHI(t0, 1), /* mfhi t0,$ac1 - OPCODE - 0x00204010 */ - MIPS32_DSP_MFHI(t0, 2), /* mfhi t0,$ac2 - OPCODE - 0x00404010 */ - MIPS32_DSP_MFHI(t0, 3), /* mfhi t0,$ac3 - OPCODE - 0x00604010*/ - MIPS32_MFLO(isa, t0), /* mflo t0 ($ac0) - OPCODE - 0x00004012 */ MIPS32_DSP_MFLO(t0, 1), /* mflo t0,$ac1 - OPCODE - 0x00204012 */ + MIPS32_DSP_MFHI(t0, 2), /* mfhi t0,$ac2 - OPCODE - 0x00404010 */ MIPS32_DSP_MFLO(t0, 2), /* mflo t0,$ac2 - OPCODE - 0x00404012 */ + MIPS32_DSP_MFHI(t0, 3), /* mfhi t0,$ac3 - OPCODE - 0x00604010*/ MIPS32_DSP_MFLO(t0, 3), /* mflo t0,$ac3 - OPCODE - 0x00604012 */ MIPS32_DSP_RDDSP(t0, 0x3F), /* rddsp t0, 0x3f (DSPCtl) - OPCODE - 0x7c3f44b8 */ }; @@ -1824,13 +1856,11 @@ static int mips32_pracc_write_dsp_reg(struct mips_ejtag *ejtag_info, uint32_t va }; uint32_t dsp_write_code[] = { - MIPS32_MTHI(isa, t0), /* mthi t0 ($ac0) - OPCODE - 0x01000011 */ MIPS32_DSP_MTHI(t0, 1), /* mthi t0, $ac1 - OPCODE - 0x01000811 */ - MIPS32_DSP_MTHI(t0, 2), /* mthi t0, $ac2 - OPCODE - 0x01001011 */ - MIPS32_DSP_MTHI(t0, 3), /* mthi t0, $ac3 - OPCODE - 0x01001811 */ - MIPS32_MTLO(isa, t0), /* mtlo t0 ($ac0) - OPCODE - 0x01000013 */ MIPS32_DSP_MTLO(t0, 1), /* mtlo t0, $ac1 - OPCODE - 0x01000813 */ + MIPS32_DSP_MTHI(t0, 2), /* mthi t0, $ac2 - OPCODE - 0x01001011 */ MIPS32_DSP_MTLO(t0, 2), /* mtlo t0, $ac2 - OPCODE - 0x01001013 */ + MIPS32_DSP_MTHI(t0, 3), /* mthi t0, $ac3 - OPCODE - 0x01001811 */ MIPS32_DSP_MTLO(t0, 3), /* mtlo t0, $ac3 - OPCODE - 0x01001813 */ MIPS32_DSP_WRDSP(t0, 0x1F), /* wrdsp t0, 0x1f (DSPCtl) - OPCODE - 0x7d00fcf8*/ }; @@ -2107,15 +2137,18 @@ static int mips32_dsp_find_register_by_name(const char *reg_name) * * @return ERROR_OK on success; error code on failure. */ -static int mips32_dsp_get_all_regs(struct command_invocation *cmd, struct mips_ejtag *ejtag_info) +static int mips32_dsp_get_all_regs(struct command_invocation *cmd, struct mips32_common *mips32) { uint32_t value = 0; + struct mips_ejtag *ejtag_info = &mips32->ejtag_info; for (int i = 0; i < MIPS32NUMDSPREGS; i++) { int retval = mips32_pracc_read_dsp_reg(ejtag_info, &value, i); if (retval != ERROR_OK) { command_print(CMD, "couldn't access reg %s", mips32_dsp_regs[i].name); return retval; } + mips32->core_regs.dsp[i] = value; + mips32->core_cache->reg_list[MIPS32_REGLIST_DSP_INDEX + i].dirty = 1; command_print(CMD, "%*s: 0x%8.8x", 7, mips32_dsp_regs[i].name, value); } return ERROR_OK; @@ -2132,20 +2165,28 @@ static int mips32_dsp_get_all_regs(struct command_invocation *cmd, struct mips_e * * @return ERROR_OK on success; error code on failure. */ -static int mips32_dsp_get_register(struct command_invocation *cmd, struct mips_ejtag *ejtag_info) +static int mips32_dsp_get_register(struct command_invocation *cmd, struct mips32_common *mips32) { uint32_t value = 0; int index = mips32_dsp_find_register_by_name(CMD_ARGV[0]); + struct mips_ejtag *ejtag_info = &mips32->ejtag_info; if (index == MIPS32NUMDSPREGS) { command_print(CMD, "ERROR: register '%s' not found", CMD_ARGV[0]); return ERROR_COMMAND_SYNTAX_ERROR; } int retval = mips32_pracc_read_dsp_reg(ejtag_info, &value, index); - if (retval != ERROR_OK) + if (retval != ERROR_OK) { command_print(CMD, "ERROR: Could not access dsp register %s", CMD_ARGV[0]); - else - command_print(CMD, "0x%8.8x", value); + return retval; + } + + command_print(CMD, "0x%8.8x", value); + + if (mips32->core_regs.dsp[index] != value) { + mips32->core_regs.dsp[index] = value; + mips32->core_cache->reg_list[MIPS32_REGLIST_DSP_INDEX + index].dirty = 1; + } return retval; } @@ -2162,9 +2203,10 @@ static int mips32_dsp_get_register(struct command_invocation *cmd, struct mips_e * * @return ERROR_OK on success; error code on failure. */ -static int mips32_dsp_set_register(struct command_invocation *cmd, struct mips_ejtag *ejtag_info) +static int mips32_dsp_set_register(struct command_invocation *cmd, struct mips32_common *mips32) { uint32_t value; + struct mips_ejtag *ejtag_info = &mips32->ejtag_info; int index = mips32_dsp_find_register_by_name(CMD_ARGV[0]); if (index == MIPS32NUMDSPREGS) { command_print(CMD, "ERROR: register '%s' not found", CMD_ARGV[0]); @@ -2174,8 +2216,13 @@ static int mips32_dsp_set_register(struct command_invocation *cmd, struct mips_e COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], value); int retval = mips32_pracc_write_dsp_reg(ejtag_info, value, index); - if (retval != ERROR_OK) + if (retval != ERROR_OK) { command_print(CMD, "Error: could not write to dsp register %s", CMD_ARGV[0]); + return retval; + } + + mips32->core_regs.dsp[index] = value; + mips32->core_cache->reg_list[MIPS32_REGLIST_DSP_INDEX + index].dirty = 1; return retval; } @@ -2193,7 +2240,6 @@ COMMAND_HANDLER(mips32_handle_dsp_command) int retval, tmp; struct target *target = get_current_target(CMD_CTX); struct mips32_common *mips32 = target_to_mips32(target); - struct mips_ejtag *ejtag_info = &mips32->ejtag_info; retval = mips32_verify_pointer(CMD, mips32); if (retval != ERROR_OK) @@ -2217,10 +2263,10 @@ COMMAND_HANDLER(mips32_handle_dsp_command) switch (CMD_ARGC) { case 0: - retval = mips32_dsp_get_all_regs(CMD, ejtag_info); + retval = mips32_dsp_get_all_regs(CMD, mips32); break; case 1: - retval = mips32_dsp_get_register(CMD, ejtag_info); + retval = mips32_dsp_get_register(CMD, mips32); break; case 2: tmp = *CMD_ARGV[0]; @@ -2228,7 +2274,7 @@ COMMAND_HANDLER(mips32_handle_dsp_command) command_print(CMD, "Error: invalid dsp command format"); retval = ERROR_COMMAND_ARGUMENT_INVALID; } else { - retval = mips32_dsp_set_register(CMD, ejtag_info); + retval = mips32_dsp_set_register(CMD, mips32); } break; default: @@ -2311,7 +2357,7 @@ COMMAND_HANDLER(mips32_handle_scan_delay_command) if (CMD_ARGC == 1) COMMAND_PARSE_NUMBER(uint, CMD_ARGV[0], ejtag_info->scan_delay); else if (CMD_ARGC > 1) - return ERROR_COMMAND_SYNTAX_ERROR; + return ERROR_COMMAND_SYNTAX_ERROR; command_print(CMD, "scan delay: %d nsec", ejtag_info->scan_delay); if (ejtag_info->scan_delay >= MIPS32_SCAN_DELAY_LEGACY_MODE) { diff --git a/src/target/mips32.h b/src/target/mips32.h index a557f31..3d919e7 100644 --- a/src/target/mips32.h +++ b/src/target/mips32.h @@ -69,7 +69,7 @@ #define MIPS32_SCAN_DELAY_LEGACY_MODE 2000000 -#define MIPS32NUMDSPREGS 9 +#define MIPS32NUMDSPREGS 7 /* Bit Mask indicating CP0 register supported by this core */ #define MIPS_CP0_MK4 0x0001 @@ -78,6 +78,7 @@ #define MIPS_CP0_IAPTIV 0x0008 /* CP0 Status register fields */ +#define MIPS32_CP0_STATUS_MX_SHIFT 24 #define MIPS32_CP0_STATUS_FR_SHIFT 26 #define MIPS32_CP0_STATUS_CU1_SHIFT 29 @@ -211,6 +212,7 @@ static const struct mips32_cp0 { enum { MIPS32_PC = 37, MIPS32_FIR = 71, + MIPS32_DSPCTL = 78, MIPS32NUMCOREREGS }; @@ -220,11 +222,13 @@ enum { #define MIPS32_REG_FP_COUNT 32 #define MIPS32_REG_FPC_COUNT 2 #define MIPS32_REG_C0_COUNT 5 +#define MIPS32_REG_DSP_COUNT 7 #define MIPS32_REGLIST_GP_INDEX 0 #define MIPS32_REGLIST_FP_INDEX (MIPS32_REGLIST_GP_INDEX + MIPS32_REG_GP_COUNT) #define MIPS32_REGLIST_FPC_INDEX (MIPS32_REGLIST_FP_INDEX + MIPS32_REG_FP_COUNT) #define MIPS32_REGLIST_C0_INDEX (MIPS32_REGLIST_FPC_INDEX + MIPS32_REG_FPC_COUNT) +#define MIPS32_REGLIST_DSP_INDEX (MIPS32_REGLIST_C0_INDEX + MIPS32_REG_C0_COUNT) #define MIPS32_REGLIST_C0_STATUS_INDEX (MIPS32_REGLIST_C0_INDEX + 0) #define MIPS32_REGLIST_C0_BADVADDR_INDEX (MIPS32_REGLIST_C0_INDEX + 1) @@ -238,6 +242,10 @@ enum { #define MIPS32_REG_C0_PC_INDEX 3 #define MIPS32_REG_C0_GUESTCTL1_INDEX 4 +#define MIPS32_REGLIST_DSP_DSPCTL_INDEX (MIPS32_REGLIST_DSP_INDEX + 6) + +#define MIPS32_REG_DSP_DSPCTL_INDEX 6 + enum mips32_isa_mode { MIPS32_ISA_MIPS32 = 0, MIPS32_ISA_MIPS16E = 1, @@ -377,6 +385,7 @@ struct mips32_core_regs { uint64_t fpr[MIPS32_REG_FP_COUNT]; uint32_t fpcr[MIPS32_REG_FPC_COUNT]; uint32_t cp0[MIPS32_REG_C0_COUNT]; + uint32_t dsp[MIPS32_REG_DSP_COUNT]; }; struct mips32_common { diff --git a/src/target/mips32_pracc.c b/src/target/mips32_pracc.c index aaf3875..ea90d6f 100644 --- a/src/target/mips32_pracc.c +++ b/src/target/mips32_pracc.c @@ -212,7 +212,7 @@ static int mips32_pracc_exec(struct mips_ejtag *ejtag_info, struct pracc_queue_i store_pending--; } else { /* read/fetch access */ - if (!final_check) { /* executing function code */ + if (!final_check) { /* executing function code */ /* check address */ if (ejtag_info->pa_addr != (MIPS32_PRACC_TEXT + code_count * 4)) { LOG_DEBUG("reading at unexpected address %" PRIx32 ", expected %x", @@ -243,7 +243,7 @@ static int mips32_pracc_exec(struct mips_ejtag *ejtag_info, struct pracc_queue_i if (code_count == ctx->code_count) /* last instruction, start final check */ final_check = 1; - } else { /* final check after function code shifted out */ + } else { /* final check after function code shifted out */ /* check address */ if (ejtag_info->pa_addr == MIPS32_PRACC_TEXT) { if (!pass) { /* first pass through pracc text */ @@ -275,7 +275,7 @@ static int mips32_pracc_exec(struct mips_ejtag *ejtag_info, struct pracc_queue_i } instr = MIPS32_NOP; /* shift out NOPs instructions */ code_count++; - } + } /* Send instruction out */ mips_ejtag_set_instr(ejtag_info, EJTAG_INST_DATA); @@ -370,7 +370,7 @@ int mips32_pracc_queue_exec(struct mips_ejtag *ejtag_info, struct pracc_queue_in return ERROR_FAIL; } - unsigned num_clocks = + unsigned int num_clocks = ((uint64_t)(ejtag_info->scan_delay) * adapter_get_speed_khz() + 500000) / 1000000; uint32_t ejtag_ctrl = ejtag_info->ejtag_ctrl & ~EJTAG_CTRL_PRACC; @@ -400,7 +400,7 @@ int mips32_pracc_queue_exec(struct mips_ejtag *ejtag_info, struct pracc_queue_in ejtag_ctrl = buf_get_u32(scan_in[scan_count].scan_32.ctrl, 0, 32); uint32_t addr = buf_get_u32(scan_in[scan_count].scan_32.addr, 0, 32); if (!(ejtag_ctrl & EJTAG_CTRL_PRACC)) { - LOG_ERROR("Error: access not pending count: %d", scan_count); + LOG_ERROR("Access not pending, count: %d", scan_count); retval = ERROR_FAIL; goto exit; } @@ -878,6 +878,7 @@ int mips32_pracc_write_regs(struct mips32_common *mips32) uint32_t *c0rs = mips32->core_regs.cp0; bool fpu_in_64bit = ((c0rs[0] & BIT(MIPS32_CP0_STATUS_FR_SHIFT)) != 0); bool fp_enabled = ((c0rs[0] & BIT(MIPS32_CP0_STATUS_CU1_SHIFT)) != 0); + bool dsp_enabled = ((c0rs[0] & BIT(MIPS32_CP0_STATUS_MX_SHIFT)) != 0); uint32_t rel = (ejtag_info->config[0] & MIPS32_CONFIG0_AR_MASK) >> MIPS32_CONFIG0_AR_SHIFT; pracc_queue_init(&ctx); @@ -943,6 +944,34 @@ int mips32_pracc_write_regs(struct mips32_common *mips32) pracc_add(&ctx, 0, MIPS32_EHB(ctx.isa)); } + /* Store DSP Accumulators */ + if (mips32->dsp_imp && dsp_enabled) { + /* Struct of mips32_dsp_regs: {ac{hi, lo}1-3, dspctl} */ + uint32_t *dspr = mips32->core_regs.dsp; + size_t dsp_regs = ARRAY_SIZE(mips32->core_regs.dsp); + + /* Starts from ac1, core_regs.dsp contains dspctl register, therefore - 1 */ + for (size_t index = 0; index != ((dsp_regs - 1) / 2); index++) { + /* Every accumulator have 2 registers, hi and lo, and core_regs.dsp stores ac[1~3] */ + /* reads hi[ac] from core_regs array */ + pracc_add_li32(&ctx, 2, dspr[index * 2], 0); + /* reads lo[ac] from core_regs array */ + pracc_add_li32(&ctx, 3, dspr[(index * 2) + 1], 0); + + /* Write to accumulator 1~3 and index starts from 0, therefore ac = index + 1 */ + size_t ac = index + 1; + pracc_add(&ctx, 0, MIPS32_DSP_MTHI(2, ac)); + pracc_add(&ctx, 0, MIPS32_DSP_MTLO(3, ac)); + } + + /* DSPCTL is the last element of register store */ + pracc_add_li32(&ctx, 2, dspr[6], 0); + pracc_add(&ctx, 0, MIPS32_DSP_WRDSP(2, 0x1F)); + + if (rel > MIPS32_RELEASE_1) + pracc_add(&ctx, 0, MIPS32_EHB(ctx.isa)); + } + /* load registers 2 to 31 with li32, optimize */ for (int i = 2; i < 32; i++) pracc_add_li32(&ctx, i, gprs[i], 1); @@ -1064,14 +1093,16 @@ int mips32_pracc_read_regs(struct mips32_common *mips32) unsigned int offset_cp0 = ((uint8_t *)&core_regs->cp0[0]) - (uint8_t *)core_regs; unsigned int offset_fpr = ((uint8_t *)&core_regs->fpr[0]) - (uint8_t *)core_regs; unsigned int offset_fpcr = ((uint8_t *)&core_regs->fpcr[0]) - (uint8_t *)core_regs; - bool fp_enabled; + unsigned int offset_dsp = ((uint8_t *)&core_regs->dsp[0]) - (uint8_t *)core_regs; + bool fp_enabled, dsp_enabled; /* - * This procedure has to be in 2 distinctive steps, because we can - * only know whether FP is enabled after reading CP0. + * This procedure has to be in 3 distinctive steps, because we can + * only know whether FP and DSP are enabled after reading CP0. * - * Step 1: Read everything except CP1 stuff + * Step 1: Read everything except CP1 and DSP stuff * Step 2: Read CP1 stuff if FP is implemented + * Step 3: Read DSP registers if dsp is implemented */ pracc_queue_init(&ctx); @@ -1149,6 +1180,50 @@ int mips32_pracc_read_regs(struct mips32_common *mips32) pracc_queue_free(&ctx); } + + dsp_enabled = (mips32->core_regs.cp0[MIPS32_REG_C0_STATUS_INDEX] & BIT(MIPS32_CP0_STATUS_MX_SHIFT)) != 0; + if (mips32->dsp_imp && dsp_enabled) { + pracc_queue_init(&ctx); + + mips32_pracc_store_regs_set_base_addr(&ctx); + + /* Struct of mips32_dsp_regs[7]: {ac{hi, lo}1-3, dspctl} */ + size_t dsp_regs = ARRAY_SIZE(mips32->core_regs.dsp); + /* Starts from ac1, core_regs.dsp have dspctl register, therefore - 1 */ + for (size_t index = 0; index != ((dsp_regs - 1) / 2); index++) { + /* Every accumulator have 2 registers, hi&lo, and core_regs.dsp stores ac[1~3] */ + /* Reads offset of hi[ac] from core_regs array */ + size_t offset_hi = offset_dsp + ((index * 2) * sizeof(uint32_t)); + /* Reads offset of lo[ac] from core_regs array */ + size_t offset_lo = offset_dsp + (((index * 2) + 1) * sizeof(uint32_t)); + + /* DSP Ac registers starts from 1 and index starts from 0, therefore ac = index + 1 */ + size_t ac = index + 1; + pracc_add(&ctx, 0, MIPS32_DSP_MFHI(8, ac)); + pracc_add(&ctx, MIPS32_PRACC_PARAM_OUT + offset_hi, + MIPS32_SW(ctx.isa, 8, PRACC_OUT_OFFSET + offset_hi, 1)); + pracc_add(&ctx, 0, MIPS32_DSP_MFLO(8, ac)); + pracc_add(&ctx, MIPS32_PRACC_PARAM_OUT + offset_lo, + MIPS32_SW(ctx.isa, 8, PRACC_OUT_OFFSET + offset_lo, 1)); + } + + /* DSPCTL is the last element of register store */ + pracc_add(&ctx, 0, MIPS32_DSP_RDDSP(8, 0x3F)); + pracc_add(&ctx, MIPS32_PRACC_PARAM_OUT + offset_dsp + ((dsp_regs - 1) * sizeof(uint32_t)), + MIPS32_SW(ctx.isa, 8, + PRACC_OUT_OFFSET + offset_dsp + ((dsp_regs - 1) * sizeof(uint32_t)), 1)); + + mips32_pracc_store_regs_restore(&ctx); + + /* jump to start */ + pracc_add(&ctx, 0, MIPS32_B(ctx.isa, NEG16((ctx.code_count + 1) << ctx.isa))); + /* load $15 in DeSave */ + pracc_add(&ctx, 0, MIPS32_MTC0(ctx.isa, 15, 31, 0)); + + ctx.retval = mips32_pracc_queue_exec(ejtag_info, &ctx, (uint32_t *)&mips32->core_regs, 1); + + pracc_queue_free(&ctx); + } return ctx.retval; } @@ -1287,7 +1362,7 @@ int mips32_pracc_fastdata_xfer(struct mips_ejtag *ejtag_info, struct working_are pracc_swap16_array(ejtag_info, jmp_code, ARRAY_SIZE(jmp_code)); /* execute jump code, with no address check */ - for (unsigned i = 0; i < ARRAY_SIZE(jmp_code); i++) { + for (unsigned int i = 0; i < ARRAY_SIZE(jmp_code); i++) { int retval = wait_for_pracc_rw(ejtag_info); if (retval != ERROR_OK) return retval; @@ -1322,7 +1397,7 @@ int mips32_pracc_fastdata_xfer(struct mips_ejtag *ejtag_info, struct working_are mips_ejtag_set_instr(ejtag_info, EJTAG_INST_FASTDATA); mips_ejtag_fastdata_scan(ejtag_info, 1, &val); - unsigned num_clocks = 0; /* like in legacy code */ + unsigned int num_clocks = 0; /* like in legacy code */ if (ejtag_info->mode != 0) num_clocks = ((uint64_t)(ejtag_info->scan_delay) * adapter_get_speed_khz() + 500000) / 1000000; diff --git a/src/target/mips32_pracc.h b/src/target/mips32_pracc.h index f78f891..a0244a6 100644 --- a/src/target/mips32_pracc.h +++ b/src/target/mips32_pracc.h @@ -45,7 +45,7 @@ struct pa_list { struct pracc_queue_info { struct mips_ejtag *ejtag_info; - unsigned isa; + unsigned int isa; int retval; int code_count; int store_count; diff --git a/src/target/mips64.c b/src/target/mips64.c index 48f4563..3d193a3 100644 --- a/src/target/mips64.c +++ b/src/target/mips64.c @@ -21,7 +21,7 @@ #include "mips64.h" static const struct { - unsigned id; + unsigned int id; const char *name; enum reg_type type; const char *group; @@ -332,8 +332,8 @@ int mips64_save_context(struct target *target) if (retval != ERROR_OK) return retval; - for (unsigned i = 0; i < MIPS64_NUM_REGS; i++) - retval = mips64->read_core_reg(target, i); + for (unsigned int i = 0; i < MIPS64_NUM_REGS; i++) + retval = mips64->read_core_reg(target, i); return retval; } @@ -343,7 +343,7 @@ int mips64_restore_context(struct target *target) struct mips64_common *mips64 = target->arch_info; struct mips_ejtag *ejtag_info = &mips64->ejtag_info; - for (unsigned i = 0; i < MIPS64_NUM_REGS; i++) { + for (unsigned int i = 0; i < MIPS64_NUM_REGS; i++) { if (mips64->core_cache->reg_list[i].dirty) mips64->write_core_reg(target, i); } @@ -379,7 +379,7 @@ int mips64_build_reg_cache(struct target *target) struct reg_cache **cache_p, *cache; struct mips64_core_reg *arch_info = NULL; struct reg *reg_list = NULL; - unsigned i; + unsigned int i; cache = calloc(1, sizeof(*cache)); if (!cache) { diff --git a/src/target/mips64_pracc.c b/src/target/mips64_pracc.c index b083f5c..11783fe 100644 --- a/src/target/mips64_pracc.c +++ b/src/target/mips64_pracc.c @@ -27,13 +27,13 @@ struct mips64_pracc_context { uint64_t *local_iparam; - unsigned num_iparam; + unsigned int num_iparam; uint64_t *local_oparam; - unsigned num_oparam; + unsigned int num_oparam; const uint32_t *code; - unsigned code_len; + unsigned int code_len; uint64_t stack[STACK_DEPTH]; - unsigned stack_offset; + unsigned int stack_offset; struct mips_ejtag *ejtag_info; }; @@ -65,7 +65,7 @@ static int wait_for_pracc_rw(struct mips_ejtag *ejtag_info, uint32_t *ctrl) static int mips64_pracc_exec_read(struct mips64_pracc_context *ctx, uint64_t address) { struct mips_ejtag *ejtag_info = ctx->ejtag_info; - unsigned offset; + unsigned int offset; uint32_t ejtag_ctrl; uint64_t data; int rc; @@ -76,12 +76,12 @@ static int mips64_pracc_exec_read(struct mips64_pracc_context *ctx, uint64_t add offset = (address - MIPS64_PRACC_PARAM_IN) / MIPS64_PRACC_DATA_STEP; if (offset >= MIPS64_PRACC_PARAM_IN_SIZE) { - LOG_ERROR("Error: iparam size exceeds MIPS64_PRACC_PARAM_IN_SIZE"); + LOG_ERROR("iparam size exceeds MIPS64_PRACC_PARAM_IN_SIZE"); return ERROR_JTAG_DEVICE_ERROR; } if (!ctx->local_iparam) { - LOG_ERROR("Error: unexpected reading of input parameter"); + LOG_ERROR("unexpected reading of input parameter"); return ERROR_JTAG_DEVICE_ERROR; } @@ -93,7 +93,7 @@ static int mips64_pracc_exec_read(struct mips64_pracc_context *ctx, uint64_t add offset = (address - MIPS64_PRACC_PARAM_OUT) / MIPS64_PRACC_DATA_STEP; if (!ctx->local_oparam) { - LOG_ERROR("Error: unexpected reading of output parameter"); + LOG_ERROR("unexpected reading of output parameter"); return ERROR_JTAG_DEVICE_ERROR; } @@ -154,7 +154,7 @@ static int mips64_pracc_exec_write(struct mips64_pracc_context *ctx, uint64_t ad { uint32_t ejtag_ctrl; uint64_t data; - unsigned offset; + unsigned int offset; struct mips_ejtag *ejtag_info = ctx->ejtag_info; int rc; @@ -181,7 +181,7 @@ static int mips64_pracc_exec_write(struct mips64_pracc_context *ctx, uint64_t ad && (address < MIPS64_PRACC_PARAM_IN + ctx->num_iparam * MIPS64_PRACC_DATA_STEP)) { offset = (address - MIPS64_PRACC_PARAM_IN) / MIPS64_PRACC_DATA_STEP; if (!ctx->local_iparam) { - LOG_ERROR("Error: unexpected writing of input parameter"); + LOG_ERROR("unexpected writing of input parameter"); return ERROR_JTAG_DEVICE_ERROR; } ctx->local_iparam[offset] = data; @@ -189,14 +189,14 @@ static int mips64_pracc_exec_write(struct mips64_pracc_context *ctx, uint64_t ad && (address < MIPS64_PRACC_PARAM_OUT + ctx->num_oparam * MIPS64_PRACC_DATA_STEP)) { offset = (address - MIPS64_PRACC_PARAM_OUT) / MIPS64_PRACC_DATA_STEP; if (!ctx->local_oparam) { - LOG_ERROR("Error: unexpected writing of output parameter"); + LOG_ERROR("unexpected writing of output parameter"); return ERROR_JTAG_DEVICE_ERROR; } ctx->local_oparam[offset] = data; } else if (address == MIPS64_PRACC_STACK) { /* save data onto our stack */ if (ctx->stack_offset >= STACK_DEPTH) { - LOG_ERROR("Error: PrAcc stack depth exceeded"); + LOG_ERROR("PrAcc stack depth exceeded"); return ERROR_FAIL; } ctx->stack[ctx->stack_offset++] = data; @@ -209,9 +209,9 @@ static int mips64_pracc_exec_write(struct mips64_pracc_context *ctx, uint64_t ad } int mips64_pracc_exec(struct mips_ejtag *ejtag_info, - unsigned code_len, const uint32_t *code, - unsigned num_param_in, uint64_t *param_in, - unsigned num_param_out, uint64_t *param_out) + unsigned int code_len, const uint32_t *code, + unsigned int num_param_in, uint64_t *param_in, + unsigned int num_param_out, uint64_t *param_out) { uint32_t ejtag_ctrl; uint64_t address = 0, address_prev = 0; @@ -219,7 +219,7 @@ int mips64_pracc_exec(struct mips_ejtag *ejtag_info, int retval; int pass = 0; bool first_time_call = true; - unsigned i; + unsigned int i; for (i = 0; i < code_len; i++) LOG_DEBUG("%08" PRIx32, code[i]); @@ -354,11 +354,11 @@ static int mips64_pracc_read_u64(struct mips_ejtag *ejtag_info, uint64_t addr, } static int mips64_pracc_read_mem64(struct mips_ejtag *ejtag_info, uint64_t addr, - unsigned count, uint64_t *buf) + unsigned int count, uint64_t *buf) { int retval = ERROR_OK; - for (unsigned i = 0; i < count; i++) { + for (unsigned int i = 0; i < count; i++) { retval = mips64_pracc_read_u64(ejtag_info, addr + 8*i, &buf[i]); if (retval != ERROR_OK) return retval; @@ -414,11 +414,11 @@ static int mips64_pracc_read_u32(struct mips_ejtag *ejtag_info, uint64_t addr, } static int mips64_pracc_read_mem32(struct mips_ejtag *ejtag_info, uint64_t addr, - unsigned count, uint32_t *buf) + unsigned int count, uint32_t *buf) { int retval = ERROR_OK; - for (unsigned i = 0; i < count; i++) { + for (unsigned int i = 0; i < count; i++) { retval = mips64_pracc_read_u32(ejtag_info, addr + 4 * i, &buf[i]); if (retval != ERROR_OK) return retval; @@ -474,11 +474,11 @@ static int mips64_pracc_read_u16(struct mips_ejtag *ejtag_info, uint64_t addr, } static int mips64_pracc_read_mem16(struct mips_ejtag *ejtag_info, uint64_t addr, - unsigned count, uint16_t *buf) + unsigned int count, uint16_t *buf) { int retval = ERROR_OK; - for (unsigned i = 0; i < count; i++) { + for (unsigned int i = 0; i < count; i++) { retval = mips64_pracc_read_u16(ejtag_info, addr + 2*i, &buf[i]); if (retval != ERROR_OK) return retval; @@ -534,11 +534,11 @@ static int mips64_pracc_read_u8(struct mips_ejtag *ejtag_info, uint64_t addr, } static int mips64_pracc_read_mem8(struct mips_ejtag *ejtag_info, uint64_t addr, - unsigned count, uint8_t *buf) + unsigned int count, uint8_t *buf) { int retval = ERROR_OK; - for (unsigned i = 0; i < count; i++) { + for (unsigned int i = 0; i < count; i++) { retval = mips64_pracc_read_u8(ejtag_info, addr + i, &buf[i]); if (retval != ERROR_OK) return retval; @@ -547,7 +547,7 @@ static int mips64_pracc_read_mem8(struct mips_ejtag *ejtag_info, uint64_t addr, } int mips64_pracc_read_mem(struct mips_ejtag *ejtag_info, uint64_t addr, - unsigned size, unsigned count, void *buf) + unsigned int size, unsigned int count, void *buf) { switch (size) { case 1: @@ -612,11 +612,11 @@ static int mips64_pracc_write_u64(struct mips_ejtag *ejtag_info, uint64_t addr, } static int mips64_pracc_write_mem64(struct mips_ejtag *ejtag_info, - uint64_t addr, unsigned count, uint64_t *buf) + uint64_t addr, unsigned int count, uint64_t *buf) { int retval = ERROR_OK; - for (unsigned i = 0; i < count; i++) { + for (unsigned int i = 0; i < count; i++) { retval = mips64_pracc_write_u64(ejtag_info, addr + 8 * i, &buf[i]); if (retval != ERROR_OK) return retval; @@ -674,11 +674,11 @@ static int mips64_pracc_write_u32(struct mips_ejtag *ejtag_info, uint64_t addr, } static int mips64_pracc_write_mem32(struct mips_ejtag *ejtag_info, uint64_t addr, - unsigned count, uint32_t *buf) + unsigned int count, uint32_t *buf) { int retval = ERROR_OK; - for (unsigned i = 0; i < count; i++) { + for (unsigned int i = 0; i < count; i++) { retval = mips64_pracc_write_u32(ejtag_info, addr + 4 * i, &buf[i]); if (retval != ERROR_OK) return retval; @@ -734,11 +734,11 @@ static int mips64_pracc_write_u16(struct mips_ejtag *ejtag_info, uint64_t addr, } static int mips64_pracc_write_mem16(struct mips_ejtag *ejtag_info, - uint64_t addr, unsigned count, uint16_t *buf) + uint64_t addr, unsigned int count, uint16_t *buf) { int retval = ERROR_OK; - for (unsigned i = 0; i < count; i++) { + for (unsigned int i = 0; i < count; i++) { retval = mips64_pracc_write_u16(ejtag_info, addr + 2 * i, &buf[i]); if (retval != ERROR_OK) return retval; @@ -795,11 +795,11 @@ static int mips64_pracc_write_u8(struct mips_ejtag *ejtag_info, uint64_t addr, } static int mips64_pracc_write_mem8(struct mips_ejtag *ejtag_info, - uint64_t addr, unsigned count, uint8_t *buf) + uint64_t addr, unsigned int count, uint8_t *buf) { int retval = ERROR_OK; - for (unsigned i = 0; i < count; i++) { + for (unsigned int i = 0; i < count; i++) { retval = mips64_pracc_write_u8(ejtag_info, addr + i, &buf[i]); if (retval != ERROR_OK) return retval; @@ -808,8 +808,8 @@ static int mips64_pracc_write_mem8(struct mips_ejtag *ejtag_info, } int mips64_pracc_write_mem(struct mips_ejtag *ejtag_info, - uint64_t addr, unsigned size, - unsigned count, void *buf) + uint64_t addr, unsigned int size, + unsigned int count, void *buf) { switch (size) { case 1: @@ -1270,7 +1270,7 @@ int mips64_pracc_read_regs(struct mips_ejtag *ejtag_info, uint64_t *regs) int mips64_pracc_fastdata_xfer(struct mips_ejtag *ejtag_info, struct working_area *source, bool write_t, uint64_t addr, - unsigned count, uint64_t *buf) + unsigned int count, uint64_t *buf) { uint32_t handler_code[] = { /* caution when editing, table is modified below */ @@ -1321,7 +1321,7 @@ int mips64_pracc_fastdata_xfer(struct mips_ejtag *ejtag_info, }; int retval; - unsigned i; + unsigned int i; uint32_t ejtag_ctrl, address32; uint64_t address, val; @@ -1385,7 +1385,7 @@ int mips64_pracc_fastdata_xfer(struct mips_ejtag *ejtag_info, mips64_ejtag_fastdata_scan(ejtag_info, 1, &val); /* like in legacy code */ - unsigned num_clocks = 0; + unsigned int num_clocks = 0; if (ejtag_info->mode != 0) num_clocks = ((uint64_t)(ejtag_info->scan_delay) * adapter_get_speed_khz() + 500000) / 1000000; LOG_DEBUG("num_clocks=%d", num_clocks); diff --git a/src/target/mips64_pracc.h b/src/target/mips64_pracc.h index 19d1519..2bdc856 100644 --- a/src/target/mips64_pracc.h +++ b/src/target/mips64_pracc.h @@ -40,20 +40,22 @@ #define MIPS64_PRACC_ADDR_STEP 4 #define MIPS64_PRACC_DATA_STEP 8 -int mips64_pracc_read_mem(struct mips_ejtag *ejtag_info, uint64_t addr, unsigned size, unsigned count, void *buf); -int mips64_pracc_write_mem(struct mips_ejtag *ejtag_info, uint64_t addr, unsigned size, unsigned count, void *buf); +int mips64_pracc_read_mem(struct mips_ejtag *ejtag_info, uint64_t addr, unsigned int size, + unsigned int count, void *buf); +int mips64_pracc_write_mem(struct mips_ejtag *ejtag_info, uint64_t addr, unsigned int size, + unsigned int count, void *buf); int mips64_pracc_read_regs(struct mips_ejtag *ejtag_info, uint64_t *regs); int mips64_pracc_write_regs(struct mips_ejtag *ejtag_info, uint64_t *regs); int mips64_pracc_exec(struct mips_ejtag *ejtag_info, - unsigned code_len, const uint32_t *code, - unsigned num_param_in, uint64_t *param_in, - unsigned num_param_out, uint64_t *param_out); + unsigned int code_len, const uint32_t *code, + unsigned int num_param_in, uint64_t *param_in, + unsigned int num_param_out, uint64_t *param_out); int mips64_pracc_fastdata_xfer(struct mips_ejtag *ejtag_info, struct working_area *source, bool write_t, uint64_t addr, - unsigned count, uint64_t *buf); + unsigned int count, uint64_t *buf); #endif /* OPENOCD_TARGET_MIPS64_PRACC_H */ diff --git a/src/target/mips_ejtag.c b/src/target/mips_ejtag.c index 389461c..2ff4aa9 100644 --- a/src/target/mips_ejtag.c +++ b/src/target/mips_ejtag.c @@ -493,7 +493,7 @@ int mips64_ejtag_config_step(struct mips_ejtag *ejtag_info, bool enable_step) MIPS64_NOP, }; const uint32_t *code = enable_step ? code_enable : code_disable; - unsigned code_len = enable_step ? ARRAY_SIZE(code_enable) : + unsigned int code_len = enable_step ? ARRAY_SIZE(code_enable) : ARRAY_SIZE(code_disable); return mips64_pracc_exec(ejtag_info, diff --git a/src/target/mips_ejtag.h b/src/target/mips_ejtag.h index 7376e51..30a4690 100644 --- a/src/target/mips_ejtag.h +++ b/src/target/mips_ejtag.h @@ -214,7 +214,7 @@ struct mips_ejtag { uint32_t reg8; uint32_t reg9; - unsigned scan_delay; + unsigned int scan_delay; int mode; uint32_t pa_ctrl; uint32_t pa_addr; diff --git a/src/target/mips_m4k.c b/src/target/mips_m4k.c index ad98089..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); @@ -1397,7 +1399,7 @@ COMMAND_HANDLER(mips_m4k_handle_scan_delay_command) if (CMD_ARGC == 1) COMMAND_PARSE_NUMBER(uint, CMD_ARGV[0], ejtag_info->scan_delay); else if (CMD_ARGC > 1) - return ERROR_COMMAND_SYNTAX_ERROR; + return ERROR_COMMAND_SYNTAX_ERROR; command_print(CMD, "scan delay: %d nsec", ejtag_info->scan_delay); if (ejtag_info->scan_delay >= MIPS32_SCAN_DELAY_LEGACY_MODE) { 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 8c38610..4b9d3bc 100644 --- a/src/target/openrisc/or1k.c +++ b/src/target/openrisc/or1k.c @@ -27,8 +27,8 @@ #include "or1k.h" #include "or1k_du.h" -LIST_HEAD(tap_list); -LIST_HEAD(du_list); +OOCD_LIST_HEAD(tap_list); +OOCD_LIST_HEAD(du_list); static int or1k_remove_breakpoint(struct target *target, struct breakpoint *breakpoint); @@ -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/openrisc/or1k_du_adv.c b/src/target/openrisc/or1k_du_adv.c index e4003a2..f401ea9 100644 --- a/src/target/openrisc/or1k_du_adv.c +++ b/src/target/openrisc/or1k_du_adv.c @@ -362,7 +362,7 @@ static int adbg_ctrl_read(struct or1k_jtag *jtag_info, uint32_t regidx, default: LOG_ERROR("Illegal debug chain selected (%i) while doing control read", jtag_info->or1k_jtag_module_selected); - return ERROR_FAIL; + return ERROR_FAIL; } /* Zero MSB = op for module, not top-level debug unit */ 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/register.h b/src/target/register.h index 1e4f2e0..b9af401 100644 --- a/src/target/register.h +++ b/src/target/register.h @@ -145,7 +145,7 @@ struct reg_cache { const char *name; struct reg_cache *next; struct reg *reg_list; - unsigned num_regs; + unsigned int num_regs; }; struct reg_arch_type { diff --git a/src/target/riscv/Makefile.am b/src/target/riscv/Makefile.am index aa82f58..189edb3 100644 --- a/src/target/riscv/Makefile.am +++ b/src/target/riscv/Makefile.am @@ -2,15 +2,17 @@ noinst_LTLIBRARIES += %D%/libriscv.la %C%_libriscv_la_SOURCES = \ - %D%/asm.h \ %D%/batch.h \ %D%/debug_defines.h \ %D%/debug_reg_printer.h \ %D%/encoding.h \ + %D%/field_helpers.h \ %D%/gdb_regs.h \ %D%/opcodes.h \ %D%/program.h \ %D%/riscv.h \ + %D%/riscv_reg_impl.h \ + %D%/riscv_reg.h \ %D%/riscv-011.h \ %D%/riscv-011_reg.h \ %D%/riscv-013.h \ @@ -26,3 +28,5 @@ noinst_LTLIBRARIES += %D%/libriscv.la %D%/riscv_semihosting.c \ %D%/debug_defines.c \ %D%/debug_reg_printer.c + +STARTUP_TCL_SRCS += %D%/startup.tcl diff --git a/src/target/riscv/asm.h b/src/target/riscv/asm.h deleted file mode 100644 index 6ceb8c9..0000000 --- a/src/target/riscv/asm.h +++ /dev/null @@ -1,40 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ - -#ifndef TARGET__RISCV__ASM_H -#define TARGET__RISCV__ASM_H - -#include "riscv.h" - -/*** Version-independent functions that we don't want in the main address space. ***/ - -static uint32_t load(const struct target *target, unsigned int rd, - unsigned int base, uint16_t offset) __attribute__ ((unused)); -static uint32_t load(const struct target *target, unsigned int rd, - unsigned int base, uint16_t offset) -{ - switch (riscv_xlen(target)) { - case 32: - return lw(rd, base, offset); - case 64: - return ld(rd, base, offset); - } - assert(0); - return 0; /* Silence -Werror=return-type */ -} - -static uint32_t store(const struct target *target, unsigned int src, - unsigned int base, uint16_t offset) __attribute__ ((unused)); -static uint32_t store(const struct target *target, unsigned int src, - unsigned int base, uint16_t offset) -{ - switch (riscv_xlen(target)) { - case 32: - return sw(src, base, offset); - case 64: - return sd(src, base, offset); - } - assert(0); - return 0; /* Silence -Werror=return-type */ -} - -#endif diff --git a/src/target/riscv/batch.c b/src/target/riscv/batch.c index bb1070a..ec68b37 100644 --- a/src/target/riscv/batch.c +++ b/src/target/riscv/batch.c @@ -6,16 +6,28 @@ #include "batch.h" #include "debug_defines.h" +#include "debug_reg_printer.h" #include "riscv.h" #include "field_helpers.h" +// TODO: DTM_DMI_MAX_ADDRESS_LENGTH should be reduced to 32 (per the debug spec) #define DTM_DMI_MAX_ADDRESS_LENGTH ((1<<DTM_DTMCS_ABITS_LENGTH)-1) #define DMI_SCAN_MAX_BIT_LENGTH (DTM_DMI_MAX_ADDRESS_LENGTH + DTM_DMI_DATA_LENGTH + DTM_DMI_OP_LENGTH) + #define DMI_SCAN_BUF_SIZE (DIV_ROUND_UP(DMI_SCAN_MAX_BIT_LENGTH, 8)) /* Reserve extra room in the batch (needed for the last NOP operation) */ #define BATCH_RESERVED_SCANS 1 +static unsigned int get_dmi_scan_length(const struct target *target) +{ + const unsigned int abits = riscv_get_dmi_address_bits(target); + assert(abits > 0); + assert(abits <= DTM_DMI_MAX_ADDRESS_LENGTH); + + return abits + DTM_DMI_DATA_LENGTH + DTM_DMI_OP_LENGTH; +} + struct riscv_batch *riscv_batch_alloc(struct target *target, size_t scans) { scans += BATCH_RESERVED_SCANS; @@ -126,20 +138,141 @@ static void add_idle_before_batch(const struct riscv_batch *batch, size_t start_ const unsigned int idle_change = new_delay - batch->last_scan_delay; LOG_TARGET_DEBUG(batch->target, "Adding %u idle cycles before the batch.", idle_change); - assert(idle_change <= INT_MAX); jtag_add_runtest(idle_change, TAP_IDLE); } -static int get_delay(const struct riscv_batch *batch, size_t scan_idx, - const struct riscv_scan_delays *delays) +static unsigned int get_delay(const struct riscv_batch *batch, size_t scan_idx, + const struct riscv_scan_delays *delays, bool resets_delays, + size_t reset_delays_after) { assert(batch); assert(scan_idx < batch->used_scans); + const bool delays_were_reset = resets_delays + && (scan_idx >= reset_delays_after); const enum riscv_scan_delay_class delay_class = batch->delay_classes[scan_idx]; const unsigned int delay = riscv_scan_get_delay(delays, delay_class); - assert(delay <= INT_MAX); - return delay; + return delays_were_reset ? 0 : delay; +} + +static unsigned int decode_dmi(const struct riscv_batch *batch, char *text, + uint32_t address, uint32_t data) +{ + static const struct { + uint32_t address; + enum riscv_debug_reg_ordinal ordinal; + } description[] = { + {DM_DMCONTROL, DM_DMCONTROL_ORDINAL}, + {DM_DMSTATUS, DM_DMSTATUS_ORDINAL}, + {DM_ABSTRACTCS, DM_ABSTRACTCS_ORDINAL}, + {DM_COMMAND, DM_COMMAND_ORDINAL}, + {DM_SBCS, DM_SBCS_ORDINAL} + }; + + for (unsigned int i = 0; i < ARRAY_SIZE(description); i++) { + if (riscv_get_dmi_address(batch->target, description[i].address) + == address) { + const riscv_debug_reg_ctx_t context = { + .XLEN = { .value = 0, .is_set = false }, + .DXLEN = { .value = 0, .is_set = false }, + .abits = { .value = 0, .is_set = false }, + }; + return riscv_debug_reg_to_s(text, description[i].ordinal, + context, data, RISCV_DEBUG_REG_HIDE_ALL_0); + } + } + if (text) + text[0] = '\0'; + return 0; +} + +static void log_dmi_decoded(const struct riscv_batch *batch, bool write, + uint32_t address, uint32_t data) +{ + const size_t size = decode_dmi(batch, /* text */ NULL, address, data) + 1; + char * const decoded = malloc(size); + if (!decoded) { + LOG_ERROR("Not enough memory to allocate %zu bytes.", size); + return; + } + decode_dmi(batch, decoded, address, data); + LOG_DEBUG("%s: %s", write ? "write" : "read", decoded); + free(decoded); +} + +static void log_batch(const struct riscv_batch *batch, size_t start_idx, + const struct riscv_scan_delays *delays, bool resets_delays, + size_t reset_delays_after) +{ + if (debug_level < LOG_LVL_DEBUG) + return; + + const unsigned int abits = riscv_get_dmi_address_bits(batch->target); + + /* Determine the "op" and "address" of the scan that preceded the first + * executed scan. + * FIXME: The code here assumes that there were no DMI operations between + * the last execution of the batch and the current one. + * Caching the info about the last executed DMI scan in "dm013_info_t" + * would be a more robust solution. + */ + bool last_scan_was_read = false; + uint32_t last_scan_address = (uint32_t)(-1) /* to silence maybe-uninitialized */; + if (start_idx > 0) { + const struct scan_field * const field = &batch->fields[start_idx - 1]; + assert(field->out_value); + last_scan_was_read = buf_get_u32(field->out_value, DTM_DMI_OP_OFFSET, + DTM_DMI_OP_LENGTH) == DTM_DMI_OP_READ; + last_scan_address = buf_get_u32(field->out_value, + DTM_DMI_ADDRESS_OFFSET, abits); + } + + /* Decode and log every executed scan */ + for (size_t i = start_idx; i < batch->used_scans; ++i) { + static const char * const op_string[] = {"-", "r", "w", "?"}; + const unsigned int delay = get_delay(batch, i, delays, resets_delays, + reset_delays_after); + const struct scan_field * const field = &batch->fields[i]; + + assert(field->out_value); + const unsigned int out_op = buf_get_u32(field->out_value, + DTM_DMI_OP_OFFSET, DTM_DMI_OP_LENGTH); + const uint32_t out_data = buf_get_u32(field->out_value, + DTM_DMI_DATA_OFFSET, DTM_DMI_DATA_LENGTH); + const uint32_t out_address = buf_get_u32(field->out_value, + DTM_DMI_ADDRESS_OFFSET, abits); + if (field->in_value) { + static const char * const status_string[] = { + "+", "?", "F", "b" + }; + const unsigned int in_op = buf_get_u32(field->in_value, + DTM_DMI_OP_OFFSET, DTM_DMI_OP_LENGTH); + const uint32_t in_data = buf_get_u32(field->in_value, + DTM_DMI_DATA_OFFSET, DTM_DMI_DATA_LENGTH); + const uint32_t in_address = buf_get_u32(field->in_value, + DTM_DMI_ADDRESS_OFFSET, abits); + + LOG_DEBUG("%db %s %08" PRIx32 " @%02" PRIx32 + " -> %s %08" PRIx32 " @%02" PRIx32 "; %ui", + field->num_bits, op_string[out_op], out_data, out_address, + status_string[in_op], in_data, in_address, delay); + + if (last_scan_was_read && in_op == DTM_DMI_OP_SUCCESS) + log_dmi_decoded(batch, /*write*/ false, + last_scan_address, in_data); + } else { + LOG_DEBUG("%db %s %08" PRIx32 " @%02" PRIx32 " -> ?; %ui", + field->num_bits, op_string[out_op], out_data, out_address, + delay); + } + + if (out_op == DTM_DMI_OP_WRITE) + log_dmi_decoded(batch, /*write*/ true, out_address, + out_data); + + last_scan_was_read = out_op == DTM_DMI_OP_READ; + last_scan_address = out_address; + } } int riscv_batch_run_from(struct riscv_batch *batch, size_t start_idx, @@ -147,6 +280,7 @@ int riscv_batch_run_from(struct riscv_batch *batch, size_t start_idx, size_t reset_delays_after) { assert(batch->used_scans); + assert(start_idx < batch->used_scans); assert(batch->last_scan == RISCV_SCAN_TYPE_NOP); assert(!batch->was_run || riscv_batch_was_scan_busy(batch, start_idx)); assert(start_idx == 0 || !riscv_batch_was_scan_busy(batch, start_idx - 1)); @@ -157,17 +291,17 @@ int riscv_batch_run_from(struct riscv_batch *batch, size_t start_idx, LOG_TARGET_DEBUG(batch->target, "Running batch of scans [%zu, %zu)", start_idx, batch->used_scans); + unsigned int delay = 0 /* to silence maybe-uninitialized */; for (size_t i = start_idx; i < batch->used_scans; ++i) { if (bscan_tunnel_ir_width != 0) - riscv_add_bscan_tunneled_scan(batch->target, batch->fields + i, batch->bscan_ctxt + i); + riscv_add_bscan_tunneled_scan(batch->target->tap, batch->fields + i, + batch->bscan_ctxt + i); else jtag_add_dr_scan(batch->target->tap, 1, batch->fields + i, TAP_IDLE); - const bool delays_were_reset = resets_delays - && (i >= reset_delays_after); - const int delay = get_delay(batch, i, delays); - - if (!delays_were_reset) + delay = get_delay(batch, i, delays, resets_delays, + reset_delays_after); + if (delay > 0) jtag_add_runtest(delay, TAP_IDLE); } @@ -188,46 +322,62 @@ int riscv_batch_run_from(struct riscv_batch *batch, size_t start_idx, } } - for (size_t i = start_idx; i < batch->used_scans; ++i) { - const int delay = get_delay(batch, i, delays); - riscv_log_dmi_scan(batch->target, delay, batch->fields + i, - /*discard_in*/ false); - } - + log_batch(batch, start_idx, delays, resets_delays, reset_delays_after); batch->was_run = true; - batch->last_scan_delay = get_delay(batch, batch->used_scans - 1, delays); + batch->last_scan_delay = delay; return ERROR_OK; } -void riscv_batch_add_dm_write(struct riscv_batch *batch, uint64_t address, uint32_t data, +void riscv_batch_add_dmi_write(struct riscv_batch *batch, uint32_t address, uint32_t data, bool read_back, enum riscv_scan_delay_class delay_class) { + // TODO: Check that the bit width of "address" is no more than dtmcs.abits, + // otherwise return an error (during batch creation or when the batch is executed). + assert(batch->used_scans < batch->allocated_scans); struct scan_field *field = batch->fields + batch->used_scans; - field->num_bits = riscv_get_dmi_scan_length(batch->target); - field->out_value = (void *)(batch->data_out + batch->used_scans * DMI_SCAN_BUF_SIZE); - riscv_fill_dm_write(batch->target, (char *)field->out_value, address, data); + + field->num_bits = get_dmi_scan_length(batch->target); + assert(field->num_bits <= DMI_SCAN_MAX_BIT_LENGTH); + + uint8_t *out_value = batch->data_out + batch->used_scans * DMI_SCAN_BUF_SIZE; + uint8_t *in_value = batch->data_in + batch->used_scans * DMI_SCAN_BUF_SIZE; + + field->out_value = out_value; + riscv_fill_dmi_write(batch->target, out_value, address, data); + if (read_back) { - field->in_value = (void *)(batch->data_in + batch->used_scans * DMI_SCAN_BUF_SIZE); - riscv_fill_dm_nop(batch->target, (char *)field->in_value); + field->in_value = in_value; + riscv_fill_dm_nop(batch->target, in_value); } else { field->in_value = NULL; } + batch->delay_classes[batch->used_scans] = delay_class; batch->last_scan = RISCV_SCAN_TYPE_WRITE; batch->used_scans++; } -size_t riscv_batch_add_dm_read(struct riscv_batch *batch, uint64_t address, +size_t riscv_batch_add_dmi_read(struct riscv_batch *batch, uint32_t address, enum riscv_scan_delay_class delay_class) { + // TODO: Check that the bit width of "address" is no more than dtmcs.abits, + // otherwise return an error (during batch creation or when the batch is executed). + assert(batch->used_scans < batch->allocated_scans); struct scan_field *field = batch->fields + batch->used_scans; - field->num_bits = riscv_get_dmi_scan_length(batch->target); - field->out_value = (void *)(batch->data_out + batch->used_scans * DMI_SCAN_BUF_SIZE); - field->in_value = (void *)(batch->data_in + batch->used_scans * DMI_SCAN_BUF_SIZE); - riscv_fill_dm_read(batch->target, (char *)field->out_value, address); - riscv_fill_dm_nop(batch->target, (char *)field->in_value); + + field->num_bits = get_dmi_scan_length(batch->target); + assert(field->num_bits <= DMI_SCAN_MAX_BIT_LENGTH); + + uint8_t *out_value = batch->data_out + batch->used_scans * DMI_SCAN_BUF_SIZE; + uint8_t *in_value = batch->data_in + batch->used_scans * DMI_SCAN_BUF_SIZE; + + field->out_value = out_value; + field->in_value = in_value; + riscv_fill_dmi_read(batch->target, out_value, address); + riscv_fill_dm_nop(batch->target, in_value); + batch->delay_classes[batch->used_scans] = delay_class; batch->last_scan = RISCV_SCAN_TYPE_READ; batch->used_scans++; @@ -236,14 +386,14 @@ size_t riscv_batch_add_dm_read(struct riscv_batch *batch, uint64_t address, return batch->read_keys_used++; } -unsigned int riscv_batch_get_dmi_read_op(const struct riscv_batch *batch, size_t key) +uint32_t riscv_batch_get_dmi_read_op(const struct riscv_batch *batch, size_t key) { assert(key < batch->read_keys_used); size_t index = batch->read_keys[key]; assert(index < batch->used_scans); uint8_t *base = batch->data_in + DMI_SCAN_BUF_SIZE * index; /* extract "op" field from the DMI read result */ - return (unsigned int)buf_get_u32(base, DTM_DMI_OP_OFFSET, DTM_DMI_OP_LENGTH); + return buf_get_u32(base, DTM_DMI_OP_OFFSET, DTM_DMI_OP_LENGTH); } uint32_t riscv_batch_get_dmi_read_data(const struct riscv_batch *batch, size_t key) @@ -260,11 +410,18 @@ void riscv_batch_add_nop(struct riscv_batch *batch) { assert(batch->used_scans < batch->allocated_scans); struct scan_field *field = batch->fields + batch->used_scans; - field->num_bits = riscv_get_dmi_scan_length(batch->target); - field->out_value = (void *)(batch->data_out + batch->used_scans * DMI_SCAN_BUF_SIZE); - field->in_value = (void *)(batch->data_in + batch->used_scans * DMI_SCAN_BUF_SIZE); - riscv_fill_dm_nop(batch->target, (char *)field->out_value); - riscv_fill_dm_nop(batch->target, (char *)field->in_value); + + field->num_bits = get_dmi_scan_length(batch->target); + assert(field->num_bits <= DMI_SCAN_MAX_BIT_LENGTH); + + uint8_t *out_value = batch->data_out + batch->used_scans * DMI_SCAN_BUF_SIZE; + uint8_t *in_value = batch->data_in + batch->used_scans * DMI_SCAN_BUF_SIZE; + + field->out_value = out_value; + field->in_value = in_value; + riscv_fill_dm_nop(batch->target, out_value); + riscv_fill_dm_nop(batch->target, in_value); + /* DMI NOP never triggers any debug module operation, * so the shortest (base) delay can be used. */ batch->delay_classes[batch->used_scans] = RISCV_DELAY_BASE; diff --git a/src/target/riscv/batch.h b/src/target/riscv/batch.h index 327406c..5d8b572 100644 --- a/src/target/riscv/batch.h +++ b/src/target/riscv/batch.h @@ -1,7 +1,7 @@ /* SPDX-License-Identifier: GPL-2.0-or-later */ -#ifndef TARGET__RISCV__SCANS_H -#define TARGET__RISCV__SCANS_H +#ifndef OPENOCD_TARGET_RISCV_BATCH_H +#define OPENOCD_TARGET_RISCV_BATCH_H #include "target/target.h" #include "jtag/jtag.h" @@ -190,15 +190,33 @@ int riscv_batch_run_from(struct riscv_batch *batch, size_t start_idx, size_t riscv_batch_finished_scans(const struct riscv_batch *batch); /* Adds a DM register write to this batch. */ -void riscv_batch_add_dm_write(struct riscv_batch *batch, uint64_t address, uint32_t data, +void riscv_batch_add_dmi_write(struct riscv_batch *batch, uint32_t address, uint32_t data, bool read_back, enum riscv_scan_delay_class delay_class); +static inline void +riscv_batch_add_dm_write(struct riscv_batch *batch, uint32_t address, uint32_t data, + bool read_back, enum riscv_scan_delay_class delay_type) +{ + return riscv_batch_add_dmi_write(batch, + riscv_get_dmi_address(batch->target, address), data, + read_back, delay_type); +} + /* DM register reads must be handled in two parts: the first one schedules a read and * provides a key, the second one actually obtains the result of the read - * status (op) and the actual data. */ -size_t riscv_batch_add_dm_read(struct riscv_batch *batch, uint64_t address, +size_t riscv_batch_add_dmi_read(struct riscv_batch *batch, uint32_t address, enum riscv_scan_delay_class delay_class); -unsigned int riscv_batch_get_dmi_read_op(const struct riscv_batch *batch, size_t key); + +static inline size_t +riscv_batch_add_dm_read(struct riscv_batch *batch, uint32_t address, + enum riscv_scan_delay_class delay_type) +{ + return riscv_batch_add_dmi_read(batch, + riscv_get_dmi_address(batch->target, address), delay_type); +} + +uint32_t riscv_batch_get_dmi_read_op(const struct riscv_batch *batch, size_t key); uint32_t riscv_batch_get_dmi_read_data(const struct riscv_batch *batch, size_t key); /* Scans in a NOP. */ @@ -210,10 +228,4 @@ size_t riscv_batch_available_scans(struct riscv_batch *batch); /* Return true iff the last scan in the batch returned DMI_OP_BUSY. */ bool riscv_batch_was_batch_busy(const struct riscv_batch *batch); -/* TODO: The function is defined in `riscv-013.c`. This is done to reduce the - * diff of the commit. The intention is to move the function definition to - * a separate module (e.g. `riscv013-jtag-dtm.c/h`) in another commit. */ -void riscv_log_dmi_scan(const struct target *target, int idle, const struct scan_field *field, - bool discard_in); - -#endif +#endif /* OPENOCD_TARGET_RISCV_BATCH_H */ diff --git a/src/target/riscv/debug_reg_printer.h b/src/target/riscv/debug_reg_printer.h index 98226b7..5089ff8 100644 --- a/src/target/riscv/debug_reg_printer.h +++ b/src/target/riscv/debug_reg_printer.h @@ -1,5 +1,8 @@ /* SPDX-License-Identifier: GPL-2.0-or-later */ +#ifndef OPENOCD_TARGET_RISCV_DEBUG_REG_PRINTER_H +#define OPENOCD_TARGET_RISCV_DEBUG_REG_PRINTER_H + #include "debug_defines.h" enum riscv_debug_reg_show { @@ -33,3 +36,5 @@ enum riscv_debug_reg_show { unsigned int riscv_debug_reg_to_s(char *buf, enum riscv_debug_reg_ordinal reg_ordinal, riscv_debug_reg_ctx_t context, uint64_t value, enum riscv_debug_reg_show show); + +#endif /* OPENOCD_TARGET_RISCV_DEBUG_REG_PRINTER_H */ diff --git a/src/target/riscv/field_helpers.h b/src/target/riscv/field_helpers.h index 16578f1..abf19f6 100644 --- a/src/target/riscv/field_helpers.h +++ b/src/target/riscv/field_helpers.h @@ -1,7 +1,7 @@ /* SPDX-License-Identifier: GPL-2.0-or-later */ -#ifndef FIELD_HELPERS_H -#define FIELD_HELPERS_H +#ifndef OPENOCD_TARGET_RISCV_FIELD_HELPERS_H +#define OPENOCD_TARGET_RISCV_FIELD_HELPERS_H #include <stdint.h> #include <assert.h> @@ -44,4 +44,4 @@ static inline uint32_t field_value32(uint32_t mask, uint32_t val) return set_field32(0, mask, val); } -#endif +#endif /* OPENOCD_TARGET_RISCV_FIELD_HELPERS_H */ diff --git a/src/target/riscv/gdb_regs.h b/src/target/riscv/gdb_regs.h index d606f73..0d03929 100644 --- a/src/target/riscv/gdb_regs.h +++ b/src/target/riscv/gdb_regs.h @@ -1,7 +1,7 @@ /* SPDX-License-Identifier: GPL-2.0-or-later */ -#ifndef TARGET__RISCV__GDB_REGS_H -#define TARGET__RISCV__GDB_REGS_H +#ifndef OPENOCD_TARGET_RISCV_GDB_REGS_H +#define OPENOCD_TARGET_RISCV_GDB_REGS_H #include "encoding.h" @@ -125,4 +125,4 @@ enum gdb_regno { GDB_REGNO_COUNT }; -#endif +#endif /* OPENOCD_TARGET_RISCV_GDB_REGS_H */ diff --git a/src/target/riscv/opcodes.h b/src/target/riscv/opcodes.h index 59c3413..e4efc5b 100644 --- a/src/target/riscv/opcodes.h +++ b/src/target/riscv/opcodes.h @@ -1,15 +1,39 @@ /* SPDX-License-Identifier: GPL-2.0-or-later */ +#ifndef OPENOCD_TARGET_RISCV_OPCODES_H +#define OPENOCD_TARGET_RISCV_OPCODES_H + #include "encoding.h" +#include <assert.h> +#include <stdbool.h> +#include <stdint.h> #define ZERO 0 #define T0 5 #define S0 8 #define S1 9 +#define MAX_GPR_NUM 31 +#define MAX_FPR_NUM 31 +#define MAX_VREG_NUM 31 +#define MAX_CSR_NUM 4095 + +#define MIN_INT12 (-0x800) +#define MAX_INT12 0x7ff + +#define MIN_INT13 (-0x1000) +#define MAX_INT13 0xfff + +#define MIN_INT21 (-0x100000) +#define MAX_INT21 0xfffff + +#define MAX_UINT5 0x1f +#define MAX_UINT11 0x7ff +#define MAX_UINT12 0xfff + static uint32_t bits(uint32_t value, unsigned int hi, unsigned int lo) { - return (value >> lo) & ((1 << (hi+1-lo)) - 1); + return (value >> lo) & (((uint32_t)1 << (hi + 1 - lo)) - 1); } static uint32_t bit(uint32_t value, unsigned int b) @@ -65,153 +89,246 @@ static uint32_t imm_j(uint32_t imm) return (bits(imm, 19, 12) << 12) | (bit(imm, 11) << 20) | (bits(imm, 10, 1) << 21) | (bit(imm, 20) << 31); } -static uint32_t jal(unsigned int rd, uint32_t imm) __attribute__ ((unused)); -static uint32_t jal(unsigned int rd, uint32_t imm) +static uint32_t jal(unsigned int rd, int32_t imm) __attribute__ ((unused)); +static uint32_t jal(unsigned int rd, int32_t imm) { - return imm_j(imm) | inst_rd(rd) | MATCH_JAL; + assert(rd <= MAX_GPR_NUM); + assert((imm >= MIN_INT21) && (imm <= MAX_INT21)); + assert((imm & 1) == 0); + + return imm_j((uint32_t)imm) | inst_rd(rd) | MATCH_JAL; } -static uint32_t csrsi(unsigned int csr, uint16_t imm) __attribute__ ((unused)); -static uint32_t csrsi(unsigned int csr, uint16_t imm) +static uint32_t csrsi(unsigned int csr, uint8_t imm) __attribute__ ((unused)); +static uint32_t csrsi(unsigned int csr, uint8_t imm) { + assert(csr <= MAX_CSR_NUM); + assert(imm <= MAX_UINT5); + return imm_i(csr) | inst_rs1(imm) | MATCH_CSRRSI; } -static uint32_t sw(unsigned int src, unsigned int base, uint16_t offset) __attribute__ ((unused)); -static uint32_t sw(unsigned int src, unsigned int base, uint16_t offset) +static uint32_t sw(unsigned int src, unsigned int base, int16_t offset) __attribute__ ((unused)); +static uint32_t sw(unsigned int src, unsigned int base, int16_t offset) { - return imm_s(offset) | inst_rs2(src) | inst_rs1(base) | MATCH_SW; + assert(src <= MAX_GPR_NUM); + assert(base <= MAX_GPR_NUM); + assert((offset >= MIN_INT12) && (offset <= MAX_INT12)); + + return imm_s((uint16_t)offset) | inst_rs2(src) | inst_rs1(base) | MATCH_SW; } -static uint32_t sd(unsigned int src, unsigned int base, uint16_t offset) __attribute__ ((unused)); -static uint32_t sd(unsigned int src, unsigned int base, uint16_t offset) +static uint32_t sd(unsigned int src, unsigned int base, int16_t offset) __attribute__ ((unused)); +static uint32_t sd(unsigned int src, unsigned int base, int16_t offset) { - return imm_s(offset) | inst_rs2(src) | inst_rs1(base) | MATCH_SD; + assert(src <= MAX_GPR_NUM); + assert(base <= MAX_GPR_NUM); + assert((offset >= MIN_INT12) && (offset <= MAX_INT12)); + + return imm_s((uint16_t)offset) | inst_rs2(src) | inst_rs1(base) | MATCH_SD; } -static uint32_t sh(unsigned int src, unsigned int base, uint16_t offset) __attribute__ ((unused)); -static uint32_t sh(unsigned int src, unsigned int base, uint16_t offset) +static uint32_t sh(unsigned int src, unsigned int base, int16_t offset) __attribute__ ((unused)); +static uint32_t sh(unsigned int src, unsigned int base, int16_t offset) { - return imm_s(offset) | inst_rs2(src) | inst_rs1(base) | MATCH_SH; + assert(src <= MAX_GPR_NUM); + assert(base <= MAX_GPR_NUM); + assert((offset >= MIN_INT12) && (offset <= MAX_INT12)); + + return imm_s((uint16_t)offset) | inst_rs2(src) | inst_rs1(base) | MATCH_SH; } -static uint32_t sb(unsigned int src, unsigned int base, uint16_t offset) __attribute__ ((unused)); -static uint32_t sb(unsigned int src, unsigned int base, uint16_t offset) +static uint32_t sb(unsigned int src, unsigned int base, int16_t offset) __attribute__ ((unused)); +static uint32_t sb(unsigned int src, unsigned int base, int16_t offset) { - return imm_s(offset) | inst_rs2(src) | inst_rs1(base) | MATCH_SB; + assert(src <= MAX_GPR_NUM); + assert(base <= MAX_GPR_NUM); + assert((offset >= MIN_INT12) && (offset <= MAX_INT12)); + + return imm_s((uint16_t)offset) | inst_rs2(src) | inst_rs1(base) | MATCH_SB; } -static uint32_t ld(unsigned int rd, unsigned int base, uint16_t offset) __attribute__ ((unused)); -static uint32_t ld(unsigned int rd, unsigned int base, uint16_t offset) +static uint32_t ld(unsigned int rd, unsigned int base, int16_t offset) __attribute__ ((unused)); +static uint32_t ld(unsigned int rd, unsigned int base, int16_t offset) { - return imm_i(offset) | inst_rs1(base) | inst_rd(rd) | MATCH_LD; + assert(rd <= MAX_GPR_NUM); + assert(base <= MAX_GPR_NUM); + assert((offset >= MIN_INT12) && (offset <= MAX_INT12)); + + return imm_i((uint16_t)offset) | inst_rs1(base) | inst_rd(rd) | MATCH_LD; } -static uint32_t lw(unsigned int rd, unsigned int base, uint16_t offset) __attribute__ ((unused)); -static uint32_t lw(unsigned int rd, unsigned int base, uint16_t offset) +static uint32_t lw(unsigned int rd, unsigned int base, int16_t offset) __attribute__ ((unused)); +static uint32_t lw(unsigned int rd, unsigned int base, int16_t offset) { - return imm_i(offset) | inst_rs1(base) | inst_rd(rd) | MATCH_LW; + assert(rd <= MAX_GPR_NUM); + assert(base <= MAX_GPR_NUM); + assert((offset >= MIN_INT12) && (offset <= MAX_INT12)); + + return imm_i((uint16_t)offset) | inst_rs1(base) | inst_rd(rd) | MATCH_LW; } -static uint32_t lh(unsigned int rd, unsigned int base, uint16_t offset) __attribute__ ((unused)); -static uint32_t lh(unsigned int rd, unsigned int base, uint16_t offset) +static uint32_t lh(unsigned int rd, unsigned int base, int16_t offset) __attribute__ ((unused)); +static uint32_t lh(unsigned int rd, unsigned int base, int16_t offset) { - return imm_i(offset) | inst_rs1(base) | inst_rd(rd) | MATCH_LH; + assert(rd <= MAX_GPR_NUM); + assert(base <= MAX_GPR_NUM); + assert((offset >= MIN_INT12) && (offset <= MAX_INT12)); + + return imm_i((uint16_t)offset) | inst_rs1(base) | inst_rd(rd) | MATCH_LH; } -static uint32_t lb(unsigned int rd, unsigned int base, uint16_t offset) __attribute__ ((unused)); -static uint32_t lb(unsigned int rd, unsigned int base, uint16_t offset) +static uint32_t lb(unsigned int rd, unsigned int base, int16_t offset) __attribute__ ((unused)); +static uint32_t lb(unsigned int rd, unsigned int base, int16_t offset) { - return imm_i(offset) | inst_rs1(base) | inst_rd(rd) | MATCH_LB; + assert(rd <= MAX_GPR_NUM); + assert(base <= MAX_GPR_NUM); + assert((offset >= MIN_INT12) && (offset <= MAX_INT12)); + + return imm_i((uint16_t)offset) | inst_rs1(base) | inst_rd(rd) | MATCH_LB; } static uint32_t csrw(unsigned int source, unsigned int csr) __attribute__ ((unused)); static uint32_t csrw(unsigned int source, unsigned int csr) { + assert(source <= MAX_GPR_NUM); + assert(csr <= MAX_CSR_NUM); + return imm_i(csr) | inst_rs1(source) | MATCH_CSRRW; } -static uint32_t addi(unsigned int dest, unsigned int src, uint16_t imm) __attribute__ ((unused)); -static uint32_t addi(unsigned int dest, unsigned int src, uint16_t imm) +static uint32_t addi(unsigned int dest, unsigned int src, int16_t imm) __attribute__ ((unused)); +static uint32_t addi(unsigned int dest, unsigned int src, int16_t imm) { - return imm_i(imm) | inst_rs1(src) | inst_rd(dest) | MATCH_ADDI; + assert(dest <= MAX_GPR_NUM); + assert(src <= MAX_GPR_NUM); + assert((imm >= MIN_INT12) && (imm <= MAX_INT12)); + + return imm_i((uint16_t)imm) | inst_rs1(src) | inst_rd(dest) | MATCH_ADDI; } static uint32_t csrr(unsigned int rd, unsigned int csr) __attribute__ ((unused)); static uint32_t csrr(unsigned int rd, unsigned int csr) { + assert(rd <= MAX_GPR_NUM); + assert(csr <= MAX_CSR_NUM); + return imm_i(csr) | inst_rd(rd) | MATCH_CSRRS; } static uint32_t csrrs(unsigned int rd, unsigned int rs, unsigned int csr) __attribute__ ((unused)); static uint32_t csrrs(unsigned int rd, unsigned int rs, unsigned int csr) { + assert(rd <= MAX_GPR_NUM); + assert(rs <= MAX_GPR_NUM); + assert(csr <= MAX_CSR_NUM); + return imm_i(csr) | inst_rs1(rs) | inst_rd(rd) | MATCH_CSRRS; } static uint32_t csrrw(unsigned int rd, unsigned int rs, unsigned int csr) __attribute__ ((unused)); static uint32_t csrrw(unsigned int rd, unsigned int rs, unsigned int csr) { + assert(rd <= MAX_GPR_NUM); + assert(rs <= MAX_GPR_NUM); + assert(csr <= MAX_CSR_NUM); + return imm_i(csr) | inst_rs1(rs) | inst_rd(rd) | MATCH_CSRRW; } -static uint32_t csrrci(unsigned int rd, unsigned int zimm, unsigned int csr) __attribute__ ((unused)); -static uint32_t csrrci(unsigned int rd, unsigned int zimm, unsigned int csr) +static uint32_t csrrci(unsigned int rd, uint8_t zimm, unsigned int csr) __attribute__ ((unused)); +static uint32_t csrrci(unsigned int rd, uint8_t zimm, unsigned int csr) { + assert(rd <= MAX_GPR_NUM); + assert(zimm <= MAX_UINT5); + assert(csr <= MAX_CSR_NUM); + return imm_i(csr) | inst_rs1(zimm) | inst_rd(rd) | MATCH_CSRRCI; } -static uint32_t csrrsi(unsigned int rd, unsigned int zimm, unsigned int csr) __attribute__ ((unused)); -static uint32_t csrrsi(unsigned int rd, unsigned int zimm, unsigned int csr) +static uint32_t csrrsi(unsigned int rd, uint8_t zimm, unsigned int csr) __attribute__ ((unused)); +static uint32_t csrrsi(unsigned int rd, uint8_t zimm, unsigned int csr) { + assert(rd <= MAX_GPR_NUM); + assert(zimm <= MAX_UINT5); + assert(csr <= MAX_CSR_NUM); + return imm_i(csr) | inst_rs1(zimm) | inst_rd(rd) | MATCH_CSRRSI; } -static uint32_t fsw(unsigned int src, unsigned int base, uint16_t offset) __attribute__ ((unused)); -static uint32_t fsw(unsigned int src, unsigned int base, uint16_t offset) +static uint32_t fsw(unsigned int src, unsigned int base, int16_t offset) __attribute__ ((unused)); +static uint32_t fsw(unsigned int src, unsigned int base, int16_t offset) { - return imm_s(offset) | inst_rs2(src) | inst_rs1(base) | MATCH_FSW; + assert(src <= MAX_FPR_NUM); + assert(base <= MAX_GPR_NUM); + assert((offset >= MIN_INT12) && (offset <= MAX_INT12)); + + return imm_s((uint16_t)offset) | inst_rs2(src) | inst_rs1(base) | MATCH_FSW; } -static uint32_t fsd(unsigned int src, unsigned int base, uint16_t offset) __attribute__ ((unused)); -static uint32_t fsd(unsigned int src, unsigned int base, uint16_t offset) +static uint32_t fsd(unsigned int src, unsigned int base, int16_t offset) __attribute__ ((unused)); +static uint32_t fsd(unsigned int src, unsigned int base, int16_t offset) { - return imm_s(offset) | inst_rs2(src) | inst_rs1(base) | MATCH_FSD; + assert(src <= MAX_FPR_NUM); + assert(base <= MAX_GPR_NUM); + assert((offset >= MIN_INT12) && (offset <= MAX_INT12)); + + return imm_s((uint16_t)offset) | inst_rs2(src) | inst_rs1(base) | MATCH_FSD; } -static uint32_t flw(unsigned int dest, unsigned int base, uint16_t offset) __attribute__ ((unused)); -static uint32_t flw(unsigned int dest, unsigned int base, uint16_t offset) +static uint32_t flw(unsigned int dest, unsigned int base, int16_t offset) __attribute__ ((unused)); +static uint32_t flw(unsigned int dest, unsigned int base, int16_t offset) { - return imm_i(offset) | inst_rs1(base) | inst_rd(dest) | MATCH_FLW; + assert(dest <= MAX_FPR_NUM); + assert(base <= MAX_GPR_NUM); + assert((offset >= MIN_INT12) && (offset <= MAX_INT12)); + + return imm_i((uint16_t)offset) | inst_rs1(base) | inst_rd(dest) | MATCH_FLW; } -static uint32_t fld(unsigned int dest, unsigned int base, uint16_t offset) __attribute__ ((unused)); -static uint32_t fld(unsigned int dest, unsigned int base, uint16_t offset) +static uint32_t fld(unsigned int dest, unsigned int base, int16_t offset) __attribute__ ((unused)); +static uint32_t fld(unsigned int dest, unsigned int base, int16_t offset) { - return imm_i(offset) | inst_rs1(base) | inst_rd(dest) | MATCH_FLD; + assert(dest <= MAX_FPR_NUM); + assert(base <= MAX_GPR_NUM); + assert((offset >= MIN_INT12) && (offset <= MAX_INT12)); + + return imm_i((uint16_t)offset) | inst_rs1(base) | inst_rd(dest) | MATCH_FLD; } -static uint32_t fmv_x_w(unsigned dest, unsigned src) __attribute__ ((unused)); -static uint32_t fmv_x_w(unsigned dest, unsigned src) +static uint32_t fmv_x_w(unsigned int dest, unsigned int src) __attribute__ ((unused)); +static uint32_t fmv_x_w(unsigned int dest, unsigned int src) { + assert(dest <= MAX_GPR_NUM); + assert(src <= MAX_FPR_NUM); + return inst_rs1(src) | inst_rd(dest) | MATCH_FMV_X_W; } -static uint32_t fmv_x_d(unsigned dest, unsigned src) __attribute__ ((unused)); -static uint32_t fmv_x_d(unsigned dest, unsigned src) +static uint32_t fmv_x_d(unsigned int dest, unsigned int src) __attribute__ ((unused)); +static uint32_t fmv_x_d(unsigned int dest, unsigned int src) { + assert(dest <= MAX_GPR_NUM); + assert(src <= MAX_FPR_NUM); + return inst_rs1(src) | inst_rd(dest) | MATCH_FMV_X_D; } -static uint32_t fmv_w_x(unsigned dest, unsigned src) __attribute__ ((unused)); -static uint32_t fmv_w_x(unsigned dest, unsigned src) +static uint32_t fmv_w_x(unsigned int dest, unsigned int src) __attribute__ ((unused)); +static uint32_t fmv_w_x(unsigned int dest, unsigned int src) { + assert(dest <= MAX_FPR_NUM); + assert(src <= MAX_GPR_NUM); + return inst_rs1(src) | inst_rd(dest) | MATCH_FMV_W_X; } -static uint32_t fmv_d_x(unsigned dest, unsigned src) __attribute__ ((unused)); -static uint32_t fmv_d_x(unsigned dest, unsigned src) +static uint32_t fmv_d_x(unsigned int dest, unsigned int src) __attribute__ ((unused)); +static uint32_t fmv_d_x(unsigned int dest, unsigned int src) { + assert(dest <= MAX_FPR_NUM); + assert(src <= MAX_GPR_NUM); + return inst_rs1(src) | inst_rd(dest) | MATCH_FMV_D_X; } @@ -238,59 +355,29 @@ static uint32_t fence_i(void) static uint32_t lui(unsigned int dest, uint32_t imm) __attribute__ ((unused)); static uint32_t lui(unsigned int dest, uint32_t imm) { - return imm_u(imm) | inst_rd(dest) | MATCH_LUI; -} - -/* -static uint32_t csrci(unsigned int csr, uint16_t imm) __attribute__ ((unused)); -static uint32_t csrci(unsigned int csr, uint16_t imm) -{ - return (csr << 20) | - (bits(imm, 4, 0) << 15) | - MATCH_CSRRCI; -} - -static uint32_t li(unsigned int dest, uint16_t imm) __attribute__ ((unused)); -static uint32_t li(unsigned int dest, uint16_t imm) -{ - return addi(dest, 0, imm); -} - -static uint32_t fsd(unsigned int src, unsigned int base, uint16_t offset) __attribute__ ((unused)); -static uint32_t fsd(unsigned int src, unsigned int base, uint16_t offset) -{ - return (bits(offset, 11, 5) << 25) | - (bits(src, 4, 0) << 20) | - (base << 15) | - (bits(offset, 4, 0) << 7) | - MATCH_FSD; -} + assert(dest <= MAX_GPR_NUM); + assert(bits(imm, 11, 0) == 0); -static uint32_t ori(unsigned int dest, unsigned int src, uint16_t imm) __attribute__ ((unused)); -static uint32_t ori(unsigned int dest, unsigned int src, uint16_t imm) -{ - return (bits(imm, 11, 0) << 20) | - (src << 15) | - (dest << 7) | - MATCH_ORI; + return imm_u(imm) | inst_rd(dest) | MATCH_LUI; } -static uint32_t nop(void) __attribute__ ((unused)); -static uint32_t nop(void) +static uint32_t xori(unsigned int dest, unsigned int src, int16_t imm) __attribute__ ((unused)); +static uint32_t xori(unsigned int dest, unsigned int src, int16_t imm) { - return addi(0, 0, 0); -} -*/ + assert(dest <= MAX_GPR_NUM); + assert(src <= MAX_GPR_NUM); + assert((imm >= MIN_INT12) && (imm <= MAX_INT12)); -static uint32_t xori(unsigned int dest, unsigned int src, uint16_t imm) __attribute__ ((unused)); -static uint32_t xori(unsigned int dest, unsigned int src, uint16_t imm) -{ - return imm_i(imm) | inst_rs1(src) | inst_rd(dest) | MATCH_XORI; + return imm_i((uint16_t)imm) | inst_rs1(src) | inst_rd(dest) | MATCH_XORI; } static uint32_t srli(unsigned int dest, unsigned int src, uint8_t shamt) __attribute__ ((unused)); static uint32_t srli(unsigned int dest, unsigned int src, uint8_t shamt) { + assert(dest <= MAX_GPR_NUM); + assert(src <= MAX_GPR_NUM); + assert(shamt <= MAX_UINT5); + return inst_rs2(shamt) | inst_rs1(src) | inst_rd(dest) | MATCH_SRLI; } @@ -304,38 +391,59 @@ static uint32_t fence_rw_rw(void) static uint32_t auipc(unsigned int dest) __attribute__((unused)); static uint32_t auipc(unsigned int dest) { + assert(dest <= MAX_GPR_NUM); + return MATCH_AUIPC | inst_rd(dest); } -static uint32_t vsetvli(unsigned int dest, unsigned int src, uint16_t imm) __attribute__((unused)); -static uint32_t vsetvli(unsigned int dest, unsigned int src, uint16_t imm) +static uint32_t vsetvli(unsigned int dest, unsigned int src, uint16_t vtypei) __attribute__((unused)); +static uint32_t vsetvli(unsigned int dest, unsigned int src, uint16_t vtypei) { - return (bits(imm, 10, 0) << 20) | inst_rs1(src) | inst_rd(dest) | MATCH_VSETVLI; + assert(dest <= MAX_GPR_NUM); + assert(src <= MAX_GPR_NUM); + assert(vtypei <= MAX_UINT11); + + return (bits(vtypei, 10, 0) << 20) | inst_rs1(src) | inst_rd(dest) | MATCH_VSETVLI; } static uint32_t vsetvl(unsigned int rd, unsigned int rs1, unsigned int rs2) __attribute__((unused)); static uint32_t vsetvl(unsigned int rd, unsigned int rs1, unsigned int rs2) { + assert(rd <= MAX_GPR_NUM); + assert(rs1 <= MAX_GPR_NUM); + assert(rs2 <= MAX_GPR_NUM); + return inst_rd(rd) | inst_rs1(rs1) | inst_rs2(rs2) | MATCH_VSETVL; } static uint32_t vmv_x_s(unsigned int rd, unsigned int vs2) __attribute__((unused)); static uint32_t vmv_x_s(unsigned int rd, unsigned int vs2) { + assert(rd <= MAX_GPR_NUM); + assert(vs2 <= MAX_VREG_NUM); + return inst_rs2(vs2) | inst_rd(rd) | MATCH_VMV_X_S; } -static uint32_t vmv_s_x(unsigned int vd, unsigned int vs2) __attribute__((unused)); -static uint32_t vmv_s_x(unsigned int vd, unsigned int rs1) +static uint32_t vmv_s_x(unsigned int vd, unsigned int rs2) __attribute__((unused)); +static uint32_t vmv_s_x(unsigned int vd, unsigned int rs2) { - return inst_rs1(rs1) | inst_rd(vd) | MATCH_VMV_S_X; + assert(vd <= MAX_VREG_NUM); + assert(rs2 <= MAX_GPR_NUM); + + return inst_rs1(rs2) | inst_rd(vd) | MATCH_VMV_S_X; } static uint32_t vslide1down_vx(unsigned int vd, unsigned int vs2, - unsigned int rs1, unsigned int vm) __attribute__((unused)); + unsigned int rs1, bool vm) __attribute__((unused)); static uint32_t vslide1down_vx(unsigned int vd, unsigned int vs2, - unsigned int rs1, unsigned int vm) + unsigned int rs1, bool vm) { - return ((vm & 1) << 25) | inst_rs2(vs2) | inst_rs1(rs1) | inst_rd(vd) | MATCH_VSLIDE1DOWN_VX; + assert(vd <= MAX_VREG_NUM); + assert(vs2 <= MAX_VREG_NUM); + assert(rs1 <= MAX_GPR_NUM); + + return (vm ? (1u << 25) : 0u) | inst_rs2(vs2) | inst_rs1(rs1) | inst_rd(vd) | MATCH_VSLIDE1DOWN_VX; } +#endif /* OPENOCD_TARGET_RISCV_OPCODES_H */ diff --git a/src/target/riscv/program.c b/src/target/riscv/program.c index c4ffb3f..bf6718f 100644 --- a/src/target/riscv/program.c +++ b/src/target/riscv/program.c @@ -10,7 +10,6 @@ #include "program.h" #include "helper/log.h" -#include "asm.h" #include "debug_defines.h" #include "encoding.h" @@ -21,8 +20,8 @@ int riscv_program_init(struct riscv_program *p, struct target *target) p->target = target; p->instruction_count = 0; - for (size_t i = 0; i < RISCV_MAX_PROGBUF_SIZE; ++i) - p->progbuf[i] = -1; + for (unsigned int i = 0; i < RISCV013_MAX_PROGBUF_SIZE; ++i) + p->progbuf[i] = (uint32_t)(-1); p->execution_result = RISCV_PROGBUF_EXEC_RESULT_NOT_EXECUTED; return ERROR_OK; @@ -30,7 +29,7 @@ int riscv_program_init(struct riscv_program *p, struct target *target) int riscv_program_write(struct riscv_program *program) { - for (unsigned i = 0; i < program->instruction_count; ++i) { + for (unsigned int i = 0; i < program->instruction_count; ++i) { LOG_TARGET_DEBUG(program->target, "progbuf[%02x] = DASM(0x%08x)", i, program->progbuf[i]); if (riscv_write_progbuf(program->target, i, program->progbuf[i]) != ERROR_OK) @@ -48,9 +47,9 @@ int riscv_program_exec(struct riscv_program *p, struct target *t) if (riscv_program_ebreak(p) != ERROR_OK) { LOG_TARGET_ERROR(t, "Unable to insert ebreak into program buffer"); - for (size_t i = 0; i < riscv_progbuf_size(p->target); ++i) - LOG_TARGET_ERROR(t, "ram[%02x]: DASM(0x%08" PRIx32 ") [0x%08" PRIx32 "]", - (int)i, p->progbuf[i], p->progbuf[i]); + for (unsigned int i = 0; i < riscv_progbuf_size(p->target); ++i) + LOG_TARGET_ERROR(t, "progbuf[%02x]: DASM(0x%08" PRIx32 ") [0x%08" PRIx32 "]", + i, p->progbuf[i], p->progbuf[i]); return ERROR_FAIL; } @@ -71,27 +70,27 @@ int riscv_program_exec(struct riscv_program *p, struct target *t) return ERROR_OK; } -int riscv_program_sdr(struct riscv_program *p, enum gdb_regno d, enum gdb_regno b, int offset) +int riscv_program_sdr(struct riscv_program *p, enum gdb_regno d, enum gdb_regno b, int16_t offset) { return riscv_program_insert(p, sd(d, b, offset)); } -int riscv_program_swr(struct riscv_program *p, enum gdb_regno d, enum gdb_regno b, int offset) +int riscv_program_swr(struct riscv_program *p, enum gdb_regno d, enum gdb_regno b, int16_t offset) { return riscv_program_insert(p, sw(d, b, offset)); } -int riscv_program_shr(struct riscv_program *p, enum gdb_regno d, enum gdb_regno b, int offset) +int riscv_program_shr(struct riscv_program *p, enum gdb_regno d, enum gdb_regno b, int16_t offset) { return riscv_program_insert(p, sh(d, b, offset)); } -int riscv_program_sbr(struct riscv_program *p, enum gdb_regno d, enum gdb_regno b, int offset) +int riscv_program_sbr(struct riscv_program *p, enum gdb_regno d, enum gdb_regno b, int16_t offset) { return riscv_program_insert(p, sb(d, b, offset)); } -int riscv_program_store(struct riscv_program *p, enum gdb_regno d, enum gdb_regno b, int offset, +int riscv_program_store(struct riscv_program *p, enum gdb_regno d, enum gdb_regno b, int16_t offset, unsigned int size) { switch (size) { @@ -108,27 +107,27 @@ int riscv_program_store(struct riscv_program *p, enum gdb_regno d, enum gdb_regn return ERROR_FAIL; } -int riscv_program_ldr(struct riscv_program *p, enum gdb_regno d, enum gdb_regno b, int offset) +int riscv_program_ldr(struct riscv_program *p, enum gdb_regno d, enum gdb_regno b, int16_t offset) { return riscv_program_insert(p, ld(d, b, offset)); } -int riscv_program_lwr(struct riscv_program *p, enum gdb_regno d, enum gdb_regno b, int offset) +int riscv_program_lwr(struct riscv_program *p, enum gdb_regno d, enum gdb_regno b, int16_t offset) { return riscv_program_insert(p, lw(d, b, offset)); } -int riscv_program_lhr(struct riscv_program *p, enum gdb_regno d, enum gdb_regno b, int offset) +int riscv_program_lhr(struct riscv_program *p, enum gdb_regno d, enum gdb_regno b, int16_t offset) { return riscv_program_insert(p, lh(d, b, offset)); } -int riscv_program_lbr(struct riscv_program *p, enum gdb_regno d, enum gdb_regno b, int offset) +int riscv_program_lbr(struct riscv_program *p, enum gdb_regno d, enum gdb_regno b, int16_t offset) { return riscv_program_insert(p, lb(d, b, offset)); } -int riscv_program_load(struct riscv_program *p, enum gdb_regno d, enum gdb_regno b, int offset, +int riscv_program_load(struct riscv_program *p, enum gdb_regno d, enum gdb_regno b, int16_t offset, unsigned int size) { switch (size) { @@ -145,13 +144,13 @@ int riscv_program_load(struct riscv_program *p, enum gdb_regno d, enum gdb_regno return ERROR_FAIL; } -int riscv_program_csrrsi(struct riscv_program *p, enum gdb_regno d, unsigned int z, enum gdb_regno csr) +int riscv_program_csrrsi(struct riscv_program *p, enum gdb_regno d, uint8_t z, enum gdb_regno csr) { assert(csr >= GDB_REGNO_CSR0 && csr <= GDB_REGNO_CSR4095); return riscv_program_insert(p, csrrsi(d, z, csr - GDB_REGNO_CSR0)); } -int riscv_program_csrrci(struct riscv_program *p, enum gdb_regno d, unsigned int z, enum gdb_regno csr) +int riscv_program_csrrci(struct riscv_program *p, enum gdb_regno d, uint8_t z, enum gdb_regno csr) { assert(csr >= GDB_REGNO_CSR0 && csr <= GDB_REGNO_CSR4095); return riscv_program_insert(p, csrrci(d, z, csr - GDB_REGNO_CSR0)); @@ -165,7 +164,7 @@ int riscv_program_csrr(struct riscv_program *p, enum gdb_regno d, enum gdb_regno int riscv_program_csrw(struct riscv_program *p, enum gdb_regno s, enum gdb_regno csr) { - assert(csr >= GDB_REGNO_CSR0); + assert(csr >= GDB_REGNO_CSR0 && csr <= GDB_REGNO_CSR4095); return riscv_program_insert(p, csrrw(GDB_REGNO_ZERO, s, csr - GDB_REGNO_CSR0)); } @@ -183,8 +182,8 @@ int riscv_program_ebreak(struct riscv_program *p) { struct target *target = p->target; RISCV_INFO(r); - if (p->instruction_count == riscv_progbuf_size(p->target) && - r->impebreak) { + if (p->instruction_count == riscv_progbuf_size(target) && + r->get_impebreak(target)) { return ERROR_OK; } return riscv_program_insert(p, ebreak()); @@ -199,8 +198,8 @@ int riscv_program_insert(struct riscv_program *p, riscv_insn_t i) { if (p->instruction_count >= riscv_progbuf_size(p->target)) { LOG_TARGET_ERROR(p->target, "Unable to insert program into progbuf, " - "capacity would be exceeded (progbufsize=%d).", - (int)riscv_progbuf_size(p->target)); + "capacity would be exceeded (progbufsize=%u).", + riscv_progbuf_size(p->target)); return ERROR_FAIL; } diff --git a/src/target/riscv/program.h b/src/target/riscv/program.h index 93dbdbf..ba44aba 100644 --- a/src/target/riscv/program.h +++ b/src/target/riscv/program.h @@ -1,13 +1,11 @@ /* SPDX-License-Identifier: GPL-2.0-or-later */ -#ifndef TARGET__RISCV__PROGRAM_H -#define TARGET__RISCV__PROGRAM_H +#ifndef OPENOCD_TARGET_RISCV_PROGRAM_H +#define OPENOCD_TARGET_RISCV_PROGRAM_H #include "riscv.h" -#define RISCV_MAX_PROGBUF_SIZE 32 -#define RISCV_REGISTER_COUNT 32 -#define RISCV_DSCRATCH_COUNT 2 +#define RISCV013_MAX_PROGBUF_SIZE 16 typedef enum { RISCV_PROGBUF_EXEC_RESULT_NOT_EXECUTED, @@ -23,10 +21,10 @@ typedef enum { struct riscv_program { struct target *target; - uint32_t progbuf[RISCV_MAX_PROGBUF_SIZE]; + uint32_t progbuf[RISCV013_MAX_PROGBUF_SIZE]; /* Number of 32-bit instructions in the program. */ - size_t instruction_count; + unsigned int instruction_count; /* execution result of the program */ /* TODO: remove this field. We should make it a parameter to riscv_program_exec */ @@ -52,22 +50,22 @@ int riscv_program_insert(struct riscv_program *p, riscv_insn_t i); /* Helpers to assemble various instructions. Return 0 on success. These might * assemble into a multi-instruction sequence that overwrites some other * register, but those will be properly saved and restored. */ -int riscv_program_ldr(struct riscv_program *p, enum gdb_regno d, enum gdb_regno a, int o); -int riscv_program_lwr(struct riscv_program *p, enum gdb_regno d, enum gdb_regno a, int o); -int riscv_program_lhr(struct riscv_program *p, enum gdb_regno d, enum gdb_regno a, int o); -int riscv_program_lbr(struct riscv_program *p, enum gdb_regno d, enum gdb_regno a, int o); -int riscv_program_load(struct riscv_program *p, enum gdb_regno d, enum gdb_regno b, int o, +int riscv_program_ldr(struct riscv_program *p, enum gdb_regno d, enum gdb_regno a, int16_t o); +int riscv_program_lwr(struct riscv_program *p, enum gdb_regno d, enum gdb_regno a, int16_t o); +int riscv_program_lhr(struct riscv_program *p, enum gdb_regno d, enum gdb_regno a, int16_t o); +int riscv_program_lbr(struct riscv_program *p, enum gdb_regno d, enum gdb_regno a, int16_t o); +int riscv_program_load(struct riscv_program *p, enum gdb_regno d, enum gdb_regno b, int16_t o, unsigned int s); -int riscv_program_sdr(struct riscv_program *p, enum gdb_regno s, enum gdb_regno a, int o); -int riscv_program_swr(struct riscv_program *p, enum gdb_regno s, enum gdb_regno a, int o); -int riscv_program_shr(struct riscv_program *p, enum gdb_regno s, enum gdb_regno a, int o); -int riscv_program_sbr(struct riscv_program *p, enum gdb_regno s, enum gdb_regno a, int o); -int riscv_program_store(struct riscv_program *p, enum gdb_regno d, enum gdb_regno b, int o, +int riscv_program_sdr(struct riscv_program *p, enum gdb_regno s, enum gdb_regno a, int16_t o); +int riscv_program_swr(struct riscv_program *p, enum gdb_regno s, enum gdb_regno a, int16_t o); +int riscv_program_shr(struct riscv_program *p, enum gdb_regno s, enum gdb_regno a, int16_t o); +int riscv_program_sbr(struct riscv_program *p, enum gdb_regno s, enum gdb_regno a, int16_t o); +int riscv_program_store(struct riscv_program *p, enum gdb_regno d, enum gdb_regno b, int16_t o, unsigned int s); -int riscv_program_csrrsi(struct riscv_program *p, enum gdb_regno d, unsigned int z, enum gdb_regno csr); -int riscv_program_csrrci(struct riscv_program *p, enum gdb_regno d, unsigned int z, enum gdb_regno csr); +int riscv_program_csrrsi(struct riscv_program *p, enum gdb_regno d, uint8_t z, enum gdb_regno csr); +int riscv_program_csrrci(struct riscv_program *p, enum gdb_regno d, uint8_t z, enum gdb_regno csr); int riscv_program_csrr(struct riscv_program *p, enum gdb_regno d, enum gdb_regno csr); int riscv_program_csrw(struct riscv_program *p, enum gdb_regno s, enum gdb_regno csr); @@ -77,4 +75,4 @@ int riscv_program_ebreak(struct riscv_program *p); int riscv_program_addi(struct riscv_program *p, enum gdb_regno d, enum gdb_regno s, int16_t i); -#endif +#endif /* OPENOCD_TARGET_RISCV_PROGRAM_H */ diff --git a/src/target/riscv/riscv-011.c b/src/target/riscv/riscv-011.c index 0715de5..54de6a1 100644 --- a/src/target/riscv/riscv-011.c +++ b/src/target/riscv/riscv-011.c @@ -26,7 +26,6 @@ #include "riscv.h" #include "riscv_reg.h" #include "riscv-011_reg.h" -#include "asm.h" #include "gdb_regs.h" #include "field_helpers.h" @@ -251,18 +250,46 @@ static unsigned int slot_offset(const struct target *target, slot_t slot) return 0; /* Silence -Werror=return-type */ } +static uint32_t load(const struct target *target, unsigned int rd, + unsigned int base, int16_t offset) +{ + switch (riscv_xlen(target)) { + case 32: + return lw(rd, base, offset); + case 64: + return ld(rd, base, offset); + } + assert(0); + return 0; /* Silence -Werror=return-type */ +} + +static uint32_t store(const struct target *target, unsigned int src, + unsigned int base, int16_t offset) +{ + switch (riscv_xlen(target)) { + case 32: + return sw(src, base, offset); + case 64: + return sd(src, base, offset); + } + assert(0); + return 0; /* Silence -Werror=return-type */ +} + static uint32_t load_slot(const struct target *target, unsigned int dest, slot_t slot) { unsigned int offset = DEBUG_RAM_START + 4 * slot_offset(target, slot); - return load(target, dest, ZERO, offset); + assert(offset <= MAX_INT12); + return load(target, dest, ZERO, (int16_t)offset); } static uint32_t store_slot(const struct target *target, unsigned int src, slot_t slot) { unsigned int offset = DEBUG_RAM_START + 4 * slot_offset(target, slot); - return store(target, src, ZERO, offset); + assert(offset <= MAX_INT12); + return store(target, src, ZERO, (int16_t)offset); } static uint16_t dram_address(unsigned int index) @@ -273,38 +300,6 @@ static uint16_t dram_address(unsigned int index) return 0x40 + index - 0x10; } -static int dtmcontrol_scan(struct target *target, uint32_t out, uint32_t *in_ptr) -{ - struct scan_field field; - uint8_t in_value[4]; - uint8_t out_value[4] = { 0 }; - - buf_set_u32(out_value, 0, 32, out); - - jtag_add_ir_scan(target->tap, &select_dtmcontrol, TAP_IDLE); - - field.num_bits = 32; - field.out_value = out_value; - field.in_value = in_value; - jtag_add_dr_scan(target->tap, 1, &field, TAP_IDLE); - - /* Always return to dbus. */ - jtag_add_ir_scan(target->tap, &select_dbus, TAP_IDLE); - - int retval = jtag_execute_queue(); - if (retval != ERROR_OK) { - LOG_ERROR("failed jtag scan: %d", retval); - return retval; - } - - uint32_t in = buf_get_u32(field.in_value, 0, 32); - LOG_DEBUG("DTMCONTROL: 0x%x -> 0x%x", out, in); - - if (in_ptr) - *in_ptr = in; - return ERROR_OK; -} - static uint32_t idcode_scan(struct target *target) { struct scan_field field; @@ -340,7 +335,7 @@ static void increase_dbus_busy_delay(struct target *target) info->dtmcontrol_idle, info->dbus_busy_delay, info->interrupt_high_delay); - dtmcontrol_scan(target, DTMCONTROL_DBUS_RESET, NULL /* discard value */); + dtmcs_scan(target->tap, DTMCONTROL_DBUS_RESET, NULL /* discard value */); } static void increase_interrupt_high_delay(struct target *target) @@ -408,7 +403,7 @@ static void dump_field(const struct scan_field *field) log_printf_lf(LOG_LVL_DEBUG, __FILE__, __LINE__, "scan", - "%db %s %c%c:%08x @%02x -> %s %c%c:%08x @%02x", + "%ub %s %c%c:%08x @%02x -> %s %c%c:%08x @%02x", field->num_bits, op_string[out_op], out_interrupt, out_haltnot, out_data, out_address, @@ -475,7 +470,7 @@ static uint64_t dbus_read(struct target *target, uint16_t address) * While somewhat nonintuitive, this is an efficient way to get the data. */ - unsigned i = 0; + unsigned int i = 0; do { status = dbus_scan(target, &address_in, &value, DBUS_OP_READ, address, 0); if (status == DBUS_STATUS_BUSY) @@ -496,7 +491,7 @@ static uint64_t dbus_read(struct target *target, uint16_t address) static void dbus_write(struct target *target, uint16_t address, uint64_t value) { dbus_status_t status = DBUS_STATUS_BUSY; - unsigned i = 0; + unsigned int i = 0; while (status == DBUS_STATUS_BUSY && i++ < 256) { status = dbus_scan(target, NULL, NULL, DBUS_OP_WRITE, address, value); if (status == DBUS_STATUS_BUSY) @@ -606,9 +601,9 @@ static void scans_add_write32(scans_t *scans, uint16_t address, uint32_t data, static void scans_add_write_jump(scans_t *scans, uint16_t address, bool set_interrupt) { - scans_add_write32(scans, address, - jal(0, (uint32_t) (DEBUG_ROM_RESUME - (DEBUG_RAM_START + 4*address))), - set_interrupt); + unsigned int jump_offset = DEBUG_ROM_RESUME - (DEBUG_RAM_START + 4 * address); + assert(jump_offset <= MAX_INT21); + scans_add_write32(scans, address, jal(0, (int32_t)jump_offset), set_interrupt); } /** Add a 32-bit dbus write for an instruction that loads from the indicated @@ -657,13 +652,13 @@ static void scans_add_read(scans_t *scans, slot_t slot, bool set_interrupt) } static uint32_t scans_get_u32(scans_t *scans, unsigned int index, - unsigned first, unsigned num) + unsigned int first, unsigned int num) { return buf_get_u32(scans->in + scans->scan_size * index, first, num); } static uint64_t scans_get_u64(scans_t *scans, unsigned int index, - unsigned first, unsigned num) + unsigned int first, unsigned int num) { return buf_get_u64(scans->in + scans->scan_size * index, first, num); } @@ -695,7 +690,7 @@ static int read_bits(struct target *target, bits_t *result) riscv011_info_t *info = get_info(target); do { - unsigned i = 0; + unsigned int i = 0; do { status = dbus_scan(target, &address_in, &value, DBUS_OP_READ, 0, 0); if (status == DBUS_STATUS_BUSY) { @@ -787,22 +782,25 @@ static void cache_set(struct target *target, slot_t slot, uint64_t data) static void cache_set_jump(struct target *target, unsigned int index) { - cache_set32(target, index, - jal(0, (uint32_t) (DEBUG_ROM_RESUME - (DEBUG_RAM_START + 4*index)))); + unsigned int jump_offset = DEBUG_ROM_RESUME - (DEBUG_RAM_START + 4 * index); + assert(jump_offset <= MAX_INT21); + cache_set32(target, index, jal(0, (int32_t)jump_offset)); } static void cache_set_load(struct target *target, unsigned int index, unsigned int reg, slot_t slot) { - uint16_t offset = DEBUG_RAM_START + 4 * slot_offset(target, slot); - cache_set32(target, index, load(target, reg, ZERO, offset)); + unsigned int offset = DEBUG_RAM_START + 4 * slot_offset(target, slot); + assert(offset <= MAX_INT12); + cache_set32(target, index, load(target, reg, ZERO, (int16_t)offset)); } static void cache_set_store(struct target *target, unsigned int index, unsigned int reg, slot_t slot) { - uint16_t offset = DEBUG_RAM_START + 4 * slot_offset(target, slot); - cache_set32(target, index, store(target, reg, ZERO, offset)); + unsigned int offset = DEBUG_RAM_START + 4 * slot_offset(target, slot); + assert(offset <= MAX_INT12); + cache_set32(target, index, store(target, reg, ZERO, (int16_t)offset)); } static void dump_debug_ram(struct target *target) @@ -1011,9 +1009,9 @@ static uint64_t cache_get(struct target *target, slot_t slot) static void dram_write_jump(struct target *target, unsigned int index, bool set_interrupt) { - dram_write32(target, index, - jal(0, (uint32_t) (DEBUG_ROM_RESUME - (DEBUG_RAM_START + 4*index))), - set_interrupt); + unsigned int jump_offset = DEBUG_ROM_RESUME - (DEBUG_RAM_START + 4 * index); + assert(jump_offset <= MAX_INT21); + dram_write32(target, index, jal(0, (int32_t)jump_offset), set_interrupt); } static int wait_for_state(struct target *target, enum target_state state) @@ -1106,9 +1104,18 @@ static int maybe_write_tselect(struct target *target) return ERROR_OK; } +static uint64_t set_ebreakx_fields(uint64_t dcsr, const struct target *target) +{ + const struct riscv_private_config * const config = riscv_private_config(target); + dcsr = set_field(dcsr, DCSR_EBREAKM, config->dcsr_ebreak_fields[RISCV_MODE_M]); + dcsr = set_field(dcsr, DCSR_EBREAKS, config->dcsr_ebreak_fields[RISCV_MODE_S]); + dcsr = set_field(dcsr, DCSR_EBREAKU, config->dcsr_ebreak_fields[RISCV_MODE_U]); + dcsr = set_field(dcsr, DCSR_EBREAKH, 1); + return dcsr; +} + static int execute_resume(struct target *target, bool step) { - RISCV_INFO(r); riscv011_info_t *info = get_info(target); LOG_DEBUG("step=%d", step); @@ -1140,10 +1147,7 @@ static int execute_resume(struct target *target, bool step) } } - info->dcsr = set_field(info->dcsr, DCSR_EBREAKM, r->riscv_ebreakm); - info->dcsr = set_field(info->dcsr, DCSR_EBREAKS, r->riscv_ebreaks); - info->dcsr = set_field(info->dcsr, DCSR_EBREAKU, r->riscv_ebreaku); - info->dcsr = set_field(info->dcsr, DCSR_EBREAKH, 1); + info->dcsr = set_ebreakx_fields(info->dcsr, target); info->dcsr &= ~DCSR_HALT; if (step) @@ -1168,7 +1172,7 @@ static int execute_resume(struct target *target, bool step) } target->state = TARGET_RUNNING; - register_cache_invalidate(target->reg_cache); + riscv_reg_cache_invalidate_all(target); return ERROR_OK; } @@ -1289,7 +1293,7 @@ static int register_write(struct target *target, unsigned int number, int result = update_mstatus_actual(target); if (result != ERROR_OK) return result; - unsigned i = 0; + unsigned int i = 0; if ((info->mstatus_actual & MSTATUS_FS) == 0) { info->mstatus_actual = set_field(info->mstatus_actual, MSTATUS_FS, 1); cache_set_load(target, i++, S0, SLOT1); @@ -1350,7 +1354,7 @@ int riscv011_get_register(struct target *target, riscv_reg_t *value, int result = update_mstatus_actual(target); if (result != ERROR_OK) return result; - unsigned i = 0; + unsigned int i = 0; if ((info->mstatus_actual & MSTATUS_FS) == 0) { info->mstatus_actual = set_field(info->mstatus_actual, MSTATUS_FS, 1); cache_set_load(target, i++, S0, SLOT1); @@ -1454,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); @@ -1484,7 +1488,7 @@ static int examine(struct target *target) { /* Don't need to select dbus, since the first thing we do is read dtmcontrol. */ uint32_t dtmcontrol; - if (dtmcontrol_scan(target, 0, &dtmcontrol) != ERROR_OK || dtmcontrol == 0) { + if (dtmcs_scan(target->tap, 0, &dtmcontrol) != ERROR_OK || dtmcontrol == 0) { LOG_ERROR("Could not scan dtmcontrol. Check JTAG connectivity/board power."); return ERROR_FAIL; } @@ -1554,7 +1558,7 @@ static int examine(struct target *target) /* 0x00000000 0x00000000:00000003 0x00000000:00000003:ffffffff:ffffffff */ cache_set32(target, 4, sw(S1, ZERO, DEBUG_RAM_START + 4)); cache_set_jump(target, 5); - for (unsigned i = 6; i < info->dramsize; i++) + for (unsigned int i = 6; i < info->dramsize; i++) cache_set32(target, i, i * 0x01020304); cache_write(target, 0, false); @@ -1585,7 +1589,7 @@ static int examine(struct target *target) LOG_DEBUG("Discovered XLEN is %d", riscv_xlen(target)); if (read_remote_csr(target, &r->misa, CSR_MISA) != ERROR_OK) { - const unsigned old_csr_misa = 0xf10; + const unsigned int old_csr_misa = 0xf10; LOG_WARNING("Failed to read misa at 0x%x; trying 0x%x.", CSR_MISA, old_csr_misa); if (read_remote_csr(target, &r->misa, old_csr_misa) != ERROR_OK) { @@ -1664,7 +1668,7 @@ static riscv_error_t handle_halt_routine(struct target *target) unsigned int dbus_busy = 0; unsigned int interrupt_set = 0; - unsigned result = 0; + unsigned int result = 0; uint64_t value = 0; reg_cache_set(target, 0, 0); /* The first scan result is the result from something old we don't care @@ -1885,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) @@ -1948,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); @@ -1960,7 +1973,6 @@ static int riscv011_resume(struct target *target, int current, static int assert_reset(struct target *target) { - RISCV_INFO(r); riscv011_info_t *info = get_info(target); /* TODO: Maybe what I implemented here is more like soft_reset_halt()? */ @@ -1974,10 +1986,7 @@ static int assert_reset(struct target *target) /* Not sure what we should do when there are multiple cores. * Here just reset the single hart we're talking to. */ - info->dcsr = set_field(info->dcsr, DCSR_EBREAKM, r->riscv_ebreakm); - info->dcsr = set_field(info->dcsr, DCSR_EBREAKS, r->riscv_ebreaks); - info->dcsr = set_field(info->dcsr, DCSR_EBREAKU, r->riscv_ebreaku); - info->dcsr = set_field(info->dcsr, DCSR_EBREAKH, 1); + info->dcsr = set_ebreakx_fields(info->dcsr, target); info->dcsr |= DCSR_HALT; if (target->reset_halt) info->dcsr |= DCSR_NDRESET; @@ -2004,9 +2013,16 @@ static int deassert_reset(struct target *target) return wait_for_state(target, TARGET_RUNNING); } -static int read_memory(struct target *target, target_addr_t address, - uint32_t size, uint32_t count, uint8_t *buffer, uint32_t increment) +static int read_memory(struct target *target, const riscv_mem_access_args_t args) { + assert(riscv_mem_access_is_read(args)); + + const target_addr_t address = args.address; + const uint32_t size = args.size; + const uint32_t count = args.count; + const uint32_t increment = args.increment; + uint8_t * const buffer = args.read_buffer; + if (increment != size) { LOG_ERROR("read_memory with custom increment not implemented"); return ERROR_NOT_IMPLEMENTED; @@ -2036,7 +2052,7 @@ static int read_memory(struct target *target, target_addr_t address, cache_write(target, CACHE_NO_READ, false); riscv011_info_t *info = get_info(target); - const unsigned max_batch_size = 256; + const unsigned int max_batch_size = 256; scans_t *scans = scans_new(target, max_batch_size); if (!scans) return ERROR_FAIL; @@ -2174,9 +2190,20 @@ static int setup_write_memory(struct target *target, uint32_t size) return ERROR_OK; } -static int write_memory(struct target *target, target_addr_t address, - uint32_t size, uint32_t count, const uint8_t *buffer) +static int write_memory(struct target *target, const riscv_mem_access_args_t args) { + assert(riscv_mem_access_is_write(args)); + + if (args.increment != args.size) { + LOG_TARGET_ERROR(target, "Write increment size has to be equal to element size"); + return ERROR_NOT_IMPLEMENTED; + } + + const target_addr_t address = args.address; + const uint32_t size = args.size; + const uint32_t count = args.count; + const uint8_t * const buffer = args.write_buffer; + riscv011_info_t *info = get_info(target); jtag_add_ir_scan(target->tap, &select_dbus, TAP_IDLE); @@ -2194,7 +2221,7 @@ static int write_memory(struct target *target, target_addr_t address, if (setup_write_memory(target, size) != ERROR_OK) return ERROR_FAIL; - const unsigned max_batch_size = 256; + const unsigned int max_batch_size = 256; scans_t *scans = scans_new(target, max_batch_size); if (!scans) return ERROR_FAIL; @@ -2312,6 +2339,15 @@ error: return ERROR_FAIL; } +static int access_memory(struct target *target, const riscv_mem_access_args_t args) +{ + assert(riscv_mem_access_is_valid(args)); + const bool is_write = riscv_mem_access_is_write(args); + if (is_write) + return write_memory(target, args); + return read_memory(target, args); +} + static int arch_state(struct target *target) { return ERROR_OK; @@ -2388,15 +2424,27 @@ static int riscv011_authdata_write(struct target *target, uint32_t value, unsign return ERROR_OK; } +static bool riscv011_get_impebreak(const struct target *target) +{ + return false; +} + +static unsigned int riscv011_get_progbufsize(const struct target *target) +{ + return 0; +} + static int init_target(struct command_context *cmd_ctx, struct target *target) { LOG_DEBUG("init"); RISCV_INFO(generic_info); - generic_info->read_memory = read_memory; + generic_info->access_memory = access_memory; generic_info->authdata_read = &riscv011_authdata_read; generic_info->authdata_write = &riscv011_authdata_write; generic_info->print_info = &riscv011_print_info; + generic_info->get_impebreak = &riscv011_get_impebreak; + generic_info->get_progbufsize = &riscv011_get_progbufsize; generic_info->version_specific = calloc(1, sizeof(riscv011_info_t)); if (!generic_info->version_specific) @@ -2426,7 +2474,5 @@ struct target_type riscv011_target = { .assert_reset = assert_reset, .deassert_reset = deassert_reset, - .write_memory = write_memory, - .arch_state = arch_state, }; diff --git a/src/target/riscv/riscv-011.h b/src/target/riscv/riscv-011.h index 8d1d06a..bbbc194 100644 --- a/src/target/riscv/riscv-011.h +++ b/src/target/riscv/riscv-011.h @@ -12,4 +12,4 @@ int riscv011_get_register(struct target *target, riscv_reg_t *value, int riscv011_set_register(struct target *target, enum gdb_regno regid, riscv_reg_t value); -#endif /*OPENOCD_TARGET_RISCV_RISCV_011_H*/ +#endif /* OPENOCD_TARGET_RISCV_RISCV_011_H */ diff --git a/src/target/riscv/riscv-011_reg.c b/src/target/riscv/riscv-011_reg.c index 7f29064..9b72918 100644 --- a/src/target/riscv/riscv-011_reg.c +++ b/src/target/riscv/riscv-011_reg.c @@ -36,21 +36,46 @@ static const struct reg_arch_type *riscv011_gdb_regno_reg_type(uint32_t regno) return &riscv011_reg_type; } -static int riscv011_init_reg(struct target *target, uint32_t regno) -{ - return riscv_reg_impl_init_one(target, regno, riscv011_gdb_regno_reg_type(regno)); -} int riscv011_reg_init_all(struct target *target) { - if (riscv_reg_impl_init_cache(target) != ERROR_OK) - return ERROR_FAIL; + int res = riscv_reg_impl_init_cache(target); + if (res != ERROR_OK) + return res; init_shared_reg_info(target); - for (uint32_t regno = 0; regno < target->reg_cache->num_regs; ++regno) - if (riscv011_init_reg(target, regno) != ERROR_OK) - return ERROR_FAIL; + RISCV_INFO(r); + assert(!r->vlenb + && "VLENB discovery is not supported on RISC-V 0.11 targets"); + /* Existence of some registers depends on others. + * E.g. the presence of "v0-31" registers is infered from "vlenb" being + * non-zero. + * Currently, discovery of the following registers is not supported on + * RISC-V 0.11 targets. */ + uint32_t non_discoverable_regs[] = { + GDB_REGNO_VLENB, + GDB_REGNO_MTOPI, + GDB_REGNO_MTOPEI + }; + for (unsigned int i = 0; i < ARRAY_SIZE(non_discoverable_regs); ++i) { + const uint32_t regno = non_discoverable_regs[i]; + res = riscv_reg_impl_init_cache_entry(target, regno, + /*exist*/ false, riscv011_gdb_regno_reg_type(regno)); + if (res != ERROR_OK) + return res; + } + + for (uint32_t regno = 0; regno < target->reg_cache->num_regs; ++regno) { + const struct reg * const reg = riscv_reg_impl_cache_entry(target, regno); + if (riscv_reg_impl_is_initialized(reg)) + continue; + res = riscv_reg_impl_init_cache_entry(target, regno, + riscv_reg_impl_gdb_regno_exist(target, regno), + riscv011_gdb_regno_reg_type(regno)); + if (res != ERROR_OK) + return res; + } if (riscv_reg_impl_expose_csrs(target) != ERROR_OK) return ERROR_FAIL; diff --git a/src/target/riscv/riscv-011_reg.h b/src/target/riscv/riscv-011_reg.h index ee00c9b..4f7911a 100644 --- a/src/target/riscv/riscv-011_reg.h +++ b/src/target/riscv/riscv-011_reg.h @@ -1,7 +1,7 @@ /* SPDX-License-Identifier: GPL-2.0-or-later */ -#ifndef OPENOCD_TARGET_RISCV_RISCV_REG_011_H -#define OPENOCD_TARGET_RISCV_RISCV_REG_011_H +#ifndef OPENOCD_TARGET_RISCV_RISCV_011_REG_H +#define OPENOCD_TARGET_RISCV_RISCV_011_REG_H #include "target/target.h" @@ -16,4 +16,4 @@ */ int riscv011_reg_init_all(struct target *target); -#endif /*OPENOCD_TARGET_RISCV_RISCV_REG_011_H*/ +#endif /* OPENOCD_TARGET_RISCV_RISCV_011_REG_H */ diff --git a/src/target/riscv/riscv-013.c b/src/target/riscv/riscv-013.c index 7898cae..b5c6bfb 100644 --- a/src/target/riscv/riscv-013.c +++ b/src/target/riscv/riscv-013.c @@ -6,6 +6,7 @@ */ #include <assert.h> +#include <stdint.h> #include <stdlib.h> #include <time.h> @@ -16,6 +17,7 @@ #include "target/target.h" #include "target/algorithm.h" #include "target/target_type.h" +#include <helper/align.h> #include <helper/log.h> #include "jtag/jtag.h" #include "target/register.h" @@ -29,7 +31,6 @@ #include "debug_defines.h" #include "rtos/rtos.h" #include "program.h" -#include "asm.h" #include "batch.h" #include "debug_reg_printer.h" #include "field_helpers.h" @@ -54,22 +55,18 @@ static riscv_insn_t riscv013_read_progbuf(struct target *target, unsigned int index); static int riscv013_invalidate_cached_progbuf(struct target *target); static int riscv013_execute_progbuf(struct target *target, uint32_t *cmderr); -static void riscv013_fill_dmi_write(struct target *target, char *buf, uint64_t a, uint32_t d); -static void riscv013_fill_dmi_read(struct target *target, char *buf, uint64_t a); -static void riscv013_fill_dmi_nop(struct target *target, char *buf); -static int riscv013_get_dmi_scan_length(struct target *target); -static void riscv013_fill_dm_write(struct target *target, char *buf, uint64_t a, uint32_t d); -static void riscv013_fill_dm_read(struct target *target, char *buf, uint64_t a); -static void riscv013_fill_dm_nop(struct target *target, char *buf); +static void riscv013_fill_dmi_write(const struct target *target, uint8_t *buf, uint32_t a, uint32_t d); +static void riscv013_fill_dmi_read(const struct target *target, uint8_t *buf, uint32_t a); +static unsigned int riscv013_get_dmi_address_bits(const struct target *target); +static void riscv013_fill_dm_nop(const struct target *target, uint8_t *buf); static unsigned int register_size(struct target *target, enum gdb_regno number); static int register_read_direct(struct target *target, riscv_reg_t *value, enum gdb_regno number); static int register_write_direct(struct target *target, enum gdb_regno number, riscv_reg_t value); -static int read_memory(struct target *target, target_addr_t address, - uint32_t size, uint32_t count, uint8_t *buffer, uint32_t increment); -static int write_memory(struct target *target, target_addr_t address, - uint32_t size, uint32_t count, const uint8_t *buffer); +static int riscv013_access_memory(struct target *target, const riscv_mem_access_args_t args); +static bool riscv013_get_impebreak(const struct target *target); +static unsigned int riscv013_get_progbufsize(const struct target *target); typedef enum { HALT_GROUP, @@ -115,7 +112,7 @@ typedef enum { typedef struct { struct list_head list; - int abs_chain_position; + unsigned int abs_chain_position; /* The base address to access this DM on DMI */ uint32_t base; /* The number of harts connected to this DM. */ @@ -148,15 +145,77 @@ 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 index; + unsigned int index; /* Number of address bits in the dbus register. */ - unsigned abits; + unsigned int abits; /* Number of abstract command data registers. */ - unsigned datacount; + unsigned int datacount; /* Number of words in the Program Buffer. */ - unsigned progbufsize; + unsigned int progbufsize; + /* Hart contains an implicit ebreak at the end of the program buffer. */ + bool impebreak; /* We cache the read-only bits of sbcs here. */ uint32_t sbcs; @@ -176,18 +235,16 @@ 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; uint8_t dataaccess; int16_t dataaddr; + /* The width of the hartsel field. */ + unsigned int hartsellen; + /* DM that provides access to this target. */ dm013_info_t *dm; @@ -202,7 +259,7 @@ typedef struct { bool haltgroup_supported; } riscv013_info_t; -static LIST_HEAD(dm_list); +static OOCD_LIST_HEAD(dm_list); static riscv013_info_t *get_info(const struct target *target) { @@ -223,7 +280,7 @@ static dm013_info_t *get_dm(struct target *target) if (info->dm) return info->dm; - int abs_chain_position = target->tap->abs_chain_position; + unsigned int abs_chain_position = target->tap->abs_chain_position; dm013_info_t *entry; dm013_info_t *dm = NULL; @@ -347,133 +404,45 @@ static uint32_t set_dmcontrol_hartsel(uint32_t initial, int hart_index) return initial; } -static unsigned int decode_dmi(const struct target *target, char *text, uint32_t address, uint32_t data) -{ - static const struct { - uint32_t address; - enum riscv_debug_reg_ordinal ordinal; - } description[] = { - {DM_DMCONTROL, DM_DMCONTROL_ORDINAL}, - {DM_DMSTATUS, DM_DMSTATUS_ORDINAL}, - {DM_ABSTRACTCS, DM_ABSTRACTCS_ORDINAL}, - {DM_COMMAND, DM_COMMAND_ORDINAL}, - {DM_SBCS, DM_SBCS_ORDINAL} - }; - - for (unsigned i = 0; i < ARRAY_SIZE(description); i++) { - if (riscv_get_dmi_address(target, description[i].address) == address) { - const riscv_debug_reg_ctx_t context = { - .XLEN = { .value = 0, .is_set = false }, - .DXLEN = { .value = 0, .is_set = false }, - .abits = { .value = 0, .is_set = false }, - }; - return riscv_debug_reg_to_s(text, description[i].ordinal, - context, data, RISCV_DEBUG_REG_HIDE_ALL_0); - } - } - if (text) - text[0] = '\0'; - return 0; -} - -void riscv_log_dmi_scan(const struct target *target, int idle, const struct scan_field *field, bool discard_in) -{ - static const char * const op_string[] = {"-", "r", "w", "?"}; - static const char * const status_string[] = {"+", "?", "F", "b"}; - - if (debug_level < LOG_LVL_DEBUG) - return; - - assert(field->out_value); - const uint64_t out = buf_get_u64(field->out_value, 0, field->num_bits); - const unsigned int out_op = get_field(out, DTM_DMI_OP); - const uint32_t out_data = get_field(out, DTM_DMI_DATA); - const uint32_t out_address = out >> DTM_DMI_ADDRESS_OFFSET; - - if (field->in_value) { - const uint64_t in = buf_get_u64(field->in_value, 0, field->num_bits); - const unsigned int in_op = get_field(in, DTM_DMI_OP); - const uint32_t in_data = get_field(in, DTM_DMI_DATA); - const uint32_t in_address = in >> DTM_DMI_ADDRESS_OFFSET; - - LOG_DEBUG("%db %s %08" PRIx32 " @%02" PRIx32 " -> %s %08" PRIx32 " @%02" PRIx32 "; %di", - field->num_bits, op_string[out_op], out_data, out_address, - status_string[in_op], in_data, in_address, idle); - - if (!discard_in && in_op == DTM_DMI_OP_SUCCESS) { - char in_decoded[decode_dmi(target, NULL, in_address, in_data) + 1]; - decode_dmi(target, in_decoded, in_address, in_data); - /* FIXME: The current code assumes that the hardware - * provides the read address in the dmi.address field - * when returning the dmi.data. That is however not - * required by the spec, and therefore not guaranteed. - * See https://github.com/riscv-collab/riscv-openocd/issues/1043 - */ - LOG_DEBUG("read: %s", in_decoded); - } - } else { - LOG_DEBUG("%db %s %08" PRIx32 " @%02" PRIx32 " -> ?; %di", - field->num_bits, op_string[out_op], out_data, out_address, - idle); - } - if (out_op == DTM_DMI_OP_WRITE) { - char out_decoded[decode_dmi(target, NULL, out_address, out_data) + 1]; - decode_dmi(target, out_decoded, out_address, out_data); - LOG_DEBUG("write: %s", out_decoded); - } -} - /*** Utility functions. ***/ -static void select_dmi(struct target *target) +static void select_dmi(struct jtag_tap *tap) { if (bscan_tunnel_ir_width != 0) { - select_dmi_via_bscan(target); + select_dmi_via_bscan(tap); return; } - jtag_add_ir_scan(target->tap, &select_dbus, TAP_IDLE); -} - -static int dtmcontrol_scan(struct target *target, uint32_t out, uint32_t *in_ptr) -{ - struct scan_field field; - uint8_t in_value[4]; - uint8_t out_value[4] = { 0 }; - - if (bscan_tunnel_ir_width != 0) - return dtmcontrol_scan_via_bscan(target, out, in_ptr); - - buf_set_u32(out_value, 0, 32, out); - - jtag_add_ir_scan(target->tap, &select_dtmcontrol, TAP_IDLE); - - field.num_bits = 32; - field.out_value = out_value; - field.in_value = in_value; - jtag_add_dr_scan(target->tap, 1, &field, TAP_IDLE); - - /* Always return to dmi. */ - select_dmi(target); - - int retval = jtag_execute_queue(); - if (retval != ERROR_OK) { - LOG_ERROR("failed jtag scan: %d", retval); - return retval; + if (!tap->enabled) + LOG_ERROR("BUG: Target's TAP '%s' is disabled!", jtag_tap_name(tap)); + + bool need_ir_scan = false; + /* FIXME: make "tap" a const pointer. */ + for (struct jtag_tap *other_tap = jtag_tap_next_enabled(NULL); + other_tap; other_tap = jtag_tap_next_enabled(other_tap)) { + if (other_tap != tap) { + /* Different TAP than ours - check if it is in bypass */ + if (!other_tap->bypass) { + need_ir_scan = true; + break; + } + } else { + /* Our TAP - check if the correct instruction is already loaded */ + if (!buf_eq(tap->cur_instr, select_dbus.out_value, tap->ir_length)) { + need_ir_scan = true; + break; + } + } } - uint32_t in = buf_get_u32(field.in_value, 0, 32); - LOG_DEBUG("DTMCS: 0x%x -> 0x%x", out, in); - - if (in_ptr) - *in_ptr = in; - return ERROR_OK; + if (need_ir_scan) + jtag_add_ir_scan(tap, &select_dbus, TAP_IDLE); } static int increase_dmi_busy_delay(struct target *target) { RISCV013_INFO(info); - int res = dtmcontrol_scan(target, DTM_DTMCS_DMIRESET, + int res = dtmcs_scan(target->tap, DTM_DTMCS_DMIRESET, NULL /* discard result */); if (res != ERROR_OK) return res; @@ -506,220 +475,6 @@ static void decrement_reset_delays_counter(struct target *target, size_t finishe "resetting learned delays (reset_delays_wait counter expired)"); reset_learned_delays(target); } -/** - * exec: If this is set, assume the scan results in an execution, so more - * run-test/idle cycles may be required. - */ -static dmi_status_t dmi_scan(struct target *target, uint32_t *address_in, - uint32_t *data_in, dmi_op_t op, uint32_t address_out, uint32_t data_out, - bool exec) -{ - riscv013_info_t *info = get_info(target); - unsigned num_bits = info->abits + DTM_DMI_OP_LENGTH + DTM_DMI_DATA_LENGTH; - size_t num_bytes = (num_bits + 7) / 8; - uint8_t in[num_bytes]; - uint8_t out[num_bytes]; - struct scan_field field = { - .num_bits = num_bits, - .out_value = out, - .in_value = in - }; - riscv_bscan_tunneled_scan_context_t bscan_ctxt; - - decrement_reset_delays_counter(target, 1); - - memset(in, 0, num_bytes); - memset(out, 0, num_bytes); - - if (info->abits == 0) { - LOG_TARGET_ERROR(target, "Can't access DMI because addrbits=0."); - return DMI_STATUS_FAILED; - } - - buf_set_u32(out, DTM_DMI_OP_OFFSET, DTM_DMI_OP_LENGTH, op); - buf_set_u32(out, DTM_DMI_DATA_OFFSET, DTM_DMI_DATA_LENGTH, data_out); - buf_set_u32(out, DTM_DMI_ADDRESS_OFFSET, info->abits, address_out); - - /* I wanted to place this code in a different function, but the way JTAG command - queueing works in the jtag handling functions, the scan fields either have to be - heap allocated, global/static, or else they need to stay on the stack until - the jtag_execute_queue() call. Heap or static fields in this case doesn't seem - the best fit. Declaring stack based field values in a subsidiary function call wouldn't - work. */ - if (bscan_tunnel_ir_width != 0) { - riscv_add_bscan_tunneled_scan(target, &field, &bscan_ctxt); - } else { - /* Assume dbus is already selected. */ - jtag_add_dr_scan(target->tap, 1, &field, TAP_IDLE); - } - - int idle_count = exec - ? riscv_scan_get_delay(&info->learned_delays, RISCV_DELAY_ABSTRACT_COMMAND) - : riscv_scan_get_delay(&info->learned_delays, RISCV_DELAY_BASE); - - if (idle_count) - jtag_add_runtest(idle_count, TAP_IDLE); - - int retval = jtag_execute_queue(); - if (retval != ERROR_OK) { - LOG_ERROR("dmi_scan failed jtag scan"); - if (data_in) - *data_in = ~0; - return DMI_STATUS_FAILED; - } - - if (bscan_tunnel_ir_width != 0) { - /* need to right-shift "in" by one bit, because of clock skew between BSCAN TAP and DM TAP */ - buffer_shr(in, num_bytes, 1); - } - - if (data_in) - *data_in = buf_get_u32(in, DTM_DMI_DATA_OFFSET, DTM_DMI_DATA_LENGTH); - - if (address_in) - *address_in = buf_get_u32(in, DTM_DMI_ADDRESS_OFFSET, info->abits); - riscv_log_dmi_scan(target, idle_count, &field, /*discard_in*/ !data_in); - return buf_get_u32(in, DTM_DMI_OP_OFFSET, DTM_DMI_OP_LENGTH); -} - -/** - * @param target - * @param data_in The data we received from the target. - * @param dmi_busy_encountered - * If non-NULL, will be updated to reflect whether DMI busy was - * encountered while executing this operation or not. - * @param op The operation to perform (read/write/nop). - * @param address The address argument to that operation. - * @param data_out The data to send to the target. - * @param timeout_sec - * @param exec When true, this scan will execute something, so extra RTI - * cycles may be added. - * @param ensure_success - * Scan a nop after the requested operation, ensuring the - * DMI operation succeeded. - */ -static int dmi_op_timeout(struct target *target, uint32_t *data_in, - bool *dmi_busy_encountered, int op, uint32_t address, - uint32_t data_out, int timeout_sec, bool exec, bool ensure_success) -{ - select_dmi(target); - - dmi_status_t status; - - if (dmi_busy_encountered) - *dmi_busy_encountered = false; - - const char *op_name; - switch (op) { - case DMI_OP_NOP: - op_name = "nop"; - break; - case DMI_OP_READ: - op_name = "read"; - break; - case DMI_OP_WRITE: - op_name = "write"; - break; - default: - LOG_ERROR("Invalid DMI operation: %d", op); - return ERROR_FAIL; - } - - keep_alive(); - - time_t start = time(NULL); - /* This first loop performs the request. Note that if for some reason this - * stays busy, it is actually due to the previous access. */ - while (1) { - status = dmi_scan(target, NULL, NULL, op, address, data_out, - exec); - if (status == DMI_STATUS_BUSY) { - int result = increase_dmi_busy_delay(target); - if (result != ERROR_OK) - return result; - if (dmi_busy_encountered) - *dmi_busy_encountered = true; - } else if (status == DMI_STATUS_SUCCESS) { - break; - } else { - dtmcontrol_scan(target, DTM_DTMCS_DMIRESET, NULL /* discard result */); - break; - } - if (time(NULL) - start > timeout_sec) - return ERROR_TIMEOUT_REACHED; - } - - if (status != DMI_STATUS_SUCCESS) { - LOG_TARGET_ERROR(target, "Failed DMI %s at 0x%x; status=%d", op_name, address, status); - return ERROR_FAIL; - } - - if (ensure_success) { - /* This second loop ensures the request succeeded, and gets back data. - * Note that NOP can result in a 'busy' result as well, but that would be - * noticed on the next DMI access we do. */ - while (1) { - status = dmi_scan(target, NULL, data_in, DMI_OP_NOP, address, 0, - false); - if (status == DMI_STATUS_BUSY) { - int result = increase_dmi_busy_delay(target); - if (result != ERROR_OK) - return result; - if (dmi_busy_encountered) - *dmi_busy_encountered = true; - } else if (status == DMI_STATUS_SUCCESS) { - break; - } else { - if (data_in) { - LOG_TARGET_ERROR(target, - "Failed DMI %s (NOP) at 0x%x; value=0x%x, status=%d", - op_name, address, *data_in, status); - } else { - LOG_TARGET_ERROR(target, - "Failed DMI %s (NOP) at 0x%x; status=%d", op_name, address, - status); - } - dtmcontrol_scan(target, DTM_DTMCS_DMIRESET, NULL /* discard result */); - return ERROR_FAIL; - } - if (time(NULL) - start > timeout_sec) - return ERROR_TIMEOUT_REACHED; - } - } - - return ERROR_OK; -} - -static int dmi_op(struct target *target, uint32_t *data_in, - bool *dmi_busy_encountered, int op, uint32_t address, - uint32_t data_out, bool exec, bool ensure_success) -{ - int result = dmi_op_timeout(target, data_in, dmi_busy_encountered, op, - address, data_out, riscv_get_command_timeout_sec(), exec, ensure_success); - if (result == ERROR_TIMEOUT_REACHED) { - LOG_TARGET_ERROR(target, "DMI operation didn't complete in %d seconds. The target is " - "either really slow or broken. You could increase the " - "timeout with riscv set_command_timeout_sec.", - riscv_get_command_timeout_sec()); - return ERROR_FAIL; - } - return result; -} - -static int dmi_read(struct target *target, uint32_t *value, uint32_t address) -{ - return dmi_op(target, value, NULL, DMI_OP_READ, address, 0, false, true); -} - -static int dmi_read_exec(struct target *target, uint32_t *value, uint32_t address) -{ - return dmi_op(target, value, NULL, DMI_OP_READ, address, 0, true, true); -} - -static int dmi_write(struct target *target, uint32_t address, uint32_t value) -{ - return dmi_op(target, NULL, NULL, DMI_OP_WRITE, address, value, false, true); -} static uint32_t riscv013_get_dmi_address(const struct target *target, uint32_t address) { @@ -731,23 +486,22 @@ static uint32_t riscv013_get_dmi_address(const struct target *target, uint32_t a return address + base; } -static int dm_op(struct target *target, uint32_t *data_in, - bool *dmi_busy_encountered, int op, uint32_t address, - uint32_t data_out, bool exec, bool ensure_success) +static int batch_run_timeout(struct target *target, struct riscv_batch *batch); + +static int dmi_read(struct target *target, uint32_t *value, uint32_t address) { - dm013_info_t *dm = get_dm(target); - if (!dm) - return ERROR_FAIL; - return dmi_op(target, data_in, dmi_busy_encountered, op, address + dm->base, - data_out, exec, ensure_success); + struct riscv_batch *batch = riscv_batch_alloc(target, 1); + riscv_batch_add_dmi_read(batch, address, RISCV_DELAY_BASE); + int res = batch_run_timeout(target, batch); + if (res == ERROR_OK && value) + *value = riscv_batch_get_dmi_read_data(batch, 0); + riscv_batch_free(batch); + return res; } static int dm_read(struct target *target, uint32_t *value, uint32_t address) { - dm013_info_t *dm = get_dm(target); - if (!dm) - return ERROR_FAIL; - return dmi_read(target, value, address + dm->base); + return dmi_read(target, value, riscv013_get_dmi_address(target, address)); } static int dm_read_exec(struct target *target, uint32_t *value, uint32_t address) @@ -755,22 +509,36 @@ static int dm_read_exec(struct target *target, uint32_t *value, uint32_t address dm013_info_t *dm = get_dm(target); if (!dm) return ERROR_FAIL; + struct riscv_batch *batch = riscv_batch_alloc(target, 1); + riscv_batch_add_dm_read(batch, address, RISCV_DELAY_ABSTRACT_COMMAND); dm->abstract_cmd_maybe_busy = true; - return dmi_read_exec(target, value, address + dm->base); + int res = batch_run_timeout(target, batch); + if (res == ERROR_OK && value) + *value = riscv_batch_get_dmi_read_data(batch, 0); + riscv_batch_free(batch); + return res; +} + +static int dmi_write(struct target *target, uint32_t address, uint32_t value) +{ + struct riscv_batch *batch = riscv_batch_alloc(target, 1); + riscv_batch_add_dmi_write(batch, address, value, /*read_back*/ true, + RISCV_DELAY_BASE); + int res = batch_run_timeout(target, batch); + riscv_batch_free(batch); + return res; } static int dm_write(struct target *target, uint32_t address, uint32_t value) { - dm013_info_t *dm = get_dm(target); - if (!dm) - return ERROR_FAIL; - return dmi_write(target, address + dm->base, value); + return dmi_write(target, riscv013_get_dmi_address(target, address), value); } static bool check_dbgbase_exists(struct target *target) { 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) { @@ -785,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); @@ -822,7 +596,7 @@ static int increase_ac_busy_delay(struct target *target) RISCV_DELAY_ABSTRACT_COMMAND); } -static uint32_t __attribute__((unused)) abstract_register_size(unsigned width) +static uint32_t __attribute__((unused)) abstract_register_size(unsigned int width) { switch (width) { case 32: @@ -915,6 +689,15 @@ static int abstract_cmd_batch_check_and_clear_cmderr(struct target *target, if (res != ERROR_OK) goto clear_cmderr; } + + dm013_info_t * const dm = get_dm(target); + if (!dm) { + LOG_ERROR("BUG: Target %s is not assigned to any RISC-V debug module", + target_name(target)); + return ERROR_FAIL; + } + dm->abstract_cmd_maybe_busy = false; + *cmderr = get_field32(abstractcs, DM_ABSTRACTCS_CMDERR); if (*cmderr == CMDERR_NONE) return ERROR_OK; @@ -930,9 +713,31 @@ clear_cmderr: return res; } -static int batch_run_timeout(struct target *target, struct riscv_batch *batch); +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 int execute_abstract_command(struct target *target, uint32_t command, +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) { assert(cmderr); @@ -965,6 +770,9 @@ static int 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; @@ -1048,10 +856,10 @@ static void abstract_data_write_fill_batch(struct riscv_batch *batch, } /* TODO: reuse "abstract_data_write_fill_batch()" here*/ -static int write_abstract_arg(struct target *target, unsigned index, - riscv_reg_t value, unsigned size_bits) +static int write_abstract_arg(struct target *target, unsigned int index, + riscv_reg_t value, unsigned int size_bits) { - unsigned offset = index * size_bits / 32; + unsigned int offset = index * size_bits / 32; switch (size_bits) { default: LOG_TARGET_ERROR(target, "Unsupported size: %d bits", size_bits); @@ -1068,8 +876,8 @@ static int write_abstract_arg(struct target *target, unsigned index, /** * @par size in bits */ -static uint32_t access_register_command(struct target *target, uint32_t number, - unsigned size, uint32_t flags) +uint32_t riscv013_access_register_command(struct target *target, uint32_t number, + unsigned int size, uint32_t flags) { uint32_t command = set_field(0, DM_COMMAND_CMDTYPE, 0); switch (size) { @@ -1110,38 +918,35 @@ static uint32_t 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 = access_register_command(target, number, size, + 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 = 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."); - } - } + int result = riscv013_execute_abstract_command(target, command, &cmderr); + if (result != ERROR_OK) return result; - } if (value) return read_abstract_arg(target, value, 0, size); @@ -1160,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 = access_register_command(target, number, size_bits, + const uint32_t command = riscv013_access_register_command(target, number, size_bits, AC_ACCESS_REGISTER_TRANSFER | AC_ACCESS_REGISTER_WRITE); + 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; @@ -1196,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; @@ -1217,7 +1007,7 @@ cleanup: * Sets the AAMSIZE field of a memory access abstract command based on * the width (bits). */ -static uint32_t abstract_memory_size(unsigned width) +static uint32_t abstract_memory_size(unsigned int width) { switch (width) { case 8: @@ -1399,7 +1189,7 @@ typedef struct { static int scratch_reserve(struct target *target, scratch_mem_t *scratch, struct riscv_program *program, - unsigned size_bytes) + unsigned int size_bytes) { riscv_addr_t alignment = 1; while (alignment < size_bytes) @@ -1431,7 +1221,7 @@ static int scratch_reserve(struct target *target, return ERROR_FAIL; /* Allow for ebreak at the end of the program. */ - unsigned program_size = (program->instruction_count + 1) * 4; + unsigned int program_size = (program->instruction_count + 1) * 4; scratch->hart_address = (info->progbuf_address + program_size + alignment - 1) & ~(alignment - 1); if ((info->progbuf_writable == YNM_YES) && @@ -1487,16 +1277,17 @@ static int scratch_read64(struct target *target, scratch_mem_t *scratch, case SPACE_DMI_RAM: { uint8_t buffer[8] = {0}; - if (read_memory(target, scratch->debug_address, 4, 2, buffer, 4) != ERROR_OK) + const riscv_mem_access_args_t args = { + .address = scratch->debug_address, + .read_buffer = buffer, + .size = 4, + .count = 2, + .increment = 4, + }; + if (riscv013_access_memory(target, args) != ERROR_OK) return ERROR_FAIL; - *value = buffer[0] | - (((uint64_t) buffer[1]) << 8) | - (((uint64_t) buffer[2]) << 16) | - (((uint64_t) buffer[3]) << 24) | - (((uint64_t) buffer[4]) << 32) | - (((uint64_t) buffer[5]) << 40) | - (((uint64_t) buffer[6]) << 48) | - (((uint64_t) buffer[7]) << 56); + *value = buf_get_u64(buffer, + /* first = */ 0, /* bit_num = */ 64); } break; } @@ -1528,7 +1319,14 @@ static int scratch_write64(struct target *target, scratch_mem_t *scratch, value >> 48, value >> 56 }; - if (write_memory(target, scratch->debug_address, 4, 2, buffer) != ERROR_OK) + const riscv_mem_access_args_t args = { + .address = scratch->debug_address, + .write_buffer = buffer, + .size = 4, + .count = 2, + .increment = 4, + }; + if (riscv013_access_memory(target, args) != ERROR_OK) return ERROR_FAIL; } break; @@ -1547,12 +1345,10 @@ static unsigned int register_size(struct target *target, enum gdb_regno number) return riscv_xlen(target); } -static bool has_sufficient_progbuf(struct target *target, unsigned size) +static bool has_sufficient_progbuf(struct target *target, unsigned int size) { RISCV013_INFO(info); - RISCV_INFO(r); - - return info->progbufsize + r->impebreak >= size; + return info->progbufsize + info->impebreak >= size; } /** @@ -1892,7 +1688,6 @@ static int set_dcsr_ebreak(struct target *target, bool step) if (dm013_select_target(target) != ERROR_OK) return ERROR_FAIL; - RISCV_INFO(r); RISCV013_INFO(info); riscv_reg_t original_dcsr, dcsr; /* We want to twiddle some bits in the debug CSR so debugging works. */ @@ -1900,11 +1695,12 @@ static int set_dcsr_ebreak(struct target *target, bool step) return ERROR_FAIL; original_dcsr = dcsr; dcsr = set_field(dcsr, CSR_DCSR_STEP, step); - dcsr = set_field(dcsr, CSR_DCSR_EBREAKM, r->riscv_ebreakm); - dcsr = set_field(dcsr, CSR_DCSR_EBREAKS, r->riscv_ebreaks && riscv_supports_extension(target, 'S')); - dcsr = set_field(dcsr, CSR_DCSR_EBREAKU, r->riscv_ebreaku && riscv_supports_extension(target, 'U')); - dcsr = set_field(dcsr, CSR_DCSR_EBREAKVS, r->riscv_ebreaku && riscv_supports_extension(target, 'H')); - dcsr = set_field(dcsr, CSR_DCSR_EBREAKVU, r->riscv_ebreaku && riscv_supports_extension(target, 'H')); + const struct riscv_private_config * const config = riscv_private_config(target); + dcsr = set_field(dcsr, CSR_DCSR_EBREAKM, config->dcsr_ebreak_fields[RISCV_MODE_M]); + dcsr = set_field(dcsr, CSR_DCSR_EBREAKS, config->dcsr_ebreak_fields[RISCV_MODE_S]); + dcsr = set_field(dcsr, CSR_DCSR_EBREAKU, config->dcsr_ebreak_fields[RISCV_MODE_U]); + dcsr = set_field(dcsr, CSR_DCSR_EBREAKVS, config->dcsr_ebreak_fields[RISCV_MODE_VS]); + dcsr = set_field(dcsr, CSR_DCSR_EBREAKVU, config->dcsr_ebreak_fields[RISCV_MODE_VU]); if (dcsr != original_dcsr && riscv_reg_set(target, GDB_REGNO_DCSR, dcsr) != ERROR_OK) return ERROR_FAIL; @@ -1984,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); @@ -2202,7 +2002,7 @@ static int examine(struct target *target) LOG_TARGET_DEBUG(target, "dbgbase=0x%x", target->dbgbase); uint32_t dtmcontrol; - if (dtmcontrol_scan(target, 0, &dtmcontrol) != ERROR_OK || dtmcontrol == 0) { + if (dtmcs_scan(target->tap, 0, &dtmcontrol) != ERROR_OK || dtmcontrol == 0) { LOG_TARGET_ERROR(target, "Could not scan dtmcontrol. Check JTAG connectivity/board power."); return ERROR_FAIL; } @@ -2222,6 +2022,34 @@ static int examine(struct target *target) info->abits = get_field(dtmcontrol, DTM_DTMCS_ABITS); info->dtmcs_idle = get_field(dtmcontrol, DTM_DTMCS_IDLE); + if (info->abits > RISCV013_DTMCS_ABITS_MAX) { + /* Max. address width given by the debug specification is exceeded */ + LOG_TARGET_ERROR(target, "The target's debug bus (DMI) address width exceeds " + "the maximum:"); + LOG_TARGET_ERROR(target, " found dtmcs.abits = %d; maximum is abits = %d.", + info->abits, RISCV013_DTMCS_ABITS_MAX); + return ERROR_FAIL; + } + + if (info->abits == 0) { + LOG_TARGET_ERROR(target, + "dtmcs.abits is zero. Check JTAG connectivity/board power"); + return ERROR_FAIL; + } + if (info->abits < RISCV013_DTMCS_ABITS_MIN) { + /* The requirement for minimum DMI address width of 7 bits is part of + * the RISC-V Debug spec since Jan-20-2017 (commit 03df6ee7). However, + * implementations exist that implement narrower DMI address. For example + * Spike as of Q1/2025 uses dmi.abits = 6. + * + * For that reason, warn the user but continue. + */ + LOG_TARGET_WARNING(target, "The target's debug bus (DMI) address width is " + "lower than the minimum:"); + LOG_TARGET_WARNING(target, " found dtmcs.abits = %d; minimum is abits = %d.", + info->abits, RISCV013_DTMCS_ABITS_MIN); + } + if (!check_dbgbase_exists(target)) { LOG_TARGET_ERROR(target, "Could not find debug module with DMI base address (dbgbase) = 0x%x", target->dbgbase); return ERROR_FAIL; @@ -2277,21 +2105,13 @@ static int examine(struct target *target) LOG_TARGET_INFO(target, "datacount=%d progbufsize=%d", info->datacount, info->progbufsize); - RISCV_INFO(r); - r->impebreak = get_field(dmstatus, DM_DMSTATUS_IMPEBREAK); + info->impebreak = get_field(dmstatus, DM_DMSTATUS_IMPEBREAK); if (!has_sufficient_progbuf(target, 2)) { LOG_TARGET_WARNING(target, "We won't be able to execute fence instructions on this " "target. Memory may not always appear consistent. " "(progbufsize=%d, impebreak=%d)", info->progbufsize, - r->impebreak); - } - - if (info->progbufsize < 4 && riscv_enable_virtual) { - LOG_TARGET_ERROR(target, "set_enable_virtual is not available on this target. It " - "requires a program buffer size of at least 4. (progbufsize=%d) " - "Use `riscv set_enable_virtual off` to continue." - , info->progbufsize); + info->impebreak); } /* Don't call any riscv_* functions until after we've counted the number of @@ -2300,6 +2120,8 @@ static int examine(struct target *target) enum riscv_hart_state state_at_examine_start; if (riscv_get_hart_state(target, &state_at_examine_start) != ERROR_OK) return ERROR_FAIL; + + RISCV_INFO(r); const bool hart_halted_at_examine_start = state_at_examine_start == RISCV_STATE_HALTED; if (!hart_halted_at_examine_start) { r->prepped = true; @@ -2313,74 +2135,9 @@ static int examine(struct target *target) target->state = TARGET_HALTED; target->debug_reason = hart_halted_at_examine_start ? DBG_REASON_UNDEFINED : DBG_REASON_DBGRQ; - /* Without knowing anything else we can at least mess with the - * program buffer. */ - r->progbuf_size = info->progbufsize; - - result = register_read_abstract_with_size(target, NULL, GDB_REGNO_S0, 64); - if (result == ERROR_OK) - r->xlen = 64; - else - r->xlen = 32; - - /* Save s0 and s1. The register cache hasn't be initialized yet so we - * need to take care of this manually. */ - uint64_t s0, s1; - if (register_read_abstract(target, &s0, GDB_REGNO_S0) != ERROR_OK) { - LOG_TARGET_ERROR(target, "Fatal: Failed to read s0."); - return ERROR_FAIL; - } - if (register_read_abstract(target, &s1, GDB_REGNO_S1) != ERROR_OK) { - LOG_TARGET_ERROR(target, "Fatal: Failed to read s1."); - return ERROR_FAIL; - } - - if (register_read_direct(target, &r->misa, GDB_REGNO_MISA)) { - LOG_TARGET_ERROR(target, "Fatal: Failed to read MISA."); - return ERROR_FAIL; - } - - uint64_t value; - if (register_read_direct(target, &value, GDB_REGNO_VLENB) != ERROR_OK) { - if (riscv_supports_extension(target, 'V')) - LOG_TARGET_WARNING(target, "Couldn't read vlenb; vector register access won't work."); - r->vlenb = 0; - } else { - r->vlenb = value; - LOG_TARGET_INFO(target, "Vector support with vlenb=%d", r->vlenb); - } - - if (register_read_direct(target, &value, GDB_REGNO_MTOPI) == ERROR_OK) { - r->mtopi_readable = true; - - if (register_read_direct(target, &value, GDB_REGNO_MTOPEI) == ERROR_OK) { - LOG_TARGET_INFO(target, "S?aia detected with IMSIC"); - r->mtopei_readable = true; - } else { - r->mtopei_readable = false; - LOG_TARGET_INFO(target, "S?aia detected without IMSIC"); - } - } else { - r->mtopi_readable = false; - } - - /* Display this as early as possible to help people who are using - * really slow simulators. */ - LOG_TARGET_DEBUG(target, " XLEN=%d, misa=0x%" PRIx64, r->xlen, r->misa); - - /* Restore s0 and s1. */ - if (register_write_direct(target, GDB_REGNO_S0, s0) != ERROR_OK) { - LOG_TARGET_ERROR(target, "Fatal: Failed to write back s0."); - return ERROR_FAIL; - } - if (register_write_direct(target, GDB_REGNO_S1, s1) != ERROR_OK) { - LOG_TARGET_ERROR(target, "Fatal: Failed to write back s1."); - return ERROR_FAIL; - } - - /* Now init registers based on what we discovered. */ - if (riscv013_reg_init_all(target) != ERROR_OK) - return ERROR_FAIL; + result = riscv013_reg_examine_all(target); + if (result != ERROR_OK) + return result; if (set_dcsr_ebreak(target, false) != ERROR_OK) return ERROR_FAIL; @@ -2461,13 +2218,13 @@ static int riscv013_authdata_write(struct target *target, uint32_t value, unsign } /* Try to find out the widest memory access size depending on the selected memory access methods. */ -static unsigned riscv013_data_bits(struct target *target) +static unsigned int riscv013_data_bits(struct target *target) { RISCV013_INFO(info); RISCV_INFO(r); - for (unsigned int i = 0; i < RISCV_NUM_MEM_ACCESS_METHODS; i++) { - int method = r->mem_access_methods[i]; + for (unsigned int i = 0; i < r->num_enabled_mem_access_methods; i++) { + riscv_mem_access_method_t method = r->mem_access_methods[i]; if (method == RISCV_MEM_ACCESS_PROGBUF) { if (has_sufficient_progbuf(target, 3)) @@ -2488,9 +2245,9 @@ static unsigned riscv013_data_bits(struct target *target) * take those into account as well. For now we assume abstract commands * support XLEN-wide accesses. */ return riscv_xlen(target); - } else if (method == RISCV_MEM_ACCESS_UNSPECIFIED) - /* No further mem access method to try. */ - break; + } else { + assert(false); + } } LOG_TARGET_ERROR(target, "Unable to determine supported data bits on this target. Assuming 32 bits."); return 32; @@ -2716,28 +2473,49 @@ static uint32_t sb_sbaccess(unsigned int size_bytes) return 0; } -static int sb_write_address(struct target *target, target_addr_t address, - bool ensure_success) +static unsigned int get_sbaadress_reg_count(const struct target *target) { RISCV013_INFO(info); - unsigned int sbasize = get_field(info->sbcs, DM_SBCS_SBASIZE); + const unsigned int sbasize = get_field(info->sbcs, DM_SBCS_SBASIZE); + return DIV_ROUND_UP(sbasize, 32); +} + +static void batch_fill_sb_write_address(const struct target *target, + struct riscv_batch *batch, target_addr_t address, + enum riscv_scan_delay_class sbaddr0_delay) +{ /* There currently is no support for >64-bit addresses in OpenOCD. */ - if (sbasize > 96) - dm_op(target, NULL, NULL, DMI_OP_WRITE, DM_SBADDRESS3, 0, false, false); - if (sbasize > 64) - dm_op(target, NULL, NULL, DMI_OP_WRITE, DM_SBADDRESS2, 0, false, false); - if (sbasize > 32) - dm_op(target, NULL, NULL, DMI_OP_WRITE, DM_SBADDRESS1, - (uint32_t)(address >> 32), false, false); - return dm_op(target, NULL, NULL, DMI_OP_WRITE, DM_SBADDRESS0, - (uint32_t)address, false, ensure_success); + assert(sizeof(target_addr_t) == sizeof(uint64_t)); + const uint32_t addresses[] = {DM_SBADDRESS0, DM_SBADDRESS1, DM_SBADDRESS2, DM_SBADDRESS3}; + const uint32_t values[] = {(uint32_t)address, (uint32_t)(address >> 32), 0, 0}; + const unsigned int reg_count = get_sbaadress_reg_count(target); + assert(reg_count > 0); + assert(reg_count <= ARRAY_SIZE(addresses)); + assert(ARRAY_SIZE(addresses) == ARRAY_SIZE(values)); + + for (unsigned int i = reg_count - 1; i > 0; --i) + riscv_batch_add_dm_write(batch, addresses[i], values[i], /* read back */ true, + RISCV_DELAY_BASE); + riscv_batch_add_dm_write(batch, addresses[0], values[0], /* read back */ true, + sbaddr0_delay); +} + +static int sb_write_address(struct target *target, target_addr_t address, + enum riscv_scan_delay_class sbaddr0_delay) +{ + struct riscv_batch *batch = riscv_batch_alloc(target, + get_sbaadress_reg_count(target)); + batch_fill_sb_write_address(target, batch, address, sbaddr0_delay); + const int res = batch_run_timeout(target, batch); + riscv_batch_free(batch); + return res; } static int batch_run(struct target *target, struct riscv_batch *batch) { RISCV_INFO(r); RISCV013_INFO(info); - select_dmi(target); + select_dmi(target->tap); riscv_batch_add_nop(batch); const int result = riscv_batch_run_from(batch, 0, &info->learned_delays, /*resets_delays*/ r->reset_delays_wait >= 0, @@ -2760,7 +2538,7 @@ static int batch_run(struct target *target, struct riscv_batch *batch) static int batch_run_timeout(struct target *target, struct riscv_batch *batch) { RISCV013_INFO(info); - select_dmi(target); + select_dmi(target->tap); riscv_batch_add_nop(batch); size_t finished_scans = 0; @@ -2934,7 +2712,7 @@ static int sample_memory_bus_v1(struct target *target, /* Discard the batch when we encounter a busy state on the DMI level. * It's too much hassle to try to recover partial data. We'll try again * with a larger DMI delay. */ - unsigned int sbcs_read_op = riscv_batch_get_dmi_read_op(batch, sbcs_read_index); + const uint32_t sbcs_read_op = riscv_batch_get_dmi_read_op(batch, sbcs_read_index); if (sbcs_read_op == DTM_DMI_OP_BUSY) { result = increase_dmi_busy_delay(target); if (result != ERROR_OK) { @@ -3052,6 +2830,13 @@ static int handle_became_unavailable(struct target *target, enum riscv_hart_state previous_riscv_state) { RISCV013_INFO(info); + + if (riscv_reg_cache_any_dirty(target, LOG_LVL_WARNING)) + LOG_TARGET_WARNING(target, "Discarding values of dirty registers " + "(due to target becoming unavailable)."); + + riscv_reg_cache_invalidate_all(target); + info->dcsr_ebreak_is_set = false; return ERROR_OK; } @@ -3085,18 +2870,20 @@ static int init_target(struct command_context *cmd_ctx, generic_info->write_progbuf = &riscv013_write_progbuf; generic_info->execute_progbuf = &riscv013_execute_progbuf; generic_info->invalidate_cached_progbuf = &riscv013_invalidate_cached_progbuf; - generic_info->fill_dm_write = &riscv013_fill_dm_write; - generic_info->fill_dm_read = &riscv013_fill_dm_read; + generic_info->fill_dmi_write = &riscv013_fill_dmi_write; + generic_info->fill_dmi_read = &riscv013_fill_dmi_read; generic_info->fill_dm_nop = &riscv013_fill_dm_nop; - generic_info->get_dmi_scan_length = &riscv013_get_dmi_scan_length; + generic_info->get_dmi_address_bits = &riscv013_get_dmi_address_bits; generic_info->authdata_read = &riscv013_authdata_read; generic_info->authdata_write = &riscv013_authdata_write; generic_info->dmi_read = &dmi_read; generic_info->dmi_write = &dmi_write; generic_info->get_dmi_address = &riscv013_get_dmi_address; - generic_info->read_memory = read_memory; + generic_info->access_memory = &riscv013_access_memory; generic_info->data_bits = &riscv013_data_bits; generic_info->print_info = &riscv013_print_info; + generic_info->get_impebreak = &riscv013_get_impebreak; + generic_info->get_progbufsize = &riscv013_get_progbufsize; generic_info->handle_became_unavailable = &handle_became_unavailable; generic_info->tick = &tick; @@ -3112,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; } @@ -3132,7 +2909,7 @@ static int assert_reset(struct target *target) RISCV013_INFO(info); int result; - select_dmi(target); + select_dmi(target->tap); if (target_has_event_action(target, TARGET_EVENT_RESET_ASSERT)) { /* Run the user-supplied script if there is one. */ @@ -3169,6 +2946,15 @@ static int assert_reset(struct target *target) return riscv013_invalidate_cached_progbuf(target); } +static bool dcsr_ebreak_config_equals_reset_value(const struct target *target) +{ + const struct riscv_private_config * const config = riscv_private_config(target); + for (int i = 0; i < N_RISCV_MODE; ++i) + if (config->dcsr_ebreak_fields[i]) + return false; + return true; +} + static int deassert_reset(struct target *target) { RISCV013_INFO(info); @@ -3177,7 +2963,7 @@ static int deassert_reset(struct target *target) return ERROR_FAIL; int result; - select_dmi(target); + select_dmi(target->tap); /* Clear the reset, but make sure haltreq is still set */ uint32_t control = 0; control = set_field(control, DM_DMCONTROL_DMACTIVE, 1); @@ -3228,6 +3014,15 @@ static int deassert_reset(struct target *target) riscv_scan_set_delay(&info->learned_delays, RISCV_DELAY_BASE, orig_base_delay); + /* Ack reset and clear DM_DMCONTROL_HALTREQ if previously set */ + control = 0; + control = set_field(control, DM_DMCONTROL_DMACTIVE, 1); + control = set_field(control, DM_DMCONTROL_ACKHAVERESET, 1); + control = set_dmcontrol_hartsel(control, info->index); + result = dm_write(target, DM_DMCONTROL, control); + if (result != ERROR_OK) + return result; + if (target->reset_halt) { target->state = TARGET_HALTED; target->debug_reason = DBG_REASON_DBGRQ; @@ -3235,21 +3030,19 @@ static int deassert_reset(struct target *target) target->state = TARGET_RUNNING; target->debug_reason = DBG_REASON_NOTHALTED; } - info->dcsr_ebreak_is_set = false; - - /* Ack reset and clear DM_DMCONTROL_HALTREQ if previously set */ - control = 0; - control = set_field(control, DM_DMCONTROL_DMACTIVE, 1); - control = set_field(control, DM_DMCONTROL_ACKHAVERESET, 1); - control = set_dmcontrol_hartsel(control, info->index); - return dm_write(target, DM_DMCONTROL, control); + info->dcsr_ebreak_is_set = dcsr_ebreak_config_equals_reset_value(target); + return ERROR_OK; } -static int execute_fence(struct target *target) +static int execute_autofence(struct target *target) { if (dm013_select_target(target) != ERROR_OK) return ERROR_FAIL; + RISCV_INFO(r); + if (!r->autofence) + return ERROR_OK; + /* FIXME: For non-coherent systems we need to flush the caches right * here, but there's no ISA-defined way of doing that. */ struct riscv_program program; @@ -3271,8 +3064,9 @@ static int execute_fence(struct target *target) LOG_TARGET_ERROR(target, "Unexpected error during fence execution"); return ERROR_FAIL; } - LOG_TARGET_DEBUG(target, "Unable to execute fence"); + LOG_TARGET_DEBUG(target, "Unable to execute fence.i and fence rw, rw"); } + LOG_TARGET_DEBUG(target, "Successfully executed fence.i and fence rw, rw"); return ERROR_OK; } @@ -3286,6 +3080,7 @@ static int execute_fence(struct target *target) } LOG_TARGET_DEBUG(target, "Unable to execute fence.i"); } + LOG_TARGET_DEBUG(target, "Successfully executed fence.i"); riscv_program_init(&program, target); riscv_program_fence_rw_rw(&program); @@ -3296,6 +3091,7 @@ static int execute_fence(struct target *target) } LOG_TARGET_DEBUG(target, "Unable to execute fence rw, rw"); } + LOG_TARGET_DEBUG(target, "Successfully executed fence rw, rw"); return ERROR_OK; } @@ -3375,7 +3171,7 @@ static int read_memory_bus_word(struct target *target, target_addr_t address, static target_addr_t sb_read_address(struct target *target) { RISCV013_INFO(info); - unsigned sbasize = get_field(info->sbcs, DM_SBCS_SBASIZE); + unsigned int sbasize = get_field(info->sbcs, DM_SBCS_SBASIZE); target_addr_t address = 0; uint32_t v; if (sbasize > 32) { @@ -3405,50 +3201,86 @@ static int read_sbcs_nonbusy(struct target *target, uint32_t *sbcs) } } -static int modify_privilege(struct target *target, uint64_t *mstatus, uint64_t *mstatus_old) +/* TODO: return struct mem_access_result */ +static int modify_privilege_for_virt2phys_mode(struct target *target, riscv_reg_t *mstatus, riscv_reg_t *mstatus_old, + riscv_reg_t *dcsr, riscv_reg_t *dcsr_old) { - if (riscv_enable_virtual && has_sufficient_progbuf(target, 5)) { - /* Read DCSR */ - uint64_t dcsr; - if (register_read_direct(target, &dcsr, GDB_REGNO_DCSR) != ERROR_OK) - return ERROR_FAIL; + assert(mstatus); + assert(mstatus_old); + assert(dcsr); + assert(dcsr_old); + if (!riscv_virt2phys_mode_is_hw(target)) + return ERROR_OK; - /* Read and save MSTATUS */ - if (register_read_direct(target, mstatus, GDB_REGNO_MSTATUS) != ERROR_OK) - return ERROR_FAIL; - *mstatus_old = *mstatus; + /* Read and save DCSR */ + if (riscv_reg_get(target, dcsr, GDB_REGNO_DCSR) != ERROR_OK) + return ERROR_FAIL; + *dcsr_old = *dcsr; + + /* Read and save MSTATUS */ + if (riscv_reg_get(target, mstatus, GDB_REGNO_MSTATUS) != ERROR_OK) + return ERROR_FAIL; + *mstatus_old = *mstatus; - /* If we come from m-mode with mprv set, we want to keep mpp */ - if (get_field(dcsr, CSR_DCSR_PRV) < 3) { - /* MPP = PRIV */ - *mstatus = set_field(*mstatus, MSTATUS_MPP, get_field(dcsr, CSR_DCSR_PRV)); + /* If we come from m-mode with mprv set, we want to keep mpp */ + if (get_field(*dcsr, CSR_DCSR_PRV) == PRV_M) + return ERROR_OK; - /* MPRV = 1 */ - *mstatus = set_field(*mstatus, MSTATUS_MPRV, 1); + /* mstatus.mpp <- dcsr.prv */ + *mstatus = set_field(*mstatus, MSTATUS_MPP, get_field(*dcsr, CSR_DCSR_PRV)); - /* Write MSTATUS */ - if (*mstatus != *mstatus_old) - if (register_write_direct(target, GDB_REGNO_MSTATUS, *mstatus) != ERROR_OK) - return ERROR_FAIL; - } - } + /* mstatus.mprv <- 1 */ + *mstatus = set_field(*mstatus, MSTATUS_MPRV, 1); + + /* Write MSTATUS */ + if (*mstatus != *mstatus_old && + riscv_reg_set(target, GDB_REGNO_MSTATUS, *mstatus) != ERROR_OK) + return ERROR_FAIL; + + /* dcsr.mprven <- 1 */ + *dcsr = set_field(*dcsr, CSR_DCSR_MPRVEN, CSR_DCSR_MPRVEN_ENABLED); + + /* Write DCSR */ + if (*dcsr != *dcsr_old && + riscv_reg_set(target, GDB_REGNO_DCSR, *dcsr) != ERROR_OK) + return ERROR_FAIL; + + return ERROR_OK; +} + +static int restore_privilege_from_virt2phys_mode(struct target *target, riscv_reg_t mstatus, riscv_reg_t mstatus_old, + riscv_reg_t dcsr, riscv_reg_t dcsr_old) +{ + if (!riscv_virt2phys_mode_is_hw(target)) + return ERROR_OK; + + /* Restore MSTATUS */ + if (mstatus != mstatus_old && + riscv_reg_set(target, GDB_REGNO_MSTATUS, mstatus_old) != ERROR_OK) + return ERROR_FAIL; + + /* Restore DCSR */ + if (dcsr != dcsr_old && + riscv_reg_set(target, GDB_REGNO_DCSR, dcsr_old) != ERROR_OK) + return ERROR_FAIL; return ERROR_OK; } -static int read_memory_bus_v0(struct target *target, target_addr_t address, - uint32_t size, uint32_t count, uint8_t *buffer, uint32_t increment) +static int read_memory_bus_v0(struct target *target, const riscv_mem_access_args_t args) { - if (size != increment) { + assert(riscv_mem_access_is_read(args)); + + if (args.size != args.increment) { LOG_TARGET_ERROR(target, "sba v0 reads only support size==increment"); return ERROR_NOT_IMPLEMENTED; } LOG_TARGET_DEBUG(target, "System Bus Access: size: %d\tcount:%d\tstart address: 0x%08" - TARGET_PRIxADDR, size, count, address); - uint8_t *t_buffer = buffer; - riscv_addr_t cur_addr = address; - riscv_addr_t fin_addr = address + (count * size); + TARGET_PRIxADDR, args.size, args.count, args.address); + uint8_t *t_buffer = args.read_buffer; + riscv_addr_t cur_addr = args.address; + riscv_addr_t fin_addr = args.address + (args.count * args.size); uint32_t access = 0; const int DM_SBCS_SBSINGLEREAD_OFFSET = 20; @@ -3458,13 +3290,13 @@ static int read_memory_bus_v0(struct target *target, target_addr_t address, const uint32_t DM_SBCS_SBAUTOREAD = (0x1U << DM_SBCS_SBAUTOREAD_OFFSET); /* ww favorise one off reading if there is an issue */ - if (count == 1) { - for (uint32_t i = 0; i < count; i++) { + if (args.count == 1) { + for (uint32_t i = 0; i < args.count; i++) { if (dm_read(target, &access, DM_SBCS) != ERROR_OK) return ERROR_FAIL; dm_write(target, DM_SBADDRESS0, cur_addr); - /* size/2 matching the bit access of the spec 0.13 */ - access = set_field(access, DM_SBCS_SBACCESS, size/2); + /* size/2 matching the bit sbaccess of the spec 0.13 */ + access = set_field(access, DM_SBCS_SBACCESS, args.size / 2); access = set_field(access, DM_SBCS_SBSINGLEREAD, 1); LOG_TARGET_DEBUG(target, "read_memory: sab: access: 0x%08x", access); dm_write(target, DM_SBCS, access); @@ -3473,9 +3305,9 @@ static int read_memory_bus_v0(struct target *target, target_addr_t address, if (dm_read(target, &value, DM_SBDATA0) != ERROR_OK) return ERROR_FAIL; LOG_TARGET_DEBUG(target, "read_memory: sab: value: 0x%08x", value); - buf_set_u32(t_buffer, 0, 8 * size, value); - t_buffer += size; - cur_addr += size; + buf_set_u32(t_buffer, 0, 8 * args.size, value); + t_buffer += args.size; + cur_addr += args.size; } return ERROR_OK; } @@ -3488,7 +3320,7 @@ static int read_memory_bus_v0(struct target *target, target_addr_t address, dm_write(target, DM_SBADDRESS0, cur_addr); /* 2) write sbaccess=2, sbsingleread,sbautoread,sbautoincrement * size/2 matching the bit access of the spec 0.13 */ - access = set_field(access, DM_SBCS_SBACCESS, size/2); + access = set_field(access, DM_SBCS_SBACCESS, args.size / 2); access = set_field(access, DM_SBCS_SBAUTOREAD, 1); access = set_field(access, DM_SBCS_SBSINGLEREAD, 1); access = set_field(access, DM_SBCS_SBAUTOINCREMENT, 1); @@ -3497,21 +3329,21 @@ static int read_memory_bus_v0(struct target *target, target_addr_t address, while (cur_addr < fin_addr) { LOG_TARGET_DEBUG(target, "sab:autoincrement:\r\n\tsize: %d\tcount:%d\taddress: 0x%08" - PRIx64, size, count, cur_addr); + PRIx64, args.size, args.count, cur_addr); /* read */ uint32_t value; if (dm_read(target, &value, DM_SBDATA0) != ERROR_OK) return ERROR_FAIL; - buf_set_u32(t_buffer, 0, 8 * size, value); - cur_addr += size; - t_buffer += size; + buf_set_u32(t_buffer, 0, 8 * args.size, value); + cur_addr += args.size; + t_buffer += args.size; /* if we are reaching last address, we must clear autoread */ - if (cur_addr == fin_addr && count != 1) { + if (cur_addr == fin_addr && args.count != 1) { dm_write(target, DM_SBCS, 0); if (dm_read(target, &value, DM_SBDATA0) != ERROR_OK) return ERROR_FAIL; - buf_set_u32(t_buffer, 0, 8 * size, value); + buf_set_u32(t_buffer, 0, 8 * args.size, value); } } @@ -3525,14 +3357,24 @@ static int read_memory_bus_v0(struct target *target, target_addr_t address, /** * Read the requested memory using the system bus interface. */ -static int read_memory_bus_v1(struct target *target, target_addr_t address, - uint32_t size, uint32_t count, uint8_t *buffer, uint32_t increment) +static int read_memory_bus_v1(struct target *target, const riscv_mem_access_args_t args) { + assert(riscv_mem_access_is_read(args)); + + const target_addr_t address = args.address; + const uint32_t increment = args.increment; + const uint32_t count = args.count; + const uint32_t size = args.size; + uint8_t *buffer = args.read_buffer; + if (increment != size && increment != 0) { LOG_TARGET_ERROR(target, "sba v1 reads only support increment of size or 0"); return ERROR_NOT_IMPLEMENTED; } + assert(size <= 16); + assert(IS_PWR_OF_2(size)); + dm013_info_t *dm = get_dm(target); if (!dm) return ERROR_FAIL; @@ -3555,21 +3397,9 @@ static int read_memory_bus_v1(struct target *target, target_addr_t address, return ERROR_FAIL; /* This address write will trigger the first read. */ - if (sb_write_address(target, next_address, true) != ERROR_OK) + if (sb_write_address(target, next_address, RISCV_DELAY_SYSBUS_READ) != ERROR_OK) return ERROR_FAIL; - unsigned int bus_master_read_delay = riscv_scan_get_delay(&info->learned_delays, - RISCV_DELAY_SYSBUS_READ); - if (bus_master_read_delay) { - LOG_TARGET_DEBUG(target, "Waiting %d cycles for bus master read delay", - bus_master_read_delay); - jtag_add_runtest(bus_master_read_delay, TAP_IDLE); - if (jtag_execute_queue() != ERROR_OK) { - LOG_TARGET_ERROR(target, "Failed to scan idle sequence"); - return ERROR_FAIL; - } - } - /* First read has been started. Optimistically assume that it has * completed. */ @@ -3580,7 +3410,6 @@ static int read_memory_bus_v1(struct target *target, target_addr_t address, * be unnecessary. */ uint32_t sbvalue[4] = {0}; - assert(size <= 16); for (uint32_t i = (next_address - address) / size; i < count - 1; i++) { const uint32_t size_in_words = DIV_ROUND_UP(size, 4); struct riscv_batch *batch = riscv_batch_alloc(target, size_in_words); @@ -3601,10 +3430,10 @@ static int read_memory_bus_v1(struct target *target, target_addr_t address, const size_t last_key = batch->read_keys_used - 1; for (size_t k = 0; k <= last_key; ++k) { - sbvalue[k] = riscv_batch_get_dmi_read_data(batch, - last_key - k); - buf_set_u32(buffer + i * size + k * 4, 0, 8 * size, sbvalue[k]); + sbvalue[k] = riscv_batch_get_dmi_read_data(batch, last_key - k); + buf_set_u32(buffer + i * size + k * 4, 0, MIN(32, 8 * size), sbvalue[k]); } + riscv_batch_free(batch); const target_addr_t read_addr = address + i * increment; log_memory_access(read_addr, sbvalue, size, true); @@ -3659,7 +3488,7 @@ static int read_memory_bus_v1(struct target *target, target_addr_t address, continue; } - unsigned error = get_field(sbcs_read, DM_SBCS_SBERROR); + unsigned int error = get_field(sbcs_read, DM_SBCS_SBERROR); if (error == DM_SBCS_SBERROR_NONE) { next_address = end_address; } else { @@ -3674,7 +3503,7 @@ static int read_memory_bus_v1(struct target *target, target_addr_t address, return ERROR_OK; } -static void log_mem_access_result(struct target *target, bool success, int method, bool is_read) +static void log_mem_access_result(struct target *target, bool success, riscv_mem_access_method_t method, bool is_read) { RISCV_INFO(r); bool warn = false; @@ -3689,18 +3518,8 @@ static void log_mem_access_result(struct target *target, bool success, int metho /* Determine the log message severity. Show warnings only once. */ if (!success) { - if (method == RISCV_MEM_ACCESS_PROGBUF) { - warn = r->mem_access_progbuf_warn; - r->mem_access_progbuf_warn = false; - } - if (method == RISCV_MEM_ACCESS_SYSBUS) { - warn = r->mem_access_sysbus_warn; - r->mem_access_sysbus_warn = false; - } - if (method == RISCV_MEM_ACCESS_ABSTRACT) { - warn = r->mem_access_abstract_warn; - r->mem_access_abstract_warn = false; - } + warn = r->mem_access_warn[method]; + r->mem_access_warn[method] = false; } if (warn) @@ -3709,101 +3528,255 @@ static void log_mem_access_result(struct target *target, bool success, int metho LOG_TARGET_DEBUG(target, "%s", msg); } -static bool mem_should_skip_progbuf(struct target *target, target_addr_t address, - uint32_t size, bool is_read, char **skip_reason) +enum mem_access_result_type { + MEM_ACCESS_RESULT_TYPE_OK, + MEM_ACCESS_RESULT_TYPE_DISABLED, + MEM_ACCESS_RESULT_TYPE_SKIPPED, + MEM_ACCESS_RESULT_TYPE_FAILED, + MEM_ACCESS_RESULT_TYPE_ENUM_SIZE, +}; + +#define LIST_OF_MEM_ACCESS_RESULTS \ + MEM_ACCESS_RESULT_HANDLER(MEM_ACCESS_OK, OK, "ok") \ + MEM_ACCESS_RESULT_HANDLER(MEM_ACCESS_DISABLED, DISABLED, "disabled") \ + MEM_ACCESS_RESULT_HANDLER(MEM_ACCESS_SKIPPED, SKIPPED, "skipped") \ + MEM_ACCESS_RESULT_HANDLER(MEM_ACCESS_SKIPPED_ABSTRACT_ACCESS_CMDERR, \ + SKIPPED, "skipped (abstract access cmderr)") \ + MEM_ACCESS_RESULT_HANDLER(MEM_ACCESS_SKIPPED_PROGBUF_NOT_PRESENT, \ + SKIPPED, "skipped (progbuf not present)") \ + MEM_ACCESS_RESULT_HANDLER(MEM_ACCESS_SKIPPED_PROGBUF_INSUFFICIENT, \ + SKIPPED, "skipped (insufficient progbuf)") \ + MEM_ACCESS_RESULT_HANDLER(MEM_ACCESS_SKIPPED_UNSUPPORTED_ACCESS_SIZE, \ + SKIPPED, "skipped (unsupported access size)") \ + MEM_ACCESS_RESULT_HANDLER(MEM_ACCESS_SKIPPED_XLEN_TOO_SHORT, \ + SKIPPED, "skipped (xlen too short)") \ + MEM_ACCESS_RESULT_HANDLER(MEM_ACCESS_SKIPPED_TARGET_NOT_HALTED, \ + SKIPPED, "skipped (target not halted)") \ + MEM_ACCESS_RESULT_HANDLER(MEM_ACCESS_SKIPPED_TOO_LARGE_ADDRESS, \ + SKIPPED, "skipped (address too large)") \ + MEM_ACCESS_RESULT_HANDLER(MEM_ACCESS_SKIPPED_UNSUPPORTED_INCREMENT_SIZE, \ + SKIPPED, "skipped (increment size not supported)") \ + MEM_ACCESS_RESULT_HANDLER(MEM_ACCESS_SKIPPED_TARGET_SELECT_FAILED, \ + SKIPPED, "skipped (dm target select failed)") \ + MEM_ACCESS_RESULT_HANDLER(MEM_ACCESS_SKIPPED_FENCE_EXEC_FAILED, \ + SKIPPED, "skipped (fence execution failed)") \ + MEM_ACCESS_RESULT_HANDLER(MEM_ACCESS_SKIPPED_SYSBUS_ACCESS_FAILED, \ + SKIPPED, "skipped (sysbus access failed)") \ + MEM_ACCESS_RESULT_HANDLER(MEM_ACCESS_SKIPPED_REG_SAVE_FAILED, \ + SKIPPED, "skipped (register save failed)") \ + MEM_ACCESS_RESULT_HANDLER(MEM_ACCESS_SKIPPED_UNKNOWN_SYSBUS_VERSION, \ + SKIPPED, "skipped (unknown sysbus version)") \ + MEM_ACCESS_RESULT_HANDLER(MEM_ACCESS_SKIPPED_PROGRAM_WRITE_FAILED, \ + SKIPPED, "skipped (program write failed)") \ + MEM_ACCESS_RESULT_HANDLER(MEM_ACCESS_SKIPPED_PROGBUF_FILL_FAILED, \ + SKIPPED, "skipped (progbuf fill failed)") \ + MEM_ACCESS_RESULT_HANDLER(MEM_ACCESS_SKIPPED_WRITE_ABSTRACT_ARG_FAILED, \ + SKIPPED, "skipped (abstract command argument write failed)") \ + MEM_ACCESS_RESULT_HANDLER(MEM_ACCESS_SKIPPED_PRIV_MOD_FAILED, \ + SKIPPED, "skipped (privilege modification failed)") \ + MEM_ACCESS_RESULT_HANDLER(MEM_ACCESS_FAILED, FAILED, "failed") \ + MEM_ACCESS_RESULT_HANDLER(MEM_ACCESS_FAILED_DM_ACCESS_FAILED, \ + FAILED, "failed (DM register access failed)") \ + MEM_ACCESS_RESULT_HANDLER(MEM_ACCESS_FAILED_PRIV_MOD_FAILED, \ + FAILED, "failed (privilege modification failed)") \ + MEM_ACCESS_RESULT_HANDLER(MEM_ACCESS_FAILED_REG_READ_FAILED, \ + FAILED, "failed (register read failed)") \ + MEM_ACCESS_RESULT_HANDLER(MEM_ACCESS_FAILED_PROGBUF_STARTUP_FAILED, \ + FAILED, "failed (progbuf startup failed)") \ + MEM_ACCESS_RESULT_HANDLER(MEM_ACCESS_FAILED_PROGBUF_INNER_FAILED, \ + FAILED, "failed (progbuf inner failed)") \ + MEM_ACCESS_RESULT_HANDLER(MEM_ACCESS_FAILED_PROGBUF_TEARDOWN_FAILED, \ + FAILED, "failed (progbuf teardown failed)") \ + MEM_ACCESS_RESULT_HANDLER(MEM_ACCESS_FAILED_EXECUTE_ABSTRACT_FAILED, \ + FAILED, "failed (execute abstract failed)") \ + MEM_ACCESS_RESULT_HANDLER(MEM_ACCESS_FAILED_NO_FORWARD_PROGRESS, \ + FAILED, "failed (no forward progress)") \ + MEM_ACCESS_RESULT_HANDLER(MEM_ACCESS_FAILED_FENCE_EXEC_FAILED, \ + FAILED, "failed (fence execution failed)") \ + + +#define MEM_ACCESS_RESULT_HANDLER(name, kind, msg) name, +enum mem_access_result_enum { + LIST_OF_MEM_ACCESS_RESULTS +}; +#undef MEM_ACCESS_RESULT_HANDLER + +/* Structure is intentionally used to contain the memory access result, + for type safety - to avoid implicit conversions to integers. */ +struct mem_access_result { + enum mem_access_result_enum value; +}; + +bool is_mem_access_ok(struct mem_access_result status) +{ + #define MEM_ACCESS_RESULT_HANDLER(name, kind, msg) \ + case name: return MEM_ACCESS_RESULT_TYPE_##kind \ + == MEM_ACCESS_RESULT_TYPE_OK; + + switch (status.value) { + LIST_OF_MEM_ACCESS_RESULTS + } + #undef MEM_ACCESS_RESULT_HANDLER + + LOG_ERROR("Unknown memory access status: %d", status.value); + assert(false && "Unknown memory access status"); + return false; +} + +bool is_mem_access_failed(struct mem_access_result status) +{ + #define MEM_ACCESS_RESULT_HANDLER(name, kind, msg) \ + case name: return MEM_ACCESS_RESULT_TYPE_##kind \ + == MEM_ACCESS_RESULT_TYPE_FAILED; + + switch (status.value) { + LIST_OF_MEM_ACCESS_RESULTS + } + #undef MEM_ACCESS_RESULT_HANDLER + + LOG_ERROR("Unknown memory access status: %d", status.value); + assert(false && "Unknown memory access status"); + return true; +} + +bool is_mem_access_skipped(struct mem_access_result status) +{ + #define MEM_ACCESS_RESULT_HANDLER(name, kind, msg) \ + case name: return MEM_ACCESS_RESULT_TYPE_##kind \ + == MEM_ACCESS_RESULT_TYPE_SKIPPED; + + switch (status.value) { + LIST_OF_MEM_ACCESS_RESULTS + } + #undef MEM_ACCESS_RESULT_HANDLER + LOG_ERROR("Unknown memory access status: %d", status.value); + assert(false && "Unknown memory access status"); + return true; +} + +const char *mem_access_result_to_str(struct mem_access_result status) +{ + #define MEM_ACCESS_RESULT_HANDLER(name, kind, msg) \ + [name] = msg, + static const char * const table[] = { + LIST_OF_MEM_ACCESS_RESULTS + }; + #undef MEM_ACCESS_RESULT_HANDLER + + assert(status.value < ARRAY_SIZE(table)); + return table[status.value]; +} + +static struct mem_access_result mem_access_result(enum mem_access_result_enum value) { - assert(skip_reason); + struct mem_access_result result = {.value = value}; + return result; +} +static struct mem_access_result mem_should_skip_progbuf(struct target *target, + const riscv_mem_access_args_t args) +{ + assert(riscv_mem_access_is_valid(args)); + const char *const access_type = + riscv_mem_access_is_read(args) ? "read" : "write"; + + if (!has_sufficient_progbuf(target, 1)) { + LOG_TARGET_DEBUG(target, "Skipping mem %s via progbuf " + "- progbuf not present", access_type); + return mem_access_result(MEM_ACCESS_SKIPPED_PROGBUF_NOT_PRESENT); + } if (!has_sufficient_progbuf(target, 3)) { - LOG_TARGET_DEBUG(target, "Skipping mem %s via progbuf - insufficient progbuf size.", - is_read ? "read" : "write"); - *skip_reason = "skipped (insufficient progbuf)"; - return true; + LOG_TARGET_DEBUG(target, "Skipping mem %s via progbuf - " + "insufficient progbuf size.", access_type); + return mem_access_result(MEM_ACCESS_SKIPPED_PROGBUF_INSUFFICIENT); } if (target->state != TARGET_HALTED) { - LOG_TARGET_DEBUG(target, "Skipping mem %s via progbuf - target not halted.", - is_read ? "read" : "write"); - *skip_reason = "skipped (target not halted)"; - return true; - } - if (riscv_xlen(target) < size * 8) { - LOG_TARGET_DEBUG(target, "Skipping mem %s via progbuf - XLEN (%d) is too short for %d-bit memory access.", - is_read ? "read" : "write", riscv_xlen(target), size * 8); - *skip_reason = "skipped (XLEN too short)"; - return true; - } - if (size > 8) { - LOG_TARGET_DEBUG(target, "Skipping mem %s via progbuf - unsupported size.", - is_read ? "read" : "write"); - *skip_reason = "skipped (unsupported size)"; - return true; - } - if ((sizeof(address) * 8 > riscv_xlen(target)) && (address >> riscv_xlen(target))) { - LOG_TARGET_DEBUG(target, "Skipping mem %s via progbuf - progbuf only supports %u-bit address.", - is_read ? "read" : "write", riscv_xlen(target)); - *skip_reason = "skipped (too large address)"; - return true; + LOG_TARGET_DEBUG(target, "Skipping mem %s via progbuf - " + "target not halted.", access_type); + return mem_access_result(MEM_ACCESS_SKIPPED_TARGET_NOT_HALTED); + } + if (riscv_xlen(target) < args.size * 8) { + LOG_TARGET_DEBUG(target, "Skipping mem %s via progbuf - " + "XLEN (%d) is too short for %d-bit memory args.", + access_type, riscv_xlen(target), args.size * 8); + return mem_access_result(MEM_ACCESS_SKIPPED_XLEN_TOO_SHORT); + } + if (args.size > 8) { + LOG_TARGET_DEBUG(target, "Skipping mem %s via progbuf - " + "unsupported size.", access_type); + return mem_access_result(MEM_ACCESS_SKIPPED_UNSUPPORTED_ACCESS_SIZE); + } + if ((sizeof(args.address) * 8 > riscv_xlen(target)) + && (args.address >> riscv_xlen(target))) { + LOG_TARGET_DEBUG(target, "Skipping mem %s via progbuf - " + "progbuf only supports %u-bit address.", access_type, riscv_xlen(target)); + return mem_access_result(MEM_ACCESS_SKIPPED_TOO_LARGE_ADDRESS); } - return false; + return mem_access_result(MEM_ACCESS_OK); } -static bool mem_should_skip_sysbus(struct target *target, target_addr_t address, - uint32_t size, uint32_t increment, bool is_read, char **skip_reason) +static struct mem_access_result +mem_should_skip_sysbus(struct target *target, const riscv_mem_access_args_t args) { - assert(skip_reason); + assert(riscv_mem_access_is_valid(args)); RISCV013_INFO(info); - if (!sba_supports_access(target, size)) { - LOG_TARGET_DEBUG(target, "Skipping mem %s via system bus - unsupported size.", - is_read ? "read" : "write"); - *skip_reason = "skipped (unsupported size)"; - return true; + const bool is_read = riscv_mem_access_is_read(args); + const char *const access_type = is_read ? "read" : "write"; + + if (!sba_supports_access(target, args.size)) { + LOG_TARGET_DEBUG(target, "Skipping mem %s via system bus - " + "unsupported size.", access_type); + return mem_access_result(MEM_ACCESS_SKIPPED_UNSUPPORTED_ACCESS_SIZE); } unsigned int sbasize = get_field(info->sbcs, DM_SBCS_SBASIZE); - if ((sizeof(address) * 8 > sbasize) && (address >> sbasize)) { - LOG_TARGET_DEBUG(target, "Skipping mem %s via system bus - sba only supports %u-bit address.", - is_read ? "read" : "write", sbasize); - *skip_reason = "skipped (too large address)"; - return true; + if ((sizeof(args.address) * 8 > sbasize) + && (args.address >> sbasize)) { + LOG_TARGET_DEBUG(target, "Skipping mem %s via system bus - " + "sba only supports %u-bit address.", access_type, sbasize); + return mem_access_result(MEM_ACCESS_SKIPPED_TOO_LARGE_ADDRESS); } - if (is_read && increment != size && (get_field(info->sbcs, DM_SBCS_SBVERSION) == 0 || increment != 0)) { - LOG_TARGET_DEBUG(target, "Skipping mem read via system bus - " - "sba reads only support size==increment or also size==0 for sba v1."); - *skip_reason = "skipped (unsupported increment)"; - return true; + if (is_read && args.increment != args.size + && (get_field(info->sbcs, DM_SBCS_SBVERSION) == 0 + || args.increment != 0)) { + LOG_TARGET_DEBUG(target, "Skipping mem %s via system bus - " + "sba %ss only support (size == increment) or also " + "size==0 for sba v1.", access_type, access_type); + return mem_access_result(MEM_ACCESS_SKIPPED_UNSUPPORTED_INCREMENT_SIZE); } - return false; + return mem_access_result(MEM_ACCESS_OK); } -static bool mem_should_skip_abstract(struct target *target, target_addr_t address, - uint32_t size, uint32_t increment, bool is_read, char **skip_reason) +static struct mem_access_result +mem_should_skip_abstract(struct target *target, const riscv_mem_access_args_t args) { - assert(skip_reason); + assert(riscv_mem_access_is_valid(args)); - if (size > 8) { + const bool is_read = riscv_mem_access_is_read(args); + const char *const access_type = is_read ? "read" : "write"; + if (args.size > 8) { /* TODO: Add 128b support if it's ever used. Involves modifying read/write_abstract_arg() to work on two 64b values. */ - LOG_TARGET_DEBUG(target, "Skipping mem %s via abstract access - unsupported size: %d bits", - is_read ? "read" : "write", size * 8); - *skip_reason = "skipped (unsupported size)"; - return true; + LOG_TARGET_DEBUG(target, "Skipping mem %s via abstract access - " + "unsupported size: %d bits", access_type, args.size * 8); + return mem_access_result(MEM_ACCESS_SKIPPED_UNSUPPORTED_ACCESS_SIZE); } - if ((sizeof(address) * 8 > riscv_xlen(target)) && (address >> riscv_xlen(target))) { - LOG_TARGET_DEBUG(target, "Skipping mem %s via abstract access - abstract access only supports %u-bit address.", - is_read ? "read" : "write", riscv_xlen(target)); - *skip_reason = "skipped (too large address)"; - return true; + if ((sizeof(args.address) * 8 > riscv_xlen(target)) + && (args.address >> riscv_xlen(target))) { + LOG_TARGET_DEBUG(target, "Skipping mem %s via abstract access - " + "abstract access only supports %u-bit address.", + access_type, riscv_xlen(target)); + return mem_access_result(MEM_ACCESS_SKIPPED_TOO_LARGE_ADDRESS); } - if (is_read && size != increment) { - LOG_TARGET_ERROR(target, "Skipping mem read via abstract access - " - "abstract command reads only support size==increment."); - *skip_reason = "skipped (unsupported increment)"; - return true; + if (is_read && args.size != args.increment) { + LOG_TARGET_ERROR(target, "Skipping mem %s via abstract access - " + "abstract command %ss only support (size == increment).", + access_type, access_type); + return mem_access_result(MEM_ACCESS_SKIPPED_UNSUPPORTED_INCREMENT_SIZE); } - - return false; + return mem_access_result(MEM_ACCESS_OK); } /* @@ -3811,88 +3784,76 @@ static bool mem_should_skip_abstract(struct target *target, target_addr_t addres * supported are 1, 2, and 4 bytes despite the spec's support of 8 and 16 byte * aamsize fields in the memory access abstract command. */ -static int read_memory_abstract(struct target *target, target_addr_t address, - uint32_t size, uint32_t count, uint8_t *buffer, uint32_t increment) +static struct mem_access_result +read_memory_abstract(struct target *target, const riscv_mem_access_args_t args) { - RISCV013_INFO(info); - - int result = ERROR_OK; - bool use_aampostincrement = info->has_aampostincrement != YNM_NO; - - LOG_TARGET_DEBUG(target, "Reading %d words of %d bytes from 0x%" TARGET_PRIxADDR, count, - size, address); + assert(riscv_mem_access_is_read(args)); - memset(buffer, 0, count * size); + memset(args.read_buffer, 0, args.count * args.size); /* Convert the size (bytes) to width (bits) */ - unsigned width = size << 3; - - /* Create the command (physical address, postincrement, read) */ - uint32_t command = access_memory_command(target, false, width, use_aampostincrement, false); + unsigned int width = args.size << 3; + + 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 = buffer; + uint8_t *p = args.read_buffer; + int result = ERROR_OK; bool updateaddr = true; - unsigned int width32 = (width < 32) ? 32 : width; - for (uint32_t c = 0; c < count; c++) { + unsigned int width32 = MAX(width, 32); + for (uint32_t c = 0; c < args.count; c++) { /* Update the address if it is the first time or aampostincrement is not supported by the target. */ if (updateaddr) { /* Set arg1 to the address: address + c * size */ - result = write_abstract_arg(target, 1, address + c * size, riscv_xlen(target)); + result = write_abstract_arg(target, 1, args.address + c * args.size, riscv_xlen(target)); if (result != ERROR_OK) { LOG_TARGET_ERROR(target, "Failed to write arg1."); - return result; + return mem_access_result(MEM_ACCESS_FAILED_DM_ACCESS_FAILED); } } /* Execute the command */ uint32_t cmderr; - result = 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 result; - - if (new_address == address + 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 = 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; - } - } + result = riscv013_execute_abstract_command(target, command, &cmderr); + 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: + * (1) Only the 1st access can result in a 'skip' + * (2) Analyze cmderr value */ if (result != ERROR_OK) - return result; + return mem_access_result(MEM_ACCESS_SKIPPED_ABSTRACT_ACCESS_CMDERR); /* Copy arg0 to buffer (rounded width up to nearest 32) */ riscv_reg_t value; result = read_abstract_arg(target, &value, 0, width32); if (result != ERROR_OK) - return result; - buf_set_u64(p, 0, 8 * size, value); + 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 += size; + p += args.size; } - return result; + return mem_access_result(MEM_ACCESS_OK); } /* @@ -3900,85 +3861,75 @@ static int read_memory_abstract(struct target *target, target_addr_t address, * sizes supported are 1, 2, and 4 bytes despite the spec's support of 8 and 16 * byte aamsize fields in the memory access abstract command. */ -static int write_memory_abstract(struct target *target, target_addr_t address, - uint32_t size, uint32_t count, const uint8_t *buffer) +static struct mem_access_result +write_memory_abstract(struct target *target, const riscv_mem_access_args_t args) { - RISCV013_INFO(info); - int result = ERROR_OK; - bool use_aampostincrement = info->has_aampostincrement != YNM_NO; + assert(riscv_mem_access_is_write(args)); - LOG_TARGET_DEBUG(target, "writing %d words of %d bytes from 0x%" TARGET_PRIxADDR, count, - size, address); + int result = ERROR_OK; /* Convert the size (bytes) to width (bits) */ - unsigned width = size << 3; - - /* Create the command (physical address, postincrement, write) */ - uint32_t command = access_memory_command(target, false, width, use_aampostincrement, true); + unsigned int width = args.size << 3; + + 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 = buffer; + const uint8_t *p = args.write_buffer; bool updateaddr = true; - for (uint32_t c = 0; c < count; c++) { + for (uint32_t c = 0; c < args.count; c++) { /* Move data to arg0 */ - riscv_reg_t value = buf_get_u64(p, 0, 8 * size); + riscv_reg_t value = buf_get_u64(p, 0, 8 * args.size); result = write_abstract_arg(target, 0, value, riscv_xlen(target)); if (result != ERROR_OK) { LOG_TARGET_ERROR(target, "Failed to write arg0."); - return result; + return mem_access_result(MEM_ACCESS_FAILED_DM_ACCESS_FAILED); } /* Update the address if it is the first time or aampostincrement is not supported by the target. */ if (updateaddr) { /* Set arg1 to the address: address + c * size */ - result = write_abstract_arg(target, 1, address + c * size, riscv_xlen(target)); + result = write_abstract_arg(target, 1, args.address + c * args.size, riscv_xlen(target)); if (result != ERROR_OK) { LOG_TARGET_ERROR(target, "Failed to write arg1."); - return result; + return mem_access_result(MEM_ACCESS_FAILED_DM_ACCESS_FAILED); } } /* Execute the command */ uint32_t cmderr; - result = 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 result; - - if (new_address == address + 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 = 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; - } - } + result = riscv013_execute_abstract_command(target, command, &cmderr); + 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: + * (1) Only the 1st access can result in a 'skip' + * (2) Analyze cmderr value */ if (result != ERROR_OK) - return result; + return mem_access_result(MEM_ACCESS_SKIPPED_ABSTRACT_ACCESS_CMDERR); - if (info->has_aampostincrement == YNM_YES) + if (use_aampostincrement) updateaddr = false; - p += size; + p += args.size; } - return result; + return mem_access_result(MEM_ACCESS_OK); } /** @@ -4008,11 +3959,11 @@ static int read_memory_progbuf_inner_startup(struct target *target, /* AC_ACCESS_REGISTER_POSTEXEC is used to trigger first stage of the * pipeline (memory -> s1) whenever this command is executed. */ - const uint32_t startup_command = access_register_command(target, + const uint32_t startup_command = riscv013_access_register_command(target, GDB_REGNO_S1, riscv_xlen(target), AC_ACCESS_REGISTER_TRANSFER | AC_ACCESS_REGISTER_POSTEXEC); uint32_t cmderr; - if (execute_abstract_command(target, startup_command, &cmderr) != ERROR_OK) + if (riscv013_execute_abstract_command(target, startup_command, &cmderr) != ERROR_OK) return ERROR_FAIL; /* TODO: we need to modify error handling here. */ /* NOTE: in case of timeout cmderr is set to CMDERR_NONE */ @@ -4052,13 +4003,6 @@ clear_abstractauto_and_fail: return ERROR_FAIL; } -struct memory_access_info { - uint8_t *buffer_address; - target_addr_t target_address; - uint32_t element_size; - uint32_t increment; -}; - /** * This function attempts to restore the pipeline after a busy on abstract * access. @@ -4069,8 +4013,10 @@ struct memory_access_info { */ static int read_memory_progbuf_inner_on_ac_busy(struct target *target, uint32_t start_index, uint32_t *elements_read, - struct memory_access_info access) + const riscv_mem_access_args_t args) { + assert(riscv_mem_access_is_read(args)); + int res = riscv013_clear_abstract_error(target); if (res != ERROR_OK) return res; @@ -4084,7 +4030,7 @@ static int read_memory_progbuf_inner_on_ac_busy(struct target *target, /* See how far we got by reading s0/a0 */ uint32_t index_on_target; - if (/*is_repeated_read*/ access.increment == 0) { + if (/*is_repeated_read*/ args.increment == 0) { /* s0 is constant, a0 is incremented by one each execution */ riscv_reg_t counter; @@ -4096,8 +4042,8 @@ static int read_memory_progbuf_inner_on_ac_busy(struct target *target, if (register_read_direct(target, &address_on_target, GDB_REGNO_S0) != ERROR_OK) return ERROR_FAIL; - index_on_target = (address_on_target - access.target_address) / - access.increment; + index_on_target = (address_on_target - args.address) / + args.increment; } /* According to the spec, if an abstract command fails, one can't make any @@ -4115,10 +4061,10 @@ static int read_memory_progbuf_inner_on_ac_busy(struct target *target, *elements_read = next_index - start_index; LOG_TARGET_WARNING(target, "Re-reading memory from addresses 0x%" TARGET_PRIxADDR " and 0x%" TARGET_PRIxADDR ".", - access.target_address + access.increment * next_index, - access.target_address + access.increment * (next_index + 1)); - return read_memory_progbuf_inner_startup(target, access.target_address, - access.increment, next_index); + args.address + args.increment * next_index, + args.address + args.increment * (next_index + 1)); + return read_memory_progbuf_inner_startup(target, args.address, + args.increment, next_index); } /** @@ -4126,8 +4072,10 @@ static int read_memory_progbuf_inner_on_ac_busy(struct target *target, */ static int read_memory_progbuf_inner_on_dmi_busy(struct target *target, uint32_t start_index, uint32_t next_start_index, - struct memory_access_info access) + const riscv_mem_access_args_t args) { + assert(riscv_mem_access_is_read(args)); + LOG_TARGET_DEBUG(target, "DMI_STATUS_BUSY encountered in batch. Memory read [%" PRIu32 ", %" PRIu32 ")", start_index, next_start_index); if (start_index == next_start_index) @@ -4135,8 +4083,8 @@ static int read_memory_progbuf_inner_on_dmi_busy(struct target *target, if (dm_write(target, DM_ABSTRACTAUTO, 0) != ERROR_OK) return ERROR_FAIL; - return read_memory_progbuf_inner_startup(target, access.target_address, - access.increment, next_start_index); + return read_memory_progbuf_inner_startup(target, args.address, + args.increment, next_start_index); } /** @@ -4145,9 +4093,11 @@ static int read_memory_progbuf_inner_on_dmi_busy(struct target *target, static int read_memory_progbuf_inner_extract_batch_data(struct target *target, const struct riscv_batch *batch, uint32_t start_index, uint32_t elements_to_read, uint32_t *elements_read, - struct memory_access_info access) + const riscv_mem_access_args_t args) { - const bool two_reads_per_element = access.element_size > 4; + assert(riscv_mem_access_is_read(args)); + + const bool two_reads_per_element = args.size > 4; const uint32_t reads_per_element = (two_reads_per_element ? 2 : 1); assert(!two_reads_per_element || riscv_xlen(target) == 64); assert(elements_to_read <= UINT32_MAX / reads_per_element); @@ -4157,7 +4107,7 @@ static int read_memory_progbuf_inner_extract_batch_data(struct target *target, case DMI_STATUS_BUSY: *elements_read = curr_idx - start_index; return read_memory_progbuf_inner_on_dmi_busy(target, start_index, curr_idx - , access); + , args); case DMI_STATUS_FAILED: LOG_TARGET_DEBUG(target, "Batch memory read encountered DMI_STATUS_FAILED on read %" @@ -4169,11 +4119,11 @@ static int read_memory_progbuf_inner_extract_batch_data(struct target *target, assert(0); } const uint32_t value = riscv_batch_get_dmi_read_data(batch, read); - uint8_t * const curr_buff = access.buffer_address + - curr_idx * access.element_size; - const target_addr_t curr_addr = access.target_address + - curr_idx * access.increment; - const uint32_t size = access.element_size; + uint8_t * const curr_buff = args.read_buffer + + curr_idx * args.size; + const target_addr_t curr_addr = args.address + + curr_idx * args.increment; + const uint32_t size = args.size; assert(size <= 8); const bool is_odd_read = read % 2; @@ -4200,9 +4150,11 @@ static int read_memory_progbuf_inner_extract_batch_data(struct target *target, * - DM_ABSTRACTAUTO_AUTOEXECDATA is set. */ static int read_memory_progbuf_inner_run_and_process_batch(struct target *target, - struct riscv_batch *batch, struct memory_access_info access, + struct riscv_batch *batch, const riscv_mem_access_args_t args, uint32_t start_index, uint32_t elements_to_read, uint32_t *elements_read) { + assert(riscv_mem_access_is_read(args)); + dm013_info_t *dm = get_dm(target); if (!dm) return ERROR_FAIL; @@ -4228,7 +4180,7 @@ static int read_memory_progbuf_inner_run_and_process_batch(struct target *target case CMDERR_BUSY: LOG_TARGET_DEBUG(target, "memory read resulted in busy response"); if (read_memory_progbuf_inner_on_ac_busy(target, start_index, - &elements_to_extract_from_batch, access) + &elements_to_extract_from_batch, args) != ERROR_OK) return ERROR_FAIL; break; @@ -4239,7 +4191,7 @@ static int read_memory_progbuf_inner_run_and_process_batch(struct target *target } if (read_memory_progbuf_inner_extract_batch_data(target, batch, start_index, - elements_to_extract_from_batch, elements_read, access) != ERROR_OK) + elements_to_extract_from_batch, elements_read, args) != ERROR_OK) return ERROR_FAIL; return ERROR_OK; @@ -4269,18 +4221,20 @@ static uint32_t read_memory_progbuf_inner_fill_batch(struct riscv_batch *batch, } static int read_memory_progbuf_inner_try_to_read(struct target *target, - struct memory_access_info access, uint32_t *elements_read, + const riscv_mem_access_args_t args, uint32_t *elements_read, uint32_t index, uint32_t loop_count) { + assert(riscv_mem_access_is_read(args)); + struct riscv_batch *batch = riscv_batch_alloc(target, RISCV_BATCH_ALLOC_SIZE); if (!batch) return ERROR_FAIL; const uint32_t elements_to_read = read_memory_progbuf_inner_fill_batch(batch, - loop_count - index, access.element_size); + loop_count - index, args.size); int result = read_memory_progbuf_inner_run_and_process_batch(target, batch, - access, index, elements_to_read, elements_read); + args, index, elements_to_read, elements_read); riscv_batch_free(batch); return result; } @@ -4290,20 +4244,22 @@ static int read_memory_progbuf_inner_try_to_read(struct target *target, * with the address argument equal to curr_target_address. */ static int read_memory_progbuf_inner_ensure_forward_progress(struct target *target, - struct memory_access_info access, uint32_t start_index) + const riscv_mem_access_args_t args, uint32_t start_index) { + assert(riscv_mem_access_is_read(args)); + LOG_TARGET_DEBUG(target, "Executing one loop iteration to ensure forward progress (index=%" PRIu32 ")", start_index); - const target_addr_t curr_target_address = access.target_address + - start_index * access.increment; - uint8_t * const curr_buffer_address = access.buffer_address + - start_index * access.element_size; - const struct memory_access_info curr_access = { - .buffer_address = curr_buffer_address, - .target_address = curr_target_address, - .element_size = access.element_size, - .increment = access.increment, + const target_addr_t curr_target_address = args.address + + start_index * args.increment; + uint8_t * const curr_buffer_address = args.read_buffer + + start_index * args.size; + const riscv_mem_access_args_t curr_access = { + .read_buffer = curr_buffer_address, + .address = curr_target_address, + .size = args.size, + .increment = args.increment, }; uint32_t elements_read; if (read_memory_progbuf_inner_try_to_read(target, curr_access, &elements_read, @@ -4321,13 +4277,15 @@ static int read_memory_progbuf_inner_ensure_forward_progress(struct target *targ return ERROR_OK; } -static void set_buffer_and_log_read(struct memory_access_info access, +static void set_buffer_and_log_read(const riscv_mem_access_args_t args, uint32_t index, uint64_t value) { - uint8_t * const buffer = access.buffer_address; - const uint32_t size = access.element_size; - const uint32_t increment = access.increment; - const target_addr_t address = access.target_address; + assert(riscv_mem_access_is_read(args)); + + uint8_t * const buffer = args.read_buffer; + const uint32_t size = args.size; + const uint32_t increment = args.increment; + const target_addr_t address = args.address; assert(size <= 8); buf_set_u64(buffer + index * size, 0, 8 * size, value); @@ -4336,47 +4294,32 @@ static void set_buffer_and_log_read(struct memory_access_info access, } static int read_word_from_dm_data_regs(struct target *target, - struct memory_access_info access, uint32_t index) + const riscv_mem_access_args_t args, uint32_t index) { - assert(access.element_size <= 8); + assert(args.size <= 8); uint64_t value; int result = read_abstract_arg(target, &value, /*index*/ 0, - access.element_size > 4 ? 64 : 32); + args.size > 4 ? 64 : 32); if (result == ERROR_OK) - set_buffer_and_log_read(access, index, value); + set_buffer_and_log_read(args, index, value); return result; } -static int read_word_from_s1(struct target *target, - struct memory_access_info access, uint32_t index) +static struct mem_access_result read_word_from_s1(struct target *target, + const riscv_mem_access_args_t args, uint32_t index) { + assert(riscv_mem_access_is_read(args)); + uint64_t value; if (register_read_direct(target, &value, GDB_REGNO_S1) != ERROR_OK) - return ERROR_FAIL; - set_buffer_and_log_read(access, index, value); - return ERROR_OK; -} - -static int riscv_program_load_mprv(struct riscv_program *p, enum gdb_regno d, - enum gdb_regno b, int offset, unsigned int size, bool mprven) -{ - if (mprven && riscv_program_csrrsi(p, GDB_REGNO_ZERO, CSR_DCSR_MPRVEN, - GDB_REGNO_DCSR) != ERROR_OK) - return ERROR_FAIL; - - if (riscv_program_load(p, d, b, offset, size) != ERROR_OK) - return ERROR_FAIL; - - if (mprven && riscv_program_csrrci(p, GDB_REGNO_ZERO, CSR_DCSR_MPRVEN, - GDB_REGNO_DCSR) != ERROR_OK) - return ERROR_FAIL; - - return ERROR_OK; + return mem_access_result(MEM_ACCESS_FAILED_REG_READ_FAILED); + set_buffer_and_log_read(args, index, value); + return mem_access_result(MEM_ACCESS_OK); } static int read_memory_progbuf_inner_fill_progbuf(struct target *target, - uint32_t increment, uint32_t size, bool mprven) + uint32_t increment, uint32_t size) { const bool is_repeated_read = increment == 0; @@ -4390,8 +4333,7 @@ static int read_memory_progbuf_inner_fill_progbuf(struct target *target, struct riscv_program program; riscv_program_init(&program, target); - if (riscv_program_load_mprv(&program, GDB_REGNO_S1, GDB_REGNO_S0, 0, size, - mprven) != ERROR_OK) + if (riscv_program_load(&program, GDB_REGNO_S1, GDB_REGNO_S0, 0, size) != ERROR_OK) return ERROR_FAIL; if (is_repeated_read) { if (riscv_program_addi(&program, GDB_REGNO_A0, GDB_REGNO_A0, 1) @@ -4416,19 +4358,19 @@ static int read_memory_progbuf_inner_fill_progbuf(struct target *target, * re-read the data only if `abstract command busy` or `DMI busy` * is encountered in the process. */ -static int read_memory_progbuf_inner(struct target *target, - struct memory_access_info access, uint32_t count, bool mprven) +static struct mem_access_result +read_memory_progbuf_inner(struct target *target, const riscv_mem_access_args_t args) { - assert(count > 1 && "If count == 1, read_memory_progbuf_inner_one must be called"); + assert(riscv_mem_access_is_read(args)); + assert(args.count > 1 && "If count == 1, read_memory_progbuf_inner_one must be called"); - if (read_memory_progbuf_inner_fill_progbuf(target, access.increment, - access.element_size, mprven) != ERROR_OK) - return ERROR_FAIL; + if (read_memory_progbuf_inner_fill_progbuf(target, + args.increment, args.size) != ERROR_OK) + return mem_access_result(MEM_ACCESS_SKIPPED_PROGBUF_FILL_FAILED); - if (read_memory_progbuf_inner_startup(target, access.target_address, - access.increment, /*index*/ 0) - != ERROR_OK) - return ERROR_FAIL; + if (read_memory_progbuf_inner_startup(target, args.address, + args.increment, /*index*/ 0) != ERROR_OK) + return mem_access_result(MEM_ACCESS_FAILED_PROGBUF_STARTUP_FAILED); /* The program in program buffer is executed twice during * read_memory_progbuf_inner_startup(). * Here: @@ -4439,20 +4381,20 @@ static int read_memory_progbuf_inner(struct target *target, * No need to execute the program any more, since S1 will already contain * M[address + increment * (count - 1)] and we can read it directly. */ - const uint32_t loop_count = count - 2; + const uint32_t loop_count = args.count - 2; for (uint32_t index = 0; index < loop_count;) { uint32_t elements_read; - if (read_memory_progbuf_inner_try_to_read(target, access, &elements_read, + if (read_memory_progbuf_inner_try_to_read(target, args, &elements_read, index, loop_count) != ERROR_OK) { dm_write(target, DM_ABSTRACTAUTO, 0); - return ERROR_FAIL; + return mem_access_result(MEM_ACCESS_FAILED_PROGBUF_INNER_FAILED); } if (elements_read == 0) { - if (read_memory_progbuf_inner_ensure_forward_progress(target, access, + if (read_memory_progbuf_inner_ensure_forward_progress(target, args, index) != ERROR_OK) { dm_write(target, DM_ABSTRACTAUTO, 0); - return ERROR_FAIL; + return mem_access_result(MEM_ACCESS_FAILED_NO_FORWARD_PROGRESS); } elements_read = 1; } @@ -4460,182 +4402,243 @@ static int read_memory_progbuf_inner(struct target *target, assert(index <= loop_count); } if (dm_write(target, DM_ABSTRACTAUTO, 0) != ERROR_OK) - return ERROR_FAIL; + return mem_access_result(MEM_ACCESS_FAILED_DM_ACCESS_FAILED); /* Read the penultimate word. */ - if (read_word_from_dm_data_regs(target, access, count - 2) - != ERROR_OK) - return ERROR_FAIL; + if (read_word_from_dm_data_regs(target, + args, args.count - 2) != ERROR_OK) + return mem_access_result(MEM_ACCESS_FAILED_DM_ACCESS_FAILED); /* Read the last word. */ - return read_word_from_s1(target, access, count - 1); + return read_word_from_s1(target, args, args.count - 1); } /** * Only need to save/restore one GPR to read a single word, and the progbuf * program doesn't need to increment. */ -static int read_memory_progbuf_inner_one(struct target *target, - struct memory_access_info access, bool mprven) +static struct mem_access_result +read_memory_progbuf_inner_one(struct target *target, const riscv_mem_access_args_t args) { + assert(riscv_mem_access_is_read(args)); + if (riscv013_reg_save(target, GDB_REGNO_S1) != ERROR_OK) - return ERROR_FAIL; + return mem_access_result(MEM_ACCESS_SKIPPED_REG_SAVE_FAILED); struct riscv_program program; riscv_program_init(&program, target); - if (riscv_program_load_mprv(&program, GDB_REGNO_S1, GDB_REGNO_S1, 0, - access.element_size, mprven) != ERROR_OK) - return ERROR_FAIL; - if (riscv_program_ebreak(&program) != ERROR_OK) - return ERROR_FAIL; + if (riscv_program_load(&program, GDB_REGNO_S1, GDB_REGNO_S1, + /* offset = */ 0, args.size) != ERROR_OK + || riscv_program_ebreak(&program) != ERROR_OK) + return mem_access_result(MEM_ACCESS_SKIPPED_PROGBUF_FILL_FAILED); + if (riscv_program_write(&program) != ERROR_OK) - return ERROR_FAIL; + return mem_access_result(MEM_ACCESS_SKIPPED_PROGRAM_WRITE_FAILED); /* Write address to S1, and execute buffer. */ - if (write_abstract_arg(target, 0, access.target_address, riscv_xlen(target)) - != ERROR_OK) - return ERROR_FAIL; - uint32_t command = access_register_command(target, GDB_REGNO_S1, + if (write_abstract_arg(target, /* index = */ 0, + args.address, riscv_xlen(target)) != ERROR_OK) + return mem_access_result(MEM_ACCESS_SKIPPED_WRITE_ABSTRACT_ARG_FAILED); + uint32_t command = riscv013_access_register_command(target, GDB_REGNO_S1, riscv_xlen(target), AC_ACCESS_REGISTER_WRITE | AC_ACCESS_REGISTER_TRANSFER | AC_ACCESS_REGISTER_POSTEXEC); uint32_t cmderr; - if (execute_abstract_command(target, command, &cmderr) != ERROR_OK) - return ERROR_FAIL; + if (riscv013_execute_abstract_command(target, command, &cmderr) != ERROR_OK) + return mem_access_result(MEM_ACCESS_FAILED_EXECUTE_ABSTRACT_FAILED); - return read_word_from_s1(target, access, 0); + return read_word_from_s1(target, args, 0); } /** * Read the requested memory, silently handling memory access errors. */ -static int read_memory_progbuf(struct target *target, target_addr_t address, - uint32_t size, uint32_t count, uint8_t *buffer, uint32_t increment) +static struct mem_access_result +read_memory_progbuf(struct target *target, const riscv_mem_access_args_t args) { - if (riscv_xlen(target) < size * 8) { - LOG_TARGET_ERROR(target, "XLEN (%d) is too short for %" - PRIu32 "-bit memory read.", riscv_xlen(target), size * 8); - return ERROR_FAIL; - } + assert(riscv_mem_access_is_read(args)); - LOG_TARGET_DEBUG(target, "reading %" PRIu32 " elements of %" PRIu32 - " bytes from 0x%" TARGET_PRIxADDR, count, size, address); + select_dmi(target->tap); + memset(args.read_buffer, 0, args.count * args.size); - if (dm013_select_target(target) != ERROR_OK) - return ERROR_FAIL; + if (execute_autofence(target) != ERROR_OK) + return mem_access_result(MEM_ACCESS_SKIPPED_FENCE_EXEC_FAILED); - select_dmi(target); + return (args.count == 1) ? + read_memory_progbuf_inner_one(target, args) : + read_memory_progbuf_inner(target, args); +} - memset(buffer, 0, count*size); +static struct mem_access_result +write_memory_progbuf(struct target *target, const riscv_mem_access_args_t args); - if (execute_fence(target) != ERROR_OK) - return ERROR_FAIL; +static struct mem_access_result +access_memory_progbuf(struct target *target, const riscv_mem_access_args_t args) +{ + struct mem_access_result skip_reason = mem_should_skip_progbuf(target, args); + if (!is_mem_access_ok(skip_reason)) + return skip_reason; - uint64_t mstatus = 0; - uint64_t mstatus_old = 0; - if (modify_privilege(target, &mstatus, &mstatus_old) != ERROR_OK) - return ERROR_FAIL; + const bool is_read = riscv_mem_access_is_read(args); + const char *const access_type = is_read ? "reading" : "writing"; + LOG_TARGET_DEBUG(target, "%s %" PRIu32 " words of %" PRIu32 + " bytes at 0x%" TARGET_PRIxADDR, access_type, args.count, + args.size, args.address); - const bool mprven = riscv_enable_virtual && get_field(mstatus, MSTATUS_MPRV); - const struct memory_access_info access = { - .target_address = address, - .increment = increment, - .buffer_address = buffer, - .element_size = size, - }; - int result = (count == 1) ? - read_memory_progbuf_inner_one(target, access, mprven) : - read_memory_progbuf_inner(target, access, count, mprven); + if (dm013_select_target(target) != ERROR_OK) + return mem_access_result(MEM_ACCESS_SKIPPED_TARGET_SELECT_FAILED); - if (mstatus != mstatus_old && - register_write_direct(target, GDB_REGNO_MSTATUS, mstatus_old) != ERROR_OK) - return ERROR_FAIL; + riscv_reg_t mstatus = 0; + riscv_reg_t mstatus_old = 0; + riscv_reg_t dcsr = 0; + riscv_reg_t dcsr_old = 0; + if (modify_privilege_for_virt2phys_mode(target, + &mstatus, &mstatus_old, &dcsr, &dcsr_old) != ERROR_OK) + return mem_access_result(MEM_ACCESS_SKIPPED_PRIV_MOD_FAILED); + + struct mem_access_result result = is_read ? + read_memory_progbuf(target, args) : + write_memory_progbuf(target, args); + + if (restore_privilege_from_virt2phys_mode(target, + mstatus, mstatus_old, dcsr, dcsr_old) != ERROR_OK) + return mem_access_result(MEM_ACCESS_FAILED_PRIV_MOD_FAILED); return result; } -static int read_memory(struct target *target, target_addr_t address, - uint32_t size, uint32_t count, uint8_t *buffer, uint32_t increment) +static int +write_memory_bus_v0(struct target *target, const riscv_mem_access_args_t args); +static int +write_memory_bus_v1(struct target *target, const riscv_mem_access_args_t args); + +static struct mem_access_result +access_memory_sysbus(struct target *target, const riscv_mem_access_args_t args) { - if (count == 0) - return ERROR_OK; + assert(riscv_mem_access_is_valid(args)); - if (size != 1 && size != 2 && size != 4 && size != 8 && size != 16) { - LOG_TARGET_ERROR(target, "BUG: Unsupported size for memory read: %d", size); - return ERROR_FAIL; - } + struct mem_access_result skip_reason = mem_should_skip_sysbus(target, args); + if (!is_mem_access_ok(skip_reason)) + return skip_reason; - int ret = ERROR_FAIL; - RISCV_INFO(r); RISCV013_INFO(info); + int ret = ERROR_FAIL; + const bool is_read = riscv_mem_access_is_read(args); + const uint64_t sbver = get_field(info->sbcs, DM_SBCS_SBVERSION); + if (sbver == 0) { + ret = is_read ? read_memory_bus_v0(target, args) : + write_memory_bus_v0(target, args); + } else if (sbver == 1) { + ret = is_read ? read_memory_bus_v1(target, args) : + write_memory_bus_v1(target, args); + } else { + LOG_TARGET_ERROR(target, "Unknown system bus version: %" PRIu64, sbver); + return mem_access_result(MEM_ACCESS_SKIPPED_UNKNOWN_SYSBUS_VERSION); + } - char *progbuf_result = "disabled"; - char *sysbus_result = "disabled"; - char *abstract_result = "disabled"; + return mem_access_result(ret == ERROR_OK ? + MEM_ACCESS_OK : MEM_ACCESS_SKIPPED_SYSBUS_ACCESS_FAILED); +} - for (unsigned int i = 0; i < RISCV_NUM_MEM_ACCESS_METHODS; i++) { - int method = r->mem_access_methods[i]; +static struct mem_access_result +access_memory_abstract(struct target *target, const riscv_mem_access_args_t args) +{ + assert(riscv_mem_access_is_valid(args)); - if (method == RISCV_MEM_ACCESS_PROGBUF) { - if (mem_should_skip_progbuf(target, address, size, true, &progbuf_result)) - continue; + struct mem_access_result skip_reason = mem_should_skip_abstract(target, args); + if (!is_mem_access_ok(skip_reason)) + return skip_reason; - ret = read_memory_progbuf(target, address, size, count, buffer, increment); + const bool is_read = riscv_mem_access_is_read(args); + const char *const access_type = is_read ? "reading" : "writing"; + LOG_TARGET_DEBUG(target, "%s %d words of %d bytes at 0x%" + TARGET_PRIxADDR, access_type, args.count, + args.size, args.address); - if (ret != ERROR_OK) - progbuf_result = "failed"; - } else if (method == RISCV_MEM_ACCESS_SYSBUS) { - if (mem_should_skip_sysbus(target, address, size, increment, true, &sysbus_result)) - continue; + return is_read ? read_memory_abstract(target, args) : + write_memory_abstract(target, args); +} - if (get_field(info->sbcs, DM_SBCS_SBVERSION) == 0) - ret = read_memory_bus_v0(target, address, size, count, buffer, increment); - else if (get_field(info->sbcs, DM_SBCS_SBVERSION) == 1) - ret = read_memory_bus_v1(target, address, size, count, buffer, increment); +static int +riscv013_access_memory(struct target *target, const riscv_mem_access_args_t args) +{ + assert(riscv_mem_access_is_valid(args)); - if (ret != ERROR_OK) - sysbus_result = "failed"; - } else if (method == RISCV_MEM_ACCESS_ABSTRACT) { - if (mem_should_skip_abstract(target, address, size, increment, true, &abstract_result)) - continue; + const bool is_read = riscv_mem_access_is_read(args); + const char *const access_type = is_read ? "read" : "write"; + if (!is_read && args.increment != args.size) { + LOG_TARGET_ERROR(target, "Write increment size has to be equal to element size"); + return ERROR_NOT_IMPLEMENTED; + } - ret = read_memory_abstract(target, address, size, count, buffer, increment); + if (!IS_PWR_OF_2(args.size) || args.size < 1 || args.size > 16) { + LOG_TARGET_ERROR(target, "BUG: Unsupported size for " + "memory %s: %d", access_type, args.size); + return ERROR_FAIL; + } - if (ret != ERROR_OK) - abstract_result = "failed"; - } else if (method == RISCV_MEM_ACCESS_UNSPECIFIED) - /* No further mem access method to try. */ - break; + struct mem_access_result skip_reason[] = { + [RISCV_MEM_ACCESS_PROGBUF] = mem_access_result(MEM_ACCESS_DISABLED), + [RISCV_MEM_ACCESS_SYSBUS] = mem_access_result(MEM_ACCESS_DISABLED), + [RISCV_MEM_ACCESS_ABSTRACT] = mem_access_result(MEM_ACCESS_DISABLED), + }; + + RISCV_INFO(r); + for (unsigned int i = 0; i < r->num_enabled_mem_access_methods; ++i) { + riscv_mem_access_method_t method = r->mem_access_methods[i]; + switch (method) { + case RISCV_MEM_ACCESS_PROGBUF: + skip_reason[method] = access_memory_progbuf(target, args); + break; + case RISCV_MEM_ACCESS_SYSBUS: + skip_reason[method] = access_memory_sysbus(target, args); + break; + case RISCV_MEM_ACCESS_ABSTRACT: + skip_reason[method] = access_memory_abstract(target, args); + break; + default: + LOG_TARGET_ERROR(target, "Unknown memory access method: %d", method); + assert(false && "Unknown memory access method"); + goto failure; + } - log_mem_access_result(target, ret == ERROR_OK, method, true); + if (is_mem_access_failed(skip_reason[method])) + goto failure; - if (ret == ERROR_OK) - return ret; + const bool success = is_mem_access_ok(skip_reason[method]); + log_mem_access_result(target, success, method, is_read); + if (success) + return ERROR_OK; } - LOG_TARGET_ERROR(target, "Failed to read memory (addr=0x%" PRIx64 ")", address); - LOG_TARGET_ERROR(target, " progbuf=%s, sysbus=%s, abstract=%s", progbuf_result, sysbus_result, abstract_result); - return ret; +failure: + LOG_TARGET_ERROR(target, "Failed to %s memory (addr=0x%" PRIx64 ")\n" + " progbuf=%s, sysbus=%s, abstract=%s", access_type, args.address, + mem_access_result_to_str(skip_reason[RISCV_MEM_ACCESS_PROGBUF]), + mem_access_result_to_str(skip_reason[RISCV_MEM_ACCESS_SYSBUS]), + mem_access_result_to_str(skip_reason[RISCV_MEM_ACCESS_ABSTRACT])); + return ERROR_FAIL; } -static int write_memory_bus_v0(struct target *target, target_addr_t address, - uint32_t size, uint32_t count, const uint8_t *buffer) +static int write_memory_bus_v0(struct target *target, const riscv_mem_access_args_t args) { + assert(riscv_mem_access_is_write(args)); + /*1) write sbaddress: for singlewrite and autoincrement, we need to write the address once*/ LOG_TARGET_DEBUG(target, "System Bus Access: size: %d\tcount:%d\tstart address: 0x%08" - TARGET_PRIxADDR, size, count, address); - dm_write(target, DM_SBADDRESS0, address); + TARGET_PRIxADDR, args.size, args.count, args.address); + dm_write(target, DM_SBADDRESS0, args.address); int64_t value = 0; int64_t access = 0; riscv_addr_t offset = 0; riscv_addr_t t_addr = 0; - const uint8_t *t_buffer = buffer + offset; + const uint8_t *t_buffer = args.write_buffer + offset; /* B.8 Writing Memory, single write check if we write in one go */ - if (count == 1) { /* count is in bytes here */ - value = buf_get_u64(t_buffer, 0, 8 * size); + if (args.count == 1) { /* count is in bytes here */ + value = buf_get_u64(t_buffer, 0, 8 * args.size); access = 0; - access = set_field(access, DM_SBCS_SBACCESS, size/2); + access = set_field(access, DM_SBCS_SBACCESS, args.size / 2); dm_write(target, DM_SBCS, access); LOG_TARGET_DEBUG(target, " access: 0x%08" PRIx64, access); LOG_TARGET_DEBUG(target, " write_memory:SAB: ONE OFF: value 0x%08" PRIx64, value); @@ -4646,19 +4649,19 @@ static int write_memory_bus_v0(struct target *target, target_addr_t address, /*B.8 Writing Memory, using autoincrement*/ access = 0; - access = set_field(access, DM_SBCS_SBACCESS, size/2); + access = set_field(access, DM_SBCS_SBACCESS, args.size / 2); access = set_field(access, DM_SBCS_SBAUTOINCREMENT, 1); LOG_TARGET_DEBUG(target, " access: 0x%08" PRIx64, access); dm_write(target, DM_SBCS, access); /*2)set the value according to the size required and write*/ - for (riscv_addr_t i = 0; i < count; ++i) { - offset = size*i; + for (riscv_addr_t i = 0; i < args.count; ++i) { + offset = args.size * i; /* for monitoring only */ - t_addr = address + offset; - t_buffer = buffer + offset; + t_addr = args.address + offset; + t_buffer = args.write_buffer + offset; - value = buf_get_u64(t_buffer, 0, 8 * size); + value = buf_get_u64(t_buffer, 0, 8 * args.size); LOG_TARGET_DEBUG(target, "SAB:autoincrement: expected address: 0x%08x value: 0x%08x" PRIx64, (uint32_t)t_addr, (uint32_t)value); dm_write(target, DM_SBDATA0, value); @@ -4670,20 +4673,22 @@ static int write_memory_bus_v0(struct target *target, target_addr_t address, return ERROR_OK; } -static int write_memory_bus_v1(struct target *target, target_addr_t address, - uint32_t size, uint32_t count, const uint8_t *buffer) +static int write_memory_bus_v1(struct target *target, const riscv_mem_access_args_t args) { + assert(riscv_mem_access_is_write(args)); + RISCV013_INFO(info); - uint32_t sbcs = sb_sbaccess(size); + uint32_t sbcs = sb_sbaccess(args.size); sbcs = set_field(sbcs, DM_SBCS_SBAUTOINCREMENT, 1); dm_write(target, DM_SBCS, sbcs); - target_addr_t next_address = address; - target_addr_t end_address = address + count * size; + target_addr_t next_address = args.address; + target_addr_t end_address = args.address + args.count * args.size; - int result; + int result = sb_write_address(target, next_address, RISCV_DELAY_BASE); + if (result != ERROR_OK) + return result; - sb_write_address(target, next_address, true); while (next_address < end_address) { LOG_TARGET_DEBUG(target, "Transferring burst starting at address 0x%" TARGET_PRIxADDR, next_address); @@ -4692,53 +4697,47 @@ static int write_memory_bus_v1(struct target *target, target_addr_t address, if (!batch) return ERROR_FAIL; - for (uint32_t i = (next_address - address) / size; i < count; i++) { - const uint8_t *p = buffer + i * size; + for (uint32_t i = (next_address - args.address) / args.size; i < args.count; i++) { + const uint8_t *p = args.write_buffer + i * args.size; - if (riscv_batch_available_scans(batch) < (size + 3) / 4) + if (riscv_batch_available_scans(batch) < (args.size + 3) / 4) break; uint32_t sbvalue[4] = { 0 }; - if (size > 12) { - sbvalue[3] = ((uint32_t)p[12]) | - (((uint32_t)p[13]) << 8) | - (((uint32_t)p[14]) << 16) | - (((uint32_t)p[15]) << 24); + if (args.size > 12) { + sbvalue[3] = buf_get_u32(&p[12], + /* first = */ 0, /* bit_num = */ 32); riscv_batch_add_dm_write(batch, DM_SBDATA3, sbvalue[3], false, RISCV_DELAY_BASE); } - if (size > 8) { - sbvalue[2] = ((uint32_t)p[8]) | - (((uint32_t)p[9]) << 8) | - (((uint32_t)p[10]) << 16) | - (((uint32_t)p[11]) << 24); + if (args.size > 8) { + sbvalue[2] = buf_get_u32(&p[8], + /* first = */ 0, /* bit_num = */ 32); riscv_batch_add_dm_write(batch, DM_SBDATA2, sbvalue[2], false, RISCV_DELAY_BASE); } - if (size > 4) { - sbvalue[1] = ((uint32_t)p[4]) | - (((uint32_t)p[5]) << 8) | - (((uint32_t)p[6]) << 16) | - (((uint32_t)p[7]) << 24); + if (args.size > 4) { + sbvalue[1] = buf_get_u32(&p[4], + /* first = */ 0, /* bit_num = */ 32); riscv_batch_add_dm_write(batch, DM_SBDATA1, sbvalue[1], false, RISCV_DELAY_BASE); } sbvalue[0] = p[0]; - if (size > 2) { + if (args.size > 2) { sbvalue[0] |= ((uint32_t)p[2]) << 16; sbvalue[0] |= ((uint32_t)p[3]) << 24; } - if (size > 1) + if (args.size > 1) sbvalue[0] |= ((uint32_t)p[1]) << 8; riscv_batch_add_dm_write(batch, DM_SBDATA0, sbvalue[0], false, RISCV_DELAY_SYSBUS_WRITE); - log_memory_access(address + i * size, sbvalue, size, false); + log_memory_access(args.address + i * args.size, sbvalue, args.size, false); - next_address += size; + next_address += args.size; } /* Execute the batch of writes */ @@ -4773,7 +4772,7 @@ static int write_memory_bus_v1(struct target *target, target_addr_t address, /* Recover from the case when the write commands were issued too fast. * Determine the address from which to resume writing. */ next_address = sb_read_address(target); - if (next_address < address) { + if (next_address < args.address) { /* This should never happen, probably buggy hardware. */ LOG_TARGET_DEBUG(target, "unexpected sbaddress=0x%" TARGET_PRIxADDR " - buggy sbautoincrement in hw?", next_address); @@ -4793,7 +4792,7 @@ static int write_memory_bus_v1(struct target *target, target_addr_t address, target_addr_t sbaddress = sb_read_address(target); LOG_TARGET_DEBUG(target, "System bus access failed with sberror=%u (sbaddress=0x%" TARGET_PRIxADDR ")", sberror, sbaddress); - if (sbaddress < address) { + if (sbaddress < args.address) { /* This should never happen, probably buggy hardware. * Make a note to the user not to trust the sbaddress value. */ LOG_TARGET_DEBUG(target, "unexpected sbaddress=0x%" TARGET_PRIxADDR @@ -4837,14 +4836,14 @@ static int write_memory_progbuf_startup(struct target *target, target_addr_t *ad /* Write and execute command that moves the value from data0 [, data1] * into S1 and executes program buffer. */ - uint32_t command = access_register_command(target, + uint32_t command = riscv013_access_register_command(target, GDB_REGNO_S1, riscv_xlen(target), AC_ACCESS_REGISTER_POSTEXEC | AC_ACCESS_REGISTER_TRANSFER | AC_ACCESS_REGISTER_WRITE); uint32_t cmderr; - if (execute_abstract_command(target, command, &cmderr) != ERROR_OK) + if (riscv013_execute_abstract_command(target, command, &cmderr) != ERROR_OK) return ERROR_FAIL; log_memory_access64(*address_p, value, size, /*is_read*/ false); @@ -4995,25 +4994,7 @@ static int write_memory_progbuf_try_to_write(struct target *target, return result; } -static int riscv_program_store_mprv(struct riscv_program *p, enum gdb_regno d, - enum gdb_regno b, int offset, unsigned int size, bool mprven) -{ - if (mprven && riscv_program_csrrsi(p, GDB_REGNO_ZERO, CSR_DCSR_MPRVEN, - GDB_REGNO_DCSR) != ERROR_OK) - return ERROR_FAIL; - - if (riscv_program_store(p, d, b, offset, size) != ERROR_OK) - return ERROR_FAIL; - - if (mprven && riscv_program_csrrci(p, GDB_REGNO_ZERO, CSR_DCSR_MPRVEN, - GDB_REGNO_DCSR) != ERROR_OK) - return ERROR_FAIL; - - return ERROR_OK; -} - -static int write_memory_progbuf_fill_progbuf(struct target *target, - uint32_t size, bool mprven) +static int write_memory_progbuf_fill_progbuf(struct target *target, uint32_t size) { if (riscv013_reg_save(target, GDB_REGNO_S0) != ERROR_OK) return ERROR_FAIL; @@ -5023,11 +5004,10 @@ static int write_memory_progbuf_fill_progbuf(struct target *target, struct riscv_program program; riscv_program_init(&program, target); - if (riscv_program_store_mprv(&program, GDB_REGNO_S1, GDB_REGNO_S0, 0, size, - mprven) != ERROR_OK) + if (riscv_program_store(&program, GDB_REGNO_S1, GDB_REGNO_S0, 0, size) != ERROR_OK) return ERROR_FAIL; - if (riscv_program_addi(&program, GDB_REGNO_S0, GDB_REGNO_S0, size) != ERROR_OK) + if (riscv_program_addi(&program, GDB_REGNO_S0, GDB_REGNO_S0, (int16_t)size) != ERROR_OK) return ERROR_FAIL; if (riscv_program_ebreak(&program) != ERROR_OK) @@ -5036,131 +5016,65 @@ static int write_memory_progbuf_fill_progbuf(struct target *target, return riscv_program_write(&program); } -static int write_memory_progbuf_inner(struct target *target, target_addr_t start_addr, - uint32_t size, uint32_t count, const uint8_t *buffer, bool mprven) +static struct mem_access_result +write_memory_progbuf_inner(struct target *target, + const riscv_mem_access_args_t args) { - if (write_memory_progbuf_fill_progbuf(target, size, - mprven) != ERROR_OK) - return ERROR_FAIL; + assert(riscv_mem_access_is_write(args)); - target_addr_t addr_on_target = start_addr; - if (write_memory_progbuf_startup(target, &addr_on_target, buffer, size) != ERROR_OK) - return ERROR_FAIL; + if (write_memory_progbuf_fill_progbuf(target, args.size) != ERROR_OK) + return mem_access_result(MEM_ACCESS_SKIPPED_PROGBUF_FILL_FAILED); - const target_addr_t end_addr = start_addr + (target_addr_t)size * count; + target_addr_t addr_on_target = args.address; + if (write_memory_progbuf_startup(target, &addr_on_target, + args.write_buffer, args.size) != ERROR_OK) + return mem_access_result(MEM_ACCESS_FAILED_PROGBUF_STARTUP_FAILED); + + const target_addr_t end_addr = args.address + (target_addr_t)args.size * args.count; for (target_addr_t next_addr_on_target = addr_on_target; addr_on_target != end_addr; addr_on_target = next_addr_on_target) { - const uint8_t * const curr_buff = buffer + (addr_on_target - start_addr); + const uint8_t * const curr_buff = args.write_buffer + (addr_on_target - args.address); if (write_memory_progbuf_try_to_write(target, &next_addr_on_target, - end_addr, size, curr_buff) != ERROR_OK) { + end_addr, args.size, curr_buff) != ERROR_OK) { write_memory_progbuf_teardown(target); - return ERROR_FAIL; + return mem_access_result(MEM_ACCESS_FAILED_PROGBUF_INNER_FAILED); } /* write_memory_progbuf_try_to_write() ensures that at least one item * gets successfully written even when busy condition is encountered. * These assertions shuld hold when next_address_on_target overflows. */ assert(next_addr_on_target - addr_on_target > 0); - assert(next_addr_on_target - start_addr <= (target_addr_t)size * count); + assert(next_addr_on_target - args.address <= (target_addr_t)args.size * args.count); } - return write_memory_progbuf_teardown(target); + return write_memory_progbuf_teardown(target) == ERROR_OK ? + mem_access_result(MEM_ACCESS_OK) : + mem_access_result(MEM_ACCESS_FAILED_PROGBUF_TEARDOWN_FAILED); } -static int write_memory_progbuf(struct target *target, target_addr_t address, - uint32_t size, uint32_t count, const uint8_t *buffer) +static struct mem_access_result +write_memory_progbuf(struct target *target, const riscv_mem_access_args_t args) { - if (riscv_xlen(target) < size * 8) { - LOG_TARGET_ERROR(target, "XLEN (%u) is too short for %" PRIu32 "-bit memory write.", - riscv_xlen(target), size * 8); - return ERROR_FAIL; - } + assert(riscv_mem_access_is_write(args)); - LOG_TARGET_DEBUG(target, "writing %" PRIu32 " words of %" PRIu32 - " bytes to 0x%" TARGET_PRIxADDR, count, size, address); + struct mem_access_result result = write_memory_progbuf_inner(target, args); - if (dm013_select_target(target) != ERROR_OK) - return ERROR_FAIL; - - uint64_t mstatus = 0; - uint64_t mstatus_old = 0; - if (modify_privilege(target, &mstatus, &mstatus_old) != ERROR_OK) - return ERROR_FAIL; - - const bool mprven = riscv_enable_virtual && get_field(mstatus, MSTATUS_MPRV); - - int result = write_memory_progbuf_inner(target, address, size, count, buffer, mprven); - - /* Restore MSTATUS */ - if (mstatus != mstatus_old) - if (register_write_direct(target, GDB_REGNO_MSTATUS, mstatus_old)) - return ERROR_FAIL; - - if (execute_fence(target) != ERROR_OK) - return ERROR_FAIL; + if (execute_autofence(target) != ERROR_OK) + return mem_access_result(MEM_ACCESS_FAILED_FENCE_EXEC_FAILED); return result; } -static int write_memory(struct target *target, target_addr_t address, - uint32_t size, uint32_t count, const uint8_t *buffer) +static bool riscv013_get_impebreak(const struct target *target) { - if (size != 1 && size != 2 && size != 4 && size != 8 && size != 16) { - LOG_TARGET_ERROR(target, "BUG: Unsupported size for memory write: %d", size); - return ERROR_FAIL; - } - - int ret = ERROR_FAIL; - RISCV_INFO(r); - RISCV013_INFO(info); - - char *progbuf_result = "disabled"; - char *sysbus_result = "disabled"; - char *abstract_result = "disabled"; - - for (unsigned int i = 0; i < RISCV_NUM_MEM_ACCESS_METHODS; i++) { - int method = r->mem_access_methods[i]; - - if (method == RISCV_MEM_ACCESS_PROGBUF) { - if (mem_should_skip_progbuf(target, address, size, false, &progbuf_result)) - continue; - - ret = write_memory_progbuf(target, address, size, count, buffer); - - if (ret != ERROR_OK) - progbuf_result = "failed"; - } else if (method == RISCV_MEM_ACCESS_SYSBUS) { - if (mem_should_skip_sysbus(target, address, size, 0, false, &sysbus_result)) - continue; - - if (get_field(info->sbcs, DM_SBCS_SBVERSION) == 0) - ret = write_memory_bus_v0(target, address, size, count, buffer); - else if (get_field(info->sbcs, DM_SBCS_SBVERSION) == 1) - ret = write_memory_bus_v1(target, address, size, count, buffer); - - if (ret != ERROR_OK) - sysbus_result = "failed"; - } else if (method == RISCV_MEM_ACCESS_ABSTRACT) { - if (mem_should_skip_abstract(target, address, size, 0, false, &abstract_result)) - continue; - - ret = write_memory_abstract(target, address, size, count, buffer); - - if (ret != ERROR_OK) - abstract_result = "failed"; - } else if (method == RISCV_MEM_ACCESS_UNSPECIFIED) - /* No further mem access method to try. */ - break; - - log_mem_access_result(target, ret == ERROR_OK, method, false); - - if (ret == ERROR_OK) - return ret; - } + RISCV013_INFO(r); + return r->impebreak; +} - LOG_TARGET_ERROR(target, "Target %s: Failed to write memory (addr=0x%" PRIx64 ")", target_name(target), address); - LOG_TARGET_ERROR(target, " progbuf=%s, sysbus=%s, abstract=%s", progbuf_result, sysbus_result, abstract_result); - return ret; +static unsigned int riscv013_get_progbufsize(const struct target *target) +{ + RISCV013_INFO(r); + return r->progbufsize; } static int arch_state(struct target *target) @@ -5182,8 +5096,6 @@ struct target_type riscv013_target = { .assert_reset = assert_reset, .deassert_reset = deassert_reset, - .write_memory = write_memory, - .arch_state = arch_state }; @@ -5267,13 +5179,13 @@ static int select_prepped_harts(struct target *target) } assert(dm->hart_count); - unsigned hawindow_count = (dm->hart_count + 31) / 32; + unsigned int hawindow_count = (dm->hart_count + 31) / 32; uint32_t *hawindow = calloc(hawindow_count, sizeof(uint32_t)); if (!hawindow) return ERROR_FAIL; target_list_t *entry; - unsigned total_selected = 0; + unsigned int total_selected = 0; unsigned int selected_index = 0; list_for_each_entry(entry, &dm->target_list, list) { struct target *t = entry->target; @@ -5305,7 +5217,7 @@ static int select_prepped_harts(struct target *target) return ERROR_FAIL; } - for (unsigned i = 0; i < hawindow_count; i++) { + for (unsigned int i = 0; i < hawindow_count; i++) { if (dm_write(target, DM_HAWINDOWSEL, i) != ERROR_OK) { free(hawindow); return ERROR_FAIL; @@ -5471,9 +5383,12 @@ static enum riscv_halt_reason riscv013_halt_reason(struct target *target) static int riscv013_write_progbuf(struct target *target, unsigned int index, riscv_insn_t data) { + assert(index < RISCV013_MAX_PROGBUF_SIZE); + dm013_info_t *dm = get_dm(target); if (!dm) return ERROR_FAIL; + if (dm->progbuf_cache[index] != data) { if (dm_write(target, DM_PROGBUF0 + index, data) != ERROR_OK) return ERROR_FAIL; @@ -5502,8 +5417,7 @@ static int riscv013_invalidate_cached_progbuf(struct target *target) } LOG_TARGET_DEBUG(target, "Invalidating progbuf cache"); - for (unsigned int i = 0; i < 15; i++) - dm->progbuf_cache[i] = 0; + memset(dm->progbuf_cache, 0, sizeof(dm->progbuf_cache)); return ERROR_OK; } @@ -5515,72 +5429,45 @@ static int riscv013_execute_progbuf(struct target *target, uint32_t *cmderr) run_program = set_field(run_program, AC_ACCESS_REGISTER_TRANSFER, 0); run_program = set_field(run_program, AC_ACCESS_REGISTER_REGNO, 0x1000); - return execute_abstract_command(target, run_program, cmderr); + return riscv013_execute_abstract_command(target, run_program, cmderr); } -static void riscv013_fill_dmi_write(struct target *target, char *buf, uint64_t a, uint32_t d) +static void riscv013_fill_dmi_write(const struct target *target, uint8_t *buf, uint32_t a, uint32_t d) { RISCV013_INFO(info); - buf_set_u64((unsigned char *)buf, DTM_DMI_OP_OFFSET, DTM_DMI_OP_LENGTH, DMI_OP_WRITE); - buf_set_u64((unsigned char *)buf, DTM_DMI_DATA_OFFSET, DTM_DMI_DATA_LENGTH, d); - buf_set_u64((unsigned char *)buf, DTM_DMI_ADDRESS_OFFSET, info->abits, a); + buf_set_u32(buf, DTM_DMI_OP_OFFSET, DTM_DMI_OP_LENGTH, DMI_OP_WRITE); + buf_set_u32(buf, DTM_DMI_DATA_OFFSET, DTM_DMI_DATA_LENGTH, d); + buf_set_u32(buf, DTM_DMI_ADDRESS_OFFSET, info->abits, a); } -static void riscv013_fill_dmi_read(struct target *target, char *buf, uint64_t a) +static void riscv013_fill_dmi_read(const struct target *target, uint8_t *buf, uint32_t a) { RISCV013_INFO(info); - buf_set_u64((unsigned char *)buf, DTM_DMI_OP_OFFSET, DTM_DMI_OP_LENGTH, DMI_OP_READ); - buf_set_u64((unsigned char *)buf, DTM_DMI_DATA_OFFSET, DTM_DMI_DATA_LENGTH, 0); - buf_set_u64((unsigned char *)buf, DTM_DMI_ADDRESS_OFFSET, info->abits, a); + buf_set_u32(buf, DTM_DMI_OP_OFFSET, DTM_DMI_OP_LENGTH, DMI_OP_READ); + buf_set_u32(buf, DTM_DMI_DATA_OFFSET, DTM_DMI_DATA_LENGTH, 0); + buf_set_u32(buf, DTM_DMI_ADDRESS_OFFSET, info->abits, a); } -static void riscv013_fill_dmi_nop(struct target *target, char *buf) +static void riscv013_fill_dm_nop(const struct target *target, uint8_t *buf) { RISCV013_INFO(info); - buf_set_u64((unsigned char *)buf, DTM_DMI_OP_OFFSET, DTM_DMI_OP_LENGTH, DMI_OP_NOP); - buf_set_u64((unsigned char *)buf, DTM_DMI_DATA_OFFSET, DTM_DMI_DATA_LENGTH, 0); - buf_set_u64((unsigned char *)buf, DTM_DMI_ADDRESS_OFFSET, info->abits, 0); + buf_set_u32(buf, DTM_DMI_OP_OFFSET, DTM_DMI_OP_LENGTH, DMI_OP_NOP); + buf_set_u32(buf, DTM_DMI_DATA_OFFSET, DTM_DMI_DATA_LENGTH, 0); + buf_set_u32(buf, DTM_DMI_ADDRESS_OFFSET, info->abits, 0); } -static int riscv013_get_dmi_scan_length(struct target *target) +static unsigned int riscv013_get_dmi_address_bits(const struct target *target) { RISCV013_INFO(info); - return info->abits + DTM_DMI_DATA_LENGTH + DTM_DMI_OP_LENGTH; -} - -void riscv013_fill_dm_write(struct target *target, char *buf, uint64_t a, uint32_t d) -{ - dm013_info_t *dm = get_dm(target); - if (!dm) - return; - riscv013_fill_dmi_write(target, buf, a + dm->base, d); -} - -void riscv013_fill_dm_read(struct target *target, char *buf, uint64_t a) -{ - dm013_info_t *dm = get_dm(target); - if (!dm) - return; - riscv013_fill_dmi_read(target, buf, a + dm->base); -} - -void riscv013_fill_dm_nop(struct target *target, char *buf) -{ - riscv013_fill_dmi_nop(target, buf); -} - -static int maybe_execute_fence_i(struct target *target) -{ - if (has_sufficient_progbuf(target, 2)) - return execute_fence(target); - return ERROR_OK; + return info->abits; } /* Helper Functions. */ static int riscv013_on_step_or_resume(struct target *target, bool step) { - if (maybe_execute_fence_i(target) != ERROR_OK) - return ERROR_FAIL; + if (has_sufficient_progbuf(target, 2)) + if (execute_autofence(target) != ERROR_OK) + return ERROR_FAIL; if (set_dcsr_ebreak(target, step) != ERROR_OK) return ERROR_FAIL; @@ -5597,11 +5484,15 @@ static int riscv013_step_or_resume_current_hart(struct target *target, LOG_TARGET_ERROR(target, "Hart is not halted!"); return ERROR_FAIL; } - LOG_TARGET_DEBUG(target, "resuming (for step?=%d)", step); + + LOG_TARGET_DEBUG(target, "resuming (operation=%s)", + step ? "single-step" : "resume"); if (riscv_reg_flush_all(target) != ERROR_OK) return ERROR_FAIL; + riscv_reg_cache_invalidate_all(target); + dm013_info_t *dm = get_dm(target); /* Issue the resume command, and then wait for the current hart to resume. */ uint32_t dmcontrol = DM_DMCONTROL_DMACTIVE | DM_DMCONTROL_RESUMEREQ; @@ -5630,16 +5521,26 @@ static int riscv013_step_or_resume_current_hart(struct target *target, return ERROR_OK; } + LOG_TARGET_ERROR(target, "Failed to %s. dmstatus=0x%08x", + step ? "single-step" : "resume", dmstatus); + dm_write(target, DM_DMCONTROL, dmcontrol); + LOG_TARGET_ERROR(target, + " cancelling the resume request (dmcontrol.resumereq <- 0)"); - LOG_TARGET_ERROR(target, "unable to resume"); if (dmstatus_read(target, &dmstatus, true) != ERROR_OK) return ERROR_FAIL; - LOG_TARGET_ERROR(target, " dmstatus=0x%08x", dmstatus); + + LOG_TARGET_ERROR(target, " dmstatus after cancellation=0x%08x", dmstatus); if (step) { - LOG_TARGET_ERROR(target, " was stepping, halting"); - riscv_halt(target); + LOG_TARGET_ERROR(target, + " trying to recover from a failed single-step, by requesting halt"); + if (riscv_halt(target) == ERROR_OK) + LOG_TARGET_ERROR(target, " halt completed after failed single-step"); + else + LOG_TARGET_ERROR(target, " could not halt, something is wrong with the taget"); + // TODO: returning ERROR_OK is questionable, this code needs to be revised return ERROR_OK; } diff --git a/src/target/riscv/riscv-013.h b/src/target/riscv/riscv-013.h index be508f7..ca2d4ae 100644 --- a/src/target/riscv/riscv-013.h +++ b/src/target/riscv/riscv-013.h @@ -19,5 +19,9 @@ int riscv013_set_register(struct target *target, enum gdb_regno rid, riscv_reg_t value); int riscv013_set_register_buf(struct target *target, enum gdb_regno regno, const uint8_t *value); +uint32_t riscv013_access_register_command(struct target *target, uint32_t number, + unsigned int size, uint32_t flags); +int riscv013_execute_abstract_command(struct target *target, uint32_t command, + uint32_t *cmderr); -#endif /*OPENOCD_TARGET_RISCV_RISCV_013_H*/ +#endif /* OPENOCD_TARGET_RISCV_RISCV_013_H */ diff --git a/src/target/riscv/riscv-013_reg.c b/src/target/riscv/riscv-013_reg.c index a71a01c..b2b1a92 100644 --- a/src/target/riscv/riscv-013_reg.c +++ b/src/target/riscv/riscv-013_reg.c @@ -5,10 +5,12 @@ #endif #include "riscv-013_reg.h" +#include "field_helpers.h" #include "riscv_reg.h" #include "riscv_reg_impl.h" #include "riscv-013.h" +#include "debug_defines.h" #include <helper/time_support.h> static int riscv013_reg_get(struct reg *reg) @@ -44,7 +46,6 @@ static int riscv013_reg_get(struct reg *reg) static int riscv013_reg_set(struct reg *reg, uint8_t *buf) { struct target *target = riscv_reg_impl_get_target(reg); - RISCV_INFO(r); char *str = buf_to_hex_str(buf, reg->size); LOG_TARGET_DEBUG(target, "Write 0x%s to %s (valid=%d).", str, reg->name, @@ -57,17 +58,6 @@ static int riscv013_reg_set(struct reg *reg, uint8_t *buf) buf_get_u64(buf, 0, reg->size) == 0) return ERROR_OK; - if (reg->number == GDB_REGNO_TDATA1 || - reg->number == GDB_REGNO_TDATA2) { - r->manual_hwbp_set = true; - /* When enumerating triggers, we clear any triggers with DMODE set, - * assuming they were left over from a previous debug session. So make - * sure that is done before a user might be setting their own triggers. - */ - if (riscv_enumerate_triggers(target) != ERROR_OK) - return ERROR_FAIL; - } - if (reg->number >= GDB_REGNO_V0 && reg->number <= GDB_REGNO_V31) { if (riscv013_set_register_buf(target, reg->number, buf) != ERROR_OK) return ERROR_FAIL; @@ -85,33 +75,270 @@ static int riscv013_reg_set(struct reg *reg, uint8_t *buf) static const struct reg_arch_type *riscv013_gdb_regno_reg_type(uint32_t regno) { - static const struct reg_arch_type riscv011_reg_type = { + static const struct reg_arch_type riscv013_reg_type = { .get = riscv013_reg_get, .set = riscv013_reg_set }; - return &riscv011_reg_type; + return &riscv013_reg_type; +} + +static int init_cache_entry(struct target *target, uint32_t regno) +{ + struct reg * const reg = riscv_reg_impl_cache_entry(target, regno); + if (riscv_reg_impl_is_initialized(reg)) + return ERROR_OK; + return riscv_reg_impl_init_cache_entry(target, regno, + riscv_reg_impl_gdb_regno_exist(target, regno), + riscv013_gdb_regno_reg_type(regno)); +} + +/** + * Some registers are optional (e.g. "misa"). For such registers it is first + * assumed they exist (via "assume_reg_exist()"), then the read is attempted + * (via the usual "riscv_reg_get()") and if the read fails, the register is + * marked as non-existing (via "riscv_reg_impl_set_exist()"). + */ +static int assume_reg_exist(struct target *target, uint32_t regno) +{ + return riscv_reg_impl_init_cache_entry(target, regno, + /* exist */ true, riscv013_gdb_regno_reg_type(regno)); +} + +static int examine_xlen(struct target *target) +{ + RISCV_INFO(r); + unsigned int cmderr; + + const uint32_t command = riscv013_access_register_command(target, + GDB_REGNO_S0, /* size */ 64, AC_ACCESS_REGISTER_TRANSFER); + int res = riscv013_execute_abstract_command(target, command, &cmderr); + if (res == ERROR_OK) { + r->xlen = 64; + return ERROR_OK; + } + if (res == ERROR_TIMEOUT_REACHED) + return ERROR_FAIL; + r->xlen = 32; + + return ERROR_OK; } -static int riscv013_init_reg(struct target *target, uint32_t regno) +static int examine_vlenb(struct target *target) { - return riscv_reg_impl_init_one(target, regno, riscv013_gdb_regno_reg_type(regno)); + RISCV_INFO(r); + + /* Reading "vlenb" requires "mstatus.vs" to be set, so "mstatus" should + * be accessible.*/ + int res = init_cache_entry(target, GDB_REGNO_MSTATUS); + if (res != ERROR_OK) + return res; + + res = assume_reg_exist(target, GDB_REGNO_VLENB); + if (res != ERROR_OK) + return res; + + riscv_reg_t vlenb_val; + if (riscv_reg_get(target, &vlenb_val, GDB_REGNO_VLENB) != ERROR_OK) { + if (riscv_supports_extension(target, 'V')) + LOG_TARGET_WARNING(target, "Couldn't read vlenb; vector register access won't work."); + r->vlenb = 0; + return riscv_reg_impl_set_exist(target, GDB_REGNO_VLENB, false); + } + /* As defined by RISC-V V extension specification: + * https://github.com/riscv/riscv-v-spec/blob/2f68ef7256d6ec53e4d2bd7cb12862f406d64e34/v-spec.adoc?plain=1#L67-L72 */ + const unsigned int vlen_max = 65536; + const unsigned int vlenb_max = vlen_max / 8; + if (vlenb_val > vlenb_max) { + LOG_TARGET_WARNING(target, "'vlenb == %" PRIu64 + "' is greater than maximum allowed by specification (%u); vector register access won't work.", + vlenb_val, vlenb_max); + r->vlenb = 0; + return ERROR_OK; + } + assert(vlenb_max <= UINT_MAX); + r->vlenb = (unsigned int)vlenb_val; + + LOG_TARGET_INFO(target, "Vector support with vlenb=%u", r->vlenb); + return ERROR_OK; +} + +enum misa_mxl { + MISA_MXL_INVALID = 0, + MISA_MXL_32 = 1, + MISA_MXL_64 = 2, + MISA_MXL_128 = 3 +}; + +unsigned int mxl_to_xlen(enum misa_mxl mxl) +{ + switch (mxl) { + case MISA_MXL_32: + return 32; + case MISA_MXL_64: + return 64; + case MISA_MXL_128: + return 128; + case MISA_MXL_INVALID: + assert(0); + } + return 0; } -int riscv013_reg_init_all(struct target *target) +static int check_misa_mxl(const struct target *target) { - if (riscv_reg_impl_init_cache(target) != ERROR_OK) + RISCV_INFO(r); + + if (r->misa == 0) { + LOG_TARGET_WARNING(target, "'misa' register is read as zero." + "OpenOCD will not be able to determine some hart's capabilities."); + return ERROR_OK; + } + const unsigned int dxlen = riscv_xlen(target); + assert(dxlen <= sizeof(riscv_reg_t) * CHAR_BIT); + assert(dxlen >= 2); + const riscv_reg_t misa_mxl_mask = (riscv_reg_t)0x3 << (dxlen - 2); + const unsigned int mxl = get_field(r->misa, misa_mxl_mask); + if (mxl == MISA_MXL_INVALID) { + /* This is not an error! + * Imagine the platform that: + * - Has no abstract access to CSRs, so that CSRs are read + * through Program Buffer via "csrr" instruction. + * - Complies to v1.10 of the Priveleged Spec, so that misa.mxl + * is WARL and MXLEN may be chainged. + * https://github.com/riscv/riscv-isa-manual/commit/9a7dd2fe29011587954560b5dcf1875477b27ad8 + * - DXLEN == MXLEN on reset == 64. + * In a following scenario: + * - misa.mxl was written, so that MXLEN is 32. + * - Debugger connects to the target. + * - Debugger observes DXLEN == 64. + * - Debugger reads misa: + * - Abstract access fails with "cmderr == not supported". + * - Access via Program Buffer involves reading "misa" to an + * "xreg" via "csrr", so that the "xreg" is filled with + * zero-extended value of "misa" (since "misa" is + * MXLEN-wide). + * - Debugger derives "misa.mxl" assumig "misa" is DXLEN-bit + * wide (64) while MXLEN is 32 and therefore erroneously + * assumes "misa.mxl" to be zero (invalid). + */ + LOG_TARGET_WARNING(target, "Detected DXLEN (%u) does not match " + "MXLEN: misa.mxl == 0, misa == 0x%" PRIx64 ".", + dxlen, r->misa); + return ERROR_OK; + } + const unsigned int mxlen = mxl_to_xlen(mxl); + if (dxlen < mxlen) { + LOG_TARGET_ERROR(target, + "MXLEN (%u) reported in misa.mxl field exceeds " + "the detected DXLEN (%u)", + mxlen, dxlen); return ERROR_FAIL; + } + /* NOTE: + * The value of "misa.mxl" may stil not coincide with "xlen". + * "misa[26:XLEN-3]" bits are marked as WIRI in at least version 1.10 + * of RISC-V Priveleged Spec. Therefore, if "xlen" is erroneously + * assumed to be 32 when it actually is 64, "mxl" will be read from + * this WIRI field and may be equal to "MISA_MXL_32" by coincidence. + * This is not an issue though from the version 1.11 onward, since + * "misa[26:XLEN-3]" became WARL and equal to 0. + */ + + /* Display this as early as possible to help people who are using + * really slow simulators. */ + LOG_TARGET_DEBUG(target, " XLEN=%d, misa=0x%" PRIx64, riscv_xlen(target), r->misa); + return ERROR_OK; +} + +static int examine_misa(struct target *target) +{ + RISCV_INFO(r); + + int res = init_cache_entry(target, GDB_REGNO_MISA); + if (res != ERROR_OK) + return res; + + res = riscv_reg_get(target, &r->misa, GDB_REGNO_MISA); + if (res != ERROR_OK) + return res; + return check_misa_mxl(target); +} + +static int examine_mtopi(struct target *target) +{ + /* Assume the registers exist */ + int res = assume_reg_exist(target, GDB_REGNO_MTOPI); + if (res != ERROR_OK) + return res; + res = assume_reg_exist(target, GDB_REGNO_MTOPEI); + if (res != ERROR_OK) + return res; + + riscv_reg_t value; + if (riscv_reg_get(target, &value, GDB_REGNO_MTOPI) != ERROR_OK) { + res = riscv_reg_impl_set_exist(target, GDB_REGNO_MTOPI, false); + if (res != ERROR_OK) + return res; + return riscv_reg_impl_set_exist(target, GDB_REGNO_MTOPEI, false); + } + if (riscv_reg_get(target, &value, GDB_REGNO_MTOPEI) != ERROR_OK) { + LOG_TARGET_INFO(target, "S?aia detected without IMSIC"); + return riscv_reg_impl_set_exist(target, GDB_REGNO_MTOPEI, false); + } + LOG_TARGET_INFO(target, "S?aia detected with IMSIC"); + return ERROR_OK; +} + +/** + * This function assumes target's DM to be initialized (target is able to + * access DMs registers, execute program buffer, etc.) + */ +int riscv013_reg_examine_all(struct target *target) +{ + int res = riscv_reg_impl_init_cache(target); + if (res != ERROR_OK) + return res; init_shared_reg_info(target); + assert(target->state == TARGET_HALTED); + + res = examine_xlen(target); + if (res != ERROR_OK) + return res; + + /* Reading CSRs may clobber "s0", "s1", so it should be possible to + * save them in cache. */ + res = init_cache_entry(target, GDB_REGNO_S0); + if (res != ERROR_OK) + return res; + res = init_cache_entry(target, GDB_REGNO_S1); + if (res != ERROR_OK) + return res; + + res = examine_misa(target); + if (res != ERROR_OK) + return res; + + res = examine_vlenb(target); + if (res != ERROR_OK) + return res; + riscv_reg_impl_init_vector_reg_type(target); - for (uint32_t regno = 0; regno < target->reg_cache->num_regs; ++regno) - if (riscv013_init_reg(target, regno) != ERROR_OK) - return ERROR_FAIL; + res = examine_mtopi(target); + if (res != ERROR_OK) + return res; - if (riscv_reg_impl_expose_csrs(target) != ERROR_OK) - return ERROR_FAIL; + for (uint32_t regno = 0; regno < target->reg_cache->num_regs; ++regno) { + res = init_cache_entry(target, regno); + if (res != ERROR_OK) + return res; + } + + res = riscv_reg_impl_expose_csrs(target); + if (res != ERROR_OK) + return res; riscv_reg_impl_hide_csrs(target); diff --git a/src/target/riscv/riscv-013_reg.h b/src/target/riscv/riscv-013_reg.h index 2bdaaa0..e542a35 100644 --- a/src/target/riscv/riscv-013_reg.h +++ b/src/target/riscv/riscv-013_reg.h @@ -1,7 +1,7 @@ /* SPDX-License-Identifier: GPL-2.0-or-later */ -#ifndef OPENOCD_TARGET_RISCV_RISCV_REG_013_H -#define OPENOCD_TARGET_RISCV_RISCV_REG_013_H +#ifndef OPENOCD_TARGET_RISCV_RISCV_013_REG_H +#define OPENOCD_TARGET_RISCV_RISCV_013_REG_H #include "target/target.h" #include "gdb_regs.h" @@ -13,10 +13,11 @@ */ /** - * Init initialize register cache. After this function all registers can be - * safely accessed via functions described here and in `riscv_reg.h`. + * This function assumes target is halted. + * After this function all registers can be safely accessed via functions + * described here and in `riscv_reg.h`. */ -int riscv013_reg_init_all(struct target *target); +int riscv013_reg_examine_all(struct target *target); /** * This function is used to save the value of a register in cache. The register @@ -28,4 +29,4 @@ int riscv013_reg_init_all(struct target *target); */ int riscv013_reg_save(struct target *target, enum gdb_regno regid); -#endif /*OPENOCD_TARGET_RISCV_RISCV_REG_013_H*/ +#endif /* OPENOCD_TARGET_RISCV_RISCV_013_REG_H */ diff --git a/src/target/riscv/riscv.c b/src/target/riscv/riscv.c index a57c709..aae5eb3 100644 --- a/src/target/riscv/riscv.c +++ b/src/target/riscv/riscv.c @@ -37,6 +37,8 @@ #define RISCV_TRIGGER_HIT_NOT_FOUND ((int64_t)-1) +#define RISCV_HALT_GROUP_REPOLL_LIMIT 5 + static uint8_t ir_dtmcontrol[4] = {DTMCONTROL}; struct scan_field select_dtmcontrol = { .in_value = NULL, @@ -54,7 +56,8 @@ struct scan_field select_idcode = { }; static bscan_tunnel_type_t bscan_tunnel_type; -int bscan_tunnel_ir_width; /* if zero, then tunneling is not present/active */ +#define BSCAN_TUNNEL_IR_WIDTH_NBITS 7 +uint8_t bscan_tunnel_ir_width; /* if zero, then tunneling is not present/active */ static int bscan_tunnel_ir_id; /* IR ID of the JTAG TAP to access the tunnel. Valid when not 0 */ static const uint8_t bscan_zero[4] = {0}; @@ -67,7 +70,6 @@ static struct scan_field select_user4 = { }; -static uint8_t bscan_tunneled_ir_width[4] = {5}; /* overridden by assignment in riscv_init_target */ static struct scan_field _bscan_tunnel_data_register_select_dmi[] = { { .num_bits = 3, @@ -80,8 +82,8 @@ static struct scan_field _bscan_tunnel_data_register_select_dmi[] = { .in_value = NULL, }, { - .num_bits = 7, - .out_value = bscan_tunneled_ir_width, + .num_bits = BSCAN_TUNNEL_IR_WIDTH_NBITS, + .out_value = &bscan_tunnel_ir_width, .in_value = NULL, }, { @@ -98,8 +100,8 @@ static struct scan_field _bscan_tunnel_nested_tap_select_dmi[] = { .in_value = NULL, }, { - .num_bits = 7, - .out_value = bscan_tunneled_ir_width, + .num_bits = BSCAN_TUNNEL_IR_WIDTH_NBITS, + .out_value = &bscan_tunnel_ir_width, .in_value = NULL, }, { @@ -139,6 +141,35 @@ struct tdata1_cache { struct list_head elem_tdata1; }; +bool riscv_virt2phys_mode_is_hw(const struct target *target) +{ + assert(target); + RISCV_INFO(r); + return r->virt2phys_mode == RISCV_VIRT2PHYS_MODE_HW; +} + +bool riscv_virt2phys_mode_is_sw(const struct target *target) +{ + assert(target); + RISCV_INFO(r); + return r->virt2phys_mode == RISCV_VIRT2PHYS_MODE_SW; +} + +const char *riscv_virt2phys_mode_to_str(riscv_virt2phys_mode_t mode) +{ + assert(mode == RISCV_VIRT2PHYS_MODE_OFF + || mode == RISCV_VIRT2PHYS_MODE_SW + || mode == RISCV_VIRT2PHYS_MODE_HW); + + static const char *const names[] = { + [RISCV_VIRT2PHYS_MODE_HW] = "hw", + [RISCV_VIRT2PHYS_MODE_SW] = "sw", + [RISCV_VIRT2PHYS_MODE_OFF] = "off", + }; + + return names[mode]; +} + /* Wall-clock timeout for a command/access. Settable via RISC-V Target commands.*/ static int riscv_command_timeout_sec_value = DEFAULT_COMMAND_TIMEOUT_SEC; @@ -150,10 +181,6 @@ int riscv_get_command_timeout_sec(void) return MAX(riscv_command_timeout_sec_value, riscv_reset_timeout_sec); } -static bool riscv_enable_virt2phys = true; - -bool riscv_enable_virtual; - static enum { RO_NORMAL, RO_REVERSED @@ -265,9 +292,12 @@ static const virt2phys_info_t sv57x4 = { static enum riscv_halt_reason riscv_halt_reason(struct target *target); static void riscv_info_init(struct target *target, struct riscv_info *r); -static void riscv_invalidate_register_cache(struct target *target); 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); @@ -286,21 +316,20 @@ static void riscv_sample_buf_maybe_add_timestamp(struct target *target, bool bef static int riscv_resume_go_all_harts(struct target *target); -void select_dmi_via_bscan(struct target *target) +void select_dmi_via_bscan(struct jtag_tap *tap) { - jtag_add_ir_scan(target->tap, &select_user4, TAP_IDLE); + jtag_add_ir_scan(tap, &select_user4, TAP_IDLE); if (bscan_tunnel_type == BSCAN_TUNNEL_DATA_REGISTER) - jtag_add_dr_scan(target->tap, bscan_tunnel_data_register_select_dmi_num_fields, + jtag_add_dr_scan(tap, bscan_tunnel_data_register_select_dmi_num_fields, bscan_tunnel_data_register_select_dmi, TAP_IDLE); else /* BSCAN_TUNNEL_NESTED_TAP */ - jtag_add_dr_scan(target->tap, bscan_tunnel_nested_tap_select_dmi_num_fields, + jtag_add_dr_scan(tap, bscan_tunnel_nested_tap_select_dmi_num_fields, bscan_tunnel_nested_tap_select_dmi, TAP_IDLE); } -int dtmcontrol_scan_via_bscan(struct target *target, uint32_t out, uint32_t *in_ptr) +static int dtmcs_scan_via_bscan(struct jtag_tap *tap, uint32_t out, uint32_t *in_ptr) { /* On BSCAN TAP: Select IR=USER4, issue tunneled IR scan via BSCAN TAP's DR */ - uint8_t tunneled_ir_width[4] = {bscan_tunnel_ir_width}; uint8_t tunneled_dr_width[4] = {32}; uint8_t out_value[5] = {0}; uint8_t in_value[5] = {0}; @@ -316,8 +345,8 @@ int dtmcontrol_scan_via_bscan(struct target *target, uint32_t out, uint32_t *in_ tunneled_ir[1].num_bits = bscan_tunnel_ir_width; tunneled_ir[1].out_value = ir_dtmcontrol; tunneled_ir[1].in_value = NULL; - tunneled_ir[2].num_bits = 7; - tunneled_ir[2].out_value = tunneled_ir_width; + tunneled_ir[2].num_bits = BSCAN_TUNNEL_IR_WIDTH_NBITS; + tunneled_ir[2].out_value = &bscan_tunnel_ir_width; tunneled_ir[2].in_value = NULL; tunneled_ir[3].num_bits = 1; tunneled_ir[3].out_value = bscan_zero; @@ -329,7 +358,7 @@ int dtmcontrol_scan_via_bscan(struct target *target, uint32_t out, uint32_t *in_ tunneled_dr[1].num_bits = 32 + 1; tunneled_dr[1].out_value = out_value; tunneled_dr[1].in_value = in_value; - tunneled_dr[2].num_bits = 7; + tunneled_dr[2].num_bits = BSCAN_TUNNEL_IR_WIDTH_NBITS; tunneled_dr[2].out_value = tunneled_dr_width; tunneled_dr[2].in_value = NULL; tunneled_dr[3].num_bits = 1; @@ -343,8 +372,8 @@ int dtmcontrol_scan_via_bscan(struct target *target, uint32_t out, uint32_t *in_ tunneled_ir[2].num_bits = bscan_tunnel_ir_width; tunneled_ir[2].out_value = ir_dtmcontrol; tunneled_ir[1].in_value = NULL; - tunneled_ir[1].num_bits = 7; - tunneled_ir[1].out_value = tunneled_ir_width; + tunneled_ir[1].num_bits = BSCAN_TUNNEL_IR_WIDTH_NBITS; + tunneled_ir[1].out_value = &bscan_tunnel_ir_width; tunneled_ir[2].in_value = NULL; tunneled_ir[0].num_bits = 1; tunneled_ir[0].out_value = bscan_zero; @@ -363,10 +392,10 @@ int dtmcontrol_scan_via_bscan(struct target *target, uint32_t out, uint32_t *in_ tunneled_dr[0].out_value = bscan_one; tunneled_dr[0].in_value = NULL; } - jtag_add_ir_scan(target->tap, &select_user4, TAP_IDLE); - jtag_add_dr_scan(target->tap, ARRAY_SIZE(tunneled_ir), tunneled_ir, TAP_IDLE); - jtag_add_dr_scan(target->tap, ARRAY_SIZE(tunneled_dr), tunneled_dr, TAP_IDLE); - select_dmi_via_bscan(target); + jtag_add_ir_scan(tap, &select_user4, TAP_IDLE); + jtag_add_dr_scan(tap, ARRAY_SIZE(tunneled_ir), tunneled_ir, TAP_IDLE); + jtag_add_dr_scan(tap, ARRAY_SIZE(tunneled_dr), tunneled_dr, TAP_IDLE); + select_dmi_via_bscan(tap); int retval = jtag_execute_queue(); if (retval != ERROR_OK) { @@ -383,38 +412,44 @@ int dtmcontrol_scan_via_bscan(struct target *target, uint32_t out, uint32_t *in_ return ERROR_OK; } -static int dtmcontrol_scan(struct target *target, uint32_t out, uint32_t *in_ptr) +/* TODO: rename "dtmcontrol"-> "dtmcs" */ +int dtmcs_scan(struct jtag_tap *tap, uint32_t out, uint32_t *in_ptr) { - struct scan_field field; - uint8_t in_value[4]; - uint8_t out_value[4] = { 0 }; + uint8_t value[4]; if (bscan_tunnel_ir_width != 0) - return dtmcontrol_scan_via_bscan(target, out, in_ptr); + return dtmcs_scan_via_bscan(tap, out, in_ptr); - buf_set_u32(out_value, 0, 32, out); + buf_set_u32(value, 0, 32, out); - jtag_add_ir_scan(target->tap, &select_dtmcontrol, TAP_IDLE); + jtag_add_ir_scan(tap, &select_dtmcontrol, TAP_IDLE); - field.num_bits = 32; - field.out_value = out_value; - field.in_value = in_value; - jtag_add_dr_scan(target->tap, 1, &field, TAP_IDLE); + struct scan_field field = { + .num_bits = 32, + .out_value = value, + .in_value = in_ptr ? value : NULL + }; + jtag_add_dr_scan(tap, 1, &field, TAP_IDLE); /* Always return to dbus. */ - jtag_add_ir_scan(target->tap, &select_dbus, TAP_IDLE); + jtag_add_ir_scan(tap, &select_dbus, TAP_IDLE); int retval = jtag_execute_queue(); if (retval != ERROR_OK) { - LOG_TARGET_ERROR(target, "dtmcontrol scan failed, error code = %d", retval); + LOG_ERROR("'dtmcs' scan failed on TAP %s, error code = %d", + jtag_tap_name(tap), retval); return retval; } - uint32_t in = buf_get_u32(field.in_value, 0, 32); - LOG_DEBUG("DTMCONTROL: 0x%x -> 0x%x", out, in); - - if (in_ptr) + if (in_ptr) { + assert(field.in_value); + uint32_t in = buf_get_u32(field.in_value, 0, 32); + LOG_DEBUG("TAP %s: DTMCS: 0x%" PRIx32 " -> 0x%" PRIx32, + jtag_tap_name(tap), out, in); *in_ptr = in; + } else { + LOG_DEBUG("TAP %s: DTMCS: 0x%" PRIx32 " -> ?", jtag_tap_name(tap), out); + } return ERROR_OK; } @@ -440,9 +475,30 @@ static struct target_type *get_target_type(struct target *target) } } +static struct riscv_private_config *alloc_default_riscv_private_config(void) +{ + struct riscv_private_config * const config = malloc(sizeof(*config)); + if (!config) { + LOG_ERROR("Out of memory!"); + return NULL; + } + + for (unsigned int i = 0; i < ARRAY_SIZE(config->dcsr_ebreak_fields); ++i) + config->dcsr_ebreak_fields[i] = true; + + return config; +} + static int riscv_create_target(struct target *target, Jim_Interp *interp) { LOG_TARGET_DEBUG(target, "riscv_create_target()"); + struct riscv_private_config *config = target->private_config; + if (!config) { + config = alloc_default_riscv_private_config(); + if (!config) + return ERROR_FAIL; + target->private_config = config; + } target->arch_info = calloc(1, sizeof(struct riscv_info)); if (!target->arch_info) { LOG_TARGET_ERROR(target, "Failed to allocate RISC-V target structure."); @@ -452,6 +508,158 @@ static int riscv_create_target(struct target *target, Jim_Interp *interp) return ERROR_OK; } +static struct jim_nvp nvp_ebreak_config_opts[] = { + { .name = "m", .value = RISCV_MODE_M }, + { .name = "s", .value = RISCV_MODE_S }, + { .name = "u", .value = RISCV_MODE_U }, + { .name = "vs", .value = RISCV_MODE_VS }, + { .name = "vu", .value = RISCV_MODE_VU }, + { .name = NULL, .value = N_RISCV_MODE } +}; + +#define RISCV_EBREAK_MODE_INVALID -1 + +static struct jim_nvp nvp_ebreak_mode_opts[] = { + { .name = "exception", .value = false }, + { .name = "halt", .value = true }, + { .name = NULL, .value = RISCV_EBREAK_MODE_INVALID } +}; + +static int jim_configure_ebreak(struct riscv_private_config *config, struct jim_getopt_info *goi) +{ + if (goi->argc == 0) { + Jim_WrongNumArgs(goi->interp, 1, goi->argv - 1, + "[?execution_mode?] ?ebreak_action?"); + return JIM_ERR; + } + struct jim_nvp *common_mode_nvp; + if (jim_nvp_name2value_obj(goi->interp, nvp_ebreak_mode_opts, goi->argv[0], + &common_mode_nvp) == JIM_OK) { + /* Here a common "ebreak" action is processed, e.g: + * "riscv.cpu configure -ebreak halt" + */ + int res = jim_getopt_obj(goi, NULL); + if (res != JIM_OK) + return res; + for (int ebreak_ctl_i = 0; ebreak_ctl_i < N_RISCV_MODE; ++ebreak_ctl_i) + config->dcsr_ebreak_fields[ebreak_ctl_i] = common_mode_nvp->value; + return JIM_OK; + } + + /* Here a "ebreak" action for a specific execution mode is processed, e.g: + * "riscv.cpu configure -ebreak m halt" + */ + if (goi->argc < 2) { + Jim_WrongNumArgs(goi->interp, 2, goi->argv - 2, + "?ebreak_action?"); + return JIM_ERR; + } + struct jim_nvp *ctrl_nvp; + if (jim_getopt_nvp(goi, nvp_ebreak_config_opts, &ctrl_nvp) != JIM_OK) { + jim_getopt_nvp_unknown(goi, nvp_ebreak_config_opts, /*hadprefix*/ true); + return JIM_ERR; + } + struct jim_nvp *mode_nvp; + if (jim_getopt_nvp(goi, nvp_ebreak_mode_opts, &mode_nvp) != JIM_OK) { + jim_getopt_nvp_unknown(goi, nvp_ebreak_mode_opts, /*hadprefix*/ true); + return JIM_ERR; + } + config->dcsr_ebreak_fields[ctrl_nvp->value] = mode_nvp->value; + return JIM_OK; +} + +/** + * Obtain dcsr.ebreak* configuration as a Tcl dictionary. + * Print the resulting string to the "buffer" and return the string length. + * The "buffer" can be NULL, in which case only the length is computed but + * nothing is written. + */ +static int ebreak_config_to_tcl_dict(const struct riscv_private_config *config, + char *buffer) +{ + int len = 0; + const char *separator = ""; + for (int ebreak_ctl_i = 0; ebreak_ctl_i < N_RISCV_MODE; + ++ebreak_ctl_i) { + const char * const format = "%s%s %s"; + const char * const priv_mode = + jim_nvp_value2name_simple(nvp_ebreak_config_opts, ebreak_ctl_i)->name; + const char * const mode = jim_nvp_value2name_simple(nvp_ebreak_mode_opts, + config->dcsr_ebreak_fields[ebreak_ctl_i])->name; + if (!buffer) + len += snprintf(NULL, 0, format, separator, priv_mode, mode); + else + len += sprintf(buffer + len, format, separator, priv_mode, mode); + + separator = "\n"; + } + return len; +} + +static int jim_report_ebreak_config(const struct riscv_private_config *config, + Jim_Interp *interp) +{ + const int len = ebreak_config_to_tcl_dict(config, NULL); + char *str = malloc(len + 1); + if (!str) { + LOG_ERROR("Unable to allocate a string of %d bytes.", len + 1); + return JIM_ERR; + } + ebreak_config_to_tcl_dict(config, str); + Jim_SetResultString(interp, str, len); + free(str); + return JIM_OK; +} + +enum riscv_cfg_opts { + RISCV_CFG_EBREAK, + RISCV_CFG_INVALID = -1 +}; + +static struct jim_nvp nvp_config_opts[] = { + { .name = "-ebreak", .value = RISCV_CFG_EBREAK }, + { .name = NULL, .value = RISCV_CFG_INVALID } +}; + +static int riscv_jim_configure(struct target *target, + struct jim_getopt_info *goi) +{ + struct riscv_private_config *config = target->private_config; + if (!config) { + config = alloc_default_riscv_private_config(); + if (!config) + return JIM_ERR; + target->private_config = config; + } + if (!goi->argc) + return JIM_OK; + + struct jim_nvp *n; + int e = jim_nvp_name2value_obj(goi->interp, nvp_config_opts, + goi->argv[0], &n); + if (e != JIM_OK) + return JIM_CONTINUE; + + e = jim_getopt_obj(goi, NULL); + if (e != JIM_OK) + return e; + + if (!goi->is_configure && goi->argc > 0) { + /* Expecting no arguments */ + Jim_WrongNumArgs(goi->interp, 2, goi->argv - 2, ""); + return JIM_ERR; + } + switch (n->value) { + case RISCV_CFG_EBREAK: + return goi->is_configure + ? jim_configure_ebreak(config, goi) + : jim_report_ebreak_config(config, goi->interp); + default: + assert(false && "'jim_getopt_nvp' should have returned an error."); + } + return JIM_ERR; +} + static int riscv_init_target(struct command_context *cmd_ctx, struct target *target) { @@ -473,7 +681,6 @@ static int riscv_init_target(struct command_context *cmd_ctx, } h_u32_to_le(ir_user4, ir_user4_raw); select_user4.num_bits = target->tap->ir_length; - bscan_tunneled_ir_width[0] = bscan_tunnel_ir_width; if (bscan_tunnel_type == BSCAN_TUNNEL_DATA_REGISTER) bscan_tunnel_data_register_select_dmi[1].num_bits = bscan_tunnel_ir_width; else /* BSCAN_TUNNEL_NESTED_TAP */ @@ -510,6 +717,8 @@ static void riscv_deinit_target(struct target *target) { LOG_TARGET_DEBUG(target, "riscv_deinit_target()"); + free(target->private_config); + struct riscv_info *info = target->arch_info; struct target_type *tt = get_target_type(target); if (!tt) @@ -527,6 +736,8 @@ static void riscv_deinit_target(struct target *target) if (!info) return; + free(info->reserved_triggers); + range_list_t *entry, *tmp; list_for_each_entry_safe(entry, tmp, &info->hide_csr, list) { free(entry->name); @@ -617,9 +828,27 @@ static int find_first_trigger_by_id(struct target *target, int unique_id) return -1; } -static int set_trigger(struct target *target, unsigned int idx, riscv_reg_t tdata1, riscv_reg_t tdata2, - riscv_reg_t tdata1_ignore_mask) +static unsigned int count_trailing_ones(riscv_reg_t reg) { + const unsigned int riscv_reg_bits = sizeof(riscv_reg_t) * CHAR_BIT; + for (unsigned int i = 0; i < riscv_reg_bits; i++) { + if ((1 & (reg >> i)) == 0) + return i; + } + return riscv_reg_bits; +} + +static int set_trigger(struct target *target, unsigned int idx, riscv_reg_t tdata1, riscv_reg_t tdata2) +{ + RISCV_INFO(r); + assert(r->reserved_triggers); + assert(idx < r->trigger_count); + if (r->reserved_triggers[idx]) { + LOG_TARGET_DEBUG(target, + "Trigger %u is reserved by 'reserve_trigger' command.", idx); + return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; + } + riscv_reg_t tdata1_rb, tdata2_rb; // Select which trigger to use if (riscv_reg_set(target, GDB_REGNO_TSELECT, idx) != ERROR_OK) @@ -642,20 +871,51 @@ static int set_trigger(struct target *target, unsigned int idx, riscv_reg_t tdat return ERROR_FAIL; if (riscv_reg_get(target, &tdata2_rb, GDB_REGNO_TDATA2) != ERROR_OK) return ERROR_FAIL; - bool tdata1_config_denied = (tdata1 & ~tdata1_ignore_mask) != (tdata1_rb & ~tdata1_ignore_mask); - bool tdata2_config_denied = tdata2 != tdata2_rb; - if (tdata1_config_denied || tdata2_config_denied) { + + const uint32_t type = get_field(tdata1, CSR_TDATA1_TYPE(riscv_xlen(target))); + const bool is_mcontrol = type == CSR_TDATA1_TYPE_MCONTROL; + + /* Determine if tdata1 supports what we need. + * For mcontrol triggers, we don't care about + * the value in the read-only "maskmax" field. + */ + const riscv_reg_t tdata1_ignore_mask = is_mcontrol ? CSR_MCONTROL_MASKMAX(riscv_xlen(target)) : 0; + const bool tdata1_config_denied = (tdata1 & ~tdata1_ignore_mask) != (tdata1_rb & ~tdata1_ignore_mask); + + /* Determine if tdata1.maxmask is sufficient + * (only relevant for mcontrol triggers and NAPOT match type) + */ + bool unsupported_napot_range = false; + riscv_reg_t maskmax_value = 0; + if (!tdata1_config_denied) { + const bool is_napot_match = get_field(tdata1_rb, CSR_MCONTROL_MATCH) == CSR_MCONTROL_MATCH_NAPOT; + if (is_mcontrol && is_napot_match) { + maskmax_value = get_field(tdata1_rb, CSR_MCONTROL_MASKMAX(riscv_xlen(target))); + const unsigned int napot_size = count_trailing_ones(tdata2) + 1; + if (maskmax_value < napot_size) + unsupported_napot_range = true; + } + } + + const bool tdata2_config_denied = tdata2 != tdata2_rb; + if (tdata1_config_denied || tdata2_config_denied || unsupported_napot_range) { LOG_TARGET_DEBUG(target, "Trigger %u doesn't support what we need.", idx); if (tdata1_config_denied) LOG_TARGET_DEBUG(target, - "After writing 0x%" PRIx64 " to tdata1 it contains 0x%" PRIx64 "; tdata1_ignore_mask=0x%" PRIx64, - tdata1, tdata1_rb, tdata1_ignore_mask); + "After writing 0x%" PRIx64 " to tdata1 it contains 0x%" PRIx64, + tdata1, tdata1_rb); if (tdata2_config_denied) LOG_TARGET_DEBUG(target, - "wrote 0x%" PRIx64 " to tdata2 but read back 0x%" PRIx64, + "After writing 0x%" PRIx64 " to tdata2 it contains 0x%" PRIx64, tdata2, tdata2_rb); + + if (unsupported_napot_range) + LOG_TARGET_DEBUG(target, + "The requested NAPOT match range (tdata2=0x%" PRIx64 ") exceeds maskmax_value=0x%" PRIx64, + tdata2, maskmax_value); + if (riscv_reg_set(target, GDB_REGNO_TDATA1, 0) != ERROR_OK) return ERROR_FAIL; return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; @@ -704,7 +964,7 @@ static int maybe_add_trigger_t1(struct target *target, struct trigger *trigger) tdata1 = set_field(tdata1, bpcontrol_bpaction, 0); /* cause bp exception */ tdata1 = set_field(tdata1, bpcontrol_bpmatch, 0); /* exact match */ tdata2 = trigger->address; - ret = set_trigger(target, idx, tdata1, tdata2, 0); + ret = set_trigger(target, idx, tdata1, tdata2); if (ret != ERROR_OK) return ret; r->trigger_unique_id[idx] = trigger->unique_id; @@ -714,13 +974,11 @@ static int maybe_add_trigger_t1(struct target *target, struct trigger *trigger) struct trigger_request_info { riscv_reg_t tdata1; riscv_reg_t tdata2; - riscv_reg_t tdata1_ignore_mask; }; static void log_trigger_request_info(struct trigger_request_info trig_info) { - LOG_DEBUG("tdata1=%" PRIx64 ", tdata2=%" PRIx64 ", tdata1_ignore_mask=%" PRIx64, - trig_info.tdata1, trig_info.tdata2, trig_info.tdata1_ignore_mask); + LOG_DEBUG("tdata1=%" PRIx64 ", tdata2=%" PRIx64, trig_info.tdata1, trig_info.tdata2); }; static struct tdata1_cache *tdata1_cache_alloc(struct list_head *tdata1_cache_head, riscv_reg_t tdata1) @@ -803,12 +1061,12 @@ static bool wp_triggers_cache_search(struct target *target, unsigned int idx, } static int try_use_trigger_and_cache_result(struct target *target, unsigned int idx, riscv_reg_t tdata1, - riscv_reg_t tdata2, riscv_reg_t tdata1_ignore_mask) + riscv_reg_t tdata2) { if (wp_triggers_cache_search(target, idx, tdata1, tdata2)) return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; - int ret = set_trigger(target, idx, tdata1, tdata2, tdata1_ignore_mask); + int ret = set_trigger(target, idx, tdata1, tdata2); /* Add these values to the cache to remember that they are not supported. */ if (ret == ERROR_TARGET_RESOURCE_NOT_AVAILABLE) @@ -831,8 +1089,7 @@ static int try_setup_single_match_trigger(struct target *target, for (unsigned int idx = 0; find_next_free_trigger(target, trigger_type, false, &idx) == ERROR_OK; ++idx) { - ret = try_use_trigger_and_cache_result(target, idx, trig_info.tdata1, trig_info.tdata2, - trig_info.tdata1_ignore_mask); + ret = try_use_trigger_and_cache_result(target, idx, trig_info.tdata1, trig_info.tdata2); if (ret == ERROR_OK) { r->trigger_unique_id[idx] = trigger->unique_id; @@ -860,16 +1117,14 @@ static int try_setup_chained_match_triggers(struct target *target, for (unsigned int idx = 0; find_next_free_trigger(target, trigger_type, true, &idx) == ERROR_OK; ++idx) { - ret = try_use_trigger_and_cache_result(target, idx, t1.tdata1, t1.tdata2, - t1.tdata1_ignore_mask); + ret = try_use_trigger_and_cache_result(target, idx, t1.tdata1, t1.tdata2); if (ret == ERROR_TARGET_RESOURCE_NOT_AVAILABLE) continue; else if (ret != ERROR_OK) return ret; - ret = try_use_trigger_and_cache_result(target, idx + 1, t2.tdata1, t2.tdata2, - t2.tdata1_ignore_mask); + ret = try_use_trigger_and_cache_result(target, idx + 1, t2.tdata1, t2.tdata2); if (ret == ERROR_OK) { r->trigger_unique_id[idx] = trigger->unique_id; @@ -877,7 +1132,7 @@ static int try_setup_chained_match_triggers(struct target *target, return ERROR_OK; } /* Undo the setting of the previous trigger */ - int ret_undo = set_trigger(target, idx, 0, 0, 0); + int ret_undo = set_trigger(target, idx, 0, 0); if (ret_undo != ERROR_OK) return ret_undo; @@ -905,7 +1160,6 @@ struct match_triggers_tdata1_fields { riscv_reg_t ge; riscv_reg_t eq; } match; - riscv_reg_t tdata1_ignore_mask; }; static struct match_triggers_tdata1_fields fill_match_triggers_tdata1_fields_t2(struct target *target, @@ -938,8 +1192,7 @@ static struct match_triggers_tdata1_fields fill_match_triggers_tdata1_fields_t2( .lt = field_value(CSR_MCONTROL_MATCH, CSR_MCONTROL_MATCH_LT), .ge = field_value(CSR_MCONTROL_MATCH, CSR_MCONTROL_MATCH_GE), .eq = field_value(CSR_MCONTROL_MATCH, CSR_MCONTROL_MATCH_EQUAL) - }, - .tdata1_ignore_mask = CSR_MCONTROL_MASKMAX(riscv_xlen(target)) + } }; return result; } @@ -976,8 +1229,7 @@ static struct match_triggers_tdata1_fields fill_match_triggers_tdata1_fields_t6( .lt = field_value(CSR_MCONTROL6_MATCH, CSR_MCONTROL6_MATCH_LT), .ge = field_value(CSR_MCONTROL6_MATCH, CSR_MCONTROL6_MATCH_GE), .eq = field_value(CSR_MCONTROL6_MATCH, CSR_MCONTROL6_MATCH_EQUAL) - }, - .tdata1_ignore_mask = 0 + } }; return result; } @@ -996,8 +1248,7 @@ static int maybe_add_trigger_t2_t6_for_wp(struct target *target, struct trigger_request_info napot = { .tdata1 = fields.common | fields.size.any | fields.chain.disable | fields.match.napot, - .tdata2 = trigger->address | ((trigger->length - 1) >> 1), - .tdata1_ignore_mask = fields.tdata1_ignore_mask + .tdata2 = trigger->address | ((trigger->length - 1) >> 1) }; ret = try_setup_single_match_trigger(target, trigger, napot); if (ret != ERROR_TARGET_RESOURCE_NOT_AVAILABLE) @@ -1013,14 +1264,12 @@ static int maybe_add_trigger_t2_t6_for_wp(struct target *target, struct trigger_request_info ge_1 = { .tdata1 = fields.common | fields.size.any | fields.chain.enable | fields.match.ge, - .tdata2 = trigger->address, - .tdata1_ignore_mask = fields.tdata1_ignore_mask + .tdata2 = trigger->address }; struct trigger_request_info lt_2 = { .tdata1 = fields.common | fields.size.any | fields.chain.disable | fields.match.lt, - .tdata2 = trigger->address + trigger->length, - .tdata1_ignore_mask = fields.tdata1_ignore_mask + .tdata2 = trigger->address + trigger->length }; ret = try_setup_chained_match_triggers(target, trigger, ge_1, lt_2); if (ret != ERROR_TARGET_RESOURCE_NOT_AVAILABLE) @@ -1030,14 +1279,12 @@ static int maybe_add_trigger_t2_t6_for_wp(struct target *target, struct trigger_request_info lt_1 = { .tdata1 = fields.common | fields.size.any | fields.chain.enable | fields.match.lt, - .tdata2 = trigger->address + trigger->length, - .tdata1_ignore_mask = fields.tdata1_ignore_mask + .tdata2 = trigger->address + trigger->length }; struct trigger_request_info ge_2 = { .tdata1 = fields.common | fields.size.any | fields.chain.disable | fields.match.ge, - .tdata2 = trigger->address, - .tdata1_ignore_mask = fields.tdata1_ignore_mask + .tdata2 = trigger->address }; ret = try_setup_chained_match_triggers(target, trigger, lt_1, ge_2); if (ret != ERROR_TARGET_RESOURCE_NOT_AVAILABLE) @@ -1053,8 +1300,7 @@ static int maybe_add_trigger_t2_t6_for_wp(struct target *target, struct trigger_request_info eq = { .tdata1 = fields.common | fields.size.any | fields.chain.disable | fields.match.eq, - .tdata2 = trigger->address, - .tdata1_ignore_mask = fields.tdata1_ignore_mask + .tdata2 = trigger->address }; ret = try_setup_single_match_trigger(target, trigger, eq); if (ret != ERROR_OK) @@ -1091,8 +1337,7 @@ static int maybe_add_trigger_t2_t6_for_bp(struct target *target, struct trigger_request_info eq = { .tdata1 = fields.common | fields.size.any | fields.chain.disable | fields.match.eq, - .tdata2 = trigger->address, - .tdata1_ignore_mask = fields.tdata1_ignore_mask + .tdata2 = trigger->address }; return try_setup_single_match_trigger(target, trigger, eq); @@ -1135,7 +1380,7 @@ static int maybe_add_trigger_t3(struct target *target, bool vs, bool vu, ret = find_next_free_trigger(target, CSR_TDATA1_TYPE_ICOUNT, false, &idx); if (ret != ERROR_OK) return ret; - ret = set_trigger(target, idx, tdata1, 0, 0); + ret = set_trigger(target, idx, tdata1, 0); if (ret != ERROR_OK) return ret; r->trigger_unique_id[idx] = unique_id; @@ -1168,7 +1413,7 @@ static int maybe_add_trigger_t4(struct target *target, bool vs, bool vu, ret = find_next_free_trigger(target, CSR_TDATA1_TYPE_ITRIGGER, false, &idx); if (ret != ERROR_OK) return ret; - ret = set_trigger(target, idx, tdata1, tdata2, 0); + ret = set_trigger(target, idx, tdata1, tdata2); if (ret != ERROR_OK) return ret; r->trigger_unique_id[idx] = unique_id; @@ -1200,7 +1445,7 @@ static int maybe_add_trigger_t5(struct target *target, bool vs, bool vu, ret = find_next_free_trigger(target, CSR_TDATA1_TYPE_ETRIGGER, false, &idx); if (ret != ERROR_OK) return ret; - ret = set_trigger(target, idx, tdata1, tdata2, 0); + ret = set_trigger(target, idx, tdata1, tdata2); if (ret != ERROR_OK) return ret; r->trigger_unique_id[idx] = unique_id; @@ -1523,21 +1768,75 @@ int riscv_remove_watchpoint(struct target *target, return ERROR_OK; } +typedef enum { + M6_HIT_ERROR, + M6_HIT_NOT_SUPPORTED, + M6_NOT_HIT, + M6_HIT_BEFORE, + M6_HIT_AFTER, + M6_HIT_IMM_AFTER +} mctrl6hitstatus; + +static mctrl6hitstatus check_mcontrol6_hit_status(struct target *target, + riscv_reg_t tdata1, uint64_t hit_mask) +{ + const uint32_t hit0 = get_field(tdata1, CSR_MCONTROL6_HIT0); + const uint32_t hit1 = get_field(tdata1, CSR_MCONTROL6_HIT1); + const uint32_t hit_info = (hit1 << 1) | hit0; + if (hit_info == CSR_MCONTROL6_HIT0_BEFORE) + return M6_HIT_BEFORE; + + if (hit_info == CSR_MCONTROL6_HIT0_AFTER) + return M6_HIT_AFTER; + + if (hit_info == CSR_MCONTROL6_HIT0_IMMEDIATELY_AFTER) + return M6_HIT_IMM_AFTER; + + if (hit_info == CSR_MCONTROL6_HIT0_FALSE) { + /* hit[1..0] equals 0, which can mean one of the following: + * - "hit" bits are supported and this trigger has not fired + * - "hit" bits are not supported on this trigger + * To distinguish these two cases, try writing all non-zero bit + * patterns to hit[1..0] to determine if the "hit" bits are supported: + */ + riscv_reg_t tdata1_tests[] = { + set_field(tdata1, CSR_MCONTROL6_HIT0, 1), + set_field(tdata1, CSR_MCONTROL6_HIT1, 1), + set_field(tdata1, CSR_MCONTROL6_HIT0, 1) | field_value(CSR_MCONTROL6_HIT1, 1) + }; + riscv_reg_t tdata1_test_rb; + for (uint64_t i = 0; i < ARRAY_SIZE(tdata1_tests); ++i) { + if (riscv_reg_set(target, GDB_REGNO_TDATA1, tdata1_tests[i]) != ERROR_OK) + return M6_HIT_ERROR; + if (riscv_reg_get(target, &tdata1_test_rb, GDB_REGNO_TDATA1) != ERROR_OK) + return M6_HIT_ERROR; + if (tdata1_test_rb == tdata1_tests[i]) { + if (riscv_reg_set(target, GDB_REGNO_TDATA1, tdata1_test_rb & ~hit_mask) != ERROR_OK) + return M6_HIT_ERROR; + return M6_NOT_HIT; + } + } + } + return M6_HIT_NOT_SUPPORTED; +} + /** * Look at the trigger hit bits to find out which trigger is the reason we're * halted. Sets *unique_id to the unique ID of that trigger. If *unique_id is * RISCV_TRIGGER_HIT_NOT_FOUND, no match was found. */ -static int riscv_trigger_detect_hit_bits(struct target *target, int64_t *unique_id) +static int riscv_trigger_detect_hit_bits(struct target *target, int64_t *unique_id, + bool *need_single_step) { /* FIXME: this function assumes that we have only one trigger that can * have hit bit set. Debug spec allows hit bit to bit set if a trigger has * matched but did not fire. Such targets will receive erroneous results. */ - // FIXME: Add hit bits support detection and caching RISCV_INFO(r); + assert(need_single_step); + *need_single_step = false; riscv_reg_t tselect; if (riscv_reg_get(target, &tselect, GDB_REGNO_TSELECT) != ERROR_OK) @@ -1563,9 +1862,21 @@ static int riscv_trigger_detect_hit_bits(struct target *target, int64_t *unique_ break; case CSR_TDATA1_TYPE_MCONTROL: hit_mask = CSR_MCONTROL_HIT; + *need_single_step = true; break; case CSR_TDATA1_TYPE_MCONTROL6: hit_mask = CSR_MCONTROL6_HIT0 | CSR_MCONTROL6_HIT1; + if (r->tinfo_version == CSR_TINFO_VERSION_0) { + *need_single_step = true; + } else if (r->tinfo_version == RISCV_TINFO_VERSION_UNKNOWN + || r->tinfo_version == CSR_TINFO_VERSION_1) { + mctrl6hitstatus hits_status = check_mcontrol6_hit_status(target, + tdata1, hit_mask); + if (hits_status == M6_HIT_ERROR) + return ERROR_FAIL; + if (hits_status == M6_HIT_BEFORE || hits_status == M6_HIT_NOT_SUPPORTED) + *need_single_step = true; + } break; case CSR_TDATA1_TYPE_ICOUNT: hit_mask = CSR_ICOUNT_HIT; @@ -1584,8 +1895,9 @@ static int riscv_trigger_detect_hit_bits(struct target *target, int64_t *unique_ /* FIXME: this logic needs to be changed to ignore triggers that are not * the last one in the chain. */ if (tdata1 & hit_mask) { - LOG_TARGET_DEBUG(target, "Trigger %u (unique_id=%" PRIi64 ") has hit bit set.", - i, r->trigger_unique_id[i]); + LOG_TARGET_DEBUG(target, "Trigger %u (unique_id=%" PRIi64 + ") has hit bit set. (need_single_step=%s)", + i, r->trigger_unique_id[i], (*need_single_step) ? "yes" : "no"); if (riscv_reg_set(target, GDB_REGNO_TDATA1, tdata1 & ~hit_mask) != ERROR_OK) return ERROR_FAIL; @@ -2125,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) @@ -2134,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 @@ -2149,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*/); @@ -2168,7 +2481,7 @@ static int riscv_examine(struct target *target) RISCV_INFO(info); uint32_t dtmcontrol; - if (dtmcontrol_scan(target, 0, &dtmcontrol) != ERROR_OK || dtmcontrol == 0) { + if (dtmcs_scan(target->tap, 0, &dtmcontrol) != ERROR_OK || dtmcontrol == 0) { LOG_TARGET_ERROR(target, "Could not read dtmcontrol. Check JTAG connectivity/board power."); return ERROR_FAIL; } @@ -2247,13 +2560,15 @@ static int set_debug_reason(struct target *target, enum riscv_halt_reason halt_r { RISCV_INFO(r); r->trigger_hit = -1; + r->need_single_step = false; switch (halt_reason) { case RISCV_HALT_EBREAK: target->debug_reason = DBG_REASON_BREAKPOINT; break; case RISCV_HALT_TRIGGER: target->debug_reason = DBG_REASON_UNDEFINED; - if (riscv_trigger_detect_hit_bits(target, &r->trigger_hit) != ERROR_OK) + if (riscv_trigger_detect_hit_bits(target, &r->trigger_hit, + &r->need_single_step) != ERROR_OK) return ERROR_FAIL; // FIXME: handle multiple hit bits if (r->trigger_hit != RISCV_TRIGGER_HIT_NOT_FOUND) { @@ -2353,10 +2668,15 @@ static int riscv_halt_go_all_harts(struct target *target) return ERROR_FAIL; } } else { + // Safety check: + if (riscv_reg_cache_any_dirty(target, LOG_LVL_ERROR)) + LOG_TARGET_INFO(target, "BUG: Registers should not be dirty while " + "the target is not halted!"); + + riscv_reg_cache_invalidate_all(target); + if (r->halt_go(target) != ERROR_OK) return ERROR_FAIL; - - riscv_invalidate_register_cache(target); } return ERROR_OK; @@ -2440,7 +2760,11 @@ static int riscv_assert_reset(struct target *target) struct target_type *tt = get_target_type(target); if (!tt) return ERROR_FAIL; - riscv_invalidate_register_cache(target); + + if (riscv_reg_cache_any_dirty(target, LOG_LVL_INFO)) + LOG_TARGET_INFO(target, "Discarding values of dirty registers."); + + riscv_reg_cache_invalidate_all(target); return tt->assert_reset(target); } @@ -2453,87 +2777,48 @@ static int riscv_deassert_reset(struct target *target) return tt->deassert_reset(target); } -/* state must be riscv_reg_t state[RISCV_MAX_HWBPS] = {0}; */ -static int disable_triggers(struct target *target, riscv_reg_t *state) +/* "wp_is_set" array must have at least "r->trigger_count" items. */ +static int disable_watchpoints(struct target *target, bool *wp_is_set) { RISCV_INFO(r); - LOG_TARGET_DEBUG(target, "Disabling triggers."); - if (riscv_enumerate_triggers(target) != ERROR_OK) - return ERROR_FAIL; - - if (r->manual_hwbp_set) { - /* Look at every trigger that may have been set. */ - riscv_reg_t tselect; - if (riscv_reg_get(target, &tselect, GDB_REGNO_TSELECT) != ERROR_OK) - return ERROR_FAIL; - for (unsigned int t = 0; t < r->trigger_count; t++) { - if (riscv_reg_set(target, GDB_REGNO_TSELECT, t) != ERROR_OK) - return ERROR_FAIL; - riscv_reg_t tdata1; - if (riscv_reg_get(target, &tdata1, GDB_REGNO_TDATA1) != ERROR_OK) + /* TODO: The algorithm is flawed and may result in a situation described in + * https://github.com/riscv-collab/riscv-openocd/issues/1108 + */ + memset(wp_is_set, false, r->trigger_count); + struct watchpoint *watchpoint = target->watchpoints; + int i = 0; + while (watchpoint) { + LOG_TARGET_DEBUG(target, "Watchpoint %" PRIu32 ": set=%s", + watchpoint->unique_id, + wp_is_set[i] ? "true" : "false"); + wp_is_set[i] = watchpoint->is_set; + if (watchpoint->is_set) { + if (riscv_remove_watchpoint(target, watchpoint) != ERROR_OK) return ERROR_FAIL; - if (tdata1 & CSR_TDATA1_DMODE(riscv_xlen(target))) { - state[t] = tdata1; - if (riscv_reg_set(target, GDB_REGNO_TDATA1, 0) != ERROR_OK) - return ERROR_FAIL; - } - } - if (riscv_reg_set(target, GDB_REGNO_TSELECT, tselect) != ERROR_OK) - return ERROR_FAIL; - - } else { - /* Just go through the triggers we manage. */ - struct watchpoint *watchpoint = target->watchpoints; - int i = 0; - while (watchpoint) { - LOG_TARGET_DEBUG(target, "Watchpoint %d: set=%d", i, watchpoint->is_set); - state[i] = watchpoint->is_set; - if (watchpoint->is_set) { - if (riscv_remove_watchpoint(target, watchpoint) != ERROR_OK) - return ERROR_FAIL; - } - watchpoint = watchpoint->next; - i++; } + watchpoint = watchpoint->next; + i++; } return ERROR_OK; } -static int enable_triggers(struct target *target, riscv_reg_t *state) +static int enable_watchpoints(struct target *target, bool *wp_is_set) { - RISCV_INFO(r); - - if (r->manual_hwbp_set) { - /* Look at every trigger that may have been set. */ - riscv_reg_t tselect; - if (riscv_reg_get(target, &tselect, GDB_REGNO_TSELECT) != ERROR_OK) - return ERROR_FAIL; - for (unsigned int t = 0; t < r->trigger_count; t++) { - if (state[t] != 0) { - if (riscv_reg_set(target, GDB_REGNO_TSELECT, t) != ERROR_OK) - return ERROR_FAIL; - if (riscv_reg_set(target, GDB_REGNO_TDATA1, state[t]) != ERROR_OK) - return ERROR_FAIL; - } - } - if (riscv_reg_set(target, GDB_REGNO_TSELECT, tselect) != ERROR_OK) - return ERROR_FAIL; - - } else { - struct watchpoint *watchpoint = target->watchpoints; - int i = 0; - while (watchpoint) { - LOG_TARGET_DEBUG(target, "Watchpoint %d: cleared=%" PRId64, i, state[i]); - if (state[i]) { - if (riscv_add_watchpoint(target, watchpoint) != ERROR_OK) - return ERROR_FAIL; - } - watchpoint = watchpoint->next; - i++; + struct watchpoint *watchpoint = target->watchpoints; + int i = 0; + while (watchpoint) { + LOG_TARGET_DEBUG(target, "Watchpoint %" PRIu32 + ": %s to be re-enabled.", watchpoint->unique_id, + wp_is_set[i] ? "needs " : "does not need"); + if (wp_is_set[i]) { + if (riscv_add_watchpoint(target, watchpoint) != ERROR_OK) + return ERROR_FAIL; } + watchpoint = watchpoint->next; + i++; } return ERROR_OK; @@ -2542,8 +2827,8 @@ static int enable_triggers(struct target *target, riscv_reg_t *state) /** * 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); @@ -2554,10 +2839,19 @@ static int resume_prep(struct target *target, int current, if (handle_breakpoints) { /* To be able to run off a trigger, we perform a step operation and then * resume. If handle_breakpoints is true then step temporarily disables - * pending breakpoints so we can safely perform the step. */ - if (old_or_new_riscv_step_impl(target, current, address, handle_breakpoints, - false /* callbacks are not called */) != ERROR_OK) - return ERROR_FAIL; + * pending breakpoints so we can safely perform the step. + * + * Two cases where single step is needed before resuming: + * 1. ebreak used in software breakpoint; + * 2. a trigger that is taken just before the instruction that triggered it is retired. + */ + if (target->debug_reason == DBG_REASON_BREAKPOINT + || (target->debug_reason == DBG_REASON_WATCHPOINT + && r->need_single_step)) { + if (old_or_new_riscv_step_impl(target, current, address, handle_breakpoints, + false /* callbacks are not called */) != ERROR_OK) + return ERROR_FAIL; + } } if (r->get_hart_state) { @@ -2575,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); @@ -2594,10 +2888,18 @@ 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); - register_cache_invalidate(target->reg_cache); + if (riscv_reg_cache_any_dirty(target, LOG_LVL_ERROR)) { + /* If this happens, it means there is a bug in the previous + * register-flushing algorithm: not all registers were flushed + * back to the target in preparation for the resume.*/ + LOG_TARGET_ERROR(target, + "BUG: registers should have been flushed by this point."); + } + + riscv_reg_cache_invalidate_all(target); target->state = debug_execution ? TARGET_DEBUG_RUNNING : TARGET_RUNNING; target->debug_reason = DBG_REASON_NOTHALTED; @@ -2611,17 +2913,17 @@ 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; struct list_head *targets; - LIST_HEAD(single_target_list); + OOCD_LIST_HEAD(single_target_list); struct target_list single_target_entry = { .lh = {NULL, NULL}, .target = target @@ -2675,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."); @@ -2715,7 +3017,7 @@ static int riscv_mmu(struct target *target, int *enabled) { *enabled = 0; - if (!riscv_enable_virt2phys) + if (!riscv_virt2phys_mode_is_sw(target)) return ERROR_OK; /* Don't use MMU in explicit or effective M (machine) mode */ @@ -2843,8 +3145,14 @@ static int riscv_address_translate(struct target *target, uint8_t buffer[8]; assert(info->pte_shift <= 3); - int retval = r->read_memory(target, pte_address, - 4, (1 << info->pte_shift) / 4, buffer, 4); + const riscv_mem_access_args_t args = { + .address = pte_address, + .read_buffer = buffer, + .size = 4, + .increment = 4, + .count = (1 << info->pte_shift) / 4, + }; + int retval = r->access_memory(target, args); if (retval != ERROR_OK) return ERROR_FAIL; @@ -3062,60 +3370,136 @@ static int riscv_virt2phys(struct target *target, target_addr_t virtual, target_ virtual, physical); } +static int check_virt_memory_access(struct target *target, target_addr_t address, + uint32_t size, uint32_t count, bool is_write) +{ + const bool is_misaligned = address % size != 0; + // TODO: This assumes that size of each page is 4 KiB, which is not necessarily the case. + const bool crosses_page_boundary = RISCV_PGBASE(address + size * count - 1) != RISCV_PGBASE(address); + if (is_misaligned && crosses_page_boundary) { + LOG_TARGET_ERROR(target, "Mis-aligned memory %s (address=0x%" TARGET_PRIxADDR ", size=%d, count=%d)" + " would access an element across page boundary. This is not supported.", + is_write ? "write" : "read", address, size, count); + return ERROR_FAIL; + } + return ERROR_OK; +} + static int riscv_read_phys_memory(struct target *target, target_addr_t phys_address, uint32_t size, uint32_t count, uint8_t *buffer) { + const riscv_mem_access_args_t args = { + .address = phys_address, + .read_buffer = buffer, + .size = size, + .count = count, + .increment = size, + }; RISCV_INFO(r); - return r->read_memory(target, phys_address, size, count, buffer, size); + return r->access_memory(target, args); } -static int riscv_read_memory(struct target *target, target_addr_t address, - uint32_t size, uint32_t count, uint8_t *buffer) +static int riscv_write_phys_memory(struct target *target, target_addr_t phys_address, + uint32_t size, uint32_t count, const uint8_t *buffer) +{ + const riscv_mem_access_args_t args = { + .address = phys_address, + .write_buffer = buffer, + .size = size, + .count = count, + .increment = size, + }; + + RISCV_INFO(r); + return r->access_memory(target, args); +} + +static int riscv_rw_memory(struct target *target, const riscv_mem_access_args_t args) { - if (count == 0) { - LOG_TARGET_WARNING(target, "0-length read from 0x%" TARGET_PRIxADDR, address); + assert(riscv_mem_access_is_valid(args)); + + const bool is_write = riscv_mem_access_is_write(args); + if (args.count == 0) { + LOG_TARGET_WARNING(target, "0-length %s 0x%" TARGET_PRIxADDR, + is_write ? "write to" : "read from", args.address); return ERROR_OK; } - target_addr_t physical_addr; - int result = target->type->virt2phys(target, address, &physical_addr); - if (result != ERROR_OK) { - LOG_TARGET_ERROR(target, "Address translation failed."); + int mmu_enabled; + int result = riscv_mmu(target, &mmu_enabled); + if (result != ERROR_OK) return result; - } RISCV_INFO(r); - return r->read_memory(target, physical_addr, size, count, buffer, size); + if (!mmu_enabled) + return r->access_memory(target, args); + + result = check_virt_memory_access(target, args.address, + args.size, args.count, is_write); + if (result != ERROR_OK) + return result; + + uint32_t current_count = 0; + target_addr_t current_address = args.address; + while (current_count < args.count) { + target_addr_t physical_addr; + result = target->type->virt2phys(target, current_address, &physical_addr); + if (result != ERROR_OK) { + LOG_TARGET_ERROR(target, "Address translation failed."); + return result; + } + + /* TODO: For simplicity, this algorithm assumes the worst case - the smallest possible page size, + * which is 4 KiB. The algorithm can be improved to detect the real page size, and allow to use larger + * memory transfers and avoid extra unnecessary virt2phys address translations. */ + uint32_t chunk_count = MIN(args.count - current_count, + (RISCV_PGSIZE - RISCV_PGOFFSET(current_address)) + / args.size); + + riscv_mem_access_args_t current_access = args; + current_access.address = physical_addr; + current_access.count = chunk_count; + if (is_write) + current_access.write_buffer += current_count * args.size; + else + current_access.read_buffer += current_count * args.size; + + result = r->access_memory(target, current_access); + if (result != ERROR_OK) + return result; + + current_count += chunk_count; + current_address += chunk_count * args.size; + } + return ERROR_OK; } -static int riscv_write_phys_memory(struct target *target, target_addr_t phys_address, - uint32_t size, uint32_t count, const uint8_t *buffer) +static int riscv_read_memory(struct target *target, target_addr_t address, + uint32_t size, uint32_t count, uint8_t *buffer) { - struct target_type *tt = get_target_type(target); - if (!tt) - return ERROR_FAIL; - return tt->write_memory(target, phys_address, size, count, buffer); + const riscv_mem_access_args_t args = { + .address = address, + .read_buffer = buffer, + .size = size, + .count = count, + .increment = size, + }; + + return riscv_rw_memory(target, args); } static int riscv_write_memory(struct target *target, target_addr_t address, uint32_t size, uint32_t count, const uint8_t *buffer) { - if (count == 0) { - LOG_TARGET_WARNING(target, "0-length write to 0x%" TARGET_PRIxADDR, address); - return ERROR_OK; - } - - target_addr_t physical_addr; - int result = target->type->virt2phys(target, address, &physical_addr); - if (result != ERROR_OK) { - LOG_TARGET_ERROR(target, "Address translation failed."); - return result; - } + const riscv_mem_access_args_t args = { + .address = address, + .write_buffer = buffer, + .size = size, + .count = count, + .increment = size, + }; - struct target_type *tt = get_target_type(target); - if (!tt) - return ERROR_FAIL; - return tt->write_memory(target, physical_addr, size, count, buffer); + return riscv_rw_memory(target, args); } static const char *riscv_get_gdb_arch(const struct target *target) @@ -3269,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(); @@ -3299,7 +3682,7 @@ static int riscv_run_algorithm(struct target *target, int num_mem_params, GDB_REGNO_PC, GDB_REGNO_MSTATUS, GDB_REGNO_MEPC, GDB_REGNO_MCAUSE, }; - for (unsigned i = 0; i < ARRAY_SIZE(regnums); i++) { + for (unsigned int i = 0; i < ARRAY_SIZE(regnums); i++) { enum gdb_regno regno = regnums[i]; riscv_reg_t reg_value; if (riscv_reg_get(target, ®_value, regno) != ERROR_OK) @@ -3394,8 +3777,8 @@ static int riscv_checksum_memory(struct target *target, static const uint8_t *crc_code; - unsigned xlen = riscv_xlen(target); - unsigned crc_code_size; + unsigned int xlen = riscv_xlen(target); + unsigned int crc_code_size; if (xlen == 32) { crc_code = riscv32_crc_code; crc_code_size = sizeof(riscv32_crc_code); @@ -3651,9 +4034,11 @@ int riscv_openocd_poll(struct target *target) { LOG_TARGET_DEBUG(target, "Polling all harts."); + struct riscv_info *i = riscv_info(target); + struct list_head *targets; - LIST_HEAD(single_target_list); + OOCD_LIST_HEAD(single_target_list); struct target_list single_target_entry = { .lh = {NULL, NULL}, .target = target @@ -3672,6 +4057,7 @@ int riscv_openocd_poll(struct target *target) unsigned int should_resume = 0; unsigned int halted = 0; unsigned int running = 0; + unsigned int cause_groups = 0; struct target_list *entry; foreach_smp_target(entry, targets) { struct target *t = entry->target; @@ -3719,6 +4105,59 @@ int riscv_openocd_poll(struct target *target) LOG_TARGET_DEBUG(target, "resume all"); riscv_resume(target, true, 0, 0, 0, false); } else if (halted && running) { + LOG_TARGET_DEBUG(target, "SMP group is in inconsistent state: %u halted, %u running", + halted, running); + + /* The SMP group is in an inconsistent state - some harts in the group have halted + * whereas others are running. The reasons for that (and corresponding + * OpenOCD actions) could be: + * 1) The targets are in the process of halting due to halt groups + * but not all of them halted --> poll again so that the halt reason of every + * hart can be accurately determined (e.g. semihosting). + * 2) The targets do not support halt groups --> OpenOCD must halt + * the remaining harts by a standard halt request. + * 3) The hart states got out of sync for some other unknown reason (problem?). --> + * Same as previous - try to halt the harts by a standard halt request + * to get them back in sync. */ + + /* Detect if the harts are just in the process of halting due to a halt group */ + foreach_smp_target(entry, targets) + { + struct target *t = entry->target; + if (t->state == TARGET_HALTED) { + riscv_reg_t dcsr; + if (riscv_reg_get(t, &dcsr, GDB_REGNO_DCSR) != ERROR_OK) + return ERROR_FAIL; + if (get_field(dcsr, CSR_DCSR_CAUSE) == CSR_DCSR_CAUSE_GROUP) + cause_groups++; + else + /* This hart has halted due to something else than a halt group. + * Don't continue checking the rest - exit early. */ + break; + } + } + /* Condition: halted == cause_groups + * + * This condition indicates a paradox where: + * - All currently halted harts show CSR_DCSR_CAUSE_GROUP + * - However, no individual hart can be identified as the actual initiator of the halt condition + * + * Poll again so that the true halt reason can be discovered (e.g. CSR_DCSR_CAUSE_EBREAK) */ + if (halted == cause_groups) { + LOG_TARGET_DEBUG(target, "The harts appear to just be in the process of halting due to a halt group."); + if (i->halt_group_repoll_count < RISCV_HALT_GROUP_REPOLL_LIMIT) { + /* Wait a little, then re-poll. */ + i->halt_group_repoll_count++; + alive_sleep(10); + LOG_TARGET_DEBUG(target, "Re-polling the state of the SMP group."); + return riscv_openocd_poll(target); + } + /* We have already re-polled multiple times but the halt group is still inconsistent. */ + LOG_TARGET_DEBUG(target, "Re-polled the SMP group %d times it is still not in a consistent state.", + RISCV_HALT_GROUP_REPOLL_LIMIT); + } + + /* Halting the whole SMP group to bring it in sync. */ LOG_TARGET_DEBUG(target, "halt all; halted=%d", halted); riscv_halt(target); @@ -3736,6 +4175,8 @@ int riscv_openocd_poll(struct target *target) } } + i->halt_group_repoll_count = 0; + /* Call tick() for every hart. What happens in tick() is opaque to this * layer. The reason it's outside the previous loop is that at this point * the state of every hart has settled, so any side effects happening in @@ -3759,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"); @@ -3781,19 +4222,24 @@ static int riscv_openocd_step_impl(struct target *target, int current, return ERROR_FAIL; } - riscv_reg_t trigger_state[RISCV_MAX_HWBPS] = {0}; - if (disable_triggers(target, trigger_state) != ERROR_OK) + if (riscv_enumerate_triggers(target) != ERROR_OK) + return ERROR_FAIL; + + RISCV_INFO(r); + bool *wps_to_enable = calloc(r->trigger_count, sizeof(*wps_to_enable)); + if (disable_watchpoints(target, wps_to_enable) != ERROR_OK) { + LOG_TARGET_ERROR(target, "Failed to temporarily disable " + "watchpoints before single-step."); return ERROR_FAIL; + } bool success = true; - uint64_t current_mstatus; + riscv_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; @@ -3805,7 +4251,15 @@ static int riscv_openocd_step_impl(struct target *target, int current, LOG_TARGET_ERROR(target, "Unable to step rtos hart."); } - register_cache_invalidate(target->reg_cache); + if (riscv_reg_cache_any_dirty(target, LOG_LVL_ERROR)) { + /* If this happens, it means there is a bug in the previous + * register-flushing algorithm: not all registers were flushed + * back to the target prior to single-step. */ + LOG_TARGET_ERROR(target, + "BUG: registers should have been flushed by this point."); + } + + riscv_reg_cache_invalidate_all(target); if (info->isrmask_mode == RISCV_ISRMASK_STEPONLY) if (riscv_interrupts_restore(target, current_mstatus) != ERROR_OK) { @@ -3814,9 +4268,10 @@ static int riscv_openocd_step_impl(struct target *target, int current, } _exit: - if (enable_triggers(target, trigger_state) != ERROR_OK) { + if (enable_watchpoints(target, wps_to_enable) != ERROR_OK) { success = false; - LOG_TARGET_ERROR(target, "Unable to enable triggers."); + LOG_TARGET_ERROR(target, "Failed to re-enable watchpoints " + "after single-step."); } if (breakpoint && (riscv_add_breakpoint(target, breakpoint) != ERROR_OK)) { @@ -3838,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 */); @@ -3848,10 +4303,9 @@ int riscv_openocd_step(struct target *target, int current, /* Command Handlers */ COMMAND_HANDLER(riscv_set_command_timeout_sec) { - if (CMD_ARGC != 1) { - LOG_ERROR("Command takes exactly 1 parameter."); + if (CMD_ARGC != 1) return ERROR_COMMAND_SYNTAX_ERROR; - } + int timeout = atoi(CMD_ARGV[0]); if (timeout <= 0) { LOG_ERROR("%s is not a valid integer argument for command.", CMD_ARGV[0]); @@ -3866,10 +4320,9 @@ COMMAND_HANDLER(riscv_set_command_timeout_sec) COMMAND_HANDLER(riscv_set_reset_timeout_sec) { LOG_WARNING("The command 'riscv set_reset_timeout_sec' is deprecated! Please, use 'riscv set_command_timeout_sec'."); - if (CMD_ARGC != 1) { - LOG_ERROR("Command takes exactly 1 parameter."); + if (CMD_ARGC != 1) return ERROR_COMMAND_SYNTAX_ERROR; - } + int timeout = atoi(CMD_ARGV[0]); if (timeout <= 0) { LOG_ERROR("%s is not a valid integer argument for command.", CMD_ARGV[0]); @@ -3888,9 +4341,10 @@ COMMAND_HANDLER(riscv_set_mem_access) int sysbus_cnt = 0; int abstract_cnt = 0; - if (CMD_ARGC < 1 || CMD_ARGC > RISCV_NUM_MEM_ACCESS_METHODS) { - LOG_ERROR("Command takes 1 to %d parameters", RISCV_NUM_MEM_ACCESS_METHODS); - return ERROR_COMMAND_SYNTAX_ERROR; + if (CMD_ARGC < 1 || CMD_ARGC > RISCV_MEM_ACCESS_MAX_METHODS_NUM) { + command_print(CMD, "Command takes 1 to %d parameters", + RISCV_MEM_ACCESS_MAX_METHODS_NUM); + return ERROR_COMMAND_ARGUMENT_INVALID; } /* Check argument validity */ @@ -3913,8 +4367,7 @@ COMMAND_HANDLER(riscv_set_mem_access) } /* Args are valid, store them */ - for (unsigned int i = 0; i < RISCV_NUM_MEM_ACCESS_METHODS; i++) - r->mem_access_methods[i] = RISCV_MEM_ACCESS_UNSPECIFIED; + r->num_enabled_mem_access_methods = CMD_ARGC; for (unsigned int i = 0; i < CMD_ARGC; i++) { if (strcmp("progbuf", CMD_ARGV[i]) == 0) r->mem_access_methods[i] = RISCV_MEM_ACCESS_PROGBUF; @@ -3925,91 +4378,106 @@ COMMAND_HANDLER(riscv_set_mem_access) } /* Reset warning flags */ - r->mem_access_progbuf_warn = true; - r->mem_access_sysbus_warn = true; - r->mem_access_abstract_warn = true; + for (size_t i = 0; i < RISCV_MEM_ACCESS_MAX_METHODS_NUM; ++i) + r->mem_access_warn[i] = true; return ERROR_OK; } -COMMAND_HANDLER(riscv_set_enable_virtual) -{ - if (CMD_ARGC != 1) { - LOG_ERROR("Command takes exactly 1 parameter"); - return ERROR_COMMAND_SYNTAX_ERROR; - } - COMMAND_PARSE_ON_OFF(CMD_ARGV[0], riscv_enable_virtual); - return ERROR_OK; -} -static int parse_ranges(struct list_head *ranges, const char *tcl_arg, const char *reg_type, unsigned int max_val) +static bool parse_csr_address(const char *reg_address_str, unsigned int *reg_addr) { - char *args = strdup(tcl_arg); - if (!args) - return ERROR_FAIL; + *reg_addr = -1; + /* skip initial spaces */ + while (isspace(reg_address_str[0])) + ++reg_address_str; + /* try to detect if string starts with 0x or 0X */ + bool is_hex_address = strncmp(reg_address_str, "0x", 2) == 0 || + strncmp(reg_address_str, "0X", 2) == 0; - /* For backward compatibility, allow multiple parameters within one TCL argument, separated by ',' */ - char *arg = strtok(args, ","); - while (arg) { - unsigned low = 0; - unsigned high = 0; + unsigned int scanned_chars; + if (is_hex_address) { + reg_address_str += 2; + if (sscanf(reg_address_str, "%x%n", reg_addr, &scanned_chars) != 1) + return false; + } else { + /* If we are here and register address string starts with zero, this is + * an indication that most likely user has an incorrect input because: + * - decimal numbers typically do not start with "0" + * - octals are not supported by our interface + * - hexadecimal numbers should have "0x" prefix + * Thus such input is rejected. */ + if (reg_address_str[0] == '0' && strlen(reg_address_str) > 1) + return false; + if (sscanf(reg_address_str, "%u%n", reg_addr, &scanned_chars) != 1) + return false; + } + return scanned_chars == strlen(reg_address_str); +} + +static int parse_reg_ranges_impl(struct list_head *ranges, char *args, + const char *reg_type, unsigned int max_val, char ** const name_buffer) +{ + /* For backward compatibility, allow multiple parameters within one TCL + * argument, separated by ',' */ + for (char *arg = strtok(args, ","); arg; arg = strtok(NULL, ",")) { + unsigned int low = 0; + unsigned int high = 0; char *name = NULL; char *dash = strchr(arg, '-'); char *equals = strchr(arg, '='); - unsigned int pos; if (!dash && !equals) { /* Expecting single register number. */ - if (sscanf(arg, "%u%n", &low, &pos) != 1 || pos != strlen(arg)) { + if (!parse_csr_address(arg, &low)) { LOG_ERROR("Failed to parse single register number from '%s'.", arg); - free(args); return ERROR_COMMAND_SYNTAX_ERROR; } } else if (dash && !equals) { /* Expecting register range - two numbers separated by a dash: ##-## */ - *dash = 0; - dash++; - if (sscanf(arg, "%u%n", &low, &pos) != 1 || pos != strlen(arg)) { - LOG_ERROR("Failed to parse single register number from '%s'.", arg); - free(args); + *dash = '\0'; + if (!parse_csr_address(arg, &low)) { + LOG_ERROR("Failed to parse '%s' - not a valid decimal or hexadecimal number.", + arg); return ERROR_COMMAND_SYNTAX_ERROR; } - if (sscanf(dash, "%u%n", &high, &pos) != 1 || pos != strlen(dash)) { - LOG_ERROR("Failed to parse single register number from '%s'.", dash); - free(args); + const char *high_num_in = dash + 1; + if (!parse_csr_address(high_num_in, &high)) { + LOG_ERROR("Failed to parse '%s' - not a valid decimal or hexadecimal number.", + high_num_in); return ERROR_COMMAND_SYNTAX_ERROR; } if (high < low) { LOG_ERROR("Incorrect range encountered [%u, %u].", low, high); - free(args); return ERROR_FAIL; } } else if (!dash && equals) { /* Expecting single register number with textual name specified: ##=name */ - *equals = 0; - equals++; - if (sscanf(arg, "%u%n", &low, &pos) != 1 || pos != strlen(arg)) { - LOG_ERROR("Failed to parse single register number from '%s'.", arg); - free(args); + *equals = '\0'; + if (!parse_csr_address(arg, &low)) { + LOG_ERROR("Failed to parse '%s' - not a valid decimal or hexadecimal number.", + arg); return ERROR_COMMAND_SYNTAX_ERROR; } - name = calloc(1, strlen(equals) + strlen(reg_type) + 2); + const char * const reg_name_in = equals + 1; + const size_t reg_type_len = strlen(reg_type); + /* format is: <reg_type>_<reg_name_in>\0 */ + *name_buffer = calloc(1, strlen(reg_name_in) + reg_type_len + 2); + name = *name_buffer; if (!name) { - LOG_ERROR("Failed to allocate register name."); - free(args); + LOG_ERROR("Out of memory"); return ERROR_FAIL; } - - /* Register prefix: "csr_" or "custom_" */ strcpy(name, reg_type); - name[strlen(reg_type)] = '_'; + name[reg_type_len] = '_'; - if (sscanf(equals, "%[_a-zA-Z0-9]%n", name + strlen(reg_type) + 1, &pos) != 1 || pos != strlen(equals)) { - LOG_ERROR("Failed to parse register name from '%s'.", equals); - free(args); - free(name); + unsigned int scanned_chars; + char *scan_dst = name + strlen(reg_type) + 1; + if (sscanf(reg_name_in, "%[_a-zA-Z0-9]%n", scan_dst, &scanned_chars) != 1 || + scanned_chars != strlen(reg_name_in)) { + LOG_ERROR("Invalid characters in register name '%s'.", reg_name_in); return ERROR_COMMAND_SYNTAX_ERROR; } } else { @@ -4018,12 +4486,11 @@ static int parse_ranges(struct list_head *ranges, const char *tcl_arg, const cha return ERROR_COMMAND_SYNTAX_ERROR; } - high = high > low ? high : low; + high = MAX(high, low); if (high > max_val) { - LOG_ERROR("Cannot expose %s register number %u, maximum allowed value is %u.", reg_type, high, max_val); - free(name); - free(args); + LOG_ERROR("Cannot expose %s register number 0x%x, maximum allowed value is 0x%x.", + reg_type, high, max_val); return ERROR_FAIL; } @@ -4041,45 +4508,53 @@ static int parse_ranges(struct list_head *ranges, const char *tcl_arg, const cha if (entry->name && name && (strcasecmp(entry->name, name) == 0)) { LOG_ERROR("Duplicate register name \"%s\" found.", name); - free(name); - free(args); return ERROR_FAIL; } } range_list_t *range = calloc(1, sizeof(range_list_t)); if (!range) { - LOG_ERROR("Failed to allocate range list."); - free(name); - free(args); + LOG_ERROR("Out of memory"); return ERROR_FAIL; } range->low = low; range->high = high; range->name = name; + /* ownership over name_buffer contents is transferred to list item here */ + *name_buffer = NULL; list_add(&range->list, ranges); - - arg = strtok(NULL, ","); } - free(args); return ERROR_OK; } +static int parse_reg_ranges(struct list_head *ranges, const char *tcl_arg, + const char *reg_type, unsigned int max_val) +{ + char *args = strdup(tcl_arg); + if (!args) { + LOG_ERROR("Out of memory"); + return ERROR_FAIL; + } + char *name_buffer = NULL; + int result = parse_reg_ranges_impl(ranges, args, reg_type, max_val, &name_buffer); + free(name_buffer); + free(args); + return result; +} + COMMAND_HANDLER(riscv_set_expose_csrs) { - if (CMD_ARGC == 0) { - LOG_ERROR("Command expects parameters."); + if (CMD_ARGC == 0) return ERROR_COMMAND_SYNTAX_ERROR; - } struct target *target = get_current_target(CMD_CTX); RISCV_INFO(info); int ret = ERROR_OK; for (unsigned int i = 0; i < CMD_ARGC; i++) { - ret = parse_ranges(&info->expose_csr, CMD_ARGV[i], "csr", 0xfff); + ret = parse_reg_ranges(&info->expose_csr, CMD_ARGV[i], "csr", 0xfff); if (ret != ERROR_OK) break; } @@ -4089,17 +4564,15 @@ COMMAND_HANDLER(riscv_set_expose_csrs) COMMAND_HANDLER(riscv_set_expose_custom) { - if (CMD_ARGC == 0) { - LOG_ERROR("Command expects parameters."); + if (CMD_ARGC == 0) return ERROR_COMMAND_SYNTAX_ERROR; - } struct target *target = get_current_target(CMD_CTX); RISCV_INFO(info); int ret = ERROR_OK; for (unsigned int i = 0; i < CMD_ARGC; i++) { - ret = parse_ranges(&info->expose_custom, CMD_ARGV[i], "custom", 0x3fff); + ret = parse_reg_ranges(&info->expose_custom, CMD_ARGV[i], "custom", 0x3fff); if (ret != ERROR_OK) break; } @@ -4109,17 +4582,15 @@ COMMAND_HANDLER(riscv_set_expose_custom) COMMAND_HANDLER(riscv_hide_csrs) { - if (CMD_ARGC == 0) { - LOG_ERROR("Command expects parameters"); + if (CMD_ARGC == 0) return ERROR_COMMAND_SYNTAX_ERROR; - } struct target *target = get_current_target(CMD_CTX); RISCV_INFO(info); int ret = ERROR_OK; for (unsigned int i = 0; i < CMD_ARGC; i++) { - ret = parse_ranges(&info->hide_csr, CMD_ARGV[i], "csr", 0xfff); + ret = parse_reg_ranges(&info->hide_csr, CMD_ARGV[i], "csr", 0xfff); if (ret != ERROR_OK) break; } @@ -4130,14 +4601,10 @@ COMMAND_HANDLER(riscv_hide_csrs) COMMAND_HANDLER(riscv_authdata_read) { unsigned int index = 0; - if (CMD_ARGC == 0) { - /* nop */ - } else if (CMD_ARGC == 1) { + if (CMD_ARGC == 1) COMMAND_PARSE_NUMBER(uint, CMD_ARGV[0], index); - } else { - LOG_ERROR("Command takes at most one parameter."); + else if (CMD_ARGC != 0) return ERROR_COMMAND_SYNTAX_ERROR; - } struct target *target = get_current_target(CMD_CTX); if (!target) { @@ -4341,10 +4808,8 @@ COMMAND_HANDLER(riscv_reset_delays) COMMAND_HANDLER(riscv_set_ir) { - if (CMD_ARGC != 2) { - LOG_ERROR("Command takes exactly 2 arguments"); + if (CMD_ARGC != 2) return ERROR_COMMAND_SYNTAX_ERROR; - } uint32_t value; COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], value); @@ -4363,10 +4828,8 @@ COMMAND_HANDLER(riscv_set_ir) COMMAND_HANDLER(riscv_resume_order) { - if (CMD_ARGC > 1) { - LOG_ERROR("Command takes at most one argument"); + if (CMD_ARGC > 1) return ERROR_COMMAND_SYNTAX_ERROR; - } if (!strcmp(CMD_ARGV[0], "normal")) { resume_order = RO_NORMAL; @@ -4382,18 +4845,23 @@ COMMAND_HANDLER(riscv_resume_order) COMMAND_HANDLER(riscv_use_bscan_tunnel) { - int irwidth = 0; + uint8_t irwidth = 0; int tunnel_type = BSCAN_TUNNEL_NESTED_TAP; - if (CMD_ARGC > 2) { - LOG_ERROR("Command takes at most two arguments"); + if (CMD_ARGC < 1 || CMD_ARGC > 2) return ERROR_COMMAND_SYNTAX_ERROR; - } else if (CMD_ARGC == 1) { - COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], irwidth); - } else if (CMD_ARGC == 2) { - COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], irwidth); - COMMAND_PARSE_NUMBER(int, CMD_ARGV[1], tunnel_type); + + if (CMD_ARGC >= 1) { + COMMAND_PARSE_NUMBER(u8, CMD_ARGV[0], irwidth); + assert(BSCAN_TUNNEL_IR_WIDTH_NBITS < 8); + if (irwidth >= (uint8_t)1 << BSCAN_TUNNEL_IR_WIDTH_NBITS) { + command_print(CMD, "'value' does not fit into %d bits.", + BSCAN_TUNNEL_IR_WIDTH_NBITS); + return ERROR_COMMAND_ARGUMENT_OVERFLOW; + } } + if (CMD_ARGC == 2) + COMMAND_PARSE_NUMBER(int, CMD_ARGV[1], tunnel_type); if (tunnel_type == BSCAN_TUNNEL_NESTED_TAP) LOG_INFO("Nested Tap based Bscan Tunnel Selected"); else if (tunnel_type == BSCAN_TUNNEL_DATA_REGISTER) @@ -4410,12 +4878,11 @@ COMMAND_HANDLER(riscv_set_bscan_tunnel_ir) { int ir_id = 0; - if (CMD_ARGC > 1) { - LOG_ERROR("Command takes at most one arguments"); + if (CMD_ARGC > 1) return ERROR_COMMAND_SYNTAX_ERROR; - } else if (CMD_ARGC == 1) { + + if (CMD_ARGC == 1) COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], ir_id); - } LOG_INFO("Bscan tunnel IR 0x%x selected", ir_id); @@ -4448,74 +4915,93 @@ COMMAND_HANDLER(riscv_set_maskisr) return ERROR_OK; } -COMMAND_HANDLER(riscv_set_enable_virt2phys) -{ - if (CMD_ARGC != 1) { - LOG_ERROR("Command takes exactly 1 parameter"); - return ERROR_COMMAND_SYNTAX_ERROR; - } - COMMAND_PARSE_ON_OFF(CMD_ARGV[0], riscv_enable_virt2phys); - return ERROR_OK; -} - -COMMAND_HANDLER(riscv_set_ebreakm) +COMMAND_HANDLER(riscv_set_autofence) { struct target *target = get_current_target(CMD_CTX); RISCV_INFO(r); if (CMD_ARGC == 0) { - command_print(CMD, "riscv_ebreakm enabled: %s", r->riscv_ebreakm ? "on" : "off"); + command_print(CMD, "autofence: %s", r->autofence ? "on" : "off"); return ERROR_OK; } else if (CMD_ARGC == 1) { - COMMAND_PARSE_ON_OFF(CMD_ARGV[0], r->riscv_ebreakm); + COMMAND_PARSE_ON_OFF(CMD_ARGV[0], r->autofence); return ERROR_OK; } - LOG_ERROR("Command takes 0 or 1 parameters"); return ERROR_COMMAND_SYNTAX_ERROR; } -COMMAND_HANDLER(riscv_set_ebreaks) +COMMAND_HELPER(ebreakx_deprecation_helper, enum riscv_priv_mode mode) { - struct target *target = get_current_target(CMD_CTX); - RISCV_INFO(r); - + struct target * const target = get_current_target(CMD_CTX); + struct riscv_private_config * const config = riscv_private_config(target); + const char *mode_str; + switch (mode) { + case RISCV_MODE_M: + mode_str = "m"; + break; + case RISCV_MODE_S: + mode_str = "s"; + break; + case RISCV_MODE_U: + mode_str = "u"; + break; + default: + assert(0 && "Unexpected execution mode"); + mode_str = "unexpected"; + } + if (CMD_ARGC > 1) + return ERROR_COMMAND_SYNTAX_ERROR; if (CMD_ARGC == 0) { - command_print(CMD, "riscv_ebreaks enabled: %s", r->riscv_ebreaks ? "on" : "off"); - return ERROR_OK; - } else if (CMD_ARGC == 1) { - COMMAND_PARSE_ON_OFF(CMD_ARGV[0], r->riscv_ebreaks); + LOG_WARNING("DEPRECATED! use '%s cget -ebreak' not '%s'", + target_name(target), CMD_NAME); + command_print(CMD, "riscv_ebreak%s enabled: %s", mode_str, + config->dcsr_ebreak_fields[mode] ? "on" : "off"); return ERROR_OK; } - - LOG_ERROR("Command takes 0 or 1 parameters"); - return ERROR_COMMAND_SYNTAX_ERROR; + assert(CMD_ARGC == 1); + command_print(CMD, "DEPRECATED! use '%s configure -ebreak %s' not '%s'", + target_name(target), mode_str, CMD_NAME); + bool ebreak_ctl; + COMMAND_PARSE_ON_OFF(CMD_ARGV[0], ebreak_ctl); + config->dcsr_ebreak_fields[mode] = ebreak_ctl; + switch (mode) { + case RISCV_MODE_S: + config->dcsr_ebreak_fields[RISCV_MODE_VS] = ebreak_ctl; + break; + case RISCV_MODE_U: + config->dcsr_ebreak_fields[RISCV_MODE_VU] = ebreak_ctl; + break; + default: + break; + } + return ERROR_OK; } -COMMAND_HANDLER(riscv_set_ebreaku) +COMMAND_HANDLER(riscv_set_ebreakm) { - struct target *target = get_current_target(CMD_CTX); - RISCV_INFO(r); + return CALL_COMMAND_HANDLER(ebreakx_deprecation_helper, + RISCV_MODE_M); +} - if (CMD_ARGC == 0) { - command_print(CMD, "riscv_ebreaku enabled: %s", r->riscv_ebreaku ? "on" : "off"); - return ERROR_OK; - } else if (CMD_ARGC == 1) { - COMMAND_PARSE_ON_OFF(CMD_ARGV[0], r->riscv_ebreaku); - return ERROR_OK; - } +COMMAND_HANDLER(riscv_set_ebreaks) +{ + return CALL_COMMAND_HANDLER(ebreakx_deprecation_helper, + RISCV_MODE_S); +} - LOG_ERROR("Command takes 0 or 1 parameters"); - return ERROR_COMMAND_SYNTAX_ERROR; +COMMAND_HANDLER(riscv_set_ebreaku) +{ + return CALL_COMMAND_HANDLER(ebreakx_deprecation_helper, + RISCV_MODE_U); } COMMAND_HELPER(riscv_clear_trigger, int trigger_id, const char *name) { struct target *target = get_current_target(CMD_CTX); - if (CMD_ARGC != 1) { - LOG_ERROR("clear command takes no extra arguments."); + if (CMD_ARGC != 1) return ERROR_COMMAND_SYNTAX_ERROR; - } + if (find_first_trigger_by_id(target, trigger_id) < 0) { LOG_TARGET_ERROR(target, "No %s is set. Nothing to clear.", name); return ERROR_FAIL; @@ -4525,10 +5011,8 @@ COMMAND_HELPER(riscv_clear_trigger, int trigger_id, const char *name) COMMAND_HANDLER(riscv_itrigger) { - if (CMD_ARGC < 1) { - LOG_ERROR("Command takes at least 1 parameter"); + if (CMD_ARGC < 1) return ERROR_COMMAND_SYNTAX_ERROR; - } struct target *target = get_current_target(CMD_CTX); const int ITRIGGER_UNIQUE_ID = -CSR_TDATA1_TYPE_ITRIGGER; @@ -4592,10 +5076,8 @@ COMMAND_HANDLER(riscv_itrigger) COMMAND_HANDLER(riscv_icount) { - if (CMD_ARGC < 1) { - LOG_ERROR("Command takes at least 1 parameter"); + if (CMD_ARGC < 1) return ERROR_COMMAND_SYNTAX_ERROR; - } struct target *target = get_current_target(CMD_CTX); const int ICOUNT_UNIQUE_ID = -CSR_TDATA1_TYPE_ICOUNT; @@ -4659,10 +5141,8 @@ COMMAND_HANDLER(riscv_icount) COMMAND_HANDLER(riscv_etrigger) { - if (CMD_ARGC < 1) { - LOG_ERROR("Command takes at least 1 parameter"); + if (CMD_ARGC < 1) return ERROR_COMMAND_SYNTAX_ERROR; - } struct target *target = get_current_target(CMD_CTX); const int ETRIGGER_UNIQUE_ID = -CSR_TDATA1_TYPE_ETRIGGER; @@ -4726,14 +5206,8 @@ COMMAND_HANDLER(handle_repeat_read) struct target *target = get_current_target(CMD_CTX); RISCV_INFO(r); - if (CMD_ARGC < 2) { - LOG_ERROR("Command requires at least count and address arguments."); + if (CMD_ARGC < 2 || CMD_ARGC > 3) return ERROR_COMMAND_SYNTAX_ERROR; - } - if (CMD_ARGC > 3) { - LOG_ERROR("Command takes at most 3 arguments."); - return ERROR_COMMAND_SYNTAX_ERROR; - } uint32_t count; COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], count); @@ -4751,7 +5225,14 @@ COMMAND_HANDLER(handle_repeat_read) LOG_ERROR("malloc failed"); return ERROR_FAIL; } - int result = r->read_memory(target, address, size, count, buffer, 0); + const riscv_mem_access_args_t args = { + .address = address, + .read_buffer = buffer, + .size = size, + .count = count, + .increment = 0, + }; + int result = r->access_memory(target, args); if (result == ERROR_OK) { target_handle_md_output(cmd, target, address, size, count, buffer, false); @@ -4779,10 +5260,8 @@ COMMAND_HANDLER(handle_memory_sample_command) return ERROR_OK; } - if (CMD_ARGC < 2) { - LOG_ERROR("Command requires at least bucket and address arguments."); + if (CMD_ARGC < 2) return ERROR_COMMAND_SYNTAX_ERROR; - } uint32_t bucket; COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], bucket); @@ -4828,10 +5307,9 @@ COMMAND_HANDLER(handle_dump_sample_buf_command) struct target *target = get_current_target(CMD_CTX); RISCV_INFO(r); - if (CMD_ARGC > 1) { - LOG_ERROR("Command takes at most 1 arguments."); + if (CMD_ARGC > 1) return ERROR_COMMAND_SYNTAX_ERROR; - } + bool base64 = false; if (CMD_ARGC > 0) { if (!strcmp(CMD_ARGV[0], "base64")) { @@ -4937,10 +5415,8 @@ COMMAND_HANDLER(handle_info) COMMAND_HANDLER(riscv_exec_progbuf) { - if (CMD_ARGC < 1 || CMD_ARGC > 16) { - LOG_ERROR("Command 'exec_progbuf' takes 1 to 16 arguments."); + if (CMD_ARGC < 1 || CMD_ARGC > 16) return ERROR_COMMAND_SYNTAX_ERROR; - } struct target *target = get_current_target(CMD_CTX); @@ -4976,7 +5452,7 @@ COMMAND_HANDLER(riscv_exec_progbuf) if (riscv_reg_flush_all(target) != ERROR_OK) return ERROR_FAIL; int error = riscv_program_exec(&prog, target); - riscv_invalidate_register_cache(target); + riscv_reg_cache_invalidate_all(target); if (error != ERROR_OK) { LOG_TARGET_ERROR(target, "exec_progbuf: Program buffer execution failed."); @@ -5031,6 +5507,87 @@ COMMAND_HANDLER(riscv_set_enable_trigger_feature) return ERROR_OK; } +static COMMAND_HELPER(report_reserved_triggers, struct target *target) +{ + RISCV_INFO(r); + if (riscv_enumerate_triggers(target) != ERROR_OK) + return ERROR_FAIL; + const char *separator = ""; + for (riscv_reg_t t = 0; t < r->trigger_count; ++t) { + if (r->reserved_triggers[t]) { + command_print_sameline(CMD, "%s%" PRIu64, separator, t); + separator = " "; + } + } + command_print_sameline(CMD, "\n"); + return ERROR_OK; +} + +COMMAND_HANDLER(handle_reserve_trigger) +{ + struct target *target = get_current_target(CMD_CTX); + if (CMD_ARGC == 0) + return CALL_COMMAND_HANDLER(report_reserved_triggers, target); + + if (CMD_ARGC != 2) + return ERROR_COMMAND_SYNTAX_ERROR; + + riscv_reg_t t; + COMMAND_PARSE_NUMBER(u64, CMD_ARGV[0], t); + + if (riscv_enumerate_triggers(target) != ERROR_OK) + return ERROR_FAIL; + RISCV_INFO(r); + if (r->trigger_count == 0) { + command_print(CMD, "Error: There are no triggers on the target."); + return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; + } + if (t >= r->trigger_count) { + command_print(CMD, "Error: trigger with index %" PRIu64 + " does not exist. There are only %u triggers" + " on the target (with indexes 0 .. %u).", + t, r->trigger_count, r->trigger_count - 1); + return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; + } + if (r->trigger_unique_id[t] != -1) { + command_print(CMD, "Error: trigger with index %" PRIu64 + " is already in use and can not be reserved.", t); + return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; + } + COMMAND_PARSE_ON_OFF(CMD_ARGV[1], r->reserved_triggers[t]); + return ERROR_OK; +} + +COMMAND_HANDLER(handle_riscv_virt2phys_mode) +{ + struct riscv_info *info = riscv_info(get_current_target(CMD_CTX)); + if (CMD_ARGC == 0) { + riscv_virt2phys_mode_t mode = info->virt2phys_mode; + command_print(CMD, "%s", riscv_virt2phys_mode_to_str(mode)); + return ERROR_OK; + } + + if (CMD_ARGC != 1) + return ERROR_COMMAND_SYNTAX_ERROR; + + // TODO: add auto mode to allow OpenOCD choose translation mode + if (!strcmp(CMD_ARGV[0], + riscv_virt2phys_mode_to_str(RISCV_VIRT2PHYS_MODE_SW))) { + info->virt2phys_mode = RISCV_VIRT2PHYS_MODE_SW; + } else if (!strcmp(CMD_ARGV[0], + riscv_virt2phys_mode_to_str(RISCV_VIRT2PHYS_MODE_HW))) { + info->virt2phys_mode = RISCV_VIRT2PHYS_MODE_HW; + } else if (!strcmp(CMD_ARGV[0], + riscv_virt2phys_mode_to_str(RISCV_VIRT2PHYS_MODE_OFF))) { + info->virt2phys_mode = RISCV_VIRT2PHYS_MODE_OFF; + } else { + command_print(CMD, "Unsupported address translation mode: %s", CMD_ARGV[0]); + return ERROR_COMMAND_ARGUMENT_INVALID; + } + + return ERROR_OK; +} + static const struct command_registration riscv_exec_command_handlers[] = { { .name = "dump_sample_buf", @@ -5064,14 +5621,14 @@ static const struct command_registration riscv_exec_command_handlers[] = { .name = "set_command_timeout_sec", .handler = riscv_set_command_timeout_sec, .mode = COMMAND_ANY, - .usage = "[sec]", + .usage = "sec", .help = "Set the wall-clock timeout (in seconds) for individual commands" }, { .name = "set_reset_timeout_sec", .handler = riscv_set_reset_timeout_sec, .mode = COMMAND_ANY, - .usage = "[sec]", + .usage = "sec", .help = "DEPRECATED. Use 'riscv set_command_timeout_sec' instead." }, { @@ -5083,19 +5640,10 @@ static const struct command_registration riscv_exec_command_handlers[] = { "of priority. Method can be one of: 'progbuf', 'sysbus' or 'abstract'." }, { - .name = "set_enable_virtual", - .handler = riscv_set_enable_virtual, - .mode = COMMAND_ANY, - .usage = "on|off", - .help = "When on, memory accesses are performed on physical or virtual " - "memory depending on the current system configuration. " - "When off (default), all memory accessses are performed on physical memory." - }, - { .name = "expose_csrs", .handler = riscv_set_expose_csrs, .mode = COMMAND_CONFIG, - .usage = "n0[-m0|=name0][,n1[-m1|=name1]]...", + .usage = "n0[-m0|=name0][,n1[-m1|=name1]]...[,n15[-m15|=name15]]", .help = "Configure a list of inclusive ranges for CSRs to expose in " "addition to the standard ones. This must be executed before " "`init`." @@ -5104,7 +5652,7 @@ static const struct command_registration riscv_exec_command_handlers[] = { .name = "expose_custom", .handler = riscv_set_expose_custom, .mode = COMMAND_CONFIG, - .usage = "n0[-m0|=name0][,n1[-m1|=name1]]...", + .usage = "n0[-m0|=name0][,n1[-m1|=name1]]...[,n15[-m15|=name15]]", .help = "Configure a list of inclusive ranges for custom registers to " "expose. custom0 is accessed as abstract register number 0xc000, " "etc. This must be executed before `init`." @@ -5189,25 +5737,21 @@ static const struct command_registration riscv_exec_command_handlers[] = { .name = "set_ir", .handler = riscv_set_ir, .mode = COMMAND_ANY, - .usage = "[idcode|dtmcs|dmi] value", + .usage = "idcode|dtmcs|dmi value", .help = "Set IR value for specified JTAG register." }, { .name = "use_bscan_tunnel", .handler = riscv_use_bscan_tunnel, - .mode = COMMAND_ANY, + .mode = COMMAND_CONFIG, .usage = "value [type]", - .help = "Enable or disable use of a BSCAN tunnel to reach DM. Supply " - "the width of the DM transport TAP's instruction register to " - "enable. Supply a value of 0 to disable. Pass A second argument " - "(optional) to indicate Bscan Tunnel Type {0:(default) NESTED_TAP , " - "1: DATA_REGISTER}" + .help = "Enable or disable use of a BSCAN tunnel to reach DM." }, { .name = "set_bscan_tunnel_ir", .handler = riscv_set_bscan_tunnel_ir, - .mode = COMMAND_ANY, - .usage = "value", + .mode = COMMAND_CONFIG, + .usage = "[value]", .help = "Specify the JTAG TAP IR used to access the bscan tunnel. " "By default it is 0x23 << (ir_length - 6), which map some " "Xilinx FPGA (IR USER4)" @@ -5220,36 +5764,28 @@ static const struct command_registration riscv_exec_command_handlers[] = { .usage = "['off'|'steponly']", }, { - .name = "set_enable_virt2phys", - .handler = riscv_set_enable_virt2phys, - .mode = COMMAND_ANY, - .usage = "on|off", - .help = "When on (default), enable translation from virtual address to " - "physical address." - }, - { .name = "set_ebreakm", .handler = riscv_set_ebreakm, .mode = COMMAND_ANY, .usage = "[on|off]", - .help = "Control dcsr.ebreakm. When off, M-mode ebreak instructions " - "don't trap to OpenOCD. Defaults to on." + .help = "DEPRECATED! use '<target_name> configure -ebreak' or " + "'<target_name> cget -ebreak'" }, { .name = "set_ebreaks", .handler = riscv_set_ebreaks, .mode = COMMAND_ANY, .usage = "[on|off]", - .help = "Control dcsr.ebreaks. When off, S-mode ebreak instructions " - "don't trap to OpenOCD. Defaults to on." + .help = "DEPRECATED! use '<target_name> configure -ebreak' or " + "'<target_name> cget -ebreak'" }, { .name = "set_ebreaku", .handler = riscv_set_ebreaku, .mode = COMMAND_ANY, .usage = "[on|off]", - .help = "Control dcsr.ebreaku. When off, U-mode ebreak instructions " - "don't trap to OpenOCD. Defaults to on." + .help = "DEPRECATED! use '<target_name> configure -ebreak' or " + "'<target_name> cget -ebreak'" }, { .name = "etrigger", @@ -5287,6 +5823,33 @@ static const struct command_registration riscv_exec_command_handlers[] = { .usage = "[('eq'|'napot'|'ge_lt'|'all') ('wp'|'none')]", .help = "Control whether OpenOCD is allowed to use certain RISC-V trigger features for watchpoints." }, + { + .name = "reserve_trigger", + .handler = handle_reserve_trigger, + /* TODO: Move this to COMMAND_ANY */ + .mode = COMMAND_EXEC, + .usage = "[index ('on'|'off')]", + .help = "Controls which RISC-V triggers shall not be touched by OpenOCD.", + }, + { + .name = "virt2phys_mode", + .handler = handle_riscv_virt2phys_mode, + .mode = COMMAND_ANY, + .usage = "['sw'|'hw'|'off']", + .help = "Configure the virtual address translation mode: " + "sw - translate vaddr to paddr by manually traversing page tables, " + "hw - translate vaddr to paddr by hardware, " + "off - no address translation." + }, + { + .name = "autofence", + .handler = riscv_set_autofence, + .mode = COMMAND_ANY, + .usage = "[on|off]", + .help = "When on (default), OpenOCD will automatically execute fence instructions in some situations. " + "When off, users need to take care of memory coherency themselves, for example by using " + "`riscv exec_progbuf` to execute fence or CMO instructions." + }, COMMAND_REGISTRATION_DONE }; @@ -5342,6 +5905,7 @@ struct target_type riscv_target = { .name = "riscv", .target_create = riscv_create_target, + .target_jim_configure = riscv_jim_configure, .init_target = riscv_init_target, .deinit_target = riscv_deinit_target, .examine = riscv_examine, @@ -5403,15 +5967,17 @@ static void riscv_info_init(struct target *target, struct riscv_info *r) r->xlen = -1; + r->virt2phys_mode = RISCV_VIRT2PHYS_MODE_SW; + r->isrmask_mode = RISCV_ISRMASK_OFF; r->mem_access_methods[0] = RISCV_MEM_ACCESS_PROGBUF; r->mem_access_methods[1] = RISCV_MEM_ACCESS_SYSBUS; r->mem_access_methods[2] = RISCV_MEM_ACCESS_ABSTRACT; - r->mem_access_progbuf_warn = true; - r->mem_access_sysbus_warn = true; - r->mem_access_abstract_warn = true; + r->num_enabled_mem_access_methods = RISCV_MEM_ACCESS_MAX_METHODS_NUM; + for (size_t i = 0; i < RISCV_MEM_ACCESS_MAX_METHODS_NUM; ++i) + r->mem_access_warn[i] = true; INIT_LIST_HEAD(&r->expose_csr); INIT_LIST_HEAD(&r->expose_custom); @@ -5419,13 +5985,11 @@ static void riscv_info_init(struct target *target, struct riscv_info *r) r->vsew64_supported = YNM_MAYBE; - r->riscv_ebreakm = true; - r->riscv_ebreaks = true; - r->riscv_ebreaku = true; - r->wp_allow_equality_match_trigger = true; r->wp_allow_ge_lt_trigger = true; r->wp_allow_napot_trigger = true; + + r->autofence = true; } static int riscv_resume_go_all_harts(struct target *target) @@ -5439,55 +6003,38 @@ static int riscv_resume_go_all_harts(struct target *target) } else { LOG_TARGET_DEBUG(target, "Hart requested resume, but was already resumed."); } - - riscv_invalidate_register_cache(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) @@ -5512,7 +6059,7 @@ static int riscv_step_rtos_hart(struct target *target) bool riscv_supports_extension(const struct target *target, char letter) { RISCV_INFO(r); - unsigned num; + unsigned int num; if (letter >= 'a' && letter <= 'z') num = letter - 'a'; else if (letter >= 'A' && letter <= 'Z') @@ -5522,7 +6069,7 @@ bool riscv_supports_extension(const struct target *target, char letter) return r->misa & BIT(num); } -unsigned riscv_xlen(const struct target *target) +unsigned int riscv_xlen(const struct target *target) { RISCV_INFO(r); return r->xlen; @@ -5534,17 +6081,6 @@ unsigned int riscv_vlenb(const struct target *target) return r->vlenb; } -static void riscv_invalidate_register_cache(struct target *target) -{ - /* Do not invalidate the register cache if it is not yet set up - * (e.g. when the target failed to get examined). */ - if (!target->reg_cache) - return; - - LOG_TARGET_DEBUG(target, "Invalidating register cache."); - register_cache_invalidate(target->reg_cache); -} - int riscv_get_hart_state(struct target *target, enum riscv_hart_state *state) { RISCV_INFO(r); @@ -5562,17 +6098,16 @@ static enum riscv_halt_reason riscv_halt_reason(struct target *target) return r->halt_reason(target); } -size_t riscv_progbuf_size(struct target *target) +unsigned int riscv_progbuf_size(struct target *target) { RISCV_INFO(r); - return r->progbuf_size; + return r->get_progbufsize(target); } -int riscv_write_progbuf(struct target *target, int index, riscv_insn_t insn) +int riscv_write_progbuf(struct target *target, unsigned int index, riscv_insn_t insn) { RISCV_INFO(r); - r->write_progbuf(target, index, insn); - return ERROR_OK; + return r->write_progbuf(target, index, insn); } riscv_insn_t riscv_read_progbuf(struct target *target, int index) @@ -5587,28 +6122,28 @@ int riscv_execute_progbuf(struct target *target, uint32_t *cmderr) return r->execute_progbuf(target, cmderr); } -void riscv_fill_dm_write(struct target *target, char *buf, uint64_t a, uint32_t d) +void riscv_fill_dmi_write(const struct target *target, uint8_t *buf, uint32_t a, uint32_t d) { RISCV_INFO(r); - r->fill_dm_write(target, buf, a, d); + r->fill_dmi_write(target, buf, a, d); } -void riscv_fill_dm_read(struct target *target, char *buf, uint64_t a) +void riscv_fill_dmi_read(const struct target *target, uint8_t *buf, uint32_t a) { RISCV_INFO(r); - r->fill_dm_read(target, buf, a); + r->fill_dmi_read(target, buf, a); } -void riscv_fill_dm_nop(struct target *target, char *buf) +void riscv_fill_dm_nop(const struct target *target, uint8_t *buf) { RISCV_INFO(r); r->fill_dm_nop(target, buf); } -int riscv_get_dmi_scan_length(struct target *target) +unsigned int riscv_get_dmi_address_bits(const struct target *target) { RISCV_INFO(r); - return r->get_dmi_scan_length(target); + return r->get_dmi_address_bits(target); } static int check_if_trigger_exists(struct target *target, unsigned int index) @@ -5711,9 +6246,24 @@ int riscv_enumerate_triggers(struct target *target) "Assuming that triggers are not implemented."); r->triggers_enumerated = true; r->trigger_count = 0; + free(r->reserved_triggers); + r->reserved_triggers = NULL; return ERROR_OK; } + /* Obtaining tinfo.version value once. + * No need to enumerate per-trigger. + * See https://github.com/riscv/riscv-debug-spec/pull/1081. + */ + riscv_reg_t tinfo; + if (riscv_reg_get(target, &tinfo, GDB_REGNO_TINFO) == ERROR_OK) { + r->tinfo_version = get_field(tinfo, CSR_TINFO_VERSION); + LOG_TARGET_DEBUG(target, "Trigger tinfo.version = %d.", r->tinfo_version); + } else { + r->tinfo_version = RISCV_TINFO_VERSION_UNKNOWN; + LOG_TARGET_DEBUG(target, "Trigger tinfo.version is unknown."); + } + unsigned int t = 0; for (; t < ARRAY_SIZE(r->trigger_tinfo); ++t) { result = check_if_trigger_exists(target, t); @@ -5745,14 +6295,16 @@ int riscv_enumerate_triggers(struct target *target) r->triggers_enumerated = true; r->trigger_count = t; LOG_TARGET_INFO(target, "Found %d triggers", r->trigger_count); + free(r->reserved_triggers); + r->reserved_triggers = calloc(t, sizeof(*r->reserved_triggers)); create_wp_trigger_cache(target); return ERROR_OK; } -void riscv_add_bscan_tunneled_scan(struct target *target, const struct scan_field *field, +void riscv_add_bscan_tunneled_scan(struct jtag_tap *tap, const struct scan_field *field, riscv_bscan_tunneled_scan_context_t *ctxt) { - jtag_add_ir_scan(target->tap, &select_user4, TAP_IDLE); + jtag_add_ir_scan(tap, &select_user4, TAP_IDLE); memset(ctxt->tunneled_dr, 0, sizeof(ctxt->tunneled_dr)); if (bscan_tunnel_type == BSCAN_TUNNEL_DATA_REGISTER) { @@ -5785,5 +6337,5 @@ void riscv_add_bscan_tunneled_scan(struct target *target, const struct scan_fiel ctxt->tunneled_dr[3].num_bits = 3; ctxt->tunneled_dr[3].out_value = bscan_zero; } - jtag_add_dr_scan(target->tap, ARRAY_SIZE(ctxt->tunneled_dr), ctxt->tunneled_dr, TAP_IDLE); + jtag_add_dr_scan(tap, ARRAY_SIZE(ctxt->tunneled_dr), ctxt->tunneled_dr, TAP_IDLE); } diff --git a/src/target/riscv/riscv.h b/src/target/riscv/riscv.h index 5b75bf6..082445e 100644 --- a/src/target/riscv/riscv.h +++ b/src/target/riscv/riscv.h @@ -1,7 +1,7 @@ /* SPDX-License-Identifier: GPL-2.0-or-later */ -#ifndef RISCV_H -#define RISCV_H +#ifndef OPENOCD_TARGET_RISCV_RISCV_H +#define OPENOCD_TARGET_RISCV_RISCV_H struct riscv_program; @@ -29,11 +29,12 @@ struct riscv_program; #define RISCV_HGATP_MODE(xlen) ((xlen) == 32 ? HGATP32_MODE : HGATP64_MODE) #define RISCV_HGATP_PPN(xlen) ((xlen) == 32 ? HGATP32_PPN : HGATP64_PPN) #define RISCV_PGSHIFT 12 +#define RISCV_PGSIZE BIT(RISCV_PGSHIFT) +#define RISCV_PGBASE(addr) ((addr) & ~(RISCV_PGSIZE - 1)) +#define RISCV_PGOFFSET(addr) ((addr) & (RISCV_PGSIZE - 1)) #define PG_MAX_LEVEL 5 -#define RISCV_NUM_MEM_ACCESS_METHODS 3 - #define RISCV_BATCH_ALLOC_SIZE 128 extern struct target_type riscv011_target; @@ -52,12 +53,20 @@ typedef enum { YNM_NO } yes_no_maybe_t; -enum riscv_mem_access_method { - RISCV_MEM_ACCESS_UNSPECIFIED, +typedef enum riscv_mem_access_method { RISCV_MEM_ACCESS_PROGBUF, RISCV_MEM_ACCESS_SYSBUS, - RISCV_MEM_ACCESS_ABSTRACT -}; + RISCV_MEM_ACCESS_ABSTRACT, + RISCV_MEM_ACCESS_MAX_METHODS_NUM +} riscv_mem_access_method_t; + +typedef enum riscv_virt2phys_mode { + RISCV_VIRT2PHYS_MODE_HW, + RISCV_VIRT2PHYS_MODE_SW, + RISCV_VIRT2PHYS_MODE_OFF +} riscv_virt2phys_mode_t; + +const char *riscv_virt2phys_mode_to_str(riscv_virt2phys_mode_t mode); enum riscv_halt_reason { RISCV_HALT_INTERRUPT, @@ -114,12 +123,48 @@ typedef struct { } range_list_t; #define DTM_DTMCS_VERSION_UNKNOWN ((unsigned int)-1) +#define RISCV_TINFO_VERSION_UNKNOWN (-1) + +#define RISCV013_DTMCS_ABITS_MIN 7 +#define RISCV013_DTMCS_ABITS_MAX 32 struct reg_name_table { unsigned int num_entries; char **reg_names; }; +typedef struct riscv_mem_access_args { + target_addr_t address; + + const uint8_t *write_buffer; + uint8_t *read_buffer; + + uint32_t size; + uint32_t count; + uint32_t increment; +} riscv_mem_access_args_t; + +static inline bool +riscv_mem_access_is_valid(const riscv_mem_access_args_t args) +{ + return !args.read_buffer != !args.write_buffer; +} + +static inline bool +riscv_mem_access_is_read(const riscv_mem_access_args_t args) +{ + assert(riscv_mem_access_is_valid(args)); + return !args.write_buffer && args.read_buffer; +} + +static inline bool +riscv_mem_access_is_write(const riscv_mem_access_args_t args) +{ + assert(riscv_mem_access_is_valid(args)); + return !args.read_buffer && args.write_buffer; +} + + struct riscv_info { unsigned int common_magic; @@ -133,15 +178,14 @@ struct riscv_info { /* It's possible that each core has a different supported ISA set. */ int xlen; + /* TODO: use the value from the register cache instead. */ riscv_reg_t misa; - /* Cached value of vlenb. 0 indicates there is no vector support. + /* TODO: use the value from the register cache instead. + * Cached value of vlenb. 0 indicates there is no vector support. * Note that you can have vector support without misa.V set, because * Zve* extensions implement vector registers without setting misa.V. */ unsigned int vlenb; - bool mtopi_readable; - bool mtopei_readable; - /* The number of triggers per hart. */ unsigned int trigger_count; @@ -154,6 +198,17 @@ struct riscv_info { /* record the tinfo of each trigger */ unsigned int trigger_tinfo[RISCV_MAX_TRIGGERS]; + /* Version of the implemented Sdtrig extension */ + int tinfo_version; + + /* Record if single-step is needed prior to resuming + * from a software breakpoint or trigger. + * Single-step is needed if the instruction that + * caused the halt was not retired. That is, + * when we halted "before" that instruction. + */ + bool need_single_step; + /* For each physical trigger contains: * -1: the hwbp is available * -4: The trigger is used by the itrigger command @@ -167,11 +222,8 @@ struct riscv_info { * most recent halt was not caused by a trigger, then this is -1. */ int64_t trigger_hit; - /* The number of entries in the program buffer. */ - int progbuf_size; - - /* This hart contains an implicit ebreak at the end of the program buffer. */ - bool impebreak; + /* The configured approach to translate virtual addresses to physical */ + riscv_virt2phys_mode_t virt2phys_mode; bool triggers_enumerated; @@ -187,6 +239,7 @@ struct riscv_info { /* Used by riscv_openocd_poll(). */ bool halted_needs_event_callback; enum target_event halted_callback_event; + unsigned int halt_group_repoll_count; enum riscv_isrmasking_mode isrmask_mode; @@ -225,10 +278,10 @@ struct riscv_info { riscv_insn_t (*read_progbuf)(struct target *target, unsigned int index); int (*execute_progbuf)(struct target *target, uint32_t *cmderr); int (*invalidate_cached_progbuf)(struct target *target); - int (*get_dmi_scan_length)(struct target *target); - void (*fill_dm_write)(struct target *target, char *buf, uint64_t a, uint32_t d); - void (*fill_dm_read)(struct target *target, char *buf, uint64_t a); - void (*fill_dm_nop)(struct target *target, char *buf); + unsigned int (*get_dmi_address_bits)(const struct target *target); + void (*fill_dmi_write)(const struct target *target, uint8_t *buf, uint32_t a, uint32_t d); + void (*fill_dmi_read)(const struct target *target, uint8_t *buf, uint32_t a); + void (*fill_dm_nop)(const struct target *target, uint8_t *buf); int (*authdata_read)(struct target *target, uint32_t *value, unsigned int index); int (*authdata_write)(struct target *target, uint32_t value, unsigned int index); @@ -236,6 +289,9 @@ struct riscv_info { int (*dmi_read)(struct target *target, uint32_t *value, uint32_t address); int (*dmi_write)(struct target *target, uint32_t address, uint32_t value); + bool (*get_impebreak)(const struct target *target); + unsigned int (*get_progbufsize)(const struct target *target); + /* Get the DMI address of target's DM's register. * The function should return the passed address * if the target is not assigned a DM yet. @@ -247,10 +303,9 @@ struct riscv_info { riscv_sample_config_t *config, int64_t until_ms); - int (*read_memory)(struct target *target, target_addr_t address, - uint32_t size, uint32_t count, uint8_t *buffer, uint32_t increment); + int (*access_memory)(struct target *target, const riscv_mem_access_args_t args); - unsigned (*data_bits)(struct target *target); + unsigned int (*data_bits)(struct target *target); COMMAND_HELPER((*print_info), struct target *target); @@ -272,18 +327,16 @@ struct riscv_info { struct reg_data_type_union vector_union; struct reg_data_type type_vector; - /* Set when trigger registers are changed by the user. This indicates we need - * to beware that we may hit a trigger that we didn't realize had been set. */ - bool manual_hwbp_set; + bool *reserved_triggers; /* Memory access methods to use, ordered by priority, highest to lowest. */ - int mem_access_methods[RISCV_NUM_MEM_ACCESS_METHODS]; + riscv_mem_access_method_t mem_access_methods[RISCV_MEM_ACCESS_MAX_METHODS_NUM]; + + unsigned int num_enabled_mem_access_methods; /* Different memory regions may need different methods but single configuration is applied * for all. Following flags are used to warn only once about failing memory access method. */ - bool mem_access_progbuf_warn; - bool mem_access_sysbus_warn; - bool mem_access_abstract_warn; + bool mem_access_warn[RISCV_MEM_ACCESS_MAX_METHODS_NUM]; /* In addition to the ones in the standard spec, we'll also expose additional * CSRs in this list. */ @@ -307,15 +360,33 @@ struct riscv_info { bool range_trigger_fallback_encountered; - bool riscv_ebreakm; - bool riscv_ebreaks; - bool riscv_ebreaku; - bool wp_allow_equality_match_trigger; bool wp_allow_napot_trigger; bool wp_allow_ge_lt_trigger; + + bool autofence; +}; + +enum riscv_priv_mode { + RISCV_MODE_M, + RISCV_MODE_S, + RISCV_MODE_U, + RISCV_MODE_VS, + RISCV_MODE_VU, + N_RISCV_MODE }; +struct riscv_private_config { + bool dcsr_ebreak_fields[N_RISCV_MODE]; +}; + +static inline struct riscv_private_config +*riscv_private_config(const struct target *target) +{ + assert(target->private_config); + return target->private_config; +} + COMMAND_HELPER(riscv_print_info_line, const char *section, const char *key, unsigned int value); @@ -327,22 +398,23 @@ typedef struct { typedef struct { const char *name; int level; - unsigned va_bits; + unsigned int va_bits; /* log2(PTESIZE) */ - unsigned pte_shift; - unsigned vpn_shift[PG_MAX_LEVEL]; - unsigned vpn_mask[PG_MAX_LEVEL]; - unsigned pte_ppn_shift[PG_MAX_LEVEL]; - unsigned pte_ppn_mask[PG_MAX_LEVEL]; - unsigned pa_ppn_shift[PG_MAX_LEVEL]; - unsigned pa_ppn_mask[PG_MAX_LEVEL]; + unsigned int pte_shift; + unsigned int vpn_shift[PG_MAX_LEVEL]; + unsigned int vpn_mask[PG_MAX_LEVEL]; + unsigned int pte_ppn_shift[PG_MAX_LEVEL]; + unsigned int pte_ppn_mask[PG_MAX_LEVEL]; + unsigned int pa_ppn_shift[PG_MAX_LEVEL]; + unsigned int pa_ppn_mask[PG_MAX_LEVEL]; } virt2phys_info_t; +bool riscv_virt2phys_mode_is_hw(const struct target *target); +bool riscv_virt2phys_mode_is_sw(const struct target *target); + /* Wall-clock timeout for a command/access. Settable via RISC-V Target commands.*/ int riscv_get_command_timeout_sec(void); -extern bool riscv_enable_virtual; - /* Everything needs the RISC-V specific info structure, so here's a nice macro * that provides that. */ static inline struct riscv_info *riscv_info(const struct target *target) __attribute__((unused)); @@ -362,13 +434,14 @@ extern struct scan_field select_dtmcontrol; extern struct scan_field select_dbus; extern struct scan_field select_idcode; +int dtmcs_scan(struct jtag_tap *tap, uint32_t out, uint32_t *in_ptr); + extern struct scan_field *bscan_tunneled_select_dmi; extern uint32_t bscan_tunneled_select_dmi_num_fields; typedef enum { BSCAN_TUNNEL_NESTED_TAP, BSCAN_TUNNEL_DATA_REGISTER } bscan_tunnel_type_t; -extern int bscan_tunnel_ir_width; +extern uint8_t bscan_tunnel_ir_width; -int dtmcontrol_scan_via_bscan(struct target *target, uint32_t out, uint32_t *in_ptr); -void select_dmi_via_bscan(struct target *target); +void select_dmi_via_bscan(struct jtag_tap *tap); /*** OpenOCD Interface */ int riscv_openocd_poll(struct target *target); @@ -377,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 ***/ @@ -387,7 +460,7 @@ int riscv_openocd_step( bool riscv_supports_extension(const struct target *target, char letter); /* Returns XLEN for the given (or current) hart. */ -unsigned riscv_xlen(const struct target *target); +unsigned int riscv_xlen(const struct target *target); /* Returns VLENB for the given (or current) hart. */ unsigned int riscv_vlenb(const struct target *target); @@ -401,16 +474,16 @@ int riscv_get_hart_state(struct target *target, enum riscv_hart_state *state); /* These helper functions let the generic program interface get target-specific * information. */ -size_t riscv_progbuf_size(struct target *target); +unsigned int riscv_progbuf_size(struct target *target); riscv_insn_t riscv_read_progbuf(struct target *target, int index); -int riscv_write_progbuf(struct target *target, int index, riscv_insn_t insn); +int riscv_write_progbuf(struct target *target, unsigned int index, riscv_insn_t insn); int riscv_execute_progbuf(struct target *target, uint32_t *cmderr); -void riscv_fill_dm_nop(struct target *target, char *buf); -void riscv_fill_dm_write(struct target *target, char *buf, uint64_t a, uint32_t d); -void riscv_fill_dm_read(struct target *target, char *buf, uint64_t a); -int riscv_get_dmi_scan_length(struct target *target); +void riscv_fill_dm_nop(const struct target *target, uint8_t *buf); +void riscv_fill_dmi_write(const struct target *target, uint8_t *buf, uint32_t a, uint32_t d); +void riscv_fill_dmi_read(const struct target *target, uint8_t *buf, uint32_t a); +unsigned int riscv_get_dmi_address_bits(const struct target *target); uint32_t riscv_get_dmi_address(const struct target *target, uint32_t dm_address); @@ -424,13 +497,10 @@ void riscv_semihosting_init(struct target *target); enum semihosting_result riscv_semihosting(struct target *target, int *retval); -void riscv_add_bscan_tunneled_scan(struct target *target, const struct scan_field *field, +void riscv_add_bscan_tunneled_scan(struct jtag_tap *tap, const struct scan_field *field, riscv_bscan_tunneled_scan_context_t *ctxt); 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 +#endif /* OPENOCD_TARGET_RISCV_RISCV_H */ diff --git a/src/target/riscv/riscv_reg.c b/src/target/riscv/riscv_reg.c index 6cf67dd..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"); @@ -346,22 +346,11 @@ static bool vlenb_exists(const struct target *target) return riscv_vlenb(target) != 0; } -static bool mtopi_exists(const struct target *target) +static bool reg_exists(const struct target *target, uint32_t regno) { - RISCV_INFO(info) - /* TODO: The naming is quite unfortunate here. `mtopi_readable` refers - * to how the fact that `mtopi` exists was deduced during examine. - */ - return info->mtopi_readable; -} - -static bool mtopei_exists(const struct target *target) -{ - RISCV_INFO(info) - /* TODO: The naming is quite unfortunate here. `mtopei_readable` refers - * to how the fact that `mtopei` exists was deduced during examine. - */ - return info->mtopei_readable; + const struct reg * const reg = riscv_reg_impl_cache_entry(target, regno); + assert(riscv_reg_impl_is_initialized(reg)); + return reg->exist; } static bool is_known_standard_csr(unsigned int csr_num) @@ -376,8 +365,19 @@ static bool is_known_standard_csr(unsigned int csr_num) return is_csr_in_buf[csr_num]; } -static bool gdb_regno_exist(const struct target *target, uint32_t regno) +bool riscv_reg_impl_gdb_regno_exist(const struct target *target, uint32_t regno) { + switch (regno) { + case GDB_REGNO_VLENB: + case GDB_REGNO_MTOPI: + case GDB_REGNO_MTOPEI: + assert(false + && "Existence of other registers is determined " + "depending on existence of these ones, so " + "whether these register exist or not should be " + "set explicitly."); + }; + if (regno <= GDB_REGNO_XPR15 || regno == GDB_REGNO_PC || regno == GDB_REGNO_PRIV) @@ -403,7 +403,6 @@ static bool gdb_regno_exist(const struct target *target, uint32_t regno) case CSR_VL: case CSR_VCSR: case CSR_VTYPE: - case CSR_VLENB: return vlenb_exists(target); case CSR_SCOUNTEREN: case CSR_SSTATUS: @@ -498,25 +497,25 @@ static bool gdb_regno_exist(const struct target *target, uint32_t regno) case CSR_MVIP: case CSR_MIEH: case CSR_MIPH: - return mtopi_exists(target); + return reg_exists(target, GDB_REGNO_MTOPI); case CSR_MIDELEGH: case CSR_MVIENH: case CSR_MVIPH: - return mtopi_exists(target) && + return reg_exists(target, GDB_REGNO_MTOPI) && riscv_xlen(target) == 32 && riscv_supports_extension(target, 'S'); /* Interrupts S-Mode CSRs. */ case CSR_SISELECT: case CSR_SIREG: case CSR_STOPI: - return mtopi_exists(target) && + return reg_exists(target, GDB_REGNO_MTOPI) && riscv_supports_extension(target, 'S'); case CSR_STOPEI: - return mtopei_exists(target) && + return reg_exists(target, GDB_REGNO_MTOPEI) && riscv_supports_extension(target, 'S'); case CSR_SIEH: case CSR_SIPH: - return mtopi_exists(target) && + return reg_exists(target, GDB_REGNO_MTOPI) && riscv_xlen(target) == 32 && riscv_supports_extension(target, 'S'); /* Interrupts Hypervisor and VS CSRs. */ @@ -527,10 +526,10 @@ static bool gdb_regno_exist(const struct target *target, uint32_t regno) case CSR_VSISELECT: case CSR_VSIREG: case CSR_VSTOPI: - return mtopi_exists(target) && + return reg_exists(target, GDB_REGNO_MTOPI) && riscv_supports_extension(target, 'H'); case CSR_VSTOPEI: - return mtopei_exists(target) && + return reg_exists(target, GDB_REGNO_MTOPEI) && riscv_supports_extension(target, 'H'); case CSR_HIDELEGH: case CSR_HVIENH: @@ -539,7 +538,7 @@ static bool gdb_regno_exist(const struct target *target, uint32_t regno) case CSR_HVIPRIO2H: case CSR_VSIEH: case CSR_VSIPH: - return mtopi_exists(target) && + return reg_exists(target, GDB_REGNO_MTOPI) && riscv_xlen(target) == 32 && riscv_supports_extension(target, 'H'); } @@ -599,14 +598,15 @@ static int resize_reg(const struct target *target, uint32_t regno, bool exist, return ERROR_OK; } -static int set_reg_exist(const struct target *target, uint32_t regno, bool exist) +int riscv_reg_impl_set_exist(const struct target *target, uint32_t regno, bool exist) { const struct reg *reg = riscv_reg_impl_cache_entry(target, regno); assert(riscv_reg_impl_is_initialized(reg)); return resize_reg(target, regno, exist, reg->size); } -int riscv_reg_impl_init_one(struct target *target, uint32_t regno, const struct reg_arch_type *reg_type) +int riscv_reg_impl_init_cache_entry(struct target *target, uint32_t regno, + bool exist, const struct reg_arch_type *reg_type) { struct reg * const reg = riscv_reg_impl_cache_entry(target, regno); if (riscv_reg_impl_is_initialized(reg)) @@ -634,8 +634,7 @@ int riscv_reg_impl_init_one(struct target *target, uint32_t regno, const struct reg_arch_info->target = target; reg_arch_info->custom_number = gdb_regno_custom_number(target, regno); } - return resize_reg(target, regno, gdb_regno_exist(target, regno), - gdb_regno_size(target, regno)); + return resize_reg(target, regno, exist, gdb_regno_size(target, regno)); } static int init_custom_register_names(struct list_head *expose_custom, @@ -725,7 +724,7 @@ int riscv_reg_impl_expose_csrs(const struct target *target) csr_number); continue; } - if (set_reg_exist(target, regno, /*exist*/ true) != ERROR_OK) + if (riscv_reg_impl_set_exist(target, regno, /*exist*/ true) != ERROR_OK) return ERROR_FAIL; LOG_TARGET_DEBUG(target, "Exposing additional CSR %d (name=%s)", csr_number, reg->name); @@ -746,7 +745,7 @@ void riscv_reg_impl_hide_csrs(const struct target *target) struct reg * const reg = riscv_reg_impl_cache_entry(target, regno); const unsigned int csr_number = regno - GDB_REGNO_CSR0; if (!reg->exist) { - LOG_TARGET_WARNING(target, + LOG_TARGET_DEBUG(target, "Not hiding CSR %d: register does not exist.", csr_number); continue; @@ -834,15 +833,8 @@ static int riscv_set_or_write_register(struct target *target, return riscv_set_or_write_register(target, GDB_REGNO_DCSR, dcsr, write_through); } - if (!target->reg_cache) { - assert(!target_was_examined(target)); - LOG_TARGET_DEBUG(target, - "No cache, writing to target: %s <- 0x%" PRIx64, - riscv_reg_gdb_regno_name(target, regid), value); - return riscv013_set_register(target, regid, value); - } - struct reg *reg = riscv_reg_impl_cache_entry(target, regid); + assert(riscv_reg_impl_is_initialized(reg)); if (!reg->exist) { LOG_TARGET_DEBUG(target, "Register %s does not exist.", reg->name); @@ -885,6 +877,34 @@ static int riscv_set_or_write_register(struct target *target, return ERROR_OK; } +bool riscv_reg_cache_any_dirty(const struct target *target, int log_level) +{ + bool any_dirty = false; + + if (!target->reg_cache) + return any_dirty; + + for (unsigned int number = 0; number < target->reg_cache->num_regs; ++number) { + const struct reg * const reg = riscv_reg_impl_cache_entry(target, number); + assert(riscv_reg_impl_is_initialized(reg)); + if (reg->dirty) { + log_printf_lf(log_level, __FILE__, __LINE__, __func__, + "[%s] Register %s is dirty!", target_name(target), reg->name); + any_dirty = true; + } + } + return any_dirty; +} + +void riscv_reg_cache_invalidate_all(struct target *target) +{ + if (!target->reg_cache) + return; + + LOG_TARGET_DEBUG(target, "Invalidating register cache."); + register_cache_invalidate(target->reg_cache); +} + /** * This function is used to change the value of a register. The new value may * be cached, and may not be written until the hart is resumed. @@ -935,21 +955,15 @@ int riscv_reg_get(struct target *target, riscv_reg_t *value, RISCV_INFO(r); assert(r); if (r->dtm_version == DTM_DTMCS_VERSION_0_11) - return riscv013_get_register(target, value, regid); + return riscv011_get_register(target, value, regid); keep_alive(); if (regid == GDB_REGNO_PC) return riscv_reg_get(target, value, GDB_REGNO_DPC); - if (!target->reg_cache) { - assert(!target_was_examined(target)); - LOG_TARGET_DEBUG(target, "No cache, reading %s from target", - riscv_reg_gdb_regno_name(target, regid)); - return riscv013_get_register(target, value, regid); - } - struct reg *reg = riscv_reg_impl_cache_entry(target, regid); + assert(riscv_reg_impl_is_initialized(reg)); if (!reg->exist) { LOG_TARGET_DEBUG(target, "Register %s does not exist.", reg->name); return ERROR_FAIL; diff --git a/src/target/riscv/riscv_reg.h b/src/target/riscv/riscv_reg.h index 264addd..dc87c55 100644 --- a/src/target/riscv/riscv_reg.h +++ b/src/target/riscv/riscv_reg.h @@ -22,6 +22,17 @@ void riscv_reg_free_all(struct target *target); /** Write all dirty registers to the target. */ int riscv_reg_flush_all(struct target *target); /** + * Check whether there are any dirty registers in the OpenOCD's register cache. + * In addition, all dirty registers will be reported to the log using the + * supplied "log_level". + */ +bool riscv_reg_cache_any_dirty(const struct target *target, int log_level); +/** + * Invalidate all registers - forget their cached register values. + * WARNING: If a register was dirty, its walue will be silently lost! + */ +void riscv_reg_cache_invalidate_all(struct target *target); +/** * Set the register value. For cacheable registers, only the cache is updated * (write-back mode). */ diff --git a/src/target/riscv/riscv_reg_impl.h b/src/target/riscv/riscv_reg_impl.h index 906a5b6..a860202 100644 --- a/src/target/riscv/riscv_reg_impl.h +++ b/src/target/riscv/riscv_reg_impl.h @@ -13,7 +13,7 @@ * This file describes the helpers to use during register cache initialization * of a RISC-V target. Each cache entry proceedes through the following stages: * - not allocated before `riscv_reg_impl_init_cache()` - * - not initialized before the call to `riscv_reg_impl_init_one()` with appropriate regno. + * - not initialized before the call to `riscv_reg_impl_init_cache_entry()` with appropriate regno. * - initialized until `riscv_reg_free_all()` is called. */ static inline bool riscv_reg_impl_is_initialized(const struct reg *reg) @@ -37,8 +37,18 @@ static inline bool riscv_reg_impl_is_initialized(const struct reg *reg) int riscv_reg_impl_init_cache(struct target *target); /** Initialize register. */ -int riscv_reg_impl_init_one(struct target *target, uint32_t regno, - const struct reg_arch_type *reg_type); +int riscv_reg_impl_init_cache_entry(struct target *target, uint32_t regno, + bool exist, const struct reg_arch_type *reg_type); + +/** + * For most registers, returns whether they exist or not. + * For some registers the "exist" bit should be set explicitly. + */ +bool riscv_reg_impl_gdb_regno_exist(const struct target *target, uint32_t regno); + +/** Mark register as existing or not. */ +int riscv_reg_impl_set_exist(const struct target *target, + uint32_t regno, bool exist); /** Return the entry in the register cache of the target. */ struct reg *riscv_reg_impl_cache_entry(const struct target *target, @@ -194,9 +204,7 @@ static inline bool riscv_reg_impl_gdb_regno_cacheable(enum gdb_regno regno, case GDB_REGNO_MISA: case GDB_REGNO_DCSR: case GDB_REGNO_DSCRATCH0: - case GDB_REGNO_MSTATUS: case GDB_REGNO_MEPC: - case GDB_REGNO_MCAUSE: case GDB_REGNO_SATP: /* * WARL registers might not contain the value we just wrote, but diff --git a/src/target/riscv/riscv_semihosting.c b/src/target/riscv/riscv_semihosting.c index 0f4f6b5..98ccf41 100644 --- a/src/target/riscv/riscv_semihosting.c +++ b/src/target/riscv/riscv_semihosting.c @@ -37,6 +37,57 @@ static int riscv_semihosting_setup(struct target *target, int enable); static int riscv_semihosting_post_result(struct target *target); +static int riscv_semihosting_detect_magic_sequence(struct target *target, + const target_addr_t pc, bool *sequence_found) +{ + assert(sequence_found); + + /* The semihosting "magic" sequence must be the exact three instructions + * listed below. All these instructions, including the ebreak, must be + * uncompressed (4 bytes long). */ + const uint32_t magic[] = { + 0x01f01013, /* slli zero,zero,0x1f */ + 0x00100073, /* ebreak */ + 0x40705013 /* srai zero,zero,0x7 */ + }; + + LOG_TARGET_DEBUG(target, "Checking for RISC-V semihosting sequence " + "at PC = 0x%" TARGET_PRIxADDR, pc); + + /* Read three uncompressed instructions: + * The previous, the current one (pointed to by PC) and the next one. */ + const target_addr_t sequence_start_address = pc - 4; + for (int i = 0; i < 3; i++) { + uint8_t buf[4]; + + /* Instruction memories may not support arbitrary read size. + * Use any size that will work. */ + const target_addr_t address = sequence_start_address + (4 * i); + int result = riscv_read_by_any_size(target, address, 4, buf); + if (result != ERROR_OK) { + *sequence_found = false; + return result; + } + + /* RISC-V instruction layout in memory is always little endian, + * regardless of the endianness of the whole system. */ + const uint32_t value = le_to_h_u32(buf); + + LOG_TARGET_DEBUG(target, "compare 0x%08" PRIx32 " from 0x%" PRIx64 " against 0x%08" PRIx32, + value, address, magic[i]); + if (value != magic[i]) { + LOG_TARGET_DEBUG(target, "Not a RISC-V semihosting sequence"); + *sequence_found = false; + return ERROR_OK; + } + } + + LOG_TARGET_DEBUG(target, "RISC-V semihosting sequence found " + "at PC = 0x%" TARGET_PRIxADDR, pc); + *sequence_found = true; + return ERROR_OK; +} + /** * Initialize RISC-V semihosting. Use common ARM code. */ @@ -57,48 +108,47 @@ void riscv_semihosting_init(struct target *target) enum semihosting_result riscv_semihosting(struct target *target, int *retval) { struct semihosting *semihosting = target->semihosting; - if (!semihosting) { - LOG_TARGET_DEBUG(target, " -> NONE (!semihosting)"); - return SEMIHOSTING_NONE; - } - - if (!semihosting->is_active) { - LOG_TARGET_DEBUG(target, " -> NONE (!semihosting->is_active)"); - return SEMIHOSTING_NONE; - } + assert(semihosting); riscv_reg_t pc; int result = riscv_reg_get(target, &pc, GDB_REGNO_PC); - if (result != ERROR_OK) + if (result != ERROR_OK) { + LOG_TARGET_DEBUG(target, "Semihosting outcome: ERROR (failed to read PC)"); return SEMIHOSTING_ERROR; + } - /* - * The instructions that trigger a semihosting call, - * always uncompressed, should look like: - */ - uint32_t magic[] = { - 0x01f01013, /* slli zero,zero,0x1f */ - 0x00100073, /* ebreak */ - 0x40705013 /* srai zero,zero,0x7 */ - }; + bool sequence_found = false; + *retval = riscv_semihosting_detect_magic_sequence(target, pc, &sequence_found); + if (*retval != ERROR_OK) { + LOG_TARGET_DEBUG(target, "Semihosting outcome: ERROR (during magic seq. detection)"); + return SEMIHOSTING_ERROR; + } - /* Read three uncompressed instructions: The previous, the current one (pointed to by PC) and the next one */ - for (int i = 0; i < 3; i++) { - uint8_t buf[4]; - /* Instruction memories may not support arbitrary read size. Use any size that will work. */ - target_addr_t address = (pc - 4) + 4 * i; - *retval = riscv_read_by_any_size(target, address, 4, buf); - if (*retval != ERROR_OK) - return SEMIHOSTING_ERROR; - uint32_t value = target_buffer_get_u32(target, buf); - LOG_TARGET_DEBUG(target, "compare 0x%08x from 0x%" PRIx64 " against 0x%08x", - value, address, magic[i]); - if (value != magic[i]) { - LOG_TARGET_DEBUG(target, " -> NONE (no magic)"); - return SEMIHOSTING_NONE; + if (!semihosting->is_active) { + if (sequence_found) { + // If semihositing is encountered but disabled, provide an additional hint to the user. + LOG_TARGET_WARNING(target, "RISC-V semihosting call encountered in the program " + "but semihosting is disabled!"); + LOG_TARGET_WARNING(target, "The target will remain halted (PC = 0x%" TARGET_PRIxADDR ").", pc); + LOG_TARGET_WARNING(target, "Hint: Restart your debug session and enable semihosting " + "by command 'arm semihosting enable'."); + // TODO: This can be improved: The ebreak halt cause detection and riscv_semihosting() call + // can be added also to "arm semihosting enable", which would allow the user to continue + // without restart of the debug session. } + + LOG_TARGET_DEBUG(target, "Semihosting outcome: NONE (semihosting not enabled)"); + return SEMIHOSTING_NONE; + } + + if (!sequence_found) { + LOG_TARGET_DEBUG(target, "Semihosting outcome: NONE (no magic sequence)"); + return SEMIHOSTING_NONE; } + /* Otherwise we have a semihosting call (and semihosting is enabled). + * Proceed with the handling of semihosting. */ + /* * Perform semihosting call if we are not waiting on a fileio * operation to complete. @@ -111,12 +161,14 @@ enum semihosting_result riscv_semihosting(struct target *target, int *retval) result = riscv_reg_get(target, &r0, GDB_REGNO_A0); if (result != ERROR_OK) { LOG_TARGET_ERROR(target, "Could not read semihosting operation code (register a0)"); + LOG_TARGET_DEBUG(target, "Semihosting outcome: ERROR (failed to read a0)"); return SEMIHOSTING_ERROR; } result = riscv_reg_get(target, &r1, GDB_REGNO_A1); if (result != ERROR_OK) { LOG_TARGET_ERROR(target, "Could not read semihosting operation code (register a1)"); + LOG_TARGET_DEBUG(target, "Semihosting outcome: ERROR (failed to read a1)"); return SEMIHOSTING_ERROR; } @@ -131,11 +183,13 @@ enum semihosting_result riscv_semihosting(struct target *target, int *retval) *retval = semihosting_common(target); if (*retval != ERROR_OK) { LOG_TARGET_ERROR(target, "Failed semihosting operation (0x%02X)", semihosting->op); + LOG_TARGET_DEBUG(target, "Semihosting outcome: ERROR (error during semihosting processing)"); return SEMIHOSTING_ERROR; } } else { /* Unknown operation number, not a semihosting call. */ LOG_TARGET_ERROR(target, "Unknown semihosting operation requested (op = 0x%x)", semihosting->op); + LOG_TARGET_DEBUG(target, "Semihosting outcome: NONE (unknown semihosting opcode)"); return SEMIHOSTING_NONE; } } @@ -150,11 +204,11 @@ enum semihosting_result riscv_semihosting(struct target *target, int *retval) * operation to complete. */ if (semihosting->is_resumable && !semihosting->hit_fileio) { - LOG_TARGET_DEBUG(target, " -> HANDLED"); + LOG_TARGET_DEBUG(target, "Semihosting outcome: HANDLED"); return SEMIHOSTING_HANDLED; } - LOG_TARGET_DEBUG(target, " -> WAITING"); + LOG_TARGET_DEBUG(target, "Semihosting outcome: WAITING"); return SEMIHOSTING_WAITING; } @@ -170,19 +224,16 @@ static int riscv_semihosting_setup(struct target *target, int enable) LOG_TARGET_DEBUG(target, "enable=%d", enable); struct semihosting *semihosting = target->semihosting; - if (semihosting) - semihosting->setup_time = clock(); + assert(semihosting); + semihosting->setup_time = clock(); return ERROR_OK; } static int riscv_semihosting_post_result(struct target *target) { struct semihosting *semihosting = target->semihosting; - if (!semihosting) { - /* If not enabled, silently ignored. */ - return 0; - } + assert(semihosting); LOG_TARGET_DEBUG(target, "Result: 0x%" PRIx64, semihosting->result); riscv_reg_set(target, GDB_REGNO_A0, semihosting->result); diff --git a/src/target/riscv/startup.tcl b/src/target/riscv/startup.tcl new file mode 100644 index 0000000..28e03a4 --- /dev/null +++ b/src/target/riscv/startup.tcl @@ -0,0 +1,55 @@ +# SPDX-License-Identifier: GPL-2.0-or-later + +lappend _telnet_autocomplete_skip "riscv set_enable_virtual" +proc {riscv set_enable_virtual} on_off { + echo {DEPRECATED! use 'riscv virt2phys_mode' not 'riscv set_enable_virtual'} + foreach t [target names] { + if {[$t cget -type] ne "riscv"} { continue } + switch -- [$t riscv virt2phys_mode] { + off - + hw { + switch -- $on_off { + on {$t riscv virt2phys_mode hw} + off {$t riscv virt2phys_mode off} + } + } + sw { + if {$on_off eq "on"} { + error {Can't enable virtual while translation mode is SW} + } + } + } + } + return {} +} + +lappend _telnet_autocomplete_skip "riscv set_enable_virt2phys" +proc {riscv set_enable_virt2phys} on_off { + echo {DEPRECATED! use 'riscv virt2phys_mode' not 'riscv set_enable_virt2phys'} + foreach t [target names] { + if {[$t cget -type] ne "riscv"} { continue } + switch -- [riscv virt2phys_mode] { + off - + sw { + switch -- $on_off { + on {riscv virt2phys_mode sw} + off {riscv virt2phys_mode off} + } + } + hw { + if {$on_off eq "on"} { + error {Can't enable virt2phys while translation mode is HW} + } + } + } + } + return {} +} + +foreach mode {m s u} { + lappend _telnet_autocomplete_skip "riscv set_ebreak$mode" +} + +proc riscv {cmd args} { + tailcall "riscv $cmd" {*}$args +} diff --git a/src/target/semihosting_common.c b/src/target/semihosting_common.c index 1eb1957..ffcd3aa 100644 --- a/src/target/semihosting_common.c +++ b/src/target/semihosting_common.c @@ -92,6 +92,8 @@ static int semihosting_common_fileio_info(struct target *target, struct gdb_fileio_info *fileio_info); static int semihosting_common_fileio_end(struct target *target, int result, int fileio_errno, bool ctrl_c); +static void semihosting_set_field(struct target *target, uint64_t value, size_t index, uint8_t *fields); +static int semihosting_write_fields(struct target *target, size_t number, uint8_t *fields); /** * Initialize common semihosting support. @@ -298,7 +300,12 @@ static inline int semihosting_getchar(struct semihosting *semihosting, int fd) */ static char *semihosting_user_op_params; -const char *semihosting_opcode_to_str(const uint64_t opcode) +/** + * @brief Convert the syscall opcode to a human-readable string + * @param[in] opcode Syscall opcode + * @return String representation of syscall opcode + */ +static const char *semihosting_opcode_to_str(const uint64_t opcode) { switch (opcode) { case SEMIHOSTING_SYS_CLOSE: @@ -1729,8 +1736,7 @@ int semihosting_read_fields(struct target *target, size_t number, /** * Write all fields of a command from buffer to target. */ -int semihosting_write_fields(struct target *target, size_t number, - uint8_t *fields) +static int semihosting_write_fields(struct target *target, size_t number, uint8_t *fields) { struct semihosting *semihosting = target->semihosting; /* Use 4-byte multiples to trigger fast memory access. */ @@ -1754,9 +1760,7 @@ uint64_t semihosting_get_field(struct target *target, size_t index, /** * Store a field in the buffer, considering register size and endianness. */ -void semihosting_set_field(struct target *target, uint64_t value, - size_t index, - uint8_t *fields) +static void semihosting_set_field(struct target *target, uint64_t value, size_t index, uint8_t *fields) { struct semihosting *semihosting = target->semihosting; if (semihosting->word_size_bytes == 8) diff --git a/src/target/semihosting_common.h b/src/target/semihosting_common.h index a1848b4..1821ca4 100644 --- a/src/target/semihosting_common.h +++ b/src/target/semihosting_common.h @@ -188,13 +188,6 @@ struct semihosting { int (*post_result)(struct target *target); }; -/** - * @brief Convert the syscall opcode to a human-readable string - * @param[in] opcode Syscall opcode - * @return String representation of syscall opcode - */ -const char *semihosting_opcode_to_str(uint64_t opcode); - int semihosting_common_init(struct target *target, void *setup, void *post_result); int semihosting_common(struct target *target); @@ -202,13 +195,8 @@ int semihosting_common(struct target *target); /* utility functions which may also be used by semihosting extensions (custom vendor-defined syscalls) */ int semihosting_read_fields(struct target *target, size_t number, uint8_t *fields); -int semihosting_write_fields(struct target *target, size_t number, - uint8_t *fields); uint64_t semihosting_get_field(struct target *target, size_t index, uint8_t *fields); -void semihosting_set_field(struct target *target, uint64_t value, - size_t index, - uint8_t *fields); extern const struct command_registration semihosting_common_handlers[]; diff --git a/src/target/stm8.c b/src/target/stm8.c index 227101b..76482e8 100644 --- a/src/target/stm8.c +++ b/src/target/stm8.c @@ -38,7 +38,7 @@ static int (*adapter_speed)(int speed); extern struct adapter_driver *adapter_driver; static const struct { - unsigned id; + unsigned int id; const char *name; const uint8_t bits; enum reg_type type; @@ -689,15 +689,13 @@ static int stm8_write_flash(struct target *target, enum mem_type type, if (stm8->flash_ncr2) stm8_write_u8(target, stm8->flash_ncr2, ~(PRG + opt)); blocksize = blocksize_param; - } else - if ((bytecnt >= 4) && ((address & 0x3) == 0)) { + } else if ((bytecnt >= 4) && ((address & 0x3) == 0)) { if (stm8->flash_cr2) stm8_write_u8(target, stm8->flash_cr2, WPRG + opt); if (stm8->flash_ncr2) stm8_write_u8(target, stm8->flash_ncr2, ~(WPRG + opt)); blocksize = 4; - } else - if (blocksize != 1) { + } else if (blocksize != 1) { if (stm8->flash_cr2) stm8_write_u8(target, stm8->flash_cr2, opt); if (stm8->flash_ncr2) @@ -982,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; @@ -1006,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, @@ -1292,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); @@ -1307,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; @@ -1552,8 +1550,8 @@ static int stm8_set_watchpoint(struct target *target, } if (watchpoint->length != 1) { - LOG_ERROR("Only watchpoints of length 1 are supported"); - return ERROR_TARGET_UNALIGNED_ACCESS; + LOG_ERROR("Only watchpoints of length 1 are supported"); + return ERROR_TARGET_UNALIGNED_ACCESS; } enum hw_break_type enable = 0; @@ -1791,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 fd9c34f..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, @@ -108,10 +116,10 @@ struct target *all_targets; static struct target_event_callback *target_event_callbacks; static struct target_timer_callback *target_timer_callbacks; static int64_t target_timer_next_event_value; -static LIST_HEAD(target_reset_callback_list); -static LIST_HEAD(target_trace_callback_list); +static OOCD_LIST_HEAD(target_reset_callback_list); +static OOCD_LIST_HEAD(target_trace_callback_list); static const unsigned int polling_interval = TARGET_DEFAULT_POLLING_INTERVAL; -static LIST_HEAD(empty_smp_targets); +static OOCD_LIST_HEAD(empty_smp_targets); enum nvp_assert { NVP_DEASSERT, @@ -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; @@ -1449,14 +1458,14 @@ int target_gdb_fileio_end(struct target *target, int retcode, int fileio_errno, target_addr_t target_address_max(struct target *target) { - unsigned bits = target_address_bits(target); + unsigned int bits = target_address_bits(target); if (sizeof(target_addr_t) * 8 == bits) return (target_addr_t) -1; else return (((target_addr_t) 1) << bits) - 1; } -unsigned target_address_bits(struct target *target) +unsigned int target_address_bits(struct target *target) { if (target->type->address_bits) return target->type->address_bits(target); @@ -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) { @@ -3032,14 +3040,14 @@ COMMAND_HANDLER(handle_reg_command) unsigned int count = 0; while (cache) { - unsigned i; + unsigned int i; command_print(CMD, "===== %s", cache->name); for (i = 0, reg = cache->reg_list; i < cache->num_regs; i++, reg++, count++) { - if (reg->exist == false || reg->hidden) + if (!reg->exist || reg->hidden) continue; /* only print cached values if they are valid */ if (reg->valid) { @@ -3067,13 +3075,13 @@ COMMAND_HANDLER(handle_reg_command) /* access a single register by its ordinal number */ if ((CMD_ARGV[0][0] >= '0') && (CMD_ARGV[0][0] <= '9')) { - unsigned num; + unsigned int num; COMMAND_PARSE_NUMBER(uint, CMD_ARGV[0], num); struct reg_cache *cache = target->reg_cache; unsigned int count = 0; while (cache) { - unsigned i; + unsigned int i; for (i = 0; i < cache->num_regs; i++) { if (count++ == num) { reg = &cache->reg_list[i]; @@ -3125,11 +3133,18 @@ COMMAND_HANDLER(handle_reg_command) /* set register value */ if (CMD_ARGC == 2) { uint8_t *buf = malloc(DIV_ROUND_UP(reg->size, 8)); - if (!buf) + if (!buf) { + LOG_ERROR("Failed to allocate memory"); return ERROR_FAIL; - str_to_buf(CMD_ARGV[1], strlen(CMD_ARGV[1]), buf, reg->size, 0); + } + + int retval = CALL_COMMAND_HANDLER(command_parse_str_to_buf, CMD_ARGV[1], buf, reg->size); + if (retval != ERROR_OK) { + free(buf); + return retval; + } - int retval = reg->type->set(reg, buf); + retval = reg->type->set(reg, buf); if (retval != ERROR_OK) { LOG_ERROR("Could not write to register '%s'", reg->name); } else { @@ -3184,7 +3199,7 @@ COMMAND_HANDLER(handle_wait_halt_command) if (CMD_ARGC > 1) return ERROR_COMMAND_SYNTAX_ERROR; - unsigned ms = DEFAULT_HALT_TIMEOUT; + unsigned int ms = DEFAULT_HALT_TIMEOUT; if (1 == CMD_ARGC) { int retval = parse_uint(CMD_ARGV[0], &ms); if (retval != ERROR_OK) @@ -3247,7 +3262,7 @@ COMMAND_HANDLER(handle_halt_command) return retval; if (CMD_ARGC == 1) { - unsigned wait_local; + unsigned int wait_local; retval = parse_uint(CMD_ARGV[0], &wait_local); if (retval != ERROR_OK) return ERROR_COMMAND_SYNTAX_ERROR; @@ -3290,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; @@ -3302,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) @@ -3327,18 +3342,18 @@ 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, struct target *target, target_addr_t address, unsigned size, - unsigned count, const uint8_t *buffer, bool include_address) + unsigned int count, const uint8_t *buffer, bool include_address) { - const unsigned line_bytecnt = 32; - unsigned line_modulo = line_bytecnt / size; + const unsigned int line_bytecnt = 32; + unsigned int line_modulo = line_bytecnt / size; char output[line_bytecnt * 4 + 1]; - unsigned output_len = 0; + unsigned int output_len = 0; const char *value_fmt; switch (size) { @@ -3399,7 +3414,7 @@ COMMAND_HANDLER(handle_md_command) if (CMD_ARGC < 1) return ERROR_COMMAND_SYNTAX_ERROR; - unsigned size = 0; + unsigned int size = 0; switch (CMD_NAME[2]) { case 'd': size = 8; @@ -3432,7 +3447,7 @@ COMMAND_HANDLER(handle_md_command) target_addr_t address; COMMAND_PARSE_ADDRESS(CMD_ARGV[0], address); - unsigned count = 1; + unsigned int count = 1; if (CMD_ARGC == 2) COMMAND_PARSE_NUMBER(uint, CMD_ARGV[1], count); @@ -3459,22 +3474,22 @@ typedef int (*target_write_fn)(struct target *target, static int target_fill_mem(struct target *target, target_addr_t address, target_write_fn fn, - unsigned data_size, + unsigned int data_size, /* value */ uint64_t b, /* count */ - unsigned c) + unsigned int c) { /* We have to write in reasonably large chunks to be able * to fill large memory areas with any sane speed */ - const unsigned chunk_size = 16384; + const unsigned int chunk_size = 16384; uint8_t *target_buf = malloc(chunk_size * data_size); if (!target_buf) { LOG_ERROR("Out of memory"); return ERROR_FAIL; } - for (unsigned i = 0; i < chunk_size; i++) { + for (unsigned int i = 0; i < chunk_size; i++) { switch (data_size) { case 8: target_buffer_set_u64(target, target_buf + i * data_size, b); @@ -3495,8 +3510,8 @@ static int target_fill_mem(struct target *target, int retval = ERROR_OK; - for (unsigned x = 0; x < c; x += chunk_size) { - unsigned current; + for (unsigned int x = 0; x < c; x += chunk_size) { + unsigned int current; current = c - x; if (current > chunk_size) current = chunk_size; @@ -3533,12 +3548,12 @@ COMMAND_HANDLER(handle_mw_command) uint64_t value; COMMAND_PARSE_NUMBER(u64, CMD_ARGV[1], value); - unsigned count = 1; + unsigned int count = 1; if (CMD_ARGC == 3) COMMAND_PARSE_NUMBER(uint, CMD_ARGV[2], count); struct target *target = get_current_target(CMD_CTX); - unsigned wordsize; + unsigned int wordsize; switch (CMD_NAME[2]) { case 'd': wordsize = 8; @@ -3834,11 +3849,11 @@ static COMMAND_HELPER(handle_verify_image_command_internal, enum verify_mode ver for (t = 0; t < buf_cnt; t++) { if (data[t] != buffer[t]) { command_print(CMD, - "diff %d address 0x%08x. Was 0x%02x instead of 0x%02x", - diffs, - (unsigned)(t + image.sections[i].base_address), - data[t], - buffer[t]); + "diff %d address " TARGET_ADDR_FMT ". Was 0x%02" PRIx8 " instead of 0x%02" PRIx8, + diffs, + t + image.sections[i].base_address, + data[t], + buffer[t]); if (diffs++ >= 127) { command_print(CMD, "More than 128 errors, the rest are not printed."); free(data); @@ -3898,7 +3913,7 @@ static int handle_bp_command_list(struct command_invocation *cmd) while (breakpoint) { if (breakpoint->type == BKPT_SOFT) { char *buf = buf_to_hex_str(breakpoint->orig_instr, - breakpoint->length); + breakpoint->length * 8); command_print(cmd, "Software breakpoint(IVA): addr=" TARGET_ADDR_FMT ", len=0x%x, orig_instr=0x%s", breakpoint->address, breakpoint->length, @@ -3927,7 +3942,7 @@ static int handle_bp_command_list(struct command_invocation *cmd) } static int handle_bp_command_set(struct command_invocation *cmd, - target_addr_t addr, uint32_t asid, uint32_t length, int hw) + target_addr_t addr, uint32_t asid, unsigned int length, int hw) { struct target *target = get_current_target(cmd->ctx); int retval; @@ -4044,7 +4059,7 @@ COMMAND_HANDLER(handle_wp_command) while (watchpoint) { char wp_type = (watchpoint->rw == WPT_READ ? 'r' : (watchpoint->rw == WPT_WRITE ? 'w' : 'a')); command_print(CMD, "address: " TARGET_ADDR_FMT - ", len: 0x%8.8" PRIx32 + ", len: 0x%8.8x" ", r/w/a: %c, value: 0x%8.8" PRIx64 ", mask: 0x%8.8" PRIx64, watchpoint->address, @@ -4186,7 +4201,7 @@ static void write_gmon(uint32_t *samples, uint32_t sample_num, const char *filen uint32_t start_address, uint32_t end_address, struct target *target, uint32_t duration_ms) { uint32_t i; - FILE *f = fopen(filename, "w"); + FILE *f = fopen(filename, "wb"); if (!f) return; write_string(f, "gmon"); @@ -4356,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; @@ -4423,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; } @@ -4458,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; } @@ -4500,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; @@ -4556,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 != NULL); - 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; @@ -4591,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; @@ -4623,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; @@ -4635,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 @@ -4646,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), @@ -4685,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 != NULL); - 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; } } @@ -4749,86 +4740,74 @@ 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; } -static int target_jim_set_reg(Jim_Interp *interp, int argc, - Jim_Obj * const *argv) +COMMAND_HANDLER(handle_set_reg_command) { - if (argc != 2) { - Jim_WrongNumArgs(interp, 1, argv, "dict"); - return JIM_ERR; - } + if (CMD_ARGC != 1) + return ERROR_COMMAND_SYNTAX_ERROR; int tmp; #if JIM_VERSION >= 80 - Jim_Obj **dict = Jim_DictPairs(interp, argv[1], &tmp); + Jim_Obj **dict = Jim_DictPairs(CMD_CTX->interp, CMD_JIMTCL_ARGV[0], &tmp); if (!dict) - return JIM_ERR; + return ERROR_FAIL; #else Jim_Obj **dict; - int ret = Jim_DictPairs(interp, argv[1], &dict, &tmp); + int ret = Jim_DictPairs(CMD_CTX->interp, CMD_JIMTCL_ARGV[0], &dict, &tmp); if (ret != JIM_OK) - return ret; + return ERROR_FAIL; #endif const unsigned int length = tmp; - struct command_context *cmd_ctx = current_command_context(interp); - assert(cmd_ctx); - const struct target *target = get_current_target(cmd_ctx); + + const struct target *target = get_current_target(CMD_CTX); + assert(target); for (unsigned int i = 0; i < length; i += 2) { const char *reg_name = Jim_String(dict[i]); const char *reg_value = Jim_String(dict[i + 1]); - struct reg *reg = register_get_by_name(target->reg_cache, reg_name, - false); + struct reg *reg = register_get_by_name(target->reg_cache, reg_name, false); if (!reg || !reg->exist) { - Jim_SetResultFormatted(interp, "unknown register '%s'", reg_name); - return JIM_ERR; + command_print(CMD, "unknown register '%s'", reg_name); + return ERROR_FAIL; } uint8_t *buf = malloc(DIV_ROUND_UP(reg->size, 8)); - if (!buf) { LOG_ERROR("Failed to allocate memory"); - return JIM_ERR; + return ERROR_FAIL; } - str_to_buf(reg_value, strlen(reg_value), buf, reg->size, 0); - int retval = reg->type->set(reg, buf); + int retval = CALL_COMMAND_HANDLER(command_parse_str_to_buf, reg_value, buf, reg->size); + if (retval != ERROR_OK) { + free(buf); + return retval; + } + + retval = reg->type->set(reg, buf); free(buf); if (retval != ERROR_OK) { - Jim_SetResultFormatted(interp, "failed to set '%s' to register '%s'", + command_print(CMD, "failed to set '%s' to register '%s'", reg_value, reg_name); - return JIM_ERR; + return retval; } } - return JIM_OK; + return ERROR_OK; } /** @@ -4838,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; } @@ -4914,7 +4893,7 @@ static int target_configure(struct jim_getopt_info *goi, struct target *target) switch (n->value) { case TCFG_TYPE: /* not settable */ - if (goi->isconfigure) { + if (goi->is_configure) { Jim_SetResultFormatted(goi->interp, "not settable: %s", n->name); return JIM_ERR; @@ -4943,7 +4922,7 @@ no_params: return e; } - if (goi->isconfigure) { + if (goi->is_configure) { if (goi->argc != 1) { Jim_WrongNumArgs(goi->interp, goi->argc, goi->argv, "-event ?event-name? ?EVENT-BODY?"); return JIM_ERR; @@ -4958,20 +4937,32 @@ 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; - } - if (goi->isconfigure) { + /* not found! */ + if (&teap->list == &target->events_action) + teap = NULL; + + if (goi->is_configure) { /* START_DEPRECATED_TPIU */ if (n->value == TARGET_EVENT_TRACE_CONFIG) LOG_INFO("DEPRECATED target event %s; use TPIU events {pre,post}-{enable,disable}", n->name); /* END_DEPRECATED_TPIU */ + jim_getopt_obj(goi, &o); + if (Jim_Length(o) == 0) { + /* 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 */ @@ -4980,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); @@ -4998,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 { @@ -5014,7 +5003,7 @@ no_params: break; case TCFG_WORK_AREA_VIRT: - if (goi->isconfigure) { + if (goi->is_configure) { target_free_all_working_areas(target); e = jim_getopt_wide(goi, &w); if (e != JIM_OK) @@ -5030,7 +5019,7 @@ no_params: break; case TCFG_WORK_AREA_PHYS: - if (goi->isconfigure) { + if (goi->is_configure) { target_free_all_working_areas(target); e = jim_getopt_wide(goi, &w); if (e != JIM_OK) @@ -5046,7 +5035,7 @@ no_params: break; case TCFG_WORK_AREA_SIZE: - if (goi->isconfigure) { + if (goi->is_configure) { target_free_all_working_areas(target); e = jim_getopt_wide(goi, &w); if (e != JIM_OK) @@ -5061,7 +5050,7 @@ no_params: break; case TCFG_WORK_AREA_BACKUP: - if (goi->isconfigure) { + if (goi->is_configure) { target_free_all_working_areas(target); e = jim_getopt_wide(goi, &w); if (e != JIM_OK) @@ -5078,7 +5067,7 @@ no_params: case TCFG_ENDIAN: - if (goi->isconfigure) { + if (goi->is_configure) { e = jim_getopt_nvp(goi, nvp_target_endian, &n); if (e != JIM_OK) { jim_getopt_nvp_unknown(goi, nvp_target_endian, 1); @@ -5099,7 +5088,7 @@ no_params: break; case TCFG_COREID: - if (goi->isconfigure) { + if (goi->is_configure) { e = jim_getopt_wide(goi, &w); if (e != JIM_OK) return e; @@ -5113,7 +5102,7 @@ no_params: break; case TCFG_CHAIN_POSITION: - if (goi->isconfigure) { + if (goi->is_configure) { Jim_Obj *o_t; struct jtag_tap *tap; @@ -5140,7 +5129,7 @@ no_params: /* loop for more e*/ break; case TCFG_DBGBASE: - if (goi->isconfigure) { + if (goi->is_configure) { e = jim_getopt_wide(goi, &w); if (e != JIM_OK) return e; @@ -5170,7 +5159,7 @@ no_params: break; case TCFG_GDB_PORT: - if (goi->isconfigure) { + if (goi->is_configure) { struct command_context *cmd_ctx = current_command_context(goi->interp); if (cmd_ctx->mode != COMMAND_CONFIG) { Jim_SetResultString(goi->interp, "-gdb-port must be configured before 'init'", -1); @@ -5192,7 +5181,7 @@ no_params: break; case TCFG_GDB_MAX_CONNECTIONS: - if (goi->isconfigure) { + if (goi->is_configure) { struct command_context *cmd_ctx = current_command_context(goi->interp); if (cmd_ctx->mode != COMMAND_CONFIG) { Jim_SetResultString(goi->interp, "-gdb-max-connections must be configured before 'init'", -1); @@ -5223,7 +5212,7 @@ static int jim_target_configure(Jim_Interp *interp, int argc, Jim_Obj * const *a struct jim_getopt_info goi; jim_getopt_setup(&goi, interp, argc - 1, argv + 1); - goi.isconfigure = !strcmp(c->name, "configure"); + goi.is_configure = !strcmp(c->name, "configure"); if (goi.argc < 1) { Jim_WrongNumArgs(goi.interp, goi.argc, goi.argv, "missing: -option ..."); @@ -5414,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; } @@ -5561,14 +5550,14 @@ 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", .mode = COMMAND_EXEC, - .jim_handler = target_jim_set_reg, + .handler = handle_set_reg_command, .help = "Set target register values", .usage = "dict", }, @@ -5582,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']", }, @@ -5779,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) { @@ -5789,7 +5780,7 @@ static int target_create(struct jim_getopt_info *goi) } target->dbgmsg = NULL; - target->dbg_msg_enabled = 0; + target->dbg_msg_enabled = false; target->endianness = TARGET_ENDIAN_UNKNOWN; @@ -5799,8 +5790,18 @@ 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->isconfigure = 1; + goi->is_configure = true; e = target_configure(goi, target); if (e == JIM_OK) { @@ -5825,6 +5826,7 @@ static int target_create(struct jim_getopt_info *goi) free(target->gdb_port_override); free(target->trace_info); free(target->type); + free(target->private_config); free(target); return e; } @@ -5834,18 +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); - return JIM_ERR; - } - if (target->type->target_create) { e = (*(target->type->target_create))(target, goi->interp); if (e != ERROR_OK) { @@ -5855,6 +5845,7 @@ static int target_create(struct jim_getopt_info *goi) free(target->gdb_port_override); free(target->trace_info); free(target->type); + free(target->private_config); free(target); return JIM_ERR; } @@ -5984,7 +5975,7 @@ static int get_target_with_common_rtos_type(struct command_invocation *cmd, COMMAND_HANDLER(handle_target_smp) { - static int smp_group = 1; + static unsigned int smp_group = 1; if (CMD_ARGC == 0) { LOG_DEBUG("Empty SMP target"); @@ -6696,14 +6687,14 @@ 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", .mode = COMMAND_EXEC, - .jim_handler = target_jim_set_reg, + .handler = handle_set_reg_command, .help = "Set target register values", .usage = "dict", }, @@ -6717,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 c74b8c2..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 @@ -163,7 +163,7 @@ struct target { struct watchpoint *watchpoints; /* list of watchpoints */ struct trace *trace_info; /* generic trace information */ struct debug_msg_receiver *dbgmsg; /* list of debug message receivers */ - uint32_t dbg_msg_enabled; /* debug message status */ + bool dbg_msg_enabled; /* debug message status */ void *arch_info; /* architecture specific information */ void *private_config; /* pointer to target specific config data (for jim_configure hook) */ struct target *next; /* next target in list */ @@ -190,7 +190,7 @@ struct target { * poll too quickly because we'll just overwhelm the user with error * messages. */ struct backoff_timer backoff; - int smp; /* Unique non-zero number for each SMP group */ + unsigned int smp; /* Unique non-zero number for each SMP group */ struct list_head *smp_targets; /* list all targets in this smp group/cluster * The head of the list is shared between the * cluster, thus here there is a pointer */ @@ -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. * @@ -691,7 +684,7 @@ target_addr_t target_address_max(struct target *target); * * This routine is a wrapper for target->type->address_bits. */ -unsigned target_address_bits(struct target *target); +unsigned int target_address_bits(struct target *target); /** * Return the number of data bits this target supports. @@ -785,7 +778,7 @@ void target_handle_event(struct target *t, enum target_event e); void target_handle_md_output(struct command_invocation *cmd, struct target *target, target_addr_t address, unsigned size, - unsigned count, const uint8_t *buffer, bool include_address); + unsigned int count, const uint8_t *buffer, bool include_address); int target_profiling_default(struct target *target, uint32_t *samples, uint32_t max_num_samples, uint32_t *num_samples, uint32_t seconds); @@ -805,6 +798,7 @@ int target_profiling_default(struct target *target, uint32_t *samples, uint32_t #define ERROR_TARGET_ALGO_EXIT (-313) #define ERROR_TARGET_SIZE_NOT_SUPPORTED (-314) #define ERROR_TARGET_PACKING_NOT_SUPPORTED (-315) +#define ERROR_TARGET_HALTED_DO_RESUME (-316) /* used to workaround incorrect debug halt */ extern bool get_target_reset_nag(void); diff --git a/src/target/target_request.c b/src/target/target_request.c index 72c8421..8d51dc3 100644 --- a/src/target/target_request.c +++ b/src/target/target_request.c @@ -107,7 +107,7 @@ static int target_hexmsg(struct target *target, int size, uint32_t length) */ int target_request(struct target *target, uint32_t request) { - target_req_cmd_t target_req_cmd = request & 0xff; + enum target_req_cmd target_req_cmd = request & 0xff; assert(target->type->target_request_data); @@ -164,7 +164,7 @@ static int add_debug_msg_receiver(struct command_context *cmd_ctx, struct target (*p)->next = NULL; /* enable callback */ - target->dbg_msg_enabled = 1; + target->dbg_msg_enabled = true; return ERROR_OK; } @@ -225,7 +225,7 @@ int delete_debug_msg_receiver(struct command_context *cmd_ctx, struct target *ta free(c); if (!*p) { /* disable callback */ - target->dbg_msg_enabled = 0; + target->dbg_msg_enabled = false; } return ERROR_OK; } else diff --git a/src/target/target_request.h b/src/target/target_request.h index 62d5c74..97edd9e 100644 --- a/src/target/target_request.h +++ b/src/target/target_request.h @@ -17,12 +17,12 @@ struct target; struct command_context; -typedef enum target_req_cmd { +enum target_req_cmd { TARGET_REQ_TRACEMSG, TARGET_REQ_DEBUGMSG, TARGET_REQ_DEBUGCHAR, /* TARGET_REQ_SEMIHOSTING, */ -} target_req_cmd_t; +}; struct debug_msg_receiver { struct command_context *cmd_ctx; diff --git a/src/target/target_type.h b/src/target/target_type.h index bc42c2d..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. * @@ -303,7 +303,7 @@ struct target_type { /* Return the number of address bits this target supports. This will * typically be 32 for 32-bit targets, and 64 for 64-bit targets. If not * implemented, it's assumed to be 32. */ - unsigned (*address_bits)(struct target *target); + unsigned int (*address_bits)(struct target *target); /* Return the number of system bus data bits this target supports. This * will typically be 32 for 32-bit targets, and 64 for 64-bit targets. If diff --git a/src/target/trace.h b/src/target/trace.h index e3d787e..dc3ab57 100644 --- a/src/target/trace.h +++ b/src/target/trace.h @@ -33,13 +33,13 @@ struct trace { * to *hardware* tracing ... split such "real" tracing out from * the contrib/libdcc support. */ -typedef enum trace_status { +enum trace_status { TRACE_IDLE = 0x0, TRACE_RUNNING = 0x1, TRACE_TRIGGERED = 0x2, TRACE_COMPLETED = 0x4, TRACE_OVERFLOWED = 0x8, -} trace_status_t; +}; int trace_point(struct target *target, uint32_t number); int trace_register_commands(struct command_context *cmd_ctx); diff --git a/src/target/x86_32_common.c b/src/target/x86_32_common.c index ecaf52b..8cca9a5 100644 --- a/src/target/x86_32_common.c +++ b/src/target/x86_32_common.c @@ -677,7 +677,7 @@ int x86_32_common_write_memory(struct target *t, target_addr_t addr, return retval; } -int x86_32_common_read_io(struct target *t, uint32_t addr, +static int x86_32_common_read_io(struct target *t, uint32_t addr, uint32_t size, uint8_t *buf) { struct x86_32_common *x86_32 = target_to_x86_32(t); @@ -1330,14 +1330,14 @@ static int write_hw_reg_from_cache(struct target *t, int num) /* x86 32 commands */ static void handle_iod_output(struct command_invocation *cmd, - struct target *target, uint32_t address, unsigned size, - unsigned count, const uint8_t *buffer) + struct target *target, uint32_t address, unsigned int size, + unsigned int count, const uint8_t *buffer) { - const unsigned line_bytecnt = 32; - unsigned line_modulo = line_bytecnt / size; + const unsigned int line_bytecnt = 32; + unsigned int line_modulo = line_bytecnt / size; char output[line_bytecnt * 4 + 1]; - unsigned output_len = 0; + unsigned int output_len = 0; const char *value_fmt; switch (size) { @@ -1356,12 +1356,12 @@ static void handle_iod_output(struct command_invocation *cmd, return; } - for (unsigned i = 0; i < count; i++) { + for (unsigned int i = 0; i < count; i++) { if (i % line_modulo == 0) { output_len += snprintf(output + output_len, sizeof(output) - output_len, - "0x%8.8x: ", - (unsigned)(address + (i*size))); + "0x%8.8" PRIx32 ": ", + address + (i * size)); } uint32_t value = 0; @@ -1399,7 +1399,7 @@ COMMAND_HANDLER(handle_iod_command) return ERROR_COMMAND_SYNTAX_ERROR; } - unsigned size = 0; + unsigned int size = 0; switch (CMD_NAME[2]) { case 'w': size = 4; @@ -1413,7 +1413,7 @@ COMMAND_HANDLER(handle_iod_command) default: return ERROR_COMMAND_SYNTAX_ERROR; } - unsigned count = 1; + unsigned int count = 1; uint8_t *buffer = calloc(count, size); struct target *target = get_current_target(CMD_CTX); int retval = x86_32_common_read_io(target, address, size, buffer); @@ -1425,7 +1425,7 @@ COMMAND_HANDLER(handle_iod_command) static int target_fill_io(struct target *target, uint32_t address, - unsigned data_size, + unsigned int data_size, /* value */ uint32_t b) { @@ -1458,7 +1458,7 @@ COMMAND_HANDLER(handle_iow_command) COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], value); struct target *target = get_current_target(CMD_CTX); - unsigned wordsize; + unsigned int wordsize; switch (CMD_NAME[2]) { case 'w': wordsize = 4; diff --git a/src/target/x86_32_common.h b/src/target/x86_32_common.h index 7392447..e232747 100644 --- a/src/target/x86_32_common.h +++ b/src/target/x86_32_common.h @@ -309,8 +309,6 @@ int x86_32_common_read_memory(struct target *t, target_addr_t addr, uint32_t size, uint32_t count, uint8_t *buf); int x86_32_common_write_memory(struct target *t, target_addr_t addr, uint32_t size, uint32_t count, const uint8_t *buf); -int x86_32_common_read_io(struct target *t, uint32_t addr, - uint32_t size, uint8_t *buf); int x86_32_common_write_io(struct target *t, uint32_t addr, uint32_t size, const uint8_t *buf); int x86_32_common_add_breakpoint(struct target *t, struct breakpoint *bp); diff --git a/src/target/xscale.c b/src/target/xscale.c index fbf4351..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); @@ -137,7 +137,7 @@ static int xscale_verify_pointer(struct command_invocation *cmd, return ERROR_OK; } -static int xscale_jtag_set_instr(struct jtag_tap *tap, uint32_t new_instr, tap_state_t end_state) +static int xscale_jtag_set_instr(struct jtag_tap *tap, uint32_t new_instr, enum tap_state end_state) { assert(tap); @@ -232,7 +232,7 @@ static int xscale_receive(struct target *target, uint32_t *buffer, int num_words struct xscale_common *xscale = target_to_xscale(target); int retval = ERROR_OK; - tap_state_t path[3]; + enum tap_state path[3]; struct scan_field fields[3]; uint8_t *field0 = malloc(num_words * 1); uint8_t field0_check_value = 0x2; @@ -330,8 +330,8 @@ static int xscale_receive(struct target *target, uint32_t *buffer, int num_words static int xscale_read_tx(struct target *target, int consume) { struct xscale_common *xscale = target_to_xscale(target); - tap_state_t path[3]; - tap_state_t noconsume_path[6]; + enum tap_state path[3]; + enum tap_state noconsume_path[6]; int retval; struct timeval timeout, now; struct scan_field fields[3]; @@ -840,7 +840,7 @@ static int xscale_debug_entry(struct target *target) struct arm *arm = &xscale->arm; uint32_t pc; uint32_t buffer[10]; - unsigned i; + unsigned int i; int retval; uint32_t moe; @@ -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); @@ -1515,7 +1515,7 @@ static int xscale_deassert_reset(struct target *target) */ { uint32_t address; - unsigned buf_cnt; + unsigned int buf_cnt; const uint8_t *buffer = xscale_debug_handler; int retval; @@ -1539,11 +1539,11 @@ static int xscale_deassert_reset(struct target *target) * coprocessors, trace data, etc. */ address = xscale->handler_address; - for (unsigned binary_size = sizeof(xscale_debug_handler); + for (unsigned int binary_size = sizeof(xscale_debug_handler); binary_size > 0; binary_size -= buf_cnt, buffer += buf_cnt) { uint32_t cache_line[8]; - unsigned i; + unsigned int i; buf_cnt = binary_size; if (buf_cnt > 32) @@ -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); } } @@ -3215,7 +3215,7 @@ COMMAND_HANDLER(xscale_handle_idcache_command) static const struct { char name[15]; - unsigned mask; + unsigned int mask; } vec_ids[] = { { "fiq", DCSR_TF, }, { "irq", DCSR_TI, }, @@ -3250,7 +3250,7 @@ COMMAND_HANDLER(xscale_handle_vector_catch_command) } } while (CMD_ARGC-- > 0) { - unsigned i; + unsigned int i; for (i = 0; i < ARRAY_SIZE(vec_ids); i++) { if (strcmp(CMD_ARGV[CMD_ARGC], vec_ids[i].name)) continue; @@ -3268,7 +3268,7 @@ COMMAND_HANDLER(xscale_handle_vector_catch_command) } dcsr_value = buf_get_u32(dcsr_reg->value, 0, 32); - for (unsigned i = 0; i < ARRAY_SIZE(vec_ids); i++) { + for (unsigned int i = 0; i < ARRAY_SIZE(vec_ids); i++) { command_print(CMD, "%15s: %s", vec_ids[i].name, (dcsr_value & vec_ids[i].mask) ? "catch" : "ignore"); } diff --git a/src/target/xtensa/xtensa.c b/src/target/xtensa/xtensa.c index 702b8fc..3a877ed 100644 --- a/src/target/xtensa/xtensa.c +++ b/src/target/xtensa/xtensa.c @@ -503,7 +503,7 @@ static enum xtensa_reg_id xtensa_windowbase_offset_to_canonical(struct xtensa *x } else if (reg_idx >= XT_REG_IDX_A0 && reg_idx <= XT_REG_IDX_A15) { idx = reg_idx - XT_REG_IDX_A0; } else { - LOG_ERROR("Error: can't convert register %d to non-windowbased register!", reg_idx); + LOG_ERROR("Can't convert register %d to non-windowbased register", reg_idx); return -1; } /* Each windowbase value represents 4 registers on LX and 8 on NX */ @@ -540,7 +540,7 @@ static void xtensa_queue_exec_ins_wide(struct xtensa *xtensa, uint8_t *ops, uint for (int32_t i = oplenw - 1; i > 0; i--) xtensa_queue_dbg_reg_write(xtensa, XDMREG_DIR0 + i, - target_buffer_get_u32(xtensa->target, &ops_padded[sizeof(uint32_t)*i])); + target_buffer_get_u32(xtensa->target, &ops_padded[sizeof(uint32_t) * i])); /* Write DIR0EXEC last */ xtensa_queue_dbg_reg_write(xtensa, XDMREG_DIR0EXEC, @@ -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; @@ -1727,7 +1729,7 @@ int xtensa_do_step(struct target *target, int current, target_addr_t address, in xtensa_reg_val_t dbreakc[XT_WATCHPOINTS_NUM_MAX]; xtensa_reg_val_t icountlvl, cause; xtensa_reg_val_t oldps, oldpc, cur_pc; - bool ps_lowered = false; + bool ps_modified = false; LOG_TARGET_DEBUG(target, "current=%d, address=" TARGET_ADDR_FMT ", handle_breakpoints=%i", current, address, handle_breakpoints); @@ -1783,14 +1785,23 @@ int xtensa_do_step(struct target *target, int current, target_addr_t address, in * RFI >= DBGLEVEL. */ if (xtensa->stepping_isr_mode == XT_STEPPING_ISR_OFF) { - if (!xtensa->core_config->high_irq.enabled) { - LOG_TARGET_WARNING( - target, - "disabling IRQs while stepping is not implemented w/o high prio IRQs option!"); - return ERROR_FAIL; + if (xtensa->core_config->core_type == XT_LX) { + if (!xtensa->core_config->high_irq.enabled) { + LOG_TARGET_WARNING(target, + "disabling IRQs while stepping is not implemented w/o high prio IRQs option!"); + return ERROR_FAIL; + } + /* Update ICOUNTLEVEL accordingly */ + icountlvl = MIN((oldps & 0xF) + 1, xtensa->core_config->debug.irq_level); + } else { + /* Xtensa NX does not have the ICOUNTLEVEL feature present in Xtensa LX + * and instead disable interrupts while stepping. This could change + * the timing of the system while under debug */ + xtensa_reg_val_t newps = oldps | XT_PS_DI_MSK; + xtensa_reg_set(target, XT_REG_IDX_PS, newps); + icountlvl = xtensa->core_config->debug.irq_level; + ps_modified = true; } - /* Update ICOUNTLEVEL accordingly */ - icountlvl = MIN((oldps & 0xF) + 1, xtensa->core_config->debug.irq_level); } else { icountlvl = xtensa->core_config->debug.irq_level; } @@ -1815,7 +1826,7 @@ int xtensa_do_step(struct target *target, int current, target_addr_t address, in xtensa_cause_clear(target); /* so we don't recurse into the same routine */ if (xtensa->core_config->core_type == XT_LX && ((oldps & 0xf) >= icountlvl)) { /* Lower interrupt level to allow stepping, but flag eps[dbglvl] to be restored */ - ps_lowered = true; + ps_modified = true; uint32_t newps = (oldps & ~0xf) | (icountlvl - 1); xtensa_reg_set(target, xtensa->eps_dbglevel_idx, newps); LOG_TARGET_DEBUG(target, @@ -1835,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; @@ -1916,11 +1927,12 @@ int xtensa_do_step(struct target *target, int current, target_addr_t address, in } /* Restore int level */ - if (ps_lowered) { + if (ps_modified) { LOG_DEBUG("Restoring %s after stepping: 0x%08" PRIx32, - xtensa->core_cache->reg_list[xtensa->eps_dbglevel_idx].name, - oldps); - xtensa_reg_set(target, xtensa->eps_dbglevel_idx, oldps); + xtensa->core_cache->reg_list[(xtensa->core_config->core_type == XT_LX) ? + xtensa->eps_dbglevel_idx : XT_REG_IDX_PS].name, oldps); + xtensa_reg_set(target, (xtensa->core_config->core_type == XT_LX) ? + xtensa->eps_dbglevel_idx : XT_REG_IDX_PS, oldps); } /* write ICOUNTLEVEL back to zero */ @@ -1931,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) @@ -2796,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. */ @@ -3000,13 +3013,13 @@ static int xtensa_build_reg_cache(struct target *target) /* Construct empty-register list for handling unknown register requests */ xtensa->empty_regs = calloc(xtensa->dbregs_num, sizeof(struct reg)); if (!xtensa->empty_regs) { - LOG_TARGET_ERROR(target, "ERROR: Out of memory"); + LOG_TARGET_ERROR(target, "Out of memory"); goto fail; } for (unsigned int i = 0; i < xtensa->dbregs_num; i++) { xtensa->empty_regs[i].name = calloc(8, sizeof(char)); if (!xtensa->empty_regs[i].name) { - LOG_TARGET_ERROR(target, "ERROR: Out of memory"); + LOG_TARGET_ERROR(target, "Out of memory"); goto fail; } sprintf((char *)xtensa->empty_regs[i].name, "?0x%04x", i & 0x0000FFFF); @@ -3024,7 +3037,7 @@ static int xtensa_build_reg_cache(struct target *target) if (xtensa->regmap_contiguous && xtensa->contiguous_regs_desc) { xtensa->contiguous_regs_list = calloc(xtensa->total_regs_num, sizeof(struct reg *)); if (!xtensa->contiguous_regs_list) { - LOG_TARGET_ERROR(target, "ERROR: Out of memory"); + LOG_TARGET_ERROR(target, "Out of memory"); goto fail; } for (unsigned int i = 0; i < xtensa->total_regs_num; i++) { @@ -3966,10 +3979,10 @@ COMMAND_HELPER(xtensa_cmd_xtreg_do, struct xtensa *xtensa) rptr->type = XT_REG_OTHER; } - /* Register flags */ + /* Register flags: includes intsetN, intclearN for LX8 */ if ((strcmp(rptr->name, "mmid") == 0) || (strcmp(rptr->name, "eraccess") == 0) || - (strcmp(rptr->name, "ddr") == 0) || (strcmp(rptr->name, "intset") == 0) || - (strcmp(rptr->name, "intclear") == 0)) + (strcmp(rptr->name, "ddr") == 0) || (strncmp(rptr->name, "intset", 6) == 0) || + (strncmp(rptr->name, "intclear", 8) == 0) || (strcmp(rptr->name, "mesrclr") == 0)) rptr->flags = XT_REGF_NOREAD; else rptr->flags = 0; @@ -4191,11 +4204,6 @@ COMMAND_HELPER(xtensa_cmd_mask_interrupts_do, struct xtensa *xtensa) return ERROR_OK; } - if (xtensa->core_config->core_type == XT_NX) { - command_print(CMD, "ERROR: ISR step mode only supported on Xtensa LX"); - return ERROR_FAIL; - } - /* Masking is ON -> interrupts during stepping are OFF, and vice versa */ if (!strcasecmp(CMD_ARGV[0], "off")) state = XT_STEPPING_ISR_ON; diff --git a/src/target/xtensa/xtensa.h b/src/target/xtensa/xtensa.h index 1d56f83..a920f77 100644 --- a/src/target/xtensa/xtensa.h +++ b/src/target/xtensa/xtensa.h @@ -45,6 +45,7 @@ /* PS register bits (NX) */ #define XT_PS_DIEXC_MSK BIT(2) +#define XT_PS_DI_MSK BIT(3) /* MS register bits (NX) */ #define XT_MS_DE_MSK BIT(5) @@ -377,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/target/xtensa/xtensa_chip.c b/src/target/xtensa/xtensa_chip.c index ac4a49c..ce6d35c 100644 --- a/src/target/xtensa/xtensa_chip.c +++ b/src/target/xtensa/xtensa_chip.c @@ -103,7 +103,7 @@ static int xtensa_chip_target_create(struct target *target, Jim_Interp *interp) LOG_DEBUG("DAP: ap_num %" PRId64 " DAP %p\n", pc->ap_num, pc->dap); } else { xtensa_chip_dm_cfg.tap = target->tap; - LOG_DEBUG("JTAG: %s:%s pos %d", target->tap->chip, target->tap->tapname, + LOG_DEBUG("JTAG: %s:%s pos %u", target->tap->chip, target->tap->tapname, target->tap->abs_chain_position); } diff --git a/src/target/xtensa/xtensa_debug_module.c b/src/target/xtensa/xtensa_debug_module.c index 8045779..943f199 100644 --- a/src/target/xtensa/xtensa_debug_module.c +++ b/src/target/xtensa/xtensa_debug_module.c @@ -60,7 +60,7 @@ static void xtensa_dm_add_dr_scan(struct xtensa_debug_module *dm, int len, const uint8_t *src, uint8_t *dest, - tap_state_t endstate) + enum tap_state endstate) { struct scan_field field; diff --git a/src/target/xtensa/xtensa_debug_module.h b/src/target/xtensa/xtensa_debug_module.h index 495da2a..8391a96 100644 --- a/src/target/xtensa/xtensa_debug_module.h +++ b/src/target/xtensa/xtensa_debug_module.h @@ -75,6 +75,7 @@ enum xtensa_dm_reg { XDMREG_DELAYCNT, XDMREG_MEMADDRSTART, XDMREG_MEMADDREND, + XDMREG_DEBUGPC,/*Unsupported, undocumented, may not be present*/ XDMREG_EXTTIMELO, XDMREG_EXTTIMEHI, XDMREG_TRAXRSVD48, @@ -184,6 +185,7 @@ struct xtensa_dm_reg_offsets { { .nar = 0x07, .apb = 0x001c }, /* XDMREG_DELAYCNT */ \ { .nar = 0x08, .apb = 0x0020 }, /* XDMREG_MEMADDRSTART */ \ { .nar = 0x09, .apb = 0x0024 }, /* XDMREG_MEMADDREND */ \ + { .nar = 0x0f, .apb = 0x003c }, /* XDMREG_DEBUGPC */ \ { .nar = 0x10, .apb = 0x0040 }, /* XDMREG_EXTTIMELO */ \ { .nar = 0x11, .apb = 0x0044 }, /* XDMREG_EXTTIMEHI */ \ { .nar = 0x12, .apb = 0x0048 }, /* XDMREG_TRAXRSVD48 */ \ diff --git a/src/transport/transport.c b/src/transport/transport.c index 81d3d58..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 n = CMD_ARGC; - unsigned 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 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 i = 0; i < n; i++) - free(argv[i]); - free(argv); - return ERROR_FAIL; -} - COMMAND_HANDLER(handle_transport_init) { LOG_DEBUG("%s", __func__); @@ -278,7 +230,6 @@ COMMAND_HANDLER(handle_transport_select) if (session) { if (!strcmp(session->name, CMD_ARGV[0])) { LOG_WARNING("Transport \"%s\" was already selected", session->name); - command_print(CMD, "%s", session->name); return ERROR_OK; } command_print(CMD, "Can't change session's transport after the initial selection was made"); @@ -301,7 +252,6 @@ COMMAND_HANDLER(handle_transport_select) int retval = transport_select(CMD_CTX, CMD_ARGV[0]); if (retval != ERROR_OK) return retval; - command_print(CMD, "%s", session->name); return ERROR_OK; } } 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); diff --git a/src/xsvf/xsvf.c b/src/xsvf/xsvf.c index 0266c21..617c2f4 100644 --- a/src/xsvf/xsvf.c +++ b/src/xsvf/xsvf.c @@ -111,10 +111,10 @@ TDO (1); static int xsvf_fd; -/* map xsvf tap state to an openocd "tap_state_t" */ -static tap_state_t xsvf_to_tap(int xsvf_state) +/* map xsvf tap state to an openocd "enum tap_state" */ +static enum tap_state xsvf_to_tap(int xsvf_state) { - tap_state_t ret; + enum tap_state ret; switch (xsvf_state) { case XSV_RESET: @@ -196,16 +196,16 @@ COMMAND_HANDLER(handle_xsvf_command) int xruntest = 0; /* number of TCK cycles OR *microseconds */ int xrepeat = 0; /* number of retries */ - tap_state_t xendir = TAP_IDLE; /* see page 8 of the SVF spec, initial + enum tap_state xendir = TAP_IDLE; /* see page 8 of the SVF spec, initial *xendir to be TAP_IDLE */ - tap_state_t xenddr = TAP_IDLE; + enum tap_state xenddr = TAP_IDLE; uint8_t opcode; uint8_t uc = 0; long file_offset = 0; int loop_count = 0; - tap_state_t loop_state = TAP_IDLE; + enum tap_state loop_state = TAP_IDLE; int loop_clocks = 0; int loop_usecs = 0; @@ -216,8 +216,8 @@ COMMAND_HANDLER(handle_xsvf_command) int verbose = 1; bool collecting_path = false; - tap_state_t path[XSTATE_MAX_PATH]; - unsigned pathlen = 0; + enum tap_state path[XSTATE_MAX_PATH]; + unsigned int pathlen = 0; /* a flag telling whether to clock TCK during waits, * or simply sleep, controlled by virt2 @@ -272,7 +272,7 @@ COMMAND_HANDLER(handle_xsvf_command) * or terminate a path. */ if (collecting_path) { - tap_state_t mystate; + enum tap_state mystate; switch (opcode) { case XCOMMENT: @@ -455,7 +455,7 @@ COMMAND_HANDLER(handle_xsvf_command) * will be skipped entirely if xrepeat is set to zero. */ - static tap_state_t exception_path[] = { + static enum tap_state exception_path[] = { TAP_DREXIT2, TAP_DRSHIFT, TAP_DREXIT1, @@ -563,7 +563,7 @@ COMMAND_HANDLER(handle_xsvf_command) case XSTATE: { - tap_state_t mystate; + enum tap_state mystate; if (read(xsvf_fd, &uc, 1) < 0) { do_abort = 1; @@ -654,7 +654,7 @@ COMMAND_HANDLER(handle_xsvf_command) uint8_t short_buf[2]; uint8_t *ir_buf; int bitcount; - tap_state_t my_end_state = xruntest ? TAP_IDLE : xendir; + enum tap_state my_end_state = xruntest ? TAP_IDLE : xendir; if (opcode == XSIR) { /* one byte bitcount */ @@ -744,15 +744,15 @@ COMMAND_HANDLER(handle_xsvf_command) uint8_t end; uint8_t delay_buf[4]; - tap_state_t wait_state; - tap_state_t end_state; + enum tap_state wait_state; + enum tap_state end_state; int delay; if (read(xsvf_fd, &wait_local, 1) < 0 - || read(xsvf_fd, &end, 1) < 0 - || read(xsvf_fd, delay_buf, 4) < 0) { - do_abort = 1; - break; + || read(xsvf_fd, &end, 1) < 0 + || read(xsvf_fd, delay_buf, 4) < 0) { + do_abort = 1; + break; } wait_state = xsvf_to_tap(wait_local); @@ -788,8 +788,8 @@ COMMAND_HANDLER(handle_xsvf_command) uint8_t usecs_buf[4]; uint8_t wait_local; uint8_t end; - tap_state_t wait_state; - tap_state_t end_state; + enum tap_state wait_state; + enum tap_state end_state; int clock_count; int usecs; |