target.c 121 KB
Newer Older
4001
		return target_configure(&goi, target);
4002
4003
4004
4005
4006
4007
4008
4009
4010
		break;
	case TS_CMD_MWW:
	case TS_CMD_MWH:
	case TS_CMD_MWB:
		/* argv[0] = cmd
		 * argv[1] = address
		 * argv[2] = data
		 * argv[3] = optional count.
		 */
4011

zwelch's avatar
zwelch committed
4012
		if ((goi.argc == 2) || (goi.argc == 3)) {
4013
4014
4015
			/* all is well */
		} else {
		mwx_error:
4016
			Jim_SetResult_sprintf(goi.interp, "expected: %s ADDR DATA [COUNT]", n->name);
4017
4018
			return JIM_ERR;
		}
4019

4020
		e = Jim_GetOpt_Wide(&goi, &a);
zwelch's avatar
zwelch committed
4021
		if (e != JIM_OK) {
4022
4023
4024
			goto mwx_error;
		}

4025
		e = Jim_GetOpt_Wide(&goi, &b);
zwelch's avatar
zwelch committed
4026
		if (e != JIM_OK) {
4027
4028
			goto mwx_error;
		}
zwelch's avatar
zwelch committed
4029
		if (goi.argc == 3) {
4030
			e = Jim_GetOpt_Wide(&goi, &c);
zwelch's avatar
zwelch committed
4031
			if (e != JIM_OK) {
4032
4033
4034
4035
4036
				goto mwx_error;
			}
		} else {
			c = 1;
		}
4037

zwelch's avatar
zwelch committed
4038
		switch (n->value) {
4039
		case TS_CMD_MWW:
4040
			target_buffer_set_u32(target, target_buf, b);
4041
4042
4043
			b = 4;
			break;
		case TS_CMD_MWH:
4044
			target_buffer_set_u16(target, target_buf, b);
4045
4046
4047
			b = 2;
			break;
		case TS_CMD_MWB:
4048
			target_buffer_set_u8(target, target_buf, b);
4049
4050
4051
			b = 1;
			break;
		}
zwelch's avatar
zwelch committed
4052
		for (x = 0 ; x < c ; x++) {
4053
			e = target_write_memory(target, a, b, 1, target_buf);
zwelch's avatar
zwelch committed
4054
			if (e != ERROR_OK) {
4055
				Jim_SetResult_sprintf(interp, "Error writing @ 0x%08x: %d\n", (int)(a), e);
4056
4057
4058
4059
4060
4061
4062
4063
4064
4065
4066
4067
4068
4069
4070
4071
				return JIM_ERR;
			}
			/* b = width */
			a = a + b;
		}
		return JIM_OK;
		break;

		/* display */
	case TS_CMD_MDW:
	case TS_CMD_MDH:
	case TS_CMD_MDB:
		/* argv[0] = command
		 * argv[1] = address
		 * argv[2] = optional count
		 */
zwelch's avatar
zwelch committed
4072
		if ((goi.argc == 2) || (goi.argc == 3)) {
4073
			Jim_SetResult_sprintf(goi.interp, "expected: %s ADDR [COUNT]", n->name);
4074
4075
			return JIM_ERR;
		}
4076
		e = Jim_GetOpt_Wide(&goi, &a);
zwelch's avatar
zwelch committed
4077
		if (e != JIM_OK) {
4078
4079
			return JIM_ERR;
		}
zwelch's avatar
zwelch committed
4080
		if (goi.argc) {
4081
			e = Jim_GetOpt_Wide(&goi, &c);
zwelch's avatar
zwelch committed
4082
			if (e != JIM_OK) {
4083
4084
4085
4086
4087
4088
				return JIM_ERR;
			}
		} else {
			c = 1;
		}
		b = 1; /* shut up gcc */
zwelch's avatar
zwelch committed
4089
		switch (n->value) {
4090
4091
4092
4093
4094
4095
4096
4097
4098
4099
4100
4101
4102
4103
		case TS_CMD_MDW:
			b =  4;
			break;
		case TS_CMD_MDH:
			b = 2;
			break;
		case TS_CMD_MDB:
			b = 1;
			break;
		}

		/* convert to "bytes" */
		c = c * b;
		/* count is now in 'BYTES' */
