diff --git a/src/openocd.c b/src/openocd.c index c7b18eb24..64965e37a 100644 --- a/src/openocd.c +++ b/src/openocd.c @@ -194,16 +194,24 @@ static int new_int_array_element(Jim_Interp * interp, const char *varname, int i int result; namebuf = alloc_printf("%s(%d)", varname, idx); + if (!namebuf) + return JIM_ERR; nameObjPtr = Jim_NewStringObj(interp, namebuf, -1); valObjPtr = Jim_NewIntObj(interp, val); + if (!nameObjPtr || !valObjPtr) + { + free(namebuf); + return JIM_ERR; + } + Jim_IncrRefCount(nameObjPtr); Jim_IncrRefCount(valObjPtr); result = Jim_SetVariable(interp, nameObjPtr, valObjPtr); Jim_DecrRefCount(interp, nameObjPtr); Jim_DecrRefCount(interp, valObjPtr); free(namebuf); - /* printf( "%s = 0%08x\n", namebuf, val ); */ + /* printf("%s(%d) <= 0%08x\n", varname, idx, val); */ return result; } @@ -223,7 +231,7 @@ static int Jim_Command_mem2array(Jim_Interp *interp, int argc, Jim_Obj *const *a /* argv[1] = name of array to receive the data * argv[2] = desired width * argv[3] = memory address - * argv[4] = length in bytes to read + * argv[4] = count of times to read */ if (argc != 5) { Jim_WrongNumArgs(interp, 1, argv, "varname width addr nelems"); @@ -309,7 +317,6 @@ static int Jim_Command_mem2array(Jim_Interp *interp, int argc, Jim_Obj *const *a } retval = target->type->read_memory( target, addr, width, count, buffer ); - if (retval != ERROR_OK) { /* BOO !*/ LOG_ERROR("mem2array: Read @ 0x%08x, w=%d, cnt=%d, failed", addr, width, count); @@ -342,6 +349,171 @@ static int Jim_Command_mem2array(Jim_Interp *interp, int argc, Jim_Obj *const *a return JIM_OK; } +static int get_int_array_element(Jim_Interp * interp, const char *varname, int idx, u32 *val) +{ + char *namebuf; + Jim_Obj *nameObjPtr, *valObjPtr; + int result; + long l; + + namebuf = alloc_printf("%s(%d)", varname, idx); + if (!namebuf) + return JIM_ERR; + + nameObjPtr = Jim_NewStringObj(interp, namebuf, -1); + if (!nameObjPtr) + { + free(namebuf); + return JIM_ERR; + } + + Jim_IncrRefCount(nameObjPtr); + valObjPtr = Jim_GetVariable(interp, nameObjPtr, JIM_ERRMSG); + Jim_DecrRefCount(interp, nameObjPtr); + free(namebuf); + if (valObjPtr == NULL) + return JIM_ERR; + + result = Jim_GetLong(interp, valObjPtr, &l); + /* printf("%s(%d) => 0%08x\n", varname, idx, val); */ + *val = l; + return result; +} + +static int Jim_Command_array2mem(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + target_t *target; + long l; + u32 width; + u32 len; + u32 addr; + u32 count; + u32 v; + const char *varname; + u8 buffer[4096]; + int i, n, e, retval; + + /* argv[1] = name of array to get the data + * argv[2] = desired width + * argv[3] = memory address + * argv[4] = count to write + */ + if (argc != 5) { + Jim_WrongNumArgs(interp, 1, argv, "varname width addr nelems"); + return JIM_ERR; + } + varname = Jim_GetString(argv[1], &len); + /* given "foo" get space for worse case "foo(%d)" .. add 20 */ + + e = Jim_GetLong(interp, argv[2], &l); + width = l; + if (e != JIM_OK) { + return e; + } + + e = Jim_GetLong(interp, argv[3], &l); + addr = l; + if (e != JIM_OK) { + return e; + } + e = Jim_GetLong(interp, argv[4], &l); + len = l; + if (e != JIM_OK) { + return e; + } + switch (width) { + case 8: + width = 1; + break; + case 16: + width = 2; + break; + case 32: + width = 4; + break; + default: + Jim_SetResult(interp, Jim_NewEmptyStringObj(interp)); + Jim_AppendStrings( interp, Jim_GetResult(interp), "Invalid width param, must be 8/16/32", NULL ); + return JIM_ERR; + } + if (len == 0) { + Jim_SetResult(interp, Jim_NewEmptyStringObj(interp)); + Jim_AppendStrings(interp, Jim_GetResult(interp), "array2mem: zero width read?", NULL); + return JIM_ERR; + } + if ((addr + (len * width)) < addr) { + Jim_SetResult(interp, Jim_NewEmptyStringObj(interp)); + Jim_AppendStrings(interp, Jim_GetResult(interp), "array2mem: addr + len - wraps to zero?", NULL); + return JIM_ERR; + } + /* absurd transfer size? */ + if (len > 65536) { + Jim_SetResult(interp, Jim_NewEmptyStringObj(interp)); + Jim_AppendStrings(interp, Jim_GetResult(interp), "array2mem: absurd > 64K item request", NULL); + return JIM_ERR; + } + + if ((width == 1) || + ((width == 2) && ((addr & 1) == 0)) || + ((width == 4) && ((addr & 3) == 0))) { + /* all is well */ + } else { + char buf[100]; + Jim_SetResult(interp, Jim_NewEmptyStringObj(interp)); + sprintf(buf, "array2mem address: 0x%08x is not aligned for %d byte reads", addr, width); + Jim_AppendStrings(interp, Jim_GetResult(interp), buf , NULL); + return JIM_ERR; + } + + target = get_current_target(active_cmd_ctx); + + /* Transfer loop */ + + /* index counter */ + n = 0; + /* assume ok */ + e = JIM_OK; + while (len) { + /* Slurp... in buffer size chunks */ + + count = len; /* in objects.. */ + if (count > (sizeof(buffer)/width)) { + count = (sizeof(buffer)/width); + } + + v = 0; /* shut up gcc */ + for (i = 0 ;i < count ;i++, n++) { + get_int_array_element(interp, varname, n, &v); + switch (width) { + case 4: + target_buffer_set_u32(target, &buffer[i*width], v); + break; + case 2: + target_buffer_set_u16(target, &buffer[i*width], v); + break; + case 1: + buffer[i] = v & 0x0ff; + break; + } + } + len -= count; + + retval = target->type->write_memory(target, addr, width, count, buffer); + if (retval != ERROR_OK) { + /* BOO !*/ + LOG_ERROR("array2mem: Write @ 0x%08x, w=%d, cnt=%d, failed", addr, width, count); + Jim_SetResult(interp, Jim_NewEmptyStringObj(interp)); + Jim_AppendStrings(interp, Jim_GetResult(interp), "mem2array: cannot read memory", NULL); + e = JIM_ERR; + len = 0; + } + } + + Jim_SetResult(interp, Jim_NewEmptyStringObj(interp)); + + return JIM_OK; +} + static void tcl_output(void *privData, const char *file, int line, const char *function, const char *string) { Jim_Obj *tclOutput=(Jim_Obj *)privData; @@ -557,7 +729,8 @@ void initJim(void) Jim_CreateCommand(interp, "find", Jim_Command_find, NULL, NULL); Jim_CreateCommand(interp, "echo", Jim_Command_echo, NULL, NULL); Jim_CreateCommand(interp, "mem2array", Jim_Command_mem2array, NULL, NULL ); - + Jim_CreateCommand(interp, "array2mem", Jim_Command_array2mem, NULL, NULL ); + /* Set Jim's STDIO */ interp->cookie_stdin = NULL; interp->cookie_stdout = NULL; diff --git a/src/tcl/bitsbytes.tcl b/src/tcl/bitsbytes.tcl index b1771b4bc..9129ae0ad 100644 --- a/src/tcl/bitsbytes.tcl +++ b/src/tcl/bitsbytes.tcl @@ -7,30 +7,28 @@ for { set x 0 } { $x < 32 } { set x [expr $x + 1]} { set vn [format "BIT%d" $x] - set $vn [expr (1 << $x)] global $vn - + set $vn [expr (1 << $x)] } # Create K bytes values # __1K ... to __2048K for { set x 1 } { $x < 2048 } { set x [expr $x * 2]} { set vn [format "__%dK" $x] - set $vn [expr (1024 * $x)] global $vn + set $vn [expr (1024 * $x)] } # Create M bytes values # __1M ... to __2048K for { set x 1 } { $x < 2048 } { set x [expr $x * 2]} { set vn [format "__%dM" $x] - set $vn [expr (1024 * 1024 * $x)] global $vn + set $vn [expr (1024 * 1024 * $x)] } proc create_mask { MSB LSB } { return [expr (((1 << ($MSB - $LSB + 1))-1) << $LSB)] - } # Cut Bits $MSB to $LSB out of this value. diff --git a/src/tcl/memory.tcl b/src/tcl/memory.tcl index 5ac3c4bd8..42cd06276 100644 --- a/src/tcl/memory.tcl +++ b/src/tcl/memory.tcl @@ -78,31 +78,56 @@ proc address_info { ADDRESS } { return "UNKNOWN 0" } -proc memread32 {ADDR } { +proc memread32 {ADDR} { set foo(0) 0 if ![ catch { mem2array foo 32 $ADDR 1 } msg ] { return $foo(0) } else { - error "memead32: $msg" + error "memread32: $msg" } } -proc memread16 {ADDR } { +proc memread16 {ADDR} { set foo(0) 0 if ![ catch { mem2array foo 16 $ADDR 1 } msg ] { return $foo(0) } else { - error "memead16: $msg" + error "memread16: $msg" } } -proc memread8 {ADDR } { +proc memread8 {ADDR} { set foo(0) 0 if ![ catch { mem2array foo 8 $ADDR 1 } msg ] { return $foo(0) } else { - error "memead8: $msg" + error "memread8: $msg" } } +proc memwrite32 {ADDR DATA} { + set foo(0) $DATA + if ![ catch { array2mem foo 32 $ADDR 1 } msg ] { + return $foo(0) + } else { + error "memwrite32: $msg" + } +} +proc memwrite16 {ADDR DATA} { + set foo(0) $DATA + if ![ catch { array2mem foo 16 $ADDR 1 } msg ] { + return $foo(0) + } else { + error "memwrite16: $msg" + } +} + +proc memwrite8 {ADDR DATA} { + set foo(0) $DATA + if ![ catch { array2mem foo 8 $ADDR 1 } msg ] { + return $foo(0) + } else { + error "memwrite8: $msg" + } +}