Beispiel #1
0
/* Code must return to the server loop before 1000ms has returned or invoke
 * this function.
 *
 * The GDB connection will time out if it spends >2000ms and you'll get nasty
 * error messages from GDB:
 *
 * Ignoring packet error, continuing...
 * Reply contains invalid hex digit 116
 *
 * While it is possible use "set remotetimeout" to more than the default 2000ms
 * in GDB, OpenOCD guarantees that it sends keep-alive packages on the
 * GDB protocol and it is a bug in OpenOCD not to either return to the server
 * loop or invoke keep_alive() every 1000ms.
 *
 * This function will send a keep alive packet if >500ms has passed since last time
 * it was invoked.
 *
 * Note that this function can be invoked often, so it needs to be relatively
 * fast when invoked more often than every 500ms.
 *
 */
void keep_alive()
{
	current_time = timeval_ms();
	if (current_time-last_time > 1000) {
		extern int gdb_actual_connections;

		if (gdb_actual_connections)
			LOG_WARNING("keep_alive() was not invoked in the "
				"1000ms timelimit. GDB alive packet not "
				"sent! (%" PRId64 "). Workaround: increase "
				"\"set remotetimeout\" in GDB",
				current_time-last_time);
		else
			LOG_DEBUG("keep_alive() was not invoked in the "
				"1000ms timelimit (%" PRId64 "). This may cause "
				"trouble with GDB connections.",
				current_time-last_time);
	}
	if (current_time-last_time > 500) {
		/* this will keep the GDB connection alive */
		LOG_USER_N("%s", "");

		/* DANGER!!!! do not add code to invoke e.g. target event processing,
		 * jim timer processing, etc. it can cause infinite recursion +
		 * jim event callbacks need to happen at a well defined time,
		 * not anywhere keep_alive() is invoked.
		 *
		 * These functions should be invoked at a well defined spot in server.c
		 */

		last_time = current_time;
	}
}
Beispiel #2
0
/* timeout in ms */
static int poll_tff(struct target *target, uint32_t io_base, int timeout)
{
	long long endtime;

	if (SMI_READ_REG(SMI_SR) & SMI_TFF)
		return ERROR_OK;

	endtime = timeval_ms() + timeout;
	do {
		alive_sleep(1);
		if (SMI_READ_REG(SMI_SR) & SMI_TFF)
			return ERROR_OK;
	} while (timeval_ms() < endtime);

	LOG_ERROR("Timeout while polling TFF");
	return ERROR_FLASH_OPERATION_FAILED;
}
Beispiel #3
0
/* wait up to timeout_ms for controller to not be busy,
 * then check whether the command passed or failed.
 *
 * this function sleeps 1ms between checks (after the first one),
 * so in some cases may slow things down without a usleep after the first read */
static int aduc702x_check_flash_completion(struct target* target, unsigned int timeout_ms)
{
        uint8_t v = 4;

        long long endtime = timeval_ms() + timeout_ms;
        while (1) {
                target_read_u8(target, ADUC702x_FLASH + ADUC702x_FLASH_FEESTA, &v);
                if ((v & 4) == 0) break;
                alive_sleep(1);
                if (timeval_ms() >= endtime) break;
        }

        if (v & 2) return ERROR_FAIL;
        // if a command is ignored, both the success and fail bits may be 0
        else if ((v & 3) == 0) return ERROR_FAIL;
        else return ERROR_OK;
}
Beispiel #4
0
static int jtagspi_wait(struct flash_bank *bank, int timeout_ms)
{
	uint32_t status;
	int64_t t0 = timeval_ms();
	int64_t dt;

	do {
		dt = timeval_ms() - t0;
		jtagspi_read_status(bank, &status);
		if ((status & SPIFLASH_BSY_BIT) == 0) {
			LOG_DEBUG("waited %" PRId64 " ms", dt);
			return ERROR_OK;
		}
		alive_sleep(1);
	} while (dt <= timeout_ms);

	LOG_ERROR("timeout, device still busy");
	return ERROR_FAIL;
}
Beispiel #5
0
/**
 * Execute one or more instructions via ITR.
 * Caller guarantees that processor is in debug state, that DSCR_ITR_EN
 * is set, the ITR Ready flag is set (as seen on the previous entry to
 * TAP_DRCAPTURE), and the DSCR sticky abort flag is clear.
 *
 * \pre arm11_run_instr_data_prepare() /  arm11_run_instr_data_finish() block
 *
 * \param arm11		Target state variable.
 * \param opcode	Pointer to sequence of ARM opcodes
 * \param count		Number of opcodes to execute
 *
 */
static
int arm11_run_instr_no_data(struct arm11_common * arm11,
		uint32_t * opcode, size_t count)
{
	arm11_add_IR(arm11, ARM11_ITRSEL, ARM11_TAP_DEFAULT);

	while (count--)
	{
		arm11_add_debug_INST(arm11, *opcode++, NULL, TAP_IDLE);

		int i = 0;
		while (1)
		{
			uint8_t flag;

			arm11_add_debug_INST(arm11, 0, &flag, count ? TAP_IDLE : TAP_DRPAUSE);

			CHECK_RETVAL(jtag_execute_queue());

			if (flag)
				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++;
		}
	}

	return ERROR_OK;
}
Beispiel #6
0
static int msp432_wait_inactive(struct target *target, uint32_t buffer)
{
	uint32_t status_code = BUFFER_ACTIVE;
	uint32_t status_addr;
	long long start_ms;
	long long elapsed_ms;

	int retval;

	switch (buffer) {
		case 1: /* Buffer 1 */
			status_addr = ALGO_BUFFER1_STATUS_ADDR;
			break;
		case 2: /* Buffer 2 */
			status_addr = ALGO_BUFFER2_STATUS_ADDR;
			break;
		default:
			return ERROR_FAIL;
	}

	start_ms = timeval_ms();
	while (BUFFER_INACTIVE != status_code) {
		retval = target_read_buffer(target, status_addr, sizeof(status_code),
					(uint8_t *)&status_code);
		if (ERROR_OK != retval)
			return retval;

		elapsed_ms = timeval_ms() - start_ms;
		if (elapsed_ms > 500)
			keep_alive();
		if (elapsed_ms > FLASH_TIMEOUT)
			break;
	};

	if (BUFFER_INACTIVE != status_code) {
		LOG_ERROR(
			"msp432: Flash operation failed: buffer not written to flash");
		return ERROR_FAIL;
	}

	return ERROR_OK;
}
Beispiel #7
0
/* timeout in ms */
static int wait_till_ready(struct flash_bank *bank, int timeout)
{
	uint32_t status;
	int retval;
	long long endtime;

	endtime = timeval_ms() + timeout;
	do {
		/* read flash status register */
		retval = read_status_reg(bank, &status);
		if (retval != ERROR_OK)
			return retval;

		if ((status & SPIFLASH_BSY_BIT) == 0)
			return ERROR_OK;
		alive_sleep(1);
	} while (timeval_ms() < endtime);

	LOG_ERROR("timeout");
	return ERROR_FAIL;
}
Beispiel #8
0
/* The log_puts() serves two somewhat different goals:
 *
 * - logging
 * - feeding low-level info to the user in GDB or Telnet
 *
 * The latter dictates that strings without newline are not logged, lest there
 * will be *MANY log lines when sending one char at the time(e.g.
 * target_request.c).
 *
 */