zwelch's avatar
zwelch committed
4104
		while (c > 0) {
4105
			y = c;
zwelch's avatar
zwelch committed
4106
			if (y > 16) {
4107
4108
				y = 16;
			}
4109
			e = target_read_memory(target, a, b, y / b, target_buf);
zwelch's avatar
zwelch committed
4110
			if (e != ERROR_OK) {
4111
				Jim_SetResult_sprintf(interp, "error reading target @ 0x%08lx", (int)(a));
4112
4113
				return JIM_ERR;
			}
4114

4115
			Jim_fprintf(interp, interp->cookie_stdout, "0x%08x ", (int)(a));
zwelch's avatar
zwelch committed
4116
			switch (b) {
4117
			case 4:
zwelch's avatar
zwelch committed
4118
				for (x = 0 ; (x < 16) && (x < y) ; x += 4) {
4119
4120
					z = target_buffer_get_u32(target, &(target_buf[ x * 4 ]));
					Jim_fprintf(interp, interp->cookie_stdout, "%08x ", (int)(z));
4121
				}
zwelch's avatar
zwelch committed
4122
				for (; (x < 16) ; x += 4) {
4123
					Jim_fprintf(interp, interp->cookie_stdout, "         ");
4124
4125
4126
				}
				break;
			case 2:
zwelch's avatar
zwelch committed
4127
				for (x = 0 ; (x < 16) && (x < y) ; x += 2) {
4128
4129
					z = target_buffer_get_u16(target, &(target_buf[ x * 2 ]));
					Jim_fprintf(interp, interp->cookie_stdout, "%04x ", (int)(z));
4130
				}
zwelch's avatar
zwelch committed
4131
				for (; (x < 16) ; x += 2) {
4132
					Jim_fprintf(interp, interp->cookie_stdout, "     ");
4133
4134
4135
4136
				}
				break;
			case 1:
			default:
zwelch's avatar
zwelch committed
4137
				for (x = 0 ; (x < 16) && (x < y) ; x += 1) {
4138
4139
					z = target_buffer_get_u8(target, &(target_buf[ x * 4 ]));
					Jim_fprintf(interp, interp->cookie_stdout, "%02x ", (int)(z));
4140
				}
zwelch's avatar
zwelch committed
4141
				for (; (x < 16) ; x += 1) {
4142
					Jim_fprintf(interp, interp->cookie_stdout, "   ");
4143
4144
4145
4146
				}
				break;
			}
			/* ascii-ify the bytes */
zwelch's avatar
zwelch committed
4147
			for (x = 0 ; x < y ; x++) {
4148
				if ((target_buf[x] >= 0x20) &&
zwelch's avatar
zwelch committed
4149
					(target_buf[x] <= 0x7e)) {
4150
4151
4152
4153
4154
4155
4156
					/* good */
				} else {
					/* smack it */
					target_buf[x] = '.';
				}
			}
			/* space pad  */
zwelch's avatar
zwelch committed
4157
			while (x < 16) {
4158
4159
4160
4161
4162
4163
				target_buf[x] = ' ';
				x++;
			}
			/* terminate */
			target_buf[16] = 0;
			/* print - with a newline */
4164
			Jim_fprintf(interp, interp->cookie_stdout, "%s\n", target_buf);
4165
4166
4167
4168
4169
4170
			/* NEXT... */
			c -= 16;
			a += 16;
		}
		return JIM_OK;
	case TS_CMD_MEM2ARRAY:
4171
		return target_mem2array(goi.interp, target, goi.argc, goi.argv);
4172
4173
		break;
	case TS_CMD_ARRAY2MEM:
4174
		return target_array2mem(goi.interp, target, goi.argc, goi.argv);
4175
4176
		break;
	case TS_CMD_EXAMINE:
zwelch's avatar
zwelch committed
4177
		if (goi.argc) {
4178
			Jim_WrongNumArgs(goi.interp, 2, argv, "[no parameters]");
4179
4180
			return JIM_ERR;
		}
zwelch's avatar
zwelch committed
4181
4182
		if (!target->tap->enabled)
			goto err_tap_disabled;
4183
		e = target->type->examine(target);
zwelch's avatar
zwelch committed
4184
		if (e != ERROR_OK) {
4185
			Jim_SetResult_sprintf(interp, "examine-fails: %d", e);
4186
4187
4188
4189
			return JIM_ERR;
		}
		return JIM_OK;
	case TS_CMD_POLL:
