pending_scan_result_t -> struct pending_scan_result
[openocd.git] / src / jtag / jlink.c
index 42787db1f972514296e08a529ad15a2ad2c3c1be..0b21c88610ba13eb04a4b9f932cc7e4c7153df20 100644 (file)
@@ -139,7 +139,7 @@ static jlink_jtag_t* jlink_jtag_handle;
 /***************************************************************************/
 /* External interface implementation */
 
-jtag_interface_t jlink_interface =
+struct jtag_interface jlink_interface =
 {
        .name = "jlink",
        .execute_queue = jlink_execute_queue,
@@ -299,13 +299,12 @@ static int jlink_register_commands(struct command_context_s *cmd_ctx)
                "query jlink info");
        register_command(cmd_ctx, NULL, "jlink_hw_jtag",
                &jlink_handle_jlink_hw_jtag_command, COMMAND_EXEC,
-               "set/get jlink hw jtag command version [2|3]");
+               "set/get jlink hw jtag command version [2 | 3]");
        return ERROR_OK;
 }
 
 static int jlink_init(void)
 {
-       int check_cnt;
        int i;
 
        jlink_jtag_handle = jlink_usb_open();
@@ -316,23 +315,27 @@ static int jlink_init(void)
                return ERROR_JTAG_INIT_FAILED;
        }
 
-       jlink_hw_jtag_version = 2;
-       check_cnt = 0;
-       while (check_cnt < 3)
-       {
-               if (jlink_get_version_info() == ERROR_OK)
-               {
-                       /* attempt to get status */
-                       jlink_get_status();
-                       break;
-               }
+       /*
+        *  The next three instructions were added after discovering a problem while using an oscilloscope.  For the V8
+        *      SAM-ICE dongle (and likely other j-link device variants), the reset line to the target microprocessor was found to
+        *      cycle only intermittently during emulator startup (even after encountering the downstream reset instruction later
+        *      in the code).  This was found to create two issues:  1) In general it is a bad practice to not reset a CPU to a known
+        *      state when starting an emulator and 2) something critical happens inside the dongle when it does the first read
+        *      following a new USB session.  Keeping the processor in reset during the first read collecting version information
+        *      seems to prevent errant "J-Link command EMU_CMD_VERSION failed" issues.
+        */
+
+       LOG_INFO("J-Link initialization started / target CPU reset initiated");
+       jlink_simple_command(EMU_CMD_HW_TRST0);
+       jlink_simple_command(EMU_CMD_HW_RESET0);
+       usleep(1000);
 
-               check_cnt++;
-       }
+       jlink_hw_jtag_version = 2;
 
-       if (check_cnt == 3)
+       if (jlink_get_version_info() == ERROR_OK)
        {
-               LOG_INFO("J-Link initial read failed, don't worry");
+               /* attempt to get status */
+               jlink_get_status();
        }
 
        LOG_INFO("J-Link JTAG Interface ready");
@@ -496,12 +499,10 @@ static void jlink_reset(int trst, int srst)
        {
                jlink_simple_command(EMU_CMD_HW_TRST0);
        }
+
        if (trst == 0)
        {
                jlink_simple_command(EMU_CMD_HW_TRST1);
-               jtag_sleep(5000);
-               jlink_end_state(TAP_RESET);
-               jlink_state_move();
        }
 }
 
@@ -674,18 +675,17 @@ static uint8_t tms_buffer[JLINK_TAP_BUFFER_SIZE];
 static uint8_t tdi_buffer[JLINK_TAP_BUFFER_SIZE];
 static uint8_t tdo_buffer[JLINK_TAP_BUFFER_SIZE];
 
-typedef struct
-{
+struct pending_scan_result {
        int first;      /* First bit position in tdo_buffer to read */
        int length; /* Number of bits to read */
        scan_command_t *command; /* Corresponding scan command */
        uint8_t *buffer;
-} pending_scan_result_t;
+};
 
 #define MAX_PENDING_SCAN_RESULTS 256
 
 static int pending_scan_results_length;
