Exemple #1
0
/** Set up high-level debug module utilities */
int arm11_dpm_init(struct arm11_common *arm11, uint32_t didr)
{
	struct arm_dpm *dpm = &arm11->dpm;
	int retval;

	dpm->arm = &arm11->arm;

	dpm->didr = didr;

	dpm->prepare = arm11_dpm_prepare;
	dpm->finish = arm11_dpm_finish;

	dpm->instr_write_data_dcc = arm11_dpm_instr_write_data_dcc;
	dpm->instr_write_data_r0 = arm11_dpm_instr_write_data_r0;

	dpm->instr_read_data_dcc = arm11_dpm_instr_read_data_dcc;
	dpm->instr_read_data_r0 = arm11_dpm_instr_read_data_r0;

	dpm->bpwp_enable = arm11_bpwp_enable;
	dpm->bpwp_disable = arm11_bpwp_disable;

	retval = arm_dpm_setup(dpm);
	if (retval != ERROR_OK)
		return retval;

	/* alloc enough to enable all breakpoints and watchpoints at once */
	arm11->bpwp_actions = calloc(2 * (dpm->nbp + dpm->nwp),
			sizeof *arm11->bpwp_actions);
	if (!arm11->bpwp_actions)
		return ERROR_FAIL;

	retval = arm_dpm_initialize(dpm);
	if (retval != ERROR_OK)
		return retval;

	return arm11_bpwp_flush(arm11);
}
Exemple #2
0
/**
 * Restore processor state.  This is called in preparation for
 * the RESTART function.
 */
static int arm11_leave_debug_state(struct arm11_common *arm11, bool bpwp)
{
	int retval;

	/* See e.g. ARM1136 TRM, "14.8.5 Leaving Debug state" */

	/* NOTE:  the ARM1136 TRM suggests restoring all registers
	 * except R0/PC/CPSR right now.  Instead, we do them all
	 * at once, just a bit later on.
	 */

	/* REVISIT once we start caring about MMU and cache state,
	 * address it here ...
	 */

	/* spec says clear wDTR and rDTR; we assume they are clear as
	   otherwise our programming would be sloppy */
	{
		CHECK_RETVAL(arm11_read_DSCR(arm11));

		if (arm11->dscr & (DSCR_DTR_RX_FULL | DSCR_DTR_TX_FULL))
		{
			/*
			The wDTR/rDTR two registers that are used to send/receive data to/from
			the core in tandem with corresponding instruction codes that are
			written into the core. The RDTR FULL/WDTR FULL flag indicates that the
			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);
			return ERROR_FAIL;
		}
	}

	/* maybe restore original wDTR */
	if (arm11->is_wdtr_saved)
	{
		retval = arm11_run_instr_data_prepare(arm11);
		if (retval != ERROR_OK)
			return retval;

		/* MCR p14,0,R0,c0,c5,0 */
		retval = arm11_run_instr_data_to_core_via_r0(arm11,
				0xee000e15, arm11->saved_wdtr);
		if (retval != ERROR_OK)
			return retval;

		retval = arm11_run_instr_data_finish(arm11);
		if (retval != ERROR_OK)
			return retval;
	}

	/* restore CPSR, PC, and R0 ... after flushing any modified
	 * registers.
	 */
	CHECK_RETVAL(arm_dpm_write_dirty_registers(&arm11->dpm, bpwp));

	CHECK_RETVAL(arm11_bpwp_flush(arm11));

	register_cache_invalidate(arm11->arm.core_cache);

	/* restore DSCR */
	CHECK_RETVAL(arm11_write_DSCR(arm11, arm11->dscr));

	/* maybe restore rDTR */
	if (arm11->is_rdtr_saved)
	{
		arm11_add_debug_SCAN_N(arm11, 0x05, ARM11_TAP_DEFAULT);

		arm11_add_IR(arm11, ARM11_EXTEST, ARM11_TAP_DEFAULT);

		struct scan_field	chain5_fields[3];

		uint8_t			Ready		= 0;	/* ignored */
		uint8_t			Valid		= 0;	/* ignored */

		arm11_setup_field(arm11, 32, &arm11->saved_rdtr,
				NULL, chain5_fields + 0);
		arm11_setup_field(arm11,  1, &Ready,	NULL, chain5_fields + 1);
		arm11_setup_field(arm11,  1, &Valid,	NULL, chain5_fields + 2);

		arm11_add_dr_scan_vc(arm11->arm.target->tap, ARRAY_SIZE(chain5_fields), chain5_fields, TAP_DRPAUSE);
	}

	/* now processor is ready to RESTART */

	return ERROR_OK;
}