zwelch's avatar
zwelch committed
4190
		if (goi.argc) {
4191
			Jim_WrongNumArgs(goi.interp, 2, argv, "[no parameters]");
4192
4193
			return JIM_ERR;
		}
zwelch's avatar
zwelch committed
4194
4195
		if (!target->tap->enabled)
			goto err_tap_disabled;
zwelch's avatar
zwelch committed
4196
		if (!(target_was_examined(target))) {
4197
4198
			e = ERROR_TARGET_NOT_EXAMINED;
		} else {
4199
			e = target->type->poll(target);
4200
		}
zwelch's avatar
zwelch committed
4201
		if (e != ERROR_OK) {
4202
			Jim_SetResult_sprintf(interp, "poll-fails: %d", e);
4203
4204
4205
4206
4207
4208
			return JIM_ERR;
		} else {
			return JIM_OK;
		}
		break;
	case TS_CMD_RESET:
zwelch's avatar
zwelch committed
4209
		if (goi.argc != 2) {
4210
4211
			Jim_WrongNumArgs(interp, 2, argv,
					"([tT]|[fF]|assert|deassert) BOOL");
4212
4213
			return JIM_ERR;
		}
4214
		e = Jim_GetOpt_Nvp(&goi, nvp_assert, &n);
zwelch's avatar
zwelch committed
4215
		if (e != JIM_OK) {
4216
			Jim_GetOpt_NvpUnknown(&goi, nvp_assert, 1);
4217
4218
			return e;
		}
4219
		/* the halt or not param */
4220
		e = Jim_GetOpt_Wide(&goi, &a);
zwelch's avatar
zwelch committed
4221
		if (e != JIM_OK) {
4222
4223
			return e;
		}
zwelch's avatar
zwelch committed
4224
4225
		if (!target->tap->enabled)
			goto err_tap_disabled;
4226
4227
4228
4229
4230
4231
4232
		if (!target->type->assert_reset
				|| !target->type->deassert_reset) {
			Jim_SetResult_sprintf(interp,
					"No target-specific reset for %s",
					target->cmd_name);
			return JIM_ERR;
		}
4233
		/* determine if we should halt or not. */
4234
		target->reset_halt = !!a;
4235
		/* When this happens - all workareas are invalid. */
4236
4237
		target_free_all_working_areas_restore(target, 0);

4238
		/* do the assert */
zwelch's avatar
zwelch committed
4239
		if (n->value == NVP_ASSERT) {
4240
			e = target->type->assert_reset(target);
4241
		} else {
4242
			e = target->type->deassert_reset(target);
4243
		}
4244
		return (e == ERROR_OK) ? JIM_OK : JIM_ERR;
4245
	case TS_CMD_HALT:
zwelch's avatar
zwelch committed
4246
		if (goi.argc) {
4247
			Jim_WrongNumArgs(goi.interp, 0, argv, "halt [no parameters]");
4248
4249
			return JIM_ERR;
		}
zwelch's avatar
zwelch committed
4250
4251
		if (!target->tap->enabled)
			goto err_tap_disabled;
4252
4253
		e = target->type->halt(target);
		return (e == ERROR_OK) ? JIM_OK : JIM_ERR;
4254
	case TS_CMD_WAITSTATE:
4255
		/* params:  <name>  statename timeoutmsecs */
zwelch's avatar
zwelch committed
4256
		if (goi.argc != 2) {
4257
			Jim_SetResult_sprintf(goi.interp, "%s STATENAME TIMEOUTMSECS", n->name);
4258
4259
			return JIM_ERR;
		}
4260
		e = Jim_GetOpt_Nvp(&goi, nvp_target_state, &n);
zwelch's avatar
zwelch committed
4261
		if (e != JIM_OK) {
4262
			Jim_GetOpt_NvpUnknown(&goi, nvp_target_state,1);
4263
4264
			return e;
		}
4265
		e = Jim_GetOpt_Wide(&goi, &a);
zwelch's avatar
zwelch committed
4266
		if (e != JIM_OK) {
4267
4268
			return e;
		}
zwelch's avatar
zwelch committed
4269
4270
		if (!target->tap->enabled)
			goto err_tap_disabled;
4271
		e = target_wait_state(target, n->value, a);