static void log_puts(enum log_levels level,
	const char *file,
	int line,
	const char *function,
	const char *string)
{
	char *f;
	if (level == LOG_LVL_OUTPUT) {
		/* do not prepend any headers, just print out what we were given and return */
		fputs(string, log_output);
		fflush(log_output);
		return;
	}

	f = strrchr(file, '/');
	if (f != NULL)
		file = f + 1;

	if (strlen(string) > 0) {
		if (debug_level >= LOG_LVL_DEBUG) {
			/* print with count and time information */
			int64_t t = timeval_ms() - start;
#ifdef _DEBUG_FREE_SPACE_
			struct mallinfo info;
			info = mallinfo();
#endif
			fprintf(log_output, "%s%d %" PRId64 " %s:%d %s()"
#ifdef _DEBUG_FREE_SPACE_
				" %d"
#endif
				": %s", log_strings[level + 1], count, t, file, line, function,
#ifdef _DEBUG_FREE_SPACE_
				info.fordblks,
#endif
				string);
		} else {
			/* if we are using gdb through pipes then we do not want any output
			 * to the pipe otherwise we get repeated strings */
			fprintf(log_output, "%s%s",
				(level > LOG_LVL_USER) ? log_strings[level + 1] : "", string);
		}
	} else {
		/* Empty strings are sent to log callbacks to keep e.g. gdbserver alive, here we do
		 *nothing. */
	}

	fflush(log_output);

	/* Never forward LOG_LVL_DEBUG, too verbose and they can be found in the log if need be */
	if (level <= LOG_LVL_INFO)
		log_forward(file, line, function, string);
}
Beispiel #9
0
static int nrf5_wait_for_nvmc(struct nrf5_info *chip)
{
	uint32_t ready;
	int res;
	int timeout_ms = 340;
	int64_t ts_start = timeval_ms();

	do {
		res = target_read_u32(chip->target, NRF5_NVMC_READY, &ready);
		if (res != ERROR_OK) {
			LOG_ERROR("Couldn't read NVMC_READY register");
			return res;
		}

		if (ready == 0x00000001)
			return ERROR_OK;

		keep_alive();

	} while ((timeval_ms()-ts_start) < timeout_ms);

	LOG_DEBUG("Timed out waiting for NVMC_READY");
	return ERROR_FLASH_BUSY;
}
Beispiel #10
0
static int wait_for_pracc_rw(struct mips_ejtag *ejtag_info, uint32_t *ctrl)
{
	uint32_t ejtag_ctrl;
	long long then = timeval_ms();
	int timeout;

	/* wait for the PrAcc to become "1" */
	mips_ejtag_set_instr(ejtag_info, EJTAG_INST_CONTROL);
	ejtag_ctrl = ejtag_info->ejtag_ctrl;

	int retval;
	if ((retval = jtag_execute_queue()) != ERROR_OK)
	{
		LOG_ERROR("fastdata load failed");
		return retval;
	}

	while (1)
	{
		retval = mips_ejtag_drscan_32(ejtag_info, &ejtag_ctrl);
		if (retval != ERROR_OK)
			return retval;

		if (ejtag_ctrl & EJTAG_CTRL_PRACC)
			break;

		if ( (timeout = timeval_ms()-then) > 1000 )
		{
			LOG_DEBUG("DEBUGMODULE: No memory access in progress!");
			return ERROR_JTAG_DEVICE_ERROR;
		}
	}

	*ctrl = ejtag_ctrl;
	return ERROR_OK;
}
Beispiel #11
0
void log_init(void)
{
	/* set defaults for daemon configuration,
	 * if not set by cmdline or cfgfile */
	if (debug_level == -1)
		debug_level = LOG_LVL_INFO;

	char *debug_env = getenv("OPENOCD_DEBUG_LEVEL");
	if (NULL != debug_env) {
		int value;
		int retval = parse_int(debug_env, &value);
		if (ERROR_OK == retval &&
				debug_level >= LOG_LVL_SILENT &&
				debug_level <= LOG_LVL_DEBUG_IO)
				debug_level = value;
	}

	if (log_output == NULL)
		log_output = stderr;

	start = last_time = timeval_ms();
}
Beispiel #12
0
/* reset keep alive timer without sending message */
void kept_alive()
{
	current_time = timeval_ms();
	last_time = current_time;
}
Beispiel #13
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;
}
Beispiel #14
0
static int arm11_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",
	//	current, address, handle_breakpoints, debug_execution);

	struct arm11_common *arm11 = target_to_arm11(target);

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


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

	address = arm11_nextpc(arm11, current, address);

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

	/* clear breakpoints/watchpoints and VCR*/
	CHECK_RETVAL(arm11_sc7_clear_vbw(arm11));

	if (!debug_execution)
		target_free_all_working_areas(target);

	/* Should we skip over breakpoints matching the PC? */
	if (handle_breakpoints) {
		struct breakpoint *bp;

		for (bp = target->breakpoints; bp; bp = bp->next)
		{
			if (bp->address == address)
			{
				LOG_DEBUG("must step over %08" PRIx32 "", bp->address);
				arm11_step(target, 1, 0, 0);
				break;
			}
		}
	}

	/* activate all breakpoints */
	if (true) {
		struct breakpoint *bp;
		unsigned brp_num = 0;

		for (bp = target->breakpoints; bp; bp = bp->next)
		{
			struct arm11_sc7_action	brp[2];

			brp[0].write	= 1;
			brp[0].address	= ARM11_SC7_BVR0 + brp_num;
			brp[0].value	= bp->address;
			brp[1].write	= 1;
			brp[1].address	= ARM11_SC7_BCR0 + brp_num;
			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)));

			LOG_DEBUG("Add BP %d at %08" PRIx32, brp_num,
					bp->address);

			brp_num++;
		}

		if (arm11->vcr)
			CHECK_RETVAL(arm11_sc7_set_vcr(arm11, arm11->vcr));
	}

	/* activate all watchpoints and breakpoints */
	CHECK_RETVAL(arm11_leave_debug_state(arm11, true));

	arm11_add_IR(arm11, ARM11_RESTART, TAP_IDLE);

	CHECK_RETVAL(jtag_execute_queue());

	int i = 0;
	while (1)
	{
		CHECK_RETVAL(arm11_read_DSCR(arm11));

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

		if (arm11->dscr & DSCR_CORE_RESTARTED)
			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++;
	}

	target->debug_reason = DBG_REASON_NOTHALTED;
	if (!debug_execution)
		target->state = TARGET_RUNNING;
	else
		target->state = TARGET_DEBUG_RUNNING;
	CHECK_RETVAL(target_call_event_callbacks(target, TARGET_EVENT_RESUMED));

	return ERROR_OK;
}
Beispiel #15
0
static int jtagdp_transaction_endcheck(struct adiv5_dap *dap)
{
	int retval;
	uint32_t ctrlstat;

	/* too expensive to call keep_alive() here */

	/* Here be dragons!
	 *
	 * It is easy to be in a JTAG clock range where the target
	 * is not operating in a stable fashion. This happens
	 * for a few reasons:
	 *
	 * - the user may construct a simple test case to try to see
	 * if a higher JTAG clock works to eke out more performance.
	 * This simple case may pass, but more complex situations can
	 * fail.
	 *
	 * - The mostly works JTAG clock rate and the complete failure
	 * JTAG clock rate may be as much as 2-4x apart. This seems
	 * to be especially true on RC oscillator driven parts.
	 *
	 * So: even if calling adi_jtag_scan_inout_check_u32() multiple
	 * times here seems to "make things better here", it is just
	 * hiding problems with too high a JTAG clock.
	 *
	 * Note that even if some parts have RCLK/RTCK, that doesn't
	 * mean that RCLK/RTCK is the *correct* rate to run the JTAG
	 * interface at, i.e. RCLK/RTCK rates can be "too high", especially
	 * before the RC oscillator phase is not yet complete.
	 */

	/* Post CTRL/STAT read; discard any previous posted read value
	 * but collect its ACK status.
	 */
	retval = adi_jtag_scan_inout_check_u32(dap, JTAG_DP_DPACC,
			DP_CTRL_STAT, DPAP_READ, 0, &ctrlstat, 0);
	if (retval != ERROR_OK)
		return retval;
	retval = jtag_execute_queue();
	if (retval != ERROR_OK)
		return retval;

	dap->ack = dap->ack & 0x7;

	/* common code path avoids calling timeval_ms() */
	if (dap->ack != JTAG_ACK_OK_FAULT) {
		long long then = timeval_ms();

		while (dap->ack != JTAG_ACK_OK_FAULT) {
			if (dap->ack == JTAG_ACK_WAIT) {
				if ((timeval_ms()-then) > 1000) {
					LOG_WARNING("Timeout (1000ms) waiting "
						"for ACK=OK/FAULT "
						"in JTAG-DP transaction - aborting");

					uint8_t ack;
					int abort_ret = jtag_ap_q_abort(dap, &ack);

					if (abort_ret != 0)
						LOG_WARNING("Abort failed : return=%d ack=%d", abort_ret, ack);

					return ERROR_JTAG_DEVICE_ERROR;
				}
			} else {
				LOG_WARNING("Invalid ACK %#x "
						"in JTAG-DP transaction",
						dap->ack);
				return ERROR_JTAG_DEVICE_ERROR;
			}

			retval = adi_jtag_scan_inout_check_u32(dap, JTAG_DP_DPACC,
					DP_CTRL_STAT, DPAP_READ, 0, &ctrlstat, 0);
			if (retval != ERROR_OK)
				return retval;
			retval = jtag_execute_queue();
			if (retval != ERROR_OK)
				return retval;
			dap->ack = dap->ack & 0x7;
		}
	}

	/* REVISIT also STICKYCMP, for pushed comparisons (nyet used) */

	/* Check for STICKYERR and STICKYORUN */
	if (ctrlstat & (SSTICKYORUN | SSTICKYERR)) {
		LOG_DEBUG("jtag-dp: CTRL/STAT error, 0x%" PRIx32, ctrlstat);
		/* Check power to debug regions */
		if ((ctrlstat & (CDBGPWRUPREQ | CDBGPWRUPACK | CSYSPWRUPREQ | CSYSPWRUPACK)) !=
						(CDBGPWRUPREQ | CDBGPWRUPACK | CSYSPWRUPREQ | CSYSPWRUPACK)) {
			LOG_ERROR("Debug regions are unpowered, an unexpected reset might have happened");
			return ERROR_JTAG_DEVICE_ERROR;
		} else {
			if (ctrlstat & SSTICKYORUN)
				LOG_ERROR("JTAG-DP OVERRUN - check clock, "
					"memaccess, or reduce jtag speed");

			if (ctrlstat & SSTICKYERR)
				LOG_ERROR("JTAG-DP STICKY ERROR");

			/* Clear Sticky Error Bits */
			retval = adi_jtag_scan_inout_check_u32(dap, JTAG_DP_DPACC,
					DP_CTRL_STAT, DPAP_WRITE,
					dap->dp_ctrl_stat | SSTICKYORUN
						| SSTICKYERR, NULL, 0);
			if (retval != ERROR_OK)
				return retval;
			retval = adi_jtag_scan_inout_check_u32(dap, JTAG_DP_DPACC,
					DP_CTRL_STAT, DPAP_READ, 0, &ctrlstat, 0);
			if (retval != ERROR_OK)
				return retval;
			retval = jtag_execute_queue();
			if (retval != ERROR_OK)
				return retval;

			LOG_DEBUG("jtag-dp: CTRL/STAT 0x%" PRIx32, ctrlstat);
		}
		retval = jtag_execute_queue();
		if (retval != ERROR_OK)
			return retval;
		return ERROR_JTAG_DEVICE_ERROR;
	}

	return ERROR_OK;
}
Beispiel #16
0
static int arm926ejs_cp15_read(struct target *target, uint32_t op1, uint32_t op2,
		uint32_t CRn, uint32_t CRm, uint32_t *value)
{
	int retval = ERROR_OK;
	struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
	struct arm_jtag *jtag_info = &arm7_9->jtag_info;
	uint32_t address = ARM926EJS_CP15_ADDR(op1, op2, CRn, CRm);
	struct scan_field fields[4];
	uint8_t address_buf[2] = {0, 0};
	uint8_t nr_w_buf = 0;
	uint8_t access_t = 1;

	buf_set_u32(address_buf, 0, 14, address);

	retval = arm_jtag_scann(jtag_info, 0xf, TAP_IDLE);
	if (retval != ERROR_OK)
		return retval;
	retval = arm_jtag_set_instr(jtag_info->tap, jtag_info->intest_instr, NULL, TAP_IDLE);
	if (retval != ERROR_OK)
		return retval;

	fields[0].num_bits = 32;
	fields[0].out_value = NULL;
	fields[0].in_value = (uint8_t *)value;

	fields[1].num_bits = 1;
	fields[1].out_value = &access_t;
	fields[1].in_value = &access_t;

	fields[2].num_bits = 14;
	fields[2].out_value = address_buf;
	fields[2].in_value = NULL;

	fields[3].num_bits = 1;
	fields[3].out_value = &nr_w_buf;
	fields[3].in_value = NULL;

	jtag_add_dr_scan(jtag_info->tap, 4, fields, TAP_IDLE);

	int64_t then = timeval_ms();

	for (;;) {
		/* rescan with NOP, to wait for the access to complete */
		access_t = 0;
		nr_w_buf = 0;
		jtag_add_dr_scan(jtag_info->tap, 4, fields, TAP_IDLE);

		jtag_add_callback(arm_le_to_h_u32, (jtag_callback_data_t)value);

		retval = jtag_execute_queue();
		if (retval != ERROR_OK)
			return retval;

		if (buf_get_u32(&access_t, 0, 1) == 1)
			break;

		/* 10ms timeout */
		if ((timeval_ms()-then) > 10) {
			LOG_ERROR("cp15 read operation timed out");
			return ERROR_FAIL;
		}
	}

#ifdef _DEBUG_INSTRUCTION_EXECUTION_
	LOG_DEBUG("addr: 0x%x value: %8.8x", address, *value);
#endif

	retval = arm_jtag_set_instr(jtag_info->tap, 0xc, NULL, TAP_IDLE);
	if (retval != ERROR_OK)
		return retval;

	return ERROR_OK;
}
Beispiel #17
0
static int msp432_write(struct flash_bank *bank, const uint8_t *buffer,
	uint32_t offset, uint32_t count)
{
	struct target *target = bank->target;
	struct msp432_bank *msp432_bank = bank->driver_priv;
	struct msp432_algo_params algo_params;
	uint32_t size;
	uint32_t data_ready = BUFFER_DATA_READY;
	long long start_ms;
	long long elapsed_ms;

	int retval;

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

	/*
	 * Block attempts to write to read-only sectors of flash
	 * The TVL region in sector 1 of the info flash is always read-only
	 * The BSL region in sectors 2 and 3 of the info flash may be unlocked
	 * The helper algorithm will hang on attempts to write to TVL
	 */
	if (1 == bank->bank_number) {
		/* Set read-only start to TVL sector */
		uint32_t start = 0x1000;
		/* Set read-only end after BSL region if locked */
		uint32_t end = (msp432_bank->unlock_bsl) ? 0x2000 : 0x4000;
		/* Check if request includes anything in read-only sectors */
		if ((offset + count - 1) < start || offset >= end) {
			/* The request includes no bytes in read-only sectors */
			/* Fall out and process the request normally */
		} else {
			/* Send a request for anything before read-only sectors */
			if (offset < start) {
				uint32_t start_count = MIN(start - offset, count);
				retval = msp432_write(bank, buffer, offset, start_count);
				if (ERROR_OK != retval)
					return retval;
			}
			/* Send a request for anything after read-only sectors */
			if ((offset + count - 1) >= end) {
				uint32_t skip = end - offset;
				count -= skip;
				offset += skip;
				buffer += skip;
				return msp432_write(bank, buffer, offset, count);
			} else {
				/* Request is entirely in read-only sectors */
				return ERROR_OK;
			}
		}
	}

	retval = msp432_init(bank);
	if (ERROR_OK != retval)
		return retval;

	/* Initialize algorithm parameters to default values */
	msp432_init_params(&algo_params);

	/* Set up parameters for requested flash write operation */
	buf_set_u32(algo_params.address, 0, 32, bank->base + offset);
	buf_set_u32(algo_params.length, 0, 32, count);

	/* Check if this is the info bank */
	if (1 == bank->bank_number) {
		/* And flag if BSL is unlocked */
		if (msp432_bank->unlock_bsl)
			buf_set_u32(algo_params.unlock_bsl, 0, 32, FLASH_UNLOCK_BSL);
	}

	/* Set up flash helper algorithm to continuous flash mode */
	retval = msp432_exec_cmd(target, &algo_params, FLASH_CONTINUOUS);
	if (ERROR_OK != retval) {
		(void)msp432_quit(bank);
		return retval;
	}

	/* Write requested data, one buffer at a time */
	start_ms = timeval_ms();
	while (count > 0) {

		if (count > ALGO_BUFFER_SIZE)
			size = ALGO_BUFFER_SIZE;
		else
			size = count;

		/* Put next block of data to flash into buffer */
		retval = target_write_buffer(target, ALGO_BUFFER1_ADDR, size, buffer);
		if (ERROR_OK != retval) {
			LOG_ERROR("Unable to write data to target memory");
			(void)msp432_quit(bank);
			return ERROR_FLASH_OPERATION_FAILED;
		}

		/* Signal the flash helper algorithm that data is ready to flash */
		retval = target_write_buffer(target, ALGO_BUFFER1_STATUS_ADDR,
					sizeof(data_ready), (uint8_t *)&data_ready);
		if (ERROR_OK != retval) {
			(void)msp432_quit(bank);
			return ERROR_FLASH_OPERATION_FAILED;
		}

		retval = msp432_wait_inactive(target, 1);
		if (ERROR_OK != retval) {
			(void)msp432_quit(bank);
			return retval;
		}

		count -= size;
		buffer += size;

		elapsed_ms = timeval_ms() - start_ms;
		if (elapsed_ms > 500)
			keep_alive();
	}

	/* Confirm that the flash helper algorithm is finished */
	retval = msp432_wait_return_code(target);
	if (ERROR_OK != retval) {
		(void)msp432_quit(bank);
		return retval;
	}

	retval = msp432_quit(bank);
	if (ERROR_OK != retval)
		return retval;

	return retval;
}
Beispiel #18
0
static int jtagdp_transaction_endcheck(struct adiv5_dap *dap)
{
	int retval;
	uint32_t ctrlstat;

	/* too expensive to call keep_alive() here */

	/* Here be dragons!
	 *
	 * It is easy to be in a JTAG clock range where the target
	 * is not operating in a stable fashion. This happens
	 * for a few reasons:
	 *
	 * - the user may construct a simple test case to try to see
	 * if a higher JTAG clock works to eke out more performance.
	 * This simple case may pass, but more complex situations can
	 * fail.
	 *
	 * - The mostly works JTAG clock rate and the complete failure
	 * JTAG clock rate may be as much as 2-4x apart. This seems
	 * to be especially true on RC oscillator driven parts.
	 *
	 * So: even if calling adi_jtag_scan_inout_check_u32() multiple
	 * times here seems to "make things better here", it is just
	 * hiding problems with too high a JTAG clock.
	 *
	 * Note that even if some parts have RCLK/RTCK, that doesn't
	 * mean that RCLK/RTCK is the *correct* rate to run the JTAG
	 * interface at, i.e. RCLK/RTCK rates can be "too high", especially
	 * before the RC oscillator phase is not yet complete.
	 */

	/* Post CTRL/STAT read; discard any previous posted read value
	 * but collect its ACK status.
	 */
	retval = adi_jtag_scan_inout_check_u32(dap, JTAG_DP_DPACC,
			DP_CTRL_STAT, DPAP_READ, 0, &ctrlstat);
	if (retval != ERROR_OK)
		return retval;
	retval = jtag_execute_queue();
	if (retval != ERROR_OK)
		return retval;

	dap->ack = dap->ack & 0x7;

	/* common code path avoids calling timeval_ms() */
	if (dap->ack != JTAG_ACK_OK_FAULT) {
		long long then = timeval_ms();

		while (dap->ack != JTAG_ACK_OK_FAULT) {
			if (dap->ack == JTAG_ACK_WAIT) {
				if ((timeval_ms()-then) > 1000) {
					/* NOTE:  this would be a good spot
					 * to use JTAG_DP_ABORT.
					 */
					LOG_WARNING("Timeout (1000ms) waiting "
						"for ACK=OK/FAULT "
						"in JTAG-DP transaction");
					return ERROR_JTAG_DEVICE_ERROR;
				}
			} else {
				LOG_WARNING("Invalid ACK %#x "
						"in JTAG-DP transaction",
						dap->ack);
				return ERROR_JTAG_DEVICE_ERROR;
			}

			retval = adi_jtag_scan_inout_check_u32(dap, JTAG_DP_DPACC,
					DP_CTRL_STAT, DPAP_READ, 0, &ctrlstat);
			if (retval != ERROR_OK)
				return retval;
			retval = jtag_execute_queue();
			if (retval != ERROR_OK)
				return retval;
			dap->ack = dap->ack & 0x7;
		}
	}

	/* REVISIT also STICKYCMP, for pushed comparisons (nyet used) */

	/* Check for STICKYERR and STICKYORUN */
	if (ctrlstat & (SSTICKYORUN | SSTICKYERR)) {
		LOG_DEBUG("jtag-dp: CTRL/STAT error, 0x%" PRIx32, ctrlstat);
		/* Check power to debug regions */
		if ((ctrlstat & 0xf0000000) != 0xf0000000) {
			retval = ahbap_debugport_init(dap);
			if (retval != ERROR_OK)
				return retval;
		} else {
			uint32_t mem_ap_csw, mem_ap_tar;

			/* Maybe print information about last intended
			 * MEM-AP access; but not if autoincrementing.
			 * *Real* CSW and TAR values are always shown.
			 */
			if (dap->ap_tar_value != (uint32_t) -1)
				LOG_DEBUG("MEM-AP Cached values: "
					"ap_bank 0x%" PRIx32
					", ap_csw 0x%" PRIx32
					", ap_tar 0x%" PRIx32,
					dap->ap_bank_value,
					dap->ap_csw_value,
					dap->ap_tar_value);

			if (ctrlstat & SSTICKYORUN)
				LOG_ERROR("JTAG-DP OVERRUN - check clock, "
					"memaccess, or reduce jtag speed");

			if (ctrlstat & SSTICKYERR)
				LOG_ERROR("JTAG-DP STICKY ERROR");

			/* Clear Sticky Error Bits */
			retval = adi_jtag_scan_inout_check_u32(dap, JTAG_DP_DPACC,
					DP_CTRL_STAT, DPAP_WRITE,
					dap->dp_ctrl_stat | SSTICKYORUN
						| SSTICKYERR, NULL);
			if (retval != ERROR_OK)
				return retval;
			retval = adi_jtag_scan_inout_check_u32(dap, JTAG_DP_DPACC,
					DP_CTRL_STAT, DPAP_READ, 0, &ctrlstat);
			if (retval != ERROR_OK)
				return retval;
			retval = jtag_execute_queue();
			if (retval != ERROR_OK)
				return retval;

			LOG_DEBUG("jtag-dp: CTRL/STAT 0x%" PRIx32, ctrlstat);

			retval = dap_queue_ap_read(dap,
					AP_REG_CSW, &mem_ap_csw);
			if (retval != ERROR_OK)
				return retval;

			retval = dap_queue_ap_read(dap,
					AP_REG_TAR, &mem_ap_tar);
			if (retval != ERROR_OK)
				return retval;

			retval = jtag_execute_queue();
			if (retval != ERROR_OK)
				return retval;
			LOG_ERROR("MEM_AP_CSW 0x%" PRIx32 ", MEM_AP_TAR 0x%"
					PRIx32, mem_ap_csw, mem_ap_tar);

		}
		retval = jtag_execute_queue();
		if (retval != ERROR_OK)
			return retval;
		return ERROR_JTAG_DEVICE_ERROR;
	}

	return ERROR_OK;
}
Beispiel #19
0
/** Execute one instruction via ITR repeatedly while
 *  passing data to the core via DTR on each execution.
 *
 * Caller guarantees that processor is in debug state, that DSCR_ITR_EN
 * is set, the ITR Ready flag is set (as seen on the previous entry to
 * TAP_DRCAPTURE), and the DSCR sticky abort flag is clear.
 *
 *  The executed instruction \em must read data from DTR.
 *
 * \pre arm11_run_instr_data_prepare() /  arm11_run_instr_data_finish() block
 *
 * \param arm11		Target state variable.
 * \param opcode	ARM opcode
 * \param data		Pointer to the data words to be passed to the core
 * \param count		Number of data words and instruction repetitions
 *
 */
