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 */
zwelch's avatar
zwelch committed
4011
		if ( n->value == NVP_ASSERT ){
4012
4013
4014
4015
4016
4017
			target->type->assert_reset( target );
		} else {
			target->type->deassert_reset( target );
		}
		return JIM_OK;
	case TS_CMD_HALT:
zwelch's avatar
zwelch committed
4018
		if ( goi.argc ){
4019
4020
4021
			Jim_WrongNumArgs( goi.interp, 0, argv, "halt [no parameters]");
			return JIM_ERR;
		}
zwelch's avatar
zwelch committed
4022
4023
		if (!target->tap->enabled)
			goto err_tap_disabled;
4024
4025
4026
		target->type->halt( target );
		return JIM_OK;
	case TS_CMD_WAITSTATE:
4027
		/* params:  <name>  statename timeoutmsecs */
zwelch's avatar
zwelch committed
4028
		if ( goi.argc != 2 ){
4029
4030
4031
4032
			Jim_SetResult_sprintf( goi.interp, "%s STATENAME TIMEOUTMSECS", n->name );
			return JIM_ERR;
		}
		e = Jim_GetOpt_Nvp( &goi, nvp_target_state, &n );
zwelch's avatar
zwelch committed
4033
		if ( e != JIM_OK ){
4034
4035
4036
4037
			Jim_GetOpt_NvpUnknown( &goi, nvp_target_state,1 );
			return e;
		}
		e = Jim_GetOpt_Wide( &goi, &a );
zwelch's avatar
zwelch committed
4038
		if ( e != JIM_OK ){
4039
4040
			return e;
		}
zwelch's avatar
zwelch committed
4041
4042
		if (!target->tap->enabled)
			goto err_tap_disabled;
4043
		e = target_wait_state( target, n->value, a );
zwelch's avatar
zwelch committed
4044
		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
4061
			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;
			command_print( cmd_ctx, "Event actions for target (%d) %s\n",
4062
						   target->target_number,
4063
4064
4065
						   target->cmd_name );
			command_print( cmd_ctx, "%-25s | Body", "Event");
			command_print( cmd_ctx, "------------------------- | ----------------------------------------");
zwelch's avatar
zwelch committed
4066
			while ( teap ){
4067
				command_print( cmd_ctx,
4068
4069
4070
4071
4072
4073
4074
4075
4076
							   "%-25s | %s",
							   Jim_Nvp_value2name_simple( nvp_target_event, teap->event )->name,
							   Jim_GetString( teap->body, NULL ) );
				teap = teap->next;
			}
			command_print( cmd_ctx, "***END***");
			return JIM_OK;
		}
	case TS_CMD_CURSTATE:
zwelch's avatar
zwelch committed
4077
		if ( goi.argc != 0 ){
4078
4079
4080
			Jim_WrongNumArgs( goi.interp, 0, argv, "[no parameters]");
			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:
zwelch's avatar
zwelch committed
4085
		if ( goi.argc != 1 ){
4086
4087
4088
4089
			Jim_SetResult_sprintf( goi.interp, "%s ?EVENTNAME?",n->name);
			return JIM_ERR;
		}
		e = Jim_GetOpt_Nvp( &goi, nvp_target_event, &n );
zwelch's avatar
zwelch committed
4090
		if ( e != JIM_OK ){
4091
4092
4093
4094
4095
			Jim_GetOpt_NvpUnknown( &goi, nvp_target_event, 1 );
			return e;
		}
		target_handle_event( target, n->value );
		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");
zwelch's avatar
zwelch committed
4116
	if ( goi->argc < 3 ){
4117
4118
4119
4120
4121
4122
4123
4124
		Jim_WrongNumArgs( goi->interp, 1, goi->argv, "?name? ?type? ..options...");
		return JIM_ERR;
	}

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

4131
4132
4133
4134
	/* TYPE */
	e = Jim_GetOpt_String( goi, &cp2, NULL );
	cp = cp2;
	/* now does target type exist */
zwelch's avatar
zwelch committed
4135
	for ( x = 0 ; target_types[x] ; x++ ){
zwelch's avatar
zwelch committed
4136
		if ( 0 == strcmp( cp, target_types[x]->name ) ){
4137
4138
4139
4140
			/* found */
			break;
		}
	}
zwelch's avatar
zwelch committed
4141
	if ( target_types[x] == NULL ){
4142
		Jim_SetResult_sprintf( goi->interp, "Unknown target type %s, try one of ", cp );
zwelch's avatar
zwelch committed
4143
		for ( x = 0 ; target_types[x] ; x++ ){
zwelch's avatar
zwelch committed
4144
			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
4153
4154
4155
4156
4157
4158
4159
4160
4161
4162
4163
4164
4165
4166
4167
								   Jim_GetResult(goi->interp),
								   " or ",
								   target_types[x]->name,NULL );
			}
		}
		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));

	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