zwelch's avatar
zwelch committed
4272
		if (e != ERROR_OK) {
4273
			Jim_SetResult_sprintf(goi.interp,
4274
								   "target: %s wait %s fails (%d) %s",
4275
4276
								   target->cmd_name,
								   n->name,
4277
								   e, target_strerror_safe(e));
4278
4279
4280
4281
4282
4283
4284
4285
4286
4287
4288
			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;
4289
			command_print(cmd_ctx, "Event actions for target (%d) %s\n",
4290
						   target->target_number,
4291
						   target->cmd_name);
4292
4293
			command_print(cmd_ctx, "%-25s | Body", "Event");
			command_print(cmd_ctx, "------------------------- | ----------------------------------------");
zwelch's avatar
zwelch committed
4294
			while (teap) {
4295
				command_print(cmd_ctx,
4296
							   "%-25s | %s",
4297
4298
							   Jim_Nvp_value2name_simple(nvp_target_event, teap->event)->name,
							   Jim_GetString(teap->body, NULL));
4299
4300
				teap = teap->next;
			}
4301
			command_print(cmd_ctx, "***END***");
4302
4303
4304
			return JIM_OK;
		}
	case TS_CMD_CURSTATE:
zwelch's avatar
zwelch committed
4305
		if (goi.argc != 0) {
4306
			Jim_WrongNumArgs(goi.interp, 0, argv, "[no parameters]");
4307
4308
			return JIM_ERR;
		}
4309
		Jim_SetResultString(goi.interp,
4310
4311
							target_state_name( target ),
							-1);
4312
		return JIM_OK;
4313
	case TS_CMD_INVOKE_EVENT:
zwelch's avatar
zwelch committed
4314
		if (goi.argc != 1) {
4315
			Jim_SetResult_sprintf(goi.interp, "%s ?EVENTNAME?",n->name);
4316
4317
			return JIM_ERR;
		}
4318
		e = Jim_GetOpt_Nvp(&goi, nvp_target_event, &n);
zwelch's avatar
zwelch committed
4319
		if (e != JIM_OK) {
4320
			Jim_GetOpt_NvpUnknown(&goi, nvp_target_event, 1);
4321
4322
			return e;
		}
4323
		target_handle_event(target, n->value);
4324
		return JIM_OK;
4325
4326
	}
	return JIM_ERR;
zwelch's avatar
zwelch committed
4327
4328
4329
4330

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

4333
static int target_create(Jim_GetOptInfo *goi)
4334
{
4335
4336
4337
4338
4339
4340
4341
4342
4343
4344
	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
4345
	if (goi->argc < 3) {
4346
		Jim_WrongNumArgs(goi->interp, 1, goi->argv, "?name? ?type? ..options...");
4347
4348
4349
4350
		return JIM_ERR;
	}

	/* COMMAND */
4351
	Jim_GetOpt_Obj(goi, &new_cmd);
4352
	/* does this command exist? */
4353
	cmd = Jim_GetCommand(goi->interp, new_cmd, JIM_ERRMSG);
zwelch's avatar
zwelch committed
4354
	if (cmd) {
4355
		cp = Jim_GetString(new_cmd, NULL);
4356
4357
4358
		Jim_SetResult_sprintf(goi->interp, "Command/target: %s Exists", cp);
		return JIM_ERR;
	}
4359

4360
	/* TYPE */
4361
	e = Jim_GetOpt_String(goi, &cp2, NULL);
4362
4363
	cp = cp2;
	/* now does target type exist */
zwelch's avatar
zwelch committed
4364
4365
	for (x = 0 ; target_types[x] ; x++) {
		if (0 == strcmp(cp, target_types[x]->name)) {
4366
4367
4368
4369
			/* found */
			break;
		}
	}
zwelch's avatar
zwelch committed
4370
	if (target_types[x] == NULL) {
4371
		Jim_SetResult_sprintf(goi->interp, "Unknown target type %s, try one of ", cp);
zwelch's avatar
zwelch committed
4372
4373
		for (x = 0 ; target_types[x] ; x++) {
			if (target_types[x + 1]) {
4374
				Jim_AppendStrings(goi->interp,
4375
4376
4377
4378
								   Jim_GetResult(goi->interp),
								   target_types[x]->name,
								   ", ", NULL);
			} else {
4379
				Jim_AppendStrings(goi->interp,
4380
4381
								   Jim_GetResult(goi->interp),
								   " or ",
4382
								   target_types[x]->name,NULL);
4383
4384
4385
4386
4387
4388
4389
4390
4391
4392
4393
4394
4395
			}
		}
		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));

