Beispiel #1
0
int arm966e_init_arch_info(struct target *target, struct arm966e_common *arm966e, struct jtag_tap *tap)
{
	struct arm7_9_common *arm7_9 = &arm966e->arm7_9_common;

	/* initialize arm7/arm9 specific info (including armv4_5) */
	arm9tdmi_init_arch_info(target, arm7_9, tap);

	arm966e->common_magic = ARM966E_COMMON_MAGIC;

	/* The ARM966E-S implements the ARMv5TE architecture which
	 * has the BKPT instruction, so we don't have to use a watchpoint comparator
	 */
	arm7_9->arm_bkpt = ARMV5_BKPT(0x0);
	arm7_9->thumb_bkpt = ARMV5_T_BKPT(0x0) & 0xffff;

	return ERROR_OK;
}
Beispiel #2
0
static int lpc2000_iap_working_area_init(struct flash_bank *bank, struct working_area **iap_working_area)
{
	struct target *target = bank->target;
	struct lpc2000_flash_bank *lpc2000_info = bank->driver_priv;

	if (target_alloc_working_area(target, IAP_CODE_LEN + lpc2000_info->iap_max_stack, iap_working_area) != ERROR_OK) {
		LOG_ERROR("no working area specified, can't write LPC2000 internal flash");
		return ERROR_FLASH_OPERATION_FAILED;
	}

	uint8_t jump_gate[8];

	/* write IAP code to working area */
	switch (lpc2000_info->variant) {
		case lpc800:
		case lpc1100:
		case lpc1500:
		case lpc1700:
		case lpc4300:
		case lpc54100:
		case lpc_auto:
			target_buffer_set_u32(target, jump_gate, ARMV4_5_T_BX(12));
			target_buffer_set_u32(target, jump_gate + 4, ARMV5_T_BKPT(0));
			break;
		case lpc2000_v1:
		case lpc2000_v2:
			target_buffer_set_u32(target, jump_gate, ARMV4_5_BX(12));
			target_buffer_set_u32(target, jump_gate + 4, ARMV4_5_B(0xfffffe, 0));
			break;
		default:
			LOG_ERROR("BUG: unknown lpc2000_info->variant encountered");
			exit(-1);
	}

	int retval = target_write_memory(target, (*iap_working_area)->address, 4, 2, jump_gate);
	if (retval != ERROR_OK) {
		LOG_ERROR("Write memory at address 0x%8.8" PRIx32 " failed (check work_area definition)",
				(*iap_working_area)->address);
		target_free_working_area(target, *iap_working_area);
	}

	return retval;
}
Beispiel #3
0
int arm926ejs_init_arch_info(struct target *target, struct arm926ejs_common *arm926ejs,
		struct jtag_tap *tap)
{
	struct arm7_9_common *arm7_9 = &arm926ejs->arm7_9_common;

	arm7_9->arm.mrc = arm926ejs_mrc;
	arm7_9->arm.mcr = arm926ejs_mcr;

	/* initialize arm7/arm9 specific info (including armv4_5) */
	arm9tdmi_init_arch_info(target, arm7_9, tap);

	arm926ejs->common_magic = ARM926EJS_COMMON_MAGIC;

	arm7_9->post_debug_entry = arm926ejs_post_debug_entry;
	arm7_9->pre_restore_context = arm926ejs_pre_restore_context;
	arm7_9->write_memory = arm926ejs_write_memory;

	arm926ejs->read_cp15 = arm926ejs_cp15_read;
	arm926ejs->write_cp15 = arm926ejs_cp15_write;
	arm926ejs->armv4_5_mmu.armv4_5_cache.ctype = -1;
	arm926ejs->armv4_5_mmu.get_ttb = arm926ejs_get_ttb;
	arm926ejs->armv4_5_mmu.read_memory = arm7_9_read_memory;
	arm926ejs->armv4_5_mmu.write_memory = arm7_9_write_memory;
	arm926ejs->armv4_5_mmu.disable_mmu_caches = arm926ejs_disable_mmu_caches;
	arm926ejs->armv4_5_mmu.enable_mmu_caches = arm926ejs_enable_mmu_caches;
	arm926ejs->armv4_5_mmu.has_tiny_pages = 1;
	arm926ejs->armv4_5_mmu.mmu_enabled = 0;

