-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
+
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;
return retval;
}
+/*
+ * Local Variables: **
+ * tab-width: 4 **
+ * c-basic-offset: 4 **
+ * End: **
+ */
+
* 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;
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);
extern int fast_and_dangerous;
#endif /* COMMAND_H */
+
+/*
+ * Local Variables: **
+ * tab-width: 4 **
+ * c-basic-offset: 4 **
+ * End: **
+ */
+
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);
{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);
#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) {
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) {
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;
}
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];
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();
}
}
/* 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--;
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';
"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--;
}
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);
* 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;
}
* 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
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
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. */
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;
}
/* -----------------------------------------------------------------------------
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]);
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);
}
}
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;
}
{
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) {
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);
}
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");
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) {
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;
}
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);
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: **
+ */
+
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.
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);
/* 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
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 */
#endif
#endif /* __JIM__H */
+
+/*
+ * Local Variables: **
+ * tab-width: 4 **
+ * c-basic-offset: 4 **
+ * End: **
+ */
+
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)
{
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();
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[])
return EXIT_SUCCESS;
}
+
+/*
+ * Local Variables: **
+ * tab-width: 4 **
+ * c-basic-offset: 4 **
+ * End: **
+ */
+
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);
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;
}
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
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;
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);
{
return ERROR_COMMAND_CLOSE_CONNECTION;
}
+
+/*
+ * Local Variables: **
+ * tab-width: 4 **
+ * c-basic-offset: 4 **
+ * End: **
+ */
+
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
*/
{
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();
}
target = targets;
while (target)
{
- execute_script(cmd_ctx, target->pre_reset_script);
+ target_invoke_script(cmd_ctx, target, "pre_reset");
target = target->next;
}
{
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>");
}
(*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;
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;
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;
}
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)
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.
*/
/* 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)
--- /dev/null
+****************************************
+****************************************
+
+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...
--- /dev/null
+#----------------------------------------
+# 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
+}
+
+
--- /dev/null
+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
+ }
+ }
+}
+
--- /dev/null
+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]
--- /dev/null
+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]
--- /dev/null
+
+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
+
--- /dev/null
+
+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
+}
+
--- /dev/null
+# 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 }
+
+
+
--- /dev/null
+set CPU_TYPE arm
+set CPU_NAME arm7tdmi
+set CPU_ARCH armv4t
+set CPU_MAX_ADDRESS 0xFFFFFFFF
+set CPU_NBITS 32
+
--- /dev/null
+set CPU_TYPE arm
+set CPU_NAME arm920
+set CPU_ARCH armv4t
+set CPU_MAX_ADDRESS 0xFFFFFFFF
+set CPU_NBITS 32
+
--- /dev/null
+set CPU_TYPE arm
+set CPU_NAME arm946
+set CPU_ARCH armv5te
+set CPU_MAX_ADDRESS 0xFFFFFFFF
+set CPU_NBITS 32
+
--- /dev/null
+set CPU_TYPE arm
+set CPU_NAME arm966
+set CPU_ARCH armv5te
+set CPU_MAX_ADDRESS 0xFFFFFFFF
+set CPU_NBITS 32
+
--- /dev/null
+# 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"
+ }
+}
+
+
--- /dev/null
+
+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 ""
+ }
+}
--- /dev/null
+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 } {
+
\ No newline at end of file