]> git.sur5r.net Git - openocd/blobdiff - src/jtag/core.c
cmsis-dap: add initial cmsis-dap support
[openocd] / src / jtag / core.c
index 6de168e61630ec2b94e100a550d16e2c07ddd4df..24f6a511d7a0f5f8911b2d06f91f98008ea7edc4 100644 (file)
@@ -25,7 +25,7 @@
  *   You should have received a copy of the GNU General Public License     *
  *   along with this program; if not, write to the                         *
  *   Free Software Foundation, Inc.,                                       *
- *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
+ *   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.           *
  ***************************************************************************/
 
 #ifdef HAVE_CONFIG_H
@@ -33,6 +33,7 @@
 #endif
 
 #include "jtag.h"
+#include "swd.h"
 #include "interface.h"
 #include <transport/transport.h>
 
@@ -133,8 +134,6 @@ static int jtag_speed;
 
 static struct jtag_interface *jtag;
 
-const struct swd_driver *swd;
-
 /* configuration */
 struct jtag_interface *jtag_interface;
 
@@ -606,6 +605,46 @@ void jtag_add_clocks(int num_cycles)
        }
 }
 
+void swd_add_reset(int req_srst)
+{
+       if (req_srst) {
+               if (!(jtag_reset_config & RESET_HAS_SRST)) {
+                       LOG_ERROR("BUG: can't assert SRST");
+                       jtag_set_error(ERROR_FAIL);
+                       return;
+               }
+               req_srst = 1;
+       }
+
+       /* Maybe change SRST signal state */
+       if (jtag_srst != req_srst) {
+               int retval;
+
+               retval = interface_jtag_add_reset(0, req_srst);
+               if (retval != ERROR_OK)
+                       jtag_set_error(retval);
+               else
+                       retval = jtag_execute_queue();
+
+               if (retval != ERROR_OK) {
+                       LOG_ERROR("TRST/SRST error");
+                       return;
+               }
+
+               /* SRST resets everything hooked up to that signal */
+               jtag_srst = req_srst;
+               if (jtag_srst) {
+                       LOG_DEBUG("SRST line asserted");
+                       if (adapter_nsrst_assert_width)
+                               jtag_add_sleep(adapter_nsrst_assert_width * 1000);
+               } else {
+                       LOG_DEBUG("SRST line released");
+                       if (adapter_nsrst_delay)
+                               jtag_add_sleep(adapter_nsrst_delay * 1000);
+               }
+       }
+}
+
 void jtag_add_reset(int req_tlr_or_trst, int req_srst)
 {
        int trst_with_tlr = 0;
@@ -853,7 +892,7 @@ void jtag_sleep(uint32_t us)
 /* A reserved manufacturer ID is used in END_OF_CHAIN_FLAG, so we
  * know that no valid TAP will have it as an IDCODE value.
  */
-#define END_OF_CHAIN_FLAG       0x000000ff
+#define END_OF_CHAIN_FLAG       0xffffffff
 
 /* a larger IR length than we ever expect to autoprobe */
 #define JTAG_IRLEN_MAX          60
@@ -921,10 +960,10 @@ static bool jtag_idcode_is_final(uint32_t idcode)
 {
        /*
         * Some devices, such as AVR8, will output all 1's instead
-        * of TDI input value at end of chain.  Allow those values
+        * of TDI input value at end of chain. Allow those values
         * instead of failing.
         */
-       return idcode == END_OF_CHAIN_FLAG || idcode == 0xFFFFFFFF;
+       return idcode == END_OF_CHAIN_FLAG;
 }
 
 /**
@@ -958,8 +997,8 @@ static bool jtag_examine_chain_match_tap(const struct jtag_tap *tap)
        if (0 == tap->expected_ids_cnt && !idcode)
                return true;
 
-       /* optionally ignore the JTAG version field */
-       uint32_t mask = tap->ignore_version ? ~(0xff << 24) : ~0;
+       /* optionally ignore the JTAG version field - bits 28-31 of IDCODE */
+       uint32_t mask = tap->ignore_version ? ~(0xf << 28) : ~0;
 
        idcode &= mask;
 
@@ -1136,7 +1175,7 @@ static int jtag_validate_ircapture(void)
        int total_ir_length = 0;
        uint8_t *ir_test = NULL;
        struct scan_field field;
-       int val;
+       uint64_t val;
        int chain_pos = 0;
        int retval;
 
@@ -1195,8 +1234,8 @@ static int jtag_validate_ircapture(void)
                 */
                if (tap->ir_length == 0) {
                        tap->ir_length = 2;
-                       while ((val = buf_get_u32(ir_test, chain_pos, tap->ir_length + 1)) == 1
-                                       && tap->ir_length <= 32) {
+                       while ((val = buf_get_u64(ir_test, chain_pos, tap->ir_length + 1)) == 1
+                                       && tap->ir_length <= 64) {
                                tap->ir_length++;
                        }
                        LOG_WARNING("AUTO %s - use \"... -irlen %d\"",
@@ -1210,25 +1249,23 @@ static int jtag_validate_ircapture(void)
                 * this part of the JTAG spec, so their capture mask/value
                 * attributes might disable this test.
                 */
-               val = buf_get_u32(ir_test, chain_pos, tap->ir_length);
+               val = buf_get_u64(ir_test, chain_pos, tap->ir_length);
                if ((val & tap->ir_capture_mask) != tap->ir_capture_value) {
-                       LOG_ERROR("%s: IR capture error; saw 0x%0*x not 0x%0*x",
+                       LOG_ERROR("%s: IR capture error; saw 0x%0*" PRIx64 " not 0x%0*" PRIx32,
                                jtag_tap_name(tap),
-                               (tap->ir_length + 7) / tap->ir_length,
-                               val,
-                               (tap->ir_length + 7) / tap->ir_length,
-                               (unsigned) tap->ir_capture_value);
+                               (tap->ir_length + 7) / tap->ir_length, val,
+                               (tap->ir_length + 7) / tap->ir_length, tap->ir_capture_value);
 
                        retval = ERROR_JTAG_INIT_FAILED;
                        goto done;
                }
-               LOG_DEBUG("%s: IR capture 0x%0*x", jtag_tap_name(tap),
+               LOG_DEBUG("%s: IR capture 0x%0*" PRIx64, jtag_tap_name(tap),
                        (tap->ir_length + 7) / tap->ir_length, val);
                chain_pos += tap->ir_length;
        }
 
        /* verify the '11' sentinel we wrote is returned at the end */
-       val = buf_get_u32(ir_test, chain_pos, 2);
+       val = buf_get_u64(ir_test, chain_pos, 2);
        if (val != 0x3) {
                char *cbuf = buf_to_str(ir_test, total_ir_length, 16);
 
@@ -1273,13 +1310,13 @@ void jtag_tap_init(struct jtag_tap *tap)
 
        /* register the reset callback for the TAP */
        jtag_register_event_callback(&jtag_reset_callback, tap);
+       jtag_tap_add(tap);
 
        LOG_DEBUG("Created Tap: %s @ abs position %d, "
-               "irlen %d, capture: 0x%x mask: 0x%x", tap->dotted_name,
-               tap->abs_chain_position, tap->ir_length,
-               (unsigned) tap->ir_capture_value,
-               (unsigned) tap->ir_capture_mask);
-       jtag_tap_add(tap);
+                       "irlen %d, capture: 0x%x mask: 0x%x", tap->dotted_name,
+                       tap->abs_chain_position, tap->ir_length,
+                       (unsigned) tap->ir_capture_value,
+                       (unsigned) tap->ir_capture_mask);
 }
 
 void jtag_tap_free(struct jtag_tap *tap)
@@ -1287,11 +1324,11 @@ void jtag_tap_free(struct jtag_tap *tap)
        jtag_unregister_event_callback(&jtag_reset_callback, tap);
 
        /** @todo is anything missing? no memory leaks please */
-       free((void *)tap->expected);
-       free((void *)tap->expected_ids);
-       free((void *)tap->chip);
-       free((void *)tap->tapname);
-       free((void *)tap->dotted_name);
+       free(tap->expected);
+       free(tap->expected_ids);
+       free(tap->chip);
+       free(tap->tapname);
+       free(tap->dotted_name);
        free(tap);
 }
 
@@ -1330,6 +1367,11 @@ int adapter_init(struct command_context *cmd_ctx)
                        return retval;
        }
 
+       if (jtag->speed == NULL) {
+               LOG_INFO("This adapter doesn't support configurable speed");
+               return ERROR_OK;
+       }
+
        if (CLOCK_MODE_UNSELECTED == clock_mode) {
                LOG_ERROR("An adapter speed is not selected in the init script."
                        " Insert a call to adapter_khz or jtag_rclk to proceed.");
@@ -1455,6 +1497,20 @@ int adapter_quit(void)
        return ERROR_OK;
 }
 
+int swd_init_reset(struct command_context *cmd_ctx)
+{
+       int retval = adapter_init(cmd_ctx);
+       if (retval != ERROR_OK)
+               return retval;
+
+       LOG_DEBUG("Initializing with hard SRST reset");
+
+       if (jtag_reset_config & RESET_HAS_SRST)
+               swd_add_reset(1);
+       swd_add_reset(0);
+       retval = jtag_execute_queue();
+       return retval;
+}
 
 int jtag_init_reset(struct command_context *cmd_ctx)
 {
@@ -1494,7 +1550,17 @@ int jtag_init_reset(struct command_context *cmd_ctx)
                if ((jtag_reset_config & RESET_SRST_PULLS_TRST) == 0)
                        jtag_add_reset(0, 1);
        }
-       jtag_add_reset(0, 0);
+
+       /* some targets enable us to connect with srst asserted */
+       if (jtag_reset_config & RESET_CNCT_UNDER_SRST) {
+               if (jtag_reset_config & RESET_SRST_NO_GATING)
+                       jtag_add_reset(0, 1);
+               else {
+                       LOG_WARNING("\'srst_nogate\' reset_config option is required");
+                       jtag_add_reset(0, 0);
+               }
+       } else
+               jtag_add_reset(0, 0);
        retval = jtag_execute_queue();
        if (retval != ERROR_OK)
                return retval;
@@ -1517,6 +1583,14 @@ int jtag_init(struct command_context *cmd_ctx)
 
        /* guard against oddball hardware: force resets to be inactive */
        jtag_add_reset(0, 0);
+
+       /* some targets enable us to connect with srst asserted */
+       if (jtag_reset_config & RESET_CNCT_UNDER_SRST) {
+               if (jtag_reset_config & RESET_SRST_NO_GATING)
+                       jtag_add_reset(0, 1);
+               else
+                       LOG_WARNING("\'srst_nogate\' reset_config option is required");
+       }
        retval = jtag_execute_queue();
        if (retval != ERROR_OK)
                return retval;
@@ -1738,3 +1812,36 @@ bool transport_is_jtag(void)
 {
        return get_current_transport() == &jtag_transport;
 }
+
+void adapter_assert_reset(void)
+{
+       if (transport_is_jtag()) {
+               if (jtag_reset_config & RESET_SRST_PULLS_TRST)
+                       jtag_add_reset(1, 1);
+               else
+                       jtag_add_reset(0, 1);
+       } else if (transport_is_swd())
+               swd_add_reset(1);
+       else if (transport_is_cmsis_dap())
+               swd_add_reset(1);  /* FIXME */
+       else if (get_current_transport() != NULL)
+               LOG_ERROR("reset is not supported on %s",
+                       get_current_transport()->name);
+       else
+               LOG_ERROR("transport is not selected");
+}
+
+void adapter_deassert_reset(void)
+{
+       if (transport_is_jtag())
+               jtag_add_reset(0, 0);
+       else if (transport_is_swd())
+               swd_add_reset(0);
+       else if (transport_is_cmsis_dap())
+               swd_add_reset(0);  /* FIXME */
+       else if (get_current_transport() != NULL)
+               LOG_ERROR("reset is not supported on %s",
+                       get_current_transport()->name);
+       else
+               LOG_ERROR("transport is not selected");
+}