	arm7_9->examine_debug_reason = arm926ejs_examine_debug_reason;

	/* The ARM926EJ-S implements the ARMv5TE architecture which
	 * has the BKPT instruction, so we don't have to use a watchpoint comparator
	 */
	arm7_9->arm_bkpt = ARMV5_BKPT(0x0);
	arm7_9->thumb_bkpt = ARMV5_T_BKPT(0x0) & 0xffff;

	return ERROR_OK;
}
Beispiel #4
0
/* call LPC1700/LPC2000 IAP function
 * uses 180 bytes working area
 * 0x0 to 0x7: jump gate (BX to thumb state, b -2 to wait)
 * 0x8 to 0x1f: command parameter table (1+5 words)
 * 0x20 to 0x33: command result table (1+4 words)
 * 0x34 to 0xb3: stack (only 128b needed)
 */
static int lpc2000_iap_call(struct flash_bank *bank,
	int code,
	uint32_t param_table[5],
	uint32_t result_table[4])
{
	int retval;
	struct lpc2000_flash_bank *lpc2000_info = bank->driver_priv;
	struct target *target = bank->target;
	struct mem_param mem_params[2];
	struct reg_param reg_params[5];
	struct arm_algorithm arm_algo;	/* for LPC2000 */
	struct armv7m_algorithm armv7m_info;	/* for LPC1700 */
	uint32_t status_code;
	uint32_t iap_entry_point = 0;	/* to make compiler happier */

	/* regrab previously allocated working_area, or allocate a new one */
	if (!lpc2000_info->iap_working_area) {
		uint8_t jump_gate[8];

		/* make sure we have a working area */
		if (target_alloc_working_area(target, 180,
				&lpc2000_info->iap_working_area) != ERROR_OK) {
			LOG_ERROR("no working area specified, can't write LPC2000 internal flash");
			return ERROR_FLASH_OPERATION_FAILED;
		}

		/* write IAP code to working area */
		switch (lpc2000_info->variant) {
			case lpc1700:
				target_buffer_set_u32(target, jump_gate, ARMV4_5_T_BX(12));
				target_buffer_set_u32(target, jump_gate + 4, ARMV5_T_BKPT(0));
				break;
			case lpc2000_v1:
			case lpc2000_v2:
				target_buffer_set_u32(target, jump_gate, ARMV4_5_BX(12));
				target_buffer_set_u32(target, jump_gate + 4, ARMV4_5_B(0xfffffe, 0));
				break;
			default:
				LOG_ERROR("BUG: unknown lpc2000_info->variant encountered");
				exit(-1);
		}

		retval = target_write_memory(target,
				lpc2000_info->iap_working_area->address, 4, 2, jump_gate);
		if (retval != ERROR_OK) {
			LOG_ERROR(
				"Write memory at address 0x%8.8" PRIx32 " failed (check work_area definition)",
				lpc2000_info->iap_working_area->address);
			return retval;
		}
	}

	switch (lpc2000_info->variant) {
		case lpc1700:
			armv7m_info.common_magic = ARMV7M_COMMON_MAGIC;
			armv7m_info.core_mode = ARMV7M_MODE_ANY;
			iap_entry_point = 0x1fff1ff1;
			break;
		case lpc2000_v1:
		case lpc2000_v2:
			arm_algo.common_magic = ARM_COMMON_MAGIC;
			arm_algo.core_mode = ARM_MODE_SVC;
			arm_algo.core_state = ARM_STATE_ARM;
			iap_entry_point = 0x7ffffff1;
			break;
		default:
			LOG_ERROR("BUG: unknown lpc2000->variant encountered");
			exit(-1);
	}

	/* command parameter table */
	init_mem_param(&mem_params[0], lpc2000_info->iap_working_area->address + 8, 6 * 4,
		PARAM_OUT);
	target_buffer_set_u32(target, mem_params[0].value, code);
	target_buffer_set_u32(target, mem_params[0].value + 0x04, param_table[0]);
	target_buffer_set_u32(target, mem_params[0].value + 0x08, param_table[1]);
	target_buffer_set_u32(target, mem_params[0].value + 0x0c, param_table[2]);
	target_buffer_set_u32(target, mem_params[0].value + 0x10, param_table[3]);
	target_buffer_set_u32(target, mem_params[0].value + 0x14, param_table[4]);

	init_reg_param(&reg_params[0], "r0", 32, PARAM_OUT);
	buf_set_u32(reg_params[0].value, 0, 32, lpc2000_info->iap_working_area->address + 0x08);

	/* command result table */
	init_mem_param(&mem_params[1],
		lpc2000_info->iap_working_area->address + 0x20,
		5 * 4,
		PARAM_IN);

	init_reg_param(&reg_params[1], "r1", 32, PARAM_OUT);
	buf_set_u32(reg_params[1].value, 0, 32, lpc2000_info->iap_working_area->address + 0x20);

	/* IAP entry point */
	init_reg_param(&reg_params[2], "r12", 32, PARAM_OUT);
	buf_set_u32(reg_params[2].value, 0, 32, iap_entry_point);

	switch (lpc2000_info->variant) {
		case lpc1700:
			/* IAP stack */
			init_reg_param(&reg_params[3], "sp", 32, PARAM_OUT);
			buf_set_u32(reg_params[3].value, 0, 32,
					lpc2000_info->iap_working_area->address + 0xb4);

			/* return address */
			init_reg_param(&reg_params[4], "lr", 32, PARAM_OUT);
			buf_set_u32(reg_params[4].value, 0, 32,
					(lpc2000_info->iap_working_area->address + 0x04) | 1);
			/* bit0 of LR = 1 to return in Thumb mode */

			target_run_algorithm(target, 2, mem_params, 5, reg_params,
					lpc2000_info->iap_working_area->address, 0, 10000, &armv7m_info);
			break;
		case lpc2000_v1:
		case lpc2000_v2:
			/* IAP stack */
			init_reg_param(&reg_params[3], "sp_svc", 32, PARAM_OUT);
			buf_set_u32(reg_params[3].value, 0, 32,
					lpc2000_info->iap_working_area->address + 0xb4);

			/* return address */
			init_reg_param(&reg_params[4], "lr_svc", 32, PARAM_OUT);
			buf_set_u32(reg_params[4].value, 0, 32,
					lpc2000_info->iap_working_area->address + 0x04);

			target_run_algorithm(target, 2, mem_params, 5, reg_params,
					lpc2000_info->iap_working_area->address,
					lpc2000_info->iap_working_area->address + 0x4,
					10000, &arm_algo);
			break;
		default:
			LOG_ERROR("BUG: unknown lpc2000->variant encountered");
			exit(-1);
	}

	status_code = target_buffer_get_u32(target, mem_params[1].value);
	result_table[0] = target_buffer_get_u32(target, mem_params[1].value + 0x04);
	result_table[1] = target_buffer_get_u32(target, mem_params[1].value + 0x08);
	result_table[2] = target_buffer_get_u32(target, mem_params[1].value + 0x0c);
	result_table[3] = target_buffer_get_u32(target, mem_params[1].value + 0x10);

	LOG_DEBUG("IAP command = %i (0x%8.8" PRIx32 ", 0x%8.8" PRIx32
			", 0x%8.8" PRIx32 ", 0x%8.8" PRIx32 ", 0x%8.8"
			PRIx32 ") completed with result = %8.8" PRIx32,
			code, param_table[0], param_table[1], param_table[2],
			param_table[3], param_table[4], status_code);

	destroy_mem_param(&mem_params[0]);
	destroy_mem_param(&mem_params[1]);

	destroy_reg_param(&reg_params[0]);
	destroy_reg_param(&reg_params[1]);
	destroy_reg_param(&reg_params[2]);
	destroy_reg_param(&reg_params[3]);
	destroy_reg_param(&reg_params[4]);

	return status_code;
}