int arm11_run_instr_data_to_core(struct arm11_common * arm11, uint32_t opcode, uint32_t * data, size_t count)
{
	arm11_add_IR(arm11, ARM11_ITRSEL, ARM11_TAP_DEFAULT);

	arm11_add_debug_INST(arm11, opcode, NULL, TAP_DRPAUSE);

	arm11_add_IR(arm11, ARM11_EXTEST, ARM11_TAP_DEFAULT);

	struct scan_field	chain5_fields[3];

	uint32_t				Data;
	uint8_t				Ready;
	uint8_t				nRetry;

	arm11_setup_field(arm11, 32,    &Data,  NULL,		chain5_fields + 0);
	arm11_setup_field(arm11,  1,    NULL,   &Ready,		chain5_fields + 1);
	arm11_setup_field(arm11,  1,    NULL,   &nRetry,	chain5_fields + 2);

	while (count--)
	{
		int i = 0;
		do
		{
			Data	    = *data;

			arm11_add_dr_scan_vc(ARRAY_SIZE(chain5_fields), chain5_fields, jtag_set_end_state(TAP_IDLE));

			CHECK_RETVAL(jtag_execute_queue());

			JTAG_DEBUG("DTR  Ready %d  nRetry %d", Ready, nRetry);

			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++;
		}
		while (!Ready);

		data++;
	}

	arm11_add_IR(arm11, ARM11_INTEST, ARM11_TAP_DEFAULT);

	int i = 0;
	do
	{
		Data	    = 0;

		arm11_add_dr_scan_vc(ARRAY_SIZE(chain5_fields), chain5_fields, TAP_DRPAUSE);

		CHECK_RETVAL(jtag_execute_queue());

		JTAG_DEBUG("DTR  Data %08x  Ready %d  nRetry %d",
				(unsigned) Data, Ready, nRetry);

		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++;
	}
	while (!Ready);

	return ERROR_OK;
}
Beispiel #20
0
// EXPORTED to FA256
int arm920t_soft_reset_halt(struct target *target)
{
	int retval = ERROR_OK;
	struct arm920t_common *arm920t = target_to_arm920(target);
	struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
	struct arm *armv4_5 = &arm7_9->armv4_5_common;
	struct reg *dbg_stat = &arm7_9->eice_cache->reg_list[EICE_DBG_STAT];

	if ((retval = target_halt(target)) != ERROR_OK)
	{
		return retval;
	}

	long long then = timeval_ms();
	int timeout;
	while (!(timeout = ((timeval_ms()-then) > 1000)))
	{
		if (buf_get_u32(dbg_stat->value, EICE_DBG_STATUS_DBGACK, 1)
				== 0)
		{
			embeddedice_read_reg(dbg_stat);
			if ((retval = jtag_execute_queue()) != ERROR_OK)
			{
				return retval;
			}
		} else
		{
			break;
		}
		if (debug_level >= 3)
		{
			/* do not eat all CPU, time out after 1 se*/
			alive_sleep(100);
		} else
		{
			keep_alive();
		}
	}
	if (timeout)
	{
		LOG_ERROR("Failed to halt CPU after 1 sec");
		return ERROR_TARGET_TIMEOUT;
	}

	target->state = TARGET_HALTED;

	/* SVC, ARM state, IRQ and FIQ disabled */
	uint32_t cpsr;

	cpsr = buf_get_u32(armv4_5->cpsr->value, 0, 32);
	cpsr &= ~0xff;
	cpsr |= 0xd3;
	arm_set_cpsr(armv4_5, cpsr);
	armv4_5->cpsr->dirty = 1;

	/* start fetching from 0x0 */
	buf_set_u32(armv4_5->pc->value, 0, 32, 0x0);
	armv4_5->pc->dirty = 1;
	armv4_5->pc->valid = 1;

	arm920t_disable_mmu_caches(target, 1, 1, 1);
	arm920t->armv4_5_mmu.mmu_enabled = 0;
	arm920t->armv4_5_mmu.armv4_5_cache.d_u_cache_enabled = 0;
	arm920t->armv4_5_mmu.armv4_5_cache.i_cache_enabled = 0;

	return target_call_event_callbacks(target, TARGET_EVENT_HALTED);
}
Beispiel #21
0
/** Apply reads and writes to scan chain 7
 *
 * \see struct arm11_sc7_action
 *
 * \param arm11		Target state variable.
 * \param actions	A list of read and/or write instructions
 * \param count		Number of instructions in the list.
 *
 */
