src/helper/configuration.h
authoroharboe <oharboe@b42882b7-edfa-0310-969c-e2dbd0fdcd60>
Sun, 6 Jul 2008 19:17:43 +0000 (19:17 +0000)
committeroharboe <oharboe@b42882b7-edfa-0310-969c-e2dbd0fdcd60>
Sun, 6 Jul 2008 19:17:43 +0000 (19:17 +0000)
- 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

27 files changed:
src/Makefile.am
src/helper/command.c
src/helper/command.h
src/helper/configuration.h
src/helper/options.c
src/jim.c
src/jim.h
src/openocd.c
src/server/gdb_server.c
src/server/telnet_server.c
src/target/target.c
src/target/target.h
src/tcl/README_ABOUT_TCL.txt [new file with mode: 0644]
src/tcl/bitsbytes.tcl [new file with mode: 0644]
src/tcl/chip/atmel/at91/aic.tcl [new file with mode: 0644]
src/tcl/chip/atmel/at91/at91sam7x128.tcl [new file with mode: 0644]
src/tcl/chip/atmel/at91/at91sam7x256.tcl [new file with mode: 0644]
src/tcl/chip/atmel/at91/pmc.tcl [new file with mode: 0644]
src/tcl/chip/atmel/at91/rtt.tcl [new file with mode: 0644]
src/tcl/chip/atmel/at91/usarts.tcl [new file with mode: 0644]
src/tcl/cpu/arm/arm7tdmi.tcl [new file with mode: 0644]
src/tcl/cpu/arm/arm920.tcl [new file with mode: 0644]
src/tcl/cpu/arm/arm946.tcl [new file with mode: 0644]
src/tcl/cpu/arm/arm966.tcl [new file with mode: 0644]
src/tcl/memory.tcl [new file with mode: 0644]
src/tcl/mmr_helpers.tcl [new file with mode: 0644]
src/tcl/readable.tcl [new file with mode: 0644]

