jtag: basic support for P&E Micro OSBDM (aka OSJTAG) adapter
authorJan Dakinevich <jan.dakinevich@gmail.com>
Mon, 27 Feb 2012 20:51:12 +0000 (00:51 +0400)
committerSpencer Oliver <spen@spen-soft.co.uk>
Tue, 13 Mar 2012 17:04:07 +0000 (17:04 +0000)
This driver provides support for the P&E Micro OSBDM adapter (sometimes
named as OSJTAG), mounted on the Freescale TWRK60N512 bord. Thus, it
provides a quick start when working with this board. The driver doesn't
use BDM commands, but work with OSBDM adapter using only JTAG commands.

Change-Id: Ibc3779538e666e07651d3136431e5d44344f3b07
Signed-off-by: Jan Dakinevich <jan.dakinevich@gmail.com>
Reviewed-on: http://openocd.zylin.com/492
Tested-by: jenkins
Reviewed-by: Tomas Frydrych <tf+openocd@r-finger.com>
Reviewed-by: Spencer Oliver <spen@spen-soft.co.uk>
configure.ac
src/jtag/drivers/Makefile.am
src/jtag/drivers/osbdm.c [new file with mode: 0644]
src/jtag/interfaces.c
tcl/board/twr-k60n512.cfg
tcl/interface/osbdm.cfg [new file with mode: 0644]

index ffab637cf1948c26a3e1a682ed27e31bcfbf7730..0b337129b752e8c49f1c3b07f9bc9e8d4d63eca0 100644 (file)
@@ -478,6 +478,10 @@ AC_ARG_ENABLE([stlink],
   AS_HELP_STRING([--enable-stlink], [Enable building support for the ST-Link JTAG Programmer]),
   [build_stlink=$enableval], [build_stlink=no])
 
+AC_ARG_ENABLE([osbdm],
+  AS_HELP_STRING([--enable-osbdm], [Enable building support for the OSBDM (JTAG only) Programmer]),
+  [build_osbdm=$enableval], [build_osbdm=no])
+
 AC_ARG_ENABLE([minidriver_dummy],
   AS_HELP_STRING([--enable-minidriver-dummy], [Enable the dummy minidriver.]),
   [build_minidriver_dummy=$enableval], [build_minidriver_dummy=no])
