/* read a word (16bit) from the netx to the pc */
int fn_read_data16(void *pvHandle, unsigned long ulNetxAddress, unsigned short *pusData)
{
	command_context_t *cmd_ctx;
	target_t *target;
	int iResult;


	/* cast the handle to the command context */
	cmd_ctx = (command_context_t*)pvHandle;

	/* get the target from the command context */
	target = get_current_target(cmd_ctx);

	/* read the data from the netX */
	iResult = target_read_u16(target, ulNetxAddress, pusData);
	if( iResult==ERROR_OK )
	{
		iResult = 0;
	}
	else
	{
		iResult = 1;
	}

	wxMilliSleep(1);

	return iResult;
}
Ejemplo n.º 2
0
int armv7m_maybe_skip_bkpt_inst(struct target *target, bool *inst_found)
{
	struct armv7m_common *armv7m = target_to_armv7m(target);
	struct reg *r = armv7m->arm.pc;
	bool result = false;


	/* if we halted last time due to a bkpt instruction
	 * then we have to manually step over it, otherwise
	 * the core will break again */

	if (target->debug_reason == DBG_REASON_BREAKPOINT) {
		uint16_t op;
		uint32_t pc = buf_get_u32(r->value, 0, 32);

		pc &= ~1;
		if (target_read_u16(target, pc, &op) == ERROR_OK) {
			if ((op & 0xFF00) == 0xBE00) {
				pc = buf_get_u32(r->value, 0, 32) + 2;
				buf_set_u32(r->value, 0, 32, pc);
				r->dirty = true;
				r->valid = true;
				result = true;
				LOG_DEBUG("Skipping over BKPT instruction");
			}
		}
	}

	if (inst_found)
		*inst_found = result;

	return ERROR_OK;
}
Ejemplo n.º 3
0
static int str9x_protect_check(struct flash_bank *bank)
{
	int retval;
	struct str9x_flash_bank *str9x_info = bank->driver_priv;
	struct target *target = bank->target;

	int i;
	uint32_t adr;
	uint32_t status = 0;
	uint16_t hstatus = 0;

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

	/* read level one protection */

	if (str9x_info->variant) {
		if (str9x_info->bank1) {
			adr = bank1start + 0x18;
			retval = target_write_u16(target, adr, 0x90);
			if (retval != ERROR_OK)
				return retval;
			retval = target_read_u16(target, adr, &hstatus);
			if (retval != ERROR_OK)
				return retval;
			status = hstatus;
		} else {
			adr = bank1start + 0x14;
			retval = target_write_u16(target, adr, 0x90);
			if (retval != ERROR_OK)
				return retval;
			retval = target_read_u32(target, adr, &status);
			if (retval != ERROR_OK)
				return retval;
		}
	} else {
		adr = bank1start + 0x10;
		retval = target_write_u16(target, adr, 0x90);
		if (retval != ERROR_OK)
			return retval;
		retval = target_read_u16(target, adr, &hstatus);
		if (retval != ERROR_OK)
			return retval;
		status = hstatus;
	}

	/* read array command */
	retval = target_write_u16(target, adr, 0xFF);
	if (retval != ERROR_OK)
		return retval;

	for (i = 0; i < bank->num_sectors; i++) {
		if (status & str9x_info->sector_bits[i])
			bank->sectors[i].is_protected = 1;
		else
			bank->sectors[i].is_protected = 0;
	}

	return ERROR_OK;
}
Ejemplo n.º 4
0
static int stm32x_probe(struct flash_bank *bank)
{
	struct target *target = bank->target;
	struct stm32x_flash_bank *stm32x_info = bank->driver_priv;
	int i;
	uint16_t num_pages;
	uint32_t device_id;
	int page_size;
	uint32_t base_address = 0x08000000;

	stm32x_info->probed = 0;
	stm32x_info->register_offset = FLASH_OFFSET_B0;

	/* read stm32 device id register */
	int retval = target_read_u32(target, 0xE0042000, &device_id);
	if (retval != ERROR_OK)
		return retval;
	LOG_INFO("device id = 0x%08" PRIx32 "", device_id);

	/* get flash size from target. */
	retval = target_read_u16(target, 0x1FFFF7E0, &num_pages);
	if (retval != ERROR_OK)
	{
		LOG_WARNING("failed reading flash size, default to max target family");
		/* failed reading flash size, default to max target family */
		num_pages = 0xffff;
	}

	if ((device_id & 0x7ff) == 0x410)
	{
		/* medium density - we have 1k pages
		 * 4 pages for a protection area */
		page_size = 1024;
		stm32x_info->ppage_size = 4;

		/* check for early silicon */
		if (num_pages == 0xffff)
		{
			/* number of sectors incorrect on revA */
			LOG_WARNING("STM32 flash size failed, probe inaccurate - assuming 128k flash");
			num_pages = 128;
		}
	}
	else if ((device_id & 0x7ff) == 0x412)
	{
		/* low density - we have 1k pages
		 * 4 pages for a protection area */
		page_size = 1024;
		stm32x_info->ppage_size = 4;

		/* check for early silicon */
		if (num_pages == 0xffff)
		{
			/* number of sectors incorrect on revA */
			LOG_WARNING("STM32 flash size failed, probe inaccurate - assuming 32k flash");
			num_pages = 32;
		}
	}
	else if ((device_id & 0x7ff) == 0x414)
	{
		/* high density - we have 2k pages
		 * 2 pages for a protection area */
		page_size = 2048;
		stm32x_info->ppage_size = 2;

		/* check for early silicon */
		if (num_pages == 0xffff)
		{
			/* number of sectors incorrect on revZ */
			LOG_WARNING("STM32 flash size failed, probe inaccurate - assuming 512k flash");
			num_pages = 512;
		}
	}
	else if ((device_id & 0x7ff) == 0x418)
	{
		/* connectivity line density - we have 2k pages
		 * 2 pages for a protection area */
		page_size = 2048;
		stm32x_info->ppage_size = 2;

		/* check for early silicon */
		if (num_pages == 0xffff)
		{
			/* number of sectors incorrect on revZ */
			LOG_WARNING("STM32 flash size failed, probe inaccurate - assuming 256k flash");
			num_pages = 256;
		}
	}
	else if ((device_id & 0x7ff) == 0x420)
	{
		/* value line density - we have 1k pages
		 * 4 pages for a protection area */
		page_size = 1024;
		stm32x_info->ppage_size = 4;

		/* check for early silicon */
		if (num_pages == 0xffff)
		{
			/* number of sectors may be incorrrect on early silicon */
			LOG_WARNING("STM32 flash size failed, probe inaccurate - assuming 128k flash");
			num_pages = 128;
		}
	}
	else if ((device_id & 0x7ff) == 0x430)
	{
		/* xl line density - we have 2k pages
		 * 2 pages for a protection area */
		page_size = 2048;
		stm32x_info->ppage_size = 2;
		stm32x_info->has_dual_banks = true;

		/* check for early silicon */
		if (num_pages == 0xffff)
		{
			/* number of sectors may be incorrrect on early silicon */
			LOG_WARNING("STM32 flash size failed, probe inaccurate - assuming 1024k flash");
			num_pages = 1024;
		}

		/* split reported size into matching bank */
		if (bank->base != 0x08080000)
		{
			/* bank 0 will be fixed 512k */
			num_pages = 512;
		}
		else
		{
			num_pages -= 512;
			/* bank1 also uses a register offset */
			stm32x_info->register_offset = FLASH_OFFSET_B1;
			base_address = 0x08080000;
		}
	}
	else
	{
		LOG_WARNING("Cannot identify target as a STM32 family.");
		return ERROR_FAIL;
	}

	LOG_INFO("flash size = %dkbytes", num_pages);

	/* calculate numbers of pages */
	num_pages /= (page_size / 1024);

	if (bank->sectors)
	{
		free(bank->sectors);
		bank->sectors = NULL;
	}

	bank->base = base_address;
	bank->size = (num_pages * page_size);
	bank->num_sectors = num_pages;
	bank->sectors = malloc(sizeof(struct flash_sector) * num_pages);

	for (i = 0; i < num_pages; i++)
	{
		bank->sectors[i].offset = i * page_size;
		bank->sectors[i].size = page_size;
		bank->sectors[i].is_erased = -1;
		bank->sectors[i].is_protected = 1;
	}

	stm32x_info->probed = 1;

	return ERROR_OK;
}
Ejemplo n.º 5
0
Archivo: fm3.c Proyecto: tthef/openocd
/* Data polling algorithm */
static int fm3_busy_wait(struct target *target, uint32_t offset, int timeout_ms)
{
	int retval = ERROR_OK;
	uint16_t state1, state2;
	int ms = 0;

	/* While(1) loop exit via "break" and "return" on error */
	while(1)
	{
		/* dummy-read - see flash manual */
		retval = target_read_u16(target, offset, &state1);
		if (retval != ERROR_OK)
			return retval;

		/* Data polling 1 */
		retval = target_read_u16(target, offset, &state1);
		if (retval != ERROR_OK)
			return retval;

		/* Data polling 2 */
		retval = target_read_u16(target, offset, &state2);
		if (retval != ERROR_OK)
			return retval;

		/* Flash command finished via polled data equal? */
		if ( (state1 & FLASH_DQ6) == (state2 & FLASH_DQ6) )
		{
			break;
		}
		/* Timeout Flag? */
		else if (state1 & FLASH_DQ5)
		{
			/* Retry data polling */

			/* Data polling 1 */
			retval = target_read_u16(target, offset, &state1);
			if (retval != ERROR_OK)
				return retval;

			/* Data polling 2 */
			retval = target_read_u16(target, offset, &state2);
			if (retval != ERROR_OK)
				return retval;

			/* Flash command finished via polled data equal? */
			if ( (state1 & FLASH_DQ6) != (state2 & FLASH_DQ6) )
			{
				return ERROR_FLASH_OPERATION_FAILED;
			}

			/* finish anyway */
			break;
		}
		usleep(1000);
		++ms;

		/* Polling time exceeded? */
		if (ms > timeout_ms)
		{
			LOG_ERROR("Polling data reading timed out!");
			return ERROR_FLASH_OPERATION_FAILED;
		}
	}

	if (retval == ERROR_OK)
		LOG_DEBUG("fm3_busy_wait(%x) needs about %d ms", offset, ms);

	return retval;
}
Ejemplo n.º 6
0
static int uCOS_III_update_threads(struct rtos *rtos)
{
	struct uCOS_III_params *params = rtos->rtos_specific_params;
	int retval;

	/* free previous thread details */
	rtos_free_threadlist(rtos);

	/* verify RTOS is running */
	uint8_t rtos_running;

	retval = target_read_u8(rtos->target,
			rtos->symbols[uCOS_III_VAL_OSRunning].address,
			&rtos_running);
	if (retval != ERROR_OK) {
		LOG_ERROR("uCOS-III: failed to read RTOS running");
		return retval;
	}

	if (rtos_running != 1 && rtos_running != 0) {
		LOG_ERROR("uCOS-III: invalid RTOS running value");
		return ERROR_FAIL;
	}

	if (!rtos_running) {
		rtos->thread_details = calloc(1, sizeof(struct thread_detail));
		if (rtos->thread_details == NULL) {
			LOG_ERROR("uCOS-III: out of memory");
			return ERROR_FAIL;
		}

		rtos->thread_count = 1;
		rtos->thread_details->threadid = 0;
		rtos->thread_details->exists = true;
		rtos->current_thread = 0;

		return ERROR_OK;
	}

	/* update thread offsets */
	retval = uCOS_III_update_thread_offsets(rtos);
	if (retval != ERROR_OK) {
		LOG_ERROR("uCOS-III: failed to update thread offsets");
		return retval;
	}

	/* read current thread address */
	symbol_address_t current_thread_address = 0;

	retval = target_read_memory(rtos->target,
			rtos->symbols[uCOS_III_VAL_OSTCBCurPtr].address,
			params->pointer_width,
			1,
			(void *)&current_thread_address);
	if (retval != ERROR_OK) {
		LOG_ERROR("uCOS-III: failed to read current thread address");
		return retval;
	}

	/* read number of tasks */
	retval = target_read_u16(rtos->target,
			rtos->symbols[uCOS_III_VAL_OSTaskQty].address,
			(void *)&rtos->thread_count);
	if (retval != ERROR_OK) {
		LOG_ERROR("uCOS-III: failed to read thread count");
		return retval;
	}

	rtos->thread_details = calloc(rtos->thread_count, sizeof(struct thread_detail));
	if (rtos->thread_details == NULL) {
		LOG_ERROR("uCOS-III: out of memory");
		return ERROR_FAIL;
	}

	/*
	 * uC/OS-III adds tasks in LIFO order; advance to the end of the
	 * list and work backwards to preserve the intended order.
	 */
	symbol_address_t thread_address = 0;

	retval = uCOS_III_find_last_thread_address(rtos, &thread_address);
	if (retval != ERROR_OK) {
		LOG_ERROR("uCOS-III: failed to find last thread address");
		return retval;
	}

	for (int i = 0; i < rtos->thread_count; i++) {
		struct thread_detail *thread_detail = &rtos->thread_details[i];
		char thread_str_buffer[UCOS_III_MAX_STRLEN + 1];

		/* find or create new threadid */
		retval = uCOS_III_find_or_create_thread(rtos, thread_address, &thread_detail->threadid);
		if (retval != ERROR_OK) {
			LOG_ERROR("uCOS-III: failed to find or create thread");
			return retval;
		}

		if (thread_address == current_thread_address)
			rtos->current_thread = thread_detail->threadid;

		thread_detail->exists = true;

		/* read thread name */
		symbol_address_t thread_name_address = 0;

		retval = target_read_memory(rtos->target,
				thread_address + params->thread_name_offset,
				params->pointer_width,
				1,
				(void *)&thread_name_address);
		if (retval != ERROR_OK) {
			LOG_ERROR("uCOS-III: failed to name address");
			return retval;
		}

		retval = target_read_buffer(rtos->target,
				thread_name_address,
				sizeof(thread_str_buffer),
				(void *)thread_str_buffer);
		if (retval != ERROR_OK) {
			LOG_ERROR("uCOS-III: failed to read thread name");
			return retval;
		}

		thread_str_buffer[sizeof(thread_str_buffer) - 1] = '\0';
		thread_detail->thread_name_str = strdup(thread_str_buffer);

		/* read thread extra info */
		uint8_t thread_state;
		uint8_t thread_priority;

		retval = target_read_u8(rtos->target,
				thread_address + params->thread_state_offset,
				&thread_state);
		if (retval != ERROR_OK) {
			LOG_ERROR("uCOS-III: failed to read thread state");
			return retval;
		}

		retval = target_read_u8(rtos->target,
				thread_address + params->thread_priority_offset,
				&thread_priority);
		if (retval != ERROR_OK) {
			LOG_ERROR("uCOS-III: failed to read thread priority");
			return retval;
		}

		const char *thread_state_str;

		if (thread_state < ARRAY_SIZE(uCOS_III_thread_state_list))
			thread_state_str = uCOS_III_thread_state_list[thread_state];
		else
			thread_state_str = "Unknown";

		snprintf(thread_str_buffer, sizeof(thread_str_buffer), "State: %s, Priority: %d",
				thread_state_str, thread_priority);
		thread_detail->extra_info_str = strdup(thread_str_buffer);

		/* read previous thread address */
		retval = target_read_memory(rtos->target,
				thread_address + params->thread_prev_offset,
				params->pointer_width,
				1,
				(void *)&thread_address);
		if (retval != ERROR_OK) {
			LOG_ERROR("uCOS-III: failed to read previous thread address");
			return retval;
		}
	}

	return ERROR_OK;
}
Ejemplo n.º 7
0
static int stm32lx_probe(struct flash_bank *bank)
{
	struct target *target = bank->target;
	struct stm32lx_flash_bank *stm32lx_info = bank->driver_priv;
	int i;
	uint16_t flash_size_in_kb;
	uint16_t max_flash_size_in_kb;
	uint32_t device_id;
	uint32_t base_address = FLASH_BANK0_ADDRESS;
	uint32_t second_bank_base;
	uint32_t first_bank_size_in_kb;

	stm32lx_info->probed = 0;

	/* read stm32 device id register */
	int retval = target_read_u32(target, DBGMCU_IDCODE, &device_id);
	if (retval != ERROR_OK)
		return retval;

	LOG_DEBUG("device id = 0x%08" PRIx32 "", device_id);

	/* set max flash size depending on family */
	switch (device_id & 0xfff) {
	case 0x416:
		max_flash_size_in_kb = 128;
		break;
	case 0x427:
		/* single bank, high density */
		max_flash_size_in_kb = 256;
		break;
	case 0x436:
		/* According to ST, the devices with id 0x436 have dual bank flash and comes with
		 * a total flash size of 384k or 256kb. However, the first bank is always 192kb,
		 * and second one holds the rest. The reason is that the 256kb version is actually
		 * the same physical flash but only the first 256kb are verified.
		 */
		max_flash_size_in_kb = 384;
		first_bank_size_in_kb = 192;
		stm32lx_info->has_dual_banks = true;
		break;
	default:
		LOG_WARNING("Cannot identify target as a STM32L family.");
		return ERROR_FAIL;
	}

	/* Get the flash size from target. */
	retval = target_read_u16(target, F_SIZE, &flash_size_in_kb);

	/* Failed reading flash size or flash size invalid (early silicon),
	 * default to max target family */
	if (retval != ERROR_OK || flash_size_in_kb == 0xffff || flash_size_in_kb == 0) {
		LOG_WARNING("STM32L flash size failed, probe inaccurate - assuming %dk flash",
			max_flash_size_in_kb);
		flash_size_in_kb = max_flash_size_in_kb;
	} else if (flash_size_in_kb > max_flash_size_in_kb) {
		LOG_WARNING("STM32L probed flash size assumed incorrect since FLASH_SIZE=%dk > %dk, - assuming %dk flash",
			flash_size_in_kb, max_flash_size_in_kb, max_flash_size_in_kb);
		flash_size_in_kb = max_flash_size_in_kb;
	}

	if (stm32lx_info->has_dual_banks) {
		/* Use the configured base address to determine if this is the first or second flash bank.
		 * Verify that the base address is reasonably correct and determine the flash bank size
		 */
		second_bank_base = base_address + first_bank_size_in_kb * 1024;
		if (bank->base == second_bank_base) {
			/* This is the second bank  */
			base_address = second_bank_base;
			flash_size_in_kb = flash_size_in_kb - first_bank_size_in_kb;
		} else if (bank->base == 0 || bank->base == base_address) {
			/* This is the first bank */
			flash_size_in_kb = first_bank_size_in_kb;
		} else {
			LOG_WARNING("STM32L flash bank base address config is incorrect. 0x%x but should rather be 0x%x or 0x%x",
						bank->base, base_address, second_bank_base);
			return ERROR_FAIL;
		}
		LOG_INFO("STM32L flash has dual banks. Bank (%d) size is %dkb, base address is 0x%x",
				bank->bank_number, flash_size_in_kb, base_address);
	} else {
		LOG_INFO("STM32L flash size is %dkb, base address is 0x%x", flash_size_in_kb, base_address);
	}

	/* if the user sets the size manually then ignore the probed value
	 * this allows us to work around devices that have a invalid flash size register value */
	if (stm32lx_info->user_bank_size) {
		flash_size_in_kb = stm32lx_info->user_bank_size / 1024;
		LOG_INFO("ignoring flash probed value, using configured bank size: %dkbytes", flash_size_in_kb);
	}

	/* STM32L - we have 32 sectors, 16 pages per sector -> 512 pages
	 * 16 pages for a protection area */

	/* calculate numbers of sectors (4kB per sector) */
	int num_sectors = (flash_size_in_kb * 1024) / FLASH_SECTOR_SIZE;

	if (bank->sectors) {
		free(bank->sectors);
		bank->sectors = NULL;
	}

	bank->size = flash_size_in_kb * 1024;
	bank->base = base_address;
	bank->num_sectors = num_sectors;
	bank->sectors = malloc(sizeof(struct flash_sector) * num_sectors);
	if (bank->sectors == NULL) {
		LOG_ERROR("failed to allocate bank sectors");
		return ERROR_FAIL;
	}

	for (i = 0; i < num_sectors; i++) {
		bank->sectors[i].offset = i * FLASH_SECTOR_SIZE;
		bank->sectors[i].size = FLASH_SECTOR_SIZE;
		bank->sectors[i].is_erased = -1;
		bank->sectors[i].is_protected = 1;
	}

	stm32lx_info->probed = 1;

	return ERROR_OK;
}
Ejemplo n.º 8
0
static int stm32x_probe(struct flash_bank *bank)
{
	struct target *target = bank->target;
	struct stm32x_flash_bank *stm32x_info = bank->driver_priv;
	int i;
	uint16_t num_pages;
	uint32_t device_id;
	int page_size;

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

	stm32x_info->probed = 0;

	/* read stm32 device id register */
	target_read_u32(target, 0xE0042000, &device_id);
	LOG_INFO("device id = 0x%08" PRIx32 "", device_id);

	/* get flash size from target */
	if (target_read_u16(target, 0x1FFFF7E0, &num_pages) != ERROR_OK)
	{
		/* failed reading flash size, default to max target family */
		num_pages = 0xffff;
	}

	if ((device_id & 0x7ff) == 0x410)
	{
		/* medium density - we have 1k pages
		 * 4 pages for a protection area */
		page_size = 1024;
		stm32x_info->ppage_size = 4;

		/* check for early silicon */
		if (num_pages == 0xffff)
		{
			/* number of sectors incorrect on revA */
			LOG_WARNING("STM32 flash size failed, probe inaccurate - assuming 128k flash");
			num_pages = 128;
		}
	}
	else if ((device_id & 0x7ff) == 0x412)
	{
		/* low density - we have 1k pages
		 * 4 pages for a protection area */
		page_size = 1024;
		stm32x_info->ppage_size = 4;

		/* check for early silicon */
		if (num_pages == 0xffff)
		{
			/* number of sectors incorrect on revA */
			LOG_WARNING("STM32 flash size failed, probe inaccurate - assuming 32k flash");
			num_pages = 32;
		}
	}
	else if ((device_id & 0x7ff) == 0x414)
	{
		/* high density - we have 2k pages
		 * 2 pages for a protection area */
		page_size = 2048;
		stm32x_info->ppage_size = 2;

		/* check for early silicon */
		if (num_pages == 0xffff)
		{
			/* number of sectors incorrect on revZ */
			LOG_WARNING("STM32 flash size failed, probe inaccurate - assuming 512k flash");
			num_pages = 512;
		}
	}
	else if ((device_id & 0x7ff) == 0x418)
	{
		/* connectivity line density - we have 2k pages
		 * 2 pages for a protection area */
		page_size = 2048;
		stm32x_info->ppage_size = 2;

		/* check for early silicon */
		if (num_pages == 0xffff)
		{
			/* number of sectors incorrect on revZ */
			LOG_WARNING("STM32 flash size failed, probe inaccurate - assuming 256k flash");
			num_pages = 256;
		}
	}
	else
	{
		LOG_WARNING("Cannot identify target as a STM32 family.");
		return ERROR_FLASH_OPERATION_FAILED;
	}

	LOG_INFO("flash size = %dkbytes", num_pages);

	/* calculate numbers of pages */
	num_pages /= (page_size / 1024);

	bank->base = 0x08000000;
	bank->size = (num_pages * page_size);
	bank->num_sectors = num_pages;
	bank->sectors = malloc(sizeof(struct flash_sector) * num_pages);

	for (i = 0; i < num_pages; i++)
	{
		bank->sectors[i].offset = i * page_size;
		bank->sectors[i].size = page_size;
		bank->sectors[i].is_erased = -1;
		bank->sectors[i].is_protected = 1;
	}

	stm32x_info->probed = 1;

	return ERROR_OK;
}
Ejemplo n.º 9
0
/**
 * Checks for and processes an ARM semihosting request.  This is meant
 * to be called when the target is stopped due to a debug mode entry.
 * If the value 0 is returned then there was nothing to process. A non-zero
 * return value signifies that a request was processed and the target resumed,
 * or an error was encountered, in which case the caller must return
 * immediately.
 *
 * @param target Pointer to the ARM target to process.  This target must
 *	not represent an ARMv6-M or ARMv7-M processor.
 * @param retval Pointer to a location where the return code will be stored
 * @return non-zero value if a request was processed or an error encountered
 */