4396
	memcpy(target->type, target_types[x], sizeof(target_type_t));
4397

4398
4399
4400
4401
4402
4403
4404
	/* 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;
4405

4406
4407
4408
4409
4410
4411
4412
	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;
4413

4414
4415
	target->display             = 1;

4416
4417
	target->halt_issued			= false;

4418
4419
4420
4421
4422
4423
4424
4425
4426
	/* 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;
4427

4428
4429
4430
4431
4432
4433
4434
	target->dbgmsg          = NULL;
	target->dbg_msg_enabled = 0;

	target->endianness = TARGET_ENDIAN_UNKNOWN;

	/* Do the rest as "configure" options */
	goi->isconfigure = 1;
4435
	e = target_configure(goi, target);
4436
4437
4438

	if (target->tap == NULL)
	{
4439
		Jim_SetResultString(interp, "-chain-position required when creating target", -1);
zwelch's avatar
zwelch committed
4440
		e = JIM_ERR;
4441
4442
	}

zwelch's avatar
zwelch committed
4443
	if (e != JIM_OK) {
4444
4445
		free(target->type);
		free(target);
4446
4447
4448
		return e;
	}

zwelch's avatar
zwelch committed
4449
	if (target->endianness == TARGET_ENDIAN_UNKNOWN) {
4450
4451
4452
4453
		/* default endian to little if not specified */
		target->endianness = TARGET_LITTLE_ENDIAN;
	}

4454
4455
4456
	/* incase variant is not set */
	if (!target->variant)
		target->variant = strdup("");
4457

4458
	/* create the target specific commands */
zwelch's avatar
zwelch committed
4459
	if (target->type->register_commands) {
4460
		(*(target->type->register_commands))(cmd_ctx);
4461
	}
zwelch's avatar
zwelch committed
4462
	if (target->type->target_create) {
4463
		(*(target->type->target_create))(target, goi->interp);
4464
4465
4466
4467
4468
4469
	}

	/* append to end of list */
	{
		target_t **tpp;
		tpp = &(all_targets);
zwelch's avatar
zwelch committed
4470
		while (*tpp) {
4471
			tpp = &((*tpp)->next);
4472
4473
4474
4475
		}
		*tpp = target;
	}

4476
	cp = Jim_GetString(new_cmd, NULL);
4477
4478
4479
	target->cmd_name = strdup(cp);

	/* now - create the new target name command */
4480
	e = Jim_CreateCommand(goi->interp,
4481
4482
4483
4484
						   /* name */
						   cp,
						   tcl_target_func, /* C function */
						   target, /* private data */
4485
						   NULL); /* no del proc */
4486
4487
4488
4489

	return e;
}

