Ejemplo n.º 1
0
/* poll current target status */
static int arm11_poll(struct target *target)
{
	int retval;
	struct arm11_common *arm11 = target_to_arm11(target);

	CHECK_RETVAL(arm11_check_init(arm11));

	if (arm11->dscr & DSCR_CORE_HALTED) {
		if (target->state != TARGET_HALTED) {
			enum target_state old_state = target->state;

			LOG_DEBUG("enter TARGET_HALTED");
			retval = arm11_debug_entry(arm11);
			if (retval != ERROR_OK)
				return retval;

			target_call_event_callbacks(target,
				(old_state == TARGET_DEBUG_RUNNING)
				? TARGET_EVENT_DEBUG_HALTED
				: TARGET_EVENT_HALTED);
		}
	} else {
		if (target->state != TARGET_RUNNING && target->state != TARGET_DEBUG_RUNNING) {
			LOG_DEBUG("enter TARGET_RUNNING");
			target->state                   = TARGET_RUNNING;
			target->debug_reason    = DBG_REASON_NOTHALTED;
		}
	}

	return ERROR_OK;
}
Ejemplo n.º 2
0
/* target execution control */
static int arm11_halt(struct target *target)
{
	struct arm11_common *arm11 = target_to_arm11(target);

	LOG_DEBUG("target->state: %s",
		target_state_name(target));

	if (target->state == TARGET_UNKNOWN)
	{
		arm11->simulate_reset_on_next_halt = true;
	}

	if (target->state == TARGET_HALTED)
	{
		LOG_DEBUG("target was already halted");
		return ERROR_OK;
	}

	arm11_add_IR(arm11, ARM11_HALT, TAP_IDLE);

	CHECK_RETVAL(jtag_execute_queue());

	int i = 0;

	while (1)
	{
		CHECK_RETVAL(arm11_read_DSCR(arm11));

		if (arm11->dscr & DSCR_CORE_HALTED)
			break;


		long long then = 0;
		if (i == 1000)
		{
			then = timeval_ms();
		}
		if (i >= 1000)
		{
			if ((timeval_ms()-then) > 1000)
			{
				LOG_WARNING("Timeout (1000ms) waiting for instructions to complete");
				return ERROR_FAIL;
			}
		}
		i++;
	}

	enum target_state old_state	= target->state;

	CHECK_RETVAL(arm11_debug_entry(arm11));

	CHECK_RETVAL(
		target_call_event_callbacks(target,
			old_state == TARGET_DEBUG_RUNNING ? TARGET_EVENT_DEBUG_HALTED : TARGET_EVENT_HALTED));

	return ERROR_OK;
}
Ejemplo n.º 3
0
static int arm11_step(struct target *target, int current,
		uint32_t address, int handle_breakpoints)
{
	LOG_DEBUG("target->state: %s",
		target_state_name(target));

	if (target->state != TARGET_HALTED)
	{
		LOG_WARNING("target was not halted");
		return ERROR_TARGET_NOT_HALTED;
	}

	struct arm11_common *arm11 = target_to_arm11(target);

	address = arm11_nextpc(arm11, current, address);

	LOG_DEBUG("STEP PC %08" PRIx32 "%s", address, !current ? "!" : "");


	/** \todo TODO: Thumb not supported here */

	uint32_t	next_instruction;

	CHECK_RETVAL(arm11_read_memory_word(arm11, address, &next_instruction));

	/* skip over BKPT */
	if ((next_instruction & 0xFFF00070) == 0xe1200070)
	{
		address = arm11_nextpc(arm11, 0, address + 4);
		LOG_DEBUG("Skipping BKPT");
	}
	/* 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);
		LOG_DEBUG("Skipping WFI");
	}
	/* ignore B to self */
	else if ((next_instruction & 0xFEFFFFFF) == 0xeafffffe)
	{
		LOG_DEBUG("Not stepping jump to self");
	}
	else
	{
		/** \todo TODO: check if break-/watchpoints make any sense at all in combination
		* with this. */

		/** \todo TODO: check if disabling IRQs might be a good idea here. Alternatively
		* the VCR might be something worth looking into. */


		/* Set up breakpoint for stepping */

		struct arm11_sc7_action	brp[2];

		brp[0].write	= 1;
		brp[0].address	= ARM11_SC7_BVR0;
		brp[1].write	= 1;
		brp[1].address	= ARM11_SC7_BCR0;

		if (arm11->hardware_step)
		{
			/* Hardware single stepping ("instruction address
			 * mismatch") is used if enabled.  It's not quite
			 * exactly "run one instruction"; "branch to here"
			 * loops won't break, neither will some other cases,
			 * but it's probably the best default.
			 *
			 * Hardware single stepping isn't supported on v6
			 * debug modules.  ARM1176 and v7 can support it...
			 *
			 * FIXME Thumb stepping likely needs to use 0x03
			 * or 0xc0 byte masks, not 0x0f.
			 */
			 brp[0].value	= address;
			 brp[1].value	= 0x1 | (3 << 1) | (0x0F << 5)
					| (0 << 14) | (0 << 16) | (0 << 20)
					| (2 << 21);
		} else
		{
			/* Sets a breakpoint on the next PC, as calculated
			 * by instruction set simulation.
			 *
			 * REVISIT stepping Thumb on ARM1156 requires Thumb2
			 * support from the simulator.
			 */
			uint32_t next_pc;
			int retval;

			retval = arm_simulate_step(target, &next_pc);
			if (retval != ERROR_OK)
				return retval;

			brp[0].value	= next_pc;
			brp[1].value	= 0x1 | (3 << 1) | (0x0F << 5)
					| (0 << 14) | (0 << 16) | (0 << 20)
					| (0 << 21);
		}

		CHECK_RETVAL(arm11_sc7_run(arm11, brp, ARRAY_SIZE(brp)));

		/* resume */


		if (arm11->step_irq_enable)
			/* this disable should be redundant ... */
			arm11->dscr &= ~DSCR_INT_DIS;
		else
			arm11->dscr |= DSCR_INT_DIS;


		CHECK_RETVAL(arm11_leave_debug_state(arm11, handle_breakpoints));

		arm11_add_IR(arm11, ARM11_RESTART, TAP_IDLE);

		CHECK_RETVAL(jtag_execute_queue());

		/* wait for halt */
		int i = 0;

		while (1)
		{
			const uint32_t mask = DSCR_CORE_RESTARTED
					| DSCR_CORE_HALTED;

			CHECK_RETVAL(arm11_read_DSCR(arm11));
			LOG_DEBUG("DSCR %08x e", (unsigned) arm11->dscr);

			if ((arm11->dscr & mask) == mask)
				break;

			long long then = 0;
			if (i == 1000)
			{
				then = timeval_ms();
			}
			if (i >= 1000)
			{
				if ((timeval_ms()-then) > 1000)
				{
					LOG_WARNING("Timeout (1000ms) waiting for instructions to complete");
					return ERROR_FAIL;
				}
			}
			i++;
		}

		/* clear breakpoint */
		CHECK_RETVAL(arm11_sc7_clear_vbw(arm11));

		/* save state */
		CHECK_RETVAL(arm11_debug_entry(arm11));

		/* restore default state */
		arm11->dscr &= ~DSCR_INT_DIS;

	}

	target->debug_reason = DBG_REASON_SINGLESTEP;

	CHECK_RETVAL(target_call_event_callbacks(target, TARGET_EVENT_HALTED));

	return ERROR_OK;
}