int arm_semihosting(struct target *target, int *retval)
{
	struct arm *arm = target_to_arm(target);
	uint32_t pc, lr, spsr;
	struct reg *r;

	if (!arm->is_semihosting)
		return 0;

	if (is_arm7_9(target_to_arm7_9(target))) {
		if (arm->core_mode != ARM_MODE_SVC)
			return 0;

		/* Check for PC == 0x00000008 or 0xffff0008: Supervisor Call vector. */
		r = arm->pc;
		pc = buf_get_u32(r->value, 0, 32);
		if (pc != 0x00000008 && pc != 0xffff0008)
			return 0;

		r = arm_reg_current(arm, 14);
		lr = buf_get_u32(r->value, 0, 32);

		/* Core-specific code should make sure SPSR is retrieved
		 * when the above checks pass...
		 */
		if (!arm->spsr->valid) {
			LOG_ERROR("SPSR not valid!");
			*retval = ERROR_FAIL;
			return 1;
		}

		spsr = buf_get_u32(arm->spsr->value, 0, 32);

		/* check instruction that triggered this trap */
		if (spsr & (1 << 5)) {
			/* was in Thumb (or ThumbEE) mode */
			uint8_t insn_buf[2];
			uint16_t insn;

			*retval = target_read_memory(target, lr-2, 2, 1, insn_buf);
			if (*retval != ERROR_OK)
				return 1;
			insn = target_buffer_get_u16(target, insn_buf);

			/* SVC 0xab */
			if (insn != 0xDFAB)
				return 0;
		} else if (spsr & (1 << 24)) {
			/* was in Jazelle mode */
			return 0;
		} else {
			/* was in ARM mode */
			uint8_t insn_buf[4];
			uint32_t insn;

			*retval = target_read_memory(target, lr-4, 4, 1, insn_buf);
			if (*retval != ERROR_OK)
				return 1;
			insn = target_buffer_get_u32(target, insn_buf);

			/* SVC 0x123456 */
			if (insn != 0xEF123456)
				return 0;
		}
	} else if (is_armv7m(target_to_armv7m(target))) {
		uint16_t insn;

		if (target->debug_reason != DBG_REASON_BREAKPOINT)
			return 0;

		r = arm->pc;
		pc = buf_get_u32(r->value, 0, 32);

		pc &= ~1;
		*retval = target_read_u16(target, pc, &insn);
		if (*retval != ERROR_OK)
			return 1;

		/* bkpt 0xAB */
		if (insn != 0xBEAB)
			return 0;
	} else {
		LOG_ERROR("Unsupported semi-hosting Target");
		return 0;
	}

	*retval = do_semihosting(target);
	return 1;
}
Ejemplo n.º 10
0
/**
 * Checks for and processes an ARM semihosting request.  This is meant
 * to be called when the target is stopped due to a debug mode entry.
 * If the value 0 is returned then there was nothing to process. A non-zero
 * return value signifies that a request was processed and the target resumed,
 * or an error was encountered, in which case the caller must return
 * immediately.
 *
 * @param target Pointer to the ARM target to process.  This target must
 *	not represent an ARMv6-M or ARMv7-M processor.
 * @param retval Pointer to a location where the return code will be stored
 * @return non-zero value if a request was processed or an error encountered
 */