@@ -783,6 +787,12 @@ else
   AC_DEFINE(BUILD_STLINK, 0, [0 if you don't want the ST-Link JTAG driver.])
 fi
 
+if test $build_osbdm = yes; then
+  AC_DEFINE(BUILD_OSBDM, 1, [1 if you want the OSBDM driver.])
+else
+  AC_DEFINE(BUILD_OSBDM, 0, [0 if you don't want the OSBDM driver.])
+fi
+
 if test "$use_internal_jimtcl" = yes; then
   if test -f "$srcdir/jimtcl/configure.ac"; then
     AX_CONFIG_SUBDIR_OPTION([jimtcl], [--disable-install-jim])
@@ -1069,7 +1079,7 @@ fi
 
 # Check for libusb1 ported drivers.
 build_usb_ng=no
-if test $build_jlink = yes -o $build_stlink = yes; then
+if test $build_jlink = yes -o $build_stlink = yes -o $build_osbdm = yes; then
   build_usb_ng=yes
 fi
 
@@ -1118,6 +1128,7 @@ AM_CONDITIONAL([ARMJTAGEW], [test $build_armjtagew = yes])
 AM_CONDITIONAL([REMOTE_BITBANG], [test $build_remote_bitbang = yes])
 AM_CONDITIONAL([BUSPIRATE], [test $build_buspirate = yes])
 AM_CONDITIONAL([STLINK], [test $build_stlink = yes])
+AM_CONDITIONAL([OSBDM], [test $build_osbdm = yes])
 AM_CONDITIONAL([USB], [test $build_usb = yes])
 AM_CONDITIONAL([USB_NG], [test $build_usb_ng = yes])
 AM_CONDITIONAL([USE_LIBUSB0], [test $use_libusb0 = yes])
index 134323d96fc2c7d0433f8587c64d36e66fbf617b..459027f99b495dce87111215b76cc046ec196479 100644 (file)
@@ -98,6 +98,9 @@ endif
 if STLINK
 DRIVERFILES += stlink_usb.c
 endif
+if OSBDM
+DRIVERFILES += osbdm.c
+endif
 
 noinst_HEADERS = \
        bitbang.h \
diff --git a/src/jtag/drivers/osbdm.c b/src/jtag/drivers/osbdm.c
new file mode 100644 (file)
index 0000000..1875600
--- /dev/null
@@ -0,0 +1,722 @@
+/***************************************************************************
+ *   Copyright (C) 2012 by Jan Dakinevich                                  *
+ *   jan.dakinevich@gmail.com                                              *
+ *                                                                         *
+ *   This program 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 of the License, or     *
+ *   (at your option) any later version.                                   *
+ *                                                                         *
+ *   This program 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 this program; if not, write to the                         *
+ *   Free Software Foundation, Inc.,                                       *
+ *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
+ ***************************************************************************/
+#ifdef HAVE_CONFIG_H
+#      include "config.h"
+#endif
+
+#include <helper/log.h>
+#include <helper/binarybuffer.h>
+#include <helper/command.h>
+#include <jtag/interface.h>
+#include "libusb_common.h"
+
+struct sequence {
+       int len;
+       void *tms;
+       void *tdo;
+       const void *tdi;
+       struct sequence *next;
+};
+
+struct queue {
+       struct sequence *head;
+       struct sequence *tail;
+};
+
+static struct sequence *queue_add_tail(struct queue *queue, int len)
+{
+       if (len <= 0) {
+               LOG_ERROR("BUG: sequences with zero length are not allowed");
+               return NULL;
+       }
+
+       struct sequence *next;
+       next = (struct sequence *)malloc(sizeof(*next));
+       if (next) {
+               next->tms = calloc(1, DIV_ROUND_UP(len, 8));
+               if (next->tms) {
+                       next->len = len;
+                       next->tdo = NULL;
+                       next->tdi = NULL;
+                       next->next = NULL;
+
+                       if (!queue->head) {
+                               /* Queue is empty at the moment */
+                               queue->head = next;
+                       } else {
+                               /* Queue already contains at least one sequence */
+                               queue->tail->next = next;
+                       }
+
+                       queue->tail = next;
+               } else {
+                       free(next);
+                       next = NULL;
+               }
+       }
+
+       if (!next)
+               LOG_ERROR("Not enough memory");
+
+       return next;
+}
+
+static void queue_drop_head(struct queue *queue)
+{
+       struct sequence *head = queue->head->next; /* New head */
+       free(queue->head->tms);
+       free(queue->head);
+       queue->head = head;
+}
+
+static void queue_free(struct queue *queue)
+{
+       if (queue) {
+               while (queue->head)
+                       queue_drop_head(queue);
+
+               free(queue);
+       }
+}
+
+static struct queue *queue_alloc(void)
+{
+       struct queue *queue = (struct queue *)malloc(sizeof(struct queue));
+       if (queue)
+               queue->head = NULL;
+       else
+               LOG_ERROR("Not enough memory");
+
+       return queue;
+}
+
+/* Size of usb communnication buffer */
+#define OSBDM_USB_BUFSIZE 64
+/* Timeout for USB transfer, ms */
+#define OSBDM_USB_TIMEOUT 1000
+/* Write end point */
+#define OSBDM_USB_EP_WRITE 0x01
+/* Read end point */
+#define OSBDM_USB_EP_READ 0x82
+
+/* Initialize OSBDM device */
+#define OSBDM_CMD_INIT 0x11
+/* Execute special, not-BDM command. But only this
+ * command is used for JTAG operation */
+#define OSBDM_CMD_SPECIAL 0x27
+/* Execute JTAG swap (tms/tdi -> tdo) */
+#define OSBDM_CMD_SPECIAL_SWAP 0x05
+/* Reset control */
+#define OSBDM_CMD_SPECIAL_SRST 0x01
+/* Maximum bit-length in one swap */
+#define OSBDM_SWAP_MAX (((OSBDM_USB_BUFSIZE - 6) / 5) * 16)
+
+/* Lists of valid VID/PID pairs
+ */
+static const uint16_t osbdm_vid[] = { 0x15a2, 0x15a2, 0 };
+static const uint16_t osbdm_pid[] = { 0x0042, 0x0058, 0 };
+
+struct osbdm {
+       struct jtag_libusb_device_handle *devh; /* USB handle */
+       uint8_t buffer[OSBDM_USB_BUFSIZE]; /* Data to send and recieved */
+       int count; /* Count data to send and to read */
+};
+
+/* osbdm instance
+ */
+static struct osbdm osbdm_context;
+
+static int osbdm_send_and_recv(struct osbdm *osbdm)
+{
+       /* Send request */
+       int count = jtag_libusb_bulk_write(osbdm->devh, OSBDM_USB_EP_WRITE,
+               (char *)osbdm->buffer, osbdm->count, OSBDM_USB_TIMEOUT);
+
+       if (count != osbdm->count) {
+               LOG_ERROR("OSBDM communnication error: can't write");
+               return ERROR_FAIL;
+       }
+
+       /* Save command code for next checking */
+       uint8_t cmd_saved = osbdm->buffer[0];
+
+       /* Reading answer */
+       osbdm->count = jtag_libusb_bulk_read(osbdm->devh, OSBDM_USB_EP_READ,
+               (char *)osbdm->buffer, OSBDM_USB_BUFSIZE, OSBDM_USB_TIMEOUT);
+
+       /* Now perform basic checks for data sent by BDM device
+        */
+
+       if (osbdm->count < 0) {
+               LOG_ERROR("OSBDM communnication error: can't read");
+               return ERROR_FAIL;
+       }
+
+       if (osbdm->count < 2) {
+               LOG_ERROR("OSBDM communnication error: answer too small");
+               return ERROR_FAIL;
+       }
+
+       if (osbdm->count != osbdm->buffer[1])  {
+               LOG_ERROR("OSBDM communnication error: answer size mismatch");
+               return ERROR_FAIL;
+       }
+
+       if (cmd_saved != osbdm->buffer[0]) {
+               LOG_ERROR("OSBDM communnication error: answer command mismatch");
+               return ERROR_FAIL;
+       }
+
+       return ERROR_OK;
+}
+
+static int osbdm_srst(struct osbdm *osbdm, int srst)
+{
+       osbdm->count = 0;
+       (void)memset(osbdm->buffer, 0, OSBDM_USB_BUFSIZE);
+
+       /* Composing request
+        */
+       osbdm->buffer[osbdm->count++] = OSBDM_CMD_SPECIAL; /* Command */
+       osbdm->buffer[osbdm->count++] = OSBDM_CMD_SPECIAL_SRST; /* Subcommand */
+       /* Length in bytes - not used */
+       osbdm->buffer[osbdm->count++] = 0;
+       osbdm->buffer[osbdm->count++] = 0;
+       /* SRST state */
+       osbdm->buffer[osbdm->count++] = (srst ? 0 : 0x08);
+
+       /* Sending data
+        */
+       if (osbdm_send_and_recv(osbdm) != ERROR_OK)
+               return ERROR_FAIL;
+
+       return ERROR_OK;
+}
+
+static int osbdm_swap(struct osbdm *osbdm, void *tms, void *tdi,
+       void *tdo, int length)
+{
+       if (length > OSBDM_SWAP_MAX) {
+               LOG_ERROR("BUG: bit sequence too long");
+               return ERROR_FAIL;
+       }
+
+       if (length <= 0) {
+               LOG_ERROR("BUG: bit sequence equal or less to 0");
+               return ERROR_FAIL;
+       }
+
+       int swap_count = DIV_ROUND_UP(length, 16);
+
+       /* cleanup */
+       osbdm->count = 0;
+       (void)memset(osbdm->buffer, 0, OSBDM_USB_BUFSIZE);
+
+       /* Composing request
+        */
+
+       osbdm->buffer[osbdm->count++] = OSBDM_CMD_SPECIAL; /* Command */
+       osbdm->buffer[osbdm->count++] = OSBDM_CMD_SPECIAL_SWAP; /* Subcommand */
+       /* Length in bytes - not used */
+       osbdm->buffer[osbdm->count++] = 0;
+       osbdm->buffer[osbdm->count++] = 0;
+       /* Swap count */
+       osbdm->buffer[osbdm->count++] = 0;
+       osbdm->buffer[osbdm->count++] = (uint8_t)swap_count;
+
+       for (int bit_idx = 0; bit_idx < length; ) {
+               /* Bit count in swap */
+               int bit_count = length - bit_idx;
+               if (bit_count > 16)
+                       bit_count = 16;
+
+               osbdm->buffer[osbdm->count++] = (uint8_t)bit_count;
+
+               /* Copying TMS and TDI data to output buffer */
+               uint32_t tms_data = buf_get_u32(tms, bit_idx, bit_count);
+               uint32_t tdi_data = buf_get_u32(tdi, bit_idx, bit_count);
+               osbdm->buffer[osbdm->count++] = (uint8_t)(tdi_data >> 8);
+               osbdm->buffer[osbdm->count++] = (uint8_t)tdi_data;
+               osbdm->buffer[osbdm->count++] = (uint8_t)(tms_data >> 8);
+               osbdm->buffer[osbdm->count++] = (uint8_t)tms_data;
+
+               /* Next bit offset */
+               bit_idx += bit_count;
+       }
+
+       assert(osbdm->count <= OSBDM_USB_BUFSIZE);
+
+       /* Sending data
+        */
+       if (osbdm_send_and_recv(osbdm) != ERROR_OK)
+               return ERROR_FAIL;
+
+       /*      Extra check
+        */
+       if (((osbdm->buffer[2] << 8) | osbdm->buffer[3]) != 2 * swap_count) {
+               LOG_ERROR("OSBDM communnication error: not proper answer to swap command");
+               return ERROR_FAIL;
+       }
+
+       /* Copy TDO responce
+        */
+       uint8_t *buffer = (uint8_t *)osbdm->buffer + 4;
+       for (int bit_idx = 0; bit_idx < length; ) {
+               int bit_count = length - bit_idx;
+               if (bit_count > 16)
+                       bit_count = 16;
+
+               /* Prepare data */
+               uint32_t tdo_data = 0;
+               tdo_data |= (*buffer++) << 8;
+               tdo_data |= (*buffer++);
+               tdo_data >>= (16 - bit_count);
+
+               /* Copy TDO to return */
+               buf_set_u32(tdo, bit_idx, bit_count, tdo_data);
+
+               bit_idx += bit_count;
+       }
+
+       return ERROR_OK;
+}
+
+static int osbdm_flush(struct osbdm *osbdm, struct queue* queue)
+{
+       uint8_t tms[DIV_ROUND_UP(OSBDM_SWAP_MAX, 8)];
+       uint8_t tdi[DIV_ROUND_UP(OSBDM_SWAP_MAX, 8)];
+       uint8_t tdo[DIV_ROUND_UP(OSBDM_SWAP_MAX, 8)];
+
+       int seq_back_len = 0;
+
+       while (queue->head) {
+               (void)memset(tms, 0, sizeof(tms));
+               (void)memset(tdi, 0, sizeof(tdi));
+               (void)memset(tdo, 0, sizeof(tdo));
+
+               int seq_len;
+               int swap_len;
+               struct sequence *seq;
+
+               /* Copy from queue to tms/tdi streams
+                */
+               seq = queue->head;
+               seq_len = seq_back_len;
+               swap_len = 0;
+
+               while (seq && swap_len != OSBDM_SWAP_MAX) {
+                       /* Count bit for copy at this iteration.
+                        * len should fit into remaining space
+                        * in tms/tdo bitstreams
+                        */
+                       int len = seq->len - seq_len;
+                       if (len > OSBDM_SWAP_MAX - swap_len)
+                               len = OSBDM_SWAP_MAX - swap_len;
+
+                       /* Set tms data */
+                       buf_set_buf(seq->tms, seq_len, tms, swap_len, len);
+
+                       /* Set tdi data if they exists */
+                       if (seq->tdi)
+                               buf_set_buf(seq->tdi, seq_len, tdi, swap_len, len);
+
+                       swap_len += len;
+                       seq_len += len;
+                       if (seq_len == seq->len) {
+                               seq = seq->next; /* Move to next sequence */
+                               seq_len = 0;
+                       }
+               }
+
+               if (osbdm_swap(osbdm, tms, tdi, tdo, swap_len))
+                       return ERROR_FAIL;
+
+               /* Copy from tdo stream to queue
+                */
+
+               for (int swap_back_len = 0; swap_back_len < swap_len; ) {
+                       int len = queue->head->len - seq_back_len;
+                       if (len > swap_len - swap_back_len)
+                               len = swap_len - swap_back_len;
+
+                       if (queue->head->tdo)
+                               buf_set_buf(tdo, swap_back_len, queue->head->tdo, seq_back_len, len);
+
+                       swap_back_len += len;
+                       seq_back_len += len;
+                       if (seq_back_len == queue->head->len) {
+                               queue_drop_head(queue);
+                               seq_back_len = 0;
+                       }
+               }
+       }
+
+       return ERROR_OK;
+}
+
+/*     Basic operation for opening USB device */
+static int osbdm_open(struct osbdm *osbdm)
+{
+       (void)memset(osbdm, 0, sizeof(*osbdm));
+       if (jtag_libusb_open(osbdm_vid, osbdm_pid, &osbdm->devh) != ERROR_OK)
+               return ERROR_FAIL;
+
+       if (jtag_libusb_claim_interface(osbdm->devh, 0) != ERROR_OK)
+               return ERROR_FAIL;
+
+       return ERROR_OK;
+}
+
+static int osbdm_quit(void)
+{
+       jtag_libusb_close(osbdm_context.devh);
+       return ERROR_OK;
+}
+
+static int osbdm_add_pathmove(
+       struct queue *queue,
+       tap_state_t *path,
+       int num_states)
+{
+       assert(num_states <= 32);
+
+       struct sequence *next = queue_add_tail(queue, num_states);
+       if (!next) {
+               LOG_ERROR("BUG: can't allocate bit sequence");
+               return ERROR_FAIL;
+       }
+
+       uint32_t tms = 0;
+       for (int i = 0; i < num_states; i++) {
+               if (tap_state_transition(tap_get_state(), 1) == path[i]) {
+                       tms |= (1 << i);
+               } else if (tap_state_transition(tap_get_state(), 0) == path[i]) {
+                       tms &= ~(1 << i); /* This line not so needed */
+               } else {
+                       LOG_ERROR("BUG: %s -> %s isn't a valid TAP state transition",
+                               tap_state_name(tap_get_state()),
+                               tap_state_name(path[i]));
+                       return ERROR_FAIL;
+               }
+
+               tap_set_state(path[i]);
+       }
+
+       buf_set_u32(next->tms, 0, num_states, tms);
+       tap_set_end_state(tap_get_state());
+
+       return ERROR_OK;
+}
+
+static int osbdm_add_statemove(
+       struct queue *queue,
+       tap_state_t new_state,
+       int skip_first)
+{
+       int len = 0;
+       int tms;
+
+       tap_set_end_state(new_state);
+       if (tap_get_end_state() == TAP_RESET) {
+               /* Ignore current state */
+               tms = 0xff;
+               len = 5;
+       } else if (tap_get_state() != tap_get_end_state()) {
+               tms = tap_get_tms_path(tap_get_state(), new_state);
+               len = tap_get_tms_path_len(tap_get_state(), new_state);
+       }
+
+       if (len && skip_first) {
+               len--;
+               tms >>= 1;
+       }
+
+       if (len) {
+               struct sequence *next = queue_add_tail(queue, len);
+               if (!next) {
+                       LOG_ERROR("BUG: can't allocate bit sequence");
+                       return ERROR_FAIL;
+               }
+               buf_set_u32(next->tms, 0, len, tms);
+       }
+
+       tap_set_state(tap_get_end_state());
+       return ERROR_OK;
+}
+
+static int osbdm_add_stableclocks(
+       struct queue *queue,
+       int count)
+{
+       if (!tap_is_state_stable(tap_get_state())) {
+               LOG_ERROR("BUG: current state (%s) is not stable",
+                       tap_state_name(tap_get_state()));
+               return ERROR_FAIL;
+       }
+
+       struct sequence *next = queue_add_tail(queue, count);
+       if (!next) {
+               LOG_ERROR("BUG: can't allocate bit sequence");
+               return ERROR_FAIL;
+       }
+
+       if (tap_get_state() == TAP_RESET)
+               (void)memset(next->tms, 0xff, DIV_ROUND_UP(count, 8));
+
+       return ERROR_OK;
+}
+
+static int osbdm_add_tms(
+       struct queue *queue,
+       const uint8_t *tms,
+       int num_bits)
+{
+       struct sequence *next = queue_add_tail(queue, num_bits);
+       if (!next) {
+               LOG_ERROR("BUG: can't allocate bit sequence");
+               return ERROR_FAIL;
+       }
+       buf_set_buf(tms, 0, next->tms, 0, num_bits);
+
+       return ERROR_OK;
+}
+
+static int osbdm_add_scan(
+       struct queue *queue,
+       struct scan_field *fields,
+       int num_fields,
+       tap_state_t end_state,
+       bool ir_scan)
+{
+       /* Move to desired shift state */
+       if (ir_scan) {
+               if (tap_get_state() != TAP_IRSHIFT) {
+                       if (osbdm_add_statemove(queue, TAP_IRSHIFT, 0) != ERROR_OK)
+                               return ERROR_FAIL;
+               }
+       } else {
+               if (tap_get_state() != TAP_DRSHIFT) {
+                       if (osbdm_add_statemove(queue, TAP_DRSHIFT, 0) != ERROR_OK)
+                               return ERROR_FAIL;
+               }
+       }
+
+       /* Add scan */
+       tap_set_end_state(end_state);
+       for (int idx = 0; idx < num_fields; idx++) {
+               struct sequence *next = queue_add_tail(queue, fields[idx].num_bits);
+               if (!next) {
+                       LOG_ERROR("Can't allocate bit sequence");
+                       return ERROR_FAIL;
+               }
+
+               (void)memset(next->tms, 0, DIV_ROUND_UP(fields[idx].num_bits, 8));
+               next->tdi = fields[idx].out_value;
+               next->tdo = fields[idx].in_value;
+       }
+
+       /* Move to end state
+        */
+       if (tap_get_state() != tap_get_end_state()) {
+               /* Exit from IRSHIFT/DRSHIFT */
+               buf_set_u32(queue->tail->tms, queue->tail->len - 1, 1, 1);
+
+               /* Move with skip_first flag */
+               if (osbdm_add_statemove(queue, tap_get_end_state(), 1) != ERROR_OK)
+                       return ERROR_FAIL;
+       }
+
+       return ERROR_OK;
+}
+
+static int osbdm_add_runtest(
+       struct queue *queue,
+       int num_cycles,
+       tap_state_t end_state)
+{
+       if (osbdm_add_statemove(queue, TAP_IDLE, 0) != ERROR_OK)
+               return ERROR_FAIL;
+
+       if (osbdm_add_stableclocks(queue, num_cycles) != ERROR_OK)
+               return ERROR_FAIL;
+
+       if (osbdm_add_statemove(queue, end_state, 0) != ERROR_OK)
+               return ERROR_FAIL;
+
+       return ERROR_OK;
+}
+
+static int osbdm_execute_command(
+       struct osbdm *osbdm,
+       struct queue *queue,
+       struct jtag_command *cmd)
+{
+       int retval = ERROR_OK;
+
+       switch (cmd->type) {
+       case JTAG_RESET:
+               if (cmd->cmd.reset->trst) {
+                       LOG_ERROR("BUG: nTRST signal is not supported");
+                       retval = ERROR_FAIL;
+               } else {
+                       retval = osbdm_flush(osbdm, queue);
+                       if (retval == ERROR_OK)
+                               retval = osbdm_srst(osbdm, cmd->cmd.reset->srst);
+               }
+               break;
+
+       case JTAG_PATHMOVE:
+               retval = osbdm_add_pathmove(
+                       queue,
+                       cmd->cmd.pathmove->path,
+                       cmd->cmd.pathmove->num_states);
+               break;
+
+       case JTAG_TLR_RESET:
+               retval = osbdm_add_statemove(
+                       queue,
+                       cmd->cmd.statemove->end_state,
+                       0);
+               break;
+
+       case JTAG_STABLECLOCKS:
+               retval = osbdm_add_stableclocks(
+                       queue,
+                       cmd->cmd.stableclocks->num_cycles);
+               break;
+
+       case JTAG_TMS:
+               retval = osbdm_add_tms(
+                       queue,
+                       cmd->cmd.tms->bits,
+                       cmd->cmd.tms->num_bits);
+               break;
+
+       case JTAG_SCAN:
+               retval = osbdm_add_scan(
+                       queue,
+                       cmd->cmd.scan->fields,
+                       cmd->cmd.scan->num_fields,
+                       cmd->cmd.scan->end_state,
+                       cmd->cmd.scan->ir_scan);
+               break;
+
+       case JTAG_SLEEP:
+               retval = osbdm_flush(osbdm, queue);
+               if (retval == ERROR_OK)
+                       jtag_sleep(cmd->cmd.sleep->us);
+               break;
+
+       case JTAG_RUNTEST:
+               retval = osbdm_add_runtest(
+                       queue,
+                       cmd->cmd.runtest->num_cycles,
+                       cmd->cmd.runtest->end_state);
+               break;
+
+       default:
+               LOG_ERROR("BUG: unknown JTAG command type encountered");
+               retval = ERROR_FAIL;
+               break;
+       }
+
+       return retval;
+}
+
+static int osbdm_execute_queue(void)
+{
+       int retval = ERROR_OK;
+
+       struct queue *queue = queue_alloc();
+       if (!queue) {
+               LOG_ERROR("BUG: can't allocate bit queue");
+               retval = ERROR_FAIL;
+       } else {
+               struct jtag_command *cmd = jtag_command_queue;
+
+               while (retval == ERROR_OK && cmd) {
+                       retval = osbdm_execute_command(&osbdm_context, queue, cmd);
+                       cmd = cmd->next;
+               }
+
+               if (retval == ERROR_OK)
+                       retval = osbdm_flush(&osbdm_context, queue);
+
+               queue_free(queue);
+       }
+
+       if (retval != ERROR_OK) {
+               LOG_ERROR("FATAL: can't execute jtag command");
+               exit(-1);
+       }
+
+       return retval;
+}
+
+static int osbdm_init(void)
+{
+       /* Open device */
+       if (osbdm_open(&osbdm_context) != ERROR_OK) {
+               LOG_ERROR("Can't open OSBDM device");
+               return ERROR_FAIL;
+       } else {
+               /* Device successfully opened */
+               LOG_INFO("OSBDM has opened");
+       }
+
+       /* Perform initialize command */
+       osbdm_context.count = 0;
+       osbdm_context.buffer[osbdm_context.count++] = OSBDM_CMD_INIT;
+       if (osbdm_send_and_recv(&osbdm_context) != ERROR_OK)
+               return ERROR_FAIL;
+
+       return ERROR_OK;
+}
+
+static int osbdm_khz(int khz, int *speed)
+{
+       *speed = khz;
+       return ERROR_OK;
+}
+
+static int osbdm_speed(int speed)
+{
+       return ERROR_OK;
+}
+
+static int osbdm_speed_div(int speed, int *khz)
+{
+       *khz = speed;
+       return ERROR_OK;
+}
+
+struct jtag_interface osbdm_interface = {
+       .name = "osbdm",
+
+       .transports = jtag_only,
+       .execute_queue = osbdm_execute_queue,
+
+       .khz = osbdm_khz,
+       .speed = osbdm_speed,
+       .speed_div = osbdm_speed_div,
+
+       .init = osbdm_init,
+       .quit = osbdm_quit
+};
index 304dab622400f360c45d758708a17b5b9662b610..4937adbac0d0c3d7021838205f1e585467c19e6c 100644 (file)
@@ -104,6 +104,9 @@ extern struct jtag_interface remote_bitbang_interface;
 #if BUILD_STLINK == 1
 extern struct jtag_interface stlink_interface;
 #endif
+#if BUILD_OSBDM == 1
+extern struct jtag_interface osbdm_interface;
+#endif
 #endif /* standard drivers */
 
 /**
@@ -176,6 +179,9 @@ struct jtag_interface *jtag_interfaces[] = {
 #if BUILD_STLINK == 1
                &stlink_interface,
 #endif
+#if BUILD_OSBDM == 1
+               &osbdm_interface,
+#endif
 #endif /* standard drivers */
                NULL,
        };
index 00cf0423add5aac267b6a31ac3fd16ba91fdc25f..4fe35bb0326f1126e2c3fdf7a6547f3746c1dff3 100644 (file)
@@ -1,10 +1,12 @@
 #
-# Freescale KwikStik development board
+# Freescale TWRK60N512 development board
 #
 
 source [find target/k60.cfg]
 
-reset_config trst_and_srst
+$_TARGETNAME configure -event reset-init {
+       puts "-event reset-init occured"
+}
 
 #
 # Bank definition for the 'program flash' (instructions and/or data)
diff --git a/tcl/interface/osbdm.cfg b/tcl/interface/osbdm.cfg
new file mode 100644 (file)
index 0000000..4d0c79d
--- /dev/null
@@ -0,0 +1,12 @@
+#
+# P&E Micro OSBDM (aka OSJTAG) interface
+#
+# http://pemicro.com/osbdm/
+#
+interface osbdm
+reset_config srst_only
+
+#
+# OSBDM doesn't support speed control
+#
+adapter_khz 1

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)