ST-Link USB support added. Change-Id: I2812646f2895b1529ff3f911edbdce7fa0051c8f Signed-off-by: Mathias K <kesmtp@freenet.de> Reviewed-on: http://openocd.zylin.com/261 Tested-by: jenkins Reviewed-by: Spencer Oliver <spen@spen-soft.co.uk>tags/v0.6.0-rc1
@@ -474,6 +474,10 @@ AC_ARG_ENABLE([buspirate], | |||
AS_HELP_STRING([--enable-buspirate], [Enable building support for the Buspirate]), | |||
[build_buspirate=$enableval], [build_buspirate=no]) | |||
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([minidriver_dummy], | |||
AS_HELP_STRING([--enable-minidriver-dummy], [Enable the dummy minidriver.]), | |||
[build_minidriver_dummy=$enableval], [build_minidriver_dummy=no]) | |||
@@ -773,6 +777,12 @@ else | |||
AC_DEFINE([BUILD_BUSPIRATE], [0], [0 if you don't want the Buspirate JTAG driver.]) | |||
fi | |||
if test $build_stlink = yes; then | |||
AC_DEFINE(BUILD_STLINK, 1, [1 if you want the ST-Link JTAG driver.]) | |||
else | |||
AC_DEFINE(BUILD_STLINK, 0, [0 if you don't want the ST-Link JTAG 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]) | |||
@@ -1059,7 +1069,7 @@ fi | |||
# Check for libusb1 ported drivers. | |||
build_usb_ng=no | |||
if test $build_jlink = yes; then | |||
if test $build_jlink = yes -o $build_stlink = yes; then | |||
build_usb_ng=yes | |||
fi | |||
@@ -1107,6 +1117,7 @@ AM_CONDITIONAL([ULINK], [test $build_ulink = yes]) | |||
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([USB], [test $build_usb = yes]) | |||
AM_CONDITIONAL([USB_NG], [test $build_usb_ng = yes]) | |||
AM_CONDITIONAL([USE_LIBUSB0], [test $use_libusb0 = yes]) | |||
@@ -1219,6 +1230,7 @@ AC_CONFIG_FILES([ | |||
src/helper/Makefile | |||
src/jtag/Makefile | |||
src/jtag/drivers/Makefile | |||
src/jtag/stlink/Makefile | |||
src/transport/Makefile | |||
src/xsvf/Makefile | |||
src/svf/Makefile | |||
@@ -39,9 +39,15 @@ else | |||
MINIDRIVER_IMP_DIR = $(srcdir)/drivers | |||
DRIVERFILES += commands.c | |||
if STLINK | |||
SUBDIRS += stlink | |||
libjtag_la_LIBADD += $(top_builddir)/src/jtag/stlink/libocdstlink.la | |||
endif | |||
SUBDIRS += drivers | |||
libjtag_la_LIBADD += $(top_builddir)/src/jtag/drivers/libocdjtagdrivers.la | |||
endif | |||
# endif // MINIDRIVER | |||
@@ -94,6 +94,9 @@ endif | |||
if REMOTE_BITBANG | |||
DRIVERFILES += remote_bitbang.c | |||
endif | |||
if STLINK | |||
DRIVERFILES += stlink_usb.c | |||
endif | |||
noinst_HEADERS = \ | |||
bitbang.h \ | |||
@@ -103,6 +106,7 @@ noinst_HEADERS = \ | |||
rlink_dtc_cmd.h \ | |||
rlink_ep1_cmd.h \ | |||
rlink_st7.h \ | |||
usb_common.h | |||
usb_common.h \ | |||
stlink_usb.h | |||
MAINTAINERCLEANFILES = $(srcdir)/Makefile.in |
@@ -0,0 +1,658 @@ | |||
/*************************************************************************** | |||
* Copyright (C) 2011 by Mathias Kuester * | |||
* Mathias Kuester <kesmtp@freenet.de> * | |||
* * | |||
* This code is based on https://github.com/texane/stlink * | |||
* * | |||
* 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 | |||
/* project specific includes */ | |||
#include <helper/binarybuffer.h> | |||
#include <jtag/interface.h> | |||
#include <jtag/stlink/stlink_layout.h> | |||
#include <jtag/stlink/stlink_interface.h> | |||
#include <target/target.h> | |||
#include "libusb_common.h" | |||
#define ENDPOINT_IN 0x80 | |||
#define ENDPOINT_OUT 0x00 | |||
#define STLINK_RX_EP (1|ENDPOINT_IN) | |||
#define STLINK_TX_EP (2|ENDPOINT_OUT) | |||
#define STLINK_CMD_SIZE (16) | |||
#define STLINK_TX_SIZE (4*128) | |||
#define STLINK_RX_SIZE (4*128) | |||
/** */ | |||
struct stlink_usb_handle_s { | |||
/** */ | |||
struct jtag_libusb_device_handle *fd; | |||
/** */ | |||
struct libusb_transfer *trans; | |||
/** */ | |||
uint8_t txbuf[STLINK_TX_SIZE]; | |||
/** */ | |||
uint8_t rxbuf[STLINK_RX_SIZE]; | |||
}; | |||
#define STLINK_OK 0x80 | |||
#define STLINK_FALSE 0x81 | |||
#define STLINK_CORE_RUNNING 0x80 | |||
#define STLINK_CORE_HALTED 0x81 | |||
#define STLINK_CORE_STAT_UNKNOWN -1 | |||
#define STLINK_GET_VERSION 0xf1 | |||
#define STLINK_GET_CURRENT_MODE 0xf5 | |||
#define STLINK_DEBUG_COMMAND 0xF2 | |||
#define STLINK_DFU_COMMAND 0xF3 | |||
#define STLINK_DFU_EXIT 0x07 | |||
#define STLINK_DEV_DFU_MODE 0x00 | |||
#define STLINK_DEV_MASS_MODE 0x01 | |||
#define STLINK_DEV_DEBUG_MODE 0x02 | |||
#define STLINK_DEV_UNKNOWN_MODE -1 | |||
#define STLINK_DEBUG_ENTER 0x20 | |||
#define STLINK_DEBUG_EXIT 0x21 | |||
#define STLINK_DEBUG_READCOREID 0x22 | |||
#define STLINK_DEBUG_GETSTATUS 0x01 | |||
#define STLINK_DEBUG_FORCEDEBUG 0x02 | |||
#define STLINK_DEBUG_RESETSYS 0x03 | |||
#define STLINK_DEBUG_READALLREGS 0x04 | |||
#define STLINK_DEBUG_READREG 0x05 | |||
#define STLINK_DEBUG_WRITEREG 0x06 | |||
#define STLINK_DEBUG_READMEM_32BIT 0x07 | |||
#define STLINK_DEBUG_WRITEMEM_32BIT 0x08 | |||
#define STLINK_DEBUG_RUNCORE 0x09 | |||
#define STLINK_DEBUG_STEPCORE 0x0a | |||
#define STLINK_DEBUG_SETFP 0x0b | |||
#define STLINK_DEBUG_WRITEMEM_8BIT 0x0d | |||
#define STLINK_DEBUG_CLEARFP 0x0e | |||
#define STLINK_DEBUG_WRITEDEBUGREG 0x0f | |||
#define STLINK_DEBUG_ENTER_SWD 0xa3 | |||
#define STLINK_DEBUG_ENTER_JTAG 0x00 | |||
#define STLINK_SWD_ENTER 0x30 | |||
#define STLINK_SWD_READCOREID 0x32 | |||
/** */ | |||
int stlink_usb_recv(void *handle, uint8_t *txbuf, int txsize, uint8_t *rxbuf, | |||
int rxsize) | |||
{ | |||
struct stlink_usb_handle_s *h; | |||
assert(handle != NULL); | |||
h = (struct stlink_usb_handle_s *)handle; | |||
if (jtag_libusb_bulk_write(h->fd, STLINK_TX_EP, (char *)txbuf, txsize, | |||
1000) != txsize) { | |||
return ERROR_FAIL; | |||
} | |||
if (rxsize && rxbuf) { | |||
if (jtag_libusb_bulk_read(h->fd, STLINK_RX_EP, (char *)rxbuf, | |||
rxsize, 1000) != rxsize) { | |||
return ERROR_FAIL; | |||
} | |||
} | |||
return ERROR_OK; | |||
} | |||
/** */ | |||
void stlink_usb_init_buffer(void *handle) | |||
{ | |||
struct stlink_usb_handle_s *h; | |||
assert(handle != NULL); | |||
h = (struct stlink_usb_handle_s *)handle; | |||
memset(h->txbuf, 0, STLINK_CMD_SIZE); | |||
} | |||
/** */ | |||
int stlink_usb_version(void *handle) | |||
{ | |||
int res; | |||
uint16_t v; | |||
struct stlink_usb_handle_s *h; | |||
assert(handle != NULL); | |||
h = (struct stlink_usb_handle_s *)handle; | |||
stlink_usb_init_buffer(handle); | |||
h->txbuf[0] = STLINK_GET_VERSION; | |||
res = stlink_usb_recv(handle, h->txbuf, STLINK_CMD_SIZE, h->rxbuf, 6); | |||
if (res != ERROR_OK) | |||
return res; | |||
v = (h->rxbuf[0] << 8) | h->rxbuf[1]; | |||
LOG_DEBUG("STLINK v%d", (v >> 12) & 0x0f); | |||
LOG_DEBUG("JTAG v%d", (v >> 6) & 0x3f); | |||
LOG_DEBUG("SWIM v%d", v & 0x3f); | |||
LOG_DEBUG("VID %04X", buf_get_u32(h->rxbuf, 16, 16)); | |||
LOG_DEBUG("PID %04X", buf_get_u32(h->rxbuf, 32, 16)); | |||
return ERROR_OK; | |||
} | |||
/** */ | |||
int stlink_usb_current_mode(void *handle, uint8_t *mode) | |||
{ | |||
int res; | |||
struct stlink_usb_handle_s *h; | |||
assert(handle != NULL); | |||
h = (struct stlink_usb_handle_s *)handle; | |||
stlink_usb_init_buffer(handle); | |||
h->txbuf[0] = STLINK_GET_CURRENT_MODE; | |||
res = stlink_usb_recv(handle, h->txbuf, STLINK_CMD_SIZE, h->rxbuf, 2); | |||
if (res != ERROR_OK) | |||
return res; | |||
*mode = h->rxbuf[0]; | |||
return ERROR_OK; | |||
} | |||
/** */ | |||
int stlink_usb_dfu_mode_leave(void *handle) | |||
{ | |||
int res; | |||
struct stlink_usb_handle_s *h; | |||
assert(handle != NULL); | |||
h = (struct stlink_usb_handle_s *)handle; | |||
stlink_usb_init_buffer(handle); | |||
h->txbuf[0] = STLINK_DFU_COMMAND; | |||
h->txbuf[1] = STLINK_DFU_EXIT; | |||
res = stlink_usb_recv(handle, h->txbuf, STLINK_CMD_SIZE, 0, 0); | |||
if (res != ERROR_OK) | |||
return res; | |||
return ERROR_OK; | |||
} | |||
/** */ | |||
int stlink_usb_swd_mode_enter(void *handle) | |||
{ | |||
int res; | |||
struct stlink_usb_handle_s *h; | |||
assert(handle != NULL); | |||
h = (struct stlink_usb_handle_s *)handle; | |||
stlink_usb_init_buffer(handle); | |||
h->txbuf[0] = STLINK_DEBUG_COMMAND; | |||
h->txbuf[1] = STLINK_DEBUG_ENTER; | |||
h->txbuf[2] = STLINK_DEBUG_ENTER_SWD; | |||
res = stlink_usb_recv(handle, h->txbuf, STLINK_CMD_SIZE, 0, 0); | |||
if (res != ERROR_OK) | |||
return res; | |||
return ERROR_OK; | |||
} | |||
/** */ | |||
int stlink_usb_debug_mode_leave(void *handle) | |||
{ | |||
int res; | |||
struct stlink_usb_handle_s *h; | |||
assert(handle != NULL); | |||
h = (struct stlink_usb_handle_s *)handle; | |||
stlink_usb_init_buffer(handle); | |||
h->txbuf[0] = STLINK_DEBUG_COMMAND; | |||
h->txbuf[1] = STLINK_DEBUG_EXIT; | |||
res = stlink_usb_recv(handle, h->txbuf, STLINK_CMD_SIZE, 0, 0); | |||
if (res != ERROR_OK) | |||
return res; | |||
return ERROR_OK; | |||
} | |||
/** */ | |||
int stlink_usb_init_mode(void *handle) | |||
{ | |||
int res; | |||
uint8_t mode; | |||
assert(handle != NULL); | |||
res = stlink_usb_current_mode(handle, &mode); | |||
if (res != ERROR_OK) | |||
return res; | |||
LOG_DEBUG("MODE: %02X", mode); | |||
if (mode == STLINK_DEV_DFU_MODE) { | |||
res = stlink_usb_dfu_mode_leave(handle); | |||
if (res != ERROR_OK) | |||
return res; | |||
} | |||
res = stlink_usb_current_mode(handle, &mode); | |||
if (res != ERROR_OK) | |||
return res; | |||
LOG_DEBUG("MODE: %02X", mode); | |||
if (mode != STLINK_DEV_DEBUG_MODE) { | |||
res = stlink_usb_swd_mode_enter(handle); | |||
if (res != ERROR_OK) | |||
return res; | |||
} | |||
res = stlink_usb_current_mode(handle, &mode); | |||
if (res != ERROR_OK) | |||
return res; | |||
LOG_DEBUG("MODE: %02X", mode); | |||
return ERROR_OK; | |||
} | |||
/** */ | |||
int stlink_usb_idcode(void *handle, uint32_t *idcode) | |||
{ | |||
int res; | |||
struct stlink_usb_handle_s *h; | |||
assert(handle != NULL); | |||
h = (struct stlink_usb_handle_s *)handle; | |||
stlink_usb_init_buffer(handle); | |||
h->txbuf[0] = STLINK_DEBUG_COMMAND; | |||
h->txbuf[1] = STLINK_DEBUG_READCOREID; | |||
res = stlink_usb_recv(handle, h->txbuf, STLINK_CMD_SIZE, h->rxbuf, 4); | |||
if (res != ERROR_OK) | |||
return res; | |||
*idcode = le_to_h_u32(h->rxbuf); | |||
LOG_DEBUG("IDCODE: %08X", *idcode); | |||
return ERROR_OK; | |||
} | |||
/** */ | |||
enum target_state stlink_usb_state(void *handle) | |||
{ | |||
int res; | |||
struct stlink_usb_handle_s *h; | |||
assert(handle != NULL); | |||
h = (struct stlink_usb_handle_s *)handle; | |||
stlink_usb_init_buffer(handle); | |||
h->txbuf[0] = STLINK_DEBUG_COMMAND; | |||
h->txbuf[1] = STLINK_DEBUG_GETSTATUS; | |||
res = stlink_usb_recv(handle, h->txbuf, STLINK_CMD_SIZE, h->rxbuf, 2); | |||
if (res != ERROR_OK) | |||
return TARGET_UNKNOWN; | |||
if (h->rxbuf[0] == STLINK_CORE_RUNNING) | |||
return TARGET_RUNNING; | |||
if (h->rxbuf[0] == STLINK_CORE_HALTED) | |||
return TARGET_HALTED; | |||
return TARGET_UNKNOWN; | |||
} | |||
/** */ | |||
int stlink_usb_reset(void *handle) | |||
{ | |||
int res; | |||
struct stlink_usb_handle_s *h; | |||
assert(handle != NULL); | |||
h = (struct stlink_usb_handle_s *)handle; | |||
stlink_usb_init_buffer(handle); | |||
h->txbuf[0] = STLINK_DEBUG_COMMAND; | |||
h->txbuf[1] = STLINK_DEBUG_RESETSYS; | |||
res = stlink_usb_recv(handle, h->txbuf, STLINK_CMD_SIZE, h->rxbuf, 2); | |||
if (res != ERROR_OK) | |||
return res; | |||
LOG_DEBUG("RESET: %08X", h->rxbuf[0]); | |||
return ERROR_OK; | |||
} | |||
/** */ | |||
int stlink_usb_run(void *handle) | |||
{ | |||
int res; | |||
struct stlink_usb_handle_s *h; | |||
assert(handle != NULL); | |||
h = (struct stlink_usb_handle_s *)handle; | |||
stlink_usb_init_buffer(handle); | |||
h->txbuf[0] = STLINK_DEBUG_COMMAND; | |||
h->txbuf[1] = STLINK_DEBUG_RUNCORE; | |||
res = stlink_usb_recv(handle, h->txbuf, STLINK_CMD_SIZE, h->rxbuf, 2); | |||
if (res != ERROR_OK) | |||
return res; | |||
return ERROR_OK; | |||
} | |||
/** */ | |||
int stlink_usb_halt(void *handle) | |||
{ | |||
int res; | |||
struct stlink_usb_handle_s *h; | |||
assert(handle != NULL); | |||
h = (struct stlink_usb_handle_s *)handle; | |||
stlink_usb_init_buffer(handle); | |||
h->txbuf[0] = STLINK_DEBUG_COMMAND; | |||
h->txbuf[1] = STLINK_DEBUG_FORCEDEBUG; | |||
res = stlink_usb_recv(handle, h->txbuf, STLINK_CMD_SIZE, h->rxbuf, 2); | |||
if (res != ERROR_OK) | |||
return res; | |||
return ERROR_OK; | |||
} | |||
/** */ | |||
int stlink_usb_step(void *handle) | |||
{ | |||
int res; | |||
struct stlink_usb_handle_s *h; | |||
assert(handle != NULL); | |||
h = (struct stlink_usb_handle_s *)handle; | |||
stlink_usb_init_buffer(handle); | |||
h->txbuf[0] = STLINK_DEBUG_COMMAND; | |||
h->txbuf[1] = STLINK_DEBUG_STEPCORE; | |||
res = stlink_usb_recv(handle, h->txbuf, STLINK_CMD_SIZE, h->rxbuf, 2); | |||
if (res != ERROR_OK) | |||
return res; | |||
return ERROR_OK; | |||
} | |||
/** */ | |||
int stlink_usb_read_regs(void *handle) | |||
{ | |||
int res; | |||
struct stlink_usb_handle_s *h; | |||
assert(handle != NULL); | |||
h = (struct stlink_usb_handle_s *)handle; | |||
stlink_usb_init_buffer(handle); | |||
h->txbuf[0] = STLINK_DEBUG_COMMAND; | |||
h->txbuf[1] = STLINK_DEBUG_READALLREGS; | |||
res = stlink_usb_recv(handle, h->txbuf, STLINK_CMD_SIZE, h->rxbuf, 84); | |||
if (res != ERROR_OK) | |||
return res; | |||
return ERROR_OK; | |||
} | |||
/** */ | |||
int stlink_usb_read_reg(void *handle, int num, uint32_t *val) | |||
{ | |||
int res; | |||
struct stlink_usb_handle_s *h; | |||
assert(handle != NULL); | |||
h = (struct stlink_usb_handle_s *)handle; | |||
stlink_usb_init_buffer(handle); | |||
h->txbuf[0] = STLINK_DEBUG_COMMAND; | |||
h->txbuf[1] = STLINK_DEBUG_READREG; | |||
h->txbuf[2] = num; | |||
res = stlink_usb_recv(handle, h->txbuf, STLINK_CMD_SIZE, h->rxbuf, 4); | |||
if (res != ERROR_OK) | |||
return res; | |||
*val = le_to_h_u32(h->rxbuf); | |||
return ERROR_OK; | |||
} | |||
/** */ | |||
int stlink_usb_write_reg(void *handle, int num, uint32_t val) | |||
{ | |||
int res; | |||
struct stlink_usb_handle_s *h; | |||
assert(handle != NULL); | |||
h = (struct stlink_usb_handle_s *)handle; | |||
stlink_usb_init_buffer(handle); | |||
h->txbuf[0] = STLINK_DEBUG_COMMAND; | |||
h->txbuf[1] = STLINK_DEBUG_WRITEREG; | |||
h->txbuf[2] = num; | |||
h_u32_to_le(h->txbuf + 3, val); | |||
res = stlink_usb_recv(handle, h->txbuf, STLINK_CMD_SIZE, h->rxbuf, 2); | |||
if (res != ERROR_OK) | |||
return res; | |||
return ERROR_OK; | |||
} | |||
/** */ | |||
int stlink_usb_read_mem32(void *handle, uint32_t addr, uint16_t len, | |||
uint32_t *buffer) | |||
{ | |||
int res; | |||
struct stlink_usb_handle_s *h; | |||
assert(handle != NULL); | |||
h = (struct stlink_usb_handle_s *)handle; | |||
stlink_usb_init_buffer(handle); | |||
len *= 4; | |||
h->txbuf[0] = STLINK_DEBUG_COMMAND; | |||
h->txbuf[1] = STLINK_DEBUG_READMEM_32BIT; | |||
h_u32_to_le(h->txbuf + 2, addr); | |||
h_u16_to_le(h->txbuf + 2 + 4, len); | |||
res = stlink_usb_recv(handle, h->txbuf, STLINK_CMD_SIZE, h->rxbuf, len); | |||
if (res != ERROR_OK) | |||
return res; | |||
memcpy(buffer, h->rxbuf, len); | |||
return ERROR_OK; | |||
} | |||
/** */ | |||
int stlink_usb_write_mem32(void *handle, uint32_t addr, uint16_t len, | |||
uint32_t *buffer) | |||
{ | |||
int res; | |||
struct stlink_usb_handle_s *h; | |||
assert(handle != NULL); | |||
h = (struct stlink_usb_handle_s *)handle; | |||
stlink_usb_init_buffer(handle); | |||
len *= 4; | |||
h->txbuf[0] = STLINK_DEBUG_COMMAND; | |||
h->txbuf[1] = STLINK_DEBUG_WRITEMEM_32BIT; | |||
h_u32_to_le(h->txbuf + 2, addr); | |||
h_u16_to_le(h->txbuf + 2 + 4, len); | |||
res = stlink_usb_recv(handle, h->txbuf, STLINK_CMD_SIZE, 0, 0); | |||
if (res != ERROR_OK) | |||
return res; | |||
res = stlink_usb_recv(handle, (uint8_t *) buffer, len, 0, 0); | |||
if (res != ERROR_OK) | |||
return res; | |||
memcpy(buffer, h->rxbuf, len); | |||
return ERROR_OK; | |||
} | |||
/** */ | |||
int stlink_usb_open(struct stlink_interface_param_s *param, void **fd) | |||
{ | |||
struct stlink_usb_handle_s *h; | |||
LOG_DEBUG("stlink_usb_open"); | |||
h = malloc(sizeof(struct stlink_usb_handle_s)); | |||
if (h == 0) { | |||
LOG_DEBUG("stlink_open_usb: malloc failed"); | |||
return ERROR_FAIL; | |||
} | |||
const uint16_t vids[] = { param->vid, 0 }; | |||
const uint16_t pids[] = { param->pid, 0 }; | |||
LOG_DEBUG("stlink_open_usb: vid: %04x pid: %04x", param->vid, | |||
param->pid); | |||
if (jtag_libusb_open(vids, pids, &h->fd) != ERROR_OK) { | |||
LOG_DEBUG("stlink_open_usb: open failed"); | |||
return ERROR_FAIL; | |||
} | |||
jtag_libusb_set_configuration(h->fd, 0); | |||
if (jtag_libusb_claim_interface(h->fd, 0) != ERROR_OK) { | |||
LOG_DEBUG("stlink_open_usb: claim failed"); | |||
return ERROR_FAIL; | |||
} | |||
stlink_usb_init_mode(h); | |||
stlink_usb_version(h); | |||
*fd = h; | |||
return ERROR_OK; | |||
} | |||
/** */ | |||
struct stlink_layout_api_s stlink_layout_api = { | |||
/** */ | |||
.open = stlink_usb_open, | |||
/** */ | |||
.idcode = stlink_usb_idcode, | |||
/** */ | |||
.state = stlink_usb_state, | |||
/** */ | |||
.reset = stlink_usb_reset, | |||
/** */ | |||
.run = stlink_usb_run, | |||
/** */ | |||
.halt = stlink_usb_halt, | |||
/** */ | |||
.step = stlink_usb_step, | |||
/** */ | |||
.read_regs = stlink_usb_read_regs, | |||
/** */ | |||
.read_reg = stlink_usb_read_reg, | |||
/** */ | |||
.write_reg = stlink_usb_write_reg, | |||
/** */ | |||
.read_mem32 = stlink_usb_read_mem32, | |||
/** */ | |||
.write_mem32 = stlink_usb_write_mem32, | |||
}; |
@@ -0,0 +1,7 @@ | |||
#ifndef _STLINK_USB_H_ | |||
#define _STLINK_USB_H_ | |||
/** */ | |||
void *stlink_open_usb(struct stlink_interface_param_s *param); | |||
#endif |
@@ -100,6 +100,9 @@ extern struct jtag_interface buspirate_interface; | |||
#if BUILD_REMOTE_BITBANG == 1 | |||
extern struct jtag_interface remote_bitbang_interface; | |||
#endif | |||
#if BUILD_STLINK == 1 | |||
extern struct jtag_interface stlink_interface; | |||
#endif | |||
#endif // standard drivers | |||
/** | |||
@@ -169,6 +172,9 @@ struct jtag_interface *jtag_interfaces[] = { | |||
#if BUILD_REMOTE_BITBANG == 1 | |||
&remote_bitbang_interface, | |||
#endif | |||
#if BUILD_STLINK == 1 | |||
&stlink_interface, | |||
#endif | |||
#endif // standard drivers | |||
NULL, | |||
}; | |||
@@ -0,0 +1,22 @@ | |||
include $(top_srcdir)/common.mk | |||
noinst_LTLIBRARIES = libocdstlink.la | |||
libocdstlink_la_SOURCES = \ | |||
$(STLINKFILES) | |||
nobase_dist_pkglib_DATA = | |||
STLINKFILES = | |||
if STLINK | |||
STLINKFILES += stlink_transport.c | |||
STLINKFILES += stlink_tcl.c | |||
STLINKFILES += stlink_interface.c | |||
STLINKFILES += stlink_layout.c | |||
endif | |||
noinst_HEADERS = \ | |||
stlink_tcl.h | |||
MAINTAINERCLEANFILES = $(srcdir)/Makefile.in |
@@ -0,0 +1,225 @@ | |||
/*************************************************************************** | |||
* Copyright (C) 2011 by Mathias Kuester * | |||
* Mathias Kuester <kesmtp@freenet.de> * | |||
* * | |||
* 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 | |||
/* project specific includes */ | |||
#include <jtag/interface.h> | |||
#include <transport/transport.h> | |||
#include <helper/time_support.h> | |||
#include <jtag/stlink/stlink_tcl.h> | |||
#include <jtag/stlink/stlink_layout.h> | |||
#include <jtag/stlink/stlink_interface.h> | |||
#include <target/target.h> | |||
static struct stlink_interface_s stlink_if = { {0, 0, 0, 0}, 0, 0 }; | |||
int stlink_interface_open(void) | |||
{ | |||
LOG_DEBUG("stlink_interface_open"); | |||
return stlink_if.layout->open(&stlink_if); | |||
} | |||
int stlink_interface_init_target(struct target *t) | |||
{ | |||
int res; | |||
/* this is the interface for the current target and we | |||
* can setup the private pointer in the tap structure | |||
* if the interface match the tap idcode | |||
*/ | |||
res = stlink_if.layout->api->idcode(stlink_if.fd, &t->tap->idcode); | |||
if (res != ERROR_OK) | |||
return res; | |||
unsigned ii, limit = t->tap->expected_ids_cnt; | |||
int found = 0; | |||
for (ii = 0; ii < limit; ii++) { | |||
uint32_t expected = t->tap->expected_ids[ii]; | |||
if (t->tap->idcode == expected) { | |||
found = 1; | |||
break; | |||
} | |||
} | |||
if (found == 0) { | |||
LOG_ERROR | |||
("stlink_interface_init_target: target not found: idcode: %x ", | |||
t->tap->idcode); | |||
return ERROR_FAIL; | |||
} | |||
t->tap->priv = &stlink_if; | |||
t->tap->hasidcode = 1; | |||
return ERROR_OK; | |||
} | |||
static int stlink_interface_init(void) | |||
{ | |||
LOG_DEBUG("stlink_interface_init"); | |||
/* here we can initialize the layout */ | |||
return stlink_layout_init(&stlink_if); | |||
} | |||
static int stlink_interface_quit(void) | |||
{ | |||
LOG_DEBUG("stlink_interface_quit"); | |||
return ERROR_OK; | |||
} | |||
static int stlink_interface_speed(int speed) | |||
{ | |||
LOG_DEBUG("stlink_interface_speed: ignore speed %d", speed); | |||
return ERROR_OK; | |||
} | |||
static int stlink_interface_execute_queue(void) | |||
{ | |||
LOG_DEBUG("stlink_interface_execute_queue: ignored"); | |||
return ERROR_OK; | |||
} | |||
COMMAND_HANDLER(stlink_interface_handle_device_desc_command) | |||
{ | |||
LOG_DEBUG("stlink_interface_handle_device_desc_command"); | |||
if (CMD_ARGC == 1) { | |||
stlink_if.param.device_desc = strdup(CMD_ARGV[0]); | |||
} else { | |||
LOG_ERROR | |||
("expected exactly one argument to stlink_device_desc <description>"); | |||
} | |||
return ERROR_OK; | |||
} | |||
COMMAND_HANDLER(stlink_interface_handle_serial_command) | |||
{ | |||
LOG_DEBUG("stlink_interface_handle_serial_command"); | |||
if (CMD_ARGC == 1) { | |||
stlink_if.param.serial = strdup(CMD_ARGV[0]); | |||
} else { | |||
LOG_ERROR | |||
("expected exactly one argument to stlink_serial <serial-number>"); | |||
} | |||
return ERROR_OK; | |||
} | |||
COMMAND_HANDLER(stlink_interface_handle_layout_command) | |||
{ | |||
LOG_DEBUG("stlink_interface_handle_layout_command"); | |||
if (CMD_ARGC != 1) { | |||
LOG_ERROR("Need exactly one argument to stlink_layout"); | |||
return ERROR_COMMAND_SYNTAX_ERROR; | |||
} | |||
if (stlink_if.layout) { | |||
LOG_ERROR("already specified stlink_layout %s", | |||
stlink_if.layout->name); | |||
return (strcmp(stlink_if.layout->name, CMD_ARGV[0]) != 0) | |||
? ERROR_FAIL : ERROR_OK; | |||
} | |||
for (const struct stlink_layout *l = stlink_layout_get_list(); l->name; | |||
l++) { | |||
if (strcmp(l->name, CMD_ARGV[0]) == 0) { | |||
stlink_if.layout = l; | |||
return ERROR_OK; | |||
} | |||
} | |||
LOG_ERROR("No STLINK layout '%s' found", CMD_ARGV[0]); | |||
return ERROR_FAIL; | |||
} | |||
COMMAND_HANDLER(stlink_interface_handle_vid_pid_command) | |||
{ | |||
LOG_DEBUG("stlink_interface_handle_vid_pid_command"); | |||
if (CMD_ARGC != 2) { | |||
LOG_WARNING | |||
("ignoring extra IDs in stlink_vid_pid (maximum is 1 pair)"); | |||
return ERROR_COMMAND_SYNTAX_ERROR; | |||
} | |||
COMMAND_PARSE_NUMBER(u16, CMD_ARGV[0], stlink_if.param.vid); | |||
COMMAND_PARSE_NUMBER(u16, CMD_ARGV[1], stlink_if.param.pid); | |||
return ERROR_OK; | |||
} | |||
static const struct command_registration stlink_interface_command_handlers[] = { | |||
{ | |||
.name = "stlink_device_desc", | |||
.handler = &stlink_interface_handle_device_desc_command, | |||
.mode = COMMAND_CONFIG, | |||
.help = "set the stlink device description of the STLINK device", | |||
.usage = "description_string", | |||
}, | |||
{ | |||
.name = "stlink_serial", | |||
.handler = &stlink_interface_handle_serial_command, | |||
.mode = COMMAND_CONFIG, | |||
.help = "set the serial number of the STLINK device", | |||
.usage = "serial_string", | |||
}, | |||
{ | |||
.name = "stlink_layout", | |||
.handler = &stlink_interface_handle_layout_command, | |||
.mode = COMMAND_CONFIG, | |||
.help = "set the layout of the STLINK to usb or sg", | |||
.usage = "layout_name", | |||
}, | |||
{ | |||
.name = "stlink_vid_pid", | |||
.handler = &stlink_interface_handle_vid_pid_command, | |||
.mode = COMMAND_CONFIG, | |||
.help = "the vendor and product ID of the STLINK device", | |||
.usage = "(vid pid)* ", | |||
}, | |||
COMMAND_REGISTRATION_DONE | |||
}; | |||
struct jtag_interface stlink_interface = { | |||
.name = "stlink", | |||
.supported = 0, | |||
.commands = stlink_interface_command_handlers, | |||
.transports = stlink_transports, | |||
.init = stlink_interface_init, | |||
.quit = stlink_interface_quit, | |||
.speed = stlink_interface_speed, | |||
.execute_queue = stlink_interface_execute_queue, | |||
}; |
@@ -0,0 +1,53 @@ | |||
/*************************************************************************** | |||
* Copyright (C) 2011 by Mathias Kuester * | |||
* Mathias Kuester <kesmtp@freenet.de> * | |||
* * | |||
* 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. * | |||
***************************************************************************/ | |||
#ifndef _STLINK_INTERFACE_ | |||
#define _STLINK_INTERFACE_ | |||
/** */ | |||
struct target; | |||
/** */ | |||
extern const char *stlink_transports[]; | |||
struct stlink_interface_param_s { | |||
/** */ | |||
char *device_desc; | |||
/** */ | |||
char *serial; | |||
/** */ | |||
uint16_t vid; | |||
/** */ | |||
uint16_t pid; | |||
}; | |||
struct stlink_interface_s { | |||
/** */ | |||
struct stlink_interface_param_s param; | |||
/** */ | |||
const struct stlink_layout *layout; | |||
/** */ | |||
void *fd; | |||
}; | |||
/** */ | |||
int stlink_interface_open(void); | |||
/** */ | |||
int stlink_interface_init_target(struct target *t); | |||
#endif |
@@ -0,0 +1,85 @@ | |||
/*************************************************************************** | |||
* Copyright (C) 2011 by Mathias Kuester * | |||
* Mathias Kuester <kesmtp@freenet.de> * | |||
* * | |||
* 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 | |||
/* project specific includes */ | |||
#include <jtag/interface.h> | |||
#include <transport/transport.h> | |||
#include <helper/time_support.h> | |||
#include <jtag/stlink/stlink_layout.h> | |||
#include <jtag/stlink/stlink_tcl.h> | |||
#include <jtag/stlink/stlink_interface.h> | |||
#define STLINK_LAYOUT_UNKNOWN 0 | |||
#define STLINK_LAYOUT_SG 1 | |||
#define STLINK_LAYOUT_USB 2 | |||
static int stlink_layout_open(struct stlink_interface_s *stlink_if) | |||
{ | |||
int res; | |||
LOG_DEBUG("stlink_layout_open"); | |||
stlink_if->fd = NULL; | |||
res = stlink_if->layout->api->open(&stlink_if->param, &stlink_if->fd); | |||
if (res != ERROR_OK) { | |||
LOG_DEBUG("stlink_layout_open: failed"); | |||
return res; | |||
} | |||
return ERROR_OK; | |||
} | |||
static int stlink_layout_close(struct stlink_interface_s *stlink_if) | |||
{ | |||
return ERROR_OK; | |||
} | |||
static const struct stlink_layout stlink_layouts[] = { | |||
{ | |||
.name = "usb", | |||
.type = STLINK_LAYOUT_USB, | |||
.open = stlink_layout_open, | |||
.close = stlink_layout_close, | |||
.api = &stlink_layout_api, | |||
}, | |||
{.name = NULL, /* END OF TABLE */ }, | |||
}; | |||
/** */ | |||
const struct stlink_layout *stlink_layout_get_list(void) | |||
{ | |||
return stlink_layouts; | |||
} | |||
int stlink_layout_init(struct stlink_interface_s *stlink_if) | |||
{ | |||
LOG_DEBUG("stlink_layout_init"); | |||
stlink_if->layout = &stlink_layouts[0]; | |||
return ERROR_OK; | |||
} |
@@ -0,0 +1,81 @@ | |||
/*************************************************************************** | |||
* Copyright (C) 2011 by Mathias Kuester * | |||
* Mathias Kuester <kesmtp@freenet.de> * | |||
* * | |||
* 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. * | |||
***************************************************************************/ | |||
#ifndef _STLINK_LAYOUT_H_ | |||
#define _STLINK_LAYOUT_H_ | |||
/** */ | |||
struct stlink_interface_s; | |||
struct stlink_interface_param_s; | |||
/** */ | |||
extern struct stlink_layout_api_s stlink_layout_api; | |||
/** */ | |||
struct stlink_layout_api_s { | |||
/** */ | |||
int (*open) (struct stlink_interface_param_s *param, void **fd); | |||
/** */ | |||
int (*close) (void *fd); | |||
/** */ | |||
int (*reset) (void *fd); | |||
/** */ | |||
int (*run) (void *fd); | |||
/** */ | |||
int (*halt) (void *fd); | |||
/** */ | |||
int (*step) (void *fd); | |||
/** */ | |||
int (*read_regs) (void *fd); | |||
/** */ | |||
int (*read_reg) (void *fd, int num, uint32_t *val); | |||
/** */ | |||
int (*write_reg) (void *fd, int num, uint32_t val); | |||
/** */ | |||
int (*read_mem32) (void *handle, uint32_t addr, uint16_t len, | |||
uint32_t *buffer); | |||
/** */ | |||
int (*write_mem32) (void *handle, uint32_t addr, uint16_t len, | |||
uint32_t *buffer); | |||
/** */ | |||
int (*idcode) (void *fd, uint32_t *idcode); | |||
/** */ | |||
enum target_state (*state) (void *fd); | |||
}; | |||
/** */ | |||
struct stlink_layout { | |||
/** */ | |||
char *name; | |||
/** */ | |||
int type; | |||
/** */ | |||
int (*open) (struct stlink_interface_s *stlink_if); | |||
/** */ | |||
int (*close) (struct stlink_interface_s *stlink_if); | |||
/** */ | |||
struct stlink_layout_api_s *api; | |||
}; | |||
/** */ | |||
const struct stlink_layout *stlink_layout_get_list(void); | |||
/** */ | |||
int stlink_layout_init(struct stlink_interface_s *stlink_if); | |||
#endif |
@@ -0,0 +1,136 @@ | |||
/*************************************************************************** | |||
* Copyright (C) 2011 by Mathias Kuester * | |||
* Mathias Kuester <kesmtp@freenet.de> * | |||
* * | |||
* 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 | |||
/* project specific includes */ | |||
#include <jtag/interface.h> | |||
#include <transport/transport.h> | |||
#include <helper/time_support.h> | |||
static int jim_newtap_expected_id(Jim_Nvp *n, Jim_GetOptInfo *goi, | |||
struct jtag_tap *pTap) | |||
{ | |||
jim_wide w; | |||
int e = Jim_GetOpt_Wide(goi, &w); | |||
if (e != JIM_OK) { | |||
Jim_SetResultFormatted(goi->interp, "option: %s bad parameter", | |||
n->name); | |||
return e; | |||
} | |||
unsigned expected_len = sizeof(uint32_t) * pTap->expected_ids_cnt; | |||
uint32_t *new_expected_ids = malloc(expected_len + sizeof(uint32_t)); | |||
if (new_expected_ids == NULL) { | |||
Jim_SetResultFormatted(goi->interp, "no memory"); | |||
return JIM_ERR; | |||
} | |||
memcpy(new_expected_ids, pTap->expected_ids, expected_len); | |||
new_expected_ids[pTap->expected_ids_cnt] = w; | |||
free(pTap->expected_ids); | |||
pTap->expected_ids = new_expected_ids; | |||
pTap->expected_ids_cnt++; | |||
return JIM_OK; | |||
} | |||
#define NTAP_OPT_EXPECTED_ID 0 | |||
static int jim_stlink_newtap_cmd(Jim_GetOptInfo *goi) | |||
{ | |||
struct jtag_tap *pTap; | |||
int x; | |||
int e; | |||
Jim_Nvp *n; | |||
char *cp; | |||
const Jim_Nvp opts[] = { | |||
{.name = "-expected-id", .value = NTAP_OPT_EXPECTED_ID}, | |||
{.name = NULL, .value = -1}, | |||
}; | |||
pTap = calloc(1, sizeof(struct jtag_tap)); | |||
if (!pTap) { | |||
Jim_SetResultFormatted(goi->interp, "no memory"); | |||
return JIM_ERR; | |||
} | |||
/* | |||
* we expect CHIP + TAP + OPTIONS | |||
* */ | |||
if (goi->argc < 3) { | |||
Jim_SetResultFormatted(goi->interp, | |||
"Missing CHIP TAP OPTIONS ...."); | |||
free(pTap); | |||
return JIM_ERR; | |||
} | |||
Jim_GetOpt_String(goi, &cp, NULL); | |||
pTap->chip = strdup(cp); | |||
Jim_GetOpt_String(goi, &cp, NULL); | |||
pTap->tapname = strdup(cp); | |||
/* name + dot + name + null */ | |||
x = strlen(pTap->chip) + 1 + strlen(pTap->tapname) + 1; | |||
cp = malloc(x); | |||
sprintf(cp, "%s.%s", pTap->chip, pTap->tapname); | |||
pTap->dotted_name = cp; | |||
LOG_DEBUG("Creating New Tap, Chip: %s, Tap: %s, Dotted: %s, %d params", | |||
pTap->chip, pTap->tapname, pTap->dotted_name, goi->argc); | |||
while (goi->argc) { | |||
e = Jim_GetOpt_Nvp(goi, opts, &n); | |||
if (e != JIM_OK) { | |||
Jim_GetOpt_NvpUnknown(goi, opts, 0); | |||
free((void *)pTap->dotted_name); | |||
free(pTap); | |||
return e; | |||
} | |||
LOG_DEBUG("Processing option: %s", n->name); | |||
switch (n->value) { | |||
case NTAP_OPT_EXPECTED_ID: | |||
e = jim_newtap_expected_id(n, goi, pTap); | |||
if (JIM_OK != e) { | |||
free((void *)pTap->dotted_name); | |||
free(pTap); | |||
return e; | |||
} | |||
break; | |||
} /* switch (n->value) */ | |||
} /* while (goi->argc) */ | |||
/* default is enabled-after-reset */ | |||
pTap->enabled = !pTap->disabled_after_reset; | |||
jtag_tap_init(pTap); | |||
return JIM_OK; | |||
} | |||
int jim_stlink_newtap(Jim_Interp *interp, int argc, Jim_Obj * const *argv) | |||
{ | |||
Jim_GetOptInfo goi; | |||
Jim_GetOpt_Setup(&goi, interp, argc - 1, argv + 1); | |||
return jim_stlink_newtap_cmd(&goi); | |||
} |
@@ -0,0 +1,26 @@ | |||
/*************************************************************************** | |||
* Copyright (C) 2011 by Mathias Kuester * | |||
* Mathias Kuester <kesmtp@freenet.de> * | |||
* * | |||
* 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. * | |||
***************************************************************************/ | |||
#ifndef _STLINK_TCL_ | |||
#define _STLINK_TCL_ | |||
/** */ | |||
int jim_stlink_newtap(Jim_Interp *interp, int argc, Jim_Obj * const *argv); | |||
#endif |
@@ -0,0 +1,180 @@ | |||
/*************************************************************************** | |||
* Copyright (C) 2011 by Mathias Kuester * | |||
* Mathias Kuester <kesmtp@freenet.de> * | |||
* * | |||
* 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 | |||
/* project specific includes */ | |||
#include <jtag/interface.h> | |||
#include <jtag/tcl.h> | |||
#include <transport/transport.h> | |||
#include <helper/time_support.h> | |||
#include <target/target.h> | |||
#include <jtag/stlink/stlink_tcl.h> | |||
#include <jtag/stlink/stlink_interface.h> | |||
COMMAND_HANDLER(stlink_transport_jtag_command) | |||
{ | |||
LOG_DEBUG("stlink_transport_jtag_command"); | |||
return ERROR_OK; | |||
} | |||
static const struct command_registration | |||
stlink_transport_stlink_subcommand_handlers[] = { | |||
{ | |||
.name = "newtap", | |||
.mode = COMMAND_CONFIG, | |||
.jim_handler = jim_stlink_newtap, | |||
.help = "Create a new TAP instance named basename.tap_type, " | |||
"and appends it to the scan chain.", | |||
.usage = "basename tap_type '-irlen' count " | |||
"['-expected_id' number] ", | |||
}, | |||
COMMAND_REGISTRATION_DONE | |||
}; | |||
static const struct command_registration | |||
stlink_transport_jtag_subcommand_handlers[] = { | |||
{ | |||
.name = "init", | |||
.mode = COMMAND_ANY, | |||
.handler = stlink_transport_jtag_command, | |||
}, | |||
{ | |||
.name = "arp_init", | |||
.mode = COMMAND_ANY, | |||
.handler = stlink_transport_jtag_command, | |||
}, | |||
{ | |||
.name = "arp_init-reset", | |||
.mode = COMMAND_ANY, | |||
.handler = stlink_transport_jtag_command, | |||
}, | |||
{ | |||
.name = "tapisenabled", | |||
.mode = COMMAND_EXEC, | |||
.jim_handler = jim_jtag_tap_enabler, | |||
}, | |||
{ | |||
.name = "tapenable", | |||
.mode = COMMAND_EXEC, | |||
.jim_handler = jim_jtag_tap_enabler, | |||
}, | |||
{ | |||
.name = "tapdisable", | |||
.mode = COMMAND_EXEC, | |||
.handler = stlink_transport_jtag_command, | |||
}, | |||
{ | |||
.name = "configure", | |||
.mode = COMMAND_EXEC, | |||
.handler = stlink_transport_jtag_command, | |||
}, | |||
{ | |||
.name = "cget", | |||
.mode = COMMAND_EXEC, | |||
.jim_handler = jim_jtag_configure, | |||
}, | |||
{ | |||
.name = "names", | |||
.mode = COMMAND_ANY, | |||
.handler = stlink_transport_jtag_command, | |||
}, | |||
COMMAND_REGISTRATION_DONE | |||
}; | |||
static const struct command_registration stlink_transport_command_handlers[] = { | |||
{ | |||
.name = "stlink", | |||
.mode = COMMAND_ANY, | |||
.help = "perform stlink actions", | |||
.chain = stlink_transport_stlink_subcommand_handlers, | |||
}, | |||
{ | |||
.name = "jtag", | |||
.mode = COMMAND_ANY, | |||
.chain = stlink_transport_jtag_subcommand_handlers, | |||
}, | |||
COMMAND_REGISTRATION_DONE | |||
}; | |||
static int stlink_transport_register_commands(struct command_context *cmd_ctx) | |||
{ | |||
return register_commands(cmd_ctx, NULL, | |||
stlink_transport_command_handlers); | |||
} | |||
static int stlink_transport_init(struct command_context *cmd_ctx) | |||
{ | |||
LOG_DEBUG("stlink_transport_init"); | |||
struct target *t = get_current_target(cmd_ctx); | |||
if (!t) { | |||
LOG_ERROR("stlink_transport_init: no current target"); | |||
return ERROR_FAIL; | |||
} | |||
stlink_interface_open(); | |||
return stlink_interface_init_target(t); | |||
} | |||
static int stlink_transport_select(struct command_context *ctx) | |||
{ | |||
LOG_DEBUG("stlink_transport_select"); | |||
int retval; | |||
/* NOTE: interface init must already have been done. | |||
* That works with only C code ... no Tcl glue required. | |||
*/ | |||
retval = stlink_transport_register_commands(ctx); | |||
if (retval != ERROR_OK) | |||
return retval; | |||
return ERROR_OK; | |||
} | |||
static struct transport stlink_transport = { | |||
.name = "stlink", | |||
.select = stlink_transport_select, | |||
.init = stlink_transport_init, | |||
}; | |||
const char *stlink_transports[] = { "stlink", NULL }; | |||
static void stlink_constructor(void) __attribute__ ((constructor)); | |||
static void stlink_constructor(void) | |||
{ | |||
transport_register(&stlink_transport); | |||
} | |||
bool transport_is_stlink(void) | |||
{ | |||
return get_current_transport() == &stlink_transport; | |||
} |
@@ -0,0 +1,23 @@ | |||
/*************************************************************************** | |||
* Copyright (C) 2011 by Mathias Kuester * | |||
* Mathias Kuester <kesmtp@freenet.de> * | |||
* * | |||
* 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. * | |||
***************************************************************************/ | |||
#ifndef _STLINK_TRANSPORT_ | |||
#define _STLINK_TRANSPORT_ | |||
#endif |