-/* SPDX-License-Identifier: GPL-2.0-or-later */
+// SPDX-License-Identifier: GPL-2.0-or-later
/***************************************************************************
* Generic Xtensa target API for OpenOCD *
uint8_t buf[4];
};
-const struct xtensa_keyval_info_s xt_qerr[XT_QERR_NUM] = {
+static const struct xtensa_keyval_info_s xt_qerr[XT_QERR_NUM] = {
{ .chrval = "E00", .intval = ERROR_FAIL },
{ .chrval = "E01", .intval = ERROR_FAIL },
{ .chrval = "E02", .intval = ERROR_COMMAND_ARGUMENT_INVALID },
static void xtensa_queue_exec_ins_wide(struct xtensa *xtensa, uint8_t *ops, uint8_t oplen)
{
- if ((oplen > 0) && (oplen <= 64)) {
- uint32_t opsw[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; /* 8 DIRx regs: max width 64B */
- uint8_t oplenw = (oplen + 3) / 4;
- if (xtensa->target->endianness == TARGET_BIG_ENDIAN)
- buf_bswap32((uint8_t *)opsw, ops, oplenw * 4);
- else
- memcpy(opsw, ops, oplen);
+ const int max_oplen = 64; /* 8 DIRx regs: max width 64B */
+ if ((oplen > 0) && (oplen <= max_oplen)) {
+ uint8_t ops_padded[max_oplen];
+ memcpy(ops_padded, ops, oplen);
+ memset(ops_padded + oplen, 0, max_oplen - oplen);
+ unsigned int oplenw = DIV_ROUND_UP(oplen, sizeof(uint32_t));
for (int32_t i = oplenw - 1; i > 0; i--)
- xtensa_queue_dbg_reg_write(xtensa, XDMREG_DIR0 + i, opsw[i]);
+ xtensa_queue_dbg_reg_write(xtensa,
+ XDMREG_DIR0 + i,
+ target_buffer_get_u32(xtensa->target, &ops_padded[sizeof(uint32_t)*i]));
/* Write DIR0EXEC last */
- xtensa_queue_dbg_reg_write(xtensa, XDMREG_DIR0EXEC, opsw[0]);
+ xtensa_queue_dbg_reg_write(xtensa,
+ XDMREG_DIR0EXEC,
+ target_buffer_get_u32(xtensa->target, &ops_padded[0]));
}
}
}
/* NOTE: Assumes A3 has already been saved */
-int xtensa_window_state_save(struct target *target, uint32_t *woe)
+static int xtensa_window_state_save(struct target *target, uint32_t *woe)
{
struct xtensa *xtensa = target_to_xtensa(target);
int woe_dis;
}
/* NOTE: Assumes A3 has already been saved */
-void xtensa_window_state_restore(struct target *target, uint32_t woe)
+static void xtensa_window_state_restore(struct target *target, uint32_t woe)
{
struct xtensa *xtensa = target_to_xtensa(target);
if (xtensa->core_config->windowed) {
int xtensa_examine(struct target *target)
{
struct xtensa *xtensa = target_to_xtensa(target);
- unsigned int cmd = PWRCTL_DEBUGWAKEUP | PWRCTL_MEMWAKEUP | PWRCTL_COREWAKEUP;
+ unsigned int cmd = PWRCTL_DEBUGWAKEUP(xtensa) | PWRCTL_MEMWAKEUP(xtensa) | PWRCTL_COREWAKEUP(xtensa);
LOG_DEBUG("coreid = %d", target->coreid);
}
xtensa_queue_pwr_reg_write(xtensa, XDMREG_PWRCTL, cmd);
- xtensa_queue_pwr_reg_write(xtensa, XDMREG_PWRCTL, cmd | PWRCTL_JTAGDEBUGUSE);
+ xtensa_queue_pwr_reg_write(xtensa, XDMREG_PWRCTL, cmd | PWRCTL_JTAGDEBUGUSE(xtensa));
xtensa_dm_queue_enable(&xtensa->dbg_mod);
xtensa_dm_queue_tdi_idle(&xtensa->dbg_mod);
int res = xtensa_dm_queue_execute(&xtensa->dbg_mod);
int xtensa_wakeup(struct target *target)
{
struct xtensa *xtensa = target_to_xtensa(target);
- unsigned int cmd = PWRCTL_DEBUGWAKEUP | PWRCTL_MEMWAKEUP | PWRCTL_COREWAKEUP;
+ unsigned int cmd = PWRCTL_DEBUGWAKEUP(xtensa) | PWRCTL_MEMWAKEUP(xtensa) | PWRCTL_COREWAKEUP(xtensa);
if (xtensa->reset_asserted)
- cmd |= PWRCTL_CORERESET;
+ cmd |= PWRCTL_CORERESET(xtensa);
xtensa_queue_pwr_reg_write(xtensa, XDMREG_PWRCTL, cmd);
/* TODO: can we join this with the write above? */
- xtensa_queue_pwr_reg_write(xtensa, XDMREG_PWRCTL, cmd | PWRCTL_JTAGDEBUGUSE);
+ xtensa_queue_pwr_reg_write(xtensa, XDMREG_PWRCTL, cmd | PWRCTL_JTAGDEBUGUSE(xtensa));
xtensa_dm_queue_tdi_idle(&xtensa->dbg_mod);
return xtensa_dm_queue_execute(&xtensa->dbg_mod);
}
struct xtensa *xtensa = target_to_xtensa(target);
LOG_TARGET_DEBUG(target, "target_number=%i, begin", target->target_number);
- target->state = TARGET_RESET;
xtensa_queue_pwr_reg_write(xtensa,
XDMREG_PWRCTL,
- PWRCTL_JTAGDEBUGUSE | PWRCTL_DEBUGWAKEUP | PWRCTL_MEMWAKEUP |
- PWRCTL_COREWAKEUP | PWRCTL_CORERESET);
+ PWRCTL_JTAGDEBUGUSE(xtensa) | PWRCTL_DEBUGWAKEUP(xtensa) | PWRCTL_MEMWAKEUP(xtensa) |
+ PWRCTL_COREWAKEUP(xtensa) | PWRCTL_CORERESET(xtensa));
xtensa_dm_queue_tdi_idle(&xtensa->dbg_mod);
int res = xtensa_dm_queue_execute(&xtensa->dbg_mod);
if (res != ERROR_OK)
return res;
+
+ /* registers are now invalid */
xtensa->reset_asserted = true;
- return res;
+ register_cache_invalidate(xtensa->core_cache);
+ target->state = TARGET_RESET;
+ return ERROR_OK;
}
int xtensa_deassert_reset(struct target *target)
OCDDCR_ENABLEOCD | OCDDCR_DEBUGINTERRUPT);
xtensa_queue_pwr_reg_write(xtensa,
XDMREG_PWRCTL,
- PWRCTL_JTAGDEBUGUSE | PWRCTL_DEBUGWAKEUP | PWRCTL_MEMWAKEUP |
- PWRCTL_COREWAKEUP);
+ PWRCTL_JTAGDEBUGUSE(xtensa) | PWRCTL_DEBUGWAKEUP(xtensa) | PWRCTL_MEMWAKEUP(xtensa) |
+ PWRCTL_COREWAKEUP(xtensa));
xtensa_dm_queue_tdi_idle(&xtensa->dbg_mod);
int res = xtensa_dm_queue_execute(&xtensa->dbg_mod);
if (res != ERROR_OK)
if (reg_num == XT_PC_REG_NUM_VIRTUAL) {
/* reg number of PC for debug interrupt depends on NDEBUGLEVEL */
reg_num = (XT_PC_REG_NUM_BASE + xtensa->core_config->debug.irq_level);
+ } else if (reg_num == xtensa_regs[XT_REG_IDX_PS].reg_num) {
+ /* reg number of PS for debug interrupt depends on NDEBUGLEVEL */
+ reg_num = (XT_PS_REG_NUM_BASE + xtensa->core_config->debug.irq_level);
} else if (reg_num == xtensa_regs[XT_REG_IDX_CPENABLE].reg_num) {
/* CPENABLE already read/updated; don't re-read */
reg_fetched = false;
target->state = TARGET_RUNNING;
return ERROR_FAIL;
}
- target->debug_reason = DBG_REASON_SINGLESTEP;
- target->state = TARGET_HALTED;
xtensa_fetch_all_regs(target);
-
cur_pc = xtensa_reg_get(target, XT_REG_IDX_PC);
LOG_TARGET_DEBUG(target,
LOG_DEBUG("Stepped from %" PRIX32 " to %" PRIX32, oldpc, cur_pc);
break;
} while (true);
+
+ target->debug_reason = DBG_REASON_SINGLESTEP;
+ target->state = TARGET_HALTED;
+ target_call_event_callbacks(target, TARGET_EVENT_HALTED);
LOG_DEBUG("Done stepping, PC=%" PRIX32, cur_pc);
if (cause & DEBUGCAUSE_DB) {
int xtensa_poll(struct target *target)
{
struct xtensa *xtensa = target_to_xtensa(target);
+ if (xtensa_dm_poll(&xtensa->dbg_mod) != ERROR_OK) {
+ target->state = TARGET_UNKNOWN;
+ return ERROR_TARGET_NOT_EXAMINED;
+ }
- int res = xtensa_dm_power_status_read(&xtensa->dbg_mod, PWRSTAT_DEBUGWASRESET |
- PWRSTAT_COREWASRESET);
+ int res = xtensa_dm_power_status_read(&xtensa->dbg_mod, PWRSTAT_DEBUGWASRESET(xtensa) |
+ PWRSTAT_COREWASRESET(xtensa));
if (xtensa->dbg_mod.power_status.stat != xtensa->dbg_mod.power_status.stath)
LOG_TARGET_DEBUG(target, "PWRSTAT: read 0x%08" PRIx32 ", clear 0x%08lx, reread 0x%08" PRIx32,
xtensa->dbg_mod.power_status.stat,
- PWRSTAT_DEBUGWASRESET | PWRSTAT_COREWASRESET,
+ PWRSTAT_DEBUGWASRESET(xtensa) | PWRSTAT_COREWASRESET(xtensa),
xtensa->dbg_mod.power_status.stath);
if (res != ERROR_OK)
return res;
"DSR has changed: was 0x%08" PRIx32 " now 0x%08" PRIx32,
prev_dsr,
xtensa->dbg_mod.core_status.dsr);
- if (xtensa->dbg_mod.power_status.stath & PWRSTAT_COREWASRESET) {
+ if (xtensa->dbg_mod.power_status.stath & PWRSTAT_COREWASRESET(xtensa)) {
/* if RESET state is persitent */
target->state = TARGET_RESET;
} else if (!xtensa_dm_is_powered(&xtensa->dbg_mod)) {
LOG_ERROR("Failed to clear OCDDCR_ENABLEOCD!");
return;
}
+ xtensa_dm_deinit(&xtensa->dbg_mod);
}
xtensa_free_reg_cache(target);
free(xtensa->hw_brps);
}
/* exe <ascii-encoded hexadecimal instruction bytes> */
-COMMAND_HELPER(xtensa_cmd_exe_do, struct target *target)
+static COMMAND_HELPER(xtensa_cmd_exe_do, struct target *target)
{
struct xtensa *xtensa = target_to_xtensa(target);