target.c 113 KB
Newer Older
4001
4002
			return e;
		}
zwelch's avatar
zwelch committed
4003
4004
		if (!target->tap->enabled)
			goto err_tap_disabled;
4005
		/* determine if we should halt or not. */
4006
		target->reset_halt = !!a;
4007
		/* When this happens - all workareas are invalid. */
4008
4009
		target_free_all_working_areas_restore(target, 0);

4010
		/* do the assert */
4011
4012
		if (n->value == NVP_ASSERT){
			target->type->assert_reset(target);
4013
		} else {
4014
			target->type->deassert_reset(target);
4015
4016
4017
		}
		return JIM_OK;
	case TS_CMD_HALT:
4018
		if (goi.argc){
4019
			Jim_WrongNumArgs(goi.interp, 0, argv, "halt [no parameters]");
4020
4021
			return JIM_ERR;
		}
zwelch's avatar
zwelch committed
4022
4023
		if (!target->tap->enabled)
			goto err_tap_disabled;
4024
		target->type->halt(target);
4025
4026
		return JIM_OK;
	case TS_CMD_WAITSTATE:
4027
		/* params:  <name>  statename timeoutmsecs */
4028
4029
		if (goi.argc != 2){
			Jim_SetResult_sprintf(goi.interp, "%s STATENAME TIMEOUTMSECS", n->name);
4030
4031
			return JIM_ERR;
		}
4032
4033
4034
		e = Jim_GetOpt_Nvp(&goi, nvp_target_state, &n);
		if (e != JIM_OK){
			Jim_GetOpt_NvpUnknown(&goi, nvp_target_state,1);
4035
4036
			return e;
		}
4037
4038
		e = Jim_GetOpt_Wide(&goi, &a);
		if (e != JIM_OK){
4039
4040
			return e;
		}
zwelch's avatar
zwelch committed
4041
4042
		if (!target->tap->enabled)
			goto err_tap_disabled;
4043
4044
		e = target_wait_state(target, n->value, a);
		if (e != ERROR_OK){
4045
			Jim_SetResult_sprintf(goi.interp,
4046
								   "target: %s wait %s fails (%d) %s",
4047
4048
								   target->cmd_name,
								   n->name,
4049
								   e, target_strerror_safe(e));
4050
4051
4052
4053
4054
4055
4056
4057
4058
4059
4060
			return JIM_ERR;
		} else {
			return JIM_OK;
		}
	case TS_CMD_EVENTLIST:
		/* List for human, Events defined for this target.
		 * scripts/programs should use 'name cget -event NAME'
		 */
		{
			target_event_action_t *teap;
			teap = target->event_action;
4061
			command_print(cmd_ctx, "Event actions for target (%d) %s\n",
4062
						   target->target_number,
4063
						   target->cmd_name);
4064
4065
			command_print(cmd_ctx, "%-25s | Body", "Event");
			command_print(cmd_ctx, "------------------------- | ----------------------------------------");
4066
			while (teap){
4067
				command_print(cmd_ctx,
4068
							   "%-25s | %s",
4069
4070
							   Jim_Nvp_value2name_simple(nvp_target_event, teap->event)->name,
							   Jim_GetString(teap->body, NULL));
4071
4072
				teap = teap->next;
			}
4073
			command_print(cmd_ctx, "***END***");
4074
4075
4076
			return JIM_OK;
		}
	case TS_CMD_CURSTATE:
4077
		if (goi.argc != 0){
4078
			Jim_WrongNumArgs(goi.interp, 0, argv, "[no parameters]");
4079
4080
			return JIM_ERR;
		}
4081
		Jim_SetResultString(goi.interp,
4082
4083
							 Jim_Nvp_value2name_simple(nvp_target_state,target->state)->name,-1);
		return JIM_OK;
4084
	case TS_CMD_INVOKE_EVENT:
4085
		if (goi.argc != 1){
4086
			Jim_SetResult_sprintf(goi.interp, "%s ?EVENTNAME?",n->name);
4087
4088
			return JIM_ERR;
		}
4089
4090
4091
		e = Jim_GetOpt_Nvp(&goi, nvp_target_event, &n);
		if (e != JIM_OK){
			Jim_GetOpt_NvpUnknown(&goi, nvp_target_event, 1);
4092
4093
			return e;
		}
4094
		target_handle_event(target, n->value);
4095
		return JIM_OK;
4096
4097
	}
	return JIM_ERR;
zwelch's avatar
zwelch committed
4098
4099
4100
4101

err_tap_disabled:
	Jim_SetResult_sprintf(interp, "[TAP is disabled]");
	return JIM_ERR;
