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
This commit is contained in:
oharboe 2008-07-06 19:17:43 +00:00
parent 71460ba9a5
commit dc796a2091
27 changed files with 2004 additions and 157 deletions

View File

@ -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

View File

@ -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: **
*/

View File

@ -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: **
*/

View File

@ -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);

View File

@ -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);

383
src/jim.c
View File

@ -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: **
*/

View File

@ -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: **
*/

View File

@ -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: **
*/

View File

@ -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;
}

View File

@ -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: **
*/

View File

@ -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)

View File

@ -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)

View File

@ -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...

63
src/tcl/bitsbytes.tcl Normal file
View File

@ -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
}

View File

@ -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
}
}
}

View File

@ -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]

View File

@ -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]

View File

@ -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

View File

@ -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
}

View File

@ -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 }

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

108
src/tcl/memory.tcl Normal file
View File

@ -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"
}
}

59
src/tcl/mmr_helpers.tcl Normal file
View File

@ -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 ""
}
}

25
src/tcl/readable.tcl Normal file
View File

@ -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 } {