1 /***************************************************************************
2 * Copyright (C) 2007,2008 Øyvind Harboe *
3 * Copyright (C) 2008 Duane Ellis *
5 * This program is free software; you can redistribute it and/or modify *
6 * it under the terms of the GNU General Public License as published by *
7 * the Free Software Foundation; either version 2 of the License, or *
8 * (at your option) any later version. *
10 * This program is distributed in the hope that it will be useful, *
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13 * GNU General Public License for more details. *
15 * You should have received a copy of the GNU General Public License *
16 * along with this program; if not, write to the *
17 * Free Software Foundation, Inc., *
18 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
19 ***************************************************************************/
25 #include "../target/target.h"
26 #include "../jtag/jtag.h"
27 #include "../flash/flash.h"
32 static int new_int_array_element(Jim_Interp * interp, const char *varname, int idx, u32 val)
35 Jim_Obj *nameObjPtr, *valObjPtr;
38 namebuf = alloc_printf("%s(%d)", varname, idx);
42 nameObjPtr = Jim_NewStringObj(interp, namebuf, -1);
43 valObjPtr = Jim_NewIntObj(interp, val);
44 if (!nameObjPtr || !valObjPtr)
50 Jim_IncrRefCount(nameObjPtr);
51 Jim_IncrRefCount(valObjPtr);
52 result = Jim_SetVariable(interp, nameObjPtr, valObjPtr);
53 Jim_DecrRefCount(interp, nameObjPtr);
54 Jim_DecrRefCount(interp, valObjPtr);
56 /* printf("%s(%d) <= 0%08x\n", varname, idx, val); */
60 static int jim_mem2array(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
63 command_context_t *context;
75 /* argv[1] = name of array to receive the data
76 * argv[2] = desired width
77 * argv[3] = memory address
78 * argv[4] = count of times to read
81 Jim_WrongNumArgs(interp, 1, argv, "varname width addr nelems");
84 varname = Jim_GetString(argv[1], &len);
85 /* given "foo" get space for worse case "foo(%d)" .. add 20 */
87 e = Jim_GetLong(interp, argv[2], &l);
93 e = Jim_GetLong(interp, argv[3], &l);
98 e = Jim_GetLong(interp, argv[4], &l);
114 Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));
115 Jim_AppendStrings( interp, Jim_GetResult(interp), "Invalid width param, must be 8/16/32", NULL );
119 Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));
120 Jim_AppendStrings(interp, Jim_GetResult(interp), "mem2array: zero width read?", NULL);
123 if ((addr + (len * width)) < addr) {
124 Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));
125 Jim_AppendStrings(interp, Jim_GetResult(interp), "mem2array: addr + len - wraps to zero?", NULL);
128 /* absurd transfer size? */
130 Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));
131 Jim_AppendStrings(interp, Jim_GetResult(interp), "mem2array: absurd > 64K item request", NULL);
136 ((width == 2) && ((addr & 1) == 0)) ||
137 ((width == 4) && ((addr & 3) == 0))) {
141 Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));
142 sprintf(buf, "mem2array address: 0x%08x is not aligned for %d byte reads", addr, width);
143 Jim_AppendStrings(interp, Jim_GetResult(interp), buf , NULL);
147 context = Jim_GetAssocData(interp, "context");
150 LOG_ERROR("mem2array: no command context");
153 target = get_current_target(context);
156 LOG_ERROR("mem2array: no current target");
167 /* Slurp... in buffer size chunks */
169 count = len; /* in objects.. */
170 if (count > (sizeof(buffer)/width)) {
171 count = (sizeof(buffer)/width);
174 retval = target->type->read_memory( target, addr, width, count, buffer );
175 if (retval != ERROR_OK) {
177 LOG_ERROR("mem2array: Read @ 0x%08x, w=%d, cnt=%d, failed", addr, width, count);
178 Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));
179 Jim_AppendStrings(interp, Jim_GetResult(interp), "mem2array: cannot read memory", NULL);
183 v = 0; /* shut up gcc */
184 for (i = 0 ;i < count ;i++, n++) {
187 v = target_buffer_get_u32(target, &buffer[i*width]);
190 v = target_buffer_get_u16(target, &buffer[i*width]);
193 v = buffer[i] & 0x0ff;
196 new_int_array_element(interp, varname, n, v);
202 Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));
207 static int get_int_array_element(Jim_Interp * interp, const char *varname, int idx, u32 *val)
210 Jim_Obj *nameObjPtr, *valObjPtr;
214 namebuf = alloc_printf("%s(%d)", varname, idx);
218 nameObjPtr = Jim_NewStringObj(interp, namebuf, -1);
225 Jim_IncrRefCount(nameObjPtr);
226 valObjPtr = Jim_GetVariable(interp, nameObjPtr, JIM_ERRMSG);
227 Jim_DecrRefCount(interp, nameObjPtr);
229 if (valObjPtr == NULL)
232 result = Jim_GetLong(interp, valObjPtr, &l);
233 /* printf("%s(%d) => 0%08x\n", varname, idx, val); */
238 static int jim_array2mem(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
241 command_context_t *context;
252 /* argv[1] = name of array to get the data
253 * argv[2] = desired width
254 * argv[3] = memory address
255 * argv[4] = count to write
258 Jim_WrongNumArgs(interp, 1, argv, "varname width addr nelems");
261 varname = Jim_GetString(argv[1], &len);
262 /* given "foo" get space for worse case "foo(%d)" .. add 20 */
264 e = Jim_GetLong(interp, argv[2], &l);
270 e = Jim_GetLong(interp, argv[3], &l);
275 e = Jim_GetLong(interp, argv[4], &l);
291 Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));
292 Jim_AppendStrings( interp, Jim_GetResult(interp), "Invalid width param, must be 8/16/32", NULL );
296 Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));
297 Jim_AppendStrings(interp, Jim_GetResult(interp), "array2mem: zero width read?", NULL);
300 if ((addr + (len * width)) < addr) {
301 Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));
302 Jim_AppendStrings(interp, Jim_GetResult(interp), "array2mem: addr + len - wraps to zero?", NULL);
305 /* absurd transfer size? */
307 Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));
308 Jim_AppendStrings(interp, Jim_GetResult(interp), "array2mem: absurd > 64K item request", NULL);
313 ((width == 2) && ((addr & 1) == 0)) ||
314 ((width == 4) && ((addr & 3) == 0))) {
318 Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));
319 sprintf(buf, "array2mem address: 0x%08x is not aligned for %d byte reads", addr, width);
320 Jim_AppendStrings(interp, Jim_GetResult(interp), buf , NULL);
324 context = Jim_GetAssocData(interp, "context");
327 LOG_ERROR("array2mem: no command context");
330 target = get_current_target(context);
333 LOG_ERROR("array2mem: no current target");
344 /* Slurp... in buffer size chunks */
346 count = len; /* in objects.. */
347 if (count > (sizeof(buffer)/width)) {
348 count = (sizeof(buffer)/width);
351 v = 0; /* shut up gcc */
352 for (unsigned i = 0 ;i < count ;i++, n++) {
353 get_int_array_element(interp, varname, n, &v);
356 target_buffer_set_u32(target, &buffer[i*width], v);
359 target_buffer_set_u16(target, &buffer[i*width], v);
362 buffer[i] = v & 0x0ff;
368 retval = target->type->write_memory(target, addr, width, count, buffer);
369 if (retval != ERROR_OK) {
371 LOG_ERROR("array2mem: Write @ 0x%08x, w=%d, cnt=%d, failed", addr, width, count);
372 Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));
373 Jim_AppendStrings(interp, Jim_GetResult(interp), "mem2array: cannot read memory", NULL);
379 Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));
384 int Jim_Command_drscan(Jim_Interp *interp, int argc, Jim_Obj *const *args)
387 scan_field_t *fields;
395 * args[3] = hex string
396 * ... repeat num bits and hex string ...
398 if ((argc < 4) || ((argc % 2)!=0))
400 Jim_WrongNumArgs(interp, 1, args, "<device> <num_bits1> <value1> <num_bits2> <value2> ...");
404 for (i = 2; i < argc; i+=2)
408 e = Jim_GetLong(interp, args[i], &bits);
413 e = Jim_GetLong(interp, args[1], &device);
417 num_fields=(argc-2)/2;
418 fields = malloc(sizeof(scan_field_t) * num_fields);
419 for (i = 2; i < argc; i+=2)
425 Jim_GetLong(interp, args[i], &bits);
426 str = Jim_GetString(args[i+1], &len);
428 fields[field_count].num_bits = bits;
429 fields[field_count].out_value = malloc(CEIL(bits, 8));
430 str_to_buf(str, len, fields[field_count].out_value, bits, 0);
431 fields[field_count].in_value = fields[field_count].out_value;
434 jtag_add_dr_scan(num_fields, fields, TAP_INVALID);
435 retval = jtag_execute_queue();
436 if (retval != ERROR_OK)
438 Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));
439 Jim_AppendStrings(interp, Jim_GetResult(interp), "drscan: jtag execute failed", NULL);
444 Jim_Obj *list = Jim_NewListObj(interp, NULL, 0);
445 for (i = 2; i < argc; i+=2)
450 Jim_GetLong(interp, args[i], &bits);
451 str = buf_to_str(fields[field_count].in_value, bits, 16);
452 free(fields[field_count].out_value);
454 Jim_ListAppendElement(interp, list, Jim_NewStringObj(interp, str, strlen(str)));
459 Jim_SetResult(interp, list);
466 static int jim_flash_banks(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
470 Jim_WrongNumArgs(interp, 1, argv, "no arguments to flash_banks command");
474 unsigned flash_banks = flash_get_bank_count();
480 Jim_Obj *list=Jim_NewListObj(interp, NULL, 0);
481 for (unsigned i = 0; i < flash_banks; i++)
483 flash_bank_t *p = get_flash_bank_by_num(i);
484 Jim_Obj *elem=Jim_NewListObj(interp, NULL, 0);
486 Jim_ListAppendElement(interp, elem, Jim_NewStringObj(interp, "name", -1));
487 Jim_ListAppendElement(interp, elem, Jim_NewStringObj(interp, p->driver->name, -1));
488 Jim_ListAppendElement(interp, elem, Jim_NewStringObj(interp, "base", -1));
489 Jim_ListAppendElement(interp, elem, Jim_NewIntObj(interp, p->base));
490 Jim_ListAppendElement(interp, elem, Jim_NewStringObj(interp, "size", -1));
491 Jim_ListAppendElement(interp, elem, Jim_NewIntObj(interp, p->size));
492 Jim_ListAppendElement(interp, elem, Jim_NewStringObj(interp, "bus_width", -1));
493 Jim_ListAppendElement(interp, elem, Jim_NewIntObj(interp, p->bus_width));
494 Jim_ListAppendElement(interp, elem, Jim_NewStringObj(interp, "chip_width", -1));
495 Jim_ListAppendElement(interp, elem, Jim_NewIntObj(interp, p->chip_width));
497 Jim_ListAppendElement(interp, list, elem);
500 Jim_SetResult(interp, list);
505 int tclapi_register_commands(struct command_context_s *cmd_ctx)
507 register_jim(cmd_ctx, "ocd_mem2array", &jim_mem2array,
508 "read memory and return as a TCL array for script processing");
509 register_jim(cmd_ctx, "ocd_array2mem", &jim_array2mem,
510 "convert a TCL array to memory locations and write the values");
511 register_jim(cmd_ctx, "drscan", &Jim_Command_drscan,
512 "execute DR scan <device> <num_bits> <value> <num_bits1> <value2> ...");
513 register_jim(cmd_ctx, "ocd_flash_banks", &jim_flash_banks,
514 "return information about the flash banks");