diff packages/redboot/current/src/main.c @ 208:e0c0827131d1 ecos

Merge from eCos master repository on 2002-05-20-20:11:54-BST
author jlarmour
date Mon, 20 May 2002 22:19:26 +0000
parents 353a011b23b8
children d2c90368aeef
line wrap: on
line diff
--- a/packages/redboot/current/src/main.c
+++ b/packages/redboot/current/src/main.c
@@ -5,29 +5,38 @@
 //      RedBoot main routine
 //
 //==========================================================================
-//####COPYRIGHTBEGIN####
-//                                                                          
-// -------------------------------------------                              
-// The contents of this file are subject to the Red Hat eCos Public License 
-// Version 1.1 (the "License"); you may not use this file except in         
-// compliance with the License.  You may obtain a copy of the License at    
-// http://www.redhat.com/                                                   
-//                                                                          
-// Software distributed under the License is distributed on an "AS IS"      
-// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.  See the 
-// License for the specific language governing rights and limitations under 
-// the License.                                                             
-//                                                                          
-// The Original Code is eCos - Embedded Configurable Operating System,      
-// released September 30, 1998.                                             
-//                                                                          
-// The Initial Developer of the Original Code is Red Hat.                   
-// Portions created by Red Hat are                                          
+//####ECOSGPLCOPYRIGHTBEGIN####
+// -------------------------------------------
+// This file is part of eCos, the Embedded Configurable Operating System.
 // Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
-// All Rights Reserved.                                                     
-// -------------------------------------------                              
-//                                                                          
-//####COPYRIGHTEND####
+//
+// eCos is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 2 or (at your option) any later version.
+//
+// eCos is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with eCos; if not, write to the Free Software Foundation, Inc.,
+// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+//
+// As a special exception, if other files instantiate templates or use macros
+// or inline functions from this file, or you compile this file and link it
+// with other works to produce a work based on this file, this file does not
+// by itself cause the resulting work to be covered by the GNU General Public
+// License. However the source code for this file must still be made available
+// in accordance with section (3) of the GNU General Public License.
+//
+// This exception does not invalidate any other reasons why a work based on
+// this file might be covered by the GNU General Public License.
+//
+// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
+// at http://sources.redhat.com/ecos/ecos-license
+// -------------------------------------------
+//####ECOSGPLCOPYRIGHTEND####
 //==========================================================================
 //#####DESCRIPTIONBEGIN####
 //
@@ -95,11 +104,27 @@ RedBoot_cmd("x",
             "-b <location> [-l <length>] [-s] [-1|2|4]",
             do_x
     );
+#ifdef CYGBLD_BUILD_REDBOOT_WITH_CKSUM
 RedBoot_cmd("cksum", 
             "Compute a 32bit checksum [POSIX algorithm] for a range of memory", 
             "-b <location> -l <length>",
             do_cksum
     );
+#endif
+#ifdef CYGBLD_BUILD_REDBOOT_WITH_MFILL
+RedBoot_cmd("mfill", 
+            "Fill a block of memory with a pattern",
+            "-b <location> -l <length> -p <pattern> [-1|-2|-4]",
+            do_mfill
+    );
+#endif
+#ifdef CYGBLD_BUILD_REDBOOT_WITH_MCMP
+RedBoot_cmd("mcmp", 
+            "Compare two blocks of memory",
+            "-s <location> -d <location> -l <length> [-1|-2|-4]",
+            do_mcmp
+    );
+#endif
 RedBoot_cmd("cache", 
             "Manage machine caches", 
             "[ON | OFF]",
@@ -137,9 +162,6 @@ extern struct idle_tab_entry __RedBoot_I
 extern void HAL_ARCH_PROGRAM_NEW_STACK(void *fun);
 #endif
 
-#ifdef CYGSEM_REDBOOT_FLASH_ALIASES
-externC void expand_aliases(char *line, int len);
-#endif
 
 void
 do_version(int argc, char *argv[])
@@ -320,9 +342,7 @@ cyg_start(void)
             } else 
 #endif // CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS
             {
-#ifdef CYGSEM_REDBOOT_FLASH_ALIASES
                 expand_aliases(line, sizeof(line));
-#endif
 		command = (char *)&line;
                 if ((*command == '#') || (*command == '=')) {
                     // Special cases
@@ -381,33 +401,42 @@ do_caches(int argc, char *argv[])
     }
 }
 
