]> git.sur5r.net Git - openocd/commitdiff
- the jtag chain is examined and validated after GDB & telnet servers
authoroharboe <oharboe@b42882b7-edfa-0310-969c-e2dbd0fdcd60>
Mon, 10 Mar 2008 14:07:28 +0000 (14:07 +0000)
committeroharboe <oharboe@b42882b7-edfa-0310-969c-e2dbd0fdcd60>
Mon, 10 Mar 2008 14:07:28 +0000 (14:07 +0000)
 are up and running. The examination and validation is actually
 "optional" from the point of view of GDB + telnet servers.
 Multiple targets should work fine with this.
- jtag_speed is dropped(divisor is increased), if jtag examination and
 validation fails.
- the chain is validated 10x to catch the worst jtag_speed offences
- added LOG_SILENT that can be used to shut up log. Feeble
 ersatz for try+catch.
- GDB register packets are now always replied in order to make sure
 that GDB connect works. If the target is not halted, then these
 packets contain dummy values.

git-svn-id: svn://svn.berlios.de/openocd/trunk@483 b42882b7-edfa-0310-969c-e2dbd0fdcd60

src/jtag/Makefile.am
src/jtag/jtag.c
src/target/arm11.c
src/target/armv4_5.c
src/target/armv7m.c
src/target/target.h

index a35e3f3f17b0e0b645acda77aac034fc76e8a0aa..04e50ffd23fa1e6175ffddcce951255107d3c310 100644 (file)
@@ -9,7 +9,7 @@ else
 FTD2XXINC =
 endif
 
-INCLUDES = -I$(top_srcdir)/src/helper $(FTD2XXINC) $(all_includes)
+INCLUDES = -I$(top_srcdir)/src/helper $(FTD2XXINC) $(all_includes) -I$(top_srcdir)/src/target 
 METASOURCES = AUTO
 noinst_LIBRARIES = libjtag.a
 
index 430a6ff87b2071ba154f9326a628824bd698f475..48cd0595646eafdebcb545da92105388f7079464 100644 (file)
@@ -28,6 +28,7 @@
 #include "command.h"
 #include "log.h"
 #include "interpreter.h"
+#include "target.h"
 
 #include "stdlib.h"
 #include "string.h"
@@ -1327,11 +1328,10 @@ void jtag_sleep(u32 us)
 
 /* Try to examine chain layout according to IEEE 1149.1 ยง12
  */
-int jtag_examine_chain()
+int jtag_examine_chain(u8 idcode_buffer[JTAG_MAX_CHAIN_SIZE * 4] )
 {
        jtag_device_t *device = jtag_devices;
        scan_field_t field;
-       u8 idcode_buffer[JTAG_MAX_CHAIN_SIZE * 4];
        int i;
        int bit_count;
        int device_count = 0;
@@ -1533,9 +1533,36 @@ int jtag_interface_init(struct command_context_s *cmd_ctx)
        return ERROR_OK;
 }
 
