Merge branch 'remotes/openocd/master' into riscv64
Merged 1025be363e
Conflicts:
src/flash/nor/Makefile.am
src/rtos/Makefile.am
src/rtos/rtos.c
src/target/Makefile.am
src/target/target.c
src/target/target_type.h
Doesn't build yet, but I fixed the conflicts that git pointed out.
This commit is contained in:
+40
-54
@@ -1,86 +1,72 @@
|
||||
include $(top_srcdir)/common.mk
|
||||
noinst_LTLIBRARIES += %D%/libjtag.la
|
||||
|
||||
METASOURCES = AUTO
|
||||
noinst_LTLIBRARIES = libjtag.la
|
||||
JTAG_SRCS =
|
||||
%C%_libjtag_la_LIBADD =
|
||||
|
||||
SUBDIRS =
|
||||
DRIVERFILES =
|
||||
libjtag_la_LIBADD =
|
||||
|
||||
CLEANFILES =
|
||||
|
||||
BUILT_SOURCES =
|
||||
|
||||
BUILT_SOURCES += minidriver_imp.h
|
||||
CLEANFILES += minidriver_imp.h
|
||||
BUILT_SOURCES += %D%/minidriver_imp.h
|
||||
CLEANFILES += %D%/minidriver_imp.h
|
||||
|
||||
if MINIDRIVER
|
||||
|
||||
if ZY1000
|
||||
DRIVERFILES += zy1000/zy1000.c
|
||||
JTAG_MINIDRIVER_DIR = $(srcdir)/zy1000
|
||||
JTAG_SRCS += %D%/zy1000/zy1000.c
|
||||
JTAG_MINIDRIVER_DIR = %D%/zy1000
|
||||
endif
|
||||
if MINIDRIVER_DUMMY
|
||||
DRIVERFILES += minidummy/minidummy.c commands.c
|
||||
JTAG_MINIDRIVER_DIR = $(srcdir)/minidummy
|
||||
JTAG_SRCS += %D%/minidummy/minidummy.c %D%/commands.c
|
||||
JTAG_MINIDRIVER_DIR = %D%/minidummy
|
||||
endif
|
||||
|
||||
MINIDRIVER_IMP_DIR = $(srcdir)/minidriver
|
||||
MINIDRIVER_IMP_DIR = %D%/minidriver
|
||||
|
||||
jtag_minidriver.h: $(JTAG_MINIDRIVER_DIR)/jtag_minidriver.h
|
||||
%D%/jtag_minidriver.h: $(JTAG_MINIDRIVER_DIR)/jtag_minidriver.h
|
||||
cp $< $@
|
||||
|
||||
BUILT_SOURCES += jtag_minidriver.h
|
||||
BUILT_SOURCES += %D%/jtag_minidriver.h
|
||||
|
||||
CLEANFILES += jtag_minidriver.h
|
||||
CLEANFILES += %D%/jtag_minidriver.h
|
||||
|
||||
else
|
||||
|
||||
MINIDRIVER_IMP_DIR = $(srcdir)/drivers
|
||||
DRIVERFILES += commands.c
|
||||
MINIDRIVER_IMP_DIR = %D%/drivers
|
||||
JTAG_SRCS += %D%/commands.c
|
||||
|
||||
if HLADAPTER
|
||||
SUBDIRS += hla
|
||||
libjtag_la_LIBADD += $(top_builddir)/src/jtag/hla/libocdhla.la
|
||||
include %D%/hla/Makefile.am
|
||||
%C%_libjtag_la_LIBADD += $(top_builddir)/%D%/hla/libocdhla.la
|
||||
endif
|
||||
|
||||
if AICE
|
||||
SUBDIRS += aice
|
||||
libjtag_la_LIBADD += $(top_builddir)/src/jtag/aice/libocdaice.la
|
||||
include %D%/aice/Makefile.am
|
||||
%C%_libjtag_la_LIBADD += $(top_builddir)/%D%/aice/libocdaice.la
|
||||
endif
|
||||
|
||||
SUBDIRS += drivers
|
||||
libjtag_la_LIBADD += $(top_builddir)/src/jtag/drivers/libocdjtagdrivers.la
|
||||
|
||||
include %D%/drivers/Makefile.am
|
||||
%C%_libjtag_la_LIBADD += $(top_builddir)/%D%/drivers/libocdjtagdrivers.la
|
||||
|
||||
endif
|
||||
|
||||
# endif // MINIDRIVER
|
||||
|
||||
minidriver_imp.h: $(MINIDRIVER_IMP_DIR)/minidriver_imp.h
|
||||
%D%/minidriver_imp.h: $(MINIDRIVER_IMP_DIR)/minidriver_imp.h
|
||||
cp $< $@
|
||||
|
||||
|
||||
libjtag_la_SOURCES = \
|
||||
adapter.c \
|
||||
core.c \
|
||||
interface.c \
|
||||
interfaces.c \
|
||||
tcl.c \
|
||||
$(DRIVERFILES)
|
||||
%C%_libjtag_la_SOURCES = \
|
||||
%D%/adapter.c \
|
||||
%D%/core.c \
|
||||
%D%/interface.c \
|
||||
%D%/interfaces.c \
|
||||
%D%/tcl.c \
|
||||
%D%/commands.h \
|
||||
%D%/driver.h \
|
||||
%D%/interface.h \
|
||||
%D%/interfaces.h \
|
||||
%D%/minidriver.h \
|
||||
%D%/jtag.h \
|
||||
%D%/minidriver/minidriver_imp.h \
|
||||
%D%/minidummy/jtag_minidriver.h \
|
||||
%D%/swd.h \
|
||||
%D%/tcl.h \
|
||||
$(JTAG_SRCS)
|
||||
|
||||
noinst_HEADERS = \
|
||||
commands.h \
|
||||
driver.h \
|
||||
interface.h \
|
||||
interfaces.h \
|
||||
minidriver.h \
|
||||
jtag.h \
|
||||
minidriver/minidriver_imp.h \
|
||||
minidummy/jtag_minidriver.h \
|
||||
swd.h \
|
||||
tcl.h
|
||||
|
||||
EXTRA_DIST = startup.tcl
|
||||
|
||||
MAINTAINERCLEANFILES = $(srcdir)/Makefile.in
|
||||
STARTUP_TCL_SRCS += %D%/startup.tcl
|
||||
|
||||
+13
-26
@@ -1,27 +1,14 @@
|
||||
include $(top_srcdir)/common.mk
|
||||
noinst_LTLIBRARIES += %D%/libocdaice.la
|
||||
|
||||
AM_CPPFLAGS += -I$(top_srcdir)/src/jtag/drivers $(LIBUSB1_CFLAGS) $(LIBUSB0_CFLAGS)
|
||||
|
||||
noinst_LTLIBRARIES = libocdaice.la
|
||||
|
||||
libocdaice_la_SOURCES = \
|
||||
$(AICEFILES)
|
||||
|
||||
AICEFILES =
|
||||
|
||||
if AICE
|
||||
AICEFILES += aice_transport.c
|
||||
AICEFILES += aice_interface.c
|
||||
AICEFILES += aice_port.c
|
||||
AICEFILES += aice_usb.c
|
||||
AICEFILES += aice_pipe.c
|
||||
endif
|
||||
|
||||
noinst_HEADERS = \
|
||||
aice_transport.h \
|
||||
aice_interface.h \
|
||||
aice_port.h \
|
||||
aice_usb.h \
|
||||
aice_pipe.h
|
||||
|
||||
MAINTAINERCLEANFILES = $(srcdir)/Makefile.in
|
||||
%C%_libocdaice_la_CPPFLAGS = -I$(top_srcdir)/src/jtag/drivers $(AM_CPPFLAGS) $(LIBUSB1_CFLAGS) $(LIBUSB0_CFLAGS)
|
||||
%C%_libocdaice_la_SOURCES = \
|
||||
%D%/aice_transport.c \
|
||||
%D%/aice_interface.c \
|
||||
%D%/aice_port.c \
|
||||
%D%/aice_usb.c \
|
||||
%D%/aice_pipe.c \
|
||||
%D%/aice_transport.h \
|
||||
%D%/aice_interface.h \
|
||||
%D%/aice_port.h \
|
||||
%D%/aice_usb.h \
|
||||
%D%/aice_pipe.h
|
||||
|
||||
@@ -786,8 +786,8 @@ static int aice_pipe_memory_mode(uint32_t coreid, enum nds_memory_select mem_sel
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
|
||||
static int aice_pipe_read_tlb(uint32_t coreid, uint32_t virtual_address,
|
||||
uint32_t *physical_address)
|
||||
static int aice_pipe_read_tlb(uint32_t coreid, target_addr_t virtual_address,
|
||||
target_addr_t *physical_address)
|
||||
{
|
||||
char line[AICE_PIPE_MAXLINE];
|
||||
char command[AICE_PIPE_MAXLINE];
|
||||
|
||||
@@ -180,7 +180,7 @@ struct aice_port_api_s {
|
||||
int (*memory_mode)(uint32_t coreid, enum nds_memory_select mem_select);
|
||||
|
||||
/** */
|
||||
int (*read_tlb)(uint32_t coreid, uint32_t virtual_address, uint32_t *physical_address);
|
||||
int (*read_tlb)(uint32_t coreid, target_addr_t virtual_address, target_addr_t *physical_address);
|
||||
|
||||
/** */
|
||||
int (*cache_ctl)(uint32_t coreid, uint32_t subtype, uint32_t address);
|
||||
|
||||
@@ -2135,10 +2135,16 @@ static int aice_usb_open(struct aice_port_param_s *param)
|
||||
|
||||
/* usb_set_configuration required under win32 */
|
||||
jtag_libusb_set_configuration(devh, 0);
|
||||
jtag_libusb_claim_interface(devh, 0);
|
||||
|
||||
unsigned int aice_read_ep;
|
||||
unsigned int aice_write_ep;
|
||||
jtag_libusb_choose_interface(devh, &aice_read_ep, &aice_write_ep, -1, -1, -1);
|
||||
#ifdef HAVE_LIBUSB1
|
||||
jtag_libusb_choose_interface(devh, &aice_read_ep, &aice_write_ep, -1, -1, -1, LIBUSB_TRANSFER_TYPE_BULK);
|
||||
#else
|
||||
jtag_libusb_choose_interface(devh, &aice_read_ep, &aice_write_ep, -1, -1, -1, USB_ENDPOINT_TYPE_BULK);
|
||||
#endif
|
||||
LOG_DEBUG("aice_read_ep=0x%x, aice_write_ep=0x%x", aice_read_ep, aice_write_ep);
|
||||
|
||||
aice_handler.usb_read_ep = aice_read_ep;
|
||||
aice_handler.usb_write_ep = aice_write_ep;
|
||||
@@ -3424,10 +3430,10 @@ static int aice_usb_memory_mode(uint32_t coreid, enum nds_memory_select mem_sele
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
static int aice_usb_read_tlb(uint32_t coreid, uint32_t virtual_address,
|
||||
uint32_t *physical_address)
|
||||
static int aice_usb_read_tlb(uint32_t coreid, target_addr_t virtual_address,
|
||||
target_addr_t *physical_address)
|
||||
{
|
||||
LOG_DEBUG("aice_usb_read_tlb, virtual address: 0x%08" PRIx32, virtual_address);
|
||||
LOG_DEBUG("aice_usb_read_tlb, virtual address: 0x%08" TARGET_PRIxADDR, virtual_address);
|
||||
|
||||
uint32_t instructions[4];
|
||||
uint32_t probe_result;
|
||||
|
||||
+2
-2
@@ -1831,11 +1831,11 @@ void jtag_set_reset_config(enum reset_types type)
|
||||
|
||||
int jtag_get_trst(void)
|
||||
{
|
||||
return jtag_trst;
|
||||
return jtag_trst == 1;
|
||||
}
|
||||
int jtag_get_srst(void)
|
||||
{
|
||||
return jtag_srst;
|
||||
return jtag_srst == 1;
|
||||
}
|
||||
|
||||
void jtag_set_nsrst_delay(unsigned delay)
|
||||
|
||||
+106
-100
@@ -1,173 +1,179 @@
|
||||
include $(top_srcdir)/common.mk
|
||||
noinst_LTLIBRARIES += %D%/libocdjtagdrivers.la
|
||||
%C%_libocdjtagdrivers_la_LIBADD =
|
||||
|
||||
noinst_LTLIBRARIES = libocdjtagdrivers.la
|
||||
libocdjtagdrivers_la_LIBADD =
|
||||
%C%_libocdjtagdrivers_la_SOURCES = \
|
||||
$(DRIVERFILES) \
|
||||
$(DRIVERHEADERS)
|
||||
|
||||
libocdjtagdrivers_la_SOURCES = \
|
||||
$(DRIVERFILES)
|
||||
%C%_libocdjtagdrivers_la_CPPFLAGS = $(AM_CPPFLAGS)
|
||||
|
||||
libocdjtagdrivers_la_CPPFLAGS = $(AM_CPPFLAGS) $(LIBUSB1_CFLAGS) \
|
||||
$(LIBUSB0_CFLAGS) $(HIDAPI_CFLAGS) $(LIBFTDI_CFLAGS)
|
||||
ULINK_FIRMWARE = %D%/OpenULINK
|
||||
|
||||
ULINK_FIRMWARE = $(srcdir)/OpenULINK
|
||||
|
||||
EXTRA_DIST = $(ULINK_FIRMWARE) \
|
||||
usb_blaster/README.CheapClone \
|
||||
Makefile.rlink \
|
||||
rlink_call.m4 \
|
||||
rlink_init.m4
|
||||
EXTRA_DIST += $(ULINK_FIRMWARE) \
|
||||
%D%/usb_blaster/README.CheapClone \
|
||||
%D%/Makefile.rlink \
|
||||
%D%/rlink_call.m4 \
|
||||
%D%/rlink_init.m4
|
||||
|
||||
DRIVERFILES =
|
||||
SUBDIRS=
|
||||
|
||||
if JLINK
|
||||
if INTERNAL_LIBJAYLINK
|
||||
SUBDIRS += libjaylink
|
||||
|
||||
libjaylink_internal_la_SOURCES = jlink.c
|
||||
libjaylink_internal_la_LIBADD = libjaylink/libjaylink/libjaylink.la
|
||||
libjaylink_internal_la_CPPFLAGS = -I$(builddir)/libjaylink/libjaylink \
|
||||
-I$(srcdir)/libjaylink $(AM_CPPFLAGS)
|
||||
|
||||
noinst_LTLIBRARIES += libjaylink_internal.la
|
||||
libocdjtagdrivers_la_LIBADD += libjaylink_internal.la
|
||||
else
|
||||
DRIVERFILES += jlink.c
|
||||
endif
|
||||
endif
|
||||
|
||||
# Standard Driver: common files
|
||||
DRIVERFILES += driver.c
|
||||
DRIVERFILES += %D%/driver.c
|
||||
|
||||
if USE_LIBUSB1
|
||||
DRIVERFILES += libusb1_common.c
|
||||
DRIVERFILES += %D%/libusb1_common.c
|
||||
%C%_libocdjtagdrivers_la_CPPFLAGS += $(LIBUSB1_CFLAGS)
|
||||
%C%_libocdjtagdrivers_la_LIBADD += $(LIBUSB1_LIBS)
|
||||
endif
|
||||
|
||||
if USE_LIBUSB0
|
||||
DRIVERFILES += usb_common.c
|
||||
DRIVERFILES += %D%/usb_common.c
|
||||
%C%_libocdjtagdrivers_la_CPPFLAGS += $(LIBUSB0_CFLAGS)
|
||||
%C%_libocdjtagdrivers_la_LIBADD += $(LIBUSB0_LIBS)
|
||||
if !USE_LIBUSB1
|
||||
DRIVERFILES += libusb0_common.c
|
||||
DRIVERFILES += %D%/libusb0_common.c
|
||||
endif
|
||||
endif
|
||||
|
||||
if USE_LIBFTDI
|
||||
%C%_libocdjtagdrivers_la_CPPFLAGS += $(LIBFTDI_CFLAGS)
|
||||
%C%_libocdjtagdrivers_la_LIBADD += $(LIBFTDI_LIBS)
|
||||
endif
|
||||
|
||||
if USE_HIDAPI
|
||||
%C%_libocdjtagdrivers_la_CPPFLAGS += $(HIDAPI_CFLAGS)
|
||||
%C%_libocdjtagdrivers_la_LIBADD += $(HIDAPI_LIBS)
|
||||
endif
|
||||
|
||||
if USE_LIBJAYLINK
|
||||
%C%_libocdjtagdrivers_la_CPPFLAGS += $(LIBJAYLINK_CFLAGS)
|
||||
%C%_libocdjtagdrivers_la_LIBADD += $(LIBJAYLINK_LIBS)
|
||||
endif
|
||||
|
||||
if JLINK
|
||||
DRIVERFILES += %D%/jlink.c
|
||||
if INTERNAL_LIBJAYLINK
|
||||
SUBDIRS += %D%/libjaylink
|
||||
DIST_SUBDIRS += %D%/libjaylink
|
||||
|
||||
%C%_libocdjtagdrivers_la_LIBADD += %D%/libjaylink/libjaylink/libjaylink.la
|
||||
%C%_libocdjtagdrivers_la_CPPFLAGS += -I$(builddir)/%D%/libjaylink/libjaylink -I$(srcdir)/%D%/libjaylink
|
||||
endif
|
||||
endif
|
||||
|
||||
if BITBANG
|
||||
DRIVERFILES += bitbang.c
|
||||
DRIVERFILES += %D%/bitbang.c
|
||||
endif
|
||||
if PARPORT
|
||||
DRIVERFILES += parport.c
|
||||
DRIVERFILES += %D%/parport.c
|
||||
endif
|
||||
if DUMMY
|
||||
DRIVERFILES += dummy.c
|
||||
endif
|
||||
if FT2232_DRIVER
|
||||
DRIVERFILES += ft2232.c
|
||||
DRIVERFILES += %D%/dummy.c
|
||||
endif
|
||||
if FTDI
|
||||
DRIVERFILES += ftdi.c mpsse.c
|
||||
DRIVERFILES += %D%/ftdi.c %D%/mpsse.c
|
||||
endif
|
||||
if JTAG_VPI
|
||||
DRIVERFILES += jtag_vpi.c
|
||||
DRIVERFILES += %D%/jtag_vpi.c
|
||||
endif
|
||||
if USB_BLASTER_DRIVER
|
||||
SUBDIRS += usb_blaster
|
||||
libocdjtagdrivers_la_LIBADD += $(top_builddir)/src/jtag/drivers/usb_blaster/libocdusbblaster.la
|
||||
%C%_libocdjtagdrivers_la_LIBADD += %D%/usb_blaster/libocdusbblaster.la
|
||||
include %D%/usb_blaster/Makefile.am
|
||||
endif
|
||||
if AMTJTAGACCEL
|
||||
DRIVERFILES += amt_jtagaccel.c
|
||||
DRIVERFILES += %D%/amt_jtagaccel.c
|
||||
endif
|
||||
if EP93XX
|
||||
DRIVERFILES += ep93xx.c
|
||||
DRIVERFILES += %D%/ep93xx.c
|
||||
endif
|
||||
if AT91RM9200
|
||||
DRIVERFILES += at91rm9200.c
|
||||
DRIVERFILES += %D%/at91rm9200.c
|
||||
endif
|
||||
if GW16012
|
||||
DRIVERFILES += gw16012.c
|
||||
DRIVERFILES += %D%/gw16012.c
|
||||
endif
|
||||
if BITQ
|
||||
DRIVERFILES += bitq.c
|
||||
DRIVERFILES += %D%/bitq.c
|
||||
endif
|
||||
if PRESTO_DRIVER
|
||||
DRIVERFILES += presto.c
|
||||
if PRESTO
|
||||
DRIVERFILES += %D%/presto.c
|
||||
endif
|
||||
if USBPROG
|
||||
DRIVERFILES += usbprog.c
|
||||
DRIVERFILES += %D%/usbprog.c
|
||||
endif
|
||||
if RLINK
|
||||
DRIVERFILES += rlink.c rlink_speed_table.c
|
||||
DRIVERFILES += %D%/rlink.c %D%/rlink_speed_table.c
|
||||
endif
|
||||
if ULINK
|
||||
DRIVERFILES += ulink.c
|
||||
DRIVERFILES += %D%/ulink.c
|
||||
ulinkdir = $(pkgdatadir)/OpenULINK
|
||||
dist_ulink_DATA = $(ULINK_FIRMWARE)/ulink_firmware.hex
|
||||
%C%_libocdjtagdrivers_la_LIBADD += -lm
|
||||
endif
|
||||
if VSLLINK
|
||||
DRIVERFILES += versaloon/usbtoxxx/usbtogpio.c
|
||||
DRIVERFILES += versaloon/usbtoxxx/usbtojtagraw.c
|
||||
DRIVERFILES += versaloon/usbtoxxx/usbtoswd.c
|
||||
DRIVERFILES += versaloon/usbtoxxx/usbtopwr.c
|
||||
DRIVERFILES += versaloon/usbtoxxx/usbtoxxx.c
|
||||
DRIVERFILES += versaloon/versaloon.c
|
||||
DRIVERFILES += vsllink.c
|
||||
DRIVERFILES += %D%/versaloon/usbtoxxx/usbtogpio.c
|
||||
DRIVERFILES += %D%/versaloon/usbtoxxx/usbtojtagraw.c
|
||||
DRIVERFILES += %D%/versaloon/usbtoxxx/usbtoswd.c
|
||||
DRIVERFILES += %D%/versaloon/usbtoxxx/usbtopwr.c
|
||||
DRIVERFILES += %D%/versaloon/usbtoxxx/usbtoxxx.c
|
||||
DRIVERFILES += %D%/versaloon/versaloon.c
|
||||
DRIVERFILES += %D%/vsllink.c
|
||||
endif
|
||||
if ARMJTAGEW
|
||||
DRIVERFILES += arm-jtag-ew.c
|
||||
DRIVERFILES += %D%/arm-jtag-ew.c
|
||||
endif
|
||||
if BUSPIRATE
|
||||
DRIVERFILES += buspirate.c
|
||||
DRIVERFILES += %D%/buspirate.c
|
||||
endif
|
||||
if REMOTE_BITBANG
|
||||
DRIVERFILES += remote_bitbang.c
|
||||
DRIVERFILES += %D%/remote_bitbang.c
|
||||
endif
|
||||
if HLADAPTER
|
||||
DRIVERFILES += stlink_usb.c
|
||||
DRIVERFILES += ti_icdi_usb.c
|
||||
DRIVERFILES += %D%/stlink_usb.c
|
||||
DRIVERFILES += %D%/ti_icdi_usb.c
|
||||
endif
|
||||
if OSBDM
|
||||
DRIVERFILES += osbdm.c
|
||||
DRIVERFILES += %D%/osbdm.c
|
||||
endif
|
||||
if OPENDOUS
|
||||
DRIVERFILES += opendous.c
|
||||
DRIVERFILES += %D%/opendous.c
|
||||
endif
|
||||
if SYSFSGPIO
|
||||
DRIVERFILES += sysfsgpio.c
|
||||
DRIVERFILES += %D%/sysfsgpio.c
|
||||
endif
|
||||
if BCM2835GPIO
|
||||
DRIVERFILES += bcm2835gpio.c
|
||||
DRIVERFILES += %D%/bcm2835gpio.c
|
||||
endif
|
||||
|
||||
if OPENJTAG
|
||||
DRIVERFILES += openjtag.c
|
||||
DRIVERFILES += %D%/openjtag.c
|
||||
endif
|
||||
|
||||
if CMSIS_DAP
|
||||
DRIVERFILES += cmsis_dap_usb.c
|
||||
DRIVERFILES += %D%/cmsis_dap_usb.c
|
||||
endif
|
||||
if IMX_GPIO
|
||||
DRIVERFILES += %D%/imx_gpio.c
|
||||
endif
|
||||
|
||||
noinst_HEADERS = \
|
||||
bitbang.h \
|
||||
bitq.h \
|
||||
ftd2xx_common.h \
|
||||
libusb0_common.h \
|
||||
libusb1_common.h \
|
||||
libusb_common.h \
|
||||
minidriver_imp.h \
|
||||
mpsse.h \
|
||||
rlink.h \
|
||||
rlink_dtc_cmd.h \
|
||||
rlink_ep1_cmd.h \
|
||||
rlink_st7.h \
|
||||
usb_common.h \
|
||||
versaloon/usbtoxxx/usbtoxxx.h \
|
||||
versaloon/usbtoxxx/usbtoxxx_internal.h \
|
||||
versaloon/versaloon.h \
|
||||
versaloon/versaloon_include.h \
|
||||
versaloon/versaloon_internal.h
|
||||
|
||||
DIST_SUBDIRS = usb_blaster
|
||||
|
||||
if INTERNAL_LIBJAYLINK
|
||||
DIST_SUBDIRS += libjaylink
|
||||
if KITPROG
|
||||
DRIVERFILES += %D%/kitprog.c
|
||||
endif
|
||||
|
||||
MAINTAINERCLEANFILES = $(srcdir)/Makefile.in
|
||||
DRIVERHEADERS = \
|
||||
%D%/bitbang.h \
|
||||
%D%/bitq.h \
|
||||
%D%/libusb0_common.h \
|
||||
%D%/libusb1_common.h \
|
||||
%D%/libusb_common.h \
|
||||
%D%/minidriver_imp.h \
|
||||
%D%/mpsse.h \
|
||||
%D%/rlink.h \
|
||||
%D%/rlink_dtc_cmd.h \
|
||||
%D%/rlink_ep1_cmd.h \
|
||||
%D%/rlink_st7.h \
|
||||
%D%/usb_common.h \
|
||||
%D%/versaloon/usbtoxxx/usbtoxxx.h \
|
||||
%D%/versaloon/usbtoxxx/usbtoxxx_internal.h \
|
||||
%D%/versaloon/versaloon.h \
|
||||
%D%/versaloon/versaloon_include.h \
|
||||
%D%/versaloon/versaloon_internal.h
|
||||
|
||||
|
||||
@@ -468,8 +468,8 @@ static int bcm2835gpio_init(void)
|
||||
return ERROR_JTAG_INIT_FAILED;
|
||||
}
|
||||
|
||||
/* set 16mA drive strength */
|
||||
pads_base[BCM2835_PADS_GPIO_0_27_OFFSET] = 0x5a000018 + 7;
|
||||
/* set 4mA drive strength, slew rate limited, hysteresis on */
|
||||
pads_base[BCM2835_PADS_GPIO_0_27_OFFSET] = 0x5a000008 + 1;
|
||||
|
||||
tdo_gpio_mode = MODE_GPIO(tdo_gpio);
|
||||
tdi_gpio_mode = MODE_GPIO(tdi_gpio);
|
||||
|
||||
@@ -118,6 +118,13 @@ static bool swd_mode;
|
||||
* Bit 7: nRESET
|
||||
*/
|
||||
|
||||
#define SWJ_PIN_TCK (1<<0)
|
||||
#define SWJ_PIN_TMS (1<<1)
|
||||
#define SWJ_PIN_TDI (1<<2)
|
||||
#define SWJ_PIN_TDO (1<<3)
|
||||
#define SWJ_PIN_TRST (1<<5)
|
||||
#define SWJ_PIN_SRST (1<<7)
|
||||
|
||||
/* CMSIS-DAP SWD Commands */
|
||||
#define CMD_DAP_SWD_CONFIGURE 0x13
|
||||
|
||||
@@ -309,9 +316,11 @@ static int cmsis_dap_usb_open(void)
|
||||
int packet_size = PACKET_SIZE;
|
||||
|
||||
/* atmel cmsis-dap uses 512 byte reports */
|
||||
/* except when it doesn't e.g. with mEDBG on SAMD10 Xplained
|
||||
* board */
|
||||
/* TODO: HID report descriptor should be parsed instead of
|
||||
* hardcoding a match by VID */
|
||||
if (target_vid == 0x03eb)
|
||||
if (target_vid == 0x03eb && target_pid != 0x2145)
|
||||
packet_size = 512 + 1;
|
||||
|
||||
cmsis_dap_handle->packet_buffer = malloc(packet_size);
|
||||
@@ -764,12 +773,12 @@ static int cmsis_dap_get_status(void)
|
||||
|
||||
if (retval == ERROR_OK) {
|
||||
LOG_INFO("SWCLK/TCK = %d SWDIO/TMS = %d TDI = %d TDO = %d nTRST = %d nRESET = %d",
|
||||
(d & (0x01 << 0)) ? 1 : 0, /* Bit 0: SWCLK/TCK */
|
||||
(d & (0x01 << 1)) ? 1 : 0, /* Bit 1: SWDIO/TMS */
|
||||
(d & (0x01 << 2)) ? 1 : 0, /* Bit 2: TDI */
|
||||
(d & (0x01 << 3)) ? 1 : 0, /* Bit 3: TDO */
|
||||
(d & (0x01 << 5)) ? 1 : 0, /* Bit 5: nTRST */
|
||||
(d & (0x01 << 7)) ? 1 : 0); /* Bit 7: nRESET */
|
||||
(d & SWJ_PIN_TCK) ? 1 : 0,
|
||||
(d & SWJ_PIN_TMS) ? 1 : 0,
|
||||
(d & SWJ_PIN_TDI) ? 1 : 0,
|
||||
(d & SWJ_PIN_TDO) ? 1 : 0,
|
||||
(d & SWJ_PIN_TRST) ? 1 : 0,
|
||||
(d & SWJ_PIN_SRST) ? 1 : 0);
|
||||
}
|
||||
|
||||
return retval;
|
||||
@@ -812,7 +821,13 @@ static int cmsis_dap_swd_switch_seq(enum swd_special_seq seq)
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
|
||||
return cmsis_dap_cmd_DAP_SWJ_Sequence(s_len, s);
|
||||
retval = cmsis_dap_cmd_DAP_SWJ_Sequence(s_len, s);
|
||||
if (retval != ERROR_OK)
|
||||
return retval;
|
||||
|
||||
/* Atmel EDBG needs renew clock setting after SWJ_Sequence
|
||||
* otherwise default frequency is used */
|
||||
return cmsis_dap_cmd_DAP_SWJ_Clock(jtag_get_speed_khz());
|
||||
}
|
||||
|
||||
static int cmsis_dap_swd_open(void)
|
||||
@@ -990,8 +1005,17 @@ static int cmsis_dap_quit(void)
|
||||
|
||||
static void cmsis_dap_execute_reset(struct jtag_command *cmd)
|
||||
{
|
||||
int retval = cmsis_dap_cmd_DAP_SWJ_Pins(cmd->cmd.reset->srst ? 0 : (1 << 7), \
|
||||
(1 << 7), 0, NULL);
|
||||
/* Set both TRST and SRST even if they're not enabled as
|
||||
* there's no way to tristate them */
|
||||
uint8_t pins = 0;
|
||||
|
||||
if (!cmd->cmd.reset->srst)
|
||||
pins |= SWJ_PIN_SRST;
|
||||
if (!cmd->cmd.reset->trst)
|
||||
pins |= SWJ_PIN_TRST;
|
||||
|
||||
int retval = cmsis_dap_cmd_DAP_SWJ_Pins(pins,
|
||||
SWJ_PIN_TRST | SWJ_PIN_SRST, 0, NULL);
|
||||
if (retval != ERROR_OK)
|
||||
LOG_ERROR("CMSIS-DAP: Interface reset failed");
|
||||
}
|
||||
@@ -1475,13 +1499,11 @@ static int cmsis_dap_execute_queue(void)
|
||||
|
||||
static int cmsis_dap_speed(int speed)
|
||||
{
|
||||
if (speed > DAP_MAX_CLOCK) {
|
||||
LOG_INFO("reduce speed request: %dkHz to %dkHz maximum", speed, DAP_MAX_CLOCK);
|
||||
speed = DAP_MAX_CLOCK;
|
||||
}
|
||||
if (speed > DAP_MAX_CLOCK)
|
||||
LOG_INFO("High speed (adapter_khz %d) may be limited by adapter firmware.", speed);
|
||||
|
||||
if (speed == 0) {
|
||||
LOG_INFO("RTCK not supported");
|
||||
LOG_ERROR("RTCK not supported. Set nonzero adapter_khz.");
|
||||
return ERROR_JTAG_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,55 +0,0 @@
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2011 by Spencer Oliver <spen@spen-soft.co.uk> *
|
||||
* *
|
||||
* Written by Arnim Laeuger, 2008 (from urjtag) *
|
||||
* *
|
||||
* 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, see <http://www.gnu.org/licenses/>. *
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef OPENOCD_JTAG_DRIVERS_FTD2XX_COMMON_H
|
||||
#define OPENOCD_JTAG_DRIVERS_FTD2XX_COMMON_H
|
||||
|
||||
#if ((BUILD_FT2232_FTD2XX == 1) || (BUILD_PRESTO_FTD2XX == 1) || (BUILD_USB_BLASTER_FTD2XX == 1))
|
||||
#include <ftd2xx.h>
|
||||
|
||||
static const char *ftd2xx_status_string(FT_STATUS status)
|
||||
{
|
||||
switch (status) {
|
||||
case FT_OK: return "OK";
|
||||
case FT_INVALID_HANDLE: return "invalid handle";
|
||||
case FT_DEVICE_NOT_FOUND: return "device not found";
|
||||
case FT_DEVICE_NOT_OPENED: return "device not opened";
|
||||
case FT_IO_ERROR: return "io error";
|
||||
case FT_INSUFFICIENT_RESOURCES: return "insufficient resources";
|
||||
case FT_INVALID_PARAMETER: return "invalid parameter";
|
||||
case FT_INVALID_BAUD_RATE: return "invalid baud rate";
|
||||
|
||||
case FT_DEVICE_NOT_OPENED_FOR_ERASE: return "device not opened for erase";
|
||||
case FT_DEVICE_NOT_OPENED_FOR_WRITE: return "device not opened for write";
|
||||
case FT_FAILED_TO_WRITE_DEVICE: return "failed to write device";
|
||||
case FT_EEPROM_READ_FAILED: return "eeprom read failed";
|
||||
case FT_EEPROM_WRITE_FAILED: return "eeprom write failed";
|
||||
case FT_EEPROM_ERASE_FAILED: return "eeprom erase failed";
|
||||
case FT_EEPROM_NOT_PRESENT: return "eeprom not present";
|
||||
case FT_EEPROM_NOT_PROGRAMMED: return "eeprom not programmed";
|
||||
case FT_INVALID_ARGS: return "invalid args";
|
||||
case FT_NOT_SUPPORTED: return "not supported";
|
||||
case FT_OTHER_ERROR: return "other error";
|
||||
}
|
||||
|
||||
return "undefined FTD2xx error";
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif /* OPENOCD_JTAG_DRIVERS_FTD2XX_COMMON_H */
|
||||
@@ -0,0 +1,552 @@
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2017 by Grzegorz Kostka, kostka.grzegorz@gmail.com *
|
||||
* *
|
||||
* Based on bcm2835gpio.c *
|
||||
* *
|
||||
* 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, see <http://www.gnu.org/licenses/>. *
|
||||
***************************************************************************/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <jtag/interface.h>
|
||||
#include "bitbang.h"
|
||||
|
||||
#include <sys/mman.h>
|
||||
|
||||
#define IMX_GPIO_BASE 0x0209c000
|
||||
#define IMX_GPIO_SIZE 0x00004000
|
||||
#define IMX_GPIO_REGS_COUNT 8
|
||||
|
||||
static uint32_t imx_gpio_peri_base = IMX_GPIO_BASE;
|
||||
|
||||
struct imx_gpio_regs {
|
||||
uint32_t dr;
|
||||
uint32_t gdir;
|
||||
uint32_t psr;
|
||||
uint32_t icr1;
|
||||
uint32_t icr2;
|
||||
uint32_t imr;
|
||||
uint32_t isr;
|
||||
uint32_t edge_sel;
|
||||
} __attribute__((aligned(IMX_GPIO_SIZE)));
|
||||
|
||||
static int dev_mem_fd;
|
||||
static volatile struct imx_gpio_regs *pio_base;
|
||||
|
||||
/* GPIO setup functions */
|
||||
static inline bool gpio_mode_get(int g)
|
||||
{
|
||||
return pio_base[g / 32].gdir >> (g & 0x1F) & 1;
|
||||
}
|
||||
|
||||
static inline void gpio_mode_input_set(int g)
|
||||
{
|
||||
pio_base[g / 32].gdir &= ~(1u << (g & 0x1F));
|
||||
}
|
||||
|
||||
static inline void gpio_mode_output_set(int g)
|
||||
{
|
||||
pio_base[g / 32].gdir |= (1u << (g & 0x1F));
|
||||
}
|
||||
|
||||
static inline void gpio_mode_set(int g, int m)
|
||||
{
|
||||
(m) ? gpio_mode_output_set(g) : gpio_mode_input_set(g);
|
||||
}
|
||||
|
||||
static inline void gpio_set(int g)
|
||||
{
|
||||
pio_base[g / 32].dr |= (1u << (g & 0x1F));
|
||||
}
|
||||
|
||||
static inline void gpio_clear(int g)
|
||||
{
|
||||
pio_base[g / 32].dr &= ~(1u << (g & 0x1F));
|
||||
}
|
||||
|
||||
static inline bool gpio_level(int g)
|
||||
{
|
||||
return pio_base[g / 32].dr >> (g & 0x1F) & 1;
|
||||
}
|
||||
|
||||
static int imx_gpio_read(void);
|
||||
static void imx_gpio_write(int tck, int tms, int tdi);
|
||||
static void imx_gpio_reset(int trst, int srst);
|
||||
|
||||
static int imx_gpio_swdio_read(void);
|
||||
static void imx_gpio_swdio_drive(bool is_output);
|
||||
|
||||
static int imx_gpio_init(void);
|
||||
static int imx_gpio_quit(void);
|
||||
|
||||
static struct bitbang_interface imx_gpio_bitbang = {
|
||||
.read = imx_gpio_read,
|
||||
.write = imx_gpio_write,
|
||||
.reset = imx_gpio_reset,
|
||||
.swdio_read = imx_gpio_swdio_read,
|
||||
.swdio_drive = imx_gpio_swdio_drive,
|
||||
.blink = NULL
|
||||
};
|
||||
|
||||
/* GPIO numbers for each signal. Negative values are invalid */
|
||||
static int tck_gpio = -1;
|
||||
static int tck_gpio_mode;
|
||||
static int tms_gpio = -1;
|
||||
static int tms_gpio_mode;
|
||||
static int tdi_gpio = -1;
|
||||
static int tdi_gpio_mode;
|
||||
static int tdo_gpio = -1;
|
||||
static int tdo_gpio_mode;
|
||||
static int trst_gpio = -1;
|
||||
static int trst_gpio_mode;
|
||||
static int srst_gpio = -1;
|
||||
static int srst_gpio_mode;
|
||||
static int swclk_gpio = -1;
|
||||
static int swclk_gpio_mode;
|
||||
static int swdio_gpio = -1;
|
||||
static int swdio_gpio_mode;
|
||||
|
||||
/* Transition delay coefficients. Tuned for IMX6UL 528MHz. Adjusted
|
||||
* experimentally for:10kHz, 100Khz, 500KHz. Speeds above 800Khz are impossible
|
||||
* to reach via memory mapped method (at least for IMX6UL@528MHz).
|
||||
* Measured mmap raw GPIO toggling speed on IMX6UL@528MHz: 1.3MHz.
|
||||
*/
|
||||
static int speed_coeff = 50000;
|
||||
static int speed_offset = 100;
|
||||
static unsigned int jtag_delay;
|
||||
|
||||
static int imx_gpio_read(void)
|
||||
{
|
||||
return gpio_level(tdo_gpio);
|
||||
}
|
||||
|
||||
static void imx_gpio_write(int tck, int tms, int tdi)
|
||||
{
|
||||
tms ? gpio_set(tms_gpio) : gpio_clear(tms_gpio);
|
||||
tdi ? gpio_set(tdi_gpio) : gpio_clear(tdi_gpio);
|
||||
tck ? gpio_set(tck_gpio) : gpio_clear(tck_gpio);
|
||||
|
||||
for (unsigned int i = 0; i < jtag_delay; i++)
|
||||
asm volatile ("");
|
||||
}
|
||||
|
||||
static void imx_gpio_swd_write(int tck, int tms, int tdi)
|
||||
{
|
||||
tdi ? gpio_set(swdio_gpio) : gpio_clear(swdio_gpio);
|
||||
tck ? gpio_set(swclk_gpio) : gpio_clear(swclk_gpio);
|
||||
|
||||
for (unsigned int i = 0; i < jtag_delay; i++)
|
||||
asm volatile ("");
|
||||
}
|
||||
|
||||
/* (1) assert or (0) deassert reset lines */
|
||||
static void imx_gpio_reset(int trst, int srst)
|
||||
{
|
||||
if (trst_gpio != -1)
|
||||
trst ? gpio_set(trst_gpio) : gpio_clear(trst_gpio);
|
||||
|
||||
if (srst_gpio != -1)
|
||||
srst ? gpio_set(srst_gpio) : gpio_clear(srst_gpio);
|
||||
}
|
||||
|
||||
static void imx_gpio_swdio_drive(bool is_output)
|
||||
{
|
||||
if (is_output)
|
||||
gpio_mode_output_set(swdio_gpio);
|
||||
else
|
||||
gpio_mode_input_set(swdio_gpio);
|
||||
}
|
||||
|
||||
static int imx_gpio_swdio_read(void)
|
||||
{
|
||||
return gpio_level(swdio_gpio);
|
||||
}
|
||||
|
||||
static int imx_gpio_khz(int khz, int *jtag_speed)
|
||||
{
|
||||
if (!khz) {
|
||||
LOG_DEBUG("RCLK not supported");
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
*jtag_speed = speed_coeff/khz - speed_offset;
|
||||
if (*jtag_speed < 0)
|
||||
*jtag_speed = 0;
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
static int imx_gpio_speed_div(int speed, int *khz)
|
||||
{
|
||||
*khz = speed_coeff/(speed + speed_offset);
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
static int imx_gpio_speed(int speed)
|
||||
{
|
||||
jtag_delay = speed;
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
static int is_gpio_valid(int gpio)
|
||||
{
|
||||
return gpio >= 0 && gpio < 32 * IMX_GPIO_REGS_COUNT;
|
||||
}
|
||||
|
||||
COMMAND_HANDLER(imx_gpio_handle_jtag_gpionums)
|
||||
{
|
||||
if (CMD_ARGC == 4) {
|
||||
COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], tck_gpio);
|
||||
COMMAND_PARSE_NUMBER(int, CMD_ARGV[1], tms_gpio);
|
||||
COMMAND_PARSE_NUMBER(int, CMD_ARGV[2], tdi_gpio);
|
||||
COMMAND_PARSE_NUMBER(int, CMD_ARGV[3], tdo_gpio);
|
||||
} else if (CMD_ARGC != 0) {
|
||||
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||
}
|
||||
|
||||
command_print(CMD_CTX,
|
||||
"imx_gpio GPIO config: tck = %d, tms = %d, tdi = %d, tdo = %d",
|
||||
tck_gpio, tms_gpio, tdi_gpio, tdo_gpio);
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
COMMAND_HANDLER(imx_gpio_handle_jtag_gpionum_tck)
|
||||
{
|
||||
if (CMD_ARGC == 1)
|
||||
COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], tck_gpio);
|
||||
|
||||
command_print(CMD_CTX, "imx_gpio GPIO config: tck = %d", tck_gpio);
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
COMMAND_HANDLER(imx_gpio_handle_jtag_gpionum_tms)
|
||||
{
|
||||
if (CMD_ARGC == 1)
|
||||
COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], tms_gpio);
|
||||
|
||||
command_print(CMD_CTX, "imx_gpio GPIO config: tms = %d", tms_gpio);
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
COMMAND_HANDLER(imx_gpio_handle_jtag_gpionum_tdo)
|
||||
{
|
||||
if (CMD_ARGC == 1)
|
||||
COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], tdo_gpio);
|
||||
|
||||
command_print(CMD_CTX, "imx_gpio GPIO config: tdo = %d", tdo_gpio);
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
COMMAND_HANDLER(imx_gpio_handle_jtag_gpionum_tdi)
|
||||
{
|
||||
if (CMD_ARGC == 1)
|
||||
COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], tdi_gpio);
|
||||
|
||||
command_print(CMD_CTX, "imx_gpio GPIO config: tdi = %d", tdi_gpio);
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
COMMAND_HANDLER(imx_gpio_handle_jtag_gpionum_srst)
|
||||
{
|
||||
if (CMD_ARGC == 1)
|
||||
COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], srst_gpio);
|
||||
|
||||
command_print(CMD_CTX, "imx_gpio GPIO config: srst = %d", srst_gpio);
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
COMMAND_HANDLER(imx_gpio_handle_jtag_gpionum_trst)
|
||||
{
|
||||
if (CMD_ARGC == 1)
|
||||
COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], trst_gpio);
|
||||
|
||||
command_print(CMD_CTX, "imx_gpio GPIO config: trst = %d", trst_gpio);
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
COMMAND_HANDLER(imx_gpio_handle_swd_gpionums)
|
||||
{
|
||||
if (CMD_ARGC == 2) {
|
||||
COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], swclk_gpio);
|
||||
COMMAND_PARSE_NUMBER(int, CMD_ARGV[1], swdio_gpio);
|
||||
} else if (CMD_ARGC != 0) {
|
||||
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||
}
|
||||
|
||||
command_print(CMD_CTX,
|
||||
"imx_gpio GPIO nums: swclk = %d, swdio = %d",
|
||||
swclk_gpio, swdio_gpio);
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
COMMAND_HANDLER(imx_gpio_handle_swd_gpionum_swclk)
|
||||
{
|
||||
if (CMD_ARGC == 1)
|
||||
COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], swclk_gpio);
|
||||
|
||||
command_print(CMD_CTX, "imx_gpio num: swclk = %d", swclk_gpio);
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
COMMAND_HANDLER(imx_gpio_handle_swd_gpionum_swdio)
|
||||
{
|
||||
if (CMD_ARGC == 1)
|
||||
COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], swdio_gpio);
|
||||
|
||||
command_print(CMD_CTX, "imx_gpio num: swdio = %d", swdio_gpio);
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
COMMAND_HANDLER(imx_gpio_handle_speed_coeffs)
|
||||
{
|
||||
if (CMD_ARGC == 2) {
|
||||
COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], speed_coeff);
|
||||
COMMAND_PARSE_NUMBER(int, CMD_ARGV[1], speed_offset);
|
||||
}
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
COMMAND_HANDLER(imx_gpio_handle_peripheral_base)
|
||||
{
|
||||
if (CMD_ARGC == 1)
|
||||
COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], imx_gpio_peri_base);
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
static const struct command_registration imx_gpio_command_handlers[] = {
|
||||
{
|
||||
.name = "imx_gpio_jtag_nums",
|
||||
.handler = &imx_gpio_handle_jtag_gpionums,
|
||||
.mode = COMMAND_CONFIG,
|
||||
.help = "gpio numbers for tck, tms, tdi, tdo. (in that order)",
|
||||
.usage = "(tck tms tdi tdo)* ",
|
||||
},
|
||||
{
|
||||
.name = "imx_gpio_tck_num",
|
||||
.handler = &imx_gpio_handle_jtag_gpionum_tck,
|
||||
.mode = COMMAND_CONFIG,
|
||||
.help = "gpio number for tck.",
|
||||
},
|
||||
{
|
||||
.name = "imx_gpio_tms_num",
|
||||
.handler = &imx_gpio_handle_jtag_gpionum_tms,
|
||||
.mode = COMMAND_CONFIG,
|
||||
.help = "gpio number for tms.",
|
||||
},
|
||||
{
|
||||
.name = "imx_gpio_tdo_num",
|
||||
.handler = &imx_gpio_handle_jtag_gpionum_tdo,
|
||||
.mode = COMMAND_CONFIG,
|
||||
.help = "gpio number for tdo.",
|
||||
},
|
||||
{
|
||||
.name = "imx_gpio_tdi_num",
|
||||
.handler = &imx_gpio_handle_jtag_gpionum_tdi,
|
||||
.mode = COMMAND_CONFIG,
|
||||
.help = "gpio number for tdi.",
|
||||
},
|
||||
{
|
||||
.name = "imx_gpio_swd_nums",
|
||||
.handler = &imx_gpio_handle_swd_gpionums,
|
||||
.mode = COMMAND_CONFIG,
|
||||
.help = "gpio numbers for swclk, swdio. (in that order)",
|
||||
.usage = "(swclk swdio)* ",
|
||||
},
|
||||
{
|
||||
.name = "imx_gpio_swclk_num",
|
||||
.handler = &imx_gpio_handle_swd_gpionum_swclk,
|
||||
.mode = COMMAND_CONFIG,
|
||||
.help = "gpio number for swclk.",
|
||||
},
|
||||
{
|
||||
.name = "imx_gpio_swdio_num",
|
||||
.handler = &imx_gpio_handle_swd_gpionum_swdio,
|
||||
.mode = COMMAND_CONFIG,
|
||||
.help = "gpio number for swdio.",
|
||||
},
|
||||
{
|
||||
.name = "imx_gpio_srst_num",
|
||||
.handler = &imx_gpio_handle_jtag_gpionum_srst,
|
||||
.mode = COMMAND_CONFIG,
|
||||
.help = "gpio number for srst.",
|
||||
},
|
||||
{
|
||||
.name = "imx_gpio_trst_num",
|
||||
.handler = &imx_gpio_handle_jtag_gpionum_trst,
|
||||
.mode = COMMAND_CONFIG,
|
||||
.help = "gpio number for trst.",
|
||||
},
|
||||
{
|
||||
.name = "imx_gpio_speed_coeffs",
|
||||
.handler = &imx_gpio_handle_speed_coeffs,
|
||||
.mode = COMMAND_CONFIG,
|
||||
.help = "SPEED_COEFF and SPEED_OFFSET for delay calculations.",
|
||||
},
|
||||
{
|
||||
.name = "imx_gpio_peripheral_base",
|
||||
.handler = &imx_gpio_handle_peripheral_base,
|
||||
.mode = COMMAND_CONFIG,
|
||||
.help = "peripheral base to access GPIOs (0x0209c000 for most IMX).",
|
||||
},
|
||||
|
||||
COMMAND_REGISTRATION_DONE
|
||||
};
|
||||
|
||||
static const char * const imx_gpio_transports[] = { "jtag", "swd", NULL };
|
||||
|
||||
struct jtag_interface imx_gpio_interface = {
|
||||
.name = "imx_gpio",
|
||||
.supported = DEBUG_CAP_TMS_SEQ,
|
||||
.execute_queue = bitbang_execute_queue,
|
||||
.transports = imx_gpio_transports,
|
||||
.swd = &bitbang_swd,
|
||||
.speed = imx_gpio_speed,
|
||||
.khz = imx_gpio_khz,
|
||||
.speed_div = imx_gpio_speed_div,
|
||||
.commands = imx_gpio_command_handlers,
|
||||
.init = imx_gpio_init,
|
||||
.quit = imx_gpio_quit,
|
||||
};
|
||||
|
||||
static bool imx_gpio_jtag_mode_possible(void)
|
||||
{
|
||||
if (!is_gpio_valid(tck_gpio))
|
||||
return 0;
|
||||
if (!is_gpio_valid(tms_gpio))
|
||||
return 0;
|
||||
if (!is_gpio_valid(tdi_gpio))
|
||||
return 0;
|
||||
if (!is_gpio_valid(tdo_gpio))
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static bool imx_gpio_swd_mode_possible(void)
|
||||
{
|
||||
if (!is_gpio_valid(swclk_gpio))
|
||||
return 0;
|
||||
if (!is_gpio_valid(swdio_gpio))
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int imx_gpio_init(void)
|
||||
{
|
||||
bitbang_interface = &imx_gpio_bitbang;
|
||||
|
||||
LOG_INFO("imx_gpio GPIO JTAG/SWD bitbang driver");
|
||||
|
||||
if (imx_gpio_jtag_mode_possible()) {
|
||||
if (imx_gpio_swd_mode_possible())
|
||||
LOG_INFO("JTAG and SWD modes enabled");
|
||||
else
|
||||
LOG_INFO("JTAG only mode enabled (specify swclk and swdio gpio to add SWD mode)");
|
||||
} else if (imx_gpio_swd_mode_possible()) {
|
||||
LOG_INFO("SWD only mode enabled (specify tck, tms, tdi and tdo gpios to add JTAG mode)");
|
||||
} else {
|
||||
LOG_ERROR("Require tck, tms, tdi and tdo gpios for JTAG mode and/or swclk and swdio gpio for SWD mode");
|
||||
return ERROR_JTAG_INIT_FAILED;
|
||||
}
|
||||
|
||||
dev_mem_fd = open("/dev/mem", O_RDWR | O_SYNC);
|
||||
if (dev_mem_fd < 0) {
|
||||
perror("open");
|
||||
return ERROR_JTAG_INIT_FAILED;
|
||||
}
|
||||
|
||||
|
||||
LOG_INFO("imx_gpio mmap: pagesize: %u, regionsize: %u",
|
||||
sysconf(_SC_PAGE_SIZE), IMX_GPIO_REGS_COUNT * IMX_GPIO_SIZE);
|
||||
pio_base = mmap(NULL, IMX_GPIO_REGS_COUNT * IMX_GPIO_SIZE,
|
||||
PROT_READ | PROT_WRITE,
|
||||
MAP_SHARED, dev_mem_fd, imx_gpio_peri_base);
|
||||
|
||||
if (pio_base == MAP_FAILED) {
|
||||
perror("mmap");
|
||||
close(dev_mem_fd);
|
||||
return ERROR_JTAG_INIT_FAILED;
|
||||
}
|
||||
|
||||
/*
|
||||
* Configure TDO as an input, and TDI, TCK, TMS, TRST, SRST
|
||||
* as outputs. Drive TDI and TCK low, and TMS/TRST/SRST high.
|
||||
*/
|
||||
if (imx_gpio_jtag_mode_possible()) {
|
||||
tdo_gpio_mode = gpio_mode_get(tdo_gpio);
|
||||
tdi_gpio_mode = gpio_mode_get(tdi_gpio);
|
||||
tck_gpio_mode = gpio_mode_get(tck_gpio);
|
||||
tms_gpio_mode = gpio_mode_get(tms_gpio);
|
||||
|
||||
gpio_clear(tdi_gpio);
|
||||
gpio_clear(tck_gpio);
|
||||
gpio_set(tms_gpio);
|
||||
|
||||
gpio_mode_input_set(tdo_gpio);
|
||||
gpio_mode_output_set(tdi_gpio);
|
||||
gpio_mode_output_set(tck_gpio);
|
||||
gpio_mode_output_set(tms_gpio);
|
||||
}
|
||||
if (imx_gpio_swd_mode_possible()) {
|
||||
swclk_gpio_mode = gpio_mode_get(swclk_gpio);
|
||||
swdio_gpio_mode = gpio_mode_get(swdio_gpio);
|
||||
|
||||
gpio_clear(swdio_gpio);
|
||||
gpio_clear(swclk_gpio);
|
||||
gpio_mode_output_set(swclk_gpio);
|
||||
gpio_mode_output_set(swdio_gpio);
|
||||
}
|
||||
if (trst_gpio != -1) {
|
||||
trst_gpio_mode = gpio_mode_get(trst_gpio);
|
||||
gpio_set(trst_gpio);
|
||||
gpio_mode_output_set(trst_gpio);
|
||||
}
|
||||
if (srst_gpio != -1) {
|
||||
srst_gpio_mode = gpio_mode_get(srst_gpio);
|
||||
gpio_set(srst_gpio);
|
||||
gpio_mode_output_set(srst_gpio);
|
||||
}
|
||||
|
||||
LOG_DEBUG("saved pinmux settings: tck %d tms %d tdi %d "
|
||||
"tdo %d trst %d srst %d", tck_gpio_mode, tms_gpio_mode,
|
||||
tdi_gpio_mode, tdo_gpio_mode, trst_gpio_mode, srst_gpio_mode);
|
||||
|
||||
if (swd_mode) {
|
||||
imx_gpio_bitbang.write = imx_gpio_swd_write;
|
||||
bitbang_switch_to_swd();
|
||||
}
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
static int imx_gpio_quit(void)
|
||||
{
|
||||
if (imx_gpio_jtag_mode_possible()) {
|
||||
gpio_mode_set(tdo_gpio, tdo_gpio_mode);
|
||||
gpio_mode_set(tdi_gpio, tdi_gpio_mode);
|
||||
gpio_mode_set(tck_gpio, tck_gpio_mode);
|
||||
gpio_mode_set(tms_gpio, tms_gpio_mode);
|
||||
}
|
||||
if (imx_gpio_swd_mode_possible()) {
|
||||
gpio_mode_set(swclk_gpio, swclk_gpio_mode);
|
||||
gpio_mode_set(swdio_gpio, swdio_gpio_mode);
|
||||
}
|
||||
if (trst_gpio != -1)
|
||||
gpio_mode_set(trst_gpio, trst_gpio_mode);
|
||||
if (srst_gpio != -1)
|
||||
gpio_mode_set(srst_gpio, srst_gpio_mode);
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
+226
-23
@@ -314,12 +314,11 @@ static int jlink_execute_queue(void)
|
||||
static int jlink_speed(int speed)
|
||||
{
|
||||
int ret;
|
||||
uint32_t freq;
|
||||
uint16_t divider;
|
||||
struct jaylink_speed tmp;
|
||||
int max_speed;
|
||||
|
||||
if (jaylink_has_cap(caps, JAYLINK_DEV_CAP_GET_SPEEDS)) {
|
||||
ret = jaylink_get_speeds(devh, &freq, ÷r);
|
||||
ret = jaylink_get_speeds(devh, &tmp);
|
||||
|
||||
if (ret != JAYLINK_OK) {
|
||||
LOG_ERROR("jaylink_get_speeds() failed: %s.",
|
||||
@@ -327,8 +326,8 @@ static int jlink_speed(int speed)
|
||||
return ERROR_JTAG_DEVICE_ERROR;
|
||||
}
|
||||
|
||||
freq = freq / 1000;
|
||||
max_speed = freq / divider;
|
||||
tmp.freq /= 1000;
|
||||
max_speed = tmp.freq / tmp.div;
|
||||
} else {
|
||||
max_speed = JLINK_MAX_SPEED;
|
||||
}
|
||||
@@ -433,15 +432,16 @@ static int select_interface(void)
|
||||
static int jlink_register(void)
|
||||
{
|
||||
int ret;
|
||||
int i;
|
||||
size_t i;
|
||||
bool handle_found;
|
||||
size_t count;
|
||||
|
||||
if (!jaylink_has_cap(caps, JAYLINK_DEV_CAP_REGISTER))
|
||||
return ERROR_OK;
|
||||
|
||||
ret = jaylink_register(devh, &conn, connlist, NULL, NULL);
|
||||
ret = jaylink_register(devh, &conn, connlist, &count);
|
||||
|
||||
if (ret < 0) {
|
||||
if (ret != JAYLINK_OK) {
|
||||
LOG_ERROR("jaylink_register() failed: %s.",
|
||||
jaylink_strerror_name(ret));
|
||||
return ERROR_FAIL;
|
||||
@@ -449,7 +449,7 @@ static int jlink_register(void)
|
||||
|
||||
handle_found = false;
|
||||
|
||||
for (i = 0; i < ret; i++) {
|
||||
for (i = 0; i < count; i++) {
|
||||
if (connlist[i].handle == conn.handle) {
|
||||
handle_found = true;
|
||||
break;
|
||||
@@ -502,6 +502,36 @@ static bool adjust_swd_buffer_size(void)
|
||||
return true;
|
||||
}
|
||||
|
||||
static int jaylink_log_handler(const struct jaylink_context *ctx,
|
||||
enum jaylink_log_level level, const char *format, va_list args,
|
||||
void *user_data)
|
||||
{
|
||||
enum log_levels tmp;
|
||||
|
||||
switch (level) {
|
||||
case JAYLINK_LOG_LEVEL_ERROR:
|
||||
tmp = LOG_LVL_ERROR;
|
||||
break;
|
||||
case JAYLINK_LOG_LEVEL_WARNING:
|
||||
tmp = LOG_LVL_WARNING;
|
||||
break;
|
||||
/*
|
||||
* Forward info messages to the debug output because they are more verbose
|
||||
* than info messages of OpenOCD.
|
||||
*/
|
||||
case JAYLINK_LOG_LEVEL_INFO:
|
||||
case JAYLINK_LOG_LEVEL_DEBUG:
|
||||
tmp = LOG_LVL_DEBUG;
|
||||
break;
|
||||
default:
|
||||
tmp = LOG_LVL_WARNING;
|
||||
}
|
||||
|
||||
log_vprintf_lf(tmp, __FILE__, __LINE__, __func__, format, args);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int jlink_init(void)
|
||||
{
|
||||
int ret;
|
||||
@@ -515,6 +545,9 @@ static int jlink_init(void)
|
||||
enum jaylink_usb_address address;
|
||||
size_t length;
|
||||
|
||||
LOG_DEBUG("Using libjaylink %s (compiled with %s).",
|
||||
jaylink_version_package_get_string(), JAYLINK_VERSION_PACKAGE_STRING);
|
||||
|
||||
ret = jaylink_init(&jayctx);
|
||||
|
||||
if (ret != JAYLINK_OK) {
|
||||
@@ -523,10 +556,28 @@ static int jlink_init(void)
|
||||
return ERROR_JTAG_INIT_FAILED;
|
||||
}
|
||||
|
||||
ret = jaylink_get_device_list(jayctx, &devs);
|
||||
ret = jaylink_log_set_callback(jayctx, &jaylink_log_handler, NULL);
|
||||
|
||||
if (ret < 0) {
|
||||
LOG_ERROR("jaylink_get_device_list() failed: %s.",
|
||||
if (ret != JAYLINK_OK) {
|
||||
LOG_ERROR("jaylink_log_set_callback() failed: %s.",
|
||||
jaylink_strerror_name(ret));
|
||||
jaylink_exit(jayctx);
|
||||
return ERROR_JTAG_INIT_FAILED;
|
||||
}
|
||||
|
||||
ret = jaylink_discovery_scan(jayctx, 0);
|
||||
|
||||
if (ret != JAYLINK_OK) {
|
||||
LOG_ERROR("jaylink_discovery_scan() failed: %s.",
|
||||
jaylink_strerror_name(ret));
|
||||
jaylink_exit(jayctx);
|
||||
return ERROR_JTAG_INIT_FAILED;
|
||||
}
|
||||
|
||||
ret = jaylink_get_devices(jayctx, &devs, NULL);
|
||||
|
||||
if (ret != JAYLINK_OK) {
|
||||
LOG_ERROR("jaylink_get_devices() failed: %s.",
|
||||
jaylink_strerror_name(ret));
|
||||
jaylink_exit(jayctx);
|
||||
return ERROR_JTAG_INIT_FAILED;
|
||||
@@ -576,7 +627,7 @@ static int jlink_init(void)
|
||||
LOG_ERROR("Failed to open device: %s.", jaylink_strerror_name(ret));
|
||||
}
|
||||
|
||||
jaylink_free_device_list(devs, 1);
|
||||
jaylink_free_devices(devs, true);
|
||||
|
||||
if (!found_device) {
|
||||
LOG_ERROR("No J-Link device found.");
|
||||
@@ -626,7 +677,7 @@ static int jlink_init(void)
|
||||
}
|
||||
}
|
||||
|
||||
jtag_command_version = JAYLINK_JTAG_V2;
|
||||
jtag_command_version = JAYLINK_JTAG_VERSION_2;
|
||||
|
||||
if (jaylink_has_cap(caps, JAYLINK_DEV_CAP_GET_HW_VERSION)) {
|
||||
ret = jaylink_get_hardware_version(devh, &hwver);
|
||||
@@ -642,7 +693,7 @@ static int jlink_init(void)
|
||||
LOG_INFO("Hardware version: %u.%02u", hwver.major, hwver.minor);
|
||||
|
||||
if (hwver.major >= 5)
|
||||
jtag_command_version = JAYLINK_JTAG_V3;
|
||||
jtag_command_version = JAYLINK_JTAG_VERSION_3;
|
||||
}
|
||||
|
||||
if (iface == JAYLINK_TIF_SWD) {
|
||||
@@ -685,7 +736,7 @@ static int jlink_init(void)
|
||||
|
||||
conn.handle = 0;
|
||||
conn.pid = 0;
|
||||
conn.hid = 0;
|
||||
strcpy(conn.hid, "0.0.0.0");
|
||||
conn.iid = 0;
|
||||
conn.cid = 0;
|
||||
|
||||
@@ -729,6 +780,7 @@ static int jlink_init(void)
|
||||
static int jlink_quit(void)
|
||||
{
|
||||
int ret;
|
||||
size_t count;
|
||||
|
||||
if (trace_enabled) {
|
||||
ret = jaylink_swo_stop(devh);
|
||||
@@ -739,9 +791,9 @@ static int jlink_quit(void)
|
||||
}
|
||||
|
||||
if (jaylink_has_cap(caps, JAYLINK_DEV_CAP_REGISTER)) {
|
||||
ret = jaylink_unregister(devh, &conn, connlist, NULL, NULL);
|
||||
ret = jaylink_unregister(devh, &conn, connlist, &count);
|
||||
|
||||
if (ret < 0)
|
||||
if (ret != JAYLINK_OK)
|
||||
LOG_ERROR("jaylink_unregister() failed: %s.",
|
||||
jaylink_strerror_name(ret));
|
||||
}
|
||||
@@ -878,14 +930,22 @@ COMMAND_HANDLER(jlink_usb_command)
|
||||
|
||||
COMMAND_HANDLER(jlink_serial_command)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (CMD_ARGC != 1) {
|
||||
command_print(CMD_CTX, "Need exactly one argument for jlink serial.");
|
||||
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||
}
|
||||
|
||||
if (sscanf(CMD_ARGV[0], "%" SCNd32, &serial_number) != 1) {
|
||||
ret = jaylink_parse_serial_number(CMD_ARGV[0], &serial_number);
|
||||
|
||||
if (ret == JAYLINK_ERR) {
|
||||
command_print(CMD_CTX, "Invalid serial number: %s.", CMD_ARGV[0]);
|
||||
return ERROR_FAIL;
|
||||
} else if (ret != JAYLINK_OK) {
|
||||
command_print(CMD_CTX, "jaylink_parse_serial_number() failed: %s.",
|
||||
jaylink_strerror_name(ret));
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
|
||||
use_serial_number = true;
|
||||
@@ -951,10 +1011,10 @@ COMMAND_HANDLER(jlink_handle_jlink_jtag_command)
|
||||
|
||||
if (!CMD_ARGC) {
|
||||
switch (jtag_command_version) {
|
||||
case JAYLINK_JTAG_V2:
|
||||
case JAYLINK_JTAG_VERSION_2:
|
||||
version = 2;
|
||||
break;
|
||||
case JAYLINK_JTAG_V3:
|
||||
case JAYLINK_JTAG_VERSION_3:
|
||||
version = 3;
|
||||
break;
|
||||
default:
|
||||
@@ -970,10 +1030,10 @@ COMMAND_HANDLER(jlink_handle_jlink_jtag_command)
|
||||
|
||||
switch (tmp) {
|
||||
case 2:
|
||||
jtag_command_version = JAYLINK_JTAG_V2;
|
||||
jtag_command_version = JAYLINK_JTAG_VERSION_2;
|
||||
break;
|
||||
case 3:
|
||||
jtag_command_version = JAYLINK_JTAG_V3;
|
||||
jtag_command_version = JAYLINK_JTAG_VERSION_3;
|
||||
break;
|
||||
default:
|
||||
command_print(CMD_CTX, "Invalid argument: %s.", CMD_ARGV[0]);
|
||||
@@ -1545,6 +1605,125 @@ COMMAND_HANDLER(jlink_handle_config_command)
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
COMMAND_HANDLER(jlink_handle_emucom_write_command)
|
||||
{
|
||||
int ret;
|
||||
size_t tmp;
|
||||
uint32_t channel;
|
||||
uint32_t length;
|
||||
uint8_t *buf;
|
||||
size_t dummy;
|
||||
|
||||
if (CMD_ARGC != 2)
|
||||
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||
|
||||
if (!jaylink_has_cap(caps, JAYLINK_DEV_CAP_EMUCOM)) {
|
||||
LOG_ERROR("Device does not support EMUCOM.");
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
|
||||
COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], channel);
|
||||
|
||||
tmp = strlen(CMD_ARGV[1]);
|
||||
|
||||
if (tmp % 2 != 0) {
|
||||
LOG_ERROR("Data must be encoded as hexadecimal pairs.");
|
||||
return ERROR_COMMAND_ARGUMENT_INVALID;
|
||||
}
|
||||
|
||||
buf = malloc(tmp / 2);
|
||||
|
||||
if (!buf) {
|
||||
LOG_ERROR("Failed to allocate buffer.");
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
|
||||
dummy = unhexify(buf, CMD_ARGV[1], tmp / 2);
|
||||
|
||||
if (dummy != (tmp / 2)) {
|
||||
LOG_ERROR("Data must be encoded as hexadecimal pairs.");
|
||||
free(buf);
|
||||
return ERROR_COMMAND_ARGUMENT_INVALID;
|
||||
}
|
||||
|
||||
length = tmp / 2;
|
||||
ret = jaylink_emucom_write(devh, channel, buf, &length);
|
||||
|
||||
free(buf);
|
||||
|
||||
if (ret == JAYLINK_ERR_DEV_NOT_SUPPORTED) {
|
||||
LOG_ERROR("Channel not supported by the device.");
|
||||
return ERROR_FAIL;
|
||||
} else if (ret != JAYLINK_OK) {
|
||||
LOG_ERROR("Failed to write to channel: %s.",
|
||||
jaylink_strerror_name(ret));
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
|
||||
if (length != (tmp / 2))
|
||||
LOG_WARNING("Only %" PRIu32 " bytes written to the channel.", length);
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
COMMAND_HANDLER(jlink_handle_emucom_read_command)
|
||||
{
|
||||
int ret;
|
||||
uint32_t channel;
|
||||
uint32_t length;
|
||||
uint8_t *buf;
|
||||
size_t tmp;
|
||||
|
||||
if (CMD_ARGC != 2)
|
||||
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||
|
||||
if (!jaylink_has_cap(caps, JAYLINK_DEV_CAP_EMUCOM)) {
|
||||
LOG_ERROR("Device does not support EMUCOM.");
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
|
||||
COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], channel);
|
||||
COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], length);
|
||||
|
||||
buf = malloc(length * 3 + 1);
|
||||
|
||||
if (!buf) {
|
||||
LOG_ERROR("Failed to allocate buffer.");
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
|
||||
ret = jaylink_emucom_read(devh, channel, buf, &length);
|
||||
|
||||
if (ret == JAYLINK_ERR_DEV_NOT_SUPPORTED) {
|
||||
LOG_ERROR("Channel is not supported by the device.");
|
||||
free(buf);
|
||||
return ERROR_FAIL;
|
||||
} else if (ret == JAYLINK_ERR_DEV_NOT_AVAILABLE) {
|
||||
LOG_ERROR("Channel is not available for the requested amount of data. "
|
||||
"%" PRIu32 " bytes are avilable.", length);
|
||||
free(buf);
|
||||
return ERROR_FAIL;
|
||||
} else if (ret != JAYLINK_OK) {
|
||||
LOG_ERROR("Failed to read from channel: %s.",
|
||||
jaylink_strerror_name(ret));
|
||||
free(buf);
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
|
||||
tmp = hexify((char *)buf + length, buf, length, 2 * length + 1);
|
||||
|
||||
if (tmp != 2 * length) {
|
||||
LOG_ERROR("Failed to convert data into hexadecimal string.");
|
||||
free(buf);
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
|
||||
command_print(CMD_CTX, "%s", buf + length);
|
||||
free(buf);
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
static const struct command_registration jlink_config_subcommand_handlers[] = {
|
||||
{
|
||||
.name = "usb",
|
||||
@@ -1590,6 +1769,24 @@ static const struct command_registration jlink_config_subcommand_handlers[] = {
|
||||
COMMAND_REGISTRATION_DONE
|
||||
};
|
||||
|
||||
static const struct command_registration jlink_emucom_subcommand_handlers[] = {
|
||||
{
|
||||
.name = "write",
|
||||
.handler = &jlink_handle_emucom_write_command,
|
||||
.mode = COMMAND_EXEC,
|
||||
.help = "write to a channel",
|
||||
.usage = "<channel> <data>",
|
||||
},
|
||||
{
|
||||
.name = "read",
|
||||
.handler = &jlink_handle_emucom_read_command,
|
||||
.mode = COMMAND_EXEC,
|
||||
.help = "read from a channel",
|
||||
.usage = "<channel> <length>"
|
||||
},
|
||||
COMMAND_REGISTRATION_DONE
|
||||
};
|
||||
|
||||
static const struct command_registration jlink_subcommand_handlers[] = {
|
||||
{
|
||||
.name = "jtag",
|
||||
@@ -1639,6 +1836,12 @@ static const struct command_registration jlink_subcommand_handlers[] = {
|
||||
"this will show the device configuration",
|
||||
.chain = jlink_config_subcommand_handlers,
|
||||
},
|
||||
{
|
||||
.name = "emucom",
|
||||
.mode = COMMAND_EXEC,
|
||||
.help = "access EMUCOM channel",
|
||||
.chain = jlink_emucom_subcommand_handlers
|
||||
},
|
||||
COMMAND_REGISTRATION_DONE
|
||||
};
|
||||
|
||||
|
||||
@@ -0,0 +1,967 @@
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2007 by Juergen Stuber <juergen@jstuber.net> *
|
||||
* based on Dominic Rath's and Benedikt Sauter's usbprog.c *
|
||||
* *
|
||||
* Copyright (C) 2008 by Spencer Oliver *
|
||||
* spen@spen-soft.co.uk *
|
||||
* *
|
||||
* Copyright (C) 2011 by Jean-Christophe PLAGNIOL-VIILARD *
|
||||
* plagnioj@jcrosoft.com *
|
||||
* *
|
||||
* Copyright (C) 2015 by Marc Schink *
|
||||
* openocd-dev@marcschink.de *
|
||||
* *
|
||||
* Copyright (C) 2015 by Paul Fertser *
|
||||
* fercerpav@gmail.com *
|
||||
* *
|
||||
* Copyright (C) 2015-2017 by Forest Crossman *
|
||||
* cyrozap@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, see <http://www.gnu.org/licenses/>. *
|
||||
***************************************************************************/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include <hidapi.h>
|
||||
|
||||
#include <jtag/interface.h>
|
||||
#include <jtag/swd.h>
|
||||
#include <jtag/commands.h>
|
||||
|
||||
#include "libusb_common.h"
|
||||
|
||||
#define VID 0x04b4
|
||||
#define PID 0xf139
|
||||
|
||||
#define BULK_EP_IN 1
|
||||
#define BULK_EP_OUT 2
|
||||
|
||||
#define CONTROL_TYPE_READ 0x01
|
||||
#define CONTROL_TYPE_WRITE 0x02
|
||||
|
||||
#define CONTROL_COMMAND_PROGRAM 0x07
|
||||
|
||||
#define CONTROL_MODE_POLL_PROGRAMMER_STATUS 0x01
|
||||
#define CONTROL_MODE_RESET_TARGET 0x04
|
||||
#define CONTROL_MODE_SET_PROGRAMMER_PROTOCOL 0x40
|
||||
#define CONTROL_MODE_SYNCHRONIZE_TRANSFER 0x41
|
||||
#define CONTROL_MODE_ACQUIRE_SWD_TARGET 0x42
|
||||
#define CONTROL_MODE_SEND_SWD_SEQUENCE 0x43
|
||||
|
||||
#define PROTOCOL_JTAG 0x00
|
||||
#define PROTOCOL_SWD 0x01
|
||||
|
||||
#define DEVICE_PSOC4 0x00
|
||||
#define DEVICE_PSOC3 0x01
|
||||
#define DEVICE_UNKNOWN 0x02
|
||||
#define DEVICE_PSOC5 0x03
|
||||
|
||||
#define ACQUIRE_MODE_RESET 0x00
|
||||
#define ACQUIRE_MODE_POWER_CYCLE 0x01
|
||||
|
||||
#define SEQUENCE_LINE_RESET 0x00
|
||||
#define SEQUENCE_JTAG_TO_SWD 0x01
|
||||
|
||||
#define PROGRAMMER_NOK_NACK 0x00
|
||||
#define PROGRAMMER_OK_ACK 0x01
|
||||
|
||||
#define HID_TYPE_WRITE 0x00
|
||||
#define HID_TYPE_READ 0x01
|
||||
#define HID_TYPE_START 0x02
|
||||
|
||||
#define HID_COMMAND_POWER 0x80
|
||||
#define HID_COMMAND_VERSION 0x81
|
||||
#define HID_COMMAND_RESET 0x82
|
||||
#define HID_COMMAND_CONFIGURE 0x8f
|
||||
#define HID_COMMAND_BOOTLOADER 0xa0
|
||||
|
||||
/* 512 bytes seems to work reliably */
|
||||
#define SWD_MAX_BUFFER_LENGTH 512
|
||||
|
||||
struct kitprog {
|
||||
hid_device *hid_handle;
|
||||
struct jtag_libusb_device_handle *usb_handle;
|
||||
uint16_t packet_size;
|
||||
uint16_t packet_index;
|
||||
uint8_t *packet_buffer;
|
||||
char *serial;
|
||||
uint8_t hardware_version;
|
||||
uint8_t minor_version;
|
||||
uint8_t major_version;
|
||||
uint16_t millivolts;
|
||||
|
||||
bool supports_jtag_to_swd;
|
||||
};
|
||||
|
||||
struct pending_transfer_result {
|
||||
uint8_t cmd;
|
||||
uint32_t data;
|
||||
void *buffer;
|
||||
};
|
||||
|
||||
static char *kitprog_serial;
|
||||
static bool kitprog_init_acquire_psoc;
|
||||
|
||||
static int pending_transfer_count, pending_queue_len;
|
||||
static struct pending_transfer_result *pending_transfers;
|
||||
|
||||
static int queued_retval;
|
||||
|
||||
static struct kitprog *kitprog_handle;
|
||||
|
||||
static int kitprog_usb_open(void);
|
||||
static void kitprog_usb_close(void);
|
||||
|
||||
static int kitprog_hid_command(uint8_t *command, size_t command_length,
|
||||
uint8_t *data, size_t data_length);
|
||||
static int kitprog_get_version(void);
|
||||
static int kitprog_get_millivolts(void);
|
||||
static int kitprog_get_info(void);
|
||||
static int kitprog_set_protocol(uint8_t protocol);
|
||||
static int kitprog_get_status(void);
|
||||
static int kitprog_set_unknown(void);
|
||||
static int kitprog_acquire_psoc(uint8_t psoc_type, uint8_t acquire_mode,
|
||||
uint8_t max_attempts);
|
||||
static int kitprog_reset_target(void);
|
||||
static int kitprog_swd_sync(void);
|
||||
static int kitprog_swd_seq(uint8_t seq_type);
|
||||
|
||||
static int kitprog_generic_acquire(void);
|
||||
|
||||
static int kitprog_swd_run_queue(void);
|
||||
static void kitprog_swd_queue_cmd(uint8_t cmd, uint32_t *dst, uint32_t data);
|
||||
static int kitprog_swd_switch_seq(enum swd_special_seq seq);
|
||||
|
||||
|
||||
static inline int mm_to_version(uint8_t major, uint8_t minor)
|
||||
{
|
||||
return (major << 8) | minor;
|
||||
}
|
||||
|
||||
static int kitprog_init(void)
|
||||
{
|
||||
int retval;
|
||||
|
||||
kitprog_handle = malloc(sizeof(struct kitprog));
|
||||
if (kitprog_handle == NULL) {
|
||||
LOG_ERROR("Failed to allocate memory");
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
|
||||
if (kitprog_usb_open() != ERROR_OK) {
|
||||
LOG_ERROR("Can't find a KitProg device! Please check device connections and permissions.");
|
||||
return ERROR_JTAG_INIT_FAILED;
|
||||
}
|
||||
|
||||
/* Get the current KitProg version and target voltage */
|
||||
if (kitprog_get_info() != ERROR_OK)
|
||||
return ERROR_FAIL;
|
||||
|
||||
/* Compatibility check */
|
||||
kitprog_handle->supports_jtag_to_swd = true;
|
||||
int kitprog_version = mm_to_version(kitprog_handle->major_version, kitprog_handle->minor_version);
|
||||
if (kitprog_version < mm_to_version(2, 14)) {
|
||||
LOG_WARNING("KitProg firmware versions below v2.14 do not support sending JTAG to SWD sequences. These sequences will be substituted with SWD line resets.");
|
||||
kitprog_handle->supports_jtag_to_swd = false;
|
||||
}
|
||||
|
||||
/* I have no idea what this does */
|
||||
if (kitprog_set_unknown() != ERROR_OK)
|
||||
return ERROR_FAIL;
|
||||
|
||||
/* SWD won't work unless we do this */
|
||||
if (kitprog_swd_sync() != ERROR_OK)
|
||||
return ERROR_FAIL;
|
||||
|
||||
/* Set the protocol to SWD */
|
||||
if (kitprog_set_protocol(PROTOCOL_SWD) != ERROR_OK)
|
||||
return ERROR_FAIL;
|
||||
|
||||
/* Reset the SWD bus */
|
||||
if (kitprog_swd_seq(SEQUENCE_LINE_RESET) != ERROR_OK)
|
||||
return ERROR_FAIL;
|
||||
|
||||
if (kitprog_init_acquire_psoc) {
|
||||
/* Try to acquire any device that will respond */
|
||||
retval = kitprog_generic_acquire();
|
||||
if (retval != ERROR_OK) {
|
||||
LOG_ERROR("No PSoC devices found");
|
||||
return retval;
|
||||
}
|
||||
}
|
||||
|
||||
/* Allocate packet buffers and queues */
|
||||
kitprog_handle->packet_size = SWD_MAX_BUFFER_LENGTH;
|
||||
kitprog_handle->packet_buffer = malloc(SWD_MAX_BUFFER_LENGTH);
|
||||
if (kitprog_handle->packet_buffer == NULL) {
|
||||
LOG_ERROR("Failed to allocate memory for the packet buffer");
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
|
||||
pending_queue_len = SWD_MAX_BUFFER_LENGTH / 5;
|
||||
pending_transfers = malloc(pending_queue_len * sizeof(*pending_transfers));
|
||||
if (pending_transfers == NULL) {
|
||||
LOG_ERROR("Failed to allocate memory for the SWD transfer queue");
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
static int kitprog_quit(void)
|
||||
{
|
||||
kitprog_usb_close();
|
||||
|
||||
if (kitprog_handle->packet_buffer != NULL)
|
||||
free(kitprog_handle->packet_buffer);
|
||||
if (kitprog_handle->serial != NULL)
|
||||
free(kitprog_handle->serial);
|
||||
if (kitprog_handle != NULL)
|
||||
free(kitprog_handle);
|
||||
|
||||
if (kitprog_serial != NULL)
|
||||
free(kitprog_serial);
|
||||
|
||||
if (pending_transfers != NULL)
|
||||
free(pending_transfers);
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
/*************** kitprog usb functions *********************/
|
||||
|
||||
static int kitprog_get_usb_serial(void)
|
||||
{
|
||||
int retval;
|
||||
const uint8_t str_index = 128; /* This seems to be a constant */
|
||||
char desc_string[256+1]; /* Max size of string descriptor */
|
||||
|
||||
retval = libusb_get_string_descriptor_ascii(kitprog_handle->usb_handle,
|
||||
str_index, (unsigned char *)desc_string, sizeof(desc_string)-1);
|
||||
if (retval < 0) {
|
||||
LOG_ERROR("libusb_get_string_descriptor_ascii() failed with %d", retval);
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
|
||||
/* Null terminate descriptor string */
|
||||
desc_string[retval] = '\0';
|
||||
|
||||
/* Allocate memory for the serial number */
|
||||
kitprog_handle->serial = calloc(retval + 1, sizeof(char));
|
||||
if (kitprog_handle->serial == NULL) {
|
||||
LOG_ERROR("Failed to allocate memory for the serial number");
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
|
||||
/* Store the serial number */
|
||||
strncpy(kitprog_handle->serial, desc_string, retval + 1);
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
static int kitprog_usb_open(void)
|
||||
{
|
||||
const uint16_t vids[] = { VID, 0 };
|
||||
const uint16_t pids[] = { PID, 0 };
|
||||
|
||||
if (jtag_libusb_open(vids, pids, kitprog_serial,
|
||||
&kitprog_handle->usb_handle) != ERROR_OK) {
|
||||
LOG_ERROR("Failed to open or find the device");
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
|
||||
/* Get the serial number for the device */
|
||||
if (kitprog_get_usb_serial() != ERROR_OK)
|
||||
LOG_WARNING("Failed to get KitProg serial number");
|
||||
|
||||
/* Convert the ASCII serial number into a (wchar_t *) */
|
||||
size_t len = strlen(kitprog_handle->serial);
|
||||
wchar_t *hid_serial = calloc(len + 1, sizeof(wchar_t));
|
||||
if (hid_serial == NULL) {
|
||||
LOG_ERROR("Failed to allocate memory for the serial number");
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
if (mbstowcs(hid_serial, kitprog_handle->serial, len + 1) == (size_t)-1) {
|
||||
free(hid_serial);
|
||||
LOG_ERROR("Failed to convert serial number");
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
|
||||
/* Use HID for the KitBridge interface */
|
||||
kitprog_handle->hid_handle = hid_open(VID, PID, hid_serial);
|
||||
free(hid_serial);
|
||||
if (kitprog_handle->hid_handle == NULL) {
|
||||
LOG_ERROR("Failed to open KitBridge (HID) interface");
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
|
||||
/* Claim the KitProg Programmer (bulk transfer) interface */
|
||||
if (jtag_libusb_claim_interface(kitprog_handle->usb_handle, 1) != ERROR_OK) {
|
||||
LOG_ERROR("Failed to claim KitProg Programmer (bulk transfer) interface");
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
static void kitprog_usb_close(void)
|
||||
{
|
||||
if (kitprog_handle->hid_handle != NULL) {
|
||||
hid_close(kitprog_handle->hid_handle);
|
||||
hid_exit();
|
||||
}
|
||||
|
||||
jtag_libusb_close(kitprog_handle->usb_handle);
|
||||
}
|
||||
|
||||
/*************** kitprog lowlevel functions *********************/
|
||||
|
||||
static int kitprog_hid_command(uint8_t *command, size_t command_length,
|
||||
uint8_t *data, size_t data_length)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = hid_write(kitprog_handle->hid_handle, command, command_length);
|
||||
if (ret < 0) {
|
||||
LOG_DEBUG("HID write returned %i", ret);
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
|
||||
ret = hid_read(kitprog_handle->hid_handle, data, data_length);
|
||||
if (ret < 0) {
|
||||
LOG_DEBUG("HID read returned %i", ret);
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
static int kitprog_get_version(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
unsigned char command[3] = {HID_TYPE_START | HID_TYPE_WRITE, 0x00, HID_COMMAND_VERSION};
|
||||
unsigned char data[64];
|
||||
|
||||
ret = kitprog_hid_command(command, sizeof command, data, sizeof data);
|
||||
if (ret != ERROR_OK)
|
||||
return ret;
|
||||
|
||||
kitprog_handle->hardware_version = data[1];
|
||||
kitprog_handle->minor_version = data[2];
|
||||
kitprog_handle->major_version = data[3];
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
static int kitprog_get_millivolts(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
unsigned char command[3] = {HID_TYPE_START | HID_TYPE_READ, 0x00, HID_COMMAND_POWER};
|
||||
unsigned char data[64];
|
||||
|
||||
ret = kitprog_hid_command(command, sizeof command, data, sizeof data);
|
||||
if (ret != ERROR_OK)
|
||||
return ret;
|
||||
|
||||
kitprog_handle->millivolts = (data[4] << 8) | data[3];
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
static int kitprog_get_info(void)
|
||||
{
|
||||
/* Get the device version information */
|
||||
if (kitprog_get_version() == ERROR_OK) {
|
||||
LOG_INFO("KitProg v%u.%02u",
|
||||
kitprog_handle->major_version, kitprog_handle->minor_version);
|
||||
LOG_INFO("Hardware version: %u",
|
||||
kitprog_handle->hardware_version);
|
||||
} else {
|
||||
LOG_ERROR("Failed to get KitProg version");
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
|
||||
/* Get the current reported target voltage */
|
||||
if (kitprog_get_millivolts() == ERROR_OK) {
|
||||
LOG_INFO("VTARG = %u.%03u V",
|
||||
kitprog_handle->millivolts / 1000, kitprog_handle->millivolts % 1000);
|
||||
} else {
|
||||
LOG_ERROR("Failed to get target voltage");
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
static int kitprog_set_protocol(uint8_t protocol)
|
||||
{
|
||||
int transferred;
|
||||
char status = PROGRAMMER_NOK_NACK;
|
||||
|
||||
transferred = jtag_libusb_control_transfer(kitprog_handle->usb_handle,
|
||||
LIBUSB_ENDPOINT_IN | LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE,
|
||||
CONTROL_TYPE_WRITE,
|
||||
(CONTROL_MODE_SET_PROGRAMMER_PROTOCOL << 8) | CONTROL_COMMAND_PROGRAM,
|
||||
protocol, &status, 1, 0);
|
||||
|
||||
if (transferred == 0) {
|
||||
LOG_DEBUG("Zero bytes transferred");
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
|
||||
if (status != PROGRAMMER_OK_ACK) {
|
||||
LOG_DEBUG("Programmer did not respond OK");
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
static int kitprog_get_status(void)
|
||||
{
|
||||
int transferred = 0;
|
||||
char status = PROGRAMMER_NOK_NACK;
|
||||
|
||||
/* Try a maximum of three times */
|
||||
for (int i = 0; (i < 3) && (transferred == 0); i++) {
|
||||
transferred = jtag_libusb_control_transfer(kitprog_handle->usb_handle,
|
||||
LIBUSB_ENDPOINT_IN | LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE,
|
||||
CONTROL_TYPE_READ,
|
||||
(CONTROL_MODE_POLL_PROGRAMMER_STATUS << 8) | CONTROL_COMMAND_PROGRAM,
|
||||
0, &status, 1, 0);
|
||||
jtag_sleep(1000);
|
||||
}
|
||||
|
||||
if (transferred == 0) {
|
||||
LOG_DEBUG("Zero bytes transferred");
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
|
||||
if (status != PROGRAMMER_OK_ACK) {
|
||||
LOG_DEBUG("Programmer did not respond OK");
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
static int kitprog_set_unknown(void)
|
||||
{
|
||||
int transferred;
|
||||
char status = PROGRAMMER_NOK_NACK;
|
||||
|
||||
transferred = jtag_libusb_control_transfer(kitprog_handle->usb_handle,
|
||||
LIBUSB_ENDPOINT_IN | LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE,
|
||||
CONTROL_TYPE_WRITE,
|
||||
(0x03 << 8) | 0x04,
|
||||
0, &status, 1, 0);
|
||||
|
||||
if (transferred == 0) {
|
||||
LOG_DEBUG("Zero bytes transferred");
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
|
||||
if (status != PROGRAMMER_OK_ACK) {
|
||||
LOG_DEBUG("Programmer did not respond OK");
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
static int kitprog_acquire_psoc(uint8_t psoc_type, uint8_t acquire_mode,
|
||||
uint8_t max_attempts)
|
||||
{
|
||||
int transferred;
|
||||
char status = PROGRAMMER_NOK_NACK;
|
||||
|
||||
transferred = jtag_libusb_control_transfer(kitprog_handle->usb_handle,
|
||||
LIBUSB_ENDPOINT_IN | LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE,
|
||||
CONTROL_TYPE_WRITE,
|
||||
(CONTROL_MODE_ACQUIRE_SWD_TARGET << 8) | CONTROL_COMMAND_PROGRAM,
|
||||
(max_attempts << 8) | (acquire_mode << 4) | psoc_type, &status, 1, 0);
|
||||
|
||||
if (transferred == 0) {
|
||||
LOG_DEBUG("Zero bytes transferred");
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
|
||||
if (status != PROGRAMMER_OK_ACK) {
|
||||
LOG_DEBUG("Programmer did not respond OK");
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
static int kitprog_reset_target(void)
|
||||
{
|
||||
int transferred;
|
||||
char status = PROGRAMMER_NOK_NACK;
|
||||
|
||||
transferred = jtag_libusb_control_transfer(kitprog_handle->usb_handle,
|
||||
LIBUSB_ENDPOINT_IN | LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE,
|
||||
CONTROL_TYPE_WRITE,
|
||||
(CONTROL_MODE_RESET_TARGET << 8) | CONTROL_COMMAND_PROGRAM,
|
||||
0, &status, 1, 0);
|
||||
|
||||
if (transferred == 0) {
|
||||
LOG_DEBUG("Zero bytes transferred");
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
|
||||
if (status != PROGRAMMER_OK_ACK) {
|
||||
LOG_DEBUG("Programmer did not respond OK");
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
static int kitprog_swd_sync(void)
|
||||
{
|
||||
int transferred;
|
||||
char status = PROGRAMMER_NOK_NACK;
|
||||
|
||||
transferred = jtag_libusb_control_transfer(kitprog_handle->usb_handle,
|
||||
LIBUSB_ENDPOINT_IN | LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE,
|
||||
CONTROL_TYPE_WRITE,
|
||||
(CONTROL_MODE_SYNCHRONIZE_TRANSFER << 8) | CONTROL_COMMAND_PROGRAM,
|
||||
0, &status, 1, 0);
|
||||
|
||||
if (transferred == 0) {
|
||||
LOG_DEBUG("Zero bytes transferred");
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
|
||||
if (status != PROGRAMMER_OK_ACK) {
|
||||
LOG_DEBUG("Programmer did not respond OK");
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
static int kitprog_swd_seq(uint8_t seq_type)
|
||||
{
|
||||
int transferred;
|
||||
char status = PROGRAMMER_NOK_NACK;
|
||||
|
||||
transferred = jtag_libusb_control_transfer(kitprog_handle->usb_handle,
|
||||
LIBUSB_ENDPOINT_IN | LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE,
|
||||
CONTROL_TYPE_WRITE,
|
||||
(CONTROL_MODE_SEND_SWD_SEQUENCE << 8) | CONTROL_COMMAND_PROGRAM,
|
||||
seq_type, &status, 1, 0);
|
||||
|
||||
if (transferred == 0) {
|
||||
LOG_DEBUG("Zero bytes transferred");
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
|
||||
if (status != PROGRAMMER_OK_ACK) {
|
||||
LOG_DEBUG("Programmer did not respond OK");
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
static int kitprog_generic_acquire(void)
|
||||
{
|
||||
const uint8_t devices[] = {DEVICE_PSOC4, DEVICE_PSOC3, DEVICE_PSOC5};
|
||||
|
||||
int retval;
|
||||
int acquire_count = 0;
|
||||
|
||||
/* Due to the way the SWD port is shared between the Test Controller (TC)
|
||||
* and the Cortex-M3 DAP on the PSoC 5LP, the TC is the default SWD target
|
||||
* after power is applied. To access the DAP, the PSoC 5LP requires at least
|
||||
* one acquisition sequence to be run (which switches the SWD mux from the
|
||||
* TC to the DAP). However, after the mux is switched, the Cortex-M3 will be
|
||||
* held in reset until a series of registers are written to (see section 5.2
|
||||
* of the PSoC 5LP Device Programming Specifications for details).
|
||||
*
|
||||
* Instead of writing the registers in this function, we just do what the
|
||||
* Cypress tools do and run the acquisition sequence a second time. This
|
||||
* will take the Cortex-M3 out of reset and enable debugging.
|
||||
*/
|
||||
for (int i = 0; i < 2; i++) {
|
||||
for (uint8_t j = 0; j < sizeof devices && acquire_count == i; j++) {
|
||||
retval = kitprog_acquire_psoc(devices[j], ACQUIRE_MODE_RESET, 3);
|
||||
if (retval != ERROR_OK) {
|
||||
LOG_DEBUG("Aquisition function failed for device 0x%02x.", devices[j]);
|
||||
return retval;
|
||||
}
|
||||
|
||||
if (kitprog_get_status() == ERROR_OK)
|
||||
acquire_count++;
|
||||
}
|
||||
|
||||
jtag_sleep(10);
|
||||
}
|
||||
|
||||
if (acquire_count < 2)
|
||||
return ERROR_FAIL;
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
/*************** swd wrapper functions *********************/
|
||||
|
||||
static int kitprog_swd_init(void)
|
||||
{
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
static void kitprog_swd_write_reg(uint8_t cmd, uint32_t value, uint32_t ap_delay_clk)
|
||||
{
|
||||
assert(!(cmd & SWD_CMD_RnW));
|
||||
kitprog_swd_queue_cmd(cmd, NULL, value);
|
||||
}
|
||||
|
||||
static void kitprog_swd_read_reg(uint8_t cmd, uint32_t *value, uint32_t ap_delay_clk)
|
||||
{
|
||||
assert(cmd & SWD_CMD_RnW);
|
||||
kitprog_swd_queue_cmd(cmd, value, 0);
|
||||
}
|
||||
|
||||
/*************** swd lowlevel functions ********************/
|
||||
|
||||
static int kitprog_swd_switch_seq(enum swd_special_seq seq)
|
||||
{
|
||||
switch (seq) {
|
||||
case JTAG_TO_SWD:
|
||||
if (kitprog_handle->supports_jtag_to_swd) {
|
||||
LOG_DEBUG("JTAG to SWD");
|
||||
if (kitprog_swd_seq(SEQUENCE_JTAG_TO_SWD) != ERROR_OK)
|
||||
return ERROR_FAIL;
|
||||
break;
|
||||
} else {
|
||||
LOG_DEBUG("JTAG to SWD not supported");
|
||||
/* Fall through to fix target reset issue */
|
||||
}
|
||||
case LINE_RESET:
|
||||
LOG_DEBUG("SWD line reset");
|
||||
if (kitprog_swd_seq(SEQUENCE_LINE_RESET) != ERROR_OK)
|
||||
return ERROR_FAIL;
|
||||
break;
|
||||
default:
|
||||
LOG_ERROR("Sequence %d not supported.", seq);
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
static int kitprog_swd_run_queue(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
size_t read_count = 0;
|
||||
size_t read_index = 0;
|
||||
size_t write_count = 0;
|
||||
uint8_t *buffer = kitprog_handle->packet_buffer;
|
||||
|
||||
do {
|
||||
LOG_DEBUG("Executing %d queued transactions", pending_transfer_count);
|
||||
|
||||
if (queued_retval != ERROR_OK) {
|
||||
LOG_DEBUG("Skipping due to previous errors: %d", queued_retval);
|
||||
break;
|
||||
}
|
||||
|
||||
if (!pending_transfer_count)
|
||||
break;
|
||||
|
||||
for (int i = 0; i < pending_transfer_count; i++) {
|
||||
uint8_t cmd = pending_transfers[i].cmd;
|
||||
uint32_t data = pending_transfers[i].data;
|
||||
|
||||
/* When proper WAIT handling is implemented in the
|
||||
* common SWD framework, this kludge can be
|
||||
* removed. However, this might lead to minor
|
||||
* performance degradation as the adapter wouldn't be
|
||||
* able to automatically retry anything (because ARM
|
||||
* has forgotten to implement sticky error flags
|
||||
* clearing). See also comments regarding
|
||||
* cmsis_dap_cmd_DAP_TFER_Configure() and
|
||||
* cmsis_dap_cmd_DAP_SWD_Configure() in
|
||||
* cmsis_dap_init().
|
||||
*/
|
||||
if (!(cmd & SWD_CMD_RnW) &&
|
||||
!(cmd & SWD_CMD_APnDP) &&
|
||||
(cmd & SWD_CMD_A32) >> 1 == DP_CTRL_STAT &&
|
||||
(data & CORUNDETECT)) {
|
||||
LOG_DEBUG("refusing to enable sticky overrun detection");
|
||||
data &= ~CORUNDETECT;
|
||||
}
|
||||
|
||||
#if 0
|
||||
LOG_DEBUG("%s %s reg %x %"PRIx32,
|
||||
cmd & SWD_CMD_APnDP ? "AP" : "DP",
|
||||
cmd & SWD_CMD_RnW ? "read" : "write",
|
||||
(cmd & SWD_CMD_A32) >> 1, data);
|
||||
#endif
|
||||
|
||||
buffer[write_count++] = (cmd | SWD_CMD_START | SWD_CMD_PARK) & ~SWD_CMD_STOP;
|
||||
read_count++;
|
||||
if (!(cmd & SWD_CMD_RnW)) {
|
||||
buffer[write_count++] = (data) & 0xff;
|
||||
buffer[write_count++] = (data >> 8) & 0xff;
|
||||
buffer[write_count++] = (data >> 16) & 0xff;
|
||||
buffer[write_count++] = (data >> 24) & 0xff;
|
||||
} else {
|
||||
read_count += 4;
|
||||
}
|
||||
}
|
||||
|
||||
ret = jtag_libusb_bulk_write(kitprog_handle->usb_handle,
|
||||
BULK_EP_OUT, (char *)buffer, write_count, 0);
|
||||
if (ret > 0) {
|
||||
queued_retval = ERROR_OK;
|
||||
} else {
|
||||
LOG_ERROR("Bulk write failed");
|
||||
queued_retval = ERROR_FAIL;
|
||||
break;
|
||||
}
|
||||
|
||||
/* We use the maximum buffer size here because the KitProg sometimes
|
||||
* doesn't like bulk reads of fewer than 62 bytes. (?!?!)
|
||||
*/
|
||||
ret = jtag_libusb_bulk_read(kitprog_handle->usb_handle,
|
||||
BULK_EP_IN | LIBUSB_ENDPOINT_IN, (char *)buffer,
|
||||
SWD_MAX_BUFFER_LENGTH, 0);
|
||||
if (ret > 0) {
|
||||
/* Handle garbage data by offsetting the initial read index */
|
||||
if ((unsigned int)ret > read_count)
|
||||
read_index = ret - read_count;
|
||||
queued_retval = ERROR_OK;
|
||||
} else {
|
||||
LOG_ERROR("Bulk read failed");
|
||||
queued_retval = ERROR_FAIL;
|
||||
break;
|
||||
}
|
||||
|
||||
for (int i = 0; i < pending_transfer_count; i++) {
|
||||
if (pending_transfers[i].cmd & SWD_CMD_RnW) {
|
||||
uint32_t data = le_to_h_u32(&buffer[read_index]);
|
||||
|
||||
#if 0
|
||||
LOG_DEBUG("Read result: %"PRIx32, data);
|
||||
#endif
|
||||
|
||||
if (pending_transfers[i].buffer)
|
||||
*(uint32_t *)pending_transfers[i].buffer = data;
|
||||
|
||||
read_index += 4;
|
||||
}
|
||||
|
||||
uint8_t ack = buffer[read_index] & 0x07;
|
||||
if (ack != SWD_ACK_OK || (buffer[read_index] & 0x08)) {
|
||||
LOG_DEBUG("SWD ack not OK: %d %s", i,
|
||||
ack == SWD_ACK_WAIT ? "WAIT" : ack == SWD_ACK_FAULT ? "FAULT" : "JUNK");
|
||||
queued_retval = ack == SWD_ACK_WAIT ? ERROR_WAIT : ERROR_FAIL;
|
||||
break;
|
||||
}
|
||||
read_index++;
|
||||
}
|
||||
} while (0);
|
||||
|
||||
pending_transfer_count = 0;
|
||||
int retval = queued_retval;
|
||||
queued_retval = ERROR_OK;
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
static void kitprog_swd_queue_cmd(uint8_t cmd, uint32_t *dst, uint32_t data)
|
||||
{
|
||||
if (pending_transfer_count == pending_queue_len) {
|
||||
/* Not enough room in the queue. Run the queue. */
|
||||
queued_retval = kitprog_swd_run_queue();
|
||||
}
|
||||
|
||||
if (queued_retval != ERROR_OK)
|
||||
return;
|
||||
|
||||
pending_transfers[pending_transfer_count].data = data;
|
||||
pending_transfers[pending_transfer_count].cmd = cmd;
|
||||
if (cmd & SWD_CMD_RnW) {
|
||||
/* Queue a read transaction */
|
||||
pending_transfers[pending_transfer_count].buffer = dst;
|
||||
}
|
||||
pending_transfer_count++;
|
||||
}
|
||||
|
||||
/*************** jtag lowlevel functions ********************/
|
||||
|
||||
static void kitprog_execute_reset(struct jtag_command *cmd)
|
||||
{
|
||||
int retval = ERROR_OK;
|
||||
|
||||
if (cmd->cmd.reset->srst == 1) {
|
||||
retval = kitprog_reset_target();
|
||||
/* Since the previous command also disables SWCLK output, we need to send an
|
||||
* SWD bus reset command to re-enable it. For some reason, running
|
||||
* kitprog_swd_seq() immediately after kitprog_reset_target() won't
|
||||
* actually fix this. Instead, kitprog_swd_seq() will be run once OpenOCD
|
||||
* tries to send a JTAG-to-SWD sequence, which should happen during
|
||||
* swd_check_reconnect (see the JTAG_TO_SWD case in kitprog_swd_switch_seq).
|
||||
*/
|
||||
}
|
||||
|
||||
if (retval != ERROR_OK)
|
||||
LOG_ERROR("KitProg: Interface reset failed");
|
||||
}
|
||||
|
||||
static void kitprog_execute_sleep(struct jtag_command *cmd)
|
||||
{
|
||||
jtag_sleep(cmd->cmd.sleep->us);
|
||||
}
|
||||
|
||||
static void kitprog_execute_command(struct jtag_command *cmd)
|
||||
{
|
||||
switch (cmd->type) {
|
||||
case JTAG_RESET:
|
||||
kitprog_execute_reset(cmd);
|
||||
break;
|
||||
case JTAG_SLEEP:
|
||||
kitprog_execute_sleep(cmd);
|
||||
break;
|
||||
default:
|
||||
LOG_ERROR("BUG: unknown JTAG command type encountered");
|
||||
exit(-1);
|
||||
}
|
||||
}
|
||||
|
||||
static int kitprog_execute_queue(void)
|
||||
{
|
||||
struct jtag_command *cmd = jtag_command_queue;
|
||||
|
||||
while (cmd != NULL) {
|
||||
kitprog_execute_command(cmd);
|
||||
cmd = cmd->next;
|
||||
}
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
COMMAND_HANDLER(kitprog_handle_info_command)
|
||||
{
|
||||
int retval = kitprog_get_info();
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
||||
COMMAND_HANDLER(kitprog_handle_acquire_psoc_command)
|
||||
{
|
||||
int retval = kitprog_generic_acquire();
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
COMMAND_HANDLER(kitprog_handle_serial_command)
|
||||
{
|
||||
if (CMD_ARGC == 1) {
|
||||
size_t len = strlen(CMD_ARGV[0]);
|
||||
kitprog_serial = calloc(len + 1, sizeof(char));
|
||||
if (kitprog_serial == NULL) {
|
||||
LOG_ERROR("Failed to allocate memory for the serial number");
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
strncpy(kitprog_serial, CMD_ARGV[0], len + 1);
|
||||
} else {
|
||||
LOG_ERROR("expected exactly one argument to kitprog_serial <serial-number>");
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
COMMAND_HANDLER(kitprog_handle_init_acquire_psoc_command)
|
||||
{
|
||||
kitprog_init_acquire_psoc = true;
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
static const struct command_registration kitprog_subcommand_handlers[] = {
|
||||
{
|
||||
.name = "info",
|
||||
.handler = &kitprog_handle_info_command,
|
||||
.mode = COMMAND_EXEC,
|
||||
.usage = "",
|
||||
.help = "show KitProg info",
|
||||
},
|
||||
{
|
||||
.name = "acquire_psoc",
|
||||
.handler = &kitprog_handle_acquire_psoc_command,
|
||||
.mode = COMMAND_EXEC,
|
||||
.usage = "",
|
||||
.help = "try to acquire a PSoC",
|
||||
},
|
||||
COMMAND_REGISTRATION_DONE
|
||||
};
|
||||
|
||||
static const struct command_registration kitprog_command_handlers[] = {
|
||||
{
|
||||
.name = "kitprog",
|
||||
.mode = COMMAND_ANY,
|
||||
.help = "perform KitProg management",
|
||||
.usage = "<cmd>",
|
||||
.chain = kitprog_subcommand_handlers,
|
||||
},
|
||||
{
|
||||
.name = "kitprog_serial",
|
||||
.handler = &kitprog_handle_serial_command,
|
||||
.mode = COMMAND_CONFIG,
|
||||
.help = "set the serial number of the adapter",
|
||||
.usage = "serial_string",
|
||||
},
|
||||
{
|
||||
.name = "kitprog_init_acquire_psoc",
|
||||
.handler = &kitprog_handle_init_acquire_psoc_command,
|
||||
.mode = COMMAND_CONFIG,
|
||||
.help = "try to acquire a PSoC during init",
|
||||
.usage = "",
|
||||
},
|
||||
COMMAND_REGISTRATION_DONE
|
||||
};
|
||||
|
||||
static const struct swd_driver kitprog_swd = {
|
||||
.init = kitprog_swd_init,
|
||||
.switch_seq = kitprog_swd_switch_seq,
|
||||
.read_reg = kitprog_swd_read_reg,
|
||||
.write_reg = kitprog_swd_write_reg,
|
||||
.run = kitprog_swd_run_queue,
|
||||
};
|
||||
|
||||
static const char * const kitprog_transports[] = { "swd", NULL };
|
||||
|
||||
struct jtag_interface kitprog_interface = {
|
||||
.name = "kitprog",
|
||||
.commands = kitprog_command_handlers,
|
||||
.transports = kitprog_transports,
|
||||
.swd = &kitprog_swd,
|
||||
.execute_queue = kitprog_execute_queue,
|
||||
.init = kitprog_init,
|
||||
.quit = kitprog_quit
|
||||
};
|
||||
Submodule src/jtag/drivers/libjaylink updated: d57dee67bc...699b7001d3
@@ -146,7 +146,7 @@ int jtag_libusb_set_configuration(jtag_libusb_device_handle *devh,
|
||||
int jtag_libusb_choose_interface(struct jtag_libusb_device_handle *devh,
|
||||
unsigned int *usb_read_ep,
|
||||
unsigned int *usb_write_ep,
|
||||
int bclass, int subclass, int protocol)
|
||||
int bclass, int subclass, int protocol, int trans_type)
|
||||
{
|
||||
struct jtag_libusb_device *udev = jtag_libusb_get_device(devh);
|
||||
struct usb_interface *iface = udev->config->interface;
|
||||
@@ -157,7 +157,8 @@ int jtag_libusb_choose_interface(struct jtag_libusb_device_handle *devh,
|
||||
for (int i = 0; i < desc->bNumEndpoints; i++) {
|
||||
if ((bclass > 0 && desc->bInterfaceClass != bclass) ||
|
||||
(subclass > 0 && desc->bInterfaceSubClass != subclass) ||
|
||||
(protocol > 0 && desc->bInterfaceProtocol != protocol))
|
||||
(protocol > 0 && desc->bInterfaceProtocol != protocol) ||
|
||||
(trans_type > 0 && (desc->endpoint[i].bmAttributes & 0x3) != trans_type))
|
||||
continue;
|
||||
|
||||
uint8_t epnum = desc->endpoint[i].bEndpointAddress;
|
||||
|
||||
@@ -67,7 +67,7 @@ int jtag_libusb_set_configuration(jtag_libusb_device_handle *devh,
|
||||
int jtag_libusb_choose_interface(struct jtag_libusb_device_handle *devh,
|
||||
unsigned int *usb_read_ep,
|
||||
unsigned int *usb_write_ep,
|
||||
int bclass, int subclass, int protocol);
|
||||
int bclass, int subclass, int protocol, int trans_type);
|
||||
int jtag_libusb_get_pid(struct jtag_libusb_device *dev, uint16_t *pid);
|
||||
|
||||
#endif /* OPENOCD_JTAG_DRIVERS_LIBUSB0_COMMON_H */
|
||||
|
||||
@@ -187,7 +187,7 @@ int jtag_libusb_set_configuration(jtag_libusb_device_handle *devh,
|
||||
int jtag_libusb_choose_interface(struct jtag_libusb_device_handle *devh,
|
||||
unsigned int *usb_read_ep,
|
||||
unsigned int *usb_write_ep,
|
||||
int bclass, int subclass, int protocol)
|
||||
int bclass, int subclass, int protocol, int trans_type)
|
||||
{
|
||||
struct jtag_libusb_device *udev = jtag_libusb_get_device(devh);
|
||||
const struct libusb_interface *inter;
|
||||
@@ -210,6 +210,8 @@ int jtag_libusb_choose_interface(struct jtag_libusb_device_handle *devh,
|
||||
continue;
|
||||
|
||||
epdesc = &interdesc->endpoint[k];
|
||||
if (trans_type > 0 && (epdesc->bmAttributes & 0x3) != trans_type)
|
||||
continue;
|
||||
|
||||
uint8_t epnum = epdesc->bEndpointAddress;
|
||||
bool is_input = epnum & 0x80;
|
||||
|
||||
@@ -69,12 +69,13 @@ int jtag_libusb_set_configuration(jtag_libusb_device_handle *devh,
|
||||
* @param bclass `bInterfaceClass` to match, or -1 to ignore this field.
|
||||
* @param subclass `bInterfaceSubClass` to match, or -1 to ignore this field.
|
||||
* @param protocol `bInterfaceProtocol` to match, or -1 to ignore this field.
|
||||
* @param trans_type `bmAttributes Bits 0..1 Transfer type` to match, or -1 to ignore this field.
|
||||
* @returns Returns ERROR_OK on success, ERROR_FAIL otherwise.
|
||||
*/
|
||||
int jtag_libusb_choose_interface(struct jtag_libusb_device_handle *devh,
|
||||
unsigned int *usb_read_ep,
|
||||
unsigned int *usb_write_ep,
|
||||
int bclass, int subclass, int protocol);
|
||||
int bclass, int subclass, int protocol, int trans_type);
|
||||
int jtag_libusb_get_pid(struct jtag_libusb_device *dev, uint16_t *pid);
|
||||
|
||||
#endif /* OPENOCD_JTAG_DRIVERS_LIBUSB1_COMMON_H */
|
||||
|
||||
@@ -19,9 +19,9 @@
|
||||
#define OPENOCD_JTAG_DRIVERS_LIBUSB_COMMON_H
|
||||
|
||||
#ifdef HAVE_LIBUSB1
|
||||
#include <libusb1_common.h>
|
||||
#include "libusb1_common.h"
|
||||
#else
|
||||
#include <libusb0_common.h>
|
||||
#include "libusb0_common.h"
|
||||
#endif
|
||||
|
||||
#endif /* OPENOCD_JTAG_DRIVERS_LIBUSB_COMMON_H */
|
||||
|
||||
@@ -247,8 +247,8 @@ static bool open_matching_device(struct mpsse_ctx *ctx, const uint16_t *vid, con
|
||||
err = libusb_detach_kernel_driver(ctx->usb_dev, ctx->interface);
|
||||
if (err != LIBUSB_SUCCESS && err != LIBUSB_ERROR_NOT_FOUND
|
||||
&& err != LIBUSB_ERROR_NOT_SUPPORTED) {
|
||||
LOG_ERROR("libusb_detach_kernel_driver() failed with %s", libusb_error_name(err));
|
||||
goto error;
|
||||
LOG_WARNING("libusb_detach_kernel_driver() failed with %s, trying to continue anyway",
|
||||
libusb_error_name(err));
|
||||
}
|
||||
|
||||
err = libusb_claim_interface(ctx->usb_dev, ctx->interface);
|
||||
@@ -872,6 +872,8 @@ int mpsse_flush(struct mpsse_ctx *ctx)
|
||||
libusb_fill_bulk_transfer(write_transfer, ctx->usb_dev, ctx->out_ep, ctx->write_buffer,
|
||||
ctx->write_count, write_cb, &write_result, ctx->usb_write_timeout);
|
||||
retval = libusb_submit_transfer(write_transfer);
|
||||
if (retval != LIBUSB_SUCCESS)
|
||||
goto error_check;
|
||||
|
||||
if (ctx->read_count) {
|
||||
read_transfer = libusb_alloc_transfer(0);
|
||||
@@ -879,22 +881,36 @@ int mpsse_flush(struct mpsse_ctx *ctx)
|
||||
ctx->read_chunk_size, read_cb, &read_result,
|
||||
ctx->usb_read_timeout);
|
||||
retval = libusb_submit_transfer(read_transfer);
|
||||
if (retval != LIBUSB_SUCCESS)
|
||||
goto error_check;
|
||||
}
|
||||
|
||||
/* Polling loop, more or less taken from libftdi */
|
||||
while (!write_result.done || !read_result.done) {
|
||||
retval = libusb_handle_events(ctx->usb_ctx);
|
||||
struct timeval timeout_usb;
|
||||
|
||||
timeout_usb.tv_sec = 1;
|
||||
timeout_usb.tv_usec = 0;
|
||||
|
||||
retval = libusb_handle_events_timeout_completed(ctx->usb_ctx, &timeout_usb, NULL);
|
||||
keep_alive();
|
||||
if (retval != LIBUSB_SUCCESS && retval != LIBUSB_ERROR_INTERRUPTED) {
|
||||
if (retval == LIBUSB_ERROR_NO_DEVICE || retval == LIBUSB_ERROR_INTERRUPTED)
|
||||
break;
|
||||
|
||||
if (retval != LIBUSB_SUCCESS) {
|
||||
libusb_cancel_transfer(write_transfer);
|
||||
if (read_transfer)
|
||||
libusb_cancel_transfer(read_transfer);
|
||||
while (!write_result.done || !read_result.done)
|
||||
if (libusb_handle_events(ctx->usb_ctx) != LIBUSB_SUCCESS)
|
||||
while (!write_result.done || !read_result.done) {
|
||||
retval = libusb_handle_events_timeout_completed(ctx->usb_ctx,
|
||||
&timeout_usb, NULL);
|
||||
if (retval != LIBUSB_SUCCESS)
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
error_check:
|
||||
if (retval != LIBUSB_SUCCESS) {
|
||||
LOG_ERROR("libusb_handle_events() failed with %s", libusb_error_name(retval));
|
||||
retval = ERROR_FAIL;
|
||||
|
||||
+248
-184
@@ -2,6 +2,10 @@
|
||||
* Driver for OpenJTAG Project (www.openjtag.org) *
|
||||
* Compatible with libftdi and ftd2xx drivers. *
|
||||
* *
|
||||
* Cypress CY7C65215 support *
|
||||
* Copyright (C) 2015 Vianney le Clément de Saint-Marcq, Essensium NV *
|
||||
* <vianney.leclement@essensium.com> *
|
||||
* *
|
||||
* Copyright (C) 2010 by Ivan Meleca <mileca@gmail.com> *
|
||||
* *
|
||||
* Copyright (C) 2013 by Ryan Corbin, GlueLogix Inc. <corbin.ryan@gmail.com> *
|
||||
@@ -41,7 +45,18 @@
|
||||
|
||||
#include <jtag/interface.h>
|
||||
#include <jtag/commands.h>
|
||||
#include "usb_common.h"
|
||||
#include "libusb_common.h"
|
||||
|
||||
static enum {
|
||||
OPENJTAG_VARIANT_STANDARD,
|
||||
OPENJTAG_VARIANT_CY7C65215,
|
||||
} openjtag_variant = OPENJTAG_VARIANT_STANDARD;
|
||||
|
||||
static const char * const openjtag_variant_names[] = {
|
||||
"standard",
|
||||
"cy7c65215",
|
||||
NULL
|
||||
};
|
||||
|
||||
/*
|
||||
* OpenJTAG-OpenOCD state conversion
|
||||
@@ -66,19 +81,8 @@ typedef enum openjtag_tap_state {
|
||||
OPENJTAG_TAP_UPDATE_IR = 15,
|
||||
} openjtag_tap_state_t;
|
||||
|
||||
#if (BUILD_OPENJTAG_FTD2XX == 1 && BUILD_OPENJTAG_LIBFTDI == 1)
|
||||
#error "BUILD_OPENJTAG_FTD2XX && BUILD_OPENJTAG_LIBFTDI "
|
||||
"are mutually exclusive"
|
||||
#elif (BUILD_OPENJTAG_FTD2XX != 1 && BUILD_OPENJTAG_LIBFTDI != 1)
|
||||
#error "BUILD_OPENJTAG_FTD2XX || BUILD_OPENJTAG_LIBFTDI must be chosen"
|
||||
#endif
|
||||
|
||||
/* OPENJTAG access library includes */
|
||||
#if BUILD_OPENJTAG_FTD2XX == 1
|
||||
#include <ftd2xx.h>
|
||||
#elif BUILD_OPENJTAG_LIBFTDI == 1
|
||||
#include <ftdi.h>
|
||||
#endif
|
||||
|
||||
/* OpenJTAG vid/pid */
|
||||
static uint16_t openjtag_vid = 0x0403;
|
||||
@@ -86,12 +90,7 @@ static uint16_t openjtag_pid = 0x6001;
|
||||
|
||||
static char *openjtag_device_desc;
|
||||
|
||||
#if BUILD_OPENJTAG_FTD2XX == 1
|
||||
static FT_HANDLE ftdih;
|
||||
|
||||
#elif BUILD_OPENJTAG_LIBFTDI == 1
|
||||
static struct ftdi_context ftdic;
|
||||
#endif
|
||||
|
||||
#define OPENJTAG_BUFFER_SIZE 504
|
||||
#define OPENJTAG_MAX_PENDING_RESULTS 256
|
||||
@@ -112,10 +111,24 @@ static uint8_t usb_rx_buf[OPENJTAG_BUFFER_SIZE];
|
||||
static struct openjtag_scan_result openjtag_scan_result_buffer[OPENJTAG_MAX_PENDING_RESULTS];
|
||||
static int openjtag_scan_result_count;
|
||||
|
||||
/* Openocd usb handler */
|
||||
struct openocd {
|
||||
struct usb_dev_handle *usb_handle;
|
||||
};
|
||||
static jtag_libusb_device_handle *usbh;
|
||||
|
||||
/* CY7C65215 model only */
|
||||
#define CY7C65215_JTAG_REQUEST 0x40 /* bmRequestType: vendor host-to-device */
|
||||
#define CY7C65215_JTAG_ENABLE 0xD0 /* bRequest: enable JTAG */
|
||||
#define CY7C65215_JTAG_DISABLE 0xD1 /* bRequest: disable JTAG */
|
||||
#define CY7C65215_JTAG_READ 0xD2 /* bRequest: read buffer */
|
||||
#define CY7C65215_JTAG_WRITE 0xD3 /* bRequest: write buffer */
|
||||
|
||||
#define CY7C65215_USB_TIMEOUT 100
|
||||
|
||||
static const uint16_t cy7c65215_vids[] = {0x04b4, 0};
|
||||
static const uint16_t cy7c65215_pids[] = {0x0007, 0};
|
||||
|
||||
#define CY7C65215_JTAG_CLASS 0xff
|
||||
#define CY7C65215_JTAG_SUBCLASS 0x04
|
||||
|
||||
static unsigned int ep_in, ep_out;
|
||||
|
||||
#ifdef _DEBUG_USB_COMMS_
|
||||
|
||||
@@ -201,26 +214,9 @@ static int8_t openjtag_get_tap_state(int8_t state)
|
||||
}
|
||||
}
|
||||
|
||||
static int openjtag_buf_write(
|
||||
static int openjtag_buf_write_standard(
|
||||
uint8_t *buf, int size, uint32_t *bytes_written)
|
||||
{
|
||||
#if BUILD_OPENJTAG_FTD2XX == 1
|
||||
FT_STATUS status;
|
||||
DWORD dw_bytes_written;
|
||||
|
||||
#ifdef _DEBUG_USB_COMMS_
|
||||
openjtag_debug_buffer(buf, size, DEBUG_TYPE_WRITE);
|
||||
#endif
|
||||
|
||||
status = FT_Write(ftdih, buf, size, &dw_bytes_written);
|
||||
if (status != FT_OK) {
|
||||
*bytes_written = dw_bytes_written;
|
||||
LOG_ERROR("FT_Write returned: %u", status);
|
||||
return ERROR_JTAG_DEVICE_ERROR;
|
||||
}
|
||||
*bytes_written = dw_bytes_written;
|
||||
return ERROR_OK;
|
||||
#elif BUILD_OPENJTAG_LIBFTDI == 1
|
||||
int retval;
|
||||
#ifdef _DEBUG_USB_COMMS_
|
||||
openjtag_debug_buffer(buf, size, DEBUG_TYPE_WRITE);
|
||||
@@ -236,36 +232,56 @@ static int openjtag_buf_write(
|
||||
*bytes_written += retval;
|
||||
|
||||
return ERROR_OK;
|
||||
#endif
|
||||
}
|
||||
|
||||
static int openjtag_buf_read(uint8_t *buf, uint32_t qty, uint32_t *bytes_read)
|
||||
static int openjtag_buf_write_cy7c65215(
|
||||
uint8_t *buf, int size, uint32_t *bytes_written)
|
||||
{
|
||||
|
||||
#if BUILD_OPENJTAG_FTD2XX == 1
|
||||
DWORD dw_bytes_read;
|
||||
FT_STATUS status;
|
||||
int timeout = 50;
|
||||
|
||||
*bytes_read = 0;
|
||||
while (qty && (*bytes_read < qty) && timeout--) {
|
||||
|
||||
status = FT_Read(ftdih, buf + *bytes_read,
|
||||
qty - *bytes_read, &dw_bytes_read);
|
||||
if (status != FT_OK) {
|
||||
*bytes_read = dw_bytes_read;
|
||||
LOG_ERROR("FT_Read returned: %u", status);
|
||||
return ERROR_JTAG_DEVICE_ERROR;
|
||||
}
|
||||
*bytes_read += dw_bytes_read;
|
||||
}
|
||||
int ret;
|
||||
|
||||
#ifdef _DEBUG_USB_COMMS_
|
||||
openjtag_debug_buffer(buf, *bytes_read, DEBUG_TYPE_READ);
|
||||
openjtag_debug_buffer(buf, size, DEBUG_TYPE_WRITE);
|
||||
#endif
|
||||
|
||||
if (size == 0) {
|
||||
*bytes_written = 0;
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
ret = jtag_libusb_control_transfer(usbh, CY7C65215_JTAG_REQUEST,
|
||||
CY7C65215_JTAG_WRITE, size, 0,
|
||||
NULL, 0, CY7C65215_USB_TIMEOUT);
|
||||
if (ret < 0) {
|
||||
LOG_ERROR("vendor command failed, error %d", ret);
|
||||
return ERROR_JTAG_DEVICE_ERROR;
|
||||
}
|
||||
|
||||
ret = jtag_libusb_bulk_write(usbh, ep_out, (char *)buf, size,
|
||||
CY7C65215_USB_TIMEOUT);
|
||||
if (ret < 0) {
|
||||
LOG_ERROR("bulk write failed, error %d", ret);
|
||||
return ERROR_JTAG_DEVICE_ERROR;
|
||||
}
|
||||
*bytes_written = ret;
|
||||
|
||||
return ERROR_OK;
|
||||
#elif BUILD_OPENJTAG_LIBFTDI == 1
|
||||
}
|
||||
|
||||
static int openjtag_buf_write(
|
||||
uint8_t *buf, int size, uint32_t *bytes_written)
|
||||
{
|
||||
switch (openjtag_variant) {
|
||||
case OPENJTAG_VARIANT_CY7C65215:
|
||||
return openjtag_buf_write_cy7c65215(buf, size, bytes_written);
|
||||
default:
|
||||
return openjtag_buf_write_standard(buf, size, bytes_written);
|
||||
}
|
||||
}
|
||||
|
||||
static int openjtag_buf_read_standard(
|
||||
uint8_t *buf, uint32_t qty, uint32_t *bytes_read)
|
||||
{
|
||||
|
||||
int retval;
|
||||
int timeout = 5;
|
||||
|
||||
@@ -287,10 +303,53 @@ static int openjtag_buf_read(uint8_t *buf, uint32_t qty, uint32_t *bytes_read)
|
||||
openjtag_debug_buffer(buf, *bytes_read, DEBUG_TYPE_READ);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
static int openjtag_buf_read_cy7c65215(
|
||||
uint8_t *buf, uint32_t qty, uint32_t *bytes_read)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (qty == 0) {
|
||||
*bytes_read = 0;
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = jtag_libusb_control_transfer(usbh, CY7C65215_JTAG_REQUEST,
|
||||
CY7C65215_JTAG_READ, qty, 0,
|
||||
NULL, 0, CY7C65215_USB_TIMEOUT);
|
||||
if (ret < 0) {
|
||||
LOG_ERROR("vendor command failed, error %d", ret);
|
||||
return ERROR_JTAG_DEVICE_ERROR;
|
||||
}
|
||||
|
||||
ret = jtag_libusb_bulk_read(usbh, ep_in, (char *)buf, qty,
|
||||
CY7C65215_USB_TIMEOUT);
|
||||
if (ret < 0) {
|
||||
LOG_ERROR("bulk read failed, error %d", ret);
|
||||
return ERROR_JTAG_DEVICE_ERROR;
|
||||
}
|
||||
*bytes_read = ret;
|
||||
|
||||
out:
|
||||
#ifdef _DEBUG_USB_COMMS_
|
||||
openjtag_debug_buffer(buf, *bytes_read, DEBUG_TYPE_READ);
|
||||
#endif
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
static int openjtag_buf_read(uint8_t *buf, uint32_t qty, uint32_t *bytes_read)
|
||||
{
|
||||
switch (openjtag_variant) {
|
||||
case OPENJTAG_VARIANT_CY7C65215:
|
||||
return openjtag_buf_read_cy7c65215(buf, qty, bytes_read);
|
||||
default:
|
||||
return openjtag_buf_read_standard(buf, qty, bytes_read);
|
||||
}
|
||||
}
|
||||
|
||||
static int openjtag_sendcommand(uint8_t cmd)
|
||||
{
|
||||
uint32_t written;
|
||||
@@ -335,109 +394,17 @@ static int openjtag_speed(int speed)
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
static int openjtag_init(void)
|
||||
static int openjtag_init_standard(void)
|
||||
{
|
||||
uint8_t latency_timer;
|
||||
|
||||
#if BUILD_OPENJTAG_FTD2XX == 1
|
||||
FT_STATUS status;
|
||||
#endif
|
||||
|
||||
usb_tx_buf_offs = 0;
|
||||
usb_rx_buf_len = 0;
|
||||
openjtag_scan_result_count = 0;
|
||||
|
||||
#if BUILD_OPENJTAG_FTD2XX == 1
|
||||
LOG_DEBUG("'openjtag' interface using FTD2XX");
|
||||
#elif BUILD_OPENJTAG_LIBFTDI == 1
|
||||
LOG_DEBUG("'openjtag' interface using libftdi");
|
||||
#endif
|
||||
|
||||
/* Open by device description */
|
||||
if (openjtag_device_desc == NULL) {
|
||||
LOG_WARNING("no openjtag device description specified, "
|
||||
/* Open by device description */
|
||||
if (openjtag_device_desc == NULL) {
|
||||
LOG_WARNING("no openjtag device description specified, "
|
||||
"using default 'Open JTAG Project'");
|
||||
openjtag_device_desc = "Open JTAG Project";
|
||||
}
|
||||
|
||||
#if BUILD_OPENJTAG_FTD2XX == 1
|
||||
|
||||
#if IS_WIN32 == 0
|
||||
/* Add non-standard Vid/Pid to the linux driver */
|
||||
status = FT_SetVIDPID(openjtag_vid, openjtag_pid);
|
||||
if (status != FT_OK) {
|
||||
LOG_WARNING("couldn't add %4.4x:%4.4x",
|
||||
openjtag_vid, openjtag_pid);
|
||||
}
|
||||
#endif
|
||||
|
||||
status = FT_OpenEx(openjtag_device_desc, FT_OPEN_BY_DESCRIPTION,
|
||||
&ftdih);
|
||||
if (status != FT_OK) {
|
||||
DWORD num_devices;
|
||||
|
||||
LOG_ERROR("unable to open ftdi device: %u", status);
|
||||
status = FT_ListDevices(&num_devices, NULL,
|
||||
FT_LIST_NUMBER_ONLY);
|
||||
if (status == FT_OK) {
|
||||
char **desc_array = malloc(sizeof(char *)
|
||||
* (num_devices + 1));
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < num_devices; i++)
|
||||
desc_array[i] = malloc(64);
|
||||
desc_array[num_devices] = NULL;
|
||||
|
||||
status = FT_ListDevices(desc_array, &num_devices,
|
||||
FT_LIST_ALL | FT_OPEN_BY_DESCRIPTION);
|
||||
|
||||
if (status == FT_OK) {
|
||||
LOG_ERROR("ListDevices: %u\n", num_devices);
|
||||
for (i = 0; i < num_devices; i++)
|
||||
LOG_ERROR("%i: %s", i, desc_array[i]);
|
||||
}
|
||||
|
||||
for (i = 0; i < num_devices; i++)
|
||||
free(desc_array[i]);
|
||||
free(desc_array);
|
||||
} else {
|
||||
LOG_ERROR("ListDevices: NONE\n");
|
||||
}
|
||||
return ERROR_JTAG_INIT_FAILED;
|
||||
openjtag_device_desc = "Open JTAG Project";
|
||||
}
|
||||
|
||||
status = FT_SetLatencyTimer(ftdih, 2);
|
||||
if (status != FT_OK) {
|
||||
LOG_ERROR("unable to set latency timer: %u", status);
|
||||
return ERROR_JTAG_INIT_FAILED;
|
||||
}
|
||||
|
||||
status = FT_GetLatencyTimer(ftdih, &latency_timer);
|
||||
if (status != FT_OK) {
|
||||
LOG_ERROR("unable to get latency timer: %u", status);
|
||||
return ERROR_JTAG_INIT_FAILED;
|
||||
}
|
||||
LOG_DEBUG("current latency timer: %i", latency_timer);
|
||||
|
||||
status = FT_SetBitMode(ftdih, 0x00, 0x40);
|
||||
if (status != FT_OK) {
|
||||
LOG_ERROR("unable to disable bit i/o mode: %u", status);
|
||||
return ERROR_JTAG_INIT_FAILED;
|
||||
}
|
||||
|
||||
status = FT_SetTimeouts(ftdih, 50, 0);
|
||||
if (status != FT_OK) {
|
||||
LOG_ERROR("unable to set timeouts: %u", status);
|
||||
return ERROR_JTAG_INIT_FAILED;
|
||||
}
|
||||
|
||||
status = FT_Purge(ftdih, FT_PURGE_RX | FT_PURGE_TX);
|
||||
if (status != FT_OK) {
|
||||
LOG_ERROR("unable to FT_Purge() %u", status);
|
||||
return ERROR_JTAG_INIT_FAILED;
|
||||
}
|
||||
|
||||
#elif BUILD_OPENJTAG_LIBFTDI == 1
|
||||
if (ftdi_init(&ftdic) < 0)
|
||||
return ERROR_JTAG_INIT_FAILED;
|
||||
|
||||
@@ -470,38 +437,107 @@ if (openjtag_device_desc == NULL) {
|
||||
ftdi_get_error_string(&ftdic));
|
||||
return ERROR_JTAG_DEVICE_ERROR;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if BUILD_OPENJTAG_FTD2XX == 1
|
||||
status = FT_Purge(ftdih, FT_PURGE_RX | FT_PURGE_TX);
|
||||
if (status != FT_OK)
|
||||
return ERROR_JTAG_INIT_FAILED;
|
||||
#elif BUILD_OPENJTAG_LIBFTDI == 1
|
||||
if (ftdi_usb_purge_buffers(&ftdic) < 0) {
|
||||
LOG_ERROR("ftdi_purge_buffers: %s", ftdic.error_str);
|
||||
return ERROR_JTAG_INIT_FAILED;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* OpenJTAG speed */
|
||||
openjtag_sendcommand(0xE0); /*Start at slowest adapter speed*/
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
/* MSB */
|
||||
openjtag_sendcommand(0x75);
|
||||
static int openjtag_init_cy7c65215(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
usbh = NULL;
|
||||
ret = jtag_libusb_open(cy7c65215_vids, cy7c65215_pids, NULL, &usbh);
|
||||
if (ret != ERROR_OK) {
|
||||
LOG_ERROR("unable to open cy7c65215 device");
|
||||
goto err;
|
||||
}
|
||||
|
||||
ret = jtag_libusb_choose_interface(usbh, &ep_in, &ep_out,
|
||||
CY7C65215_JTAG_CLASS,
|
||||
CY7C65215_JTAG_SUBCLASS, -1, LIBUSB_TRANSFER_TYPE_BULK);
|
||||
if (ret != ERROR_OK) {
|
||||
LOG_ERROR("unable to claim JTAG interface");
|
||||
goto err;
|
||||
}
|
||||
|
||||
ret = jtag_libusb_control_transfer(usbh,
|
||||
CY7C65215_JTAG_REQUEST,
|
||||
CY7C65215_JTAG_ENABLE,
|
||||
0, 0, NULL, 0, CY7C65215_USB_TIMEOUT);
|
||||
if (ret < 0) {
|
||||
LOG_ERROR("could not enable JTAG module");
|
||||
goto err;
|
||||
}
|
||||
|
||||
return ERROR_OK;
|
||||
|
||||
err:
|
||||
if (usbh != NULL)
|
||||
jtag_libusb_close(usbh);
|
||||
return ERROR_JTAG_INIT_FAILED;
|
||||
}
|
||||
|
||||
static int openjtag_init(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
usb_tx_buf_offs = 0;
|
||||
usb_rx_buf_len = 0;
|
||||
openjtag_scan_result_count = 0;
|
||||
|
||||
switch (openjtag_variant) {
|
||||
case OPENJTAG_VARIANT_CY7C65215:
|
||||
ret = openjtag_init_cy7c65215();
|
||||
break;
|
||||
default:
|
||||
ret = openjtag_init_standard();
|
||||
}
|
||||
if (ret != ERROR_OK)
|
||||
return ret;
|
||||
|
||||
openjtag_speed(375); /* Start at slowest adapter speed */
|
||||
openjtag_sendcommand(0x75); /* MSB */
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
static int openjtag_quit_standard(void)
|
||||
{
|
||||
ftdi_usb_close(&ftdic);
|
||||
ftdi_deinit(&ftdic);
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
static int openjtag_quit_cy7c65215(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = jtag_libusb_control_transfer(usbh,
|
||||
CY7C65215_JTAG_REQUEST,
|
||||
CY7C65215_JTAG_DISABLE,
|
||||
0, 0, NULL, 0, CY7C65215_USB_TIMEOUT);
|
||||
if (ret < 0)
|
||||
LOG_WARNING("could not disable JTAG module");
|
||||
|
||||
jtag_libusb_close(usbh);
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
static int openjtag_quit(void)
|
||||
{
|
||||
#if BUILD_OPENJTAG_FTD2XX == 1
|
||||
FT_Close(ftdih);
|
||||
#elif BUILD_OPENJTAG_LIBFTDI == 1
|
||||
ftdi_usb_close(&ftdic);
|
||||
ftdi_deinit(&ftdic);
|
||||
#endif
|
||||
|
||||
return ERROR_OK;
|
||||
switch (openjtag_variant) {
|
||||
case OPENJTAG_VARIANT_CY7C65215:
|
||||
return openjtag_quit_cy7c65215();
|
||||
default:
|
||||
return openjtag_quit_standard();
|
||||
}
|
||||
}
|
||||
|
||||
static void openjtag_write_tap_buffer(void)
|
||||
@@ -536,8 +572,8 @@ static int openjtag_execute_tap_queue(void)
|
||||
|
||||
uint8_t *buffer = openjtag_scan_result_buffer[res_count].buffer;
|
||||
|
||||
while (len) {
|
||||
if (len <= 8) {
|
||||
while (len > 0) {
|
||||
if (len <= 8 && openjtag_variant != OPENJTAG_VARIANT_CY7C65215) {
|
||||
DEBUG_JTAG_IO("bits < 8 buf = 0x%X, will be 0x%X",
|
||||
usb_rx_buf[rx_offs], usb_rx_buf[rx_offs] >> (8 - len));
|
||||
buffer[count] = usb_rx_buf[rx_offs] >> (8 - len);
|
||||
@@ -724,11 +760,14 @@ static void openjtag_execute_runtest(struct jtag_command *cmd)
|
||||
if (cmd->cmd.runtest->num_cycles > 16)
|
||||
LOG_WARNING("num_cycles > 16 on run test");
|
||||
|
||||
uint8_t command;
|
||||
command = 7;
|
||||
command |= ((cmd->cmd.runtest->num_cycles - 1) & 0x0F) << 4;
|
||||
if (openjtag_variant != OPENJTAG_VARIANT_CY7C65215 ||
|
||||
cmd->cmd.runtest->num_cycles) {
|
||||
uint8_t command;
|
||||
command = 7;
|
||||
command |= ((cmd->cmd.runtest->num_cycles - 1) & 0x0F) << 4;
|
||||
|
||||
openjtag_add_byte(command);
|
||||
openjtag_add_byte(command);
|
||||
}
|
||||
|
||||
tap_set_end_state(end_state);
|
||||
if (tap_get_end_state() != tap_get_state()) {
|
||||
@@ -816,6 +855,24 @@ COMMAND_HANDLER(openjtag_handle_device_desc_command)
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
COMMAND_HANDLER(openjtag_handle_variant_command)
|
||||
{
|
||||
if (CMD_ARGC == 1) {
|
||||
const char * const *name = openjtag_variant_names;
|
||||
int variant = 0;
|
||||
for (; *name; name++, variant++) {
|
||||
if (strcasecmp(CMD_ARGV[0], *name) == 0) {
|
||||
openjtag_variant = variant;
|
||||
return ERROR_OK;
|
||||
}
|
||||
}
|
||||
LOG_ERROR("unknown openjtag variant '%s'", CMD_ARGV[0]);
|
||||
} else {
|
||||
LOG_ERROR("require exactly one argument to "
|
||||
"openjtag_variant <variant>");
|
||||
}
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
static const struct command_registration openjtag_command_handlers[] = {
|
||||
{
|
||||
@@ -825,6 +882,13 @@ static const struct command_registration openjtag_command_handlers[] = {
|
||||
.help = "set the USB device description of the OpenJTAG",
|
||||
.usage = "description-string",
|
||||
},
|
||||
{
|
||||
.name = "openjtag_variant",
|
||||
.handler = openjtag_handle_variant_command,
|
||||
.mode = COMMAND_CONFIG,
|
||||
.help = "set the OpenJTAG variant",
|
||||
.usage = "variant-string",
|
||||
},
|
||||
COMMAND_REGISTRATION_DONE
|
||||
};
|
||||
|
||||
|
||||
@@ -34,14 +34,7 @@
|
||||
#include "bitq.h"
|
||||
|
||||
/* PRESTO access library includes */
|
||||
#if BUILD_PRESTO_FTD2XX == 1
|
||||
#include <ftd2xx.h>
|
||||
#include "ftd2xx_common.h"
|
||||
#elif BUILD_PRESTO_LIBFTDI == 1
|
||||
#include <ftdi.h>
|
||||
#else
|
||||
#error "BUG: either FTD2XX and LIBFTDI has to be used"
|
||||
#endif
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
@@ -55,13 +48,8 @@
|
||||
#define BUFFER_SIZE (64*62)
|
||||
|
||||
struct presto {
|
||||
#if BUILD_PRESTO_FTD2XX == 1
|
||||
FT_HANDLE handle;
|
||||
FT_STATUS status;
|
||||
#elif BUILD_PRESTO_LIBFTDI == 1
|
||||
struct ftdi_context ftdic;
|
||||
int retval;
|
||||
#endif
|
||||
|
||||
char serial[FT_DEVICE_SERNUM_LEN];
|
||||
|
||||
@@ -95,15 +83,6 @@ static uint8_t presto_init_seq[] = {
|
||||
|
||||
static int presto_write(uint8_t *buf, uint32_t size)
|
||||
{
|
||||
#if BUILD_PRESTO_FTD2XX == 1
|
||||
DWORD ftbytes;
|
||||
presto->status = FT_Write(presto->handle, buf, size, &ftbytes);
|
||||
if (presto->status != FT_OK) {
|
||||
LOG_ERROR("FT_Write returned: %s", ftd2xx_status_string(presto->status));
|
||||
return ERROR_JTAG_DEVICE_ERROR;
|
||||
}
|
||||
|
||||
#elif BUILD_PRESTO_LIBFTDI == 1
|
||||
uint32_t ftbytes;
|
||||
presto->retval = ftdi_write_data(&presto->ftdic, buf, size);
|
||||
if (presto->retval < 0) {
|
||||
@@ -111,7 +90,6 @@ static int presto_write(uint8_t *buf, uint32_t size)
|
||||
return ERROR_JTAG_DEVICE_ERROR;
|
||||
}
|
||||
ftbytes = presto->retval;
|
||||
#endif
|
||||
|
||||
if (ftbytes != size) {
|
||||
LOG_ERROR("couldn't write the requested number of bytes to PRESTO (%u < %u)",
|
||||
@@ -124,15 +102,6 @@ static int presto_write(uint8_t *buf, uint32_t size)
|
||||
|
||||
static int presto_read(uint8_t *buf, uint32_t size)
|
||||
{
|
||||
#if BUILD_PRESTO_FTD2XX == 1
|
||||
DWORD ftbytes;
|
||||
presto->status = FT_Read(presto->handle, buf, size, &ftbytes);
|
||||
if (presto->status != FT_OK) {
|
||||
LOG_ERROR("FT_Read returned: %s", ftd2xx_status_string(presto->status));
|
||||
return ERROR_JTAG_DEVICE_ERROR;
|
||||
}
|
||||
|
||||
#elif BUILD_PRESTO_LIBFTDI == 1
|
||||
uint32_t ftbytes = 0;
|
||||
|
||||
struct timeval timeout, now;
|
||||
@@ -152,7 +121,6 @@ static int presto_read(uint8_t *buf, uint32_t size)
|
||||
((now.tv_sec == timeout.tv_sec) && (now.tv_usec > timeout.tv_usec)))
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (ftbytes != size) {
|
||||
/* this is just a warning, there might have been timeout when detecting PRESTO,
|
||||
@@ -165,150 +133,6 @@ static int presto_read(uint8_t *buf, uint32_t size)
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
#if BUILD_PRESTO_FTD2XX == 1
|
||||
static int presto_open_ftd2xx(char *req_serial)
|
||||
{
|
||||
uint32_t i;
|
||||
DWORD numdevs;
|
||||
DWORD vidpid;
|
||||
char devname[FT_DEVICE_NAME_LEN];
|
||||
FT_DEVICE device;
|
||||
|
||||
BYTE presto_data;
|
||||
DWORD ftbytes;
|
||||
|
||||
presto->handle = (FT_HANDLE)INVALID_HANDLE_VALUE;
|
||||
|
||||
#if IS_WIN32 == 0
|
||||
/* Add non-standard Vid/Pid to the linux driver */
|
||||
presto->status = FT_SetVIDPID(PRESTO_VID, PRESTO_PID);
|
||||
if (presto->status != FT_OK) {
|
||||
LOG_ERROR("couldn't add PRESTO VID/PID");
|
||||
exit(-1);
|
||||
}
|
||||
#endif
|
||||
|
||||
presto->status = FT_ListDevices(&numdevs, NULL, FT_LIST_NUMBER_ONLY);
|
||||
if (presto->status != FT_OK) {
|
||||
LOG_ERROR("FT_ListDevices failed: %s", ftd2xx_status_string(presto->status));
|
||||
return ERROR_JTAG_DEVICE_ERROR;
|
||||
}
|
||||
|
||||
LOG_DEBUG("FTDI devices available: %" PRIu32, (uint32_t)numdevs);
|
||||
for (i = 0; i < numdevs; i++) {
|
||||
presto->status = FT_Open(i, &(presto->handle));
|
||||
if (presto->status != FT_OK) {
|
||||
/* this is not fatal, the device may be legitimately open by other process,
|
||||
*hence debug message only */
|
||||
LOG_DEBUG("FT_Open failed: %s", ftd2xx_status_string(presto->status));
|
||||
continue;
|
||||
}
|
||||
LOG_DEBUG("FTDI device %i open", (int)i);
|
||||
|
||||
presto->status = FT_GetDeviceInfo(presto->handle, &device,
|
||||
&vidpid, presto->serial, devname, NULL);
|
||||
if (presto->status == FT_OK) {
|
||||
if (vidpid == PRESTO_VID_PID && (req_serial == NULL ||
|
||||
!strcmp(presto->serial, req_serial)))
|
||||
break;
|
||||
} else
|
||||
LOG_DEBUG("FT_GetDeviceInfo failed: %s", ftd2xx_status_string(
|
||||
presto->status));
|
||||
|
||||
LOG_DEBUG("FTDI device %i does not match, closing", (int)i);
|
||||
FT_Close(presto->handle);
|
||||
presto->handle = (FT_HANDLE)INVALID_HANDLE_VALUE;
|
||||
}
|
||||
|
||||
if (presto->handle == (FT_HANDLE)INVALID_HANDLE_VALUE)
|
||||
return ERROR_JTAG_DEVICE_ERROR; /* presto not open, return */
|
||||
|
||||
presto->status = FT_SetLatencyTimer(presto->handle, 1);
|
||||
if (presto->status != FT_OK)
|
||||
return ERROR_JTAG_DEVICE_ERROR;
|
||||
|
||||
presto->status = FT_SetTimeouts(presto->handle, 100, 0);
|
||||
if (presto->status != FT_OK)
|
||||
return ERROR_JTAG_DEVICE_ERROR;
|
||||
|
||||
presto->status = FT_Purge(presto->handle, FT_PURGE_TX | FT_PURGE_RX);
|
||||
if (presto->status != FT_OK)
|
||||
return ERROR_JTAG_DEVICE_ERROR;
|
||||
|
||||
presto_data = 0xD0;
|
||||
presto->status = FT_Write(presto->handle, &presto_data, 1, &ftbytes);
|
||||
if (presto->status != FT_OK)
|
||||
return ERROR_JTAG_DEVICE_ERROR;
|
||||
|
||||
/* delay between first write/read turnaround (after purge?) necessary
|
||||
* under Linux for unknown reason,
|
||||
* probably a bug in library threading */
|
||||
usleep(100000);
|
||||
presto->status = FT_Read(presto->handle, &presto_data, 1, &ftbytes);
|
||||
if (presto->status != FT_OK)
|
||||
return ERROR_JTAG_DEVICE_ERROR;
|
||||
|
||||
if (ftbytes != 1) {
|
||||
LOG_DEBUG("PRESTO reset");
|
||||
|
||||
presto->status = FT_Purge(presto->handle, FT_PURGE_TX | FT_PURGE_RX);
|
||||
if (presto->status != FT_OK)
|
||||
return ERROR_JTAG_DEVICE_ERROR;
|
||||
presto->status = FT_SetBitMode(presto->handle, 0x80, 1);
|
||||
if (presto->status != FT_OK)
|
||||
return ERROR_JTAG_DEVICE_ERROR;
|
||||
presto->status = FT_SetBaudRate(presto->handle, 9600);
|
||||
if (presto->status != FT_OK)
|
||||
return ERROR_JTAG_DEVICE_ERROR;
|
||||
|
||||
presto_data = 0;
|
||||
for (i = 0; i < 4 * 62; i++) {
|
||||
presto->status = FT_Write(presto->handle, &presto_data, 1, &ftbytes);
|
||||
if (presto->status != FT_OK)
|
||||
return ERROR_JTAG_DEVICE_ERROR;
|
||||
}
|
||||
usleep(100000);
|
||||
|
||||
presto->status = FT_SetBitMode(presto->handle, 0x00, 0);
|
||||
if (presto->status != FT_OK)
|
||||
return ERROR_JTAG_DEVICE_ERROR;
|
||||
|
||||
presto->status = FT_Purge(presto->handle, FT_PURGE_TX | FT_PURGE_RX);
|
||||
if (presto->status != FT_OK)
|
||||
return ERROR_JTAG_DEVICE_ERROR;
|
||||
|
||||
presto_data = 0xD0;
|
||||
presto->status = FT_Write(presto->handle, &presto_data, 1, &ftbytes);
|
||||
if (presto->status != FT_OK)
|
||||
return ERROR_JTAG_DEVICE_ERROR;
|
||||
|
||||
/* delay between first write/read turnaround (after purge?) necessary under Linux for unknown reason,
|
||||
probably a bug in library threading */
|
||||
usleep(100000);
|
||||
presto->status = FT_Read(presto->handle, &presto_data, 1, &ftbytes);
|
||||
if (presto->status != FT_OK)
|
||||
return ERROR_JTAG_DEVICE_ERROR;
|
||||
|
||||
if (ftbytes != 1) {
|
||||
LOG_DEBUG("PRESTO not responding");
|
||||
return ERROR_JTAG_DEVICE_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
presto->status = FT_SetTimeouts(presto->handle, 0, 0);
|
||||
if (presto->status != FT_OK)
|
||||
return ERROR_JTAG_DEVICE_ERROR;
|
||||
|
||||
presto->status = FT_Write(presto->handle, &presto_init_seq,
|
||||
sizeof(presto_init_seq), &ftbytes);
|
||||
|
||||
if (presto->status != FT_OK || ftbytes != sizeof(presto_init_seq))
|
||||
return ERROR_JTAG_DEVICE_ERROR;
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
#elif BUILD_PRESTO_LIBFTDI == 1
|
||||
static int presto_open_libftdi(char *req_serial)
|
||||
{
|
||||
uint8_t presto_data;
|
||||
@@ -371,7 +195,6 @@ static int presto_open_libftdi(char *req_serial)
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
#endif /* BUILD_PRESTO_LIBFTDI == 1 */
|
||||
|
||||
static int presto_open(char *req_serial)
|
||||
{
|
||||
@@ -391,11 +214,7 @@ static int presto_open(char *req_serial)
|
||||
|
||||
presto->jtag_speed = 0;
|
||||
|
||||
#if BUILD_PRESTO_FTD2XX == 1
|
||||
return presto_open_ftd2xx(req_serial);
|
||||
#elif BUILD_PRESTO_LIBFTDI == 1
|
||||
return presto_open_libftdi(req_serial);
|
||||
#endif
|
||||
}
|
||||
|
||||
static int presto_close(void)
|
||||
@@ -403,35 +222,6 @@ static int presto_close(void)
|
||||
|
||||
int result = ERROR_OK;
|
||||
|
||||
#if BUILD_PRESTO_FTD2XX == 1
|
||||
DWORD ftbytes;
|
||||
|
||||
if (presto->handle == (FT_HANDLE)INVALID_HANDLE_VALUE)
|
||||
return result;
|
||||
|
||||
presto->status = FT_Purge(presto->handle, FT_PURGE_TX | FT_PURGE_RX);
|
||||
if (presto->status != FT_OK)
|
||||
result = ERROR_JTAG_DEVICE_ERROR;
|
||||
|
||||
presto->status = FT_Write(presto->handle,
|
||||
&presto_init_seq,
|
||||
sizeof(presto_init_seq),
|
||||
&ftbytes);
|
||||
if (presto->status != FT_OK || ftbytes != sizeof(presto_init_seq))
|
||||
result = ERROR_JTAG_DEVICE_ERROR;
|
||||
|
||||
presto->status = FT_SetLatencyTimer(presto->handle, 16);
|
||||
if (presto->status != FT_OK)
|
||||
result = ERROR_JTAG_DEVICE_ERROR;
|
||||
|
||||
presto->status = FT_Close(presto->handle);
|
||||
if (presto->status != FT_OK)
|
||||
result = ERROR_JTAG_DEVICE_ERROR;
|
||||
else
|
||||
presto->handle = (FT_HANDLE)INVALID_HANDLE_VALUE;
|
||||
|
||||
#elif BUILD_PRESTO_LIBFTDI == 1
|
||||
|
||||
presto->retval = ftdi_write_data(&presto->ftdic, presto_init_seq, sizeof(presto_init_seq));
|
||||
if (presto->retval != sizeof(presto_init_seq))
|
||||
result = ERROR_JTAG_DEVICE_ERROR;
|
||||
@@ -445,7 +235,6 @@ static int presto_close(void)
|
||||
result = ERROR_JTAG_DEVICE_ERROR;
|
||||
else
|
||||
ftdi_deinit(&presto->ftdic);
|
||||
#endif
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -455,11 +244,7 @@ static int presto_flush(void)
|
||||
if (presto->buff_out_pos == 0)
|
||||
return ERROR_OK;
|
||||
|
||||
#if BUILD_PRESTO_FTD2XX == 1
|
||||
if (presto->status != FT_OK) {
|
||||
#elif BUILD_PRESTO_LIBFTDI == 1
|
||||
if (presto->retval < 0) {
|
||||
#endif
|
||||
LOG_DEBUG("error in previous communication, canceling I/O operation");
|
||||
return ERROR_JTAG_DEVICE_ERROR;
|
||||
}
|
||||
@@ -502,13 +287,9 @@ static int presto_sendbyte(int data)
|
||||
} else
|
||||
return ERROR_JTAG_DEVICE_ERROR;
|
||||
|
||||
#if BUILD_PRESTO_FTD2XX == 1
|
||||
if (presto->buff_out_pos >= BUFFER_SIZE)
|
||||
#elif BUILD_PRESTO_LIBFTDI == 1
|
||||
/* libftdi does not do background read, be sure that USB IN buffer does not overflow (128
|
||||
*bytes only!) */
|
||||
if (presto->buff_out_pos >= BUFFER_SIZE || presto->buff_in_exp == 128)
|
||||
#endif
|
||||
return presto_flush();
|
||||
|
||||
return ERROR_OK;
|
||||
|
||||
@@ -216,7 +216,7 @@ struct stlink_usb_handle_s {
|
||||
#define STLINK_DEBUG_APIV2_DRIVE_NRST_HIGH 0x01
|
||||
#define STLINK_DEBUG_APIV2_DRIVE_NRST_PULSE 0x02
|
||||
|
||||
#define STLINK_TRACE_SIZE 1024
|
||||
#define STLINK_TRACE_SIZE 4096
|
||||
#define STLINK_TRACE_MAX_HZ 2000000
|
||||
#define STLINK_TRACE_MIN_VERSION 13
|
||||
|
||||
|
||||
@@ -242,7 +242,8 @@ static int icdi_send_remote_cmd(void *handle, const char *data)
|
||||
struct icdi_usb_handle_s *h = handle;
|
||||
|
||||
size_t cmd_len = sprintf(h->write_buffer, PACKET_START "qRcmd,");
|
||||
cmd_len += hexify(h->write_buffer + cmd_len, data, 0, h->max_packet - cmd_len);
|
||||
cmd_len += hexify(h->write_buffer + cmd_len, (const uint8_t *)data,
|
||||
strlen(data), h->max_packet - cmd_len);
|
||||
|
||||
return icdi_send_packet(handle, cmd_len);
|
||||
}
|
||||
@@ -266,7 +267,7 @@ static int icdi_get_cmd_result(void *handle)
|
||||
|
||||
if (h->read_buffer[offset] == 'E') {
|
||||
/* get error code */
|
||||
char result;
|
||||
uint8_t result;
|
||||
if (unhexify(&result, h->read_buffer + offset + 1, 1) != 1)
|
||||
return ERROR_FAIL;
|
||||
return result;
|
||||
@@ -328,7 +329,7 @@ static int icdi_usb_version(void *handle)
|
||||
}
|
||||
|
||||
/* convert reply */
|
||||
if (unhexify(version, h->read_buffer + 2, 4) != 4) {
|
||||
if (unhexify((uint8_t *)version, h->read_buffer + 2, 4) != 4) {
|
||||
LOG_WARNING("unable to get ICDI version");
|
||||
return ERROR_OK;
|
||||
}
|
||||
@@ -495,7 +496,7 @@ static int icdi_usb_read_reg(void *handle, int num, uint32_t *val)
|
||||
|
||||
/* convert result */
|
||||
uint8_t buf[4];
|
||||
if (unhexify((char *)buf, h->read_buffer + 2, 4) != 4) {
|
||||
if (unhexify(buf, h->read_buffer + 2, 4) != 4) {
|
||||
LOG_ERROR("failed to convert result");
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
@@ -512,7 +513,7 @@ static int icdi_usb_write_reg(void *handle, int num, uint32_t val)
|
||||
h_u32_to_le(buf, val);
|
||||
|
||||
int cmd_len = snprintf(cmd, sizeof(cmd), "P%x=", num);
|
||||
hexify(cmd + cmd_len, (const char *)buf, 4, sizeof(cmd));
|
||||
hexify(cmd + cmd_len, buf, 4, sizeof(cmd));
|
||||
|
||||
result = icdi_send_cmd(handle, cmd);
|
||||
if (result != ERROR_OK)
|
||||
|
||||
@@ -2066,7 +2066,7 @@ static int ulink_khz(int khz, int *jtag_speed)
|
||||
}
|
||||
|
||||
#ifdef _DEBUG_JTAG_IO_
|
||||
long f_tck, f_tms, f_scan_in, f_scan_out, f_scan_io;
|
||||
long f_tck = 0, f_tms = 0, f_scan_in = 0, f_scan_out = 0, f_scan_io = 0;
|
||||
|
||||
ulink_calculate_frequency(DELAY_CLOCK_TCK, ulink_handle->delay_clock_tck,
|
||||
&f_tck);
|
||||
|
||||
@@ -1,24 +1,13 @@
|
||||
include $(top_srcdir)/common.mk
|
||||
noinst_LTLIBRARIES += %D%/libocdusbblaster.la
|
||||
%C%_libocdusbblaster_la_SOURCES = $(USB_BLASTER_SRC)
|
||||
%C%_libocdusbblaster_la_CPPFLAGS = -I$(top_srcdir)/src/jtag/drivers $(AM_CPPFLAGS) $(LIBUSB1_CFLAGS) $(LIBFTDI_CFLAGS)
|
||||
|
||||
AM_CPPFLAGS += -I$(top_srcdir)/src/jtag/drivers $(LIBUSB1_CFLAGS) $(LIBFTDI_CFLAGS)
|
||||
USB_BLASTER_SRC = %D%/usb_blaster.c %D%/ublast_access.h
|
||||
|
||||
noinst_LTLIBRARIES = libocdusbblaster.la
|
||||
libocdusbblaster_la_SOURCES = $(USB_BLASTER_SRC)
|
||||
|
||||
USB_BLASTER_SRC = usb_blaster.c
|
||||
|
||||
if USB_BLASTER_LIBFTDI
|
||||
USB_BLASTER_SRC += ublast_access_ftdi.c
|
||||
endif
|
||||
|
||||
if USB_BLASTER_FTD2XX
|
||||
USB_BLASTER_SRC += ublast_access_ftd2xx.c
|
||||
if USB_BLASTER
|
||||
USB_BLASTER_SRC += %D%/ublast_access_ftdi.c
|
||||
endif
|
||||
|
||||
if USB_BLASTER_2
|
||||
USB_BLASTER_SRC += ublast2_access_libusb.c
|
||||
USB_BLASTER_SRC += %D%/ublast2_access_libusb.c
|
||||
endif
|
||||
|
||||
noinst_HEADERS = ublast_access.h
|
||||
|
||||
MAINTAINERCLEANFILES = $(srcdir)/Makefile.in
|
||||
|
||||
@@ -56,19 +56,16 @@ struct ublast_lowlevel {
|
||||
|
||||
/**
|
||||
* ublast_register_ftdi - get a lowlevel USB Blaster driver
|
||||
* ublast_register_ftd2xx - get a lowlevel USB Blaster driver
|
||||
* ublast2_register_libusb - get a lowlevel USB Blaster II driver
|
||||
*
|
||||
* Get a lowlevel USB-Blaster driver. In the current implementation, there are 3
|
||||
* Get a lowlevel USB-Blaster driver. In the current implementation, there are 2
|
||||
* possible lowlevel drivers :
|
||||
* - one based on libftdi from ftdichip.com
|
||||
* - one based on libftdxx, the free alternative
|
||||
* - one based on libftdi,
|
||||
* - one based on libusb, specific to the USB-Blaster II
|
||||
*
|
||||
* Returns the lowlevel driver structure.
|
||||
*/
|
||||
extern struct ublast_lowlevel *ublast_register_ftdi(void);
|
||||
extern struct ublast_lowlevel *ublast_register_ftd2xx(void);
|
||||
extern struct ublast_lowlevel *ublast2_register_libusb(void);
|
||||
|
||||
#endif /* OPENOCD_JTAG_DRIVERS_USB_BLASTER_UBLAST_ACCESS_H */
|
||||
|
||||
@@ -1,180 +0,0 @@
|
||||
/*
|
||||
* Driver for USB-JTAG, Altera USB-Blaster and compatibles
|
||||
*
|
||||
* Inspired from original code from Kolja Waschk's USB-JTAG project
|
||||
* (http://www.ixo.de/info/usb_jtag/), and from openocd project.
|
||||
*
|
||||
* Copyright (C) 2012 Robert Jarzmik robert.jarzmik@free.fr
|
||||
* Copyright (C) 2011 Ali Lown ali@lown.me.uk
|
||||
* Copyright (C) 2009 Catalin Patulea cat@vv.carleton.ca
|
||||
* Copyright (C) 2006 Kolja Waschk usbjtag@ixo.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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
#include <jtag/interface.h>
|
||||
#include <jtag/commands.h>
|
||||
|
||||
#include "ublast_access.h"
|
||||
|
||||
#include <ftd2xx.h>
|
||||
#include "jtag/drivers/ftd2xx_common.h"
|
||||
|
||||
static FT_HANDLE *ublast_getftdih(struct ublast_lowlevel *low)
|
||||
{
|
||||
return low->priv;
|
||||
}
|
||||
|
||||
static int ublast_ftd2xx_write(struct ublast_lowlevel *low, uint8_t *buf, int size,
|
||||
uint32_t *bytes_written)
|
||||
{
|
||||
FT_STATUS status;
|
||||
DWORD dw_bytes_written;
|
||||
FT_HANDLE *ftdih = ublast_getftdih(low);
|
||||
|
||||
status = FT_Write(*ftdih, buf, size, &dw_bytes_written);
|
||||
if (status != FT_OK) {
|
||||
*bytes_written = dw_bytes_written;
|
||||
LOG_ERROR("FT_Write returned: %s", ftd2xx_status_string(status));
|
||||
return ERROR_JTAG_DEVICE_ERROR;
|
||||
}
|
||||
*bytes_written = dw_bytes_written;
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
static int ublast_ftd2xx_read(struct ublast_lowlevel *low, uint8_t *buf,
|
||||
unsigned size, uint32_t *bytes_read)
|
||||
{
|
||||
DWORD dw_bytes_read;
|
||||
FT_STATUS status;
|
||||
FT_HANDLE *ftdih = ublast_getftdih(low);
|
||||
|
||||
status = FT_Read(*ftdih, buf, size, &dw_bytes_read);
|
||||
if (status != FT_OK) {
|
||||
*bytes_read = dw_bytes_read;
|
||||
LOG_ERROR("FT_Read returned: %s", ftd2xx_status_string(status));
|
||||
return ERROR_JTAG_DEVICE_ERROR;
|
||||
}
|
||||
*bytes_read = dw_bytes_read;
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
static int ublast_ftd2xx_init(struct ublast_lowlevel *low)
|
||||
{
|
||||
FT_STATUS status;
|
||||
FT_HANDLE *ftdih = ublast_getftdih(low);
|
||||
uint8_t latency_timer;
|
||||
|
||||
LOG_INFO("usb blaster interface using FTD2XX");
|
||||
/* Open by device description */
|
||||
if (low->ublast_device_desc == NULL) {
|
||||
LOG_WARNING("no usb blaster device description specified, "
|
||||
"using default 'USB-Blaster'");
|
||||
low->ublast_device_desc = "USB-Blaster";
|
||||
}
|
||||
|
||||
#if IS_WIN32 == 0
|
||||
/* Add non-standard Vid/Pid to the linux driver */
|
||||
status = FT_SetVIDPID(low->ublast_vid, low->ublast_pid);
|
||||
if (status != FT_OK) {
|
||||
LOG_WARNING("couldn't add %4.4x:%4.4x",
|
||||
low->ublast_vid, low->ublast_pid);
|
||||
}
|
||||
#endif
|
||||
status = FT_OpenEx(low->ublast_device_desc, FT_OPEN_BY_DESCRIPTION,
|
||||
ftdih);
|
||||
if (status != FT_OK) {
|
||||
DWORD num_devices;
|
||||
|
||||
LOG_ERROR("unable to open ftdi device: %s",
|
||||
ftd2xx_status_string(status));
|
||||
status = FT_ListDevices(&num_devices, NULL, FT_LIST_NUMBER_ONLY);
|
||||
if (status == FT_OK) {
|
||||
char **desc_array =
|
||||
malloc(sizeof(char *) * (num_devices + 1));
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < num_devices; i++)
|
||||
desc_array[i] = malloc(64);
|
||||
desc_array[num_devices] = NULL;
|
||||
|
||||
status = FT_ListDevices(desc_array, &num_devices,
|
||||
FT_LIST_ALL | FT_OPEN_BY_DESCRIPTION);
|
||||
|
||||
if (status == FT_OK) {
|
||||
LOG_ERROR("ListDevices: %" PRIu32, (uint32_t)num_devices);
|
||||
for (i = 0; i < num_devices; i++)
|
||||
LOG_ERROR("%i: %s", i, desc_array[i]);
|
||||
}
|
||||
|
||||
for (i = 0; i < num_devices; i++)
|
||||
free(desc_array[i]);
|
||||
free(desc_array);
|
||||
} else {
|
||||
printf("ListDevices: NONE\n");
|
||||
}
|
||||
return ERROR_JTAG_INIT_FAILED;
|
||||
}
|
||||
|
||||
status = FT_SetLatencyTimer(*ftdih, 2);
|
||||
if (status != FT_OK) {
|
||||
LOG_ERROR("unable to set latency timer: %s",
|
||||
ftd2xx_status_string(status));
|
||||
return ERROR_JTAG_INIT_FAILED;
|
||||
}
|
||||
|
||||
status = FT_GetLatencyTimer(*ftdih, &latency_timer);
|
||||
if (status != FT_OK)
|
||||
LOG_ERROR("unable to get latency timer: %s",
|
||||
ftd2xx_status_string(status));
|
||||
else
|
||||
LOG_DEBUG("current latency timer: %i", latency_timer);
|
||||
|
||||
status = FT_SetBitMode(*ftdih, 0x00, 0);
|
||||
if (status != FT_OK) {
|
||||
LOG_ERROR("unable to disable bit i/o mode: %s",
|
||||
ftd2xx_status_string(status));
|
||||
return ERROR_JTAG_INIT_FAILED;
|
||||
}
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
static int ublast_ftd2xx_quit(struct ublast_lowlevel *low)
|
||||
{
|
||||
FT_HANDLE *ftdih = ublast_getftdih(low);
|
||||
|
||||
FT_Close(*ftdih);
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
static struct ublast_lowlevel_priv {
|
||||
FT_HANDLE ftdih;
|
||||
} info;
|
||||
|
||||
static struct ublast_lowlevel low = {
|
||||
.open = ublast_ftd2xx_init,
|
||||
.close = ublast_ftd2xx_quit,
|
||||
.read = ublast_ftd2xx_read,
|
||||
.write = ublast_ftd2xx_write,
|
||||
.priv = &info,
|
||||
};
|
||||
|
||||
struct ublast_lowlevel *ublast_register_ftd2xx(void)
|
||||
{
|
||||
return &low;
|
||||
}
|
||||
@@ -147,12 +147,9 @@ struct drvs_map {
|
||||
};
|
||||
|
||||
static struct drvs_map lowlevel_drivers_map[] = {
|
||||
#if BUILD_USB_BLASTER_LIBFTDI
|
||||
#if BUILD_USB_BLASTER
|
||||
{ .name = "ftdi", .drv_register = ublast_register_ftdi },
|
||||
#endif
|
||||
#if BUILD_USB_BLASTER_FTD2XX
|
||||
{ .name = "ftd2xx", .drv_register = ublast_register_ftd2xx },
|
||||
#endif
|
||||
#if BUILD_USB_BLASTER_2
|
||||
{ .name = "ublast2", .drv_register = ublast2_register_libusb },
|
||||
#endif
|
||||
@@ -1048,8 +1045,8 @@ static const struct command_registration ublast_command_handlers[] = {
|
||||
.name = "usb_blaster_lowlevel_driver",
|
||||
.handler = ublast_handle_lowlevel_drv_command,
|
||||
.mode = COMMAND_CONFIG,
|
||||
.help = "set the lowlevel access for the USB Blaster (ftdi, ftd2xx, ublast2)",
|
||||
.usage = "(ftdi|ftd2xx|ublast2)",
|
||||
.help = "set the lowlevel access for the USB Blaster (ftdi, ublast2)",
|
||||
.usage = "(ftdi|ublast2)",
|
||||
},
|
||||
{
|
||||
.name = "usb_blaster_pin",
|
||||
|
||||
+10
-22
@@ -1,23 +1,11 @@
|
||||
include $(top_srcdir)/common.mk
|
||||
noinst_LTLIBRARIES += %D%/libocdhla.la
|
||||
|
||||
noinst_LTLIBRARIES = libocdhla.la
|
||||
|
||||
libocdhla_la_SOURCES = \
|
||||
$(HLFILES)
|
||||
|
||||
HLFILES =
|
||||
|
||||
if HLADAPTER
|
||||
HLFILES += hla_transport.c
|
||||
HLFILES += hla_tcl.c
|
||||
HLFILES += hla_interface.c
|
||||
HLFILES += hla_layout.c
|
||||
endif
|
||||
|
||||
noinst_HEADERS = \
|
||||
hla_interface.h \
|
||||
hla_layout.h \
|
||||
hla_tcl.h \
|
||||
hla_transport.h
|
||||
|
||||
MAINTAINERCLEANFILES = $(srcdir)/Makefile.in
|
||||
%C%_libocdhla_la_SOURCES = \
|
||||
%D%/hla_transport.c \
|
||||
%D%/hla_tcl.c \
|
||||
%D%/hla_interface.c \
|
||||
%D%/hla_layout.c \
|
||||
%D%/hla_transport.h \
|
||||
%D%/hla_interface.h \
|
||||
%D%/hla_layout.h \
|
||||
%D%/hla_tcl.h
|
||||
|
||||
+16
-16
@@ -51,16 +51,10 @@ extern struct jtag_interface parport_interface;
|
||||
#if BUILD_DUMMY == 1
|
||||
extern struct jtag_interface dummy_interface;
|
||||
#endif
|
||||
#if BUILD_FT2232_FTD2XX == 1
|
||||
extern struct jtag_interface ft2232_interface;
|
||||
#endif
|
||||
#if BUILD_FT2232_LIBFTDI == 1
|
||||
extern struct jtag_interface ft2232_interface;
|
||||
#endif
|
||||
#if BUILD_FTDI == 1
|
||||
extern struct jtag_interface ftdi_interface;
|
||||
#endif
|
||||
#if BUILD_USB_BLASTER_LIBFTDI == 1 || BUILD_USB_BLASTER_FTD2XX == 1 || BUILD_USB_BLASTER_2 == 1
|
||||
#if BUILD_USB_BLASTER == 1 || BUILD_USB_BLASTER_2 == 1
|
||||
extern struct jtag_interface usb_blaster_interface;
|
||||
#endif
|
||||
#if BUILD_JTAG_VPI == 1
|
||||
@@ -78,7 +72,7 @@ extern struct jtag_interface at91rm9200_interface;
|
||||
#if BUILD_GW16012 == 1
|
||||
extern struct jtag_interface gw16012_interface;
|
||||
#endif
|
||||
#if BUILD_PRESTO_LIBFTDI == 1 || BUILD_PRESTO_FTD2XX == 1
|
||||
#if BUILD_PRESTO
|
||||
extern struct jtag_interface presto_interface;
|
||||
#endif
|
||||
#if BUILD_USBPROG == 1
|
||||
@@ -129,6 +123,12 @@ extern struct jtag_interface bcm2835gpio_interface;
|
||||
#if BUILD_CMSIS_DAP == 1
|
||||
extern struct jtag_interface cmsis_dap_interface;
|
||||
#endif
|
||||
#if BUILD_KITPROG == 1
|
||||
extern struct jtag_interface kitprog_interface;
|
||||
#endif
|
||||
#if BUILD_IMX_GPIO == 1
|
||||
extern struct jtag_interface imx_gpio_interface;
|
||||
#endif
|
||||
#endif /* standard drivers */
|
||||
|
||||
/**
|
||||
@@ -150,16 +150,10 @@ struct jtag_interface *jtag_interfaces[] = {
|
||||
#if BUILD_DUMMY == 1
|
||||
&dummy_interface,
|
||||
#endif
|
||||
#if BUILD_FT2232_FTD2XX == 1
|
||||
&ft2232_interface,
|
||||
#endif
|
||||
#if BUILD_FT2232_LIBFTDI == 1
|
||||
&ft2232_interface,
|
||||
#endif
|
||||
#if BUILD_FTDI == 1
|
||||
&ftdi_interface,
|
||||
#endif
|
||||
#if BUILD_USB_BLASTER_LIBFTDI == 1 || BUILD_USB_BLASTER_FTD2XX == 1 || BUILD_USB_BLASTER_2 == 1
|
||||
#if BUILD_USB_BLASTER || BUILD_USB_BLASTER_2 == 1
|
||||
&usb_blaster_interface,
|
||||
#endif
|
||||
#if BUILD_JTAG_VPI == 1
|
||||
@@ -177,7 +171,7 @@ struct jtag_interface *jtag_interfaces[] = {
|
||||
#if BUILD_GW16012 == 1
|
||||
&gw16012_interface,
|
||||
#endif
|
||||
#if BUILD_PRESTO_LIBFTDI == 1 || BUILD_PRESTO_FTD2XX == 1
|
||||
#if BUILD_PRESTO
|
||||
&presto_interface,
|
||||
#endif
|
||||
#if BUILD_USBPROG == 1
|
||||
@@ -228,6 +222,12 @@ struct jtag_interface *jtag_interfaces[] = {
|
||||
#if BUILD_CMSIS_DAP == 1
|
||||
&cmsis_dap_interface,
|
||||
#endif
|
||||
#if BUILD_KITPROG == 1
|
||||
&kitprog_interface,
|
||||
#endif
|
||||
#if BUILD_IMX_GPIO == 1
|
||||
&imx_gpio_interface,
|
||||
#endif
|
||||
#endif /* standard drivers */
|
||||
NULL,
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user