+void
+show_help(struct cmd *cmd, struct cmd *cmd_end, char *which, char *pre)
+{
+    bool show;
+    int len = 0;
+
+    if (which) {
+        len = strlen(which);
+    }
+    while (cmd != cmd_end) {
+        show = true;
+        if (which && (strncasecmp(which, cmd->str, len) != 0)) {
+            show = false;
+        }
+        if (show) {
+            diag_printf("%s\n  %s %s %s\n", cmd->help, pre, cmd->str, cmd->usage);
+            if ((cmd->sub_cmds != (struct cmd *)0) && (which != (char *)0)) {
+                show_help(cmd->sub_cmds, cmd->sub_cmds_end, 0, cmd->str);
+            }
+        }
+        cmd++;
+    }
+}
 
 void
 do_help(int argc, char *argv[])
 {
     struct cmd *cmd;
     char *which = (char *)0;
-    bool show;
-    int len = 0;
 
     if (!scan_opts(argc, argv, 1, 0, 0, (void **)&which, OPTION_ARG_TYPE_STR, "<topic>")) {
         diag_printf("Invalid argument\n");
         return;
     }
-    if (which) {
-        len = strlen(which);
-    }
     cmd = __RedBoot_CMD_TAB__;
-    while (cmd != &__RedBoot_CMD_TAB_END__) {
-        show = true;
-        if (which && (strncasecmp(which, cmd->str, len) != 0)) {
-            show = false;
-        }
-        if (show) {
-            diag_printf("%s\n   %s %s\n", cmd->help, cmd->str, cmd->usage);
-        }
-        cmd++;
-    }
+    show_help(cmd, &__RedBoot_CMD_TAB_END__, which, "");
     return;
 }
 
@@ -419,10 +448,7 @@ do_dump(int argc, char *argv[])
     bool base_set, len_set;
     static unsigned long _base, _len;
     static char _size = 1;
-    bool srec_dump;
-    bool set_32bit = false;
-    bool set_16bit = false;
-    bool set_8bit = false;
+    bool srec_dump, set_32bit, set_16bit, set_8bit;
     int i, n, off, cksum;
     cyg_uint8 ch;
 
@@ -505,6 +531,7 @@ do_x(int argc, char *argv[])
     do_dump(argc, argv);
 }
 
+#ifdef CYGBLD_BUILD_REDBOOT_WITH_CKSUM
 void
 do_cksum(int argc, char *argv[])
 {
@@ -524,12 +551,146 @@ do_cksum(int argc, char *argv[])
         return;
     }
     if (!base_set || !len_set) {
-        diag_printf("usage: cksum -b <addr> -l <length>\n");
+	if (load_address >= (CYG_ADDRESS)ram_start &&
+	    load_address_end < (CYG_ADDRESS)ram_end &&
+	    load_address < load_address_end) {
+	    base = load_address;
+	    len = load_address_end - load_address;
+            diag_printf("Computing cksum for area %p-%p\n",
+                        base, load_address_end);
+	} else {
+	    diag_printf("usage: cksum -b <addr> -l <length>\n");
+	    return;
+	}
+    }
+    crc = posix_crc32((unsigned char *)base, len);
+    diag_printf("POSIX cksum = %lu %lu (0x%08lx 0x%08lx)\n", crc, len, crc, len);
+}
+#endif
+
+#ifdef CYGBLD_BUILD_REDBOOT_WITH_MFILL
+void
+do_mfill(int argc, char *argv[])
+{
+    // Fill a region of memory with a pattern
+    struct option_info opts[6];
+    unsigned long base, pat;
+    long len;
+    bool base_set, len_set, pat_set;
+    bool set_32bit, set_16bit, set_8bit;
+
+    init_opts(&opts[0], 'b', true, OPTION_ARG_TYPE_NUM, 
+              (void **)&base, (bool *)&base_set, "base address");
+    init_opts(&opts[1], 'l', true, OPTION_ARG_TYPE_NUM, 
+              (void **)&len, (bool *)&len_set, "length");
+    init_opts(&opts[2], 'p', true, OPTION_ARG_TYPE_NUM, 
+              (void **)&pat, (bool *)&pat_set, "pattern");
+    init_opts(&opts[3], '4', false, OPTION_ARG_TYPE_FLG,
+              (void *)&set_32bit, (bool *)0, "fill 32 bit units");
+    init_opts(&opts[4], '2', false, OPTION_ARG_TYPE_FLG,
+              (void **)&set_16bit, (bool *)0, "fill 16 bit units");
+    init_opts(&opts[5], '1', false, OPTION_ARG_TYPE_FLG,
+              (void **)&set_8bit, (bool *)0, "fill 8 bit units");
+    if (!scan_opts(argc, argv, 1, opts, 6, 0, 0, "")) {
+        return;
+    }
+    if (!base_set || !len_set) {
+        diag_printf("usage: mfill -b <addr> -l <length> [-p <pattern>] [-1|-2|-4]\n");
         return;
     }
-    crc = posix_crc32((unsigned char *)base, len);
-    diag_printf("POSIX cksum = 0x%08lx (%lu)\n", crc, crc);
+    if (!pat_set) {
+        pat = 0;
+    }
+    // No checks here    
+    if (set_8bit) {
+        // Fill 8 bits at a time
+        while ((len -= sizeof(cyg_uint8)) >= 0) {
+            *((cyg_uint8 *)base)++ = (cyg_uint8)pat;
+        }
+    } else if (set_16bit) {
+        // Fill 16 bits at a time
+        while ((len -= sizeof(cyg_uint16)) >= 0) {
+            *((cyg_uint16 *)base)++ = (cyg_uint16)pat;
+        }
+    } else {
+        // Default - 32 bits
+        while ((len -= sizeof(cyg_uint32)) >= 0) {
+            *((cyg_uint32 *)base)++ = (cyg_uint32)pat;
+        }
+    }
 }
