int arc_ocd_examine(struct target *target) { uint32_t status; struct arc32_common *arc32 = target_to_arc32(target); LOG_DEBUG("-"); CHECK_RETVAL(arc_jtag_startup(&arc32->jtag_info)); if (!target_was_examined(target)) { CHECK_RETVAL(arc_jtag_status(&arc32->jtag_info, &status)); if (status & ARC_JTAG_STAT_RU) { target->state = TARGET_RUNNING; } else { /* It is first time we examine the target, it is halted * and we don't know why. Let's set debug reason, * otherwise OpenOCD will complain that reason is * unknown. */ if (target->state == TARGET_UNKNOWN) target->debug_reason = DBG_REASON_DBGRQ; target->state = TARGET_HALTED; } /* Read BCRs and configure optional registers. */ CHECK_RETVAL(arc32_configure(target)); target_set_examined(target); } return ERROR_OK; }
int arc_ocd_poll(struct target *target) { uint32_t status; struct arc32_common *arc32 = target_to_arc32(target); /* gdb calls continuously through this arc_poll() function */ CHECK_RETVAL(arc_jtag_status(&arc32->jtag_info, &status)); /* check for processor halted */ if (status & ARC_JTAG_STAT_RU) { target->state = TARGET_RUNNING; } else { if ((target->state == TARGET_RUNNING) || (target->state == TARGET_RESET)) { target->state = TARGET_HALTED; LOG_DEBUG("ARC core is halted or in reset."); CHECK_RETVAL(arc_dbg_debug_entry(target)); target_call_event_callbacks(target, TARGET_EVENT_HALTED); } else if (target->state == TARGET_DEBUG_RUNNING) { target->state = TARGET_HALTED; LOG_DEBUG("ARC core is in debug running mode"); CHECK_RETVAL(arc_dbg_debug_entry(target)); target_call_event_callbacks(target, TARGET_EVENT_DEBUG_HALTED); } } return ERROR_OK; }
/* Write byte at address */ static int arc_mem_write_block8(struct target *target, uint32_t addr, uint32_t count, void *buf) { struct arc32_common *arc32 = target_to_arc32(target); uint32_t i; LOG_DEBUG("Write 1-byte memory block: addr=0x%08" PRIx32 ", count=%" PRIu32, addr, count); /* We will read data from memory, so we need to flush D$. */ CHECK_RETVAL(arc32_dcache_flush(target)); uint32_t buffer_he; uint8_t buffer_te[sizeof(uint32_t)]; /* non-word writes are less common, than 4-byte writes, so I suppose we can * allowe ourselves to write this in a cycle, instead of calling arc_jtag * with count > 1. */ for(i = 0; i < count; i++) { /* See comment in arc_mem_write_block16 for details. Since it is a byte * there is not need to convert write buffer to target endianness, but * we still have to convert read buffer. */ CHECK_RETVAL(arc_jtag_read_memory(&arc32->jtag_info, (addr + i) & ~3, 1, &buffer_he, arc_mem_is_slow_memory(arc32, (addr + i) & ~3, 4, 1))); target_buffer_set_u32(target, buffer_te, buffer_he); memcpy(buffer_te + ((addr + i) & 3), (uint8_t*)buf + i, 1); buffer_he = target_buffer_get_u32(target, buffer_te); CHECK_RETVAL(arc_jtag_write_memory(&arc32->jtag_info, (addr + i) & ~3, 1, &buffer_he)); } /* Invalidate caches. */ CHECK_RETVAL(arc32_cache_invalidate(target)); return ERROR_OK; }
int arc_ocd_assert_reset(struct target *target) { struct arc32_common *arc32 = target_to_arc32(target); LOG_DEBUG("target->state: %s", target_state_name(target)); enum reset_types jtag_reset_config = jtag_get_reset_config(); if (target_has_event_action(target, TARGET_EVENT_RESET_ASSERT)) { /* allow scripts to override the reset event */ target_handle_event(target, TARGET_EVENT_RESET_ASSERT); register_cache_invalidate(arc32->core_cache); /* An ARC target might be in halt state after reset, so * if script requested processor to resume, then it must * be manually started to ensure that this request * is satisfied. */ 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)); } target->state = TARGET_RESET; return ERROR_OK; } /* some cores support connecting while srst is asserted * use that mode is it has been configured */ bool srst_asserted = false; if (!(jtag_reset_config & RESET_SRST_PULLS_TRST) && (jtag_reset_config & RESET_SRST_NO_GATING)) { jtag_add_reset(0, 1); srst_asserted = true; } if (jtag_reset_config & RESET_HAS_SRST) { /* should issue a srst only, but we may have to assert trst as well */ if (jtag_reset_config & RESET_SRST_PULLS_TRST) jtag_add_reset(1, 1); else if (!srst_asserted) jtag_add_reset(0, 1); } target->state = TARGET_RESET; jtag_add_sleep(50000); register_cache_invalidate(arc32->core_cache); if (target->reset_halt) CHECK_RETVAL(target_halt(target)); return ERROR_OK; }
/* Write half-word at half-word-aligned address */ static int arc_mem_write_block16(struct target *target, uint32_t addr, int count, void *buf) { struct arc32_common *arc32 = target_to_arc32(target); int retval = ERROR_OK; int i; LOG_DEBUG("Write memory (16bit): addr=0x%" PRIx32 ", count=%i", addr, count); /* Check arguments */ if (addr & 1u) return ERROR_TARGET_UNALIGNED_ACCESS; /* We will read data from memory, so we need to flush D$. */ retval = arc32_dcache_flush(target); if (ERROR_OK != retval) return retval; uint32_t buffer_he; uint8_t buffer_te[sizeof(uint32_t)]; uint8_t halfword_te[sizeof(uint16_t)]; /* non-word writes are less common, than 4-byte writes, so I suppose we can * allowe ourselves to write this in a cycle, instead of calling arc_jtag * with count > 1. */ for(i = 0; i < count; i++) { /* We can read only word at word-aligned address. Also *jtag_read_memory * functions return data in host endianness, so host endianness != * target endianness we have to convert data back to target endianness, * or bytes will be at the wrong places.So: * 1) read word * 2) convert to target endianness * 3) make changes * 4) convert back to host endianness * 5) write word back to target. */ retval = arc_jtag_read_memory(&arc32->jtag_info, (addr + i * sizeof(uint16_t)) & ~3u, 1, &buffer_he); target_buffer_set_u32(target, buffer_te, buffer_he); /* buf is in host endianness, convert to target */ target_buffer_set_u16(target, halfword_te, ((uint16_t *)buf)[i]); memcpy(buffer_te + ((addr + i * sizeof(uint16_t)) & 3u), halfword_te, sizeof(uint16_t)); buffer_he = target_buffer_get_u32(target, buffer_te); retval = arc_jtag_write_memory(&arc32->jtag_info, (addr + i * sizeof(uint16_t)) & ~3u, 1, &buffer_he); if (ERROR_OK != retval) return retval; } /* Invalidate caches. */ retval = arc32_cache_invalidate(target); return retval; }
int arc_ocd_examine(struct target *target) { uint32_t status; struct arc32_common *arc32 = target_to_arc32(target); LOG_DEBUG("-"); CHECK_RETVAL(arc_jtag_startup(&arc32->jtag_info)); if (!target_was_examined(target)) { /* read ARC core info */ if (strncmp(target_name(target), ARCEM_STR, 6) == 0) { arc32->processor_type = ARCEM_NUM; LOG_USER("Processor type: %s", ARCEM_STR); } else if (strncmp(target_name(target), ARC600_STR, 6) == 0) { arc32->processor_type = ARC600_NUM; LOG_USER("Processor type: %s", ARC600_STR); } else if (strncmp(target_name(target), ARC700_STR, 6) == 0) { arc32->processor_type = ARC700_NUM; LOG_USER("Processor type: %s", ARC700_STR); } else { LOG_WARNING(" THIS IS A UNSUPPORTED TARGET: %s", target_name(target)); } CHECK_RETVAL(arc_jtag_status(&arc32->jtag_info, &status)); if (status & ARC_JTAG_STAT_RU) { target->state = TARGET_RUNNING; } else { /* It is first time we examine the target, it is halted * and we don't know why. Let's set debug reason, * otherwise OpenOCD will complain that reason is * unknown. */ if (target->state == TARGET_UNKNOWN) target->debug_reason = DBG_REASON_DBGRQ; target->state = TARGET_HALTED; } /* Read BCRs and configure optinal registers. */ CHECK_RETVAL(arc_regs_read_bcrs(target)); arc_regs_build_reg_list(target); CHECK_RETVAL(arc32_configure(target)); target_set_examined(target); } return ERROR_OK; }
int arc_ocd_assert_reset(struct target *target) { struct arc32_common *arc32 = target_to_arc32(target); LOG_DEBUG("target->state: %s", target_state_name(target)); enum reset_types jtag_reset_config = jtag_get_reset_config(); if (target_has_event_action(target, TARGET_EVENT_RESET_ASSERT)) { /* allow scripts to override the reset event */ target_handle_event(target, TARGET_EVENT_RESET_ASSERT); register_cache_invalidate(arc32->core_cache); target->state = TARGET_RESET; return ERROR_OK; } /* some cores support connecting while srst is asserted * use that mode is it has been configured */ bool srst_asserted = false; if (!(jtag_reset_config & RESET_SRST_PULLS_TRST) && (jtag_reset_config & RESET_SRST_NO_GATING)) { jtag_add_reset(0, 1); srst_asserted = true; } if (jtag_reset_config & RESET_HAS_SRST) { /* should issue a srst only, but we may have to assert trst as well */ if (jtag_reset_config & RESET_SRST_PULLS_TRST) jtag_add_reset(1, 1); else if (!srst_asserted) jtag_add_reset(0, 1); } target->state = TARGET_RESET; jtag_add_sleep(50000); register_cache_invalidate(arc32->core_cache); if (target->reset_halt) CHECK_RETVAL(target_halt(target)); return ERROR_OK; }
static int arc_mem_read_block(struct target *target, uint32_t addr, uint32_t size, uint32_t count, void *buf) { struct arc32_common *arc32 = target_to_arc32(target); LOG_DEBUG("Read memory: addr=0x%08" PRIx32 ", size=%" PRIu32 ", count=%" PRIu32, addr, size, count); assert(!(addr & 3)); assert(size == 4); /* Always call D$ flush, it will decide whether to perform actual * flush. */ CHECK_RETVAL(arc32_dcache_flush(target)); CHECK_RETVAL(arc_jtag_read_memory(&arc32->jtag_info, addr, count, buf, arc_mem_is_slow_memory(arc32, addr, size, count))); return ERROR_OK; }
/* Write word at word-aligned address */ static int arc_mem_write_block32(struct target *target, uint32_t addr, uint32_t count, void *buf) { struct arc32_common *arc32 = target_to_arc32(target); LOG_DEBUG("Write 4-byte memory block: addr=0x%08" PRIx32 ", count=%" PRIu32, addr, count); /* Check arguments */ assert(!(addr & 3)); /* No need to flush cache, because we don't read values from memory. */ CHECK_RETVAL(arc_jtag_write_memory( &arc32->jtag_info, addr, count, (uint32_t *)buf)); /* Invalidate caches. */ CHECK_RETVAL(arc32_cache_invalidate(target)); return ERROR_OK; }
/* Write word at word-aligned address */ static int arc_mem_write_block32(struct target *target, uint32_t addr, int count, void *buf) { struct arc32_common *arc32 = target_to_arc32(target); int retval = ERROR_OK; /* Check arguments */ if (addr & 0x3u) return ERROR_TARGET_UNALIGNED_ACCESS; /* No need to flush cache, because we don't read values from memory. */ retval = arc_jtag_write_memory( &arc32->jtag_info, addr, count, (uint32_t *)buf); if (ERROR_OK != retval) return retval; /* Invalidate caches. */ retval = arc32_cache_invalidate(target); return retval; }
static int arc_mem_read_block(struct target *target, uint32_t addr, int size, int count, void *buf) { struct arc32_common *arc32 = target_to_arc32(target); int retval = ERROR_OK; LOG_DEBUG("Read memory: addr=0x%" PRIx32 ", size=%i, count=%i", addr, size, count); assert(!(addr & 3)); assert(size == 4); /* Always call D$ flush, it will decide whether to perform actual * flush. */ retval = arc32_dcache_flush(target); if (ERROR_OK != retval) return retval; retval = arc_jtag_read_memory(&arc32->jtag_info, addr, count, buf); return retval; }
/* Write byte at address */ static int arc_mem_write_block8(struct target *target, uint32_t addr, int count, void *buf) { struct arc32_common *arc32 = target_to_arc32(target); int retval = ERROR_OK; int i; /* We will read data from memory, so we need to flush D$. */ retval = arc32_dcache_flush(target); if (ERROR_OK != retval) return retval; uint32_t buffer_he; uint8_t buffer_te[sizeof(uint32_t)]; /* non-word writes are less common, than 4-byte writes, so I suppose we can * allowe ourselves to write this in a cycle, instead of calling arc_jtag * with count > 1. */ for(i = 0; i < count; i++) { /* See comment in arc_mem_write_block16 for details. Since it is a byte * there is not need to convert write buffer to target endianness, but * we still have to convert read buffer. */ retval = arc_jtag_read_memory(&arc32->jtag_info, (addr + i) & ~3, 1, &buffer_he); target_buffer_set_u32(target, buffer_te, buffer_he); memcpy(buffer_te + ((addr + i) & 3), (uint8_t*)buf + i, 1); buffer_he = target_buffer_get_u32(target, buffer_te); retval = arc_jtag_write_memory(&arc32->jtag_info, (addr + i) & ~3, 1, &buffer_he); if (ERROR_OK != retval) return retval; } /* Invalidate caches. */ retval = arc32_cache_invalidate(target); return retval; }