-static pending_scan_result_t pending_scan_results_buffer[MAX_PENDING_SCAN_RESULTS];
+static struct pending_scan_result pending_scan_results_buffer[MAX_PENDING_SCAN_RESULTS];
 
 static void jlink_tap_init(void)
 {
@@ -739,7 +739,7 @@ static void jlink_tap_append_step(int tms, int tdi)
 
 static void jlink_tap_append_scan(int length, uint8_t *buffer, scan_command_t *command)
 {
-       pending_scan_result_t *pending_scan_result =
+       struct pending_scan_result *pending_scan_result =
                &pending_scan_results_buffer[pending_scan_results_length];
        int i;
 
@@ -801,7 +801,7 @@ static int jlink_tap_execute(void)
 
        for (i = 0; i < pending_scan_results_length; i++)
        {
-               pending_scan_result_t *pending_scan_result = &pending_scan_results_buffer[i];
+               struct pending_scan_result *pending_scan_result = &pending_scan_results_buffer[i];
                uint8_t *buffer = pending_scan_result->buffer;
                int length = pending_scan_result->length;
                int first = pending_scan_result->first;
@@ -832,13 +832,37 @@ static int jlink_tap_execute(void)
        return ERROR_OK;
 }
 
+static struct usb_device* find_jlink_device(void)
+{
+       struct usb_bus *busses;
+       struct usb_bus *bus;
+       struct usb_device *dev;
+
+       usb_find_busses();
+       usb_find_devices();
+
+       busses = usb_get_busses();
+
+       /* find jlink_jtag device in usb bus */
+
+       for (bus = busses; bus; bus = bus->next)
+       {
+               for (dev = bus->devices; dev; dev = dev->next)
+               {
+                       if ((dev->descriptor.idVendor == VID) && (dev->descriptor.idProduct == PID)) {
+                               return dev;
+                       }
+               }
+       }
+
+       return NULL;
+}
+
 /*****************************************************************************/
 /* JLink USB low-level functions */
 
 static jlink_jtag_t* jlink_usb_open()
 {
-       struct usb_bus *busses;
-       struct usb_bus *bus;
        struct usb_device *dev;
 
        jlink_jtag_t *result;
@@ -846,47 +870,81 @@ static jlink_jtag_t* jlink_usb_open()
        result = (jlink_jtag_t*) malloc(sizeof(jlink_jtag_t));
 
        usb_init();
-       usb_find_busses();
-       usb_find_devices();
 
-       busses = usb_get_busses();
+       if ((dev = find_jlink_device()) == NULL) {
+               free(result);
+               return NULL;
+       }
 
-       /* find jlink_jtag device in usb bus */
+       result->usb_handle = usb_open(dev);
 
-       for (bus = busses; bus; bus = bus->next)
+       if (result->usb_handle)
        {
-               for (dev = bus->devices; dev; dev = dev->next)
+
+               /* BE ***VERY CAREFUL*** ABOUT MAKING CHANGES IN THIS AREA!!!!!!!!!!!
+                * The behavior of libusb is not completely consistent across Windows, Linux, and Mac OS X platforms.  The actions taken
+                * in the following compiler conditionals may not agree with published documentation for libusb, but were found
+                * to be necessary through trials and tribulations.  Even little tweaks can break one or more platforms, so if you do make changes
+                * test them carefully on all platforms before committing them!
+                */
+
+#if IS_WIN32 == 0
+
+               usb_reset(result->usb_handle);
+
+#if IS_DARWIN == 0
+
+               int timeout = 5;
+
+               /* reopen jlink after usb_reset
+                * on win32 this may take a second or two to re-enumerate */
+               while ((dev = find_jlink_device()) == NULL)
                {
-                       if ((dev->descriptor.idVendor == VID) && (dev->descriptor.idProduct == PID))
-                       {
-                               result->usb_handle = usb_open(dev);
+                       usleep(1000);
+                       timeout--;
+                       if (!timeout) {
+                               break;
+                       }
+               }
+
+               if (dev == NULL)
+               {
+                       free(result);
+                       return NULL;
+               }
 
-                               /* usb_set_configuration required under win32 */
-                               usb_set_configuration(result->usb_handle, dev->config[0].bConfigurationValue);
-                               usb_claim_interface(result->usb_handle, 0);
+               result->usb_handle = usb_open(dev);
+#endif
+
+#endif
+
+               if (result->usb_handle)
+               {
+                       /* usb_set_configuration required under win32 */
+                       usb_set_configuration(result->usb_handle, dev->config[0].bConfigurationValue);
+                       usb_claim_interface(result->usb_handle, 0);
 
 #if 0
-                               /*
-                                * This makes problems under Mac OS X. And is not needed
-                                * under Windows. Hopefully this will not break a linux build
-                                */
-                               usb_set_altinterface(result->usb_handle, 0);
+                       /*
+                        * This makes problems under Mac OS X. And is not needed
+                        * under Windows. Hopefully this will not break a linux build
+                        */
+                       usb_set_altinterface(result->usb_handle, 0);
 #endif
-                               struct usb_interface *iface = dev->config->interface;
-                               struct usb_interface_descriptor *desc = iface->altsetting;
-                               for (int i = 0; i < desc->bNumEndpoints; i++)
-                               {
-                                       uint8_t epnum = desc->endpoint[i].bEndpointAddress;
-                                       bool is_input = epnum & 0x80;
-                                       LOG_DEBUG("usb ep %s %02x", is_input ? "in" : "out", epnum);
-                                       if (is_input)
-                                               jlink_read_ep = epnum;
-                                       else
-                                               jlink_write_ep = epnum;
-                               }
-
-                               return result;
+                       struct usb_interface *iface = dev->config->interface;
+                       struct usb_interface_descriptor *desc = iface->altsetting;
+                       for (int i = 0; i < desc->bNumEndpoints; i++)
+                       {
+                               uint8_t epnum = desc->endpoint[i].bEndpointAddress;
+                               bool is_input = epnum & 0x80;
+                               LOG_DEBUG("usb ep %s %02x", is_input ? "in" : "out", epnum);
+                               if (is_input)
+                                       jlink_read_ep = epnum;
+                               else
+                                       jlink_write_ep = epnum;
                        }
+
+                       return result;
                }
        }
 

Linking to existing account procedure

If you already have an account and want to add another login method you MUST first sign in with your existing account and then change URL to read https://review.openocd.org/login/?link to get to this page again but this time it'll work for linking. Thank you.

SSH host keys fingerprints

1024 SHA256:YKx8b7u5ZWdcbp7/4AeXNaqElP49m6QrwfXaqQGJAOk gerrit-code-review@openocd.zylin.com (DSA)
384 SHA256:jHIbSQa4REvwCFG4cq5LBlBLxmxSqelQPem/EXIrxjk gerrit-code-review@openocd.org (ECDSA)
521 SHA256:UAOPYkU9Fjtcao0Ul/Rrlnj/OsQvt+pgdYSZ4jOYdgs gerrit-code-review@openocd.org (ECDSA)
256 SHA256:A13M5QlnozFOvTllybRZH6vm7iSt0XLxbA48yfc2yfY gerrit-code-review@openocd.org (ECDSA)
256 SHA256:spYMBqEYoAOtK7yZBrcwE8ZpYt6b68Cfh9yEVetvbXg gerrit-code-review@openocd.org (ED25519)
+--[ED25519 256]--+
|=..              |
|+o..   .         |
|*.o   . .        |
|+B . . .         |
|Bo. = o S        |
|Oo.+ + =         |
|oB=.* = . o      |
| =+=.+   + E     |
|. .=o   . o      |
+----[SHA256]-----+
2048 SHA256:0Onrb7/PHjpo6iVZ7xQX2riKN83FJ3KGU0TvI0TaFG4 gerrit-code-review@openocd.zylin.com (RSA)