4102
4103
}

4104
static int target_create(Jim_GetOptInfo *goi)
4105
{
4106
4107
4108
4109
4110
4111
4112
4113
4114
4115
	Jim_Obj *new_cmd;
	Jim_Cmd *cmd;
	const char *cp;
	char *cp2;
	int e;
	int x;
	target_t *target;
	struct command_context_s *cmd_ctx;

	cmd_ctx = Jim_GetAssocData(goi->interp, "context");
4116
	if (goi->argc < 3){
4117
		Jim_WrongNumArgs(goi->interp, 1, goi->argv, "?name? ?type? ..options...");
4118
4119
4120
4121
		return JIM_ERR;
	}

	/* COMMAND */
4122
	Jim_GetOpt_Obj(goi, &new_cmd);
4123
	/* does this command exist? */
4124
4125
4126
	cmd = Jim_GetCommand(goi->interp, new_cmd, JIM_ERRMSG);
	if (cmd){
		cp = Jim_GetString(new_cmd, NULL);
4127
4128
4129
		Jim_SetResult_sprintf(goi->interp, "Command/target: %s Exists", cp);
		return JIM_ERR;
	}
4130

4131
	/* TYPE */
4132
	e = Jim_GetOpt_String(goi, &cp2, NULL);
4133
4134
	cp = cp2;
	/* now does target type exist */
4135
4136
	for (x = 0 ; target_types[x] ; x++){
		if (0 == strcmp(cp, target_types[x]->name)){
4137
4138
4139
4140
			/* found */
			break;
		}
	}
4141
4142
4143
4144
	if (target_types[x] == NULL){
		Jim_SetResult_sprintf(goi->interp, "Unknown target type %s, try one of ", cp);
		for (x = 0 ; target_types[x] ; x++){
			if (target_types[x + 1]){
4145
				Jim_AppendStrings(goi->interp,
4146
4147
4148
4149
								   Jim_GetResult(goi->interp),
								   target_types[x]->name,
								   ", ", NULL);
			} else {
4150
				Jim_AppendStrings(goi->interp,
4151
4152
								   Jim_GetResult(goi->interp),
								   " or ",
4153
								   target_types[x]->name,NULL);
4154
4155
4156
4157
4158
4159
4160
4161
4162
4163
4164
4165
4166
			}
		}
		return JIM_ERR;
	}

	/* Create it */
	target = calloc(1,sizeof(target_t));
	/* set target number */
	target->target_number = new_target_number();

	/* allocate memory for each unique target type */
	target->type = (target_type_t*)calloc(1,sizeof(target_type_t));

4167
	memcpy(target->type, target_types[x], sizeof(target_type_t));
4168

4169
4170
4171
4172
4173
4174
4175
	/* will be set by "-endian" */
	target->endianness = TARGET_ENDIAN_UNKNOWN;

	target->working_area        = 0x0;
	target->working_area_size   = 0x0;
	target->working_areas       = NULL;
	target->backup_working_area = 0;
4176

4177
4178
4179
4180
4181
4182
4183
	target->state               = TARGET_UNKNOWN;
	target->debug_reason        = DBG_REASON_UNDEFINED;
	target->reg_cache           = NULL;
	target->breakpoints         = NULL;
	target->watchpoints         = NULL;
	target->next                = NULL;
	target->arch_info           = NULL;
4184

4185
4186
	target->display             = 1;

4187
4188
4189
4190
4191
4192
4193
4194
4195
	/* initialize trace information */
	target->trace_info = malloc(sizeof(trace_t));
	target->trace_info->num_trace_points         = 0;
	target->trace_info->trace_points_size        = 0;
	target->trace_info->trace_points             = NULL;
	target->trace_info->trace_history_size       = 0;
	target->trace_info->trace_history            = NULL;
	target->trace_info->trace_history_pos        = 0;
	target->trace_info->trace_history_overflowed = 0;
4196

4197
4198
4199
4200
4201
4202
4203
	target->dbgmsg          = NULL;
	target->dbg_msg_enabled = 0;

	target->endianness = TARGET_ENDIAN_UNKNOWN;

	/* Do the rest as "configure" options */
	goi->isconfigure = 1;
4204
	e = target_configure(goi, target);
4205
4206
4207

	if (target->tap == NULL)
	{
4208
		Jim_SetResultString(interp, "-chain-position required when creating target", -1);
zwelch's avatar
zwelch committed
4209
		e = JIM_ERR;
4210
4211
	}

4212
4213
4214
	if (e != JIM_OK){
		free(target->type);
		free(target);
4215
4216
4217
		return e;
	}

4218
	if (target->endianness == TARGET_ENDIAN_UNKNOWN){
4219
4220
4221
4222
		/* default endian to little if not specified */
		target->endianness = TARGET_LITTLE_ENDIAN;
	}

4223
4224
4225
	/* incase variant is not set */
	if (!target->variant)
		target->variant = strdup("");
4226

4227
	/* create the target specific commands */
4228
4229
	if (target->type->register_commands){
		(*(target->type->register_commands))(cmd_ctx);
4230
	}
4231
4232
	if (target->type->target_create){
		(*(target->type->target_create))(target, goi->interp);
4233
4234
4235
4236
4237
4238
	}

	/* append to end of list */
	{
		target_t **tpp;
		tpp = &(all_targets);
4239
4240
		while (*tpp){
			tpp = &((*tpp)->next);
4241
4242
4243
4244
		}
		*tpp = target;
	}

4245
	cp = Jim_GetString(new_cmd, NULL);
4246
4247
4248
	target->cmd_name = strdup(cp);

	/* now - create the new target name command */
4249
	e = Jim_CreateCommand(goi->interp,
4250
4251
4252
4253
						   /* name */
						   cp,
						   tcl_target_func, /* C function */
						   target, /* private data */
4254
						   NULL); /* no del proc */
4255
4256
4257
4258

	return e;
}