4204
	target->dbgmsg          = NULL;
	target->dbg_msg_enabled = 0;

	target->endianness = TARGET_ENDIAN_UNKNOWN;

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

	if (target->tap == NULL)
	{
		Jim_SetResultString( interp, "-chain-position required when creating target", -1);
		e=JIM_ERR;
	}

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

zwelch's avatar
zwelch committed
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 */
zwelch's avatar
zwelch committed
4228
	if ( target->type->register_commands ){
4229
4230
		(*(target->type->register_commands))( cmd_ctx );
	}
zwelch's avatar
zwelch committed
4231
	if ( target->type->target_create ){
4232
4233
4234
4235
4236
4237
4238
		(*(target->type->target_create))( target, goi->interp );
	}

	/* append to end of list */
	{
		target_t **tpp;
		tpp = &(all_targets);
zwelch's avatar
zwelch committed
4239
		while ( *tpp ){
4240
4241
4242
4243
4244
4245
4246
4247
4248
4249
4250
4251
4252
4253
4254
4255
4256
4257
4258
			tpp = &( (*tpp)->next );
		}
		*tpp = target;
	}

	cp = Jim_GetString( new_cmd, NULL );
	target->cmd_name = strdup(cp);

	/* now - create the new target name command */
	e = Jim_CreateCommand( goi->interp,
						   /* name */
						   cp,
						   tcl_target_func, /* C function */
						   target, /* private data */
						   NULL ); /* no del proc */

	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
4285
4286
4287

	cmd_ctx = Jim_GetAssocData( interp, "context" );

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

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

4293
	/* Jim_GetOpt_Debug( &goi ); */
4294
	r = Jim_GetOpt_Enum( &goi, target_cmds, &x   );
zwelch's avatar
zwelch committed
4295
	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:
zwelch's avatar
zwelch committed
4304
		if ( goi.argc != 0 ){
4305
4306
4307
4308
4309
4310
			Jim_WrongNumArgs( goi.interp, 1, goi.argv, "Too many parameters");
			return JIM_ERR;
		}
		Jim_SetResultString( goi.interp, get_current_target( cmd_ctx )->cmd_name, -1 );
		return JIM_OK;
	case TG_CMD_TYPES:
zwelch's avatar
zwelch committed
4311
		if ( goi.argc != 0 ){
4312
4313
4314
4315
			Jim_WrongNumArgs( goi.interp, 1, goi.argv, "Too many parameters" );
			return JIM_ERR;
		}
		Jim_SetResult( goi.interp, Jim_NewListObj( goi.interp, NULL, 0 ) );
zwelch's avatar
zwelch committed
4316
		for ( x = 0 ; target_types[x] ; x++ ){
4317
4318
4319
4320
4321
4322
			Jim_ListAppendElement( goi.interp,
								   Jim_GetResult(goi.interp),
								   Jim_NewStringObj( goi.interp, target_types[x]->name, -1 ) );
		}
		return JIM_OK;
	case TG_CMD_NAMES:
zwelch's avatar
zwelch committed
4323
		if ( goi.argc != 0 ){
4324
4325
4326
4327
4328
			Jim_WrongNumArgs( goi.interp, 1, goi.argv, "Too many parameters" );
			return JIM_ERR;
		}
		Jim_SetResult( goi.interp, Jim_NewListObj( goi.interp, NULL, 0 ) );
		target = all_targets;