4490
static int jim_target(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
4491
4492
4493
4494
4495
4496
4497
4498
4499
4500
4501
4502
4503
4504
4505
4506
{
	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[] = {
4507
		"create", "types", "names", "current", "number",
4508
		"count",
4509
		NULL /* terminate */
4510
4511
4512
	};

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

4515
	cmd_ctx = Jim_GetAssocData(interp, "context");
4516

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

zwelch's avatar
zwelch committed
4519
	if (goi.argc == 0) {
4520
4521
4522
4523
		Jim_WrongNumArgs(interp, 1, argv, "missing: command ...");
		return JIM_ERR;
	}

4524
4525
	/* Jim_GetOpt_Debug(&goi); */
	r = Jim_GetOpt_Enum(&goi, target_cmds, &x);
zwelch's avatar
zwelch committed
4526
	if (r != JIM_OK) {
4527
4528
4529
		return r;
	}

zwelch's avatar
zwelch committed
4530
	switch (x) {
4531
4532
4533
4534
	default:
		Jim_Panic(goi.interp,"Why am I here?");
		return JIM_ERR;
	case TG_CMD_CURRENT:
zwelch's avatar
zwelch committed
4535
		if (goi.argc != 0) {
4536
			Jim_WrongNumArgs(goi.interp, 1, goi.argv, "Too many parameters");
4537
4538
			return JIM_ERR;
		}
4539
		Jim_SetResultString(goi.interp, get_current_target(cmd_ctx)->cmd_name, -1);
4540
4541
		return JIM_OK;
	case TG_CMD_TYPES:
zwelch's avatar
zwelch committed
4542
		if (goi.argc != 0) {
4543
			Jim_WrongNumArgs(goi.interp, 1, goi.argv, "Too many parameters");
4544
4545
			return JIM_ERR;
		}
4546
		Jim_SetResult(goi.interp, Jim_NewListObj(goi.interp, NULL, 0));
zwelch's avatar
zwelch committed
4547
		for (x = 0 ; target_types[x] ; x++) {
4548
			Jim_ListAppendElement(goi.interp,
4549
								   Jim_GetResult(goi.interp),
4550
								   Jim_NewStringObj(goi.interp, target_types[x]->name, -1));
4551
4552
4553
		}
		return JIM_OK;
	case TG_CMD_NAMES:
zwelch's avatar
zwelch committed
4554
		if (goi.argc != 0) {
4555
			Jim_WrongNumArgs(goi.interp, 1, goi.argv, "Too many parameters");
4556
4557
			return JIM_ERR;
		}
4558
		Jim_SetResult(goi.interp, Jim_NewListObj(goi.interp, NULL, 0));
4559
		target = all_targets;
zwelch's avatar
zwelch committed
4560
		while (target) {
4561
			Jim_ListAppendElement(goi.interp,
4562
								   Jim_GetResult(goi.interp),
4563
								   Jim_NewStringObj(goi.interp, target->cmd_name, -1));
4564
4565
			target = target->next;
		}
4566
		return JIM_OK;
4567
	case TG_CMD_CREATE:
zwelch's avatar
zwelch committed
4568
		if (goi.argc < 3) {
4569
			Jim_WrongNumArgs(goi.interp, goi.argc, goi.argv, "?name  ... config options ...");
4570
4571
			return JIM_ERR;
		}
4572
		return target_create(&goi);
4573
4574
		break;
	case TG_CMD_NUMBER:
4575
4576
		/* It's OK to remove this mechanism sometime after August 2010 or so */
		LOG_WARNING("don't use numbers as target identifiers; use names");
zwelch's avatar
zwelch committed
4577
		if (goi.argc != 1) {
4578
			Jim_SetResult_sprintf(goi.interp, "expected: target number ?NUMBER?");
4579
4580
			return JIM_ERR;
		}
4581
		e = Jim_GetOpt_Wide(&goi, &w);
zwelch's avatar
zwelch committed
4582
		if (e != JIM_OK) {
4583
4584
			return JIM_ERR;
		}
4585
4586
4587
		for (x = 0, target = all_targets; target; target = target->next, x++) {
			if (target->target_number == w)
				break;
4588
		}
4589
4590
4591
4592
4593
4594
4595
		if (target == NULL) {
			Jim_SetResult_sprintf(goi.interp,
					"Target: number %d does not exist", (int)(w));
			return JIM_ERR;
		}
		Jim_SetResultString(goi.interp, target->cmd_name, -1);
		return JIM_OK;
4596
	case TG_CMD_COUNT:
zwelch's avatar
zwelch committed
4597
		if (goi.argc != 0) {
4598
			Jim_WrongNumArgs(goi.interp, 0, goi.argv, "<no parameters>");
4599
4600
			return JIM_ERR;
		}
4601
4602
4603
		for (x = 0, target = all_targets; target; target = target->next, x++)
			continue;
		Jim_SetResult(goi.interp, Jim_NewIntObj(goi.interp, x));
4604
4605
		return JIM_OK;
	}
4606
4607

	return JIM_ERR;
4608
}
4609
4610
4611
4612


struct FastLoad
{
4613
	uint32_t address;
4614
	uint8_t *data;
4615
4616
4617
4618
4619
4620
4621
	int length;

};

static int fastload_num;
static struct FastLoad *fastload;

4622
static void free_fastload(void)
4623
{
zwelch's avatar
zwelch committed
4624
	if (fastload != NULL)
4625
4626
	{
		int i;
zwelch's avatar
zwelch committed
4627
		for (i = 0; i < fastload_num; i++)
4628
4629
4630
4631
4632
		{
			if (fastload[i].data)
				free(fastload[i].data);
		}
		free(fastload);
zwelch's avatar
zwelch committed
4633
		fastload = NULL;
4634
4635
4636
4637
4638
4639
	}
}




4640
static int handle_fast_load_image_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
4641
{
4642
	uint8_t *buffer;
4643
4644
	uint32_t buf_cnt;
	uint32_t image_size;
zwelch's avatar
zwelch committed
4645
4646
	uint32_t min_address = 0;
	uint32_t max_address = 0xffffffff;
4647
4648
4649
4650
	int i;

	image_t image;

4651
	int retval = parse_load_image_command_args(cmd_ctx, args, argc,
4652
4653
4654
			&image, &min_address, &max_address);
	if (ERROR_OK != retval)
		return retval;
4655

Zachary T Welch's avatar
Zachary T Welch committed
4656
4657
	struct duration bench;
	duration_start(&bench);
4658
4659
4660
4661
4662
4663
4664
4665

	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
4666
4667
	fastload_num = image.num_sections;
	fastload = (struct FastLoad *)malloc(sizeof(struct FastLoad)*image.num_sections);
zwelch's avatar
zwelch committed
4668
	if (fastload == NULL)
4669
4670
4671
4672
4673
4674
4675
4676
4677
4678
	{
		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)
		{
4679
			command_print(cmd_ctx, "error allocating buffer for section (%d bytes)",
duane's avatar
duane committed
4680
						  (int)(image.sections[i].size));
4681
4682
4683
4684
4685
4686
4687
4688
4689
			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
4690
4691
		uint32_t offset = 0;
		uint32_t length = buf_cnt;
4692
4693
4694
4695


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

zwelch's avatar
zwelch committed
4696
		if ((image.sections[i].base_address + buf_cnt >= min_address)&&
zwelch's avatar
zwelch committed
4697
				(image.sections[i].base_address < max_address))
4698
		{
zwelch's avatar
zwelch committed
4699
			if (image.sections[i].base_address < min_address)
4700
4701
			{
				/* clip addresses below */
zwelch's avatar
zwelch committed
4702
				offset += min_address-image.sections[i].base_address;
zwelch's avatar
zwelch committed
4703
				length -= offset;
4704
4705
			}

zwelch's avatar
zwelch committed
4706
			if (image.sections[i].base_address + buf_cnt > max_address)
4707
			{
zwelch's avatar
zwelch committed
4708
				length -= (image.sections[i].base_address + buf_cnt)-max_address;
4709
4710
			}

zwelch's avatar
zwelch committed
4711
			fastload[i].address = image.sections[i].base_address + offset;
zwelch's avatar
zwelch committed
4712
			fastload[i].data = malloc(length);
zwelch's avatar
zwelch committed
4713
			if (fastload[i].data == NULL)
4714
4715
4716
4717
			{
				free(buffer);
				break;
			}
zwelch's avatar
zwelch committed
4718
			memcpy(fastload[i].data, buffer + offset, length);
zwelch's avatar
zwelch committed
4719
			fastload[i].length = length;
4720
4721

			image_size += length;
oharboe's avatar
oharboe committed
4722
			command_print(cmd_ctx, "%u bytes written at address 0x%8.8x",
4723
						  (unsigned int)length,
zwelch's avatar
zwelch committed
4724
						  ((unsigned int)(image.sections[i].base_address + offset)));
4725
4726
4727
4728
4729
		}

		free(buffer);
	}

Zachary T Welch's avatar
Zachary T Welch committed
4730
	if ((ERROR_OK == retval) && (duration_measure(&bench) == ERROR_OK))
4731
	{
Zachary T Welch's avatar
Zachary T Welch committed
4732
4733
4734
4735
4736
4737
4738
		command_print(cmd_ctx, "Loaded %" PRIu32 " bytes "
				"in %fs (%0.3f kb/s)", image_size, 
				duration_elapsed(&bench), duration_kbps(&bench, image_size));

		command_print(cmd_ctx,
				"WARNING: image has not been loaded to target!"
				"You can issue a 'fast_load' to finish loading.");
4739
4740
4741
4742
	}

	image_close(&image);

zwelch's avatar
zwelch committed
4743
	if (retval != ERROR_OK)
4744
4745
4746
4747
4748
4749
4750
	{
		free_fastload();
	}

	return retval;
}

4751
static int handle_fast_load_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
4752
{
zwelch's avatar
zwelch committed
4753
	if (argc > 0)
4754
		return ERROR_COMMAND_SYNTAX_ERROR;
zwelch's avatar
zwelch committed
4755
	if (fastload == NULL)
4756
4757
4758
4759
4760
	{
		LOG_ERROR("No image in memory");
		return ERROR_FAIL;
	}
	int i;
zwelch's avatar
zwelch committed
4761
4762
4763
	int ms = timeval_ms();
	int size = 0;
	int retval = ERROR_OK;
zwelch's avatar
zwelch committed
4764
	for (i = 0; i < fastload_num;i++)
4765
4766
	{
		target_t *target = get_current_target(cmd_ctx);
4767
4768
		command_print(cmd_ctx, "Write to 0x%08x, length 0x%08x",
					  (unsigned int)(fastload[i].address),
duane's avatar
duane committed
4769
					  (unsigned int)(fastload[i].length));
zwelch's avatar
zwelch committed
4770
		if (retval == ERROR_OK)
4771
		{
oharboe's avatar
oharboe committed
4772
			retval = target_write_buffer(target, fastload[i].address, fastload[i].length, fastload[i].data);
4773
		}
zwelch's avatar
zwelch committed
4774
		size += fastload[i].length;
4775
	}
zwelch's avatar
zwelch committed
4776
	int after = timeval_ms();
4777
	command_print(cmd_ctx, "Loaded image %f kBytes/s", (float)(size/1024.0)/((float)(after-ms)/1000.0));
oharboe's avatar
oharboe committed
4778
	return retval;
4779
}
duane's avatar
duane committed
4780

4781
4782
4783
4784
4785
static int jim_mcrmrc(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
	command_context_t *context;
	target_t *target;
	int retval;
duane's avatar
duane committed
4786

4787
4788
4789
4790
4791
4792
4793
4794
4795
4796
4797
4798
4799
4800
4801
4802
4803
4804
4805
4806
4807
4808
4809
4810
4811
4812
4813
4814
4815
4816
4817
4818
4819
4820
4821
4822
4823
4824
4825
4826
4827
	context = Jim_GetAssocData(interp, "context");
	if (context == NULL) {
		LOG_ERROR("array2mem: no command context");
		return JIM_ERR;
	}
	target = get_current_target(context);
	if (target == NULL) {
		LOG_ERROR("array2mem: no current target");
		return JIM_ERR;
	}

	if ((argc < 6) || (argc > 7))
	{
		return JIM_ERR;
	}

	int cpnum;
	uint32_t op1;
	uint32_t op2;
	uint32_t CRn;
	uint32_t CRm;
	uint32_t value;

	int e;
	long l;
	e = Jim_GetLong(interp, argv[1], &l);
	if (e != JIM_OK) {
		return e;
	}
	cpnum = l;

	e = Jim_GetLong(interp, argv[2], &l);
	if (e != JIM_OK) {
		return e;
	}
	op1 = l;

	e = Jim_GetLong(interp, argv[3], &l);
	if (e != JIM_OK) {
		return e;
	}
4828
	CRn = l;
4829
4830
4831
4832
4833

	e = Jim_GetLong(interp, argv[4], &l);
	if (e != JIM_OK) {
		return e;
	}
4834
	CRm = l;
4835
4836
4837
4838
4839

	e = Jim_GetLong(interp, argv[5], &l);
	if (e != JIM_OK) {
		return e;
	}
4840
	op2 = l;
4841
4842
4843
4844
4845
4846
4847
4848
4849
4850
4851
4852
4853
4854
4855
4856
4857
4858
4859
4860
4861
4862
4863
4864
4865

	value = 0;

	if (argc == 7)
	{
		e = Jim_GetLong(interp, argv[6], &l);
		if (e != JIM_OK) {
			return e;
		}
		value = l;

		retval = target_mcr(target, cpnum, op1, op2, CRn, CRm, value);
		if (retval != ERROR_OK)
			return JIM_ERR;
	} else
	{
		retval = target_mrc(target, cpnum, op1, op2, CRn, CRm, &value);
		if (retval != ERROR_OK)
			return JIM_ERR;

		Jim_SetResult(interp, Jim_NewIntObj(interp, value));
	}

	return JIM_OK;
}
For faster browsing, not all history is shown. View entire blame