index 462b5ee..924040e 100644 (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  
+
index ed0a82e..386572e 100644 (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: **
+ */
+
index 8d50d6e..8db1675 100644 (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: **
+ */
+
index 894d874..1d315cc 100644 (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);
 
index ab36a28..afff55b 100644 (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);
 
index a466a08..4cf4f3d 100644 (file)
--- a/src/jim.c
+++ b/src/jim.c
@@ -363,7 +363,7 @@ int Jim_StringToWide(const char *str, jim_wide *widePtr, int base)
 #else
     *widePtr = strtol(str, &endptr, base);
 #endif
-    if (str[0] == '\0')
+    if ((str[0] == '\0') || (str == endptr) )
         return JIM_ERR;
     if (endptr[0] != '\0') {
         while(*endptr) {
@@ -380,7 +380,7 @@ int Jim_StringToIndex(const char *str, int *intPtr)
     char *endptr;
 
     *intPtr = strtol(str, &endptr, 10);
-    if (str[0] == '\0')
+    if ( (str[0] == '\0') || (str == endptr) )
         return JIM_ERR;
     if (endptr[0] != '\0') {
         while(*endptr) {
@@ -437,7 +437,7 @@ int Jim_StringToDouble(const char *str, double *doublePtr)
     char *endptr;
 
     *doublePtr = strtod(str, &endptr);
-    if (str[0] == '\0' || endptr[0] != '\0')
+    if (str[0] == '\0' || endptr[0] != '\0' || (str == endptr) )
         return JIM_ERR;
     return JIM_OK;
 }
@@ -460,13 +460,16 @@ static jim_wide JimPowWide(jim_wide b, jim_wide e)
 void Jim_Panic(Jim_Interp *interp, const char *fmt, ...)
 {
     va_list ap;
-    FILE *fp = interp ? interp->stderr_ : stderr;
 
     va_start(ap, fmt);
-    fprintf(fp, JIM_NL "JIM INTERPRETER PANIC: ");
-    vfprintf(fp, fmt, ap);
-    fprintf(fp, JIM_NL JIM_NL);
+       /* 
+        * Send it here first.. Assuming STDIO still works
+        */
+    fprintf(stderr, JIM_NL "JIM INTERPRETER PANIC: ");
+    vfprintf(stderr, fmt, ap);
+    fprintf(stderr, JIM_NL JIM_NL);
     va_end(ap);
+
 #ifdef HAVE_BACKTRACE
     {
         void *array[40];
@@ -481,6 +484,13 @@ void Jim_Panic(Jim_Interp *interp, const char *fmt, ...)
         fprintf(fp,"[backtrace] of 'nm <executable>' in the bug report." JIM_NL);
     }
 #endif
+       
+       /* This may actually crash... we do it last */
+       if( interp && interp->cookie_stderr ){
+               Jim_fprintf(  interp, interp->cookie_stderr, JIM_NL "JIM INTERPRETER PANIC: ");
+               Jim_vfprintf( interp, interp->cookie_stderr, fmt, ap );
+               Jim_fprintf(  interp, interp->cookie_stderr, JIM_NL JIM_NL );
+       }
     abort();
 }
 
@@ -2136,21 +2146,36 @@ static Jim_Obj *JimStringToUpper(Jim_Interp *interp, Jim_Obj *strObjPtr)
 }
 
 /* This is the core of the [format] command.
- * TODO: Export it, make it real... for now only %s and %%
- * specifiers supported. */
+ * TODO: Lots of things work - via a hack
+ *       However, no format item can be >= JIM_MAX_FMT 
+ */
 Jim_Obj *Jim_FormatString(Jim_Interp *interp, Jim_Obj *fmtObjPtr,
         int objc, Jim_Obj *const *objv)
 {
-    const char *fmt;
+    const char *fmt, *_fmt;
     int fmtLen;
     Jim_Obj *resObjPtr;
+    
 
     fmt = Jim_GetString(fmtObjPtr, &fmtLen);
+       _fmt = fmt;
     resObjPtr = Jim_NewStringObj(interp, "", 0);
     while (fmtLen) {
         const char *p = fmt;
         char spec[2], c;
         jim_wide wideValue;
+               double doubleValue;
+               /* we cheat and use Sprintf()! */
+#define JIM_MAX_FMT 2048
+               char sprintf_buf[JIM_MAX_FMT];
+               char fmt_str[100];
+               char *cp;
+               int width;
+               int ljust;
+               int zpad;
+               int spad;
+               int altfm;
+               int forceplus;
 
         while (*fmt != '%' && fmtLen) {
             fmt++; fmtLen--;
@@ -2159,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: **
+ */
+
index cbd0d8f..b08c11f 100644 (file)
--- a/src/jim.h
+++ b/src/jim.h
@@ -497,9 +497,14 @@ typedef struct Jim_Interp {
     struct Jim_HashTable assocData; /* per-interp storage for use by packages */
     Jim_PrngState *prngState; /* per interpreter Random Number Gen. state. */
     struct Jim_HashTable packages; /* Provided packages hash table */
-    FILE *stdin_; /* input file pointer, 'stdin' by default */
-    FILE *stdout_; /* output file pointer, 'stdout' by default */
-    FILE *stderr_; /* errors file pointer, 'stderr' by default */
+    void *cookie_stdin; /* input file pointer, 'stdin' by default */
+    void *cookie_stdout; /* output file pointer, 'stdout' by default */
+    void *cookie_stderr; /* errors file pointer, 'stderr' by default */
+    size_t (*cb_fwrite  )( const void *ptr, size_t size, size_t n, void *cookie );
+       size_t (*cb_fread   )( void *ptr, size_t size, size_t n, void *cookie );
+       int    (*cb_vfprintf)( void *cookie, const char *fmt, va_list ap );
+       int    (*cb_fflush  )( void *cookie );
+       char  *(*cb_fgets   )( char *s, int size, void *cookie );
 } Jim_Interp;
 
 /* Currently provided as macro that performs the increment.
@@ -662,9 +667,9 @@ JIM_STATIC int JIM_API(Jim_GetFinalizer) (Jim_Interp *interp, Jim_Obj *objPtr, J
 JIM_STATIC Jim_Interp * JIM_API(Jim_CreateInterp) (void);
 JIM_STATIC void JIM_API(Jim_FreeInterp) (Jim_Interp *i);
 JIM_STATIC int JIM_API(Jim_GetExitCode) (Jim_Interp *interp);
-JIM_STATIC FILE * JIM_API(Jim_SetStdin) (Jim_Interp *interp, FILE *fp);
-JIM_STATIC FILE * JIM_API(Jim_SetStdout) (Jim_Interp *interp, FILE *fp);
-JIM_STATIC FILE * JIM_API(Jim_SetStderr) (Jim_Interp *interp, FILE *fp);
+JIM_STATIC void * JIM_API(Jim_SetStdin) (Jim_Interp *interp, void *fp);
+JIM_STATIC void * JIM_API(Jim_SetStdout) (Jim_Interp *interp, void *fp);
+JIM_STATIC void * JIM_API(Jim_SetStderr) (Jim_Interp *interp, void *fp);
 
 /* commands */
 JIM_STATIC void JIM_API(Jim_RegisterCoreCommands) (Jim_Interp *interp);
@@ -815,6 +820,15 @@ JIM_STATIC int JIM_API(Jim_InteractivePrompt) (Jim_Interp *interp);
 /* Misc */
 JIM_STATIC void JIM_API(Jim_Panic) (Jim_Interp *interp, const char *fmt, ...);
 
+/* Jim's STDIO */
+JIM_STATIC int     JIM_API( Jim_fprintf  )( Jim_Interp *interp, void *cookie, const char *fmt, ... );
+JIM_STATIC int     JIM_API( Jim_vfprintf )( Jim_Interp *interp, void *cookie, const char *fmt, va_list ap );
+JIM_STATIC size_t  JIM_API( Jim_fwrite   )( Jim_Interp *interp, const void *ptr, size_t size, size_t nmeb, void *cookie );
+JIM_STATIC size_t  JIM_API( Jim_fread    )( Jim_Interp *interp, void *ptr, size_t size, size_t nmeb, void *cookie );
+JIM_STATIC int     JIM_API( Jim_fflush   )( Jim_Interp *interp, void *cookie );
+JIM_STATIC char *  JIM_API( Jim_fgets    )( Jim_Interp *interp, char *s, int size, void *cookie );
+
+
 #undef JIM_STATIC
 #undef JIM_API
 
@@ -942,6 +956,13 @@ static void Jim_InitExtension(Jim_Interp *interp)
   JIM_GET_API(StackPop);
   JIM_GET_API(StackPeek);
   JIM_GET_API(FreeStackElements);
+  JIM_GET_API(fprintf  );
+  JIM_GET_API(vfprintf );
+  JIM_GET_API(fwrite   );
+  JIM_GET_API(fread    );
+  JIM_GET_API(fflush   );
+  JIM_GET_API(fgets    );
+  
 }
 #endif /* defined JIM_EXTENSION || defined JIM_EMBEDDED */
 
@@ -962,3 +983,11 @@ static void Jim_InitEmbedded(void) {
 #endif
 
 #endif /* __JIM__H */
+
+/*
+ * Local Variables: **
+ * tab-width: 4 **
+ * c-basic-offset: 4 **
+ * End: **
+ */
+
index 99ee652..b6b217d 100644 (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: **
+ */
+
index c2c18ba..3ea1dde 100644 (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;
 }
index fc3f211..fc39c72 100644 (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: **
+ */
+
index 0237fd6..86b42db 100644 (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)
index c12dff5..05ea584 100644 (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)
diff --git a/src/tcl/README_ABOUT_TCL.txt b/src/tcl/README_ABOUT_TCL.txt
new file mode 100644 (file)
index 0000000..47131fe
--- /dev/null
@@ -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...
diff --git a/src/tcl/bitsbytes.tcl b/src/tcl/bitsbytes.tcl
new file mode 100644 (file)
index 0000000..b1771b4
--- /dev/null
@@ -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
+}
+
+
diff --git a/src/tcl/chip/atmel/at91/aic.tcl b/src/tcl/chip/atmel/at91/aic.tcl
new file mode 100644 (file)
index 0000000..245224a
--- /dev/null
@@ -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
+       }
+    }
+}
+
diff --git a/src/tcl/chip/atmel/at91/at91sam7x128.tcl b/src/tcl/chip/atmel/at91/at91sam7x128.tcl
new file mode 100644 (file)
index 0000000..1cf7c1c
--- /dev/null
@@ -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]
diff --git a/src/tcl/chip/atmel/at91/at91sam7x256.tcl b/src/tcl/chip/atmel/at91/at91sam7x256.tcl
new file mode 100644 (file)
index 0000000..1cba485
--- /dev/null
@@ -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]
diff --git a/src/tcl/chip/atmel/at91/pmc.tcl b/src/tcl/chip/atmel/at91/pmc.tcl
new file mode 100644 (file)
index 0000000..584acb8
--- /dev/null
@@ -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
+
diff --git a/src/tcl/chip/atmel/at91/rtt.tcl b/src/tcl/chip/atmel/at91/rtt.tcl
new file mode 100644 (file)
index 0000000..56abb29
--- /dev/null
@@ -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
+}
+
diff --git a/src/tcl/chip/atmel/at91/usarts.tcl b/src/tcl/chip/atmel/at91/usarts.tcl
new file mode 100644 (file)
index 0000000..19f4ed4
--- /dev/null
@@ -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 }
+
+
+
diff --git a/src/tcl/cpu/arm/arm7tdmi.tcl b/src/tcl/cpu/arm/arm7tdmi.tcl
new file mode 100644 (file)
index 0000000..37db266
--- /dev/null
@@ -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
+
diff --git a/src/tcl/cpu/arm/arm920.tcl b/src/tcl/cpu/arm/arm920.tcl
new file mode 100644 (file)
index 0000000..f19b20b
--- /dev/null
@@ -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
+
diff --git a/src/tcl/cpu/arm/arm946.tcl b/src/tcl/cpu/arm/arm946.tcl
new file mode 100644 (file)
index 0000000..5204101
--- /dev/null
@@ -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
+
diff --git a/src/tcl/cpu/arm/arm966.tcl b/src/tcl/cpu/arm/arm966.tcl
new file mode 100644 (file)
index 0000000..83ce0f6
--- /dev/null
@@ -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
+
diff --git a/src/tcl/memory.tcl b/src/tcl/memory.tcl
new file mode 100644 (file)
index 0000000..1f90ef2
--- /dev/null
@@ -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"
+    }
+}    
+
+
diff --git a/src/tcl/mmr_helpers.tcl b/src/tcl/mmr_helpers.tcl
new file mode 100644 (file)
index 0000000..5dac48a
--- /dev/null
@@ -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 ""
+    }
+}
diff --git a/src/tcl/readable.tcl b/src/tcl/readable.tcl
new file mode 100644 (file)
index 0000000..39f43ca
--- /dev/null
@@ -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 } {
+    
\ No newline at end of file