+#endif
+
+#ifdef CYGBLD_BUILD_REDBOOT_WITH_MCMP
+void
+do_mcmp(int argc, char *argv[])
+{
+    // Fill a region of memory with a pattern
+    struct option_info opts[6];
+    unsigned long src_base, dst_base;
+    long len;
+    bool src_base_set, dst_base_set, len_set;
+    bool set_32bit, set_16bit, set_8bit;
+
+    init_opts(&opts[0], 's', true, OPTION_ARG_TYPE_NUM, 
+              (void **)&src_base, (bool *)&src_base_set, "base address");
+    init_opts(&opts[1], 'l', true, OPTION_ARG_TYPE_NUM, 
+              (void **)&len, (bool *)&len_set, "length");
+    init_opts(&opts[2], 'd', true, OPTION_ARG_TYPE_NUM, 
+              (void **)&dst_base, (bool *)&dst_base_set, "base address");
+    init_opts(&opts[3], '4', false, OPTION_ARG_TYPE_FLG,
+              (void *)&set_32bit, (bool *)0, "fill 32 bit units");
+    init_opts(&opts[4], '2', false, OPTION_ARG_TYPE_FLG,
+              (void **)&set_16bit, (bool *)0, "fill 16 bit units");
+    init_opts(&opts[5], '1', false, OPTION_ARG_TYPE_FLG,
+              (void **)&set_8bit, (bool *)0, "fill 8 bit units");
+    if (!scan_opts(argc, argv, 1, opts, 6, 0, 0, "")) {
+        return;
+    }
+    if (!src_base_set || !dst_base_set || !len_set) {
+        diag_printf("usage: mcmp -s <addr> -d <addr> -l <length> [-1|-2|-4]\n");
+        return;
+    }
+    // No checks here    
+    if (set_8bit) {
+        // Compare 8 bits at a time
+        while ((len -= sizeof(cyg_uint8)) >= 0) {
+            if (*((cyg_uint8 *)src_base)++ != *((cyg_uint8 *)dst_base)++) {
+                ((cyg_uint8 *)src_base)--;
+                ((cyg_uint8 *)dst_base)--;
+                diag_printf("Buffers don't match - %p=0x%02x, %p=0x%02x\n",
+                            src_base, *((cyg_uint8 *)src_base),
+                            dst_base, *((cyg_uint8 *)dst_base));
+                return;
+            }
+        }
+    } else if (set_16bit) {
+        // Compare 16 bits at a time
+        while ((len -= sizeof(cyg_uint16)) >= 0) {
+            if (*((cyg_uint16 *)src_base)++ != *((cyg_uint16 *)dst_base)++) {
+                ((cyg_uint16 *)src_base)--;
+                ((cyg_uint16 *)dst_base)--;
+                diag_printf("Buffers don't match - %p=0x%04x, %p=0x%04x\n",
+                            src_base, *((cyg_uint16 *)src_base),
+                            dst_base, *((cyg_uint16 *)dst_base));
+                return;
+            }
+        }
+    } else {
+        // Default - 32 bits
+        while ((len -= sizeof(cyg_uint32)) >= 0) {
+            if (*((cyg_uint32 *)src_base)++ != *((cyg_uint32 *)dst_base)++) {
+                ((cyg_uint32 *)src_base)--;
+                ((cyg_uint32 *)dst_base)--;
+                diag_printf("Buffers don't match - %p=0x%08x, %p=0x%08x\n",
+                            src_base, *((cyg_uint32 *)src_base),
+                            dst_base, *((cyg_uint32 *)dst_base));
+                return;
+            }
+        }
+    }
+}
+#endif
 
 void
 do_go(int argc, char *argv[])