int arm_semihosting(struct target *target, int *retval)
{
	struct arm *arm = target_to_arm(target);
	struct armv7a_common *armv7a = target_to_armv7a(target);
	uint32_t pc, lr, spsr;
	struct reg *r;

	if (!arm->is_semihosting)
		return 0;

	if (is_arm7_9(target_to_arm7_9(target)) ||
	    is_armv7a(armv7a)) {
		uint32_t vbar = 0x00000000;

		if (arm->core_mode != ARM_MODE_SVC)
			return 0;

		if (is_armv7a(armv7a)) {
			struct arm_dpm *dpm = armv7a->arm.dpm;

			*retval = dpm->prepare(dpm);
			if (*retval == ERROR_OK) {
				*retval = dpm->instr_read_data_r0(dpm,
								 ARMV4_5_MRC(15, 0, 0, 12, 0, 0),
								 &vbar);

				dpm->finish(dpm);

				if (*retval != ERROR_OK)
					return 1;
			} else {
				return 1;
			}
		}

		/* Check for PC == 0x00000008 or 0xffff0008: Supervisor Call vector. */
		r = arm->pc;
		pc = buf_get_u32(r->value, 0, 32);
		if (pc != (vbar + 0x00000008) && pc != 0xffff0008)
			return 0;

		r = arm_reg_current(arm, 14);
		lr = buf_get_u32(r->value, 0, 32);

		/* Core-specific code should make sure SPSR is retrieved
		 * when the above checks pass...
		 */
		if (!arm->spsr->valid) {
			LOG_ERROR("SPSR not valid!");
			*retval = ERROR_FAIL;
			return 1;
		}

		spsr = buf_get_u32(arm->spsr->value, 0, 32);

		/* check instruction that triggered this trap */
		if (spsr & (1 << 5)) {
			/* was in Thumb (or ThumbEE) mode */
			uint8_t insn_buf[2];
			uint16_t insn;

			*retval = target_read_memory(target, lr-2, 2, 1, insn_buf);
			if (*retval != ERROR_OK)
				return 1;
			insn = target_buffer_get_u16(target, insn_buf);

			/* SVC 0xab */
			if (insn != 0xDFAB)
				return 0;
		} else if (spsr & (1 << 24)) {
			/* was in Jazelle mode */
			return 0;
		} else {
			/* was in ARM mode */
			uint8_t insn_buf[4];
			uint32_t insn;

			*retval = target_read_memory(target, lr-4, 4, 1, insn_buf);
			if (*retval != ERROR_OK)
				return 1;
			insn = target_buffer_get_u32(target, insn_buf);

			/* SVC 0x123456 */
			if (insn != 0xEF123456)
				return 0;
		}
	} else if (is_armv7m(target_to_armv7m(target))) {
		uint16_t insn;

		if (target->debug_reason != DBG_REASON_BREAKPOINT)
			return 0;

		r = arm->pc;
		pc = buf_get_u32(r->value, 0, 32);

		pc &= ~1;
		*retval = target_read_u16(target, pc, &insn);
		if (*retval != ERROR_OK)
			return 1;

		/* bkpt 0xAB */
		if (insn != 0xBEAB)
			return 0;
	} else {
		LOG_ERROR("Unsupported semi-hosting Target");
		return 0;
	}

	/* Perform semihosting if we are not waiting on a fileio
	 * operation to complete.
	 */
	if (!arm->semihosting_hit_fileio) {
		*retval = do_semihosting(target);
		if (*retval != ERROR_OK) {
			LOG_ERROR("Failed semihosting operation");
			return 0;
		}
	}

	/* Post result to target if we are not waiting on a fileio
	 * operation to complete:
	 */
	if (!arm->semihosting_hit_fileio) {
		*retval = post_result(target);
		if (*retval != ERROR_OK) {
			LOG_ERROR("Failed to post semihosting result");
			return 0;
		}

		*retval = target_resume(target, 1, 0, 0, 0);
		if (*retval != ERROR_OK) {
			LOG_ERROR("Failed to resume target");
			return 0;
		}

		return 1;
	}

	return 0;
}