int arm11_sc7_run(struct arm11_common * arm11, struct arm11_sc7_action * actions, size_t count)
{
	int retval;

	retval = arm11_add_debug_SCAN_N(arm11, 0x07, ARM11_TAP_DEFAULT);
	if (retval != ERROR_OK)
		return retval;

	arm11_add_IR(arm11, ARM11_EXTEST, ARM11_TAP_DEFAULT);

	struct scan_field	chain7_fields[3];

	uint8_t				nRW;
	uint32_t				DataOut;
	uint8_t				AddressOut;
	uint8_t				Ready;
	uint32_t				DataIn;
	uint8_t				AddressIn;

	arm11_setup_field(arm11,  1, &nRW,			&Ready,		chain7_fields + 0);
	arm11_setup_field(arm11, 32, &DataOut,		&DataIn,	chain7_fields + 1);
	arm11_setup_field(arm11,  7, &AddressOut,	&AddressIn,	chain7_fields + 2);

	for (size_t i = 0; i < count + 1; i++)
	{
		if (i < count)
		{
			nRW			= actions[i].write ? 1 : 0;
			DataOut		= actions[i].value;
			AddressOut	= actions[i].address;
		}
		else
		{
			nRW			= 1;
			DataOut		= 0;
			AddressOut	= 0;
		}

		/* Timeout here so we don't get stuck. */
		int i = 0;
		while (1)
		{
			JTAG_DEBUG("SC7 <= c%-3d Data %08x %s",
					(unsigned) AddressOut,
					(unsigned) DataOut,
					nRW ? "write" : "read");

			arm11_add_dr_scan_vc(ARRAY_SIZE(chain7_fields),
					chain7_fields, TAP_DRPAUSE);

			CHECK_RETVAL(jtag_execute_queue());

			/* 'nRW' is 'Ready' on read out */
			if (Ready)
				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++;
		}

		if (!nRW)
			JTAG_DEBUG("SC7 => Data %08x", (unsigned) DataIn);

		if (i > 0)
		{
			if (actions[i - 1].address != AddressIn)
			{
				LOG_WARNING("Scan chain 7 shifted out unexpected address");
			}

			if (!actions[i - 1].write)
			{
				actions[i - 1].value = DataIn;
			}
			else
			{
				if (actions[i - 1].value != DataIn)
				{
					LOG_WARNING("Scan chain 7 shifted out unexpected data");
				}
			}
		}
	}
	return ERROR_OK;
}
Beispiel #22
0
int linux_get_tasks(struct target *target, int context)
{
    int loop = 0;
    int retval = 0;
    struct linux_os *linux_os = (struct linux_os *)
                                target->rtos->rtos_specific_params;
    linux_os->thread_list = NULL;
    linux_os->thread_count = 0;

    if (linux_os->init_task_addr == 0xdeadbeef) {
        LOG_INFO("no init symbol\n");
        return ERROR_FAIL;
    }

    int64_t start = timeval_ms();

    struct threads *t = calloc(1, sizeof(struct threads));
    struct threads *last = NULL;
    t->base_addr = linux_os->init_task_addr;
    /* retrieve the thread id , currently running in the different smp core */
    get_current(target, 1);

    while (((t->base_addr != linux_os->init_task_addr) &&
            (t->base_addr != 0)) || (loop == 0)) {
        loop++;
        fill_task(target, t);
        retval = get_name(target, t);

        if (loop > MAX_THREADS) {
            free(t);
            LOG_INFO("more than %d threads !!", MAX_THREADS);
            return ERROR_FAIL;
        }

        if (retval != ERROR_OK) {
            free(t);
            return ERROR_FAIL;
        }

        /*  check that this thread is not one the current threads already
         *  created */
#ifdef PID_CHECK

        if (!current_pid(linux_os, t->pid)) {
#else
        if (!current_base_addr(linux_os, t->base_addr)) {
#endif
            t->threadid = linux_os->threadid_count;
            t->status = 1;
            linux_os->threadid_count++;

            linux_os->thread_list =
                liste_add_task(linux_os->thread_list, t, &last);
            /* no interest to fill the context if it is a current thread. */
            linux_os->thread_count++;
            t->thread_info_addr = 0xdeadbeef;

            if (context)
                t->context =
                    cpu_context_read(target, t->base_addr,
                                     &t->thread_info_addr);
        } else {
            /*LOG_INFO("thread %s is a current thread already created",t->name); */
            free(t);
        }

        uint32_t base_addr = next_task(target, t);
        t = calloc(1, sizeof(struct threads));
        t->base_addr = base_addr;
    }

    linux_os->threads_lookup = 1;
    linux_os->threads_needs_update = 0;
    linux_os->preupdtate_threadid_count = linux_os->threadid_count - 1;
    /*  check that all current threads have been identified  */

    LOG_INFO("complete time %" PRId64 ", thread mean %" PRId64 "\n",
             (timeval_ms() - start),
             (timeval_ms() - start) / linux_os->threadid_count);

    LOG_INFO("threadid count %d", linux_os->threadid_count);
    free(t);

    return ERROR_OK;
}

static int clean_threadlist(struct target *target)
{
    struct linux_os *linux_os = (struct linux_os *)
                                target->rtos->rtos_specific_params;
    struct threads *old, *temp = linux_os->thread_list;

    while (temp != NULL) {
        old = temp;

        if (temp->context)
            free(temp->context);

        temp = temp->next;
        free(old);
    }

    return ERROR_OK;
}

static int linux_os_clean(struct target *target)
{
    struct linux_os *os_linux = (struct linux_os *)
                                target->rtos->rtos_specific_params;
    clean_threadlist(target);
    os_linux->init_task_addr = 0xdeadbeef;
    os_linux->name = "linux";
    os_linux->thread_list = NULL;
    os_linux->thread_count = 0;
    os_linux->nr_cpus = 0;
    os_linux->threads_lookup = 0;
    os_linux->threads_needs_update = 0;
    os_linux->threadid_count = 1;
    return ERROR_OK;
}

static int insert_into_threadlist(struct target *target, struct threads *t)
{
    struct linux_os *linux_os = (struct linux_os *)
                                target->rtos->rtos_specific_params;
    struct threads *temp = linux_os->thread_list;
    t->threadid = linux_os->threadid_count;
    linux_os->threadid_count++;
    t->status = 1;
    t->next = NULL;

    if (temp == NULL)
        linux_os->thread_list = t;
    else {
        while (temp->next != NULL)
            temp = temp->next;

        t->next = NULL;
        temp->next = t;
    }

    return ERROR_OK;
}

static void linux_identify_current_threads(struct target *target)
{
    struct linux_os *linux_os = (struct linux_os *)
                                target->rtos->rtos_specific_params;
    struct threads *thread_list = linux_os->thread_list;
    struct current_thread *ct = linux_os->current_threads;
    struct threads *t = NULL;

    while ((ct != NULL)) {
        if (ct->threadid == -1) {

            /*  un-identified thread */
            int found = 0;
            t = calloc(1, sizeof(struct threads));
            t->base_addr = ct->TS;
#ifdef PID_CHECK

            if (fill_task_pid(target, t) != ERROR_OK) {
error_handling:
                free(t);
                LOG_ERROR
                ("linux identify_current_threads: unable to read pid");
                return;
            }
#endif

            /* search in the list of threads if pid
               already present */
            while ((thread_list != NULL) && (found == 0)) {
#ifdef PID_CHECK
                if (thread_list->pid == t->pid) {
#else
                if (thread_list->base_addr == t->base_addr) {
#endif
                    free(t);
                    t = thread_list;
                    found = 1;
                }
                thread_list = thread_list->next;
            }

            if (!found) {
                /*  it is a new thread */
                if (fill_task(target, t) != ERROR_OK)
                    goto error_handling;

                get_name(target, t);
                insert_into_threadlist(target, t);
                t->thread_info_addr = 0xdeadbeef;
            }

            t->status = 3;
            ct->threadid = t->threadid;
#ifdef PID_CHECK
            ct->pid = t->pid;
#endif
            linux_os->thread_count++;
#if 0
            if (found == 0)
                LOG_INFO("current thread core %x identified %s",
                         ct->core_id, t->name);
            else
                LOG_INFO("current thread core %x, reused %s",
                         ct->core_id, t->name);
#endif
        }
#if 0
        else {
            struct threads tmp;
            tmp.base_addr = ct->TS;
            get_name(target, &tmp);
            LOG_INFO("current thread core %x , already identified %s !!!",
                     ct->core_id, tmp.name);
        }
#endif
        ct = ct->next;
    }

    return;
#ifndef PID_CHECK
error_handling:
    free(t);
    LOG_ERROR("unable to read pid");
    return;

#endif
}
Beispiel #23
0
static int linux_task_update(struct target *target, int context)
{
    struct linux_os *linux_os = (struct linux_os *)
                                target->rtos->rtos_specific_params;
    struct threads *thread_list = linux_os->thread_list;
    int retval;
    int loop = 0;
    linux_os->thread_count = 0;

    /*thread_list = thread_list->next; skip init_task*/
    while (thread_list != NULL) {
        thread_list->status = 0;	/*setting all tasks to dead state*/

        if (thread_list->context) {
            free(thread_list->context);
            thread_list->context = NULL;
        }

        thread_list = thread_list->next;
    }

    int found = 0;

    if (linux_os->init_task_addr == 0xdeadbeef) {
        LOG_INFO("no init symbol\n");
        return ERROR_FAIL;
    }
    int64_t start = timeval_ms();
    struct threads *t = calloc(1, sizeof(struct threads));
    uint32_t previous = 0xdeadbeef;
    t->base_addr = linux_os->init_task_addr;
    retval = get_current(target, 0);
    /*check that all current threads have been identified  */
    linux_identify_current_threads(target);

    while (((t->base_addr != linux_os->init_task_addr) &&
            (t->base_addr != previous)) || (loop == 0)) {
        /*  for avoiding any permanent loop for any reason possibly due to
         *  target */
        loop++;
        previous = t->base_addr;
        /*  read only pid */
#ifdef PID_CHECK
        retval = fill_task_pid(target, t);
#endif

        if (retval != ERROR_OK) {
            free(t);
            return ERROR_FAIL;
        }

        thread_list = linux_os->thread_list;

        while (thread_list != NULL) {
#ifdef PID_CHECK
            if (t->pid == thread_list->pid) {
#else
            if (t->base_addr == thread_list->base_addr) {
#endif
                if (!thread_list->status) {
#ifdef PID_CHECK
                    if (t->base_addr != thread_list->base_addr)
                        LOG_INFO("thread base_addr has changed !!");
#endif
                    /*  this is not a current thread  */
                    thread_list->base_addr = t->base_addr;
                    thread_list->status = 1;

                    /*  we don 't update this field any more */

                    /*thread_list->state = t->state;
                    thread_list->oncpu = t->oncpu;
                    thread_list->asid = t->asid;
                    */
                    if (context)
                        thread_list->context =
                            cpu_context_read(target,
                                             thread_list->
                                             base_addr,
                                             &thread_list->
                                             thread_info_addr);
                } else {
                    /*  it is a current thread no need to read context */
                }

                linux_os->thread_count++;
                found = 1;
                break;
            } else {
                found = 0;
                thread_list = thread_list->next;
            }
        }

        if (found == 0) {
            uint32_t base_addr;
            fill_task(target, t);
            get_name(target, t);
            retval = insert_into_threadlist(target, t);
            t->thread_info_addr = 0xdeadbeef;

            if (context)
                t->context =
                    cpu_context_read(target, t->base_addr,
                                     &t->thread_info_addr);

            base_addr = next_task(target, t);
            t = calloc(1, sizeof(struct threads));
            t->base_addr = base_addr;
            linux_os->thread_count++;
        } else
            t->base_addr = next_task(target, t);
    }

    LOG_INFO("update thread done %" PRId64 ", mean%" PRId64 "\n",
             (timeval_ms() - start), (timeval_ms() - start) / loop);
    free(t);
    linux_os->threads_needs_update = 0;
    return ERROR_OK;
}

int linux_gdb_thread_packet(struct target *target,
                            struct connection *connection, char *packet,
                            int packet_size)
{
    int retval;
    struct linux_os *linux_os =
        (struct linux_os *)target->rtos->rtos_specific_params;

    if (linux_os->init_task_addr == 0xdeadbeef) {
        /* it has not been initialized */
        LOG_INFO("received thread request without init task address");
        gdb_put_packet(connection, "l", 1);
        return ERROR_OK;
    }

    retval = linux_get_tasks(target, 1);

    if (retval != ERROR_OK)
        return ERROR_TARGET_FAILURE;

    char *out_str = (char *)calloc(1, 350 * sizeof(int64_t));
    char *tmp_str = out_str;
    tmp_str += sprintf(tmp_str, "m");
    struct threads *temp = linux_os->thread_list;
    tmp_str += sprintf(tmp_str, "%016" PRIx64, temp->threadid);
    temp = temp->next;

    while (temp != NULL) {
        tmp_str += sprintf(tmp_str, ",");
        tmp_str += sprintf(tmp_str, "%016" PRIx64, temp->threadid);
        temp = temp->next;
    }

    gdb_put_packet(connection, out_str, strlen(out_str));
    return ERROR_OK;
}
Beispiel #24
0
static int xtensa_step(struct target *target,
	int current,
	uint32_t address,
	int handle_breakpoints)
{
	int res;
	int icountLevel = 1;
	int originalIntenable = 0;
	uint32_t dosr;
	struct xtensa_common *xtensa = target_to_xtensa(target);
	
	static const uint32_t icount_val = -2; /* ICOUNT value to load for 1 step */
	if (target->state != TARGET_HALTED) {
		LOG_WARNING("%s: target not halted", __func__);
		return ERROR_TARGET_NOT_HALTED;
	}

	LOG_DEBUG("%s current=%d address=%"PRIx32, __func__, current, address);

	/* Load debug level into ICOUNTLEVEL

	   Originally had DEBUGLEVEL (ie 2) set here, not 1, but
	   seemed to result in occasionally stepping out into
	   inaccessible bits of ROM (low level interrupt handlers?)
	   and never quite recovering... One loop started at
	   0x40000050. Re-attaching with ICOUNTLEVEL 1 caused this to
	   immediately step into an interrupt handler.

	   ICOUNTLEVEL 1 still steps into interrupt handlers, but also
	   seems to recover.

	   TODO: Experiment more, look into CPU exception nuances,
	   consider making this step level a configuration command.
	 */
	res = xtensa_read_register(target, XT_REG_IDX_PS, 0);
	if (res == ERROR_OK)
	{
		int psValue = buf_get_u32(xtensa->core_cache->reg_list[XT_REG_IDX_PS].value, 0, 8);
		if (psValue & 0x10)
		{
			//We are executing code in the exception mode. Setting ICOUNTLEVEL to 1 would step into the first instruction that gets executed after the exception handler is done.
			//What we actually want is to step into the next instruction of the code we are debugging (i.e. an exception handler). Hence we ned to set ICOUNTLEVEL to 2 in order to count exception mode instructions as well.
			icountLevel = 2;
		}
	}
	
	if (s_DisableInterruptsForStepping)
	{
		res = xtensa_read_register(target, XT_REG_IDX_INTENABLE, 0);
		if (res != ERROR_OK)
			LOG_ERROR("%s: Failed to read the INTENABLE register during single step", __func__);
		else
		{
			originalIntenable = buf_get_u32(xtensa->core_cache->reg_list[XT_REG_IDX_INTENABLE].value, 0, 32);
			if (originalIntenable)
			{
				buf_set_u32(xtensa->core_cache->reg_list[XT_REG_IDX_INTENABLE].value, 0, 32, 0);
				xtensa->core_cache->reg_list[XT_REG_IDX_INTENABLE].dirty = 1;
			}
		}
	}
	
	res = xtensa_tap_queue_write_sr(target, XT_REG_IDX_ICOUNTLEVEL, icountLevel);
	if(res != ERROR_OK)
		return res;

	/* load ICOUNT step count value */
	res = xtensa_tap_queue_write_sr(target, XT_REG_IDX_ICOUNT, icount_val);
	if(res != ERROR_OK)
		return res;
	
	res = xtensa_tap_queue_cpu_inst(target, XT_INS_ISYNC);
	if (res != ERROR_OK)
		return res;

	res = xtensa_tap_queue_cpu_inst(target, XT_INS_ISYNC);
	if (res != ERROR_OK)
		return res;
	
	res = jtag_execute_queue();
	if(res != ERROR_OK)
		return res;

	/* Wait for everything to settle, seems necessary to avoid bad resumes */
	do {
		res = xtensa_tap_exec(target, TAP_INS_READ_DOSR, 0, &dosr);
		if(res != ERROR_OK) {
			LOG_ERROR("Failed to read DOSR. Not Xtensa OCD?");
			return ERROR_FAIL;
		}
	} while(!(dosr & DOSR_IN_OCD_MODE) || (dosr & DOSR_EXCEPTION));

	/* Now ICOUNT is set, we can resume as if we were going to run */
	res = xtensa_resume(target, current, address, 0, 0);
	if(res != ERROR_OK) {
		LOG_ERROR("%s: Failed to resume after setting up single step", __func__);
		return res;
	}

	/* Wait for stepping to complete */
	int64_t start = timeval_ms();
	while(target->state != TARGET_HALTED && timeval_ms() < start+500) {
		res = target_poll(target);
		if(res != ERROR_OK)
			return res;
		if(target->state != TARGET_HALTED)
			usleep(50000);
	}
	if(target->state != TARGET_HALTED) {
		xtensa_halt(target);
		LOG_ERROR("%s: Timed out waiting for target to finish stepping.", __func__);
		return ERROR_TARGET_TIMEOUT;
	}
	
	if (originalIntenable)
	{
		buf_set_u32(xtensa->core_cache->reg_list[XT_REG_IDX_INTENABLE].value, 0, 32, originalIntenable);
		xtensa->core_cache->reg_list[XT_REG_IDX_INTENABLE].dirty = 1;
	}

	/* write ICOUNTLEVEL back to zero */
	res = xtensa_tap_queue_write_sr(target, XT_REG_IDX_ICOUNTLEVEL, 0);
	if(res != ERROR_OK)
		return res;
	res = jtag_execute_queue();

	return res;
}