@@ -601,27 +762,39 @@ do_reset(int argc, char *argv[])
 #include <flash_config.h>
 #endif
 
-void
+int
 set_console_baud_rate(int rate)
 {
     hal_virtual_comm_table_t *__chan;
-    int ret;
     static int current_rate = CYGNUM_HAL_VIRTUAL_VECTOR_CONSOLE_CHANNEL_BAUD;
+    int ret = current_rate;
 
     if (rate != current_rate) {
         __chan = CYGACC_CALL_IF_CONSOLE_PROCS();
         ret = CYGACC_COMM_IF_CONTROL(*__chan, __COMMCTL_SETBAUD, rate);
-        if (ret <= 0) {
-            diag_printf("Failed\n");
+        if (ret < 0) {
+            diag_printf("Setting console baud rate to %d failed\n", rate);
+            return ret;
         }
+        ret = current_rate;
         current_rate = rate;
     }
+    return ret;
+}
+
+static void
+_sleep(int ms)
+{
+    int i;
+    for (i = 0;  i < ms;  i++) {
+        CYGACC_CALL_IF_DELAY_US((cyg_int32)1000);
+    }
 }
 
 void
 do_baud_rate(int argc, char *argv[])
 {
-    int new_rate, ret;
+    int new_rate, ret, old_rate;
     bool new_rate_set;
     hal_virtual_comm_table_t *__chan;
     struct option_info opts[1];
@@ -636,6 +809,29 @@ do_baud_rate(int argc, char *argv[])
     }
     __chan = CYGACC_CALL_IF_CONSOLE_PROCS();
     if (new_rate_set) {
+        diag_printf("Baud rate will be changed to %d - update your settings\n", new_rate);
+        _sleep(500);  // Give serial time to flush
+        old_rate = CYGACC_COMM_IF_CONTROL(*__chan, __COMMCTL_GETBAUD);
+        ret = set_console_baud_rate(new_rate);
+        if (ret < 0) {
+            if (old_rate > 0) {
+                // Try to restore
+                set_console_baud_rate(old_rate);
+                _sleep(500);  // Give serial time to flush
+                diag_printf("\nret = %d\n", ret);
+            }
+            return;  // Couldn't set the desired rate
+        }
+        old_rate = ret;
+        // Make sure this new rate works or back off to previous value
+        // Sleep for a few seconds, then prompt to see if it works
+        _sleep(3000);  // Give serial time to flush
+        if (!verify_action_with_timeout(5000, "Baud rate changed to %d", new_rate)) {
+            _sleep(500);  // Give serial time to flush
+            set_console_baud_rate(old_rate);
+            _sleep(500);  // Give serial time to flush
+            return;
+        }
 #ifdef CYGSEM_REDBOOT_FLASH_CONFIG
         opt.type = CONFIG_INT;
         opt.enable = (char *)0;
@@ -644,7 +840,6 @@ do_baud_rate(int argc, char *argv[])
         opt.dflt = new_rate;
         flash_add_config(&opt, true);
 #endif
-        set_console_baud_rate(new_rate);
     } else {
         ret = CYGACC_COMM_IF_CONTROL(*__chan, __COMMCTL_GETBAUD);
         diag_printf("Baud rate = ");