Skip to content
Snippets Groups Projects
arm11.c 43.8 KiB
Newer Older
	/* assert reset lines */
	/* resets only the DBGTAP, not the ARM */
	jtag_add_reset(1, 0);
	jtag_add_sleep(5000);
	arm11_common_t * arm11 = target->arch_info;
	arm11->trst_active = true;
	if (target->reset_halt)
	{
		int retval;
		if ((retval = target_halt(target))!=ERROR_OK)
			return retval;
}

int arm11_deassert_reset(struct target_s *target)
{
	LOG_DEBUG("target->state: %s",
		  Jim_Nvp_value2name_simple( nvp_target_state, target->state )->name );
	/* deassert reset lines */
	jtag_add_reset(0, 0);
	arm11_common_t * arm11 = target->arch_info;
	arm11->trst_active = false;
	if (arm11->halt_requested)
	return arm11_halt(target);
#endif

}

int arm11_soft_reset_halt(struct target_s *target)
{
	FNC_INFO_NOTIMPLEMENTED;
}

/* target register access for gdb */
int arm11_get_gdb_reg_list(struct target_s *target, struct reg_s **reg_list[], int *reg_list_size)
{
	arm11_common_t * arm11 = target->arch_info;
	*reg_list_size	= ARM11_GDB_REGISTER_COUNT;
	*reg_list		= malloc(sizeof(reg_t*) * ARM11_GDB_REGISTER_COUNT);
	{size_t i;
	for (i = 16; i < 24; i++)
	{
	(*reg_list)[i] = &arm11_gdb_dummy_fp_reg;
	(*reg_list)[24] = &arm11_gdb_dummy_fps_reg;
	{size_t i;
	for (i = 0; i < ARM11_REGCACHE_COUNT; i++)
	{
	if (arm11_reg_defs[i].gdb_num == -1)

	(*reg_list)[arm11_reg_defs[i].gdb_num] = arm11->reg_list + i;
* size: 1 = byte (8bit), 2 = half-word (16bit), 4 = word (32bit)
* count: number of items of <size>
*/
int arm11_read_memory(struct target_s *target, u32 address, u32 size, u32 count, u8 *buffer)
{
	/** \todo TODO: check if buffer cast to u32* and u16* might cause alignment problems */
	if (target->state != TARGET_HALTED)
	{
	LOG_WARNING("target was not halted");
	return ERROR_TARGET_NOT_HALTED;
	LOG_DEBUG("ADDR %08x  SIZE %08x  COUNT %08x", address, size, count);
	arm11_common_t * arm11 = target->arch_info;
	arm11_run_instr_data_prepare(arm11);
	/* MRC p14,0,r0,c0,c5,0 */
	arm11_run_instr_data_to_core1(arm11, 0xee100e15, address);
	/** \todo TODO: check if dirty is the right choice to force a rewrite on arm11_resume() */
	arm11->reg_list[ARM11_RC_R1].dirty = 1;

oharboe's avatar
oharboe committed
	{size_t i;
	for (i = 0; i < count; i++)
		/* ldrb    r1, [r0], #1 */
		arm11_run_instr_no_data1(arm11, 0xe4d01001);
		u32 res;
		/* MCR p14,0,R1,c0,c5,0 */
		arm11_run_instr_data_from_core(arm11, 0xEE001E15, &res, 1);
oharboe's avatar
oharboe committed
	}}

	arm11->reg_list[ARM11_RC_R1].dirty = 1;

	u16 * buf16 = (u16*)buffer;

oharboe's avatar
oharboe committed
	{size_t i;
	for (i = 0; i < count; i++)
		/* ldrh    r1, [r0], #2 */
		arm11_run_instr_no_data1(arm11, 0xe0d010b2);
		/* MCR p14,0,R1,c0,c5,0 */
		arm11_run_instr_data_from_core(arm11, 0xEE001E15, &res, 1);
oharboe's avatar
oharboe committed
	}}


	/* LDC p14,c5,[R0],#4 */
	arm11_run_instr_data_from_core(arm11, 0xecb05e01, (u32 *)buffer, count);
	break;
	arm11_run_instr_data_finish(arm11);
}

int arm11_write_memory(struct target_s *target, u32 address, u32 size, u32 count, u8 *buffer)
{
	if (target->state != TARGET_HALTED)
	{
	LOG_WARNING("target was not halted");
	return ERROR_TARGET_NOT_HALTED;
	LOG_DEBUG("ADDR %08x  SIZE %08x  COUNT %08x", address, size, count);
	arm11_common_t * arm11 = target->arch_info;
	arm11_run_instr_data_prepare(arm11);
	/* MRC p14,0,r0,c0,c5,0 */
	arm11_run_instr_data_to_core1(arm11, 0xee100e15, address);
	arm11->reg_list[ARM11_RC_R1].dirty = 1;

oharboe's avatar
oharboe committed
	{size_t i;
	for (i = 0; i < count; i++)
		/* MRC p14,0,r1,c0,c5,0 */
		arm11_run_instr_data_to_core1(arm11, 0xee101e15, *buffer++);
		/* strb    r1, [r0], #1 */
		arm11_run_instr_no_data1(arm11, 0xe4c01001);
oharboe's avatar
oharboe committed
	}}

	arm11->reg_list[ARM11_RC_R1].dirty = 1;

	u16 * buf16 = (u16*)buffer;

oharboe's avatar
oharboe committed
	{size_t i;
	for (i = 0; i < count; i++)
		/* MRC p14,0,r1,c0,c5,0 */
		arm11_run_instr_data_to_core1(arm11, 0xee101e15, *buf16++);
		/* strh    r1, [r0], #2 */
		arm11_run_instr_no_data1(arm11, 0xe0c010b2);
oharboe's avatar
oharboe committed
	}}

	/** \todo TODO: check if buffer cast to u32* might cause alignment problems */

oharboe's avatar
oharboe committed
	if (!arm11_config_memwrite_burst)
	{
		/* STC p14,c5,[R0],#4 */
		arm11_run_instr_data_to_core(arm11, 0xeca05e01, (u32 *)buffer, count);
oharboe's avatar
oharboe committed
	}
	else
	{
		/* STC p14,c5,[R0],#4 */
		arm11_run_instr_data_to_core_noack(arm11, 0xeca05e01, (u32 *)buffer, count);
oharboe's avatar
oharboe committed
	}

oharboe's avatar
oharboe committed
#if 1
	/* r0 verification */
	{
oharboe's avatar
oharboe committed
	u32 r0;

	/* MCR p14,0,R0,c0,c5,0 */
	arm11_run_instr_data_from_core(arm11, 0xEE000E15, &r0, 1);

	if (address + size * count != r0)
	{
		LOG_ERROR("Data transfer failed. (%d)", (r0 - address) - size * count);
oharboe's avatar
oharboe committed

		if (arm11_config_memwrite_burst)
		LOG_ERROR("use 'arm11 memwrite burst disable' to disable fast burst mode");
oharboe's avatar
oharboe committed

		if (arm11_config_memwrite_error_fatal)
			return ERROR_FAIL;
	}
oharboe's avatar
oharboe committed
	}
#endif

	arm11_run_instr_data_finish(arm11);
oharboe's avatar
oharboe committed

}


/* write target memory in multiples of 4 byte, optimized for writing large quantities of data */
int arm11_bulk_write_memory(struct target_s *target, u32 address, u32 count, u8 *buffer)
{
	if (target->state != TARGET_HALTED)
	{
	LOG_WARNING("target was not halted");
	return ERROR_TARGET_NOT_HALTED;
	return arm11_write_memory(target, address, 4, count, buffer);
}

int arm11_checksum_memory(struct target_s *target, u32 address, u32 count, u32* checksum)
{
	FNC_INFO_NOTIMPLEMENTED;
* rw: 0 = write, 1 = read, 2 = access
*/
int arm11_add_breakpoint(struct target_s *target, breakpoint_t *breakpoint)
{
oharboe's avatar
oharboe committed

	arm11_common_t * arm11 = target->arch_info;
oharboe's avatar
oharboe committed

#if 0
	if (breakpoint->type == BKPT_SOFT)
	{
	LOG_INFO("sw breakpoint requested, but software breakpoints not enabled");
oharboe's avatar
oharboe committed
	return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
oharboe's avatar
oharboe committed
#endif

	if (!arm11->free_brps)
	{
	LOG_INFO("no breakpoint unit available for hardware breakpoint");
oharboe's avatar
oharboe committed
	return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
oharboe's avatar
oharboe committed

	if (breakpoint->length != 4)
	{
	LOG_INFO("only breakpoints of four bytes length supported");
oharboe's avatar
oharboe committed
	return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
oharboe's avatar
oharboe committed

	arm11->free_brps--;
}

int arm11_remove_breakpoint(struct target_s *target, breakpoint_t *breakpoint)
{
oharboe's avatar
oharboe committed

	arm11_common_t * arm11 = target->arch_info;
	arm11->free_brps++;
}

int arm11_add_watchpoint(struct target_s *target, watchpoint_t *watchpoint)
{
	FNC_INFO_NOTIMPLEMENTED;
}

int arm11_remove_watchpoint(struct target_s *target, watchpoint_t *watchpoint)
{
	FNC_INFO_NOTIMPLEMENTED;
/* target algorithm support */
int arm11_run_algorithm(struct target_s *target, int num_mem_params, mem_param_t *mem_params,
			int num_reg_params, reg_param_t *reg_params, u32 entry_point, u32 exit_point,
			int timeout_ms, void *arch_info)
		arm11_common_t *arm11 = target->arch_info;
	armv4_5_algorithm_t *arm11_algorithm_info = arch_info;
//	enum armv4_5_state core_state = arm11->core_state;
//	enum armv4_5_mode core_mode = arm11->core_mode;
	u32 context[16];
	u32 cpsr;
	int exit_breakpoint_size = 0;
	int i;
	int retval = ERROR_OK;
		LOG_DEBUG("Running algorithm");

	if (arm11_algorithm_info->common_magic != ARMV4_5_COMMON_MAGIC)
	{
		LOG_ERROR("current target isn't an ARMV4/5 target");
		return ERROR_TARGET_INVALID;
	}
	if (target->state != TARGET_HALTED)
	{
		LOG_WARNING("target not halted");
		return ERROR_TARGET_NOT_HALTED;
	}

	// FIXME
//	if (armv4_5_mode_to_number(arm11->core_mode)==-1)
//		return ERROR_FAIL;

	// Save regs
	for (i = 0; i < 16; i++)
	{
		context[i] = buf_get_u32((u8*)(&arm11->reg_values[i]),0,32);
		LOG_DEBUG("Save %i: 0x%x",i,context[i]);
	}

	cpsr = buf_get_u32((u8*)(arm11->reg_values+ARM11_RC_CPSR),0,32);
	LOG_DEBUG("Save CPSR: 0x%x", cpsr);

	for (i = 0; i < num_mem_params; i++)
	{
		target_write_buffer(target, mem_params[i].address, mem_params[i].size, mem_params[i].value);
	}

	// Set register parameters
	for (i = 0; i < num_reg_params; i++)
	{
		reg_t *reg = register_get_by_name(arm11->core_cache, reg_params[i].reg_name, 0);
		if (!reg)
		{
			LOG_ERROR("BUG: register '%s' not found", reg_params[i].reg_name);
			exit(-1);
		}

		if (reg->size != reg_params[i].size)
		{
			LOG_ERROR("BUG: register '%s' size doesn't match reg_params[i].size", reg_params[i].reg_name);
			exit(-1);
		}
		arm11_set_reg(reg,reg_params[i].value);
//		printf("%i: Set %s =%08x\n", i, reg_params[i].reg_name,val);
	}

	exit_breakpoint_size = 4;

/*	arm11->core_state = arm11_algorithm_info->core_state;
	if (arm11->core_state == ARMV4_5_STATE_ARM)
				exit_breakpoint_size = 4;
	else if (arm11->core_state == ARMV4_5_STATE_THUMB)
		exit_breakpoint_size = 2;
	else
	{
		LOG_ERROR("BUG: can't execute algorithms when not in ARM or Thumb state");
		exit(-1);
	}
*/
	if (arm11_algorithm_info->core_mode != ARMV4_5_MODE_ANY)
	{
		LOG_DEBUG("setting core_mode: 0x%2.2x", arm11_algorithm_info->core_mode);
		buf_set_u32(arm11->reg_list[ARM11_RC_CPSR].value, 0, 5, arm11_algorithm_info->core_mode);
		arm11->reg_list[ARM11_RC_CPSR].dirty = 1;
		arm11->reg_list[ARM11_RC_CPSR].valid = 1;
	}

	if ((retval = breakpoint_add(target, exit_point, exit_breakpoint_size, BKPT_HARD)) != ERROR_OK)
	{
		LOG_ERROR("can't add breakpoint to finish algorithm execution");
		retval = ERROR_TARGET_FAILURE;
		goto restore;
	}

	// no debug, otherwise breakpoint is not set
	if((retval = target_resume(target, 0, entry_point, 1, 0)) != ERROR_OK)
	{
		return retval;
	}

	if((retval = target_wait_state(target, TARGET_HALTED, timeout_ms)) != ERROR_OK)
	{
		return retval;
	}

	if (target->state != TARGET_HALTED)
	{
		if ((retval=target_halt(target))!=ERROR_OK)
			return retval;
		if ((retval=target_wait_state(target, TARGET_HALTED, 500))!=ERROR_OK)
		{
			return retval;
		}
		retval = ERROR_TARGET_TIMEOUT;
		goto del_breakpoint;
	}

	if (buf_get_u32(arm11->reg_list[15].value, 0, 32) != exit_point)
	{
		LOG_WARNING("target reentered debug state, but not at the desired exit point: 0x%4.4x",
			buf_get_u32(arm11->reg_list[15].value, 0, 32));
		retval = ERROR_TARGET_TIMEOUT;
		goto del_breakpoint;
	}

	for (i = 0; i < num_mem_params; i++)
	{
		if (mem_params[i].direction != PARAM_OUT)
			target_read_buffer(target, mem_params[i].address, mem_params[i].size, mem_params[i].value);
	}

	for (i = 0; i < num_reg_params; i++)
	{
		if (reg_params[i].direction != PARAM_OUT)
		{
			reg_t *reg = register_get_by_name(arm11->core_cache, reg_params[i].reg_name, 0);
			if (!reg)
			{
				LOG_ERROR("BUG: register '%s' not found", reg_params[i].reg_name);
				exit(-1);
			}

			if (reg->size != reg_params[i].size)
			{
				LOG_ERROR("BUG: register '%s' size doesn't match reg_params[i].size", reg_params[i].reg_name);
				exit(-1);
			}

			buf_set_u32(reg_params[i].value, 0, 32, buf_get_u32(reg->value, 0, 32));
		}
	}

del_breakpoint:
	breakpoint_remove(target, exit_point);

restore:
	// Restore context
	for (i = 0; i < 16; i++)
	{
		LOG_DEBUG("restoring register %s with value 0x%8.8x",
			 arm11->reg_list[i].name, context[i]);
		arm11_set_reg(&arm11->reg_list[i], (u8*)&context[i]);
	}
	LOG_DEBUG("restoring CPSR with value 0x%8.8x", cpsr);
	arm11_set_reg(&arm11->reg_list[ARM11_RC_CPSR], (u8*)&cpsr);

//	arm11->core_state = core_state;
//	arm11->core_mode = core_mode;

	return retval;
int arm11_target_create(struct target_s *target, Jim_Interp *interp)
	int retval = ERROR_OK;
	NEW(arm11_common_t, arm11, 1);
	arm11->target = target;
	/* prepare JTAG information for the new target */
	arm11->jtag_info.chain_pos	= target->chain_position;
	arm11->jtag_info.scann_size	= 5;
	if((retval = arm_jtag_setup_connection(&arm11->jtag_info)) != ERROR_OK)
	{
		return retval;
	}
	jtag_device_t *device = jtag_get_device(target->chain_position);
	if (device->ir_length != 5)
	{
		LOG_ERROR("'target arm11' expects 'jtag_device 5 0x01 0x1F 0x1E'");
		return ERROR_COMMAND_SYNTAX_ERROR;
	target->arch_info = arm11;
}

int arm11_init_target(struct command_context_s *cmd_ctx, struct target_s *target)
{
	/* Initialize anything we can set up without talking to the target */
	return arm11_build_reg_cache(target);

int arm11_examine(struct target_s *target)
	arm11_common_t * arm11 = target->arch_info;
	/* check IDCODE */
	arm11_add_IR(arm11, ARM11_IDCODE, -1);
	scan_field_t		idcode_field;
	arm11_setup_field(arm11, 32, NULL, &arm11->device_id, &idcode_field);
	arm11_add_dr_scan_vc(1, &idcode_field, TAP_PD);
	arm11_add_debug_SCAN_N(arm11, 0x00, -1);
	arm11_add_IR(arm11, ARM11_INTEST, -1);
	scan_field_t		chain0_fields[2];
	arm11_setup_field(arm11, 32, NULL,	&arm11->didr,		chain0_fields + 0);
	arm11_setup_field(arm11,  8, NULL,	&arm11->implementor,	chain0_fields + 1);
	arm11_add_dr_scan_vc(asizeof(chain0_fields), chain0_fields, TAP_RTI);
	if ((retval=jtag_execute_queue())!=ERROR_OK)
		return retval;
	switch (arm11->device_id & 0x0FFFF000)
	{
	case 0x07B36000:	LOG_INFO("found ARM1136"); break;
	case 0x07B56000:	LOG_INFO("found ARM1156"); break;
	case 0x07B76000:	LOG_INFO("found ARM1176"); break;
	default:
	{
		LOG_ERROR("'target arm11' expects IDCODE 0x*7B*7****");
		return ERROR_FAIL;
	arm11->debug_version = (arm11->didr >> 16) & 0x0F;
oharboe's avatar
oharboe committed

	if (arm11->debug_version != ARM11_DEBUG_V6 &&
oharboe's avatar
oharboe committed
	arm11->debug_version != ARM11_DEBUG_V61)
	LOG_ERROR("Only ARMv6 v6 and v6.1 architectures supported.");
	return ERROR_FAIL;
oharboe's avatar
oharboe committed


	arm11->brp	= ((arm11->didr >> 24) & 0x0F) + 1;
	arm11->wrp	= ((arm11->didr >> 28) & 0x0F) + 1;
	/** \todo TODO: reserve one brp slot if we allow breakpoints during step */
	arm11->free_brps = arm11->brp;
	arm11->free_wrps = arm11->wrp;
	LOG_DEBUG("IDCODE %08x IMPLEMENTOR %02x DIDR %08x",
	arm11->device_id,
	arm11->implementor,
	arm11->didr);

	/* as a side-effect this reads DSCR and thus
	 * clears the ARM11_DSCR_STICKY_PRECISE_DATA_ABORT / Sticky Precise Data Abort Flag
	 * as suggested by the spec.
	 */
	arm11_check_init(arm11, NULL);
	target->type->examined = 1;
}

int arm11_quit(void)
{
	FNC_INFO_NOTIMPLEMENTED;
}

/** Load a register that is marked !valid in the register cache */
int arm11_get_reg(reg_t *reg)
{
	target_t * target = ((arm11_reg_state_t *)reg->arch_info)->target;
	if (target->state != TARGET_HALTED)
	{
	LOG_WARNING("target was not halted");
	return ERROR_TARGET_NOT_HALTED;
	/** \todo TODO: Check this. We assume that all registers are fetched at debug entry. */
	arm11_common_t *arm11 = target->arch_info;
	const arm11_reg_defs_t * arm11_reg_info = arm11_reg_defs + ((arm11_reg_state_t *)reg->arch_info)->def_index;
}

/** Change a value in the register cache */
int arm11_set_reg(reg_t *reg, u8 *buf)
{
	target_t * target = ((arm11_reg_state_t *)reg->arch_info)->target;
	arm11_common_t *arm11 = target->arch_info;
//	  const arm11_reg_defs_t * arm11_reg_info = arm11_reg_defs + ((arm11_reg_state_t *)reg->arch_info)->def_index;
	arm11->reg_values[((arm11_reg_state_t *)reg->arch_info)->def_index] = buf_get_u32(buf, 0, 32);
	reg->valid	= 1;
	reg->dirty	= 1;
int arm11_build_reg_cache(target_t *target)
	arm11_common_t *arm11 = target->arch_info;

	NEW(reg_cache_t,		cache,			1);
	NEW(reg_t,			reg_list,		ARM11_REGCACHE_COUNT);
	NEW(arm11_reg_state_t,	arm11_reg_states,	ARM11_REGCACHE_COUNT);
	if (arm11_regs_arch_type == -1)
		arm11_regs_arch_type = register_reg_arch_type(arm11_get_reg, arm11_set_reg);
	register_init_dummy(&arm11_gdb_dummy_fp_reg);
	register_init_dummy(&arm11_gdb_dummy_fps_reg);
	arm11->reg_list	= reg_list;
	/* Build the process context cache */
	cache->name		= "arm11 registers";
	cache->next		= NULL;
	cache->reg_list	= reg_list;
	cache->num_regs	= ARM11_REGCACHE_COUNT;
	reg_cache_t **cache_p = register_get_last_cache_p(&target->reg_cache);
	(*cache_p) = cache;
	arm11->core_cache = cache;
//	  armv7m->process_context = cache;
	/* Not very elegant assertion */
	if (ARM11_REGCACHE_COUNT != asizeof(arm11->reg_values) ||
	ARM11_REGCACHE_COUNT != asizeof(arm11_reg_defs) ||
	ARM11_REGCACHE_COUNT != ARM11_RC_MAX)
	LOG_ERROR("BUG: arm11->reg_values inconsistent (%d " ZU " " ZU " %d)", ARM11_REGCACHE_COUNT, asizeof(arm11->reg_values), asizeof(arm11_reg_defs), ARM11_RC_MAX);
	exit(-1);
	for (i = 0; i < ARM11_REGCACHE_COUNT; i++)
	{
	reg_t *				r	= reg_list		+ i;
	const arm11_reg_defs_t *	rd	= arm11_reg_defs	+ i;
	arm11_reg_state_t *		rs	= arm11_reg_states	+ i;

	r->name			= rd->name;
	r->size			= 32;
	r->value		= (u8 *)(arm11->reg_values + i);
	r->dirty		= 0;
	r->valid		= 0;
	r->bitfield_desc	= NULL;
	r->num_bitfields	= 0;
	r->arch_type		= arm11_regs_arch_type;
	r->arch_info		= rs;

	rs->def_index		= i;
	rs->target		= target;
oharboe's avatar
oharboe committed
int arm11_handle_bool(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, bool * var, char * name)
oharboe's avatar
oharboe committed
{
	LOG_INFO("%s is %s.", name, *var ? "enabled" : "disabled");
oharboe's avatar
oharboe committed
	return ERROR_OK;
oharboe's avatar
oharboe committed

oharboe's avatar
oharboe committed
	return ERROR_COMMAND_SYNTAX_ERROR;

	switch (args[0][0])
	{
	case '0':	/* 0 */
	case 'f':	/* false */
	case 'F':
	case 'd':	/* disable */
	case 'D':
oharboe's avatar
oharboe committed
	*var = false;
oharboe's avatar
oharboe committed
	break;

	case '1':	/* 1 */
	case 't':	/* true */
	case 'T':
	case 'e':	/* enable */
	case 'E':
oharboe's avatar
oharboe committed
	*var = true;
oharboe's avatar
oharboe committed
	break;
oharboe's avatar
oharboe committed

	LOG_INFO("%s %s.", *var ? "Enabled" : "Disabled", name);
oharboe's avatar
oharboe committed

oharboe's avatar
oharboe committed
}

#define BOOL_WRAPPER(name, print_name)	\
oharboe's avatar
oharboe committed
int arm11_handle_bool_##name(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc) \
{ \
	return arm11_handle_bool(cmd_ctx, cmd, args, argc, &arm11_config_##name, print_name); \
oharboe's avatar
oharboe committed
}

#define RC_TOP(name, descr, more)  \
{ \
	command_t * new_cmd = register_command(cmd_ctx, top_cmd, name, NULL, COMMAND_ANY, descr);  \
	command_t * top_cmd = new_cmd; \
	more \
oharboe's avatar
oharboe committed
}
#define RC_FINAL(name, descr, handler)	\
	register_command(cmd_ctx, top_cmd, name, handler, COMMAND_ANY, descr);
oharboe's avatar
oharboe committed
#define RC_FINAL_BOOL(name, descr, var)  \
	register_command(cmd_ctx, top_cmd, name, arm11_handle_bool_##var, COMMAND_ANY, descr);
oharboe's avatar
oharboe committed

BOOL_WRAPPER(memwrite_burst,		"memory write burst mode")
BOOL_WRAPPER(memwrite_error_fatal,	"fatal error mode for memory writes")

int arm11_handle_vcr(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
{
oharboe's avatar
oharboe committed
	arm11_vcr = strtoul(args[0], NULL, 0);
oharboe's avatar
oharboe committed
	return ERROR_COMMAND_SYNTAX_ERROR;
oharboe's avatar
oharboe committed

	LOG_INFO("VCR 0x%08X", arm11_vcr);
	return ERROR_OK;
oharboe's avatar
oharboe committed
}

const u32 arm11_coproc_instruction_limits[] =
{
	15,			/* coprocessor */
	7,			/* opcode 1 */
	15,			/* CRn */
	15,			/* CRm */
	7,			/* opcode 2 */
	0xFFFFFFFF,		/* value */
};

const char arm11_mrc_syntax[] = "Syntax: mrc <jtag_target> <coprocessor> <opcode 1> <CRn> <CRm> <opcode 2>. All parameters are numbers only.";
const char arm11_mcr_syntax[] = "Syntax: mcr <jtag_target> <coprocessor> <opcode 1> <CRn> <CRm> <opcode 2> <32bit value to write>. All parameters are numbers only.";

arm11_common_t * arm11_find_target(const char * arg)
{
	size_t jtag_target		= strtoul(arg, NULL, 0);
	{target_t * t;
	for (t = all_targets; t; t = t->next)
	{
		if (strcmp(t->type->name,"arm11"))
		continue;

	arm11_common_t * arm11 = t->arch_info;

	if (arm11->jtag_info.chain_pos != jtag_target)
}

int arm11_handle_mrc_mcr(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, bool read)
{
	if (argc != (read ? 6 : 7))
	{
	LOG_ERROR("Invalid number of arguments. %s", read ? arm11_mrc_syntax : arm11_mcr_syntax);
	arm11_common_t * arm11 = arm11_find_target(args[0]);
	LOG_ERROR("Parameter 1 is not a the JTAG chain position of an ARM11 device. %s",
		read ? arm11_mrc_syntax : arm11_mcr_syntax);

	return -1;

	if (arm11->target->state != TARGET_HALTED)
	{
	LOG_WARNING("target was not halted");
	return ERROR_TARGET_NOT_HALTED;
	{size_t i;
	for (i = 0; i < (read ? 5 : 6); i++)
	{
	values[i] = strtoul(args[i + 1], NULL, 0);

	if (values[i] > arm11_coproc_instruction_limits[i])
	{
		LOG_ERROR("Parameter %ld out of bounds (%d max). %s",
			  (long)(i + 2), arm11_coproc_instruction_limits[i],
		read ? arm11_mrc_syntax : arm11_mcr_syntax);
	u32 instr = 0xEE000010	|
	(values[0] <<  8) |
	(values[1] << 21) |
	(values[2] << 16) |
	(values[3] <<  0) |
	(values[4] <<  5);

	arm11_run_instr_data_prepare(arm11);
	arm11_run_instr_data_from_core_via_r0(arm11, instr, &result);

	LOG_INFO("MRC p%d, %d, R0, c%d, c%d, %d = 0x%08x (%d)",
		values[0], values[1], values[2], values[3], values[4], result, result);
	}
	else
	{
	arm11_run_instr_data_to_core_via_r0(arm11, instr, values[5]);

	LOG_INFO("MRC p%d, %d, R0 (#0x%08x), c%d, c%d, %d",
		values[0], values[1],
		values[5],
		values[2], values[3], values[4]);
	}
	arm11_run_instr_data_finish(arm11);
}

int arm11_handle_mrc(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
{
	return arm11_handle_mrc_mcr(cmd_ctx, cmd, args, argc, true);
}

int arm11_handle_mcr(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
{
	return arm11_handle_mrc_mcr(cmd_ctx, cmd, args, argc, false);
oharboe's avatar
oharboe committed

int arm11_register_commands(struct command_context_s *cmd_ctx)
{
oharboe's avatar
oharboe committed

	command_t * top_cmd = NULL;
oharboe's avatar
oharboe committed

	RC_TOP(			"arm11",	"arm11 specific commands",
oharboe's avatar
oharboe committed

	RC_TOP(			"memwrite",	"Control memory write transfer mode",

		RC_FINAL_BOOL(	"burst",	"Enable/Disable non-standard but fast burst mode (default: enabled)",
oharboe's avatar
oharboe committed
						memwrite_burst)

		RC_FINAL_BOOL(	"error_fatal",
oharboe's avatar
oharboe committed
						"Terminate program if transfer error was found (default: enabled)",
						memwrite_error_fatal)
	)

	RC_FINAL(		"vcr",		"Control (Interrupt) Vector Catch Register",
						arm11_handle_vcr)

	RC_FINAL(		"mrc",		"Read Coprocessor register",
						arm11_handle_mrc)

	RC_FINAL(		"mcr",		"Write Coprocessor register",
						arm11_handle_mcr)
oharboe's avatar
oharboe committed

oharboe's avatar
oharboe committed
}