- Log output handlers now get a "const char *line" - Added "const" to parameter. src/helper/command.c src/helper/command.h - New function: 'command_output_text()' - Log output handlers now get a "const char *line" src/helper/options.c - Log output handlers now get a "const char *line" src/server/telnet_server.c - DO not transmit NULL bytes via TELNET. - Log output handlers now get a "const char *line" src/server/gdb_server.c - Log output handlers now get a "const char *line" *** THIS INCLUDES PORTIONS OF A PATCH FROM Oyvind sent previously to the mailing list for TCL users try src/target/target.c *** THIS INCLUDES PORTIONS OF A PATCH FROM Oyvind sent previously to the mailing list for TCL users try src/target/target.h *** THIS INCLUDES PORTIONS OF A PATCH FROM Oyvind sent previously to the mailing list for TCL users try src/openocd.c - **MAJOR** Work: New TCL/Jim function: mem2array - **MAJOR** Work: Redirect Tcl/Jim stdio output to remote users. - Previously: TCL output did not go to GDB. - Previously: TCL output did not go to TELNET - Previously: TCL output only goes to control console. - This fixes that problem. + Created callbacks: +openocd_jim_fwrite() +openocd_jim_fread() +openocd_jim_vfprintf() +openocd_jim_fflush() +openocd_jim_fgets() src/Makefile.am - New TCL files. - Future note: This should be more automated. As the list of 'tcl' files grows maintaning this list will suck. src/Jim.c - ** THIS INCLUDES A PREVIOUS PATCH I SENT EARLIER ** - that impliments many [format] specifies JIM did not support. - Jim_FormatString() - **MAJOR** work. - Previously only supported "%s" "%d" and "%c" - And what support existed had bugs. - NEW: *MANY* formating parameters are now supported. - TODO: The "precision" specifier is not supported. ** NEW ** This patch. - Jim_StringToWide() test if no conversion occured. - Jim_StringToIndex() test if no conversion occured. - Jim_StringToDouble() test if no conversion occured. ** NEW ** This Patch. Major Work. - Previously output from JIM did not get sent to GDB - Ditto: Output to Telnet session. - Above items are now fixed - By introducing callbacks new function pointers in the "interp" structure. - Helpers that call the callbacks. - New function: Jim_fprintf() - New function: Jim_vfprintf() - New function: Jim_fwrite() - New function: Jim_fread() - New function: Jim_fflush() - New function: Jim_fgets() By default: the output is to STDIO as previous. The "openocd.c" - redirects the output as needed. - Jim_Panic() - Send panic to both STDERR and the interps specified STDERR output as a 2nd choice. - Now JIM's "stdin/stdout/stderr" paramters are "void *" and are no longer "FILE *". src/Jim.h - **MAJOR** - New JIM STDIO callbacks in the "interp" structure. - change: "stdin/stdout/stderr" are now "void *" cookies. - New JIM stdio helper functions. git-svn-id: svn://svn.berlios.de/openocd/trunk@755 b42882b7-edfa-0310-969c-e2dbd0fdcd60tags/v0.1.0
@@ -81,4 +81,20 @@ openocd_LDADD = $(top_builddir)/src/xsvf/libxsvf.a \ | |||
nobase_dist_pkglib_DATA = tcl/commands.tcl | |||
nobase_dist_pkglib_DATA = \ | |||
tcl/commands.tcl \ | |||
tcl/bitsbytes.tcl \ | |||
tcl/chip/atmel/at91/aic.tcl \ | |||
tcl/chip/atmel/at91/at91sam7x128.tcl \ | |||
tcl/chip/atmel/at91/at91sam7x256.tcl \ | |||
tcl/chip/atmel/at91/pmc.tcl \ | |||
tcl/chip/atmel/at91/rtt.tcl \ | |||
tcl/chip/atmel/at91/usarts.tcl \ | |||
tcl/cpu/arm/arm7tdmi.tcl \ | |||
tcl/cpu/arm/arm920.tcl \ | |||
tcl/cpu/arm/arm946.tcl \ | |||
tcl/cpu/arm/arm966.tcl \ | |||
tcl/memory.tcl \ | |||
tcl/mmr_helpers.tcl \ | |||
tcl/readable.tcl | |||
@@ -621,7 +621,7 @@ int command_print_help(command_context_t* context, char* name, char** args, int | |||
return command_print_help_match(context, context->commands, name, args, argc); | |||
} | |||
void command_set_output_handler(command_context_t* context, int (*output_handler)(struct command_context_s *context, char* line), void *priv) | |||
void command_set_output_handler(command_context_t* context, int (*output_handler)(struct command_context_s *context, const char* line), void *priv) | |||
{ | |||
context->output_handler = output_handler; | |||
context->output_handler_priv = priv; | |||
@@ -720,3 +720,10 @@ int handle_time_command(struct command_context_s *cmd_ctx, char *cmd, char **arg | |||
return retval; | |||
} | |||
/* | |||
* Local Variables: ** | |||
* tab-width: 4 ** | |||
* c-basic-offset: 4 ** | |||
* End: ** | |||
*/ | |||
@@ -48,7 +48,7 @@ typedef struct command_context_s | |||
* Returning ERROR_COMMAND_SYNTAX_ERROR will have the effect of | |||
* printing out the syntax of the command. | |||
*/ | |||
int (*output_handler)(struct command_context_s *context, char* line); | |||
int (*output_handler)(struct command_context_s *context, const char* line); | |||
void *output_handler_priv; | |||
} command_context_t; | |||
@@ -67,7 +67,7 @@ typedef struct command_s | |||
extern command_t* register_command(command_context_t *context, command_t *parent, char *name, int (*handler)(struct command_context_s *context, char* name, char** args, int argc), enum command_mode mode, char *help); | |||
extern int unregister_command(command_context_t *context, char *name); | |||
extern int unregister_all_commands(command_context_t *context); | |||
extern void command_set_output_handler(command_context_t* context, int (*output_handler)(struct command_context_s *context, char* line), void *priv); | |||
extern void command_set_output_handler(command_context_t* context, int (*output_handler)(struct command_context_s *context, const char* line), void *priv); | |||
extern command_context_t* copy_command_context(command_context_t* context); | |||
extern command_context_t* command_init(); | |||
extern int command_done(command_context_t *context); | |||
@@ -86,3 +86,11 @@ extern int command_run_file(command_context_t *context, FILE *file, enum command | |||
extern int fast_and_dangerous; | |||
#endif /* COMMAND_H */ | |||
/* | |||
* Local Variables: ** | |||
* tab-width: 4 ** | |||
* c-basic-offset: 4 ** | |||
* End: ** | |||
*/ | |||
@@ -27,7 +27,7 @@ extern int parse_cmdline_args(struct command_context_s *cmd_ctx, int argc, char | |||
extern int parse_config_file(struct command_context_s *cmd_ctx); | |||
extern void add_config_command (const char *cfg); | |||
extern void add_script_search_dir (const char *dir); | |||
extern int configuration_output_handler(struct command_context_s *context, char* line); | |||
extern int configuration_output_handler(struct command_context_s *context, const char* line); | |||
extern FILE *open_file_from_path (char *file, char *mode); | |||
extern char *find_file(char *name); | |||
@@ -45,7 +45,7 @@ static struct option long_options[] = | |||
{0, 0, 0, 0} | |||
}; | |||
int configuration_output_handler(struct command_context_s *context, char* line) | |||
int configuration_output_handler(struct command_context_s *context, const char* line) | |||
{ | |||
LOG_INFO_N(line); | |||
@@ -363,7 +363,7 @@ int Jim_StringToWide(const char *str, jim_wide *widePtr, int base) | |||
#else | |||
*widePtr = strtol(str, &endptr, base); | |||
#endif | |||
if (str[0] == '\0') | |||
if ((str[0] == '\0') || (str == endptr) ) | |||
return JIM_ERR; | |||
if (endptr[0] != '\0') { | |||
while(*endptr) { | |||
@@ -380,7 +380,7 @@ int Jim_StringToIndex(const char *str, int *intPtr) | |||
char *endptr; | |||
*intPtr = strtol(str, &endptr, 10); | |||
if (str[0] == '\0') | |||
if ( (str[0] == '\0') || (str == endptr) ) | |||
return JIM_ERR; | |||
if (endptr[0] != '\0') { | |||
while(*endptr) { | |||
@@ -437,7 +437,7 @@ int Jim_StringToDouble(const char *str, double *doublePtr) | |||
char *endptr; | |||
*doublePtr = strtod(str, &endptr); | |||
if (str[0] == '\0' || endptr[0] != '\0') | |||
if (str[0] == '\0' || endptr[0] != '\0' || (str == endptr) ) | |||
return JIM_ERR; | |||
return JIM_OK; | |||
} | |||
@@ -460,13 +460,16 @@ static jim_wide JimPowWide(jim_wide b, jim_wide e) | |||
void Jim_Panic(Jim_Interp *interp, const char *fmt, ...) | |||
{ | |||
va_list ap; | |||
FILE *fp = interp ? interp->stderr_ : stderr; | |||
va_start(ap, fmt); | |||
fprintf(fp, JIM_NL "JIM INTERPRETER PANIC: "); | |||
vfprintf(fp, fmt, ap); | |||
fprintf(fp, JIM_NL JIM_NL); | |||
/* | |||
* Send it here first.. Assuming STDIO still works | |||
*/ | |||
fprintf(stderr, JIM_NL "JIM INTERPRETER PANIC: "); | |||
vfprintf(stderr, fmt, ap); | |||
fprintf(stderr, JIM_NL JIM_NL); | |||
va_end(ap); | |||
#ifdef HAVE_BACKTRACE | |||
{ | |||
void *array[40]; | |||
@@ -481,6 +484,13 @@ void Jim_Panic(Jim_Interp *interp, const char *fmt, ...) | |||
fprintf(fp,"[backtrace] of 'nm <executable>' in the bug report." JIM_NL); | |||
} | |||
#endif | |||
/* This may actually crash... we do it last */ | |||
if( interp && interp->cookie_stderr ){ | |||
Jim_fprintf( interp, interp->cookie_stderr, JIM_NL "JIM INTERPRETER PANIC: "); | |||
Jim_vfprintf( interp, interp->cookie_stderr, fmt, ap ); | |||
Jim_fprintf( interp, interp->cookie_stderr, JIM_NL JIM_NL ); | |||
} | |||
abort(); | |||
} | |||
@@ -2136,21 +2146,36 @@ static Jim_Obj *JimStringToUpper(Jim_Interp *interp, Jim_Obj *strObjPtr) | |||
} | |||
/* This is the core of the [format] command. | |||
* TODO: Export it, make it real... for now only %s and %% | |||
* specifiers supported. */ | |||
* TODO: Lots of things work - via a hack | |||
* However, no format item can be >= JIM_MAX_FMT | |||
*/ | |||
Jim_Obj *Jim_FormatString(Jim_Interp *interp, Jim_Obj *fmtObjPtr, | |||
int objc, Jim_Obj *const *objv) | |||
{ | |||
const char *fmt; | |||
const char *fmt, *_fmt; | |||
int fmtLen; | |||
Jim_Obj *resObjPtr; | |||
fmt = Jim_GetString(fmtObjPtr, &fmtLen); | |||
_fmt = fmt; | |||
resObjPtr = Jim_NewStringObj(interp, "", 0); | |||
while (fmtLen) { | |||
const char *p = fmt; | |||
char spec[2], c; | |||
jim_wide wideValue; | |||
double doubleValue; | |||
/* we cheat and use Sprintf()! */ | |||
#define JIM_MAX_FMT 2048 | |||
char sprintf_buf[JIM_MAX_FMT]; | |||
char fmt_str[100]; | |||
char *cp; | |||
int width; | |||
int ljust; | |||
int zpad; | |||
int spad; | |||
int altfm; | |||
int forceplus; | |||
while (*fmt != '%' && fmtLen) { | |||
fmt++; fmtLen--; | |||
@@ -2159,38 +2184,191 @@ Jim_Obj *Jim_FormatString(Jim_Interp *interp, Jim_Obj *fmtObjPtr, | |||
if (fmtLen == 0) | |||
break; | |||
fmt++; fmtLen--; /* skip '%' */ | |||
if (*fmt != '%') { | |||
zpad = 0; | |||
spad = 0; | |||
width = -1; | |||
ljust = 0; | |||
altfm = 0; | |||
forceplus = 0; | |||
next_fmt: | |||
if( fmtLen <= 0 ){ | |||
break; | |||
} | |||
switch( *fmt ){ | |||
/* terminals */ | |||
case 'b': /* binary - not all printfs() do this */ | |||
case 's': /* string */ | |||
case 'i': /* integer */ | |||
case 'd': /* decimal */ | |||
case 'x': /* hex */ | |||
case 'X': /* CAP hex */ | |||
case 'c': /* char */ | |||
case 'o': /* octal */ | |||
case 'u': /* unsigned */ | |||
case 'f': /* float */ | |||
break; | |||
/* non-terminals */ | |||
case '0': /* zero pad */ | |||
zpad = 1; | |||
*fmt++; fmtLen--; | |||
goto next_fmt; | |||
break; | |||
case '+': | |||
forceplus = 1; | |||
*fmt++; fmtLen--; | |||
goto next_fmt; | |||
break; | |||
case ' ': /* sign space */ | |||
spad = 1; | |||
*fmt++; fmtLen--; | |||
goto next_fmt; | |||
break; | |||
case '-': | |||
ljust = 1; | |||
*fmt++; fmtLen--; | |||
goto next_fmt; | |||
break; | |||
case '#': | |||
altfm = 1; | |||
*fmt++; fmtLen--; | |||
goto next_fmt; | |||
case '1': | |||
case '2': | |||
case '3': | |||
case '4': | |||
case '5': | |||
case '6': | |||
case '7': | |||
case '8': | |||
case '9': | |||
width = 0; | |||
while( isdigit(*fmt) && (fmtLen > 0) ){ | |||
width = (width * 10) + (*fmt - '0'); | |||
fmt++; fmtLen--; | |||
} | |||
goto next_fmt; | |||
case '*': | |||
/* suck up the next item as an integer */ | |||
*fmt++; fmtLen--; | |||
objc--; | |||
if( objc <= 0 ){ | |||
goto not_enough_args; | |||
} | |||
if( Jim_GetWide(interp,objv[0],&wideValue )== JIM_ERR ){ | |||
Jim_FreeNewObj(interp, resObjPtr ); | |||
return NULL; | |||
} | |||
width = wideValue; | |||
if( width < 0 ){ | |||
ljust = 1; | |||
width = -width; | |||
} | |||
objv++; | |||
goto next_fmt; | |||
break; | |||
} | |||
if (*fmt != '%') { | |||
if (objc == 0) { | |||
not_enough_args: | |||
Jim_FreeNewObj(interp, resObjPtr); | |||
Jim_SetResultString(interp, | |||
"not enough arguments for all format specifiers", -1); | |||
"not enough arguments for all format specifiers", -1); | |||
return NULL; | |||
} else { | |||
objc--; | |||
} | |||
} | |||
/* | |||
* Create the formatter | |||
* cause we cheat and use sprintf() | |||
*/ | |||
cp = fmt_str; | |||
*cp++ = '%'; | |||
if( altfm ){ | |||
*cp++ = '#'; | |||
} | |||
if( forceplus ){ | |||
*cp++ = '+'; | |||
} else if( spad ){ | |||
/* PLUS overrides */ | |||
*cp++ = ' '; | |||
} | |||
if( ljust ){ | |||
*cp++ = '-'; | |||
} | |||
if( zpad ){ | |||
*cp++ = '0'; | |||
} | |||
if( width > 0 ){ | |||
sprintf( cp, "%d", width ); | |||
/* skip ahead */ | |||
cp = strchr(cp,0); | |||
} | |||
*cp = 0; | |||
/* here we do the work */ | |||
/* actually - we make sprintf() do it for us */ | |||
switch(*fmt) { | |||
case 's': | |||
Jim_AppendObj(interp, resObjPtr, objv[0]); | |||
objv++; | |||
*cp++ = 's'; | |||
*cp = 0; | |||
/* BUG: we do not handled embeded NULLs */ | |||
snprintf( sprintf_buf, JIM_MAX_FMT, fmt_str, Jim_GetString( objv[0], NULL )); | |||
break; | |||
case 'c': | |||
*cp++ = 'c'; | |||
*cp = 0; | |||
if (Jim_GetWide(interp, objv[0], &wideValue) == JIM_ERR) { | |||
Jim_FreeNewObj(interp, resObjPtr); | |||
return NULL; | |||
} | |||
c = (char) wideValue; | |||
Jim_AppendString(interp, resObjPtr, &c, 1); | |||
snprintf( sprintf_buf, JIM_MAX_FMT, fmt_str, c ); | |||
break; | |||
case 'f': | |||
case 'F': | |||
case 'g': | |||
case 'G': | |||
case 'e': | |||
case 'E': | |||
*cp++ = *fmt; | |||
*cp = 0; | |||
if( Jim_GetDouble( interp, objv[0], &doubleValue ) == JIM_ERR ){ | |||
Jim_FreeNewObj( interp, resObjPtr ); | |||
return NULL; | |||
} | |||
snprintf( sprintf_buf, JIM_MAX_FMT, fmt_str, doubleValue ); | |||
break; | |||
case 'b': | |||
case 'd': | |||
case 'i': | |||
case 'u': | |||
case 'x': | |||
case 'X': | |||
/* jim widevaluse are 64bit */ | |||
if( sizeof(jim_wide) == sizeof(long long) ){ | |||
*cp++ = 'l'; | |||
*cp++ = 'l'; | |||
} else { | |||
*cp++ = 'l'; | |||
} | |||
*cp++ = *fmt; | |||
*cp = 0; | |||
if (Jim_GetWide(interp, objv[0], &wideValue) == JIM_ERR) { | |||
Jim_FreeNewObj(interp, resObjPtr); | |||
return NULL; | |||
} | |||
Jim_AppendObj(interp, resObjPtr, objv[0]); | |||
snprintf(sprintf_buf, JIM_MAX_FMT, fmt_str, wideValue ); | |||
break; | |||
case '%': | |||
Jim_AppendString(interp, resObjPtr, "%" , 1); | |||
sprintf_buf[0] = '%'; | |||
sprintf_buf[1] = 0; | |||
objv--; /* undo the objv++ below */ | |||
break; | |||
default: | |||
spec[0] = *fmt; spec[1] = '\0'; | |||
@@ -2200,6 +2378,16 @@ Jim_Obj *Jim_FormatString(Jim_Interp *interp, Jim_Obj *fmtObjPtr, | |||
"bad field specifier \"", spec, "\"", NULL); | |||
return NULL; | |||
} | |||
/* force terminate */ | |||
#if 0 | |||
printf("FMT was: %s\n", fmt_str ); | |||
printf("RES was: |%s|\n", sprintf_buf ); | |||
#endif | |||
sprintf_buf[ JIM_MAX_FMT - 1] = 0; | |||
Jim_AppendString( interp, resObjPtr, sprintf_buf, strlen(sprintf_buf) ); | |||
/* next obj */ | |||
objv++; | |||
fmt++; | |||
fmtLen--; | |||
} | |||
@@ -3910,7 +4098,7 @@ int Jim_Collect(Jim_Interp *interp) | |||
Jim_AddHashEntry(&marks, | |||
&objPtr->internalRep.refValue.id, NULL); | |||
#ifdef JIM_DEBUG_GC | |||
fprintf(interp->stdout_, | |||
Jim_fprintf(interp,interp->cookie_stdout, | |||
"MARK (reference): %d refcount: %d" JIM_NL, | |||
(int) objPtr->internalRep.refValue.id, | |||
objPtr->refCount); | |||
@@ -3949,7 +4137,7 @@ int Jim_Collect(Jim_Interp *interp) | |||
* was found. Mark it. */ | |||
Jim_AddHashEntry(&marks, &id, NULL); | |||
#ifdef JIM_DEBUG_GC | |||
fprintf(interp->stdout_,"MARK: %d" JIM_NL, (int)id); | |||
Jim_fprintf(interp,interp->cookie_stdout,"MARK: %d" JIM_NL, (int)id); | |||
#endif | |||
p += JIM_REFERENCE_SPACE; | |||
} | |||
@@ -3969,7 +4157,7 @@ int Jim_Collect(Jim_Interp *interp) | |||
* this reference. */ | |||
if (Jim_FindHashEntry(&marks, refId) == NULL) { | |||
#ifdef JIM_DEBUG_GC | |||
fprintf(interp->stdout_,"COLLECTING %d" JIM_NL, (int)*refId); | |||
Jim_fprintf(interp,interp->cookie_stdout,"COLLECTING %d" JIM_NL, (int)*refId); | |||
#endif | |||
collected++; | |||
/* Drop the reference, but call the | |||
@@ -4057,9 +4245,14 @@ Jim_Interp *Jim_CreateInterp(void) | |||
i->freeFramesList = NULL; | |||
i->prngState = NULL; | |||
i->evalRetcodeLevel = -1; | |||
i->stdin_ = stdin; | |||
i->stdout_ = stdout; | |||
i->stderr_ = stderr; | |||
i->cookie_stdin = stdin; | |||
i->cookie_stdout = stdout; | |||
i->cookie_stderr = stderr; | |||
i->cb_fwrite = ((size_t (*)( const void *, size_t, size_t, void *))(fwrite)); | |||
i->cb_fread = ((size_t (*)( void *, size_t, size_t, void *))(fread)); | |||
i->cb_vfprintf = ((int (*)( void *, const char *fmt, va_list ))(vfprintf)); | |||
i->cb_fflush = ((int (*)( void *))(fflush)); | |||
i->cb_fgets = ((char * (*)( char *, int, void *))(fgets)); | |||
/* Note that we can create objects only after the | |||
* interpreter liveList and freeList pointers are | |||
@@ -4128,23 +4321,23 @@ void Jim_FreeInterp(Jim_Interp *i) | |||
if (i->liveList != NULL) { | |||
Jim_Obj *objPtr = i->liveList; | |||
fprintf(i->stdout_,JIM_NL "-------------------------------------" JIM_NL); | |||
fprintf(i->stdout_,"Objects still in the free list:" JIM_NL); | |||
Jim_fprintf( i, i->cookie_stdout,JIM_NL "-------------------------------------" JIM_NL); | |||
Jim_fprintf( i, i->cookie_stdout,"Objects still in the free list:" JIM_NL); | |||
while(objPtr) { | |||
const char *type = objPtr->typePtr ? | |||
objPtr->typePtr->name : ""; | |||
fprintf(i->stdout_,"%p \"%-10s\": '%.20s' (refCount: %d)" JIM_NL, | |||
Jim_fprintf( i, i->cookie_stdout,"%p \"%-10s\": '%.20s' (refCount: %d)" JIM_NL, | |||
objPtr, type, | |||
objPtr->bytes ? objPtr->bytes | |||
: "(null)", objPtr->refCount); | |||
if (objPtr->typePtr == &sourceObjType) { | |||
fprintf(i->stdout_, "FILE %s LINE %d" JIM_NL, | |||
Jim_fprintf( i, i->cookie_stdout, "FILE %s LINE %d" JIM_NL, | |||
objPtr->internalRep.sourceValue.fileName, | |||
objPtr->internalRep.sourceValue.lineNumber); | |||
} | |||
objPtr = objPtr->nextObjPtr; | |||
} | |||
fprintf(stdout, "-------------------------------------" JIM_NL JIM_NL); | |||
Jim_fprintf( i, i->cookie_stdout, "-------------------------------------" JIM_NL JIM_NL); | |||
Jim_Panic(i,"Live list non empty freeing the interpreter! Leak?"); | |||
} | |||
/* Free all the freed objects. */ | |||
@@ -4330,22 +4523,22 @@ int Jim_GetExitCode(Jim_Interp *interp) { | |||
return interp->exitCode; | |||
} | |||
FILE *Jim_SetStdin(Jim_Interp *interp, FILE *fp) | |||
void *Jim_SetStdin(Jim_Interp *interp, void *fp) | |||
{ | |||
if (fp != NULL) interp->stdin_ = fp; | |||
return interp->stdin_; | |||
if (fp != NULL) interp->cookie_stdin = fp; | |||
return interp->cookie_stdin; | |||
} | |||
FILE *Jim_SetStdout(Jim_Interp *interp, FILE *fp) | |||
void *Jim_SetStdout(Jim_Interp *interp, void *fp) | |||
{ | |||
if (fp != NULL) interp->stdout_ = fp; | |||
return interp->stdout_; | |||
if (fp != NULL) interp->cookie_stdout = fp; | |||
return interp->cookie_stdout; | |||
} | |||
FILE *Jim_SetStderr(Jim_Interp *interp, FILE *fp) | |||
void *Jim_SetStderr(Jim_Interp *interp, void *fp) | |||
{ | |||
if (fp != NULL) interp->stderr_ = fp; | |||
return interp->stderr_; | |||
if (fp != NULL) interp->cookie_stderr = fp; | |||
return interp->cookie_stderr; | |||
} | |||
/* ----------------------------------------------------------------------------- | |||
@@ -8478,7 +8671,7 @@ int Jim_EvalObjBackground(Jim_Interp *interp, Jim_Obj *scriptObjPtr) | |||
Jim_IncrRefCount(objv[1]); | |||
if (Jim_EvalObjVector(interp, 2, objv) != JIM_OK) { | |||
/* Report the error to stderr. */ | |||
fprintf(interp->stderr_, "Background error:" JIM_NL); | |||
Jim_fprintf( interp, interp->cookie_stderr, "Background error:" JIM_NL); | |||
Jim_PrintErrorMessage(interp); | |||
} | |||
Jim_DecrRefCount(interp, objv[0]); | |||
@@ -8509,10 +8702,12 @@ int Jim_EvalFile(Jim_Interp *interp, const char *filename) | |||
maxlen = totread+buflen+1; | |||
prg = Jim_Realloc(prg, maxlen); | |||
} | |||
/* do not use Jim_fread() - this is really a file */ | |||
if ((nread = fread(prg+totread, 1, buflen, fp)) == 0) break; | |||
totread += nread; | |||
} | |||
prg[totread] = '\0'; | |||
/* do not use Jim_fclose() - this is really a file */ | |||
fclose(fp); | |||
scriptObjPtr = Jim_NewStringObjNoAlloc(interp, prg, totread); | |||
@@ -9011,8 +9206,8 @@ static int Jim_PutsCoreCommand(Jim_Interp *interp, int argc, | |||
} | |||
} | |||
str = Jim_GetString(argv[1], &len); | |||
fwrite(str, 1, len, interp->stdout_); | |||
if (!nonewline) fprintf(interp->stdout_, JIM_NL); | |||
Jim_fwrite(interp, str, 1, len, interp->cookie_stdout); | |||
if (!nonewline) Jim_fprintf( interp, interp->cookie_stdout, JIM_NL); | |||
return JIM_OK; | |||
} | |||
@@ -11744,9 +11939,9 @@ void Jim_PrintErrorMessage(Jim_Interp *interp) | |||
{ | |||
int len, i; | |||
fprintf(interp->stderr_, "Runtime error, file \"%s\", line %d:" JIM_NL, | |||
interp->errorFileName, interp->errorLine); | |||
fprintf(interp->stderr_, " %s" JIM_NL, | |||
Jim_fprintf(interp, interp->cookie_stderr, "Runtime error, file \"%s\", line %d:" JIM_NL, | |||
interp->errorFileName, interp->errorLine); | |||
Jim_fprintf(interp,interp->cookie_stderr, " %s" JIM_NL, | |||
Jim_GetString(interp->result, NULL)); | |||
Jim_ListLength(interp, interp->stackTrace, &len); | |||
for (i = 0; i < len; i+= 3) { | |||
@@ -11761,7 +11956,7 @@ void Jim_PrintErrorMessage(Jim_Interp *interp) | |||
Jim_ListIndex(interp, interp->stackTrace, i+2, &objPtr, | |||
JIM_NONE); | |||
line = Jim_GetString(objPtr, NULL); | |||
fprintf(interp->stderr_, | |||
Jim_fprintf( interp, interp->cookie_stderr, | |||
"In procedure '%s' called at file \"%s\", line %s" JIM_NL, | |||
proc, file, line); | |||
} | |||
@@ -11772,7 +11967,7 @@ int Jim_InteractivePrompt(Jim_Interp *interp) | |||
int retcode = JIM_OK; | |||
Jim_Obj *scriptObjPtr; | |||
fprintf(interp->stdout_, "Welcome to Jim version %d.%d, " | |||
Jim_fprintf(interp,interp->cookie_stdout, "Welcome to Jim version %d.%d, " | |||
"Copyright (c) 2005-8 Salvatore Sanfilippo" JIM_NL, | |||
JIM_VERSION / 100, JIM_VERSION % 100); | |||
Jim_SetVariableStrWithStr(interp, "jim_interactive", "1"); | |||
@@ -11786,12 +11981,12 @@ int Jim_InteractivePrompt(Jim_Interp *interp) | |||
if (retcode != 0) { | |||
if (retcode >= 2 && retcode <= 6) | |||
fprintf(interp->stdout_, "[%s] . ", retcodestr[retcode]); | |||
Jim_fprintf(interp,interp->cookie_stdout, "[%s] . ", retcodestr[retcode]); | |||
else | |||
fprintf(interp->stdout_, "[%d] . ", retcode); | |||
Jim_fprintf(interp,interp->cookie_stdout, "[%d] . ", retcode); | |||
} else | |||
fprintf(interp->stdout_, ". "); | |||
fflush(interp->stdout_); | |||
Jim_fprintf( interp, interp->cookie_stdout, ". "); | |||
Jim_fflush( interp, interp->cookie_stdout); | |||
scriptObjPtr = Jim_NewStringObj(interp, "", 0); | |||
Jim_IncrRefCount(scriptObjPtr); | |||
while(1) { | |||
@@ -11799,7 +11994,7 @@ int Jim_InteractivePrompt(Jim_Interp *interp) | |||
char state; | |||
int len; | |||
if (fgets(buf, 1024, interp->stdin_) == NULL) { | |||
if ( Jim_fgets(interp, buf, 1024, interp->cookie_stdin) == NULL) { | |||
Jim_DecrRefCount(interp, scriptObjPtr); | |||
goto out; | |||
} | |||
@@ -11807,8 +12002,8 @@ int Jim_InteractivePrompt(Jim_Interp *interp) | |||
str = Jim_GetString(scriptObjPtr, &len); | |||
if (Jim_ScriptIsComplete(str, len, &state)) | |||
break; | |||
fprintf(interp->stdout_, "%c> ", state); | |||
fflush(stdout); | |||
Jim_fprintf( interp, interp->cookie_stdout, "%c> ", state); | |||
Jim_fflush( interp, interp->cookie_stdout); | |||
} | |||
retcode = Jim_EvalObj(interp, scriptObjPtr); | |||
Jim_DecrRefCount(interp, scriptObjPtr); | |||
@@ -11819,11 +12014,91 @@ int Jim_InteractivePrompt(Jim_Interp *interp) | |||
exit(Jim_GetExitCode(interp)); | |||
} else { | |||
if (reslen) { | |||
fwrite(result, 1, reslen, interp->stdout_); | |||
fprintf(interp->stdout_, JIM_NL); | |||
Jim_fwrite( interp, result, 1, reslen, interp->cookie_stdout); | |||
Jim_fprintf( interp,interp->cookie_stdout, JIM_NL); | |||
} | |||
} | |||
} | |||
out: | |||
return 0; | |||
} | |||
/* ----------------------------------------------------------------------------- | |||
* Jim's idea of STDIO.. | |||
* ---------------------------------------------------------------------------*/ | |||
int | |||
Jim_fprintf( Jim_Interp *interp, void *cookie, const char *fmt, ... ) | |||
{ | |||
int r; | |||
va_list ap; | |||
va_start(ap,fmt); | |||
r = Jim_vfprintf( interp, cookie, fmt,ap ); | |||
va_end(ap); | |||
return r; | |||
} | |||
int | |||
Jim_vfprintf( Jim_Interp *interp, void *cookie, const char *fmt, va_list ap ) | |||
{ | |||
if( (interp == NULL) || (interp->cb_vfprintf == NULL) ){ | |||
errno = ENOTSUP; | |||
return -1; | |||
} | |||
return (*(interp->cb_vfprintf))( cookie, fmt, ap ); | |||
} | |||
size_t | |||
Jim_fwrite( Jim_Interp *interp, const void *ptr, size_t size, size_t n, void *cookie ) | |||
{ | |||
if( (interp == NULL) || (interp->cb_fwrite == NULL) ){ | |||
errno = ENOTSUP; | |||
return 0; | |||
} | |||
return (*(interp->cb_fwrite))( ptr, size, n, cookie); | |||
} | |||
size_t | |||
Jim_fread( Jim_Interp *interp, void *ptr, size_t size, size_t n, void *cookie ) | |||
{ | |||
if( (interp == NULL) || (interp->cb_fread == NULL) ){ | |||
errno = ENOTSUP; | |||
return 0; | |||
} | |||
return (*(interp->cb_fread))( ptr, size, n, cookie); | |||
} | |||
int | |||
Jim_fflush( Jim_Interp *interp, void *cookie ) | |||
{ | |||
if( (interp == NULL) || (interp->cb_fflush == NULL) ){ | |||
/* pretend all is well */ | |||
return 0; | |||
} | |||
return (*(interp->cb_fflush))( cookie ); | |||
} | |||
char * | |||
Jim_fgets( Jim_Interp *interp, char *s, int size, void *cookie ) | |||
{ | |||
if( (interp == NULL) || (interp->cb_fgets == NULL) ){ | |||
errno = ENOTSUP; | |||
return NULL; | |||
} | |||
return (*(interp->cb_fgets))( s, size, cookie ); | |||
} | |||
/* | |||
* Local Variables: ** | |||
* tab-width: 4 ** | |||
* c-basic-offset: 4 ** | |||
* End: ** | |||
*/ | |||
@@ -497,9 +497,14 @@ typedef struct Jim_Interp { | |||
struct Jim_HashTable assocData; /* per-interp storage for use by packages */ | |||
Jim_PrngState *prngState; /* per interpreter Random Number Gen. state. */ | |||
struct Jim_HashTable packages; /* Provided packages hash table */ | |||
FILE *stdin_; /* input file pointer, 'stdin' by default */ | |||
FILE *stdout_; /* output file pointer, 'stdout' by default */ | |||
FILE *stderr_; /* errors file pointer, 'stderr' by default */ | |||
void *cookie_stdin; /* input file pointer, 'stdin' by default */ | |||
void *cookie_stdout; /* output file pointer, 'stdout' by default */ | |||
void *cookie_stderr; /* errors file pointer, 'stderr' by default */ | |||
size_t (*cb_fwrite )( const void *ptr, size_t size, size_t n, void *cookie ); | |||
size_t (*cb_fread )( void *ptr, size_t size, size_t n, void *cookie ); | |||
int (*cb_vfprintf)( void *cookie, const char *fmt, va_list ap ); | |||
int (*cb_fflush )( void *cookie ); | |||
char *(*cb_fgets )( char *s, int size, void *cookie ); | |||
} Jim_Interp; | |||
/* Currently provided as macro that performs the increment. | |||
@@ -662,9 +667,9 @@ JIM_STATIC int JIM_API(Jim_GetFinalizer) (Jim_Interp *interp, Jim_Obj *objPtr, J | |||
JIM_STATIC Jim_Interp * JIM_API(Jim_CreateInterp) (void); | |||
JIM_STATIC void JIM_API(Jim_FreeInterp) (Jim_Interp *i); | |||
JIM_STATIC int JIM_API(Jim_GetExitCode) (Jim_Interp *interp); | |||
JIM_STATIC FILE * JIM_API(Jim_SetStdin) (Jim_Interp *interp, FILE *fp); | |||
JIM_STATIC FILE * JIM_API(Jim_SetStdout) (Jim_Interp *interp, FILE *fp); | |||
JIM_STATIC FILE * JIM_API(Jim_SetStderr) (Jim_Interp *interp, FILE *fp); | |||
JIM_STATIC void * JIM_API(Jim_SetStdin) (Jim_Interp *interp, void *fp); | |||
JIM_STATIC void * JIM_API(Jim_SetStdout) (Jim_Interp *interp, void *fp); | |||
JIM_STATIC void * JIM_API(Jim_SetStderr) (Jim_Interp *interp, void *fp); | |||
/* commands */ | |||
JIM_STATIC void JIM_API(Jim_RegisterCoreCommands) (Jim_Interp *interp); | |||
@@ -815,6 +820,15 @@ JIM_STATIC int JIM_API(Jim_InteractivePrompt) (Jim_Interp *interp); | |||
/* Misc */ | |||
JIM_STATIC void JIM_API(Jim_Panic) (Jim_Interp *interp, const char *fmt, ...); | |||
/* Jim's STDIO */ | |||
JIM_STATIC int JIM_API( Jim_fprintf )( Jim_Interp *interp, void *cookie, const char *fmt, ... ); | |||
JIM_STATIC int JIM_API( Jim_vfprintf )( Jim_Interp *interp, void *cookie, const char *fmt, va_list ap ); | |||
JIM_STATIC size_t JIM_API( Jim_fwrite )( Jim_Interp *interp, const void *ptr, size_t size, size_t nmeb, void *cookie ); | |||
JIM_STATIC size_t JIM_API( Jim_fread )( Jim_Interp *interp, void *ptr, size_t size, size_t nmeb, void *cookie ); | |||
JIM_STATIC int JIM_API( Jim_fflush )( Jim_Interp *interp, void *cookie ); | |||
JIM_STATIC char * JIM_API( Jim_fgets )( Jim_Interp *interp, char *s, int size, void *cookie ); | |||
#undef JIM_STATIC | |||
#undef JIM_API | |||
@@ -942,6 +956,13 @@ static void Jim_InitExtension(Jim_Interp *interp) | |||
JIM_GET_API(StackPop); | |||
JIM_GET_API(StackPeek); | |||
JIM_GET_API(FreeStackElements); | |||
JIM_GET_API(fprintf ); | |||
JIM_GET_API(vfprintf ); | |||
JIM_GET_API(fwrite ); | |||
JIM_GET_API(fread ); | |||
JIM_GET_API(fflush ); | |||
JIM_GET_API(fgets ); | |||
} | |||
#endif /* defined JIM_EXTENSION || defined JIM_EMBEDDED */ | |||
@@ -962,3 +983,11 @@ static void Jim_InitEmbedded(void) { | |||
#endif | |||
#endif /* __JIM__H */ | |||
/* | |||
* Local Variables: ** | |||
* tab-width: 4 ** | |||
* c-basic-offset: 4 ** | |||
* End: ** | |||
*/ | |||
@@ -165,6 +165,191 @@ void unlockBigLock() | |||
Jim_Interp *interp; | |||
command_context_t *active_cmd_ctx; | |||
static int | |||
new_int_array_element( Jim_Interp * interp, | |||
const char *varname, | |||
int idx, | |||
u32 val ) | |||
{ | |||
char *namebuf; | |||
Jim_Obj *nameObjPtr, *valObjPtr; | |||
int result; | |||
namebuf = alloca( strlen(varname) + 30 ); | |||
sprintf( namebuf, "%s(%d)", varname, idx ); | |||
nameObjPtr = Jim_NewStringObj(interp, namebuf, -1); | |||
valObjPtr = Jim_NewIntObj(interp, val ); | |||
Jim_IncrRefCount(nameObjPtr); | |||
Jim_IncrRefCount(valObjPtr); | |||
result = Jim_SetVariable(interp, nameObjPtr, valObjPtr); | |||
Jim_DecrRefCount(interp, nameObjPtr); | |||
Jim_DecrRefCount(interp, valObjPtr); | |||
// printf( "%s = 0%08x\n", namebuf, val ); | |||
return result; | |||
} | |||
static int | |||
Jim_Command_mem2array( Jim_Interp *interp, int argc, Jim_Obj *const *argv) | |||
{ | |||
target_t *target; | |||
long l; | |||
u32 width; | |||
u32 endian; | |||
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 receive the data | |||
* argv[2] = desired width | |||
* argv[3] = memory address | |||
* argv[4] = length in bytes to read | |||
*/ | |||
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), | |||
"mem2array: zero width read?", NULL ); | |||
return JIM_ERR; | |||
} | |||
if( (addr + (len * width)) < addr ){ | |||
Jim_SetResult(interp, | |||
Jim_NewEmptyStringObj(interp)); | |||
Jim_AppendStrings( interp, Jim_GetResult(interp), | |||
"mem2array: 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), | |||
"mem2array: 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, | |||
"mem2array 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); | |||
} | |||
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 ); | |||
Jim_SetResult(interp, | |||
Jim_NewEmptyStringObj(interp)); | |||
Jim_AppendStrings( interp, Jim_GetResult(interp), | |||
"mem2array: cannot read memory", NULL ); | |||
e = JIM_ERR; | |||
len = 0; | |||
} else { | |||
v = 0; /* shut up gcc */ | |||
for( i = 0 ; i < count ; i++, n++ ){ | |||
switch(width){ | |||
case 4: | |||
v = target_buffer_get_u32( target, &buffer[i*width] ); | |||
break; | |||
case 2: | |||
v = target_buffer_get_u16( target, &buffer[i*width] ); | |||
break; | |||
case 1: | |||
v = buffer[i] & 0x0ff; | |||
break; | |||
} | |||
new_int_array_element( interp, varname, n, v ); | |||
} | |||
len -= count; | |||
} | |||
} | |||
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) | |||
{ | |||
@@ -323,6 +508,97 @@ Jim_Command_echo(Jim_Interp *interp, | |||
return JIM_OK; | |||
} | |||
static size_t | |||
openocd_jim_fwrite( const void *_ptr, size_t size, size_t n, void *cookie ) | |||
{ | |||
size_t nbytes; | |||
const char *ptr; | |||
/* make it a char easier to read code */ | |||
ptr = _ptr; | |||
nbytes = size * n; | |||
if( nbytes == 0 ){ | |||
return 0; | |||
} | |||
if( !active_cmd_ctx ){ | |||
/* FIXME: Where should this go? */ | |||
return n; | |||
} | |||
/* do we have to chunk it? */ | |||
if( ptr[ nbytes ] == 0 ){ | |||
/* no it is a C style string */ | |||
command_output_text( active_cmd_ctx, ptr ); | |||
return; | |||
} | |||
/* GRR we must chunk - not null terminated */ | |||
while( nbytes ){ | |||
char chunk[128+1]; | |||
int x; | |||
x = nbytes; | |||
if( x > 128 ){ | |||
x = 128; | |||
} | |||
/* copy it */ | |||
memcpy( chunk, ptr, x ); | |||
/* terminate it */ | |||
chunk[n] = 0; | |||
/* output it */ | |||
command_output_text( active_cmd_ctx, chunk ); | |||
ptr += x; | |||
nbytes -= x; | |||
} | |||
return n; | |||
} | |||
static size_t | |||
openocd_jim_fread(void *ptr, size_t size, size_t n, void *cookie ) | |||
{ | |||
/* TCL wants to read... tell him no */ | |||
return 0; | |||
} | |||
static int | |||
openocd_jim_vfprintf( void *cookie, const char *fmt, va_list ap ) | |||
{ | |||
char *cp; | |||
int n; | |||
n = -1; | |||
if( active_cmd_ctx ){ | |||
cp = alloc_vprintf( fmt, ap ); | |||
if( cp ){ | |||
command_output_text( active_cmd_ctx, cp ); | |||
n = strlen(cp); | |||
free(cp); | |||
} | |||
} | |||
return n; | |||
} | |||
static int | |||
openocd_jim_fflush( void *cookie ) | |||
{ | |||
/* nothing to flush */ | |||
return 0; | |||
} | |||
static char * | |||
openocd_jim_fgets( char *s, int size, void *cookie ) | |||
{ | |||
/* not supported */ | |||
errno = ENOTSUP; | |||
return NULL; | |||
} | |||
void initJim(void) | |||
{ | |||
Jim_InitEmbedded(); | |||
@@ -335,6 +611,17 @@ void initJim(void) | |||
Jim_CreateCommand(interp, "openocd_throw", Jim_Command_openocd_throw, NULL, NULL); | |||
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 ); | |||
/* Set Jim's STDIO */ | |||
interp->cookie_stdin = NULL; | |||
interp->cookie_stdout = NULL; | |||
interp->cookie_stderr = NULL; | |||
interp->cb_fwrite = openocd_jim_fwrite; | |||
interp->cb_fread = openocd_jim_fread ; | |||
interp->cb_vfprintf = openocd_jim_vfprintf; | |||
interp->cb_fflush = openocd_jim_fflush; | |||
interp->cb_fgets = openocd_jim_fgets; | |||
} | |||
int main(int argc, char *argv[]) | |||
@@ -422,3 +709,11 @@ int main(int argc, char *argv[]) | |||
return EXIT_SUCCESS; | |||
} | |||
/* | |||
* Local Variables: ** | |||
* tab-width: 4 ** | |||
* c-basic-offset: 4 ** | |||
* End: ** | |||
*/ | |||
@@ -568,7 +568,7 @@ int gdb_output_con(connection_t *connection, const char* line) | |||
return ERROR_OK; | |||
} | |||
int gdb_output(struct command_context_s *context, char* line) | |||
int gdb_output(struct command_context_s *context, const char* line) | |||
{ | |||
/* this will be dumped to the log and also sent as an O packet if possible */ | |||
LOG_USER_N("%s", line); | |||
@@ -577,24 +577,10 @@ int gdb_output(struct command_context_s *context, char* line) | |||
int gdb_program_handler(struct target_s *target, enum target_event event, void *priv) | |||
{ | |||
FILE *script; | |||
struct command_context_s *cmd_ctx = priv; | |||
if (target->gdb_program_script) | |||
{ | |||
script = open_file_from_path(target->gdb_program_script, "r"); | |||
if (!script) | |||
{ | |||
LOG_ERROR("couldn't open script file %s", target->gdb_program_script); | |||
return ERROR_OK; | |||
} | |||
LOG_INFO("executing gdb_program script '%s'", target->gdb_program_script); | |||
command_run_file(cmd_ctx, script, COMMAND_EXEC); | |||
fclose(script); | |||
jtag_execute_queue(); | |||
} | |||
target_invoke_script(cmd_ctx, target, "gdb_program"); | |||
jtag_execute_queue(); | |||
return ERROR_OK; | |||
} | |||
@@ -92,7 +92,7 @@ int telnet_outputline(connection_t *connection, const char *line) | |||
telnet_write(connection, line, len); | |||
if (line_end) | |||
{ | |||
telnet_write(connection, "\r\n\0", 3); | |||
telnet_write(connection, "\r\n", 2); | |||
line += len+1; | |||
} | |||
else | |||
@@ -104,7 +104,7 @@ int telnet_outputline(connection_t *connection, const char *line) | |||
return ERROR_OK; | |||
} | |||
int telnet_output(struct command_context_s *cmd_ctx, char* line) | |||
int telnet_output(struct command_context_s *cmd_ctx, const char* line) | |||
{ | |||
connection_t *connection = cmd_ctx->output_handler_priv; | |||
@@ -181,7 +181,7 @@ int telnet_new_connection(connection_t *connection) | |||
if (telnet_service->banner) | |||
{ | |||
telnet_write(connection, telnet_service->banner, strlen(telnet_service->banner)); | |||
telnet_write(connection, "\r\n\0", 3); | |||
telnet_write(connection, "\r\n", 2); | |||
} | |||
telnet_prompt(connection); | |||
@@ -658,3 +658,11 @@ int handle_exit_command(struct command_context_s *cmd_ctx, char *cmd, char **arg | |||
{ | |||
return ERROR_COMMAND_CLOSE_CONNECTION; | |||
} | |||
/* | |||
* Local Variables: ** | |||
* tab-width: 4 ** | |||
* c-basic-offset: 4 ** | |||
* End: ** | |||
*/ | |||
@@ -215,23 +215,6 @@ target_t* get_current_target(command_context_t *cmd_ctx) | |||
return target; | |||
} | |||
static void execute_script(struct command_context_s *cmd_ctx, char *reset_script) | |||
{ | |||
if (reset_script==NULL) | |||
return; | |||
FILE *script; | |||
script = open_file_from_path(reset_script, "r"); | |||
if (!script) | |||
{ | |||
LOG_ERROR("couldn't open script file %s", reset_script); | |||
return; | |||
} | |||
LOG_INFO("executing script '%s'", reset_script); | |||
command_run_file(cmd_ctx, script, COMMAND_EXEC); | |||
fclose(script); | |||
} | |||
/* Process target initialization, when target entered debug out of reset | |||
* the handler is unregistered at the end of this function, so it's only called once | |||
*/ | |||
@@ -243,7 +226,7 @@ int target_init_handler(struct target_s *target, enum target_event event, void * | |||
{ | |||
target_unregister_event_callback(target_init_handler, priv); | |||
execute_script(cmd_ctx, target->reset_script); | |||
target_invoke_script(cmd_ctx, target, "reset"); | |||
jtag_execute_queue(); | |||
} | |||
@@ -305,7 +288,7 @@ int target_process_reset(struct command_context_s *cmd_ctx) | |||
target = targets; | |||
while (target) | |||
{ | |||
execute_script(cmd_ctx, target->pre_reset_script); | |||
target_invoke_script(cmd_ctx, target, "pre_reset"); | |||
target = target->next; | |||
} | |||
@@ -950,7 +933,8 @@ int target_register_commands(struct command_context_s *cmd_ctx) | |||
{ | |||
register_command(cmd_ctx, NULL, "target", handle_target_command, COMMAND_CONFIG, "target <cpu> [reset_init default - DEPRECATED] <chainpos> <endianness> <variant> [cpu type specifc args]"); | |||
register_command(cmd_ctx, NULL, "targets", handle_targets_command, COMMAND_EXEC, NULL); | |||
register_command(cmd_ctx, NULL, "target_script", handle_target_script_command, COMMAND_CONFIG, NULL); | |||
register_command(cmd_ctx, NULL, "target_script", handle_target_script_command, COMMAND_CONFIG, | |||
"target_script <target#> <event=reset/pre_reset/post_halt/pre_resume/gdb_program_config> <script_file>"); | |||
register_command(cmd_ctx, NULL, "run_and_halt_time", handle_run_and_halt_time_command, COMMAND_CONFIG, "<target> <run time ms>"); | |||
register_command(cmd_ctx, NULL, "working_area", handle_working_area_command, COMMAND_ANY, "working_area <target#> <address> <size> <'backup'|'nobackup'> [virtual address]"); | |||
register_command(cmd_ctx, NULL, "virt2phys", handle_virt2phys_command, COMMAND_ANY, "virt2phys <virtual address>"); | |||
@@ -1437,12 +1421,6 @@ int handle_target_command(struct command_context_s *cmd_ctx, char *cmd, char **a | |||
} | |||
(*last_target_p)->run_and_halt_time = 1000; /* default 1s */ | |||
(*last_target_p)->reset_script = NULL; | |||
(*last_target_p)->pre_reset_script = NULL; | |||
(*last_target_p)->post_halt_script = NULL; | |||
(*last_target_p)->pre_resume_script = NULL; | |||
(*last_target_p)->gdb_program_script = NULL; | |||
(*last_target_p)->working_area = 0x0; | |||
(*last_target_p)->working_area_size = 0x0; | |||
(*last_target_p)->working_areas = NULL; | |||
@@ -1487,7 +1465,14 @@ int handle_target_command(struct command_context_s *cmd_ctx, char *cmd, char **a | |||
return ERROR_OK; | |||
} | |||
/* usage: target_script <target#> <event> <script_file> */ | |||
int target_invoke_script(struct command_context_s *cmd_ctx, target_t *target, char *name) | |||
{ | |||
return command_run_linef(cmd_ctx, " if {[catch {info body target_%s_%d} t]==0} {target_%s_%d}", | |||
name, get_num_by_target(target), | |||
name, get_num_by_target(target)); | |||
} | |||
int handle_target_script_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc) | |||
{ | |||
target_t *target = NULL; | |||
@@ -1505,41 +1490,14 @@ int handle_target_script_command(struct command_context_s *cmd_ctx, char *cmd, c | |||
return ERROR_COMMAND_SYNTAX_ERROR; | |||
} | |||
if ((strcmp(args[1], "reset") == 0)||(strcmp(args[1], "post_reset") == 0)) | |||
{ | |||
if (target->reset_script) | |||
free(target->reset_script); | |||
target->reset_script = strdup(args[2]); | |||
} | |||
else if (strcmp(args[1], "pre_reset") == 0) | |||
{ | |||
if (target->pre_reset_script) | |||
free(target->pre_reset_script); | |||
target->pre_reset_script = strdup(args[2]); | |||
} | |||
else if (strcmp(args[1], "post_halt") == 0) | |||
{ | |||
if (target->post_halt_script) | |||
free(target->post_halt_script); | |||
target->post_halt_script = strdup(args[2]); | |||
} | |||
else if (strcmp(args[1], "pre_resume") == 0) | |||
{ | |||
if (target->pre_resume_script) | |||
free(target->pre_resume_script); | |||
target->pre_resume_script = strdup(args[2]); | |||
} | |||
else if (strcmp(args[1], "gdb_program_config") == 0) | |||
{ | |||
if (target->gdb_program_script) | |||
free(target->gdb_program_script); | |||
target->gdb_program_script = strdup(args[2]); | |||
} | |||
else | |||
{ | |||
LOG_ERROR("unknown event type: '%s", args[1]); | |||
return ERROR_COMMAND_SYNTAX_ERROR; | |||
} | |||
/* Define a tcl procedure which we'll invoke upon some event */ | |||
command_run_linef(cmd_ctx, | |||
"proc target_%s_%d {} {" | |||
"openocd {script %s}" | |||
"}", | |||
args[1], | |||
get_num_by_target(target), | |||
args[2]); | |||
return ERROR_OK; | |||
} | |||
@@ -2021,14 +1979,11 @@ int handle_md_command(struct command_context_s *cmd_ctx, char *cmd, char **args, | |||
output_len = 0; | |||
} | |||
} | |||
} else | |||
{ | |||
LOG_ERROR("Failure examining memory"); | |||
} | |||
free(buffer); | |||
return ERROR_OK; | |||
return retval; | |||
} | |||
int handle_mw_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc) | |||
@@ -200,11 +200,6 @@ typedef struct target_s | |||
target_type_t *type; /* target type definition (name, access functions) */ | |||
enum target_reset_mode reset_mode; /* what to do after a reset */ | |||
int run_and_halt_time; /* how long the target should run after a run_and_halt reset */ | |||
char *pre_reset_script; /* script file to initialize the target before a reset */ | |||
char *reset_script; /* script file to initialize the target after a reset */ | |||
char *post_halt_script; /* script file to execute after the target halted */ | |||
char *pre_resume_script; /* script file to execute before the target resumed */ | |||
char *gdb_program_script; /* script file to execute before programming vis gdb */ | |||
u32 working_area; /* working area (initialized RAM). Evaluated | |||
upon first allocation from virtual/physical address. | |||
*/ | |||
@@ -325,6 +320,9 @@ int target_write_u8(struct target_s *target, u32 address, u8 value); | |||
/* Issues USER() statements with target state information */ | |||
int target_arch_state(struct target_s *target); | |||
int target_invoke_script(struct command_context_s *cmd_ctx, target_t *target, char *name); | |||
#define ERROR_TARGET_INVALID (-300) | |||
#define ERROR_TARGET_INIT_FAILED (-301) | |||
#define ERROR_TARGET_TIMEOUT (-302) | |||
@@ -0,0 +1,430 @@ | |||
**************************************** | |||
**************************************** | |||
This is a short introduction to 'un-scare' you about the language | |||
known as TCL. It is structured as a guided tour through the files | |||
written by me [Duane Ellis] - in early July 2008 for OpenOCD. | |||
Which uses the "JIM" embedded Tcl clone-ish language. | |||
Thing described here are *totally* TCL generic... not Jim specific. | |||
The goal of this document is to encourage you to add your own set of | |||
chips to the TCL package - and most importantly you should know where | |||
you should put them - so they end up in an orginized way. | |||
--Duane Ellis. | |||
duane@duaneellis.com | |||
**************************************** | |||
**************************************** | |||
Adding "chip" support - Duane Ellis July 5 - 2008. | |||
The concept is this: | |||
In your "openocd.cfg" file add something like this: | |||
source [find tcl/chip/VENDOR/FAMILY/NAME.tcl] | |||
For example... | |||
source [find tcl/chip/atmel/at91/at91sam7x256.tcl] | |||
You'll notice that it makes use of: | |||
tcl/cpu/arm/<NAME>.tcl. | |||
Yes, that is where you should put "core" specific things. | |||
Be carefull and learn the difference: | |||
THE "CORE" - is not the entire chip! | |||
Definition: | |||
That "file" listed above is called a "CHIP FILE". | |||
It may be standalone, or may need to "source" other "helper" files. | |||
The reference [7/5/2008] is the at91sam7x256.tcl file. | |||
**************************************** | |||
**************************************** | |||
=== TCL TOUR === | |||
Open: at91sam7x256.tcl | |||
=== TCL TOUR === | |||
A walk through --- For those who are new to TCL. | |||
Examine the file: at91sam7x256.tcl | |||
It starts with: | |||
source [find path/filename.tcl] | |||
In TCL - this is very important. | |||
Rule #1 Everything is a string. | |||
Rule #2 If you think other wise See #1. | |||
Reminds you of: | |||
Rule #1: The wife is correct. | |||
Rule #2: If you think otherwise, See #1 | |||
Any text contained inside of [square-brackets] | |||
is just like `back-ticks` in BASH. | |||
Hence, the [find FILENAME] executes the command find with a single | |||
parameter the filename. | |||
======================================== | |||
Next you see a series of: | |||
set NAME VALUE | |||
It is mostly "obious" what is going on. | |||
Execption: The arrays. | |||
You would *THINK* Tcl supports arrays. | |||
In fact, multi-dim arrays. That is false. | |||
For the index for"FLASH(0,CHIPSELECT)" is actually the string | |||
"0,CHIPSELECT". This is problematic. In the normal world, you think | |||
of array indexes as integers. | |||
For example these are different: | |||
set foo(0x0c) 123 | |||
set foo(12) 444 | |||
Why? Because 0x0c {lowercase} is a string. | |||
Don't forget UPPER CASE. | |||
You must be careful - always... always... use simple decimal | |||
numbers. When in doubt use 'expr' the evaluator. These are all the | |||
same. | |||
set x 0x0c | |||
set foo([expr $x]) "twelve" | |||
set x 12 | |||
set foo([expr $x]) "twelve" | |||
set x "2 * 6" | |||
set foo([expr $x]) "twelve" | |||
************************************************** | |||
*************************************************** | |||
=== TCL TOUR === | |||
Open the file: "bitsbytes.tcl" | |||
There is some tricky things going on. | |||
=============== | |||
First, there is a "for" loop - at level 0 | |||
{level 0 means: out side of a proc/function} | |||
This means it is evaluated when the file is parsed. | |||
== SIDEBAR: About The FOR command == | |||
In TCL, "FOR" is a funny thing, it is not what you think it is. | |||
Syntatically - FOR is a just a command, it is not language | |||
construct like for(;;) in C... | |||
The "for" command takes 4 parameters. | |||
(1) The "initial command" to execute. | |||
(2) the test "expression" | |||
(3) the "next command" | |||
(4) the "body command" of the FOR loop. | |||
Notice I used the words "command" and "expresion" above. | |||
The FOR command: | |||
1) executes the "initial command" | |||
2) evaluates the expression if 0 it stops. | |||
3) executes the "body command" | |||
4) executes the "next command" | |||
5) Goto Step 2. | |||
As show, each of these items are in {curly-braces}. This means they | |||
are passed as they are - KEY-POINT: un evaluated to the FOR | |||
command. Think of it like escaping the backticks in Bash so that the | |||
"under-lying" command can evaluate the contents. In this case, the FOR | |||
COMMAND. | |||
== END: SIDEBAR: About The FOR command == | |||
You'll see two lines: | |||
LINE1: | |||
set vn [format "BIT%d" $x] | |||
Format is like "sprintf". Because of the [brackets], it becomes what | |||
you think. But here's how: | |||
First - the line is parsed - for {braces}. In this case, there are | |||
none. The, the parser looks for [brackets] and finds them. The, | |||
parser then evaluates the contents of the [brackets], and replaces | |||
them. It is alot this bash statement. | |||
EXPORT vn=`date` | |||
LINE 2 & 3 | |||
set $vn [expr (1024 * $x)] | |||
global $vn | |||
In line 1, we dynamically created a variable name. Here, we are | |||
assigning it a value. Lastly Line 3 we force the variable to be | |||
global, not "local" the the "for command body" | |||
=============== | |||
The PROCS | |||
proc create_mask { MSB LSB } { | |||
... body .... | |||
} | |||
Like "for" - PROC is really just a command that takes 3 parameters. | |||
The (1) NAME of the function, a (2) LIST of parameters, and a (3) BODY | |||
Again, this is at "level 0" so it is a global function. (Yes, TCL | |||
supports local functions, you put them inside of a function} | |||
You'll see in some cases, I nest [brackets] alot and in others I'm | |||
lazy or wanted it to be more clear... it is a matter of choice. | |||
=============== | |||
************************************************** | |||
*************************************************** | |||
=== TCL TOUR === | |||
Open the file: "memory.tcl" | |||
=============== | |||
Here is where I setup some 'memory definitions' that various targets can use. | |||
For example - there is an "unknown" memory region. | |||
All memory regions must have 2 things: | |||
(1) N_<name> | |||
(2) NAME( array ) | |||
And the array must have some specific names: | |||
( <idx>, THING ) | |||
Where: THING is one of: | |||
CHIPSELECT | |||
BASE | |||
LEN | |||
HUMAN | |||
TYPE | |||
RWX - the access ablity. | |||
WIDTH - the accessable width. | |||
ie: Some regions of memory are not 'word' | |||
accessable. | |||
The function "address_info" - given an address should | |||
tell you about the address. | |||
[as of this writing: 7/5/2008 I have done | |||
only a little bit with this -Duane] | |||
=== | |||
MAJOR FUNCTION: | |||
== | |||
proc memread32 { ADDR } | |||
proc memread16 { ADDR } | |||
proc memread8 { ADDR } | |||
All read memory - and return the contents. | |||
[ fixme: 7/5/2008 - I need to create "memwrite" functions] | |||
************************************************** | |||
*************************************************** | |||
=== TCL TOUR === | |||
Open the file: "mmr_helpers.tcl" | |||
=============== | |||
This file is used to display and work with "memory mapped registers" | |||
For example - 'show_mmr32_reg' is given the NAME of the register to | |||
display. The assumption is - the NAME is a global variable holding the | |||
address of that MMR. | |||
The code does some tricks. The [set [set NAME]] is the TCL way | |||
of doing double variable interpolation - like makefiles... | |||
In a makefile or shell script you may have seen this: | |||
FOO_linux = "Penguins rule" | |||
FOO_winXP = "Broken Glass" | |||
FOO_mac = "I like cat names" | |||
# Pick one | |||
BUILD = linux | |||
#BUILD = winXP | |||
#BUILD = mac | |||
FOO = ${FOO_${BUILD}} | |||
The "double [set] square bracket" thing is the TCL way, nothing more. | |||
---- | |||
The IF statement - and "CATCH" . | |||
Notice this IF COMMAND - (not statement) is like this: | |||
[7/5/2008 it is this way] | |||
if ![catch { command } msg ] { | |||
...something... | |||
} else { | |||
error [format string...] | |||
} | |||
The "IF" command expects either 2 params, or 4 params. | |||
=== Sidebar: About "commands" === | |||
Take a look at the internals of "jim.c" | |||
Look for the function: Jim_IfCoreCommand() | |||
And all those other "CoreCommands" | |||
You'll notice - they all have "argc" and "argv" | |||
Yea, the entire thing is done that way. | |||
IF is a command. SO is "FOR" and "WHILE" and "DO" and the | |||
others. That is why I keep using the prhase it is a "command" | |||
=== END: Sidebar: About "commands" === | |||
Paramter 1 to the IF command is expected to be an expression. | |||
As such, I do not need to wrap it in {braces}. | |||
In this case, the "expression" is the resul of the "CATCH" command. | |||
CATCH - is an error catcher. | |||
You give CATCH 1 or 2 parameters. | |||
The first 1st parameter is the "code to execute" | |||
The 2nd (optional) is where to put the error message. | |||
CATCH returns 0 on success, 1 for failure. | |||
The "![catch command]" is self explaintory. | |||
The 3rd parameter to IF must be exacty "else" or "elseif" [I lied | |||
above, the IF command can take many parameters they just have to | |||
be joined by exactly the words "else" or "elseif". | |||
The 4th parameter contains: | |||
"error [format STRING....]" | |||
This lets me modify the previous lower level error by tacking more | |||
text onto the end of it. In this case, i want to add the MMR register | |||
name to make my error message look better. | |||
--------- | |||
Back to something inside show_mmr32_reg{}. | |||
You'll see something 'set fn show_${NAME}_helper' Here I am | |||
constructing a 'function name' Then - I look it up to see if it | |||
exists. {the function: "proc_exists" does this} | |||
And - if it does - I call the function. | |||
In "C" it is alot like using: 'sprintf()' to construct a function name | |||
string, then using "dlopen()" and "dlsym()" to look it up - and get a | |||
function pointer - and calling the function pointer. | |||
In this case - I execute a dynamic command. You can do some cool | |||
tricks with interpretors. | |||
---------- | |||
Function: show_mmr32_bits() | |||
In this case, we use the special TCL command "upvar" which tcl's way | |||
of passing things by reference. In this case, we want to reach up into | |||
the callers lexical scope and find the array named "NAMES" | |||
The rest of the function is pretty straight forward. | |||
First - we figure out the longest name. | |||
Then print 4 rows of 8bits - with names. | |||
************************************************** | |||
*************************************************** | |||
=== TCL TOUR === | |||
Open the file: "chips/atmel/at91/usarts.tcl" | |||
=============== | |||
First - about the AT91SAM series - all of the usarts | |||
are basically identical... | |||
Second - there can be many of them. | |||
In this case - I do some more TCL tricks to dynamically | |||
create functions out of thin air. | |||
Some assumptions: | |||
The "CHIP" file has defined some variables in a proper form. | |||
ie: AT91C_BASE_US0 - for usart0, | |||
AT91C_BASE_US1 - for usart1 | |||
... And so on ... | |||
Near the end of the file - look for a large "foreach" loop that | |||
looks like this: | |||
foreach WHO { US0 US1 US2 US3 US4 .... } { | |||
} | |||
In this case, I'm trying to figure out what USARTs exist. | |||
Step 1 - is to determine if the NAME has been defined. | |||
ie: Does AT91C_BASE_USx - where X is some number exist? | |||
The "info exists VARNAME" tells you if the variable exists. Then - | |||
inside the IF statement... There is another loop. This loop is the | |||
name of various "sub-registers" within the USART. | |||
Some more trick are played with the [set VAR] backtick evaluation stuff. | |||
And we create two variables | |||
We calculate and create the global variable name for every subregister in the USART. | |||
And - declare that variable as GLOBAL so the world can find it. | |||
Then - we dynamically create a function - based on the register name. | |||
Look carefully at how that is done. You'll notice the FUNCTION BODY is | |||
a string - not something in {braces}. Why? This is because we need TCL | |||
to evaluate the contents of that string "*NOW*" - when $vn exists not | |||
later, when the function "show_FOO" is invoked. | |||
Lastly - we build a "str" of commands - and create a single function - | |||
with the generated list of commands for the entire USART. | |||
With that little bit of code - I now have a bunch of functions like: | |||
show_US0, show_US1, show_US2, .... etc ... | |||
And show_US0_MR, show_US0_IMR ... etc... | |||
And - I have this for every USART... without having to create tons of | |||
boiler plate yucky code. | |||
**************************************** | |||
**************************************** | |||
END of the Tcl Intro and Walk Through | |||
**************************************** | |||
**************************************** | |||
FUTURE PLANS | |||
Some "GPIO" functions... |
@@ -0,0 +1,63 @@ | |||
#---------------------------------------- | |||
# Purpose - Create some $BIT variables | |||
# Create $K and $M variables | |||
# and some bit field extraction variables. | |||
# Creat helper variables ... | |||
# BIT0.. BIT31 | |||
for { set x 0 } { $x < 32 } { set x [expr $x + 1]} { | |||
set vn [format "BIT%d" $x] | |||
set $vn [expr (1 << $x)] | |||
global $vn | |||
} | |||
# 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 | |||
} | |||
# 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 | |||
} | |||
proc create_mask { MSB LSB } { | |||
return [expr (((1 << ($MSB - $LSB + 1))-1) << $LSB)] | |||
} | |||
# Cut Bits $MSB to $LSB out of this value. | |||
# Example: % format "0x%08x" [extract_bitfield 0x12345678 27 16] | |||
# Result: 0x02340000 | |||
proc extract_bitfield { VALUE MSB LSB } { | |||
return [expr [create_mask $MSB $LSB] & $VALUE] | |||
} | |||
# Cut bits $MSB to $LSB out of this value | |||
# and shift (normalize) them down to bit 0. | |||
# | |||
# Example: % format "0x%08x" [normalize_bitfield 0x12345678 27 16] | |||
# Result: 0x00000234 | |||
# | |||
proc normalize_bitfield { VALUE MSB LSB } { | |||
return [expr [extract_bitfield $VALUE $MSB $LSB ] >> $LSB] | |||
} | |||
proc show_normalize_bitfield { VALUE MSB LSB } { | |||
set m [create_mask $MSB $LSB] | |||
set mr [expr $VALUE & $m] | |||
set sr [expr $mr >> $LSB] | |||
puts [format "((0x%08x & 0x%08x) -> 0x%08x) >> %2d => (0x%x) %5d " $VALUE $m $mr $LSB $sr $sr] | |||
return $sr | |||
} | |||
@@ -0,0 +1,101 @@ | |||
set AIC_SMR [expr $AT91C_BASE_AIC + 0x00000000 ] | |||
global AIC_SMR | |||
set AIC_SVR [expr $AT91C_BASE_AIC + 0x00000080 ] | |||
global AIC_SVR | |||
set AIC_IVR [expr $AT91C_BASE_AIC + 0x00000100 ] | |||
global AIC_IVR | |||
set AIC_FVR [expr $AT91C_BASE_AIC + 0x00000104 ] | |||
global AIC_FVR | |||
set AIC_ISR [expr $AT91C_BASE_AIC + 0x00000108 ] | |||
global AIC_ISR | |||
set AIC_IPR [expr $AT91C_BASE_AIC + 0x0000010C ] | |||
global AIC_IPR | |||
set AIC_IMR [expr $AT91C_BASE_AIC + 0x00000110 ] | |||
global AIC_IMR | |||
set AIC_CISR [expr $AT91C_BASE_AIC + 0x00000114 ] | |||
global AIC_CISR | |||
set AIC_IECR [expr $AT91C_BASE_AIC + 0x00000120 ] | |||
global AIC_IECR | |||
set AIC_IDCR [expr $AT91C_BASE_AIC + 0x00000124 ] | |||
global AIC_IDCR | |||
set AIC_ICCR [expr $AT91C_BASE_AIC + 0x00000128 ] | |||
global AIC_ICCR | |||
set AIC_ISCR [expr $AT91C_BASE_AIC + 0x0000012C ] | |||
global AIC_ISCR | |||
set AIC_EOICR [expr $AT91C_BASE_AIC + 0x00000130 ] | |||
global AIC_EOICR | |||
set AIC_SPU [expr $AT91C_BASE_AIC + 0x00000134 ] | |||
global AIC_SPU | |||
set AIC_DCR [expr $AT91C_BASE_AIC + 0x00000138 ] | |||
global AIC_DCR | |||
set AIC_FFER [expr $AT91C_BASE_AIC + 0x00000140 ] | |||
global AIC_FFER | |||
set AIC_FFDR [expr $AT91C_BASE_AIC + 0x00000144 ] | |||
global AIC_FFDR | |||
set AIC_FFSR [expr $AT91C_BASE_AIC + 0x00000148 ] | |||
global AIC_FFSR | |||
proc aic_enable_disable_list { VAL ENAME DNAME } { | |||
global AT91C_ID | |||
show_mmr32_bits AT91C_ID $VAL | |||
} | |||
proc show_AIC_IPR_helper { NAME ADDR VAL } { | |||
aic_enable_disable_list $VAL "IRQ PENDING" "irq not-pending" | |||
} | |||
proc show_AIC_IMR_helper { NAME ADDR VAL } { | |||
aic_enable_disable_list $VAL "IRQ ENABLED" "irq disabled" | |||
} | |||
proc show_AIC { } { | |||
global AIC_SMR | |||
if [catch { mem2array aaa 32 $AIC_SMR [expr 32 * 4] } msg ] { | |||
error [format "%s (%s)" $msg AIC_SMR] | |||
} | |||
puts "AIC_SMR: Mode & Type" | |||
global AT91C_ID | |||
for { set x 0 } { $x < 32 } { } { | |||
puts -nonewline " " | |||
puts -nonewline [format "%2d: %5s 0x%08x | " $x $AT91C_ID($x) $aaa($x)] | |||
incr x | |||
puts -nonewline [format "%2d: %5s 0x%08x | " $x $AT91C_ID($x) $aaa($x)] | |||
incr x | |||
puts -nonewline [format "%2d: %5s 0x%08x | " $x $AT91C_ID($x) $aaa($x)] | |||
incr x | |||
puts [format "%2d: %5s 0x%08x" $x $AT91C_ID($x) $aaa($x)] | |||
incr x | |||
} | |||
global AIC_SVR | |||
if [catch { mem2array aaa 32 $AIC_SVR [expr 32 * 4] } msg ] { | |||
error [format "%s (%s)" $msg AIC_SVR] | |||
} | |||
puts "AIC_SVR: Vectors" | |||
for { set x 0 } { $x < 32 } { } { | |||
puts -nonewline " " | |||
puts -nonewline [format "%2d: %5s 0x%08x | " $x $AT91C_ID($x) $aaa($x)] | |||
incr x | |||
puts -nonewline [format "%2d: %5s 0x%08x | " $x $AT91C_ID($x) $aaa($x)] | |||
incr x | |||
puts -nonewline [format "%2d: %5s 0x%08x | " $x $AT91C_ID($x) $aaa($x)] | |||
incr x | |||
puts [format "%2d: %5s 0x%08x" $x $AT91C_ID($x) $aaa($x)] | |||
incr x | |||
} | |||
foreach REG { | |||
AIC_IVR AIC_FVR AIC_ISR | |||
AIC_IPR AIC_IMR AIC_CISR AIC_IECR AIC_IDCR | |||
AIC_ICCR AIC_ISCR AIC_EOICR AIC_SPU AIC_DCR | |||
AIC_FFER AIC_FFDR AIC_FFSR } { | |||
if [catch { show_mmr32_reg $REG } msg ] { | |||
error $msg | |||
break | |||
} | |||
} | |||
} | |||
@@ -0,0 +1,128 @@ | |||
source [find tcl/bitsbytes.tcl] | |||
source [find tcl/cpu/arm/arm7tdmi.tcl] | |||
source [find tcl/memory.tcl] | |||
source [find tcl/mmr_helpers.tcl] | |||
set CHIP_MAKER atmel | |||
set CHIP_FAMILY at91sam7 | |||
set CHIP_NAME at91sam7x128 | |||
# how many flash regions. | |||
set N_FLASH 1 | |||
set FLASH(0,CHIPSELECT) -1 | |||
set FLASH(0,BASE) 0x00100000 | |||
set FLASH(0,LEN) $__128K | |||
set FLASH(0,HUMAN) "internal flash" | |||
set FLASH(0,TYPE) "flash" | |||
set FLASH(0,RWX) $RWX_R_X | |||
set FLASH(0,ACCESS_WIDTH) $ACCESS_WIDTH_ANY | |||
# how many ram regions. | |||
set N_RAM 1 | |||
set RAM(0,CHIPSELECT) -1 | |||
set RAM(0,BASE) 0x00200000 | |||
set RAM(0,LEN) $__32K | |||
set RAM(0,HUMAN) "internal ram" | |||
set RAM(0,TYPE) "ram" | |||
set RAM(0,RWX) $RWX_RWX | |||
set RAM(0,ACCESS_WIDTH) $ACCESS_WIDTH_ANY | |||
# I AM LAZY... I create 1 region for all MMRs. | |||
set N_MMREGS 1 | |||
set MMREGS(0,CHIPSELECT) -1 | |||
set MMREGS(0,BASE) 0xfff00000 | |||
set MMREGS(0,LEN) 0x000fffff | |||
set MMREGS(0,HUMAN) "mm-regs" | |||
set MMREGS(0,TYPE) "mmr" | |||
set MMREGS(0,RWX) $RWX_RW | |||
set MMREGS(0,ACCESS_WIDTH) $ACCESS_WIDTH_ANY | |||
# no external memory | |||
set N_XMEM 0 | |||
set AT91C_BASE_SYS 0xFFFFF000 | |||
set AT91C_BASE_AIC 0xFFFFF000 | |||
set AT91C_BASE_PDC_DBGU 0xFFFFF300 | |||
set AT91C_BASE_DBGU 0xFFFFF200 | |||
set AT91C_BASE_PIOA 0xFFFFF400 | |||
set AT91C_BASE_PIOB 0xFFFFF600 | |||
set AT91C_BASE_CKGR 0xFFFFFC20 | |||
set AT91C_BASE_PMC 0xFFFFFC00 | |||
set AT91C_BASE_RSTC 0xFFFFFD00 | |||
set AT91C_BASE_RTTC 0xFFFFFD20 | |||
set AT91C_BASE_PITC 0xFFFFFD30 | |||
set AT91C_BASE_WDTC 0xFFFFFD40 | |||
set AT91C_BASE_VREG 0xFFFFFD60 | |||
set AT91C_BASE_MC 0xFFFFFF00 | |||
set AT91C_BASE_PDC_SPI1 0xFFFE4100 | |||
set AT91C_BASE_SPI1 0xFFFE4000 | |||
set AT91C_BASE_PDC_SPI0 0xFFFE0100 | |||
set AT91C_BASE_SPI0 0xFFFE0000 | |||
set AT91C_BASE_PDC_US1 0xFFFC4100 | |||
set AT91C_BASE_US1 0xFFFC4000 | |||
set AT91C_BASE_PDC_US0 0xFFFC0100 | |||
set AT91C_BASE_US0 0xFFFC0000 | |||
set AT91C_BASE_PDC_SSC 0xFFFD4100 | |||
set AT91C_BASE_SSC 0xFFFD4000 | |||
set AT91C_BASE_TWI 0xFFFB8000 | |||
set AT91C_BASE_PWMC_CH3 0xFFFCC260 | |||
set AT91C_BASE_PWMC_CH2 0xFFFCC240 | |||
set AT91C_BASE_PWMC_CH1 0xFFFCC220 | |||
set AT91C_BASE_PWMC_CH0 0xFFFCC200 | |||
set AT91C_BASE_PWMC 0xFFFCC000 | |||
set AT91C_BASE_UDP 0xFFFB0000 | |||
set AT91C_BASE_TC0 0xFFFA0000 | |||
set AT91C_BASE_TC1 0xFFFA0040 | |||
set AT91C_BASE_TC2 0xFFFA0080 | |||
set AT91C_BASE_TCB 0xFFFA0000 | |||
set AT91C_BASE_CAN_MB0 0xFFFD0200 | |||
set AT91C_BASE_CAN_MB1 0xFFFD0220 | |||
set AT91C_BASE_CAN_MB2 0xFFFD0240 | |||
set AT91C_BASE_CAN_MB3 0xFFFD0260 | |||
set AT91C_BASE_CAN_MB4 0xFFFD0280 | |||
set AT91C_BASE_CAN_MB5 0xFFFD02A0 | |||
set AT91C_BASE_CAN_MB6 0xFFFD02C0 | |||
set AT91C_BASE_CAN_MB7 0xFFFD02E0 | |||
set AT91C_BASE_CAN 0xFFFD0000 | |||
set AT91C_BASE_EMAC 0xFFFDC000 | |||
set AT91C_BASE_PDC_ADC 0xFFFD8100 | |||
set AT91C_BASE_ADC 0xFFFD8000 | |||
set AT91C_ID(0) FIQ | |||
set AT91C_ID(1) SYS | |||
set AT91C_ID(2) PIOA | |||
set AT91C_ID(3) PIOB | |||
set AT91C_ID(4) SPI0 | |||
set AT91C_ID(5) SPI1 | |||
set AT91C_ID(6) US0 | |||
set AT91C_ID(7) US1 | |||
set AT91C_ID(8) SSC | |||
set AT91C_ID(9) TWI | |||
set AT91C_ID(10) PWMC | |||
set AT91C_ID(11) UDP | |||
set AT91C_ID(12) TC0 | |||
set AT91C_ID(13) TC1 | |||
set AT91C_ID(14) TC2 | |||
set AT91C_ID(15) CAN | |||
set AT91C_ID(16) EMAC | |||
set AT91C_ID(17) ADC | |||
set AT91C_ID(18) "" | |||
set AT91C_ID(19) "" | |||
set AT91C_ID(20) "" | |||
set AT91C_ID(21) "" | |||
set AT91C_ID(22) "" | |||
set AT91C_ID(23) "" | |||
set AT91C_ID(24) "" | |||
set AT91C_ID(25) "" | |||
set AT91C_ID(26) "" | |||
set AT91C_ID(27) "" | |||
set AT91C_ID(28) "" | |||
set AT91C_ID(29) "" | |||
set AT91C_ID(30) IRQ0 | |||
set AT91C_ID(31) IRQ1 | |||
source [find tcl/chip/atmel/at91/aic.tcl] | |||
source [find tcl/chip/atmel/at91/usarts.tcl] | |||
source [find tcl/chip/atmel/at91/pmc.tcl] | |||
source [find tcl/chip/atmel/at91/rtt.tcl] |
@@ -0,0 +1,126 @@ | |||
source [find tcl/bitsbytes.tcl] | |||
source [find tcl/cpu/arm/arm7tdmi.tcl] | |||
source [find tcl/memory.tcl] | |||
source [find tcl/mmr_helpers.tcl] | |||
set CHIP_MAKER atmel | |||
set CHIP_FAMILY at91sam7 | |||
set CHIP_NAME at91sam7x256 | |||
# how many flash regions. | |||
set N_FLASH 1 | |||
set FLASH(0,CHIPSELECT) -1 | |||
set FLASH(0,BASE) 0x00100000 | |||
set FLASH(0,LEN) $__256K | |||
set FLASH(0,HUMAN) "internal flash" | |||
set FLASH(0,TYPE) "flash" | |||
set FLASH(0,RWX) $RWX_R_X | |||
set FLASH(0,ACCESS_WIDTH) $ACCESS_WIDTH_ANY | |||
# how many ram regions. | |||
set N_RAM 1 | |||
set RAM(0,CHIPSELECT) -1 | |||
set RAM(0,BASE) 0x00200000 | |||
set RAM(0,LEN) $__64K | |||
set RAM(0,HUMAN) "internal ram" | |||
set RAM(0,TYPE) "ram" | |||
set RAM(0,RWX) $RWX_RWX | |||
set RAM(0,ACCESS_WIDTH) $ACCESS_WIDTH_ANY | |||
# I AM LAZY... I create 1 region for all MMRs. | |||
set N_MMREGS 1 | |||
set MMREGS(0,CHIPSELECT) -1 | |||
set MMREGS(0,BASE) 0xfff00000 | |||
set MMREGS(0,LEN) 0x000fffff | |||
set MMREGS(0,HUMAN) "mm-regs" | |||
set MMREGS(0,TYPE) "mmr" | |||
set MMREGS(0,RWX) $RWX_RW | |||
set MMREGS(0,ACCESS_WIDTH) $ACCESS_WIDTH_ANY | |||
# no external memory | |||
set N_XMEM 0 | |||
set AT91C_BASE_SYS 0xFFFFF000 | |||
set AT91C_BASE_AIC 0xFFFFF000 | |||
set AT91C_BASE_PDC_DBGU 0xFFFFF300 | |||
set AT91C_BASE_DBGU 0xFFFFF200 | |||
set AT91C_BASE_PIOA 0xFFFFF400 | |||
set AT91C_BASE_PIOB 0xFFFFF600 | |||
set AT91C_BASE_CKGR 0xFFFFFC20 | |||
set AT91C_BASE_PMC 0xFFFFFC00 | |||
set AT91C_BASE_RSTC 0xFFFFFD00 | |||
set AT91C_BASE_RTTC 0xFFFFFD20 | |||
set AT91C_BASE_PITC 0xFFFFFD30 | |||
set AT91C_BASE_WDTC 0xFFFFFD40 | |||
set AT91C_BASE_VREG 0xFFFFFD60 | |||
set AT91C_BASE_MC 0xFFFFFF00 | |||
set AT91C_BASE_PDC_SPI1 0xFFFE4100 | |||
set AT91C_BASE_SPI1 0xFFFE4000 | |||
set AT91C_BASE_PDC_SPI0 0xFFFE0100 | |||
set AT91C_BASE_SPI0 0xFFFE0000 | |||
set AT91C_BASE_PDC_US1 0xFFFC4100 | |||
set AT91C_BASE_US1 0xFFFC4000 | |||
set AT91C_BASE_PDC_US0 0xFFFC0100 | |||
set AT91C_BASE_US0 0xFFFC0000 | |||
set AT91C_BASE_PDC_SSC 0xFFFD4100 | |||
set AT91C_BASE_SSC 0xFFFD4000 | |||
set AT91C_BASE_TWI 0xFFFB8000 | |||
set AT91C_BASE_PWMC_CH3 0xFFFCC260 | |||
set AT91C_BASE_PWMC_CH2 0xFFFCC240 | |||
set AT91C_BASE_PWMC_CH1 0xFFFCC220 | |||
set AT91C_BASE_PWMC_CH0 0xFFFCC200 | |||
set AT91C_BASE_PWMC 0xFFFCC000 | |||
set AT91C_BASE_UDP 0xFFFB0000 | |||
set AT91C_BASE_TC0 0xFFFA0000 | |||
set AT91C_BASE_TC1 0xFFFA0040 | |||
set AT91C_BASE_TC2 0xFFFA0080 | |||
set AT91C_BASE_TCB 0xFFFA0000 | |||
set AT91C_BASE_CAN_MB0 0xFFFD0200 | |||
set AT91C_BASE_CAN_MB1 0xFFFD0220 | |||
set AT91C_BASE_CAN_MB2 0xFFFD0240 | |||
set AT91C_BASE_CAN_MB3 0xFFFD0260 | |||
set AT91C_BASE_CAN_MB4 0xFFFD0280 | |||
set AT91C_BASE_CAN_MB5 0xFFFD02A0 | |||
set AT91C_BASE_CAN_MB6 0xFFFD02C0 | |||
set AT91C_BASE_CAN_MB7 0xFFFD02E0 | |||
set AT91C_BASE_CAN 0xFFFD0000 | |||
set AT91C_BASE_EMAC 0xFFFDC000 | |||
set AT91C_BASE_PDC_ADC 0xFFFD8100 | |||
set AT91C_BASE_ADC 0xFFFD8000 | |||
set AT91C_ID(0) "FIQ" | |||
set AT91C_ID(1) "SYS" | |||
set AT91C_ID(2) "PIOA" | |||
set AT91C_ID(3) "PIOB" | |||
set AT91C_ID(4) "SPI0" | |||
set AT91C_ID(5) "SPI1" | |||
set AT91C_ID(6) "US0" | |||
set AT91C_ID(7) "US1" | |||
set AT91C_ID(8) "SSC" | |||
set AT91C_ID(9) "TWI" | |||
set AT91C_ID(10) "PWMC" | |||
set AT91C_ID(11) "UDP" | |||
set AT91C_ID(12) "TC0" | |||
set AT91C_ID(13) "TC1" | |||
set AT91C_ID(14) "TC2" | |||
set AT91C_ID(15) "CAN" | |||
set AT91C_ID(16) "EMAC" | |||
set AT91C_ID(17) "ADC" | |||
set AT91C_ID(18) "" | |||
set AT91C_ID(19) "" | |||
set AT91C_ID(20) "" | |||
set AT91C_ID(21) "" | |||
set AT91C_ID(22) "" | |||
set AT91C_ID(23) "" | |||
set AT91C_ID(24) "" | |||
set AT91C_ID(25) "" | |||
set AT91C_ID(26) "" | |||
set AT91C_ID(27) "" | |||
set AT91C_ID(28) "" | |||
set AT91C_ID(29) "" | |||
set AT91C_ID(30) "IRQ0" | |||
set AT91C_ID(31) "IRQ1" | |||
source [find tcl/chip/atmel/at91/aic.tcl] | |||
source [find tcl/chip/atmel/at91/usarts.tcl] | |||
source [find tcl/chip/atmel/at91/pmc.tcl] | |||
source [find tcl/chip/atmel/at91/rtt.tcl] |
@@ -0,0 +1,17 @@ | |||
if [info exists AT91C_MAINOSC_FREQ] { | |||
# user set this... let it be. | |||
} { | |||
# 18.432mhz is a common thing... | |||
set AT91C_MAINOSC_FREQ 18432000 | |||
} | |||
global AT91C_MAINOSC_FREQ | |||
if [info exists AT91C_SLOWOSC_FREQ] { | |||
# user set this... let it be. | |||
} { | |||
# 32khz is the norm | |||
set AT91C_SLOWOSC_FREQ 32768 | |||
} | |||
global AT91C_SLOWOSC_FREQ | |||
@@ -0,0 +1,54 @@ | |||
set RTTC_RTMR [expr $AT91C_BASE_RTTC + 0x00] | |||
set RTTC_RTAR [expr $AT91C_BASE_RTTC + 0x04] | |||
set RTTC_RTVR [expr $AT91C_BASE_RTTC + 0x08] | |||
set RTTC_RTSR [expr $AT91C_BASE_RTTC + 0x0c] | |||
global RTTC_RTMR | |||
global RTTC_RTAR | |||
global RTTC_RTVR | |||
global RTTC_RTSR | |||
proc show_RTTC_RTMR_helper { NAME ADDR VAL } { | |||
set rtpres [expr $VAL & 0x0ffff] | |||
global BIT16 BIT17 | |||
if { $rtpres == 0 } { | |||
set rtpres 65536; | |||
} | |||
global AT91C_SLOWOSC_FREQ | |||
set f [expr double($AT91C_SLOWOSC_FREQ) / double($rtpres)] | |||
puts [format "\tPrescale value: 0x%04x (%5d) => %f Hz" $rtpres $rtpres $f] | |||
if { $VAL & $BIT16 } { | |||
puts "\tBit16 -> Alarm IRQ Enabled" | |||
} else { | |||
puts "\tBit16 -> Alarm IRQ Disabled" | |||
} | |||
if { $VAL & $BIT17 } { | |||
puts "\tBit17 -> RTC Inc IRQ Enabled" | |||
} else { | |||
puts "\tBit17 -> RTC Inc IRQ Disabled" | |||
} | |||
# Bit 18 is write only. | |||
} | |||
proc show_RTTC_RTSR_helper { NAME ADDR VAL } { | |||
global BIT0 BIT1 | |||
if { $VAL & $BIT0 } { | |||
puts "\tBit0 -> ALARM PENDING" | |||
} else { | |||
puts "\tBit0 -> alarm not pending" | |||
} | |||
if { $VAL & $BIT1 } { | |||
puts "\tBit0 -> RTINC PENDING" | |||
} else { | |||
puts "\tBit0 -> rtinc not pending" | |||
} | |||
} | |||
proc show_RTTC { } { | |||
show_mmr32_reg RTTC_RTMR | |||
show_mmr32_reg RTTC_RTAR | |||
show_mmr32_reg RTTC_RTVR | |||
show_mmr32_reg RTTC_RTSR | |||
} | |||
@@ -0,0 +1,135 @@ | |||
# the DBGU and USARTs are 'almost' indentical' | |||
set DBGU_CR [expr $AT91C_BASE_DBGU + 0x00000000] | |||
set DBGU_MR [expr $AT91C_BASE_DBGU + 0x00000004] | |||
set DBGU_IER [expr $AT91C_BASE_DBGU + 0x00000008] | |||
set DBGU_IDR [expr $AT91C_BASE_DBGU + 0x0000000C] | |||
set DBGU_IMR [expr $AT91C_BASE_DBGU + 0x00000010] | |||
set DBGU_CSR [expr $AT91C_BASE_DBGU + 0x00000014] | |||
set DBGU_RHR [expr $AT91C_BASE_DBGU + 0x00000018] | |||
set DBGU_THR [expr $AT91C_BASE_DBGU + 0x0000001C] | |||
set DBGU_BRGR [expr $AT91C_BASE_DBGU + 0x00000020] | |||
# no RTOR | |||
# no TTGR | |||
# no FIDI | |||
# no NER | |||
set DBGU_CIDR [expr $AT91C_BASE_DBGU + 0x00000040] | |||
set DBGU_EXID [expr $AT91C_BASE_DBGU + 0x00000044] | |||
set DBGU_FNTR [expr $AT91C_BASE_DBGU + 0x00000048] | |||
set USx_CR 0x00000000 | |||
set USx_MR 0x00000004 | |||
set USx_IER 0x00000008 | |||
set USx_IDR 0x0000000C | |||
set USx_IMR 0x00000010 | |||
set USx_CSR 0x00000014 | |||
set USx_RHR 0x00000018 | |||
set USx_THR 0x0000001C | |||
set USx_BRGR 0x00000020 | |||
set USx_RTOR 0x00000024 | |||
set USx_TTGR 0x00000028 | |||
set USx_FIDI 0x00000040 | |||
set USx_NER 0x00000044 | |||
set USx_IF 0x0000004C | |||
# Create all the uarts that exist.. | |||
# we blow up if there are >9 | |||
proc show_mmr_USx_MR_helper { NAME ADDR VAL } { | |||
# First - just print it | |||
set x [show_normalize_bitfield $VAL 3 0] | |||
if { $x == 0 } { | |||
puts "\tNormal operation" | |||
} else { | |||
puts [format "\tNon Normal operation mode: 0x%02x" $x] | |||
} | |||
set x [show_normalize_bitfield $VAL 11 9] | |||
set s "unknown" | |||
switch -exact $x { | |||
0 { set s "Even" } | |||
1 { set s "Odd" } | |||
2 { set s "Force=0" } | |||
3 { set s "Force=1" } | |||
* { | |||
set $x [expr $x & 6] | |||
switch -exact $x { | |||
4 { set s "None" } | |||
6 { set s "Multidrop Mode" } | |||
} | |||
} | |||
} | |||
puts [format "\tParity: %s " $s] | |||
set x [expr 5 + [show_normalize_bitfield $VAL 7 6]] | |||
puts [format "\tDatabits: %d" $x] | |||
set x [show_normalize_bitfield $VAL 13 12] | |||
switch -exact $x { | |||
0 { puts "\tStop bits: 1" } | |||
1 { puts "\tStop bits: 1.5" } | |||
2 { puts "\tStop bits: 2" } | |||
3 { puts "\tStop bits: Illegal/Reserved" } | |||
} | |||
} | |||
# For every possbile usart... | |||
foreach WHO { US0 US1 US2 US3 US4 US5 US6 US7 US8 US9 } { | |||
set n AT91C_BASE_[set WHO] | |||
set str "" | |||
# Only if it exists on the chip | |||
if [ info exists $n ] { | |||
# Hence: $n - is like AT91C_BASE_USx | |||
# For every sub-register | |||
foreach REG {CR MR IER IDR IMR CSR RHR THR BRGR RTOR TTGR FIDI NER IF} { | |||
# vn = variable name | |||
set vn [set WHO]_[set REG] | |||
# vn = USx_IER | |||
# vv = variable value | |||
set vv [expr $$n + [set USx_[set REG]]] | |||
# And VV is the address in memory of that register | |||
# make that VN a GLOBAL so others can find it | |||
global $vn | |||
set $vn $vv | |||
# Create a command for this specific register. | |||
proc show_$vn { } "show_mmr32_reg $vn" | |||
# Add this command to the Device(as a whole) command | |||
set str "$str\nshow_$vn" | |||
} | |||
# Now - create the DEVICE(as a whole) command | |||
set fn show_$WHO | |||
proc $fn { } $str | |||
} | |||
} | |||
# The Debug Uart is special.. | |||
set str "" | |||
# For every sub-register | |||
foreach REG {DBGU_CR DBGU_MR DBGU_IER DBGU_IDR DBGU_IMR | |||
DBGU_CSR DBGU_RHR DBGU_THR DBGU_BRGR DBGU_CIDR DBGU_EXID DBGU_FNTR} { | |||
# Create a command for this specific register. | |||
proc show_$REG { } "show_mmr32_reg $REG" | |||
# Add this command to the Device(as a whole) command | |||
set str "$str\nshow_$REG" | |||
} | |||
# Now - create the DEVICE(as a whole) command | |||
proc show_DBGU { } $str | |||
unset str | |||
proc show_DBGU_MR_helper { NAME ADDR VAL } { show_mmr_USx_MR_helper $NAME $ADDR $VAL } | |||
@@ -0,0 +1,6 @@ | |||
set CPU_TYPE arm | |||
set CPU_NAME arm7tdmi | |||
set CPU_ARCH armv4t | |||
set CPU_MAX_ADDRESS 0xFFFFFFFF | |||
set CPU_NBITS 32 | |||
@@ -0,0 +1,6 @@ | |||
set CPU_TYPE arm | |||
set CPU_NAME arm920 | |||
set CPU_ARCH armv4t | |||
set CPU_MAX_ADDRESS 0xFFFFFFFF | |||
set CPU_NBITS 32 | |||
@@ -0,0 +1,6 @@ | |||
set CPU_TYPE arm | |||
set CPU_NAME arm946 | |||
set CPU_ARCH armv5te | |||
set CPU_MAX_ADDRESS 0xFFFFFFFF | |||
set CPU_NBITS 32 | |||
@@ -0,0 +1,6 @@ | |||
set CPU_TYPE arm | |||
set CPU_NAME arm966 | |||
set CPU_ARCH armv5te | |||
set CPU_MAX_ADDRESS 0xFFFFFFFF | |||
set CPU_NBITS 32 | |||
@@ -0,0 +1,108 @@ | |||
# MEMORY | |||
# | |||
# All Memory regions have two components. | |||
# (1) A count of regions, in the form N_NAME | |||
# (2) An array within info about each region. | |||
# | |||
# The ARRAY | |||
# | |||
# <NAME>( RegionNumber , ATTRIBUTE ) | |||
# | |||
# Where <NAME> is one of: | |||
# | |||
# N_FLASH & FLASH (internal memory) | |||
# N_RAM & RAM (internal memory) | |||
# N_MMREGS & MMREGS (for memory mapped registers) | |||
# N_XMEM & XMEM (off chip memory, ie: flash on cs0, sdram on cs2) | |||
# or N_UNKNOWN & UNKNOWN for things that do not exist. | |||
# | |||
# We have 1 unknown region. | |||
set N_UNKNOWN 1 | |||
# All MEMORY regions must have these attributes | |||
# CS - chip select (if internal, use -1) | |||
set UNKNOWN(0,CHIPSELECT) -1 | |||
# BASE - base address in memory | |||
set UNKNOWN(0,BASE) 0 | |||
# LEN - length in bytes | |||
set UNKNOWN(0,LEN) $CPU_MAX_ADDRESS | |||
# HUMAN - human name of the region | |||
set UNKNOWN(0,HUMAN) "unknown" | |||
# TYPE - one of: | |||
# flash, ram, mmr, unknown | |||
# For harvard arch: | |||
# iflash, dflash, iram, dram | |||
set UNKNOWN(0,TYPE) "unknown" | |||
# RWX - access ablity | |||
# unix style chmod bits | |||
# 0 - no access | |||
# 1 - execute | |||
# 2 - write | |||
# 4 - read | |||
# hence: 7 - readwrite execute | |||
set RWX_NO_ACCESS 0 | |||
set RWX_X_ONLY $BIT0 | |||
set RWX_W_ONLY $BIT1 | |||
set RWX_R_ONLY $BIT2 | |||
set RWX_RW [expr $RWX_R_ONLY + $RWX_W_ONLY] | |||
set RWX_R_X [expr $RWX_R_ONLY + $RWX_X_ONLY] | |||
set RWX_RWX [expr $RWX_R_ONLY + $RWX_W_ONLY + $RWX_X_ONLY] | |||
set UNKNOWN(0,RWX) $RWX_NO_ACCESS | |||
# WIDTH - access width | |||
# 8,16,32 [0 means ANY] | |||
set ACCESS_WIDTH_NONE 0 | |||
set ACCESS_WIDTH_8 $BIT0 | |||
set ACCESS_WIDTH_16 $BIT1 | |||
set ACCESS_WIDTH_32 $BIT2 | |||
set ACCESS_WIDTH_ANY [expr $ACCESS_WIDTH_8 + $ACCESS_WIDTH_16 + $ACCESS_WIDTH_32] | |||
set UNKNOWN(0,ACCESS_WIDTH) $ACCESS_WIDTH_NONE | |||
proc iswithin { ADDRESS BASE LEN } { | |||
return [expr ((($ADDRESS - $BASE) > 0) && (($ADDRESS - $BASE + $LEN) > 0))] | |||
} | |||
proc address_info { ADDRESS } { | |||
foreach WHERE { FLASH RAM MMREGS XMEM UNKNOWN } { | |||
if { info exists $WHERE } { | |||
set lmt [set N_[set WHERE]] | |||
for { set region 0 } { $region < $lmt } { incr region } { | |||
if { iswithin $ADDRESS $WHERE($region,BASE) $WHERE($region,LEN) } { | |||
return "$WHERE $region"; | |||
} | |||
} | |||
} | |||
} | |||
# Return the 'unknown' | |||
return "UNKNOWN 0" | |||
} | |||
proc memread32 {ADDR } { | |||
set foo(0) 0 | |||
if ![ catch { mem2array foo 32 $ADDR 1 } msg ] { | |||
return $foo(0) | |||
} else { | |||
error "memead32: $msg" | |||
} | |||
} | |||
proc memread16 {ADDR } { | |||
set foo(0) 0 | |||
if ![ catch { mem2array foo 16 $ADDR 1 } msg ] { | |||
return $foo(0) | |||
} else { | |||
error "memead16: $msg" | |||
} | |||
} | |||
proc memread82 {ADDR } { | |||
set foo(0) 0 | |||
if ![ catch { mem2array foo 8 $ADDR 1 } msg ] { | |||
return $foo(0) | |||
} else { | |||
error "memead8: $msg" | |||
} | |||
} | |||
@@ -0,0 +1,59 @@ | |||
proc proc_exists { NAME } { | |||
set n [info commands $NAME] | |||
set l [string length $n] | |||
return [expr $l != 0] | |||
} | |||
# Give: REGISTER name - must be a global variable. | |||
proc show_mmr32_reg { NAME } { | |||
global $NAME | |||
# we want $($NAME) | |||
set a [set [set NAME]] | |||
if ![catch { set v [memread32 $a] } msg ] { | |||
puts [format "%10s: (0x%08x): 0x%08x" $NAME $a $v] | |||
# Was a helper defined? | |||
set fn show_${NAME}_helper | |||
if [ proc_exists $fn ] { | |||
# Then call it | |||
$fn $NAME $a $v | |||
} | |||
return $v; | |||
} else { | |||
error [format "%s (%s)" $msg $NAME ] | |||
} | |||
} | |||
# Give: NAMES - an array of names accessable | |||
# in the callers symbol-scope. | |||
# VAL - the bits to display. | |||
proc show_mmr32_bits { NAMES VAL } { | |||
upvar $NAMES MYNAMES | |||
set w 0 | |||
foreach {IDX N} $MYNAMES { | |||
set l [string length $N] | |||
if { $l > $w } { set w $l } | |||
} | |||
for { set x 24 } { $x >= 0 } { incr x -8 } { | |||
puts -nonewline " " | |||
for { set y 7 } { $y >= 0 } { incr y -1 } { | |||
set s $MYNAMES([expr $x + $y]) | |||
puts -nonewline [format "%2d: %-*s | " [expr $x + $y] $w $s ] | |||
} | |||
puts "" | |||
puts -nonewline " " | |||
for { set y 7 } { $y >= 0 } { incr y -1 } { | |||
puts -nonewline [format " %d%*s | " [expr !!($VAL & (1 << ($x + $y)))] [expr $w -1] ""] | |||
} | |||
puts "" | |||
} | |||
} |
@@ -0,0 +1,25 @@ | |||
proc iswithin { ADDRESS BASE LEN } { | |||
return [expr ((($ADDRESS - $BASE) > 0) && (($ADDRESS - $BASE + $LEN) > 0))] | |||
} | |||
proc memorytype { ADDRESS } { | |||
for { set chip 0 } { $chip < $N_CHIP } { incr chip } { | |||
if { iswithin $ADDRESS $FLASH($chip,BASE) $FLASH($chip,LEN) } { | |||
return "flash" | |||
} | |||
} | |||
for { set chip 0 } { $chip < $N_RAM } { incr chip } { | |||
if { iswithin $ADDRESS $RAM($chip,BASE) $RAM($chip,LEN) } { | |||
return "ram" | |||
} | |||
} | |||
} | |||
# default to 32bit reads. | |||
proc isreadable { ADDRESS } { | |||
return isreadable32 $ADDRESS | |||
} | |||
proc isreadable32 { ADDRESS } { | |||