4259
static int jim_target(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
4260
4261
4262
4263
4264
4265
4266
4267
4268
4269
4270
4271
4272
4273
4274
4275
{
	int x,r,e;
	jim_wide w;
	struct command_context_s *cmd_ctx;
	target_t *target;
	Jim_GetOptInfo goi;
	enum tcmd {
		/* TG = target generic */
		TG_CMD_CREATE,
		TG_CMD_TYPES,
		TG_CMD_NAMES,
		TG_CMD_CURRENT,
		TG_CMD_NUMBER,
		TG_CMD_COUNT,
	};
	const char *target_cmds[] = {
4276
		"create", "types", "names", "current", "number",
4277
		"count",
4278
		NULL /* terminate */
4279
4280
4281
	};

	LOG_DEBUG("Target command params:");
4282
	LOG_DEBUG("%s", Jim_Debug_ArgvString(interp, argc, argv));
4283

4284
	cmd_ctx = Jim_GetAssocData(interp, "context");
4285

4286
	Jim_GetOpt_Setup(&goi, interp, argc-1, argv + 1);
4287

4288
	if (goi.argc == 0){
4289
4290
4291
4292
		Jim_WrongNumArgs(interp, 1, argv, "missing: command ...");
		return JIM_ERR;
	}

4293
4294
4295
	/* Jim_GetOpt_Debug(&goi); */
	r = Jim_GetOpt_Enum(&goi, target_cmds, &x);
	if (r != JIM_OK){
4296
4297
4298
		return r;
	}

zwelch's avatar
zwelch committed
4299
	switch (x){
4300
4301
4302
4303
	default:
		Jim_Panic(goi.interp,"Why am I here?");
		return JIM_ERR;
	case TG_CMD_CURRENT:
4304
		if (goi.argc != 0){
4305
			Jim_WrongNumArgs(goi.interp, 1, goi.argv, "Too many parameters");
4306
4307
			return JIM_ERR;
		}
4308
		Jim_SetResultString(goi.interp, get_current_target(cmd_ctx)->cmd_name, -1);
4309
4310
		return JIM_OK;
	case TG_CMD_TYPES:
4311
4312
		if (goi.argc != 0){
			Jim_WrongNumArgs(goi.interp, 1, goi.argv, "Too many parameters");
4313
4314
			return JIM_ERR;
		}
4315
4316
		Jim_SetResult(goi.interp, Jim_NewListObj(goi.interp, NULL, 0));
		for (x = 0 ; target_types[x] ; x++){
4317
			Jim_ListAppendElement(goi.interp,
4318
								   Jim_GetResult(goi.interp),
4319
								   Jim_NewStringObj(goi.interp, target_types[x]->name, -1));
4320
4321
4322
		}
		return JIM_OK;
	case TG_CMD_NAMES:
4323
4324
		if (goi.argc != 0){
			Jim_WrongNumArgs(goi.interp, 1, goi.argv, "Too many parameters");
4325
4326
			return JIM_ERR;
		}
4327
		Jim_SetResult(goi.interp, Jim_NewListObj(goi.interp, NULL, 0));
4328
		target = all_targets;
4329
		while (target){
4330
			Jim_ListAppendElement(goi.interp,
4331
								   Jim_GetResult(goi.interp),
4332
								   Jim_NewStringObj(goi.interp, target->cmd_name, -1));
4333
4334
			target = target->next;
		}
4335
		return JIM_OK;
4336
	case TG_CMD_CREATE:
4337
		if (goi.argc < 3){
4338
			Jim_WrongNumArgs(goi.interp, goi.argc, goi.argv, "?name  ... config options ...");
4339
4340
			return JIM_ERR;
		}
4341
		return target_create(&goi);
4342
4343
		break;
	case TG_CMD_NUMBER:
4344
		if (goi.argc != 1){
4345
			Jim_SetResult_sprintf(goi.interp, "expected: target number ?NUMBER?");
4346
4347
			return JIM_ERR;
		}
4348
4349
		e = Jim_GetOpt_Wide(&goi, &w);
		if (e != JIM_OK){
4350
4351
4352
4353
4354
			return JIM_ERR;
		}
		{
			target_t *t;
			t = get_target_by_num(w);
4355
			if (t == NULL){
4356
				Jim_SetResult_sprintf(goi.interp,"Target: number %d does not exist", (int)(w));
4357
4358
				return JIM_ERR;
			}
4359
			Jim_SetResultString(goi.interp, t->cmd_name, -1);
4360
4361
4362
			return JIM_OK;
		}
	case TG_CMD_COUNT:
4363
		if (goi.argc != 0){
4364
			Jim_WrongNumArgs(goi.interp, 0, goi.argv, "<no parameters>");
4365
4366
			return JIM_ERR;
		}
4367
4368
		Jim_SetResult(goi.interp,
					   Jim_NewIntObj(goi.interp, max_target_number()));
4369
4370
		return JIM_OK;
	}
4371
4372

	return JIM_ERR;
4373
}
4374
4375
4376
4377


struct FastLoad
{
4378
	uint32_t address;
4379
	uint8_t *data;
4380
4381
4382
4383
4384
4385
4386
	int length;

};

static int fastload_num;
static struct FastLoad *fastload;

4387
static void free_fastload(void)
4388
{
zwelch's avatar
zwelch committed
4389
	if (fastload != NULL)
4390
4391
	{
		int i;
zwelch's avatar
zwelch committed
4392
		for (i = 0; i < fastload_num; i++)
4393
4394
4395
4396
4397
		{
			if (fastload[i].data)
				free(fastload[i].data);
		}
		free(fastload);
zwelch's avatar
zwelch committed
4398
		fastload = NULL;
4399
4400
4401
4402
4403
4404
	}
}




4405
static int handle_fast_load_image_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
4406
{
4407
	uint8_t *buffer;
4408
4409
	uint32_t buf_cnt;
	uint32_t image_size;
zwelch's avatar
zwelch committed
4410
4411
	uint32_t min_address = 0;
	uint32_t max_address = 0xffffffff;
4412
4413
4414
4415
4416
4417
4418
	int i;

	image_t image;

	duration_t duration;
	char *duration_text;

4419
4420
4421
4422
	int retval = parse_load_image_command_args(args, argc,
			&image, &min_address, &max_address);
	if (ERROR_OK != retval)
		return retval;
4423
4424
4425
4426
4427
4428
4429
4430
4431
4432

	duration_start_measure(&duration);

	if (image_open(&image, args[0], (argc >= 3) ? args[2] : NULL) != ERROR_OK)
	{
		return ERROR_OK;
	}

	image_size = 0x0;
	retval = ERROR_OK;
zwelch's avatar
zwelch committed
4433
4434
	fastload_num = image.num_sections;
	fastload = (struct FastLoad *)malloc(sizeof(struct FastLoad)*image.num_sections);
zwelch's avatar
zwelch committed
4435
	if (fastload == NULL)
4436
4437
4438
4439
4440
4441
4442
4443
4444
4445
	{
		image_close(&image);
		return ERROR_FAIL;
	}
	memset(fastload, 0, sizeof(struct FastLoad)*image.num_sections);
	for (i = 0; i < image.num_sections; i++)
	{
		buffer = malloc(image.sections[i].size);
		if (buffer == NULL)
		{
duane's avatar
duane committed
4446
4447
			command_print(cmd_ctx, "error allocating buffer for section (%d bytes)", 
						  (int)(image.sections[i].size));
4448
4449
4450
4451
4452
4453
4454
4455
4456
			break;
		}

		if ((retval = image_read_section(&image, i, 0x0, image.sections[i].size, buffer, &buf_cnt)) != ERROR_OK)
		{
			free(buffer);
			break;
		}

zwelch's avatar
zwelch committed
4457
4458
		uint32_t offset = 0;
		uint32_t length = buf_cnt;
4459
4460
4461
4462


		/* DANGER!!! beware of unsigned comparision here!!! */

zwelch's avatar
zwelch committed
4463
		if ((image.sections[i].base_address + buf_cnt >= min_address)&&
zwelch's avatar
zwelch committed
4464
				(image.sections[i].base_address < max_address))
4465
		{
zwelch's avatar
zwelch committed
4466
			if (image.sections[i].base_address < min_address)
4467
4468
			{
				/* clip addresses below */
zwelch's avatar
zwelch committed
4469
				offset += min_address-image.sections[i].base_address;
zwelch's avatar
zwelch committed
4470
				length -= offset;
4471
4472
			}

zwelch's avatar
zwelch committed
4473
			if (image.sections[i].base_address + buf_cnt > max_address)
4474
			{
zwelch's avatar
zwelch committed
4475
				length -= (image.sections[i].base_address + buf_cnt)-max_address;
4476
4477
			}

zwelch's avatar
zwelch committed
4478
			fastload[i].address = image.sections[i].base_address + offset;
zwelch's avatar
zwelch committed
4479
			fastload[i].data = malloc(length);
zwelch's avatar
zwelch committed
4480
			if (fastload[i].data == NULL)
4481
4482
4483
4484
			{
				free(buffer);
				break;
			}
zwelch's avatar
zwelch committed
4485
			memcpy(fastload[i].data, buffer + offset, length);
zwelch's avatar
zwelch committed
4486
			fastload[i].length = length;
4487
4488

			image_size += length;
duane's avatar
duane committed
4489
4490
			command_print(cmd_ctx, "%u byte written at address 0x%8.8x", 
						  (unsigned int)length, 
zwelch's avatar
zwelch committed
4491
						  ((unsigned int)(image.sections[i].base_address + offset)));
4492
4493
4494
4495
4496
4497
		}

		free(buffer);
	}

	duration_stop_measure(&duration, &duration_text);
zwelch's avatar
zwelch committed
4498
	if (retval == ERROR_OK)
4499
	{
duane's avatar
duane committed
4500
		command_print(cmd_ctx, "Loaded %u bytes in %s", (unsigned int)image_size, duration_text);
4501
4502
4503
4504
4505
4506
		command_print(cmd_ctx, "NB!!! image has not been loaded to target, issue a subsequent 'fast_load' to do so.");
	}
	free(duration_text);

	image_close(&image);

zwelch's avatar
zwelch committed
4507
	if (retval != ERROR_OK)
4508
4509
4510
4511
4512
4513
4514
	{
		free_fastload();
	}

	return retval;
}

4515
static int handle_fast_load_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
4516
{
zwelch's avatar
zwelch committed
4517
	if (argc > 0)
4518
		return ERROR_COMMAND_SYNTAX_ERROR;
zwelch's avatar
zwelch committed
4519
	if (fastload == NULL)
4520
4521
4522
4523
4524
	{
		LOG_ERROR("No image in memory");
		return ERROR_FAIL;
	}
	int i;
zwelch's avatar
zwelch committed
4525
4526
4527
	int ms = timeval_ms();
	int size = 0;
	int retval = ERROR_OK;
zwelch's avatar
zwelch committed
4528
	for (i = 0; i < fastload_num;i++)
4529
4530
	{
		target_t *target = get_current_target(cmd_ctx);
duane's avatar
duane committed
4531
4532
4533
		command_print(cmd_ctx, "Write to 0x%08x, length 0x%08x", 
					  (unsigned int)(fastload[i].address), 
					  (unsigned int)(fastload[i].length));
zwelch's avatar
zwelch committed
4534
		if (retval == ERROR_OK)
4535
		{
oharboe's avatar
oharboe committed
4536
			retval = target_write_buffer(target, fastload[i].address, fastload[i].length, fastload[i].data);
4537
		}
zwelch's avatar
zwelch committed
4538
		size += fastload[i].length;
4539
	}
zwelch's avatar
zwelch committed
4540
	int after = timeval_ms();
4541
	command_print(cmd_ctx, "Loaded image %f kBytes/s", (float)(size/1024.0)/((float)(after-ms)/1000.0));
oharboe's avatar
oharboe committed
4542
	return retval;
4543
}
duane's avatar
duane committed
4544
4545
4546
4547
4548
4549
4550
4551


/*
 * Local Variables: 
 * c-basic-offset: 4
 * tab-width: 4
 * End:
 */
For faster browsing, not all history is shown. View entire blame