src/helper/configuration.h
- 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-e2dbd0fdcd60__archive__
parent
71460ba9a5
commit
dc796a2091
|
@ -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);
|
||||
|
||||
|
|
377
src/jim.c
377
src/jim.c
|
@ -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,8 +2184,96 @@ Jim_Obj *Jim_FormatString(Jim_Interp *interp, Jim_Obj *fmtObjPtr,
|
|||
if (fmtLen == 0)
|
||||
break;
|
||||
fmt++; fmtLen--; /* skip '%' */
|
||||
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);
|
||||
|
@ -2169,28 +2282,93 @@ Jim_Obj *Jim_FormatString(Jim_Interp *interp, Jim_Obj *fmtObjPtr,
|
|||
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,
|
||||
Jim_fprintf(interp, interp->cookie_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, " %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: **
|
||||
*/
|
||||
|
||||
|
|
41
src/jim.h
41
src/jim.h
|
@ -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: **
|
||||
*/
|
||||
|
||||
|
|
295
src/openocd.c
295
src/openocd.c
|
@ -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);
|
||||
|
||||
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 } {
|
||||
|
Loading…
Reference in New Issue