+extern int jtag_init_chain(struct command_context_s *cmd_ctx);
+
+static int jtag_sense_handler(void *priv)
+{
+       struct command_context_s *cmd_ctx;
+       cmd_ctx=(struct command_context_s *)priv;
+
+       static int scan_complete = 0;
+       if (!scan_complete)
+       {
+               if (jtag_init_chain(cmd_ctx)==ERROR_OK)
+               {
+                       scan_complete = 1;
+               }
+               return ERROR_OK;
+       }
+       
+       return ERROR_OK;
+}
+
+/* OpenOCD will start telnet/gdb servers before the JTAG chain has
+ * been enumerated. This is to allow e.g. GDB init script to
+ * run monitor commands to initialize the target so jtag_init_chain()
+ * will succeed.
+ * 
+ * A timer callback is added where sensing is retried once every second
+ * until it succeeds.
+ */
 int jtag_init(struct command_context_s *cmd_ctx)
 {
-       int validate_tries = 0;
        jtag_device_t *device;
 
        DEBUG("-");
@@ -1556,24 +1583,76 @@ int jtag_init(struct command_context_s *cmd_ctx)
        jtag_add_statemove(TAP_TLR);
        jtag_execute_queue();
 
+       target_register_timer_callback(jtag_sense_handler, 1000, 1, cmd_ctx);
+       
+       return ERROR_OK;
+       }
+       
+static int jtag_test_chain(u8 idcode_buffer[JTAG_MAX_CHAIN_SIZE * 4])
+{
+       jtag_add_statemove(TAP_TLR);
+       jtag_execute_queue();
+
        /* examine chain first, as this could discover the real chain layout */
-       if (jtag_examine_chain() != ERROR_OK)
+       if (jtag_examine_chain(idcode_buffer)!=ERROR_OK)
        {
-               ERROR("trying to validate configured JTAG chain anyway...");
+               WARNING("trying to validate configured JTAG chain anyway...");
        }
        
-       while (jtag_validate_chain() != ERROR_OK)
-       {
-               validate_tries++;
-               if (validate_tries > 5)
+       return jtag_validate_chain();
+}
+
+/* Unless we can do this successfully 10 times, we're not
+ * satisfied with the quality of the JTAG communication.
+ * 
+ * Since we're continously repeating this operation, be a bit
+ * wary of filling the log with megabytes of data.
+ * 
+ * Keep increasing the jtag_divisor until we've got a solid
+ * result.
+ */
+int jtag_init_chain(struct command_context_s *cmd_ctx)
+{
+       int i, j;
+       int retval;
+       for (i=jtag_speed; i<64; i++)
+               {
+               u8 idcode_buffer[JTAG_MAX_CHAIN_SIZE * 4];
+               jtag_speed=i;
+               if ((retval=jtag->speed(jtag_speed))!=ERROR_OK)
+                       continue;
+               for (j=0; j<10; j++)
                {
-                       ERROR("Could not validate JTAG chain, exit");
-                       return ERROR_JTAG_INVALID_INTERFACE;
+                       u8 idcode_current[JTAG_MAX_CHAIN_SIZE * 4];
+                       enum log_levels save_log_level=debug_level;
+                       /* avoid spamming log */
+                       debug_level=LOG_SILENT;
+                       retval=jtag_test_chain(idcode_current);
+                       if (retval==ERROR_OK)
+                       {
+                               if (j==0)
+                               {
+                                       memcpy(idcode_buffer, idcode_current, sizeof(idcode_buffer));
+                               } else
+                               {
+                                       retval=(memcmp(idcode_buffer, idcode_current, sizeof(idcode_buffer))==0)?ERROR_OK:ERROR_JTAG_INIT_FAILED;
+                               }
+                       }
+                       debug_level = save_log_level;
+                       if (retval!=ERROR_OK)
+                       {
+                               break;
+                       }
                }
-               usleep(10000);
+               if (retval==ERROR_OK)
+               {
+                       /* Print out result  */
+                       INFO("Succeeded jtag chain test jtag_speed=%d", jtag_speed);
+                       return jtag_test_chain(idcode_buffer);
+               }
+               DEBUG("Failed jtag chain test, dropping clock rate. Trying jtag_speed=%d\n", i+1);
        }
-
-       return ERROR_OK;
+       return retval;
 }
 
 int handle_interface_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
@@ -1778,12 +1857,11 @@ int handle_jtag_speed_command(struct command_context_s *cmd_ctx, char *cmd, char
 
        if (argc > 0)
        {
+               jtag_speed = strtoul(args[0], NULL, 0);
                /* this command can be called during CONFIG, 
                 * in which case jtag isn't initialized */
                if (jtag)
-                       jtag->speed(strtoul(args[0], NULL, 0));
-               else
-                       jtag_speed = strtoul(args[0], NULL, 0);
+                       jtag->speed(jtag_speed);
        }
 
        return ERROR_OK;
index a197945fa913c9725d767cda47871fa83e2a3b41..890b836bb29015916feff62da9db80d676b029f1 100644 (file)
@@ -1040,12 +1040,6 @@ int arm11_get_gdb_reg_list(struct target_s *target, struct reg_s **reg_list[], i
 
     arm11_common_t * arm11 = target->arch_info;
 
-    if (target->state != TARGET_HALTED)
-    {
-       WARNING("target was not halted");
-       return ERROR_TARGET_NOT_HALTED;
-    }
-       
     *reg_list_size  = ARM11_GDB_REGISTER_COUNT;
     *reg_list      = malloc(sizeof(reg_t*) * ARM11_GDB_REGISTER_COUNT);
 
index 82e65c78906d4a781e06242fb60d5b54e0bed6ac..ff5f4735c9adec9fc22c2fcf7acea40a78326620 100644 (file)
@@ -474,12 +474,6 @@ int armv4_5_get_gdb_reg_list(target_t *target, reg_t **reg_list[], int *reg_list
        armv4_5_common_t *armv4_5 = target->arch_info;
        int i;
        
-       if (target->state != TARGET_HALTED)
-       {
-               ERROR("Target not halted");
-               return ERROR_TARGET_NOT_HALTED;
-       }
-       
        *reg_list_size = 26;
        *reg_list = malloc(sizeof(reg_t*) * (*reg_list_size));
        
index 6ee5903ac8074628374163226e802032f5d88fa0..f1f0ac967a0d91f90f3c8cd0dbddd4e2a2f7428a 100644 (file)
@@ -321,12 +321,6 @@ int armv7m_get_gdb_reg_list(target_t *target, reg_t **reg_list[], int *reg_list_
        armv7m_common_t *armv7m = target->arch_info;
        int i;
        
-       if (target->state != TARGET_HALTED)
-       {
-               ERROR("Target not halted");
-               return ERROR_TARGET_NOT_HALTED;
-       }
-       
        *reg_list_size = 26;
        *reg_list = malloc(sizeof(reg_t*) * (*reg_list_size));
        
index 8d70e77ebc9f3ac1cb2263dd742676804e74bfca..e028665043909984b886197ca093693b8d0b80b3 100644 (file)
@@ -127,7 +127,15 @@ typedef struct target_type_s
        int (*soft_reset_halt)(struct target_s *target);
        int (*prepare_reset_halt)(struct target_s *target);
        
-       /* target register access for gdb */
+       /* target register access for gdb.
+        * 
+        * Danger! this function will succeed even if the target is running
+        * and return a register list with dummy values.
+        * 
+        * The reason is that GDB connection will fail without a valid register
+        * list, however it is after GDB is connected that monitor commands can
+        * be run to properly initialize the target
+        */
        int (*get_gdb_reg_list)(struct target_s *target, struct reg_s **reg_list[], int *reg_list_size);
        
        /* target memory access