X-Git-Url: https://review.openocd.org/gitweb?p=openocd.git;a=blobdiff_plain;f=src%2Ftarget%2Fnds32.c;h=2926b236778d20f3c1bb4a2858466d7a871081c1;hp=50d6e3b9e1818cad65b5022b7b73cd821117a634;hb=d0e763ac7ef6aa17b17bd00ccdfbccfb4eacda69;hpb=399561eafa747e71202d00985206b65868142afb diff --git a/src/target/nds32.c b/src/target/nds32.c index 50d6e3b9e1..2926b23677 100644 --- a/src/target/nds32.c +++ b/src/target/nds32.c @@ -13,9 +13,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ #ifdef HAVE_CONFIG_H @@ -86,32 +84,32 @@ static int nds32_get_core_reg(struct reg *reg) } if (reg->valid) { - LOG_DEBUG("reading register(cached) %i(%s), value: 0x%8.8" PRIx32, - reg_arch_info->num, reg->name, reg_arch_info->value); + uint32_t val = buf_get_u32(reg_arch_info->value, 0, 32); + LOG_DEBUG("reading register(cached) %" PRIi32 "(%s), value: 0x%8.8" PRIx32, + reg_arch_info->num, reg->name, val); return ERROR_OK; } int mapped_regnum = nds32->register_map(nds32, reg_arch_info->num); if (reg_arch_info->enable == false) { - reg_arch_info->value = NDS32_REGISTER_DISABLE; + buf_set_u32(reg_arch_info->value, 0, 32, NDS32_REGISTER_DISABLE); retval = ERROR_FAIL; } else { - if ((nds32->fpu_enable == false) && - (NDS32_REG_TYPE_FPU == nds32_reg_type(mapped_regnum))) { - reg_arch_info->value = 0; + uint32_t val = 0; + if ((nds32->fpu_enable == false) + && (NDS32_REG_TYPE_FPU == nds32_reg_type(mapped_regnum))) { retval = ERROR_OK; - } else if ((nds32->audio_enable == false) && - (NDS32_REG_TYPE_AUMR == nds32_reg_type(mapped_regnum))) { - reg_arch_info->value = 0; + } else if ((nds32->audio_enable == false) + && (NDS32_REG_TYPE_AUMR == nds32_reg_type(mapped_regnum))) { retval = ERROR_OK; } else { - retval = aice_read_register(aice, - mapped_regnum, &(reg_arch_info->value)); + retval = aice_read_register(aice, mapped_regnum, &val); } + buf_set_u32(reg_arch_info->value, 0, 32, val); - LOG_DEBUG("reading register %i(%s), value: 0x%8.8" PRIx32, - reg_arch_info->num, reg->name, reg_arch_info->value); + LOG_DEBUG("reading register %" PRIi32 "(%s), value: 0x%8.8" PRIx32, + reg_arch_info->num, reg->name, val); } if (retval == ERROR_OK) { @@ -139,17 +137,17 @@ static int nds32_get_core_reg_64(struct reg *reg) return ERROR_OK; if (reg_arch_info->enable == false) { - reg_arch_info->value_64 = NDS32_REGISTER_DISABLE; + buf_set_u64(reg_arch_info->value, 0, 64, NDS32_REGISTER_DISABLE); retval = ERROR_FAIL; } else { - if ((nds32->fpu_enable == false) && - ((FD0 <= reg_arch_info->num) && (reg_arch_info->num <= FD31))) { - reg_arch_info->value_64 = 0; + uint64_t val = 0; + if ((nds32->fpu_enable == false) + && ((FD0 <= reg_arch_info->num) && (reg_arch_info->num <= FD31))) { retval = ERROR_OK; } else { - retval = aice_read_reg_64(aice, reg_arch_info->num, - &(reg_arch_info->value_64)); + retval = aice_read_reg_64(aice, reg_arch_info->num, &val); } + buf_set_u64(reg_arch_info->value, 0, 64, val); } if (retval == ERROR_OK) { @@ -309,7 +307,7 @@ static int nds32_set_core_reg(struct reg *reg, uint8_t *buf) if (nds32_reg_exception(mapped_regnum, value)) return ERROR_OK; - LOG_DEBUG("writing register %i(%s) with value 0x%8.8" PRIx32, + LOG_DEBUG("writing register %" PRIi32 "(%s) with value 0x%8.8" PRIx32, reg_arch_info->num, reg->name, value); if ((nds32->fpu_enable == false) && @@ -322,11 +320,13 @@ static int nds32_set_core_reg(struct reg *reg, uint8_t *buf) buf_set_u32(reg->value, 0, 32, 0); } else { buf_set_u32(reg->value, 0, 32, value); - aice_write_register(aice, mapped_regnum, reg_arch_info->value); + uint32_t val = buf_get_u32(reg_arch_info->value, 0, 32); + aice_write_register(aice, mapped_regnum, val); /* After set value to registers, read the value from target * to avoid W1C inconsistency. */ - aice_read_register(aice, mapped_regnum, &(reg_arch_info->value)); + aice_read_register(aice, mapped_regnum, &val); + buf_set_u32(reg_arch_info->value, 0, 32, val); } reg->valid = true; @@ -395,7 +395,7 @@ static const struct reg_arch_type nds32_reg_access_type_64 = { static struct reg_cache *nds32_build_reg_cache(struct target *target, struct nds32 *nds32) { - struct reg_cache *cache = malloc(sizeof(struct reg_cache)); + struct reg_cache *cache = calloc(sizeof(struct reg_cache), 1); struct reg *reg_list = calloc(TOTAL_REG_NUM, sizeof(struct reg)); struct nds32_reg *reg_arch_info = calloc(TOTAL_REG_NUM, sizeof(struct nds32_reg)); int i; @@ -423,17 +423,17 @@ static struct reg_cache *nds32_build_reg_cache(struct target *target, reg_list[i].size = nds32_reg_size(i); reg_list[i].arch_info = ®_arch_info[i]; - reg_list[i].reg_data_type = malloc(sizeof(struct reg_data_type)); + reg_list[i].reg_data_type = calloc(sizeof(struct reg_data_type), 1); if (FD0 <= reg_arch_info[i].num && reg_arch_info[i].num <= FD31) { - reg_list[i].value = &(reg_arch_info[i].value_64); + reg_list[i].value = reg_arch_info[i].value; reg_list[i].type = &nds32_reg_access_type_64; reg_list[i].reg_data_type->type = REG_TYPE_IEEE_DOUBLE; reg_list[i].reg_data_type->id = "ieee_double"; reg_list[i].group = "float"; } else { - reg_list[i].value = &(reg_arch_info[i].value); + reg_list[i].value = reg_arch_info[i].value; reg_list[i].type = &nds32_reg_access_type; reg_list[i].group = "general"; @@ -1545,14 +1545,18 @@ int nds32_restore_context(struct target *target) if (reg->valid == true) { LOG_DEBUG("examining dirty reg: %s", reg->name); - LOG_DEBUG("writing register %i " - "with value 0x%8.8" PRIx32, i, buf_get_u32(reg->value, 0, 32)); + LOG_DEBUG("writing register %d with value 0x%8.8" PRIx32, + i, buf_get_u32(reg->value, 0, 32)); reg_arch_info = reg->arch_info; - if (FD0 <= reg_arch_info->num && reg_arch_info->num <= FD31) - aice_write_reg_64(aice, reg_arch_info->num, reg_arch_info->value_64); - else - aice_write_register(aice, reg_arch_info->num, reg_arch_info->value); + if (FD0 <= reg_arch_info->num && reg_arch_info->num <= FD31) { + uint64_t val = buf_get_u64(reg_arch_info->value, 0, 64); + aice_write_reg_64(aice, reg_arch_info->num, val); + } else { + uint32_t val = buf_get_u32(reg_arch_info->value, 0, 32); + aice_write_register(aice, reg_arch_info->num, val); + } + reg->valid = true; reg->dirty = false; } @@ -1572,7 +1576,7 @@ int nds32_edm_config(struct nds32 *nds32) aice_read_debug_reg(aice, NDS_EDM_SR_EDM_CFG, &edm_cfg); nds32->edm.version = (edm_cfg >> 16) & 0xFFFF; - LOG_INFO("EDM version 0x%04" PRIx32, nds32->edm.version); + LOG_INFO("EDM version 0x%04x", nds32->edm.version); nds32->edm.breakpoint_num = (edm_cfg & 0x7) + 1; @@ -1644,11 +1648,20 @@ int nds32_init_arch_info(struct target *target, struct nds32 *nds32) nds32->reset_halt_as_examine = false; nds32->keep_target_edm_ctl = false; nds32->word_access_mem = false; - nds32->virtual_hosting = false; + nds32->virtual_hosting = true; nds32->hit_syscall = false; nds32->active_syscall_id = NDS32_SYSCALL_UNDEFINED; nds32->virtual_hosting_errno = 0; nds32->virtual_hosting_ctrl_c = false; + nds32->attached = false; + + nds32->syscall_break.asid = 0; + nds32->syscall_break.length = 4; + nds32->syscall_break.set = 0; + nds32->syscall_break.orig_instr = NULL; + nds32->syscall_break.next = NULL; + nds32->syscall_break.unique_id = 0x515CAll + target->target_number; + nds32->syscall_break.linked_BRP = 0; nds32_reg_init(); @@ -1999,7 +2012,7 @@ int nds32_login(struct nds32 *nds32) code_str[copy_length] = '\0'; code = strtoul(code_str, NULL, 16); - sprintf(command_str, "write_misc gen_port0 0x%x;", code); + sprintf(command_str, "write_misc gen_port0 0x%" PRIx32 ";", code); strcat(command_sequence, command_str); } @@ -2024,7 +2037,7 @@ int nds32_login(struct nds32 *nds32) else return ERROR_FAIL; - sprintf(command_str, "write_misc %s 0x%x;", reg_name, code); + sprintf(command_str, "write_misc %s 0x%" PRIx32 ";", reg_name, code); if (ERROR_OK != aice_program_edm(aice, command_str)) return ERROR_FAIL; } @@ -2109,7 +2122,9 @@ int nds32_poll(struct target *target) int nds32_resume(struct target *target, int current, uint32_t address, int handle_breakpoints, int debug_execution) { - LOG_DEBUG("current %d address %08x handle_breakpoints %d debug_execution %d", + LOG_DEBUG("current %d address %08" PRIx32 + " handle_breakpoints %d" + " debug_execution %d", current, address, handle_breakpoints, debug_execution); struct nds32 *nds32 = target_to_nds32(target); @@ -2155,16 +2170,48 @@ int nds32_resume(struct target *target, int current, return ERROR_OK; } +static int nds32_soft_reset_halt(struct target *target) +{ + /* TODO: test it */ + struct nds32 *nds32 = target_to_nds32(target); + struct aice_port_s *aice = target_to_aice(target); + + aice_assert_srst(aice, AICE_SRST); + + /* halt core and set pc to 0x0 */ + int retval = target_halt(target); + if (retval != ERROR_OK) + return retval; + + /* start fetching from IVB */ + uint32_t value_ir3; + nds32_get_mapped_reg(nds32, IR3, &value_ir3); + nds32_set_mapped_reg(nds32, PC, value_ir3 & 0xFFFF0000); + + return ERROR_OK; +} + int nds32_assert_reset(struct target *target) { struct nds32 *nds32 = target_to_nds32(target); struct aice_port_s *aice = target_to_aice(target); + struct nds32_cpu_version *cpu_version = &(nds32->cpu_version); - jtag_poll_set_enabled(true); + /* TODO: apply hw reset signal in not examined state */ + if (!(target_was_examined(target))) { + LOG_WARNING("Reset is not asserted because the target is not examined."); + LOG_WARNING("Use a reset button or power cycle the target."); + return ERROR_TARGET_NOT_EXAMINED; + } if (target->reset_halt) { - if (nds32->soft_reset_halt) - target->type->soft_reset_halt(target); + if ((nds32->soft_reset_halt) + || (nds32->edm.version < 0x51) + || ((nds32->edm.version == 0x51) + && (cpu_version->revision == 0x1C) + && (cpu_version->cpu_id_family == 0xC) + && (cpu_version->cpu_id_version == 0x0))) + nds32_soft_reset_halt(target); else aice_assert_srst(aice, AICE_RESET_HOLD); } else { @@ -2183,25 +2230,21 @@ int nds32_assert_reset(struct target *target) return ERROR_OK; } -static uint32_t nds32_backup_edm_ctl; -static bool gdb_attached; - static int nds32_gdb_attach(struct nds32 *nds32) { - LOG_DEBUG("nds32_gdb_attach"); + LOG_DEBUG("nds32_gdb_attach, target coreid: %" PRId32, nds32->target->coreid); - if (gdb_attached == false) { + if (nds32->attached == false) { if (nds32->keep_target_edm_ctl) { /* backup target EDM_CTL */ struct aice_port_s *aice = target_to_aice(nds32->target); - aice_read_debug_reg(aice, NDS_EDM_SR_EDM_CTL, &nds32_backup_edm_ctl); + aice_read_debug_reg(aice, NDS_EDM_SR_EDM_CTL, &nds32->backup_edm_ctl); } target_halt(nds32->target); - target_poll(nds32->target); - gdb_attached = true; + nds32->attached = true; } return ERROR_OK; @@ -2212,7 +2255,7 @@ static int nds32_gdb_detach(struct nds32 *nds32) LOG_DEBUG("nds32_gdb_detach"); bool backup_virtual_hosting_setting; - if (gdb_attached) { + if (nds32->attached) { backup_virtual_hosting_setting = nds32->virtual_hosting; /* turn off virtual hosting before resume as gdb-detach */ @@ -2223,13 +2266,10 @@ static int nds32_gdb_detach(struct nds32 *nds32) if (nds32->keep_target_edm_ctl) { /* restore target EDM_CTL */ struct aice_port_s *aice = target_to_aice(nds32->target); - aice_write_debug_reg(aice, NDS_EDM_SR_EDM_CTL, nds32_backup_edm_ctl); + aice_write_debug_reg(aice, NDS_EDM_SR_EDM_CTL, nds32->backup_edm_ctl); } - /* turn off polling */ - jtag_poll_set_enabled(false); - - gdb_attached = false; + nds32->attached = false; } return ERROR_OK; @@ -2239,7 +2279,12 @@ static int nds32_callback_event_handler(struct target *target, enum target_event event, void *priv) { int retval = ERROR_OK; - struct nds32 *nds32 = priv; + int target_number = *(int *)priv; + + if (target_number != target->target_number) + return ERROR_OK; + + struct nds32 *nds32 = target_to_nds32(target); switch (event) { case TARGET_EVENT_GDB_ATTACH: @@ -2260,11 +2305,9 @@ int nds32_init(struct nds32 *nds32) /* Initialize anything we can set up without talking to the target */ nds32->memory.access_channel = NDS_MEMORY_ACC_CPU; - /* turn off polling by default */ - jtag_poll_set_enabled(false); - /* register event callback */ - target_register_event_callback(nds32_callback_event_handler, nds32); + target_register_event_callback(nds32_callback_event_handler, + &(nds32->target->target_number)); return ERROR_OK; } @@ -2288,7 +2331,7 @@ int nds32_get_gdb_fileio_info(struct target *target, struct gdb_fileio_info *fil syscall_id = (value_ir6 >> 16) & 0x7FFF; nds32->active_syscall_id = syscall_id; - LOG_DEBUG("hit syscall ID: 0x%x", syscall_id); + LOG_DEBUG("hit syscall ID: 0x%" PRIx32, syscall_id); /* free previous identifier storage */ if (NULL != fileio_info->identifier) { @@ -2298,14 +2341,14 @@ int nds32_get_gdb_fileio_info(struct target *target, struct gdb_fileio_info *fil switch (syscall_id) { case NDS32_SYSCALL_EXIT: - fileio_info->identifier = (char *)malloc(5); + fileio_info->identifier = malloc(5); sprintf(fileio_info->identifier, "exit"); nds32_get_mapped_reg(nds32, R0, &(fileio_info->param_1)); break; case NDS32_SYSCALL_OPEN: { uint8_t filename[256]; - fileio_info->identifier = (char *)malloc(5); + fileio_info->identifier = malloc(5); sprintf(fileio_info->identifier, "open"); nds32_get_mapped_reg(nds32, R0, &(fileio_info->param_1)); /* reserve fileio_info->param_2 for length of path */ @@ -2318,26 +2361,26 @@ int nds32_get_gdb_fileio_info(struct target *target, struct gdb_fileio_info *fil } break; case NDS32_SYSCALL_CLOSE: - fileio_info->identifier = (char *)malloc(6); + fileio_info->identifier = malloc(6); sprintf(fileio_info->identifier, "close"); nds32_get_mapped_reg(nds32, R0, &(fileio_info->param_1)); break; case NDS32_SYSCALL_READ: - fileio_info->identifier = (char *)malloc(5); + fileio_info->identifier = malloc(5); sprintf(fileio_info->identifier, "read"); nds32_get_mapped_reg(nds32, R0, &(fileio_info->param_1)); nds32_get_mapped_reg(nds32, R1, &(fileio_info->param_2)); nds32_get_mapped_reg(nds32, R2, &(fileio_info->param_3)); break; case NDS32_SYSCALL_WRITE: - fileio_info->identifier = (char *)malloc(6); + fileio_info->identifier = malloc(6); sprintf(fileio_info->identifier, "write"); nds32_get_mapped_reg(nds32, R0, &(fileio_info->param_1)); nds32_get_mapped_reg(nds32, R1, &(fileio_info->param_2)); nds32_get_mapped_reg(nds32, R2, &(fileio_info->param_3)); break; case NDS32_SYSCALL_LSEEK: - fileio_info->identifier = (char *)malloc(6); + fileio_info->identifier = malloc(6); sprintf(fileio_info->identifier, "lseek"); nds32_get_mapped_reg(nds32, R0, &(fileio_info->param_1)); nds32_get_mapped_reg(nds32, R1, &(fileio_info->param_2)); @@ -2346,7 +2389,7 @@ int nds32_get_gdb_fileio_info(struct target *target, struct gdb_fileio_info *fil case NDS32_SYSCALL_UNLINK: { uint8_t filename[256]; - fileio_info->identifier = (char *)malloc(7); + fileio_info->identifier = malloc(7); sprintf(fileio_info->identifier, "unlink"); nds32_get_mapped_reg(nds32, R0, &(fileio_info->param_1)); /* reserve fileio_info->param_2 for length of path */ @@ -2359,7 +2402,7 @@ int nds32_get_gdb_fileio_info(struct target *target, struct gdb_fileio_info *fil case NDS32_SYSCALL_RENAME: { uint8_t filename[256]; - fileio_info->identifier = (char *)malloc(7); + fileio_info->identifier = malloc(7); sprintf(fileio_info->identifier, "rename"); nds32_get_mapped_reg(nds32, R0, &(fileio_info->param_1)); /* reserve fileio_info->param_2 for length of old path */ @@ -2376,7 +2419,7 @@ int nds32_get_gdb_fileio_info(struct target *target, struct gdb_fileio_info *fil } break; case NDS32_SYSCALL_FSTAT: - fileio_info->identifier = (char *)malloc(6); + fileio_info->identifier = malloc(6); sprintf(fileio_info->identifier, "fstat"); nds32_get_mapped_reg(nds32, R0, &(fileio_info->param_1)); nds32_get_mapped_reg(nds32, R1, &(fileio_info->param_2)); @@ -2384,7 +2427,7 @@ int nds32_get_gdb_fileio_info(struct target *target, struct gdb_fileio_info *fil case NDS32_SYSCALL_STAT: { uint8_t filename[256]; - fileio_info->identifier = (char *)malloc(5); + fileio_info->identifier = malloc(5); sprintf(fileio_info->identifier, "stat"); nds32_get_mapped_reg(nds32, R0, &(fileio_info->param_1)); /* reserve fileio_info->param_2 for length of old path */ @@ -2396,20 +2439,20 @@ int nds32_get_gdb_fileio_info(struct target *target, struct gdb_fileio_info *fil } break; case NDS32_SYSCALL_GETTIMEOFDAY: - fileio_info->identifier = (char *)malloc(13); + fileio_info->identifier = malloc(13); sprintf(fileio_info->identifier, "gettimeofday"); nds32_get_mapped_reg(nds32, R0, &(fileio_info->param_1)); nds32_get_mapped_reg(nds32, R1, &(fileio_info->param_2)); break; case NDS32_SYSCALL_ISATTY: - fileio_info->identifier = (char *)malloc(7); + fileio_info->identifier = malloc(7); sprintf(fileio_info->identifier, "isatty"); nds32_get_mapped_reg(nds32, R0, &(fileio_info->param_1)); break; case NDS32_SYSCALL_SYSTEM: { uint8_t command[256]; - fileio_info->identifier = (char *)malloc(7); + fileio_info->identifier = malloc(7); sprintf(fileio_info->identifier, "system"); nds32_get_mapped_reg(nds32, R0, &(fileio_info->param_1)); /* reserve fileio_info->param_2 for length of old path */ @@ -2420,12 +2463,12 @@ int nds32_get_gdb_fileio_info(struct target *target, struct gdb_fileio_info *fil } break; case NDS32_SYSCALL_ERRNO: - fileio_info->identifier = (char *)malloc(6); + fileio_info->identifier = malloc(6); sprintf(fileio_info->identifier, "errno"); nds32_set_mapped_reg(nds32, R0, nds32->virtual_hosting_errno); break; default: - fileio_info->identifier = (char *)malloc(8); + fileio_info->identifier = malloc(8); sprintf(fileio_info->identifier, "unknown"); break; } @@ -2435,7 +2478,7 @@ int nds32_get_gdb_fileio_info(struct target *target, struct gdb_fileio_info *fil int nds32_gdb_fileio_end(struct target *target, int retcode, int fileio_errno, bool ctrl_c) { - LOG_DEBUG("syscall return code: 0x%x, errno: 0x%x, ctrl_c: %s", + LOG_DEBUG("syscall return code: 0x%x, errno: 0x%x , ctrl_c: %s", retcode, fileio_errno, ctrl_c ? "true" : "false"); struct nds32 *nds32 = target_to_nds32(target); @@ -2449,6 +2492,25 @@ int nds32_gdb_fileio_end(struct target *target, int retcode, int fileio_errno, b return ERROR_OK; } +int nds32_profiling(struct target *target, uint32_t *samples, + uint32_t max_num_samples, uint32_t *num_samples, uint32_t seconds) +{ + /* sample $PC every 10 milliseconds */ + uint32_t iteration = seconds * 100; + struct aice_port_s *aice = target_to_aice(target); + struct nds32 *nds32 = target_to_nds32(target); + + if (max_num_samples < iteration) + iteration = max_num_samples; + + int pc_regnum = nds32->register_map(nds32, PC); + aice_profiling(aice, 10, iteration, pc_regnum, samples, num_samples); + + register_cache_invalidate(nds32->core_cache); + + return ERROR_OK; +} + int nds32_gdb_fileio_write_memory(struct nds32 *nds32, uint32_t address, uint32_t size, const uint8_t *buffer) {