zwelch's avatar
zwelch committed
4329
		while ( target ){
4330
4331
4332
4333
4334
			Jim_ListAppendElement( goi.interp,
								   Jim_GetResult(goi.interp),
								   Jim_NewStringObj( goi.interp, target->cmd_name, -1 ) );
			target = target->next;
		}
4335
		return JIM_OK;
4336
	case TG_CMD_CREATE:
zwelch's avatar
zwelch committed
4337
		if ( goi.argc < 3 ){
4338
4339
4340
4341
4342
4343
			Jim_WrongNumArgs( goi.interp, goi.argc, goi.argv, "?name  ... config options ...");
			return JIM_ERR;
		}
		return target_create( &goi );
		break;
	case TG_CMD_NUMBER:
zwelch's avatar
zwelch committed
4344
		if ( goi.argc != 1 ){
4345
4346
4347
4348
			Jim_SetResult_sprintf( goi.interp, "expected: target number ?NUMBER?");
			return JIM_ERR;
		}
		e = Jim_GetOpt_Wide( &goi, &w );
zwelch's avatar
zwelch committed
4349
		if ( e != JIM_OK ){
4350
4351
4352
4353
4354
			return JIM_ERR;
		}
		{
			target_t *t;
			t = get_target_by_num(w);
zwelch's avatar
zwelch committed
4355
			if ( t == NULL ){
4356
4357
4358
4359
4360
4361
4362
				Jim_SetResult_sprintf( goi.interp,"Target: number %d does not exist", (int)(w));
				return JIM_ERR;
			}
			Jim_SetResultString( goi.interp, t->cmd_name, -1 );
			return JIM_OK;
		}
	case TG_CMD_COUNT:
zwelch's avatar
zwelch committed
4363
		if ( goi.argc != 0 ){
4364
4365
4366
			Jim_WrongNumArgs( goi.interp, 0, goi.argv, "<no parameters>");
			return JIM_ERR;
		}
4367
		Jim_SetResult( goi.interp,
4368
4369
4370
					   Jim_NewIntObj( goi.interp, max_target_number()));
		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
4392
4393
4394
4395
4396
4397
4398
4399
4400
4401
4402
4403
4404
	{
		int i;
		for (i=0; i<fastload_num; i++)
		{
			if (fastload[i].data)
				free(fastload[i].data);
		}
		free(fastload);
		fastload=NULL;
	}
}




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
4410
4411
	uint32_t buf_cnt;
	uint32_t image_size;
	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
4433
4434
4435
4436
4437
4438
4439
4440
4441
4442
4443
4444
4445

	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;
	fastload_num=image.num_sections;
	fastload=(struct FastLoad *)malloc(sizeof(struct FastLoad)*image.num_sections);
	if (fastload==NULL)
	{
		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;
		}

4457
4458
		uint32_t offset=0;
		uint32_t length=buf_cnt;
4459
4460
4461
4462
4463
4464
4465
4466
4467
4468
4469


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

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

			if (image.sections[i].base_address+buf_cnt>max_address)
			{
zwelch's avatar
zwelch committed
4475
				length -= (image.sections[i].base_address+buf_cnt)-max_address;
4476
4477
4478
4479
4480
4481
4482
4483
4484
4485
4486
4487
4488
			}

			fastload[i].address=image.sections[i].base_address+offset;
			fastload[i].data=malloc(length);
			if (fastload[i].data==NULL)
			{
				free(buffer);
				break;
			}
			memcpy(fastload[i].data, buffer+offset, length);
			fastload[i].length=length;

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

		free(buffer);
	}

	duration_stop_measure(&duration, &duration_text);
	if (retval==ERROR_OK)
	{
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
4517
4518
4519
4520
4521
4522
4523
4524
4525
4526
{
	if (argc>0)
		return ERROR_COMMAND_SYNTAX_ERROR;
	if (fastload==NULL)
	{
		LOG_ERROR("No image in memory");
		return ERROR_FAIL;
	}
	int i;
	int ms=timeval_ms();
	int size=0;
oharboe's avatar
oharboe committed
4527
	int retval=ERROR_OK;
4528
4529
4530
	for (i=0; i<fastload_num;i++)
	{
		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));
oharboe's avatar
oharboe 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
4538
4539
4540
4541
		}
		size+=fastload[i].length;
	}
	int after=timeval_ms();
	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