]> git.sur5r.net Git - openocd/blobdiff - src/jtag/jtag.c
comment.
[openocd] / src / jtag / jtag.c
index 3d2fb294d62d02e5fd962431a53b36c2b16725ea..e0b008baf0702680c399dc69c0b7423569d48053 100644 (file)
@@ -156,7 +156,11 @@ static int hasKHz = 0;
 #if BUILD_PARPORT == 1
        extern jtag_interface_t parport_interface;
 #endif
-
+        
+#if BUILD_DUMMY == 1
+       extern jtag_interface_t dummy_interface;
+#endif
+       
 #if BUILD_FT2232_FTD2XX == 1
        extern jtag_interface_t ft2232_interface;
 #endif
@@ -189,6 +193,10 @@ static int hasKHz = 0;
        extern jtag_interface_t usbprog_interface;
 #endif
 
+#if BUILD_JLINK == 1
+       extern jtag_interface_t jlink_interface;
+#endif
+
 jtag_interface_t *jtag_interfaces[] = {
 #if BUILD_ECOSBOARD == 1
        &eCosBoard_interface,
@@ -196,6 +204,9 @@ jtag_interface_t *jtag_interfaces[] = {
 #if BUILD_PARPORT == 1
        &parport_interface,
 #endif
+#if BUILD_DUMMY == 1
+       &dummy_interface,
+#endif
 #if BUILD_FT2232_FTD2XX == 1
        &ft2232_interface,
 #endif
@@ -219,6 +230,9 @@ jtag_interface_t *jtag_interfaces[] = {
 #endif
 #if BUILD_USBPROG == 1
        &usbprog_interface,
+#endif
+#if BUILD_JLINK == 1
+       &jlink_interface,
 #endif
        NULL,
 };
@@ -361,6 +375,7 @@ void* cmd_queue_alloc(size_t size)
 {
        cmd_queue_page_t **p_page = &cmd_queue_pages;
        int offset;
+       u8 *t;
 
        if (*p_page)
        {
@@ -381,7 +396,7 @@ void* cmd_queue_alloc(size_t size)
        offset = (*p_page)->used;
        (*p_page)->used += size;
        
-       u8 *t=(u8 *)((*p_page)->address);
+       t=(u8 *)((*p_page)->address);
        return t + offset;
 }
 
@@ -425,9 +440,11 @@ static void jtag_prelude(enum tap_state state)
 
 void jtag_add_ir_scan(int num_fields, scan_field_t *fields, enum tap_state state)
 {
+       int retval;
+       
        jtag_prelude(state);
        
-       int retval=interface_jtag_add_ir_scan(num_fields, fields, cmd_queue_end_state);
+       retval=interface_jtag_add_ir_scan(num_fields, fields, cmd_queue_end_state);
        if (retval!=ERROR_OK)
                jtag_error=retval;
 }
@@ -511,9 +528,11 @@ int MINIDRIVER(interface_jtag_add_ir_scan)(int num_fields, scan_field_t *fields,
 
 void jtag_add_plain_ir_scan(int num_fields, scan_field_t *fields, enum tap_state state)
 {
+       int retval;
+       
        jtag_prelude(state);
        
-       int retval=interface_jtag_add_plain_ir_scan(num_fields, fields, cmd_queue_end_state);
+       retval=interface_jtag_add_plain_ir_scan(num_fields, fields, cmd_queue_end_state);
        if (retval!=ERROR_OK)
                jtag_error=retval;
 }
@@ -557,9 +576,11 @@ int MINIDRIVER(interface_jtag_add_plain_ir_scan)(int num_fields, scan_field_t *f
 
 void jtag_add_dr_scan(int num_fields, scan_field_t *fields, enum tap_state state)
 {
+       int retval;
+       
        jtag_prelude(state);
 
-       int retval=interface_jtag_add_dr_scan(num_fields, fields, cmd_queue_end_state);
+       retval=interface_jtag_add_dr_scan(num_fields, fields, cmd_queue_end_state);
        if (retval!=ERROR_OK)
                jtag_error=retval;
 }
@@ -653,8 +674,8 @@ int MINIDRIVER(interface_jtag_add_dr_scan)(int num_fields, scan_field_t *fields,
 
 void MINIDRIVER(interface_jtag_add_dr_out)(int device_num, 
                int num_fields,
-               int *num_bits,
-               u32 *value,
+               const int *num_bits,
+               const u32 *value,
                enum tap_state end_state)
 {
        int i;
@@ -742,9 +763,11 @@ void MINIDRIVER(interface_jtag_add_dr_out)(int device_num,
 
 void jtag_add_plain_dr_scan(int num_fields, scan_field_t *fields, enum tap_state state)
 {
+       int retval;
+       
        jtag_prelude(state);
 
-       int retval=interface_jtag_add_plain_dr_scan(num_fields, fields, cmd_queue_end_state);
+       retval=interface_jtag_add_plain_dr_scan(num_fields, fields, cmd_queue_end_state);
        if (retval!=ERROR_OK)
                jtag_error=retval;
 }
@@ -785,17 +808,17 @@ int MINIDRIVER(interface_jtag_add_plain_dr_scan)(int num_fields, scan_field_t *f
        return ERROR_OK;
 }
 
-void jtag_add_tms()
+void jtag_add_tlr()
 {
        jtag_prelude(TAP_TLR);
        
        int retval;
-       retval=interface_jtag_add_tms();
+       retval=interface_jtag_add_tlr();
        if (retval!=ERROR_OK)
                jtag_error=retval;
 }
 
-int MINIDRIVER(interface_jtag_add_tms)()
+int MINIDRIVER(interface_jtag_add_tlr)()
 {
        enum tap_state state = TAP_TLR;
        jtag_command_t **last_cmd = jtag_get_last_command_p();
@@ -815,6 +838,10 @@ int MINIDRIVER(interface_jtag_add_tms)()
 
 void jtag_add_pathmove(int num_states, enum tap_state *path)
 {
+       enum tap_state cur_state=cmd_queue_cur_state;
+       int i;
+       int retval;
+
        /* the last state has to be a stable state */
        if (tap_move_map[path[num_states - 1]] == -1)
        {
@@ -822,8 +849,6 @@ void jtag_add_pathmove(int num_states, enum tap_state *path)
                exit(-1);
        }
 
-       enum tap_state cur_state=cmd_queue_cur_state;
-       int i;
        for (i=0; i<num_states; i++)
        {
                if ((tap_transitions[cur_state].low != path[i])&&
@@ -839,7 +864,7 @@ void jtag_add_pathmove(int num_states, enum tap_state *path)
        
        cmd_queue_cur_state = path[num_states - 1];
 
-       int retval=interface_jtag_add_pathmove(num_states, path);
+       retval=interface_jtag_add_pathmove(num_states, path);
        if (retval!=ERROR_OK)
                jtag_error=retval;
 }
@@ -885,22 +910,41 @@ int MINIDRIVER(interface_jtag_add_runtest)(int num_cycles, enum tap_state state)
 
 void jtag_add_runtest(int num_cycles, enum tap_state state)
 {
+       int retval;
+       
        jtag_prelude(state);
        
        /* executed by sw or hw fifo */
-       int retval=interface_jtag_add_runtest(num_cycles, cmd_queue_end_state);
+       retval=interface_jtag_add_runtest(num_cycles, cmd_queue_end_state);
        if (retval!=ERROR_OK)
                jtag_error=retval;
 }
 
-void jtag_add_reset(int req_tms_or_trst, int req_srst)
+void jtag_add_reset(int req_tlr_or_trst, int req_srst)
 {
-       int trst_with_tms = 0;
+       int trst_with_tlr = 0;
        int retval;
        
+       /* FIX!!! there are *many* different cases here. A better
+        * approach is needed for legal combinations of transitions...
+       */
+       if ((jtag_reset_config & RESET_HAS_SRST)&&
+                       (jtag_reset_config & RESET_HAS_TRST)&& 
+                       ((jtag_reset_config & RESET_SRST_PULLS_TRST)==0))
+       {
+               if (((req_tlr_or_trst&&!jtag_trst)||
+                               (!req_tlr_or_trst&&jtag_trst))&&
+                               ((req_srst&&!jtag_srst)||
+                                               (!req_srst&&jtag_srst)))
+               {
+                       // FIX!!! srst_pulls_trst allows 1,1 => 0,0 transition....
+                       //LOG_ERROR("BUG: transition of req_tlr_or_trst and req_srst in the same jtag_add_reset() call is undefined");
+               }
+       }
+       
        /* Make sure that jtag_reset_config allows the requested reset */
        /* if SRST pulls TRST, we can't fulfill srst == 1 with trst == 0 */
-       if (((jtag_reset_config & RESET_SRST_PULLS_TRST) && (req_srst == 1)) && (!req_tms_or_trst))
+       if (((jtag_reset_config & RESET_SRST_PULLS_TRST) && (req_srst == 1)) && (!req_tlr_or_trst))
        {
                LOG_ERROR("BUG: requested reset would assert trst");
                jtag_error=ERROR_FAIL;
@@ -908,9 +952,9 @@ void jtag_add_reset(int req_tms_or_trst, int req_srst)
        }
                
        /* if TRST pulls SRST, we reset with TAP T-L-R */
-       if (((jtag_reset_config & RESET_TRST_PULLS_SRST) && (req_tms_or_trst)) && (req_srst == 0))
+       if (((jtag_reset_config & RESET_TRST_PULLS_SRST) && (req_tlr_or_trst)) && (req_srst == 0))
        {
-               trst_with_tms = 1;
+               trst_with_tlr = 1;
        }
        
        if (req_srst && !(jtag_reset_config & RESET_HAS_SRST))
@@ -920,14 +964,14 @@ void jtag_add_reset(int req_tms_or_trst, int req_srst)
                return;
        }
        
-       if (req_tms_or_trst)
+       if (req_tlr_or_trst)
        {
-               if (!trst_with_tms && (jtag_reset_config & RESET_HAS_TRST))
+               if (!trst_with_tlr && (jtag_reset_config & RESET_HAS_TRST))
                {
                        jtag_trst = 1;
                } else
                {
-                       trst_with_tms = 1;
+                       trst_with_tlr = 1;
                }
        } else
        {
@@ -954,11 +998,11 @@ void jtag_add_reset(int req_tms_or_trst, int req_srst)
                        jtag_add_sleep(jtag_nsrst_delay * 1000);
        }
        
-       if (trst_with_tms)
+       if (trst_with_tlr)
        {
                LOG_DEBUG("JTAG reset with tms instead of TRST");
                jtag_add_end_state(TAP_TLR);
-               jtag_add_tms();
+               jtag_add_tlr();
                jtag_call_event_callbacks(JTAG_TRST_ASSERTED);
                return;
        }
@@ -1427,9 +1471,9 @@ int jtag_register_commands(struct command_context_s *cmd_ctx)
        register_command(cmd_ctx, NULL, "reset_config", handle_reset_config_command,
                COMMAND_CONFIG, NULL);
        register_command(cmd_ctx, NULL, "jtag_nsrst_delay", handle_jtag_nsrst_delay_command,
-               COMMAND_CONFIG, NULL);
+               COMMAND_ANY, "jtag_nsrst_delay <ms> - delay after deasserting srst in ms");
        register_command(cmd_ctx, NULL, "jtag_ntrst_delay", handle_jtag_ntrst_delay_command,
-               COMMAND_CONFIG, NULL);
+               COMMAND_ANY, "jtag_ntrst_delay <ms> - delay after deasserting trst in ms");
                
        register_command(cmd_ctx, NULL, "scan_chain", handle_scan_chain_command,
                COMMAND_EXEC, "print current scan chain configuration");
@@ -1452,6 +1496,9 @@ int jtag_register_commands(struct command_context_s *cmd_ctx)
 
 int jtag_interface_init(struct command_context_s *cmd_ctx)
 {
+       if (jtag)
+               return ERROR_OK;
+       
        if (!jtag_interface)
        {
                /* nothing was previously specified by "interface" command */
@@ -1461,10 +1508,8 @@ int jtag_interface_init(struct command_context_s *cmd_ctx)
        if(hasKHz)
        {
                /*stay on "reset speed"*/
-               if (jtag_interface->khz(speed1, &speed1) == ERROR_OK)
-                       jtag_speed = speed1;
-               if (jtag_interface->khz(speed2, &speed2) == ERROR_OK)
-                       jtag_speed_post_reset = speed2;
+               jtag_interface->khz(speed1, &jtag_speed);
+               jtag_interface->khz(speed2, &jtag_speed_post_reset);
                hasKHz = 0;
        }
 
@@ -1477,16 +1522,14 @@ int jtag_interface_init(struct command_context_s *cmd_ctx)
        return ERROR_OK;
 }
 
-int jtag_init(struct command_context_s *cmd_ctx)
+static int jtag_init_inner(struct command_context_s *cmd_ctx)
 {
        int validate_tries = 0;
        jtag_device_t *device;
+       int retval;
 
-       LOG_DEBUG("-");
+       LOG_DEBUG("Init JTAG chain");
        
-       if (!jtag && jtag_interface_init(cmd_ctx) != ERROR_OK)
-               return ERROR_JTAG_INIT_FAILED;
-
        device = jtag_devices;
        jtag_ir_scan_size = 0;
        jtag_num_devices = 0;
@@ -1497,8 +1540,9 @@ int jtag_init(struct command_context_s *cmd_ctx)
                device = device->next;
        }
        
-       jtag_add_tms();
-       jtag_execute_queue();
+       jtag_add_tlr();
+       if ((retval=jtag_execute_queue())!=ERROR_OK)
+               return retval;
 
        /* examine chain first, as this could discover the real chain layout */
        if (jtag_examine_chain() != ERROR_OK)
@@ -1521,6 +1565,63 @@ int jtag_init(struct command_context_s *cmd_ctx)
        return ERROR_OK;
 }
 
+int jtag_init_reset(struct command_context_s *cmd_ctx)
+{
+       int retval;
+
+       if ((retval=jtag_interface_init(cmd_ctx)) != ERROR_OK)
+               return retval;
+
+       LOG_DEBUG("Trying to bring the JTAG controller to life by asserting TRST / tms");
+
+       /* Reset can happen after a power cycle.
+        * 
+        * Ideally we would only assert TRST or run tms before the target reset.
+        * 
+        * However w/srst_pulls_trst, trst is asserted together with the target
+        * reset whether we want it or not.
+        * 
+        * NB! Some targets have JTAG circuitry disabled until a 
+        * trst & srst has been asserted.
+        * 
+        * NB! here we assume nsrst/ntrst delay are sufficient!
+        * 
+        * NB! order matters!!!! srst *can* disconnect JTAG circuitry
+        * 
+        */
+       jtag_add_reset(1, 0); /* TMS or TRST */
+       if (jtag_reset_config & RESET_HAS_SRST)
+       {
+               jtag_add_reset(1, 1);
+               if ((jtag_reset_config & RESET_SRST_PULLS_TRST)==0)
+                       jtag_add_reset(0, 1);
+       }
+       jtag_add_reset(0, 0);
+       if ((retval = jtag_execute_queue()) != ERROR_OK)
+               return retval;
+       
+       /* Check that we can communication on the JTAG chain + eventually we want to
+        * be able to perform enumeration only after OpenOCD has started 
+        * telnet and GDB server
+        * 
+        * That would allow users to more easily perform any magic they need to before
+        * reset happens.
+        */
+       return jtag_init_inner(cmd_ctx);
+}
+
+int jtag_init(struct command_context_s *cmd_ctx)
+{
+       int retval;
+       if ((retval=jtag_interface_init(cmd_ctx)) != ERROR_OK)
+               return retval;
+       if (jtag_init_inner(cmd_ctx)==ERROR_OK)
+       {
+               return ERROR_OK;
+       }
+       return jtag_init_reset(cmd_ctx);
+}
+
 
 static int default_khz(int khz, int *jtag_speed)
 {
@@ -1528,6 +1629,11 @@ static int default_khz(int khz, int *jtag_speed)
        return ERROR_FAIL;
 }
 
+static int default_speed_div(int speed, int *khz)
+{
+       return ERROR_FAIL;      
+}
+
 int handle_interface_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
 {
        int i;
@@ -1558,6 +1664,10 @@ int handle_interface_command(struct command_context_s *cmd_ctx, char *cmd, char
                        {
                                jtag_interface->khz = default_khz;
                        }
+                       if (jtag_interface->speed_div == NULL)
+                       {
+                               jtag_interface->speed_div = default_speed_div;
+                       }
                        return ERROR_OK;
                }
        }
@@ -1754,7 +1864,11 @@ int handle_jtag_speed_command(struct command_context_s *cmd_ctx, char *cmd, char
                /* this command can be called during CONFIG, 
                 * in which case jtag isn't initialized */
                if (jtag)
+               {
+                       jtag->speed_div(jtag_speed, &speed1);
+                       jtag->speed_div(jtag_speed_post_reset, &speed2);
                        jtag->speed(cur_speed);
+               }
        }               
        command_print(cmd_ctx, "jtag_speed: %d, %d", jtag_speed, jtag_speed_post_reset);
        
@@ -1765,34 +1879,45 @@ int handle_jtag_khz_command(struct command_context_s *cmd_ctx, char *cmd, char *
 {
        LOG_DEBUG("handle jtag khz");
        
-       if ((argc<1) || (argc>2))
+       if (argc>2)
                return ERROR_COMMAND_SYNTAX_ERROR;
 
-       if (argc >= 1)
-               speed1 = speed2 = strtoul(args[0], NULL, 0);
-       if (argc == 2)
-               speed2 = strtoul(args[1], NULL, 0);
-
-       if (jtag != NULL)
+       if(argc != 0)
        {
-               int cur_speed = 0;
-               LOG_DEBUG("have interface set up");
-               int speed_div1, speed_div2;
-               if (jtag->khz(speed1, &speed_div1)!=ERROR_OK)
-                       return ERROR_OK;
-               if (jtag->khz(speed2, &speed_div2)!=ERROR_OK)
-                       return ERROR_OK;
-
+               
                if (argc >= 1)
-                       cur_speed = jtag_speed = jtag_speed_post_reset = speed_div1;
+                       speed1 = speed2 = strtoul(args[0], NULL, 0);
                if (argc == 2)
-                       cur_speed = jtag_speed_post_reset = speed_div2;
-
-               jtag->speed(cur_speed);
-       } else
-       {
-               hasKHz = 1;
+                       speed2 = strtoul(args[1], NULL, 0);
+       
+               if (jtag != NULL)
+               {
+                       int cur_speed = 0;
+                       LOG_DEBUG("have interface set up");
+                       int speed_div1, speed_div2;
+                       if (jtag->khz(speed1, &speed_div1)!=ERROR_OK)
+                       {
+                               speed1 = speed2 = 0;
+                               return ERROR_OK;
+                       }
+                       if (jtag->khz(speed2, &speed_div2)!=ERROR_OK)
+                       {
+                               speed1 = speed2 = 0;
+                               return ERROR_OK;
+                       }
+       
+                       if (argc >= 1)
+                               cur_speed = jtag_speed = jtag_speed_post_reset = speed_div1;
+                       if (argc == 2)
+                               cur_speed = jtag_speed_post_reset = speed_div2;
+       
+                       jtag->speed(cur_speed);
+               } else
+               {
+                       hasKHz = 1;
+               }
        }
+       command_print(cmd_ctx, "jtag_khz: %d, %d", speed1, speed2);
        
        return ERROR_OK;
 }
@@ -1850,7 +1975,7 @@ int handle_jtag_reset_command(struct command_context_s *cmd_ctx, char *cmd, char
                return ERROR_COMMAND_SYNTAX_ERROR;
        }
 
-       if (!jtag && jtag_interface_init(cmd_ctx) != ERROR_OK)
+       if (jtag_interface_init(cmd_ctx) != ERROR_OK)
                return ERROR_JTAG_INIT_FAILED;
 
        jtag_add_reset(trst, srst);