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:
Tim Newsome
2017-06-13 11:52:50 -07:00
303 changed files with 17138 additions and 10591 deletions
+49 -80
View File
@@ -1,60 +1,41 @@
include $(top_srcdir)/common.mk
noinst_LTLIBRARIES += %D%/libopenocd.la
bin_PROGRAMS += %D%/openocd
SUBDIRS = \
jtag \
helper \
target \
transport \
flash \
svf \
xsvf \
pld \
server \
rtos
%C%_openocd_SOURCES = \
%D%/main.c
noinst_LTLIBRARIES = libopenocd.la
bin_PROGRAMS = openocd
%C%_libopenocd_la_SOURCES = \
%D%/hello.c %D%/hello.h \
%D%/openocd.c %D%/openocd.h
MAINFILE = main.c
%C%_openocd_LDADD = %D%/libopenocd.la
openocd_SOURCES = $(MAINFILE)
openocd_LDADD = libopenocd.la
%C%_openocd_LDADD += $(MINGWLDADD)
if INTERNAL_JIMTCL
openocd_LDADD += $(top_builddir)/jimtcl/libjim.a
%C%_openocd_LDADD += $(top_builddir)/jimtcl/libjim.a
else
openocd_LDADD += -ljim
%C%_openocd_LDADD += -ljim
endif
if ULINK
openocd_LDADD += -lm
endif
libopenocd_la_SOURCES = \
hello.c \
openocd.c
noinst_HEADERS = \
hello.h \
openocd.h
libopenocd_la_CPPFLAGS = -DPKGBLDDATE=\"`date +%F-%R`\"
%C%_libopenocd_la_CPPFLAGS =
# banner output includes RELSTR appended to $VERSION from the configure script
# guess-rev.sh returns either a repository version ID or "-snapshot"
if RELEASE
libopenocd_la_CPPFLAGS += -DRELSTR=\"\"
libopenocd_la_CPPFLAGS += -DGITVERSION=\"\"
%C%_libopenocd_la_CPPFLAGS += -DRELSTR=\"\"
%C%_libopenocd_la_CPPFLAGS += -DGITVERSION=\"\"
else
libopenocd_la_CPPFLAGS += -DRELSTR=\"`$(top_srcdir)/guess-rev.sh $(top_srcdir)`\"
libopenocd_la_CPPFLAGS += -DGITVERSION=\"`cd $(top_srcdir) && git describe`\"
%C%_libopenocd_la_CPPFLAGS += -DRELSTR=\"`$(top_srcdir)/guess-rev.sh $(top_srcdir)`\"
%C%_libopenocd_la_CPPFLAGS += -DGITVERSION=\"`cd $(top_srcdir) && git describe`\"
%C%_libopenocd_la_CPPFLAGS += -DPKGBLDDATE=\"`date +%F-%R`\"
endif
# add default CPPFLAGS
libopenocd_la_CPPFLAGS += $(AM_CPPFLAGS) $(CPPFLAGS)
%C%_libopenocd_la_CPPFLAGS += $(AM_CPPFLAGS) $(CPPFLAGS)
# the library search path.
libopenocd_la_LDFLAGS = $(all_libraries)
%C%_libopenocd_la_LDFLAGS = $(all_libraries)
if IS_MINGW
MINGWLDADD = -lws2_32
@@ -62,55 +43,43 @@ else
MINGWLDADD =
endif
libopenocd_la_LIBADD = \
$(top_builddir)/src/xsvf/libxsvf.la \
$(top_builddir)/src/svf/libsvf.la \
$(top_builddir)/src/pld/libpld.la \
$(top_builddir)/src/jtag/libjtag.la \
$(top_builddir)/src/transport/libtransport.la \
$(top_builddir)/src/flash/libflash.la \
$(top_builddir)/src/target/libtarget.la \
$(top_builddir)/src/server/libserver.la \
$(top_builddir)/src/rtos/librtos.la \
$(top_builddir)/src/helper/libhelper.la \
$(LIBFTDI_LIBS) $(MINGWLDADD) \
$(HIDAPI_LIBS) $(LIBUSB0_LIBS) $(LIBUSB1_LIBS)
%C%_libopenocd_la_LIBADD = \
%D%/xsvf/libxsvf.la \
%D%/svf/libsvf.la \
%D%/pld/libpld.la \
%D%/jtag/libjtag.la \
%D%/transport/libtransport.la \
%D%/flash/libflash.la \
%D%/target/libtarget.la \
%D%/server/libserver.la \
%D%/rtos/librtos.la \
%D%/helper/libhelper.la
STARTUP_TCL_SRCS = \
$(srcdir)/helper/startup.tcl \
$(srcdir)/jtag/startup.tcl \
$(srcdir)/target/startup.tcl \
$(srcdir)/flash/startup.tcl \
$(srcdir)/server/startup.tcl
BIN2C = $(srcdir)/%D%/helper/bin2char.sh
EXTRA_DIST = $(STARTUP_TCL_SRCS)
STARTUP_TCL_SRCS =
EXTRA_DIST += $(STARTUP_TCL_SRCS)
BUILT_SOURCES = startup_tcl.inc
startup.tcl: $(STARTUP_TCL_SRCS)
cat $^ > $@
BIN2C = $(top_srcdir)/src/helper/bin2char.sh
BUILT_SOURCES += %D%/startup_tcl.inc
# Convert .tcl to c-array
startup_tcl.inc: startup.tcl $(BIN2C)
$(BIN2C) < $< > $@ || { rm -f $@; false; }
%D%/startup_tcl.inc: $(STARTUP_TCL_SRCS)
cat $^ | $(BIN2C) > $@ || { rm -f $@; false; }
# add generated files to make clean list
CLEANFILES = startup.tcl startup_tcl.inc
CLEANFILES += %D%/startup_tcl.inc
# we do not want generated file in the dist
dist-hook:
rm -f $(distdir)/startup_tcl.inc
MAINTAINERCLEANFILES = $(srcdir)/Makefile.in
# The "quick" target builds executables & reinstalls the executables
# Primary use: developer types to quicken the edit/compile/debug
# cycle. by not requiring a "full build and full install". Note the
# assumption is: You are only rebuilding the EXE.... and everything
# else is/was previously installed.
#
# use at your own risk
quick: all install-binPROGRAMS
#dist-hook:
# rm -f $(distdir)/%D%/startup_tcl.inc
include %D%/helper/Makefile.am
include %D%/jtag/Makefile.am
include %D%/transport/Makefile.am
include %D%/xsvf/Makefile.am
include %D%/svf/Makefile.am
include %D%/target/Makefile.am
include %D%/rtos/Makefile.am
include %D%/server/Makefile.am
include %D%/flash/Makefile.am
include %D%/pld/Makefile.am
+10 -20
View File
@@ -1,23 +1,13 @@
include $(top_srcdir)/common.mk
noinst_LTLIBRARIES += %D%/libflash.la
%C%_libflash_la_SOURCES = \
%D%/common.c %D%/common.h \
%D%/mflash.c %D%/mflash.h
SUBDIRS = \
nor \
nand
%C%_libflash_la_LIBADD = \
%D%/nor/libocdflashnor.la \
%D%/nand/libocdflashnand.la
METASOURCES = AUTO
noinst_LTLIBRARIES = libflash.la
libflash_la_SOURCES = \
common.c \
mflash.c
STARTUP_TCL_SRCS += %D%/startup.tcl
libflash_la_LIBADD = \
$(top_builddir)/src/flash/nor/libocdflashnor.la \
$(top_builddir)/src/flash/nand/libocdflashnand.la
noinst_HEADERS = \
common.h \
mflash.h
EXTRA_DIST = startup.tcl
MAINTAINERCLEANFILES = $(srcdir)/Makefile.in
include %D%/nor/Makefile.am
include %D%/nand/Makefile.am
+1
View File
@@ -44,5 +44,6 @@ bool flash_driver_name_matches(const char *name, const char *expected);
#define ERROR_FLASH_SECTOR_NOT_ERASED (-906)
#define ERROR_FLASH_BANK_NOT_PROBED (-907)
#define ERROR_FLASH_OPER_UNSUPPORTED (-908)
#define ERROR_FLASH_PROTECTED (-909)
#endif /* OPENOCD_FLASH_COMMON_H */
+38 -41
View File
@@ -1,46 +1,43 @@
include $(top_srcdir)/common.mk
noinst_LTLIBRARIES += %D%/libocdflashnand.la
noinst_LTLIBRARIES = libocdflashnand.la
libocdflashnand_la_SOURCES = \
ecc.c \
ecc_kw.c \
core.c \
fileio.c \
tcl.c \
arm_io.c \
%C%_libocdflashnand_la_SOURCES = \
%D%/ecc.c \
%D%/ecc_kw.c \
%D%/core.c \
%D%/fileio.c \
%D%/tcl.c \
%D%/arm_io.c \
$(NAND_DRIVERS) \
driver.c
%D%/driver.c \
$(NANDHEADERS)
NAND_DRIVERS = \
nonce.c \
davinci.c \
lpc3180.c \
lpc32xx.c \
mxc.c \
mx3.c \
orion.c \
s3c24xx.c \
s3c2410.c \
s3c2412.c \
s3c2440.c \
s3c2443.c \
s3c6400.c \
at91sam9.c \
nuc910.c
%D%/nonce.c \
%D%/davinci.c \
%D%/lpc3180.c \
%D%/lpc32xx.c \
%D%/mxc.c \
%D%/mx3.c \
%D%/orion.c \
%D%/s3c24xx.c \
%D%/s3c2410.c \
%D%/s3c2412.c \
%D%/s3c2440.c \
%D%/s3c2443.c \
%D%/s3c6400.c \
%D%/at91sam9.c \
%D%/nuc910.c
noinst_HEADERS = \
arm_io.h \
core.h \
driver.h \
fileio.h \
imp.h \
lpc3180.h \
lpc32xx.h \
mxc.h \
mx3.h \
s3c24xx.h \
s3c24xx_regs.h \
nuc910.h
MAINTAINERCLEANFILES = $(srcdir)/Makefile.in
NANDHEADERS = \
%D%/arm_io.h \
%D%/core.h \
%D%/driver.h \
%D%/fileio.h \
%D%/imp.h \
%D%/lpc3180.h \
%D%/lpc32xx.h \
%D%/mxc.h \
%D%/mx3.h \
%D%/s3c24xx.h \
%D%/s3c24xx_regs.h \
%D%/nuc910.h
+4 -2
View File
@@ -254,7 +254,8 @@ COMMAND_HANDLER(handle_nand_write_command)
int bytes_read = nand_fileio_read(nand, &s);
if (bytes_read <= 0) {
command_print(CMD_CTX, "error while reading file");
return nand_fileio_cleanup(&s);
nand_fileio_cleanup(&s);
return ERROR_FAIL;
}
s.size -= bytes_read;
@@ -264,7 +265,8 @@ COMMAND_HANDLER(handle_nand_write_command)
command_print(CMD_CTX, "failed writing file %s "
"to NAND flash %s at offset 0x%8.8" PRIx32,
CMD_ARGV[1], CMD_ARGV[0], s.address);
return nand_fileio_cleanup(&s);
nand_fileio_cleanup(&s);
return retval;
}
s.address += s.page_size;
}
+64 -66
View File
@@ -1,70 +1,68 @@
include $(top_srcdir)/common.mk
noinst_LTLIBRARIES = libocdflashnor.la
libocdflashnor_la_SOURCES = \
core.c \
tcl.c \
noinst_LTLIBRARIES += %D%/libocdflashnor.la
%C%_libocdflashnor_la_SOURCES = \
%D%/core.c \
%D%/tcl.c \
$(NOR_DRIVERS) \
drivers.c
%D%/drivers.c \
$(NORHEADERS)
NOR_DRIVERS = \
aduc702x.c \
aducm360.c \
ambiqmicro.c \
at91sam4.c \
at91sam4l.c \
at91samd.c \
at91sam3.c \
at91sam7.c \
atsamv.c \
avrf.c \
cfi.c \
dsp5680xx_flash.c \
efm32.c \
em357.c \
fespi.c \
faux.c \
fm3.c \
fm4.c \
jtagspi.c \
kinetis.c \
kinetis_ke.c \
lpc2000.c \
lpc288x.c \
lpc2900.c \
lpcspifi.c \
mdr.c \
mrvlqspi.c \
niietcm4.c \
non_cfi.c \
nrf51.c \
numicro.c \
ocl.c \
pic32mx.c \
psoc4.c \
sim3x.c \
spi.c \
stmsmi.c \
stellaris.c \
stm32f1x.c \
stm32f2x.c \
stm32lx.c \
stm32l4x.c \
str7x.c \
str9x.c \
str9xpec.c \
tms470.c \
virtual.c \
xmc1xxx.c \
xmc4xxx.c
%D%/aduc702x.c \
%D%/aducm360.c \
%D%/ambiqmicro.c \
%D%/at91sam4.c \
%D%/at91sam4l.c \
%D%/at91samd.c \
%D%/at91sam3.c \
%D%/at91sam7.c \
%D%/ath79.c \
%D%/atsamv.c \
%D%/avrf.c \
%D%/cfi.c \
%D%/dsp5680xx_flash.c \
%D%/efm32.c \
%D%/em357.c \
%D%/fespi.c \
%D%/faux.c \
%D%/fm3.c \
%D%/fm4.c \
%D%/jtagspi.c \
%D%/kinetis.c \
%D%/kinetis_ke.c \
%D%/lpc2000.c \
%D%/lpc288x.c \
%D%/lpc2900.c \
%D%/lpcspifi.c \
%D%/mdr.c \
%D%/mrvlqspi.c \
%D%/niietcm4.c \
%D%/non_cfi.c \
%D%/nrf51.c \
%D%/numicro.c \
%D%/ocl.c \
%D%/pic32mx.c \
%D%/psoc4.c \
%D%/sim3x.c \
%D%/spi.c \
%D%/stmsmi.c \
%D%/stellaris.c \
%D%/stm32f1x.c \
%D%/stm32f2x.c \
%D%/stm32lx.c \
%D%/stm32l4x.c \
%D%/str7x.c \
%D%/str9x.c \
%D%/str9xpec.c \
%D%/tms470.c \
%D%/virtual.c \
%D%/xmc1xxx.c \
%D%/xmc4xxx.c
noinst_HEADERS = \
core.h \
cfi.h \
driver.h \
imp.h \
non_cfi.h \
ocl.h \
spi.h
MAINTAINERCLEANFILES = $(srcdir)/Makefile.in
NORHEADERS = \
%D%/core.h \
%D%/cfi.h \
%D%/driver.h \
%D%/imp.h \
%D%/non_cfi.h \
%D%/ocl.h \
%D%/spi.h
+542 -23
View File
@@ -65,8 +65,9 @@
#define REG_NAME_WIDTH (12)
/* at91sam4s/at91sam4e series (has always one flash bank)*/
/* at91sam4s/at91sam4e/at91sam4c series (has always one flash bank)*/
#define FLASH_BANK_BASE_S 0x00400000
#define FLASH_BANK_BASE_C 0x01000000
/* at91sam4sd series (two one flash banks), first bank address */
#define FLASH_BANK0_BASE_SD FLASH_BANK_BASE_S
@@ -75,6 +76,10 @@
/* at91sam4sd32x, second bank address */
#define FLASH_BANK1_BASE_2048K_SD (FLASH_BANK0_BASE_SD+(2048*1024/2))
/* at91sam4c32x, first and second bank address */
#define FLASH_BANK0_BASE_C32 FLASH_BANK_BASE_C
#define FLASH_BANK1_BASE_C32 (FLASH_BANK_BASE_C+(2048*1024/2))
#define AT91C_EFC_FCMD_GETD (0x0) /* (EFC) Get Flash Descriptor */
#define AT91C_EFC_FCMD_WP (0x1) /* (EFC) Write Page */
#define AT91C_EFC_FCMD_WPL (0x2) /* (EFC) Write Page and Lock */
@@ -258,6 +263,188 @@ static struct sam4_chip *get_current_sam4(struct command_context *cmd_ctx)
/* these are used to *initialize* the "pChip->details" structure. */
static const struct sam4_chip_details all_sam4_details[] = {
/* Start at91sam4c* series */
/* at91sam4c32e - LQFP144 */
{
.chipid_cidr = 0xA66D0EE0,
.name = "at91sam4c32e",
.total_flash_size = 2024 * 1024,
.total_sram_size = 256 * 1024,
.n_gpnvms = 3,
.n_banks = 2,
/* .bank[0] = { */
{
{
.probed = 0,
.pChip = NULL,
.pBank = NULL,
.bank_number = 0,
.base_address = FLASH_BANK0_BASE_C32,
.controller_address = 0x400e0a00,
.flash_wait_states = 5,
.present = 1,
.size_bytes = 1024 * 1024,
.nsectors = 128,
.sector_size = 8192,
.page_size = 512,
},
/* .bank[1] = { */
{
.probed = 0,
.pChip = NULL,
.pBank = NULL,
.bank_number = 1,
.base_address = FLASH_BANK1_BASE_C32,
.controller_address = 0x400e0c00,
.flash_wait_states = 5,
.present = 1,
.size_bytes = 1024 * 1024,
.nsectors = 128,
.sector_size = 8192,
.page_size = 512,
},
},
},
/* at91sam4c32c - LQFP100 */
{
.chipid_cidr = 0xA64D0EE0,
.name = "at91sam4c32c",
.total_flash_size = 2024 * 1024,
.total_sram_size = 256 * 1024,
.n_gpnvms = 3,
.n_banks = 2,
/* .bank[0] = { */
{
{
.probed = 0,
.pChip = NULL,
.pBank = NULL,
.bank_number = 0,
.base_address = FLASH_BANK0_BASE_C32,
.controller_address = 0x400e0a00,
.flash_wait_states = 5,
.present = 1,
.size_bytes = 1024 * 1024,
.nsectors = 128,
.sector_size = 8192,
.page_size = 512,
},
/* .bank[1] = { */
{
.probed = 0,
.pChip = NULL,
.pBank = NULL,
.bank_number = 1,
.base_address = FLASH_BANK1_BASE_C32,
.controller_address = 0x400e0c00,
.flash_wait_states = 5,
.present = 1,
.size_bytes = 1024 * 1024,
.nsectors = 128,
.sector_size = 8192,
.page_size = 512,
},
},
},
/* at91sam4c16c - LQFP100 */
{
.chipid_cidr = 0xA64C0CE0,
.name = "at91sam4c16c",
.total_flash_size = 1024 * 1024,
.total_sram_size = 128 * 1024,
.n_gpnvms = 2,
.n_banks = 1,
{
/* .bank[0] = {*/
{
.probed = 0,
.pChip = NULL,
.pBank = NULL,
.bank_number = 0,
.base_address = FLASH_BANK_BASE_C,
.controller_address = 0x400e0a00,
.flash_wait_states = 5,
.present = 1,
.size_bytes = 1024 * 1024,
.nsectors = 128,
.sector_size = 8192,
.page_size = 512,
},
/* .bank[1] = {*/
{
.present = 0,
.probed = 0,
.bank_number = 1,
},
},
},
/* at91sam4c8c - LQFP100 */
{
.chipid_cidr = 0xA64C0AE0,
.name = "at91sam4c8c",
.total_flash_size = 512 * 1024,
.total_sram_size = 128 * 1024,
.n_gpnvms = 2,
.n_banks = 1,
{
/* .bank[0] = {*/
{
.probed = 0,
.pChip = NULL,
.pBank = NULL,
.bank_number = 0,
.base_address = FLASH_BANK_BASE_C,
.controller_address = 0x400e0a00,
.flash_wait_states = 5,
.present = 1,
.size_bytes = 512 * 1024,
.nsectors = 64,
.sector_size = 8192,
.page_size = 512,
},
/* .bank[1] = {*/
{
.present = 0,
.probed = 0,
.bank_number = 1,
},
},
},
/* at91sam4c4c (rev B) - LQFP100 */
{
.chipid_cidr = 0xA64C0CE5,
.name = "at91sam4c4c",
.total_flash_size = 256 * 1024,
.total_sram_size = 128 * 1024,
.n_gpnvms = 2,
.n_banks = 1,
{
/* .bank[0] = {*/
{
.probed = 0,
.pChip = NULL,
.pBank = NULL,
.bank_number = 0,
.base_address = FLASH_BANK_BASE_C,
.controller_address = 0x400e0a00,
.flash_wait_states = 5,
.present = 1,
.size_bytes = 256 * 1024,
.nsectors = 32,
.sector_size = 8192,
.page_size = 512,
},
/* .bank[1] = {*/
{
.present = 0,
.probed = 0,
.bank_number = 1,
},
},
},
/* Start at91sam4e* series */
/*atsam4e16e - LQFP144/LFBGA144*/
@@ -479,7 +666,7 @@ static const struct sam4_chip_details all_sam4_details[] = {
.bank_number = 0,
.base_address = FLASH_BANK_BASE_S,
.controller_address = 0x400e0a00,
.flash_wait_states = 6, /* workaround silicon bug */
.flash_wait_states = 5,
.present = 1,
.size_bytes = 1024 * 1024,
.nsectors = 128,
@@ -495,7 +682,7 @@ static const struct sam4_chip_details all_sam4_details[] = {
},
},
},
/*atsam4s16b - LQFP64/QFN64*/
/*atsam4s16b - LQFP64/QFN64/WLCSP64*/
{
.chipid_cidr = 0x289C0CE0,
.name = "at91sam4s16b",
@@ -512,7 +699,7 @@ static const struct sam4_chip_details all_sam4_details[] = {
.bank_number = 0,
.base_address = FLASH_BANK_BASE_S,
.controller_address = 0x400e0a00,
.flash_wait_states = 6, /* workaround silicon bug */
.flash_wait_states = 5,
.present = 1,
.size_bytes = 1024 * 1024,
.nsectors = 128,
@@ -545,7 +732,7 @@ static const struct sam4_chip_details all_sam4_details[] = {
.bank_number = 0,
.base_address = FLASH_BANK_BASE_S,
.controller_address = 0x400e0a00,
.flash_wait_states = 6, /* workaround silicon bug */
.flash_wait_states = 5,
.present = 1,
.size_bytes = 1024 * 1024,
.nsectors = 128,
@@ -578,7 +765,7 @@ static const struct sam4_chip_details all_sam4_details[] = {
.bank_number = 0,
.base_address = FLASH_BANK_BASE_S,
.controller_address = 0x400e0a00,
.flash_wait_states = 6, /* workaround silicon bug */
.flash_wait_states = 5,
.present = 1,
.size_bytes = 1024 * 1024,
.nsectors = 128,
@@ -611,7 +798,7 @@ static const struct sam4_chip_details all_sam4_details[] = {
.bank_number = 0,
.base_address = FLASH_BANK_BASE_S,
.controller_address = 0x400e0a00,
.flash_wait_states = 6, /* workaround silicon bug */
.flash_wait_states = 5,
.present = 1,
.size_bytes = 512 * 1024,
.nsectors = 64,
@@ -627,7 +814,7 @@ static const struct sam4_chip_details all_sam4_details[] = {
},
},
},
/*atsam4s8b - LQFP64/BGA64*/
/*atsam4s8b - LQFP64/QFN64/WLCSP64*/
{
.chipid_cidr = 0x289C0AE0,
.name = "at91sam4s8b",
@@ -644,7 +831,7 @@ static const struct sam4_chip_details all_sam4_details[] = {
.bank_number = 0,
.base_address = FLASH_BANK_BASE_S,
.controller_address = 0x400e0a00,
.flash_wait_states = 6, /* workaround silicon bug */
.flash_wait_states = 5,
.present = 1,
.size_bytes = 512 * 1024,
.nsectors = 64,
@@ -677,7 +864,7 @@ static const struct sam4_chip_details all_sam4_details[] = {
.bank_number = 0,
.base_address = FLASH_BANK_BASE_S,
.controller_address = 0x400e0a00,
.flash_wait_states = 6, /* workaround silicon bug */
.flash_wait_states = 5,
.present = 1,
.size_bytes = 512 * 1024,
.nsectors = 64,
@@ -694,10 +881,10 @@ static const struct sam4_chip_details all_sam4_details[] = {
},
},
/*atsam4s4a - LQFP48/BGA48*/
/*atsam4s4c - LQFP100/BGA100*/
{
.chipid_cidr = 0x288b09e0,
.name = "at91sam4s4a",
.chipid_cidr = 0x28ab09e0,
.name = "at91sam4s4c",
.total_flash_size = 256 * 1024,
.total_sram_size = 64 * 1024,
.n_gpnvms = 2,
@@ -711,7 +898,7 @@ static const struct sam4_chip_details all_sam4_details[] = {
.bank_number = 0,
.base_address = FLASH_BANK_BASE_S,
.controller_address = 0x400e0a00,
.flash_wait_states = 6, /* workaround silicon bug */
.flash_wait_states = 5,
.present = 1,
.size_bytes = 256 * 1024,
.nsectors = 32,
@@ -728,7 +915,177 @@ static const struct sam4_chip_details all_sam4_details[] = {
},
},
/*at91sam4sd32c*/
/*atsam4s4b - LQFP64/QFN64/WLCSP64*/
{
.chipid_cidr = 0x289b09e0,
.name = "at91sam4s4b",
.total_flash_size = 256 * 1024,
.total_sram_size = 64 * 1024,
.n_gpnvms = 2,
.n_banks = 1,
{
/* .bank[0] = {*/
{
.probed = 0,
.pChip = NULL,
.pBank = NULL,
.bank_number = 0,
.base_address = FLASH_BANK_BASE_S,
.controller_address = 0x400e0a00,
.flash_wait_states = 5,
.present = 1,
.size_bytes = 256 * 1024,
.nsectors = 32,
.sector_size = 8192,
.page_size = 512,
},
/* .bank[1] = {*/
{
.present = 0,
.probed = 0,
.bank_number = 1,
},
},
},
/*atsam4s4a - LQFP48/QFN48*/
{
.chipid_cidr = 0x288b09e0,
.name = "at91sam4s4a",
.total_flash_size = 256 * 1024,
.total_sram_size = 64 * 1024,
.n_gpnvms = 2,
.n_banks = 1,
{
/* .bank[0] = {*/
{
.probed = 0,
.pChip = NULL,
.pBank = NULL,
.bank_number = 0,
.base_address = FLASH_BANK_BASE_S,
.controller_address = 0x400e0a00,
.flash_wait_states = 5,
.present = 1,
.size_bytes = 256 * 1024,
.nsectors = 32,
.sector_size = 8192,
.page_size = 512,
},
/* .bank[1] = {*/
{
.present = 0,
.probed = 0,
.bank_number = 1,
},
},
},
/*atsam4s2c - LQFP100/BGA100*/
{
.chipid_cidr = 0x28ab07e0,
.name = "at91sam4s2c",
.total_flash_size = 128 * 1024,
.total_sram_size = 64 * 1024,
.n_gpnvms = 2,
.n_banks = 1,
{
/* .bank[0] = {*/
{
.probed = 0,
.pChip = NULL,
.pBank = NULL,
.bank_number = 0,
.base_address = FLASH_BANK_BASE_S,
.controller_address = 0x400e0a00,
.flash_wait_states = 5,
.present = 1,
.size_bytes = 128 * 1024,
.nsectors = 16,
.sector_size = 8192,
.page_size = 512,
},
/* .bank[1] = {*/
{
.present = 0,
.probed = 0,
.bank_number = 1,
},
},
},
/*atsam4s2b - LQPF64/QFN64/WLCSP64*/
{
.chipid_cidr = 0x289b07e0,
.name = "at91sam4s2b",
.total_flash_size = 128 * 1024,
.total_sram_size = 64 * 1024,
.n_gpnvms = 2,
.n_banks = 1,
{
/* .bank[0] = {*/
{
.probed = 0,
.pChip = NULL,
.pBank = NULL,
.bank_number = 0,
.base_address = FLASH_BANK_BASE_S,
.controller_address = 0x400e0a00,
.flash_wait_states = 5,
.present = 1,
.size_bytes = 128 * 1024,
.nsectors = 16,
.sector_size = 8192,
.page_size = 512,
},
/* .bank[1] = {*/
{
.present = 0,
.probed = 0,
.bank_number = 1,
},
},
},
/*atsam4s2a - LQFP48/QFN48*/
{
.chipid_cidr = 0x288b07e0,
.name = "at91sam4s2a",
.total_flash_size = 128 * 1024,
.total_sram_size = 64 * 1024,
.n_gpnvms = 2,
.n_banks = 1,
{
/* .bank[0] = {*/
{
.probed = 0,
.pChip = NULL,
.pBank = NULL,
.bank_number = 0,
.base_address = FLASH_BANK_BASE_S,
.controller_address = 0x400e0a00,
.flash_wait_states = 5,
.present = 1,
.size_bytes = 128 * 1024,
.nsectors = 16,
.sector_size = 8192,
.page_size = 512,
},
/* .bank[1] = {*/
{
.present = 0,
.probed = 0,
.bank_number = 1,
},
},
},
/*at91sam4sd32c - LQFP100/BGA100*/
{
.chipid_cidr = 0x29a70ee0,
.name = "at91sam4sd32c",
@@ -746,7 +1103,7 @@ static const struct sam4_chip_details all_sam4_details[] = {
.bank_number = 0,
.base_address = FLASH_BANK0_BASE_SD,
.controller_address = 0x400e0a00,
.flash_wait_states = 6, /* workaround silicon bug */
.flash_wait_states = 5,
.present = 1,
.size_bytes = 1024 * 1024,
.nsectors = 128,
@@ -762,7 +1119,7 @@ static const struct sam4_chip_details all_sam4_details[] = {
.bank_number = 1,
.base_address = FLASH_BANK1_BASE_2048K_SD,
.controller_address = 0x400e0c00,
.flash_wait_states = 6, /* workaround silicon bug */
.flash_wait_states = 5,
.present = 1,
.size_bytes = 1024 * 1024,
.nsectors = 128,
@@ -772,7 +1129,51 @@ static const struct sam4_chip_details all_sam4_details[] = {
},
},
/*at91sam4sd16c*/
/*at91sam4sd32b - LQFP64/BGA64*/
{
.chipid_cidr = 0x29970ee0,
.name = "at91sam4sd32b",
.total_flash_size = 2048 * 1024,
.total_sram_size = 160 * 1024,
.n_gpnvms = 3,
.n_banks = 2,
/* .bank[0] = { */
{
{
.probed = 0,
.pChip = NULL,
.pBank = NULL,
.bank_number = 0,
.base_address = FLASH_BANK0_BASE_SD,
.controller_address = 0x400e0a00,
.flash_wait_states = 5,
.present = 1,
.size_bytes = 1024 * 1024,
.nsectors = 128,
.sector_size = 8192,
.page_size = 512,
},
/* .bank[1] = { */
{
.probed = 0,
.pChip = NULL,
.pBank = NULL,
.bank_number = 1,
.base_address = FLASH_BANK1_BASE_2048K_SD,
.controller_address = 0x400e0c00,
.flash_wait_states = 5,
.present = 1,
.size_bytes = 1024 * 1024,
.nsectors = 128,
.sector_size = 8192,
.page_size = 512,
},
},
},
/*at91sam4sd16c - LQFP100/BGA100*/
{
.chipid_cidr = 0x29a70ce0,
.name = "at91sam4sd16c",
@@ -790,7 +1191,7 @@ static const struct sam4_chip_details all_sam4_details[] = {
.bank_number = 0,
.base_address = FLASH_BANK0_BASE_SD,
.controller_address = 0x400e0a00,
.flash_wait_states = 6, /* workaround silicon bug */
.flash_wait_states = 5,
.present = 1,
.size_bytes = 512 * 1024,
.nsectors = 64,
@@ -806,7 +1207,51 @@ static const struct sam4_chip_details all_sam4_details[] = {
.bank_number = 1,
.base_address = FLASH_BANK1_BASE_1024K_SD,
.controller_address = 0x400e0c00,
.flash_wait_states = 6, /* workaround silicon bug */
.flash_wait_states = 5,
.present = 1,
.size_bytes = 512 * 1024,
.nsectors = 64,
.sector_size = 8192,
.page_size = 512,
},
},
},
/*at91sam4sd16b - LQFP64/BGA64*/
{
.chipid_cidr = 0x29970ce0,
.name = "at91sam4sd16b",
.total_flash_size = 1024 * 1024,
.total_sram_size = 160 * 1024,
.n_gpnvms = 3,
.n_banks = 2,
/* .bank[0] = { */
{
{
.probed = 0,
.pChip = NULL,
.pBank = NULL,
.bank_number = 0,
.base_address = FLASH_BANK0_BASE_SD,
.controller_address = 0x400e0a00,
.flash_wait_states = 5,
.present = 1,
.size_bytes = 512 * 1024,
.nsectors = 64,
.sector_size = 8192,
.page_size = 512,
},
/* .bank[1] = { */
{
.probed = 0,
.pChip = NULL,
.pBank = NULL,
.bank_number = 1,
.base_address = FLASH_BANK1_BASE_1024K_SD,
.controller_address = 0x400e0c00,
.flash_wait_states = 5,
.present = 1,
.size_bytes = 512 * 1024,
.nsectors = 64,
@@ -895,6 +1340,74 @@ static const struct sam4_chip_details all_sam4_details[] = {
}
},
/* atsamg55g19 */
{
.chipid_cidr = 0x24470ae0,
.name = "atsamg55g19",
.total_flash_size = 512 * 1024,
.total_sram_size = 160 * 1024,
.n_gpnvms = 2,
.n_banks = 1,
{
/* .bank[0] = */
{
.probed = 0,
.pChip = NULL,
.pBank = NULL,
.bank_number = 0,
.base_address = FLASH_BANK_BASE_S,
.controller_address = 0x400e0a00,
.flash_wait_states = 5,
.present = 1,
.size_bytes = 512 * 1024,
.nsectors = 64,
.sector_size = 8192,
.page_size = 512,
},
/* .bank[1] = */
{
.present = 0,
.probed = 0,
.bank_number = 1,
},
}
},
/* atsamg55j19 */
{
.chipid_cidr = 0x24570ae0,
.name = "atsamg55j19",
.total_flash_size = 512 * 1024,
.total_sram_size = 160 * 1024,
.n_gpnvms = 2,
.n_banks = 1,
{
/* .bank[0] = */
{
.probed = 0,
.pChip = NULL,
.pBank = NULL,
.bank_number = 0,
.base_address = FLASH_BANK_BASE_S,
.controller_address = 0x400e0a00,
.flash_wait_states = 5,
.present = 1,
.size_bytes = 512 * 1024,
.nsectors = 64,
.sector_size = 8192,
.page_size = 512,
},
/* .bank[1] = */
{
.present = 0,
.probed = 0,
.bank_number = 1,
},
}
},
/* terminate */
{
.chipid_cidr = 0,
@@ -1402,7 +1915,7 @@ static uint32_t sam4_reg_fieldname(struct sam4_chip *pChip,
static const char _unknown[] = "unknown";
static const char *const eproc_names[] = {
_unknown, /* 0 */
"Cortex-M7", /* 0 */
"arm946es", /* 1 */
"arm7tdmi", /* 2 */
"Cortex-M3", /* 3 */
@@ -1430,7 +1943,7 @@ static const char *const nvpsize[] = {
"64K bytes", /* 5 */
_unknown, /* 6 */
"128K bytes", /* 7 */
_unknown, /* 8 */
"160K bytes", /* 8 */
"256K bytes", /* 9 */
"512K bytes", /* 10 */
_unknown, /* 11 */
@@ -1472,12 +1985,16 @@ static const struct archnames { unsigned value; const char *name; } archnames[]
{ 0x42, "AT91x42 Series" },
{ 0x43, "SAMG51 Series"
},
{ 0x44, "SAMG55 Series (49-pin WLCSP)" },
{ 0x45, "SAMG55 Series (64-pin)" },
{ 0x47, "SAMG53 Series"
},
{ 0x55, "AT91x55 Series" },
{ 0x60, "AT91SAM7Axx Series" },
{ 0x61, "AT91SAM7AQxx Series" },
{ 0x63, "AT91x63 Series" },
{ 0x64, "SAM4CxxC (100-pin version)" },
{ 0x66, "SAM4CxxE (144-pin version)" },
{ 0x70, "AT91SAM7Sxx Series" },
{ 0x71, "AT91SAM7XCxx Series" },
{ 0x72, "AT91SAM7SExx Series" },
@@ -1975,15 +2492,17 @@ FLASH_BANK_COMMAND_HANDLER(sam4_flash_bank_command)
/* at91sam4s series only has bank 0*/
/* at91sam4sd series has the same address for bank 0 (FLASH_BANK0_BASE_SD)*/
case FLASH_BANK_BASE_S:
case FLASH_BANK_BASE_C:
bank->driver_priv = &(pChip->details.bank[0]);
bank->bank_number = 0;
pChip->details.bank[0].pChip = pChip;
pChip->details.bank[0].pBank = bank;
break;
/* Bank 1 of at91sam4sd series */
/* Bank 1 of at91sam4sd/at91sam4c32 series */
case FLASH_BANK1_BASE_1024K_SD:
case FLASH_BANK1_BASE_2048K_SD:
case FLASH_BANK1_BASE_C32:
bank->driver_priv = &(pChip->details.bank[1]);
bank->bank_number = 1;
pChip->details.bank[1].pChip = pChip;
+9 -4
View File
@@ -645,10 +645,15 @@ static int sam4l_write(struct flash_bank *bank, const uint8_t *buffer,
COMMAND_HANDLER(sam4l_handle_reset_deassert)
{
struct target *target = get_current_target(CMD_CTX);
struct armv7m_common *armv7m = target_to_armv7m(target);
int retval = ERROR_OK;
enum reset_types jtag_reset_config = jtag_get_reset_config();
/* If the target has been unresponsive before, try to re-establish
* communication now - CPU is held in reset by DSU, DAP is working */
if (!target_was_examined(target))
target_examine_one(target);
target_poll(target);
/* In case of sysresetreq, debug retains state set in cortex_m_assert_reset()
* so we just release reset held by SMAP
*
@@ -657,14 +662,14 @@ COMMAND_HANDLER(sam4l_handle_reset_deassert)
* After vectreset SMAP release is not needed however makes no harm
*/
if (target->reset_halt && (jtag_reset_config & RESET_HAS_SRST)) {
retval = mem_ap_write_u32(armv7m->debug_ap, DCB_DHCSR, DBGKEY | C_HALT | C_DEBUGEN);
retval = target_write_u32(target, DCB_DHCSR, DBGKEY | C_HALT | C_DEBUGEN);
if (retval == ERROR_OK)
retval = mem_ap_write_atomic_u32(armv7m->debug_ap, DCB_DEMCR,
retval = target_write_u32(target, DCB_DEMCR,
TRCENA | VC_HARDERR | VC_BUSERR | VC_CORERESET);
/* do not return on error here, releasing SMAP reset is more important */
}
int retval2 = mem_ap_write_atomic_u32(armv7m->debug_ap, SMAP_SCR, SMAP_SCR_HCR);
int retval2 = target_write_u32(target, SMAP_SCR, SMAP_SCR_HCR);
if (retval2 != ERROR_OK)
return retval2;
+1 -1
View File
@@ -661,7 +661,7 @@ static int at91sam7_erase_check(struct flash_bank *bank)
retval = target_blank_check_memory(target,
bank->base + bank->sectors[nSector].offset,
bank->sectors[nSector].size,
&blank);
&blank, bank->erased_value);
if (retval != ERROR_OK) {
fast_check = 0;
break;
+61 -47
View File
@@ -36,6 +36,7 @@
#define SAMD_DSU_STATUSA 1 /* DSU status register */
#define SAMD_DSU_DID 0x18 /* Device ID register */
#define SAMD_DSU_CTRL_EXT 0x100 /* CTRL register, external access */
#define SAMD_NVMCTRL_CTRLA 0x00 /* NVM control A register */
#define SAMD_NVMCTRL_CTRLB 0x04 /* NVM control B register */
@@ -423,39 +424,43 @@ static int samd_probe(struct flash_bank *bank)
return ERROR_OK;
}
static bool samd_check_error(struct target *target)
static int samd_check_error(struct target *target)
{
int ret;
bool error;
int ret, ret2;
uint16_t status;
ret = target_read_u16(target,
SAMD_NVMCTRL + SAMD_NVMCTRL_STATUS, &status);
if (ret != ERROR_OK) {
LOG_ERROR("Can't read NVM status");
return true;
return ret;
}
if (status & 0x001C) {
if (status & (1 << 4)) /* NVME */
LOG_ERROR("SAMD: NVM Error");
if (status & (1 << 3)) /* LOCKE */
LOG_ERROR("SAMD: NVM lock error");
if (status & (1 << 2)) /* PROGE */
LOG_ERROR("SAMD: NVM programming error");
if ((status & 0x001C) == 0)
return ERROR_OK;
error = true;
} else {
error = false;
if (status & (1 << 4)) { /* NVME */
LOG_ERROR("SAMD: NVM Error");
ret = ERROR_FLASH_OPERATION_FAILED;
}
if (status & (1 << 3)) { /* LOCKE */
LOG_ERROR("SAMD: NVM lock error");
ret = ERROR_FLASH_PROTECTED;
}
if (status & (1 << 2)) { /* PROGE */
LOG_ERROR("SAMD: NVM programming error");
ret = ERROR_FLASH_OPER_UNSUPPORTED;
}
/* Clear the error conditions by writing a one to them */
ret = target_write_u16(target,
ret2 = target_write_u16(target,
SAMD_NVMCTRL + SAMD_NVMCTRL_STATUS, status);
if (ret != ERROR_OK)
if (ret2 != ERROR_OK)
LOG_ERROR("Can't clear NVM error conditions");
return error;
return ret;
}
static int samd_issue_nvmctrl_command(struct target *target, uint16_t cmd)
@@ -474,10 +479,7 @@ static int samd_issue_nvmctrl_command(struct target *target, uint16_t cmd)
return res;
/* Check to see if the NVM command resulted in an error condition. */
if (samd_check_error(target))
return ERROR_FAIL;
return ERROR_OK;
return samd_check_error(target);
}
static int samd_erase_row(struct target *target, uint32_t address)
@@ -531,12 +533,19 @@ static int samd_modify_user_row(struct target *target, uint32_t value,
uint8_t startb, uint8_t endb)
{
int res;
uint32_t nvm_ctrlb;
bool manual_wp = true;
if (is_user_row_reserved_bit(startb) || is_user_row_reserved_bit(endb)) {
LOG_ERROR("Can't modify bits in the requested range");
return ERROR_FAIL;
}
/* Check if we need to do manual page write commands */
res = target_read_u32(target, SAMD_NVMCTRL + SAMD_NVMCTRL_CTRLB, &nvm_ctrlb);
if (res == ERROR_OK)
manual_wp = (nvm_ctrlb & SAMD_NVM_CTRLB_MANW) != 0;
/* Retrieve the MCU's page size, in bytes. This is also the size of the
* entire User Row. */
uint32_t page_size;
@@ -559,8 +568,8 @@ static int samd_modify_user_row(struct target *target, uint32_t value,
if (!buf)
return ERROR_FAIL;
/* Read the user row (comprising one page) by half-words. */
res = target_read_memory(target, SAMD_USER_ROW, 2, page_size / 2, buf);
/* Read the user row (comprising one page) by words. */
res = target_read_memory(target, SAMD_USER_ROW, 4, page_size / 4, buf);
if (res != ERROR_OK)
goto out_user_row;
@@ -579,20 +588,18 @@ static int samd_modify_user_row(struct target *target, uint32_t value,
/* Modify */
buf_set_u32(buf, startb, endb - startb + 1, value);
/* Write the page buffer back out to the target. A Flash write will be
* triggered automatically. */
/* Write the page buffer back out to the target. */
res = target_write_memory(target, SAMD_USER_ROW, 4, page_size / 4, buf);
if (res != ERROR_OK)
goto out_user_row;
if (samd_check_error(target)) {
res = ERROR_FAIL;
goto out_user_row;
if (manual_wp) {
/* Trigger flash write */
res = samd_issue_nvmctrl_command(target, SAMD_NVM_CMD_WAP);
} else {
res = samd_check_error(target);
}
/* Success */
res = ERROR_OK;
out_user_row:
free(buf);
@@ -784,18 +791,15 @@ static int samd_write(struct flash_bank *bank, const uint8_t *buffer,
* then issue CMD_WP always */
if (manual_wp || pg_offset + 4 * nw < chip->page_size) {
res = samd_issue_nvmctrl_command(bank->target, SAMD_NVM_CMD_WP);
if (res != ERROR_OK) {
LOG_ERROR("%s: %d", __func__, __LINE__);
goto free_pb;
}
} else {
/* Access through AHB is stalled while flash is being programmed */
usleep(200);
res = samd_check_error(bank->target);
}
/* Access through AHB is stalled while flash is being programmed */
usleep(200);
if (samd_check_error(bank->target)) {
if (res != ERROR_OK) {
LOG_ERROR("%s: write failed at address 0x%08" PRIx32, __func__, address);
res = ERROR_FAIL;
goto free_pb;
}
@@ -856,18 +860,23 @@ COMMAND_HANDLER(samd_handle_info_command)
COMMAND_HANDLER(samd_handle_chip_erase_command)
{
struct target *target = get_current_target(CMD_CTX);
int res = ERROR_FAIL;
if (target) {
/* Enable access to the DSU by disabling the write protect bit */
target_write_u32(target, SAMD_PAC1, (1<<1));
/* intentionally without error checking - not accessible on secured chip */
/* Tell the DSU to perform a full chip erase. It takes about 240ms to
* perform the erase. */
target_write_u8(target, SAMD_DSU, (1<<4));
command_print(CMD_CTX, "chip erased");
res = target_write_u8(target, SAMD_DSU + SAMD_DSU_CTRL_EXT, (1<<4));
if (res == ERROR_OK)
command_print(CMD_CTX, "chip erase started");
else
command_print(CMD_CTX, "write to DSU CTRL failed");
}
return ERROR_OK;
return res;
}
COMMAND_HANDLER(samd_handle_set_security_command)
@@ -1018,10 +1027,15 @@ COMMAND_HANDLER(samd_handle_bootloader_command)
COMMAND_HANDLER(samd_handle_reset_deassert)
{
struct target *target = get_current_target(CMD_CTX);
struct armv7m_common *armv7m = target_to_armv7m(target);
int retval = ERROR_OK;
enum reset_types jtag_reset_config = jtag_get_reset_config();
/* If the target has been unresponsive before, try to re-establish
* communication now - CPU is held in reset by DSU, DAP is working */
if (!target_was_examined(target))
target_examine_one(target);
target_poll(target);
/* In case of sysresetreq, debug retains state set in cortex_m_assert_reset()
* so we just release reset held by DSU
*
@@ -1030,9 +1044,9 @@ COMMAND_HANDLER(samd_handle_reset_deassert)
* After vectreset DSU release is not needed however makes no harm
*/
if (target->reset_halt && (jtag_reset_config & RESET_HAS_SRST)) {
retval = mem_ap_write_u32(armv7m->debug_ap, DCB_DHCSR, DBGKEY | C_HALT | C_DEBUGEN);
retval = target_write_u32(target, DCB_DHCSR, DBGKEY | C_HALT | C_DEBUGEN);
if (retval == ERROR_OK)
retval = mem_ap_write_u32(armv7m->debug_ap, DCB_DEMCR,
retval = target_write_u32(target, DCB_DEMCR,
TRCENA | VC_HARDERR | VC_BUSERR | VC_CORERESET);
/* do not return on error here, releasing DSU reset is more important */
}
+901
View File
@@ -0,0 +1,901 @@
/***************************************************************************
* Copyright (C) 2015 by Tobias Diedrich *
* <ranma+openwrt@tdiedrich.de> *
* *
* based on the stmsmi code written by Antonio Borneo *
* <borneo.antonio@gmail.com> *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc. *
* *
***************************************************************************/
/*
* Driver for the Atheros AR7xxx/AR9xxx SPI flash interface.
*
* Since no SPI mode register is present, presumably only
* SPI "mode 3" (CPOL=1 and CPHA=1) is supported.
*
* The SPI interface supports up to 3 chip selects, however the SPI flash
* used for booting the system must be connected to CS0.
*
* On boot, the first 4MiB of flash space are memory-mapped into the
* area bf000000 - bfffffff (4 copies), so the MIPS bootstrap
* vector bfc00000 is mapped to the beginning of the flash.
*
* By writing a 1 to the REMAP_DISABLE bit in the SPI_CONTROL register,
* the full area of 16MiB is mapped.
*
* By writing a 0 to the SPI_FUNCTION_SELECT register (write-only dword
* register @bf000000), memory mapping is disabled and the SPI registers
* are exposed to the CPU instead:
* bf000000 SPI_FUNCTION_SELECT
* bf000004 SPI_CONTROL
* bf000008 SPI_IO_CONTROL
* bf00000c SPI_READ_DATA
*
* When not memory-mapped, the SPI interface is essentially bitbanged
* using SPI_CONTROL and SPI_IO_CONTROL with the only hardware-assistance
* being the 32bit read-only shift-register SPI_READ_DATA.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "imp.h"
#include "spi.h"
#include <jtag/jtag.h>
#include <helper/time_support.h>
#include <helper/types.h>
#include <target/mips32.h>
#include <target/mips32_pracc.h>
#include <target/target.h>
#define BITS_PER_BYTE 8
#define ATH79_REG_FS 0
#define ATH79_REG_CLOCK 4
#define ATH79_REG_WRITE 8
#define ATH79_REG_DATA 12
#define ATH79_SPI_CS_ALLHI 0x70000
#define ATH79_SPI_CS0_HI 0x10000
#define ATH79_SPI_CS1_HI 0x20000
#define ATH79_SPI_CS2_HI 0x40000
#define ATH79_SPI_CE_HI 0x00100
#define ATH79_SPI_DO_HI 0x00001
#define ATH79_XFER_FINAL 0x00000001
#define ATH79_XFER_PARTIAL 0x00000000
/* Timeout in ms */
#define ATH79_MAX_TIMEOUT (3000)
struct ath79_spi_ctx {
uint8_t *page_buf;
int pre_deselect;
int post_deselect;
};
struct ath79_flash_bank {
int probed;
int chipselect;
uint32_t io_base;
const struct flash_device *dev;
struct ath79_spi_ctx spi;
};
struct ath79_target {
char *name;
uint32_t tap_idcode;
uint32_t io_base;
};
static const struct ath79_target target_devices[] = {
/* name, tap_idcode, io_base */
{ "ATH79", 0x00000001, 0xbf000000 },
{ NULL, 0, 0 }
};
static const uint32_t ath79_chipselects[] = {
(~ATH79_SPI_CS0_HI & ATH79_SPI_CS_ALLHI),
(~ATH79_SPI_CS1_HI & ATH79_SPI_CS_ALLHI),
(~ATH79_SPI_CS2_HI & ATH79_SPI_CS_ALLHI),
};
static void ath79_pracc_addn(struct pracc_queue_info *ctx,
const uint32_t *instr,
int n)
{
for (int i = 0; i < n; i++)
pracc_add(ctx, 0, instr[i]);
}
static int ath79_spi_bitbang_codegen(struct ath79_flash_bank *ath79_info,
struct pracc_queue_info *ctx,
uint8_t *data, int len,
int partial_xfer)
{
uint32_t cs_high = ATH79_SPI_CS_ALLHI;
uint32_t cs_low = ath79_chipselects[ath79_info->chipselect];
uint32_t clock_high = cs_low | ATH79_SPI_CE_HI;
uint32_t clock_low = cs_low;
uint32_t pracc_out = 0;
uint32_t io_base = ath79_info->io_base;
const uint32_t preamble1[] = {
/* $15 = MIPS32_PRACC_BASE_ADDR */
MIPS32_LUI(0, 15, PRACC_UPPER_BASE_ADDR),
/* $1 = io_base */
MIPS32_LUI(0, 1, UPPER16(io_base)),
};
ath79_pracc_addn(ctx, preamble1, ARRAY_SIZE(preamble1));
if (ath79_info->spi.pre_deselect) {
/* Clear deselect flag so we don't deselect again if
* this is a partial xfer.
*/
ath79_info->spi.pre_deselect = 0;
const uint32_t pre_deselect[] = {
/* [$1 + FS] = 1 (enable flash io register access) */
MIPS32_LUI(0, 2, UPPER16(1)),
MIPS32_ORI(0, 2, 2, LOWER16(1)),
MIPS32_SW(0, 2, ATH79_REG_FS, 1),
/* deselect flash just in case */
/* $2 = SPI_CS_DIS */
MIPS32_LUI(0, 2, UPPER16(cs_high)),
MIPS32_ORI(0, 2, 2, LOWER16(cs_high)),
/* [$1 + WRITE] = $2 */
MIPS32_SW(0, 2, ATH79_REG_WRITE, 1),
};
ath79_pracc_addn(ctx, pre_deselect, ARRAY_SIZE(pre_deselect));
}
const uint32_t preamble2[] = {
/* t0 = CLOCK_LOW + 0-bit */
MIPS32_LUI(0, 8, UPPER16((clock_low + 0))),
MIPS32_ORI(0, 8, 8, LOWER16((clock_low + 0))),
/* t1 = CLOCK_LOW + 1-bit */
MIPS32_LUI(0, 9, UPPER16((clock_low + 1))),
MIPS32_ORI(0, 9, 9, LOWER16((clock_low + 1))),
/* t2 = CLOCK_HIGH + 0-bit */
MIPS32_LUI(0, 10, UPPER16((clock_high + 0))),
MIPS32_ORI(0, 10, 10, LOWER16((clock_high + 0))),
/* t3 = CLOCK_HIGH + 1-bit */
MIPS32_LUI(0, 11, UPPER16((clock_high + 1))),
MIPS32_ORI(0, 11, 11, LOWER16((clock_high + 1))),
};
ath79_pracc_addn(ctx, preamble2, ARRAY_SIZE(preamble2));
for (int i = 0; i < len; i++) {
uint8_t x = data[i];
/* Generate bitbang code for one byte, highest bit first .*/
for (int j = BITS_PER_BYTE - 1; j >= 0; j--) {
int bit = ((x >> j) & 1);
if (bit) {
/* [$1 + WRITE] = t1 */
pracc_add(ctx, 0,
MIPS32_SW(0, 9, ATH79_REG_WRITE, 1));
/* [$1 + WRITE] = t3 */
pracc_add(ctx, 0,
MIPS32_SW(0, 11, ATH79_REG_WRITE, 1));
} else {
/* [$1 + WRITE] = t0 */
pracc_add(ctx, 0,
MIPS32_SW(0, 8, ATH79_REG_WRITE, 1));
/* [$1 + WRITE] = t2 */
pracc_add(ctx, 0,
MIPS32_SW(0, 10, ATH79_REG_WRITE, 1));
}
}
if (i % 4 == 3) {
/* $3 = [$1 + DATA] */
pracc_add(ctx, 0, MIPS32_LW(0, 3, ATH79_REG_DATA, 1));
/* [OUTi] = $3 */
pracc_add(ctx, MIPS32_PRACC_PARAM_OUT + pracc_out,
MIPS32_SW(0, 3, PRACC_OUT_OFFSET +
pracc_out, 15));
pracc_out += 4;
}
}
if (len & 3) { /* not a multiple of 4 bytes */
/* $3 = [$1 + DATA] */
pracc_add(ctx, 0, MIPS32_LW(0, 3, ATH79_REG_DATA, 1));
/* [OUTi] = $3 */
pracc_add(ctx, MIPS32_PRACC_PARAM_OUT + pracc_out,
MIPS32_SW(0, 3, PRACC_OUT_OFFSET + pracc_out, 15));
pracc_out += 4;
}
if (ath79_info->spi.post_deselect && !partial_xfer) {
const uint32_t post_deselect[] = {
/* $2 = SPI_CS_DIS */
MIPS32_LUI(0, 2, UPPER16(cs_high)),
MIPS32_ORI(0, 2, 2, LOWER16(cs_high)),
/* [$1 + WRITE] = $2 */
MIPS32_SW(0, 2, ATH79_REG_WRITE, 1),
/* [$1 + FS] = 0 (disable flash io register access) */
MIPS32_XORI(0, 2, 2, 0),
MIPS32_SW(0, 2, ATH79_REG_FS, 1),
};
ath79_pracc_addn(ctx, post_deselect, ARRAY_SIZE(post_deselect));
}
/* common pracc epilogue */
/* jump to start */
pracc_add(ctx, 0, MIPS32_B(0, NEG16(ctx->code_count + 1)));
/* restore $15 from DeSave */
pracc_add(ctx, 0, MIPS32_MFC0(0, 15, 31, 0));
return pracc_out / 4;
}
static int ath79_spi_bitbang_chunk(struct flash_bank *bank,
uint8_t *data, int len, int *transferred)
{
struct target *target = bank->target;
struct ath79_flash_bank *ath79_info = bank->driver_priv;
struct mips32_common *mips32 = target_to_mips32(target);
struct mips_ejtag *ejtag_info = &mips32->ejtag_info;
int pracc_words;
/*
* These constants must match the worst case in the above code
* generator function ath79_spi_bitbang_codegen.
*/
const int pracc_pre_post = 26;
const int pracc_loop_byte = 8 * 2 + 2;
struct pracc_queue_info ctx = {
.ejtag_info = ejtag_info
};
int max_len = (PRACC_MAX_INSTRUCTIONS - pracc_pre_post) / pracc_loop_byte;
int to_xfer = len > max_len ? max_len : len;
int partial_xfer = len != to_xfer;
int padded_len = (to_xfer + 3) & ~3;
uint32_t *out = malloc(padded_len);
if (!out) {
LOG_ERROR("not enough memory");
return ERROR_FAIL;
}
*transferred = 0;
pracc_queue_init(&ctx);
LOG_DEBUG("ath79_spi_bitbang_bytes(%p, %08x, %p, %d)",
target, ath79_info->io_base, data, len);
LOG_DEBUG("max code %d => max len %d. to_xfer %d",
PRACC_MAX_INSTRUCTIONS, max_len, to_xfer);
pracc_words = ath79_spi_bitbang_codegen(
ath79_info, &ctx, data, to_xfer, partial_xfer);
LOG_DEBUG("Assembled %d instructions, %d stores",
ctx.code_count, ctx.store_count);
ctx.retval = mips32_pracc_queue_exec(ejtag_info, &ctx, out, 1);
if (ctx.retval != ERROR_OK)
goto exit;
if (to_xfer & 3) { /* Not a multiple of 4 bytes. */
/*
* Need to realign last word since we didn't shift the
* full 32 bits.
*/
int missed_bytes = 4 - (to_xfer & 3);
out[pracc_words - 1] <<= BITS_PER_BYTE * missed_bytes;
}
/*
* pracc reads return uint32_t in host endianness, convert to
* target endianness.
* Since we know the ATH79 target is big endian and the SPI
* shift register has the bytes in highest to lowest bit order,
* this will ensure correct memory byte order regardless of host
* endianness.
*/
target_buffer_set_u32_array(target, (uint8_t *)out, pracc_words, out);
if (LOG_LEVEL_IS(LOG_LVL_DEBUG)) {
for (int i = 0; i < to_xfer; i++) {
LOG_DEBUG("bitbang %02x => %02x",
data[i], ((uint8_t *)out)[i]);
}
}
memcpy(data, out, to_xfer);
*transferred = to_xfer;
exit:
pracc_queue_free(&ctx);
free(out);
return ctx.retval;
}
static void ath79_spi_bitbang_prepare(struct flash_bank *bank)
{
struct ath79_flash_bank *ath79_info = bank->driver_priv;
ath79_info->spi.pre_deselect = 1;
}
static int ath79_spi_bitbang_bytes(struct flash_bank *bank,
uint8_t *data, int len, uint32_t flags)
{
struct ath79_flash_bank *ath79_info = bank->driver_priv;
int retval;
int transferred;
ath79_info->spi.post_deselect = !!(flags & ATH79_XFER_FINAL);
do {
transferred = 0;
retval = ath79_spi_bitbang_chunk(
bank, data, len, &transferred);
if (retval != ERROR_OK)
return retval;
data += transferred;
len -= transferred;
} while (len > 0);
return ERROR_OK;
}
FLASH_BANK_COMMAND_HANDLER(ath79_flash_bank_command)
{
struct ath79_flash_bank *ath79_info;
int chipselect = 0;
LOG_DEBUG("%s", __func__);
if (CMD_ARGC < 6 || CMD_ARGC > 7)
return ERROR_COMMAND_SYNTAX_ERROR;
if (CMD_ARGC == 7) {
if (strcmp(CMD_ARGV[6], "cs0") == 0)
chipselect = 0; /* default */
else if (strcmp(CMD_ARGV[6], "cs1") == 0)
chipselect = 1;
else if (strcmp(CMD_ARGV[6], "cs2") == 0)
chipselect = 2;
else {
LOG_ERROR("Unknown arg: %s", CMD_ARGV[6]);
return ERROR_COMMAND_SYNTAX_ERROR;
}
}
ath79_info = calloc(1, sizeof(struct ath79_flash_bank));
if (!ath79_info) {
LOG_ERROR("not enough memory");
return ERROR_FAIL;
}
ath79_info->chipselect = chipselect;
bank->driver_priv = ath79_info;
return ERROR_OK;
}
/* Read the status register of the external SPI flash chip. */
static int read_status_reg(struct flash_bank *bank, uint32_t *status)
{
uint8_t spi_bytes[] = {SPIFLASH_READ_STATUS, 0};
int retval;
/* Send SPI command "read STATUS" */
ath79_spi_bitbang_prepare(bank);
retval = ath79_spi_bitbang_bytes(
bank, spi_bytes, sizeof(spi_bytes),
ATH79_XFER_FINAL);
*status = spi_bytes[1];
return retval;
}
/* check for WIP (write in progress) bit in status register */
/* timeout in ms */
static int wait_till_ready(struct flash_bank *bank, int timeout)
{
uint32_t status;
int retval;
long long endtime;
endtime = timeval_ms() + timeout;
do {
/* read flash status register */
retval = read_status_reg(bank, &status);
if (retval != ERROR_OK)
return retval;
if ((status & SPIFLASH_BSY_BIT) == 0)
return ERROR_OK;
alive_sleep(1);
} while (timeval_ms() < endtime);
LOG_ERROR("timeout");
return ERROR_FAIL;
}
/* Send "write enable" command to SPI flash chip. */
static int ath79_write_enable(struct flash_bank *bank)
{
uint32_t status;
int retval;
uint8_t spi_bytes[] = {SPIFLASH_WRITE_ENABLE};
/* Send SPI command "write enable" */
ath79_spi_bitbang_prepare(bank);
retval = ath79_spi_bitbang_bytes(
bank, spi_bytes, sizeof(spi_bytes),
ATH79_XFER_FINAL);
if (retval != ERROR_OK)
return retval;
/* read flash status register */
retval = read_status_reg(bank, &status);
if (retval != ERROR_OK)
return retval;
/* Check write enabled */
if ((status & SPIFLASH_WE_BIT) == 0) {
LOG_ERROR("Cannot enable write to flash. Status=0x%08" PRIx32,
status);
return ERROR_FAIL;
}
return ERROR_OK;
}
static int erase_command(struct flash_bank *bank, int sector)
{
struct ath79_flash_bank *ath79_info = bank->driver_priv;
uint32_t offset = bank->sectors[sector].offset;
uint8_t spi_bytes[] = {
ath79_info->dev->erase_cmd,
offset >> 16,
offset >> 8,
offset
};
/* bitbang command */
ath79_spi_bitbang_prepare(bank);
return ath79_spi_bitbang_bytes(
bank, spi_bytes, sizeof(spi_bytes),
ATH79_XFER_FINAL);
}
static int ath79_erase_sector(struct flash_bank *bank, int sector)
{
int retval = ath79_write_enable(bank);
if (retval != ERROR_OK)
return retval;
/* send SPI command "block erase" */
retval = erase_command(bank, sector);
if (retval != ERROR_OK)
return retval;
/* poll WIP for end of self timed Sector Erase cycle */
return wait_till_ready(bank, ATH79_MAX_TIMEOUT);
}
static int ath79_erase(struct flash_bank *bank, int first, int last)
{
struct target *target = bank->target;
struct ath79_flash_bank *ath79_info = bank->driver_priv;
int retval = ERROR_OK;
int sector;
LOG_DEBUG("%s: from sector %d to sector %d", __func__, first, last);
if (target->state != TARGET_HALTED) {
LOG_ERROR("Target not halted");
return ERROR_TARGET_NOT_HALTED;
}
if ((first < 0) || (last < first) || (last >= bank->num_sectors)) {
LOG_ERROR("Flash sector invalid");
return ERROR_FLASH_SECTOR_INVALID;
}
if (!ath79_info->probed) {
LOG_ERROR("Flash bank not probed");
return ERROR_FLASH_BANK_NOT_PROBED;
}
for (sector = first; sector <= last; sector++) {
if (bank->sectors[sector].is_protected) {
LOG_ERROR("Flash sector %d protected", sector);
return ERROR_FAIL;
}
}
for (sector = first; sector <= last; sector++) {
retval = ath79_erase_sector(bank, sector);
if (retval != ERROR_OK)
break;
keep_alive();
}
return retval;
}
static int ath79_protect(struct flash_bank *bank, int set,
int first, int last)
{
int sector;
for (sector = first; sector <= last; sector++)
bank->sectors[sector].is_protected = set;
return ERROR_OK;
}
static int ath79_write_page(struct flash_bank *bank, const uint8_t *buffer,
uint32_t address, uint32_t len)
{
struct ath79_flash_bank *ath79_info = bank->driver_priv;
uint8_t spi_bytes[] = {
SPIFLASH_PAGE_PROGRAM,
address >> 16,
address >> 8,
address,
};
int retval;
uint32_t i;
if (address & 0xff) {
LOG_ERROR("ath79_write_page: unaligned write address: %08x",
address);
return ERROR_FAIL;
}
if (!ath79_info->spi.page_buf) {
LOG_ERROR("ath79_write_page: page buffer not initialized");
return ERROR_FAIL;
}
if (len > ath79_info->dev->pagesize) {
LOG_ERROR("ath79_write_page: len bigger than page size %d: %d",
ath79_info->dev->pagesize, len);
return ERROR_FAIL;
}
for (i = 0; i < len; i++) {
if (buffer[i] != 0xff)
break;
}
if (i == len) /* all 0xff, no need to program. */
return ERROR_OK;
LOG_INFO("writing %d bytes to flash page @0x%08x", len, address);
memcpy(ath79_info->spi.page_buf, buffer, len);
/* unlock writes */
retval = ath79_write_enable(bank);
if (retval != ERROR_OK)
return retval;
/* bitbang command */
ath79_spi_bitbang_prepare(bank);
retval = ath79_spi_bitbang_bytes(
bank, spi_bytes, sizeof(spi_bytes),
ATH79_XFER_PARTIAL);
if (retval != ERROR_OK)
return retval;
/* write data */
return ath79_spi_bitbang_bytes(
bank, ath79_info->spi.page_buf, len,
ATH79_XFER_FINAL);
}
static int ath79_write_buffer(struct flash_bank *bank, const uint8_t *buffer,
uint32_t address, uint32_t len)
{
struct ath79_flash_bank *ath79_info = bank->driver_priv;
const uint32_t page_size = ath79_info->dev->pagesize;
int retval;
LOG_DEBUG("%s: address=0x%08" PRIx32 " len=0x%08" PRIx32,
__func__, address, len);
while (len > 0) {
int page_len = len > page_size ? page_size : len;
retval = ath79_write_page(
bank, buffer, address, page_len);
if (retval != ERROR_OK)
return retval;
buffer += page_size;
address += page_size;
len -= page_len;
}
return ERROR_OK;
}
static int ath79_write(struct flash_bank *bank, const uint8_t *buffer,
uint32_t offset, uint32_t count)
{
struct target *target = bank->target;
int sector;
LOG_DEBUG("%s: offset=0x%08" PRIx32 " count=0x%08" PRIx32,
__func__, offset, count);
if (offset < bank->base || offset >= bank->base + bank->size) {
LOG_ERROR("Start address out of range");
return ERROR_FAIL;
}
offset -= bank->base;
if (target->state != TARGET_HALTED) {
LOG_ERROR("Target not halted");
return ERROR_TARGET_NOT_HALTED;
}
if (offset + count > bank->size) {
LOG_WARNING("Write pasts end of flash. Extra data discarded.");
count = bank->size - offset;
}
/* Check sector protection */
for (sector = 0; sector < bank->num_sectors; sector++) {
/* Start offset in or before this sector? */
/* End offset in or behind this sector? */
struct flash_sector *bs = &bank->sectors[sector];
if ((offset < (bs->offset + bs->size)) &&
((offset + count - 1) >= bs->offset) &&
bs->is_protected) {
LOG_ERROR("Flash sector %d protected", sector);
return ERROR_FAIL;
}
}
return ath79_write_buffer(bank, buffer, offset, count);
}
static int ath79_read_buffer(struct flash_bank *bank, uint8_t *buffer,
uint32_t address, uint32_t len)
{
uint8_t spi_bytes[] = {
SPIFLASH_READ,
address >> 16,
address >> 8,
address,
};
int retval;
LOG_DEBUG("%s: address=0x%08" PRIx32 " len=0x%08" PRIx32,
__func__, address, len);
if (address & 0xff) {
LOG_ERROR("ath79_read_buffer: unaligned read address: %08x",
address);
return ERROR_FAIL;
}
LOG_INFO("reading %d bytes from flash @0x%08x", len, address);
/* bitbang command */
ath79_spi_bitbang_prepare(bank);
retval = ath79_spi_bitbang_bytes(
bank, spi_bytes, sizeof(spi_bytes), ATH79_XFER_PARTIAL);
if (retval != ERROR_OK)
return retval;
/* read data */
return ath79_spi_bitbang_bytes(
bank, buffer, len, ATH79_XFER_FINAL);
}
static int ath79_read(struct flash_bank *bank, uint8_t *buffer,
uint32_t offset, uint32_t count)
{
struct target *target = bank->target;
LOG_DEBUG("%s: offset=0x%08" PRIx32 " count=0x%08" PRIx32,
__func__, offset, count);
if (offset < bank->base || offset >= bank->base + bank->size) {
LOG_ERROR("Start address out of range");
return ERROR_FAIL;
}
offset -= bank->base;
if (target->state != TARGET_HALTED) {
LOG_ERROR("Target not halted");
return ERROR_TARGET_NOT_HALTED;
}
if (offset + count > bank->size) {
LOG_WARNING("Reads past end of flash. Extra data discarded.");
count = bank->size - offset;
}
return ath79_read_buffer(bank, buffer, offset, count);
}
/* Return ID of flash device */
static int read_flash_id(struct flash_bank *bank, uint32_t *id)
{
struct target *target = bank->target;
int retval;
uint8_t spi_bytes[] = {SPIFLASH_READ_ID, 0, 0, 0};
if (target->state != TARGET_HALTED) {
LOG_ERROR("Target not halted");
return ERROR_TARGET_NOT_HALTED;
}
/* Send SPI command "read ID" */
ath79_spi_bitbang_prepare(bank);
retval = ath79_spi_bitbang_bytes(
bank, spi_bytes, sizeof(spi_bytes), ATH79_XFER_FINAL);
if (retval != ERROR_OK)
return retval;
*id = (spi_bytes[1] << 0)
| (spi_bytes[2] << 8)
| (spi_bytes[3] << 16);
if (*id == 0xffffff) {
LOG_ERROR("No SPI flash found");
return ERROR_FAIL;
}
return ERROR_OK;
}
static int ath79_probe(struct flash_bank *bank)
{
struct target *target = bank->target;
struct ath79_flash_bank *ath79_info = bank->driver_priv;
struct flash_sector *sectors;
uint32_t id = 0; /* silence uninitialized warning */
const struct ath79_target *target_device;
int retval;
if (ath79_info->probed) {
free(bank->sectors);
free(ath79_info->spi.page_buf);
}
ath79_info->probed = 0;
for (target_device = target_devices; target_device->name;
++target_device)
if (target_device->tap_idcode == target->tap->idcode)
break;
if (!target_device->name) {
LOG_ERROR("Device ID 0x%" PRIx32 " is not known",
target->tap->idcode);
return ERROR_FAIL;
}
ath79_info->io_base = target_device->io_base;
LOG_DEBUG("Found device %s at address 0x%" PRIx32,
target_device->name, bank->base);
retval = read_flash_id(bank, &id);
if (retval != ERROR_OK)
return retval;
ath79_info->dev = NULL;
for (const struct flash_device *p = flash_devices; p->name; p++)
if (p->device_id == id) {
ath79_info->dev = p;
break;
}
if (!ath79_info->dev) {
LOG_ERROR("Unknown flash device (ID 0x%08" PRIx32 ")", id);
return ERROR_FAIL;
}
LOG_INFO("Found flash device \'%s\' (ID 0x%08" PRIx32 ")",
ath79_info->dev->name, ath79_info->dev->device_id);
/* Set correct size value */
bank->size = ath79_info->dev->size_in_bytes;
/* create and fill sectors array */
bank->num_sectors =
ath79_info->dev->size_in_bytes / ath79_info->dev->sectorsize;
sectors = calloc(1, sizeof(struct flash_sector) * bank->num_sectors);
if (!sectors) {
LOG_ERROR("not enough memory");
return ERROR_FAIL;
}
ath79_info->spi.page_buf = malloc(ath79_info->dev->pagesize);
if (!ath79_info->spi.page_buf) {
LOG_ERROR("not enough memory");
free(sectors);
return ERROR_FAIL;
}
for (int sector = 0; sector < bank->num_sectors; sector++) {
sectors[sector].offset = sector * ath79_info->dev->sectorsize;
sectors[sector].size = ath79_info->dev->sectorsize;
sectors[sector].is_erased = 0;
sectors[sector].is_protected = 1;
}
bank->sectors = sectors;
ath79_info->probed = 1;
return ERROR_OK;
}
static int ath79_auto_probe(struct flash_bank *bank)
{
struct ath79_flash_bank *ath79_info = bank->driver_priv;
if (ath79_info->probed)
return ERROR_OK;
return ath79_probe(bank);
}
static int ath79_flash_blank_check(struct flash_bank *bank)
{
/* Not implemented */
return ERROR_OK;
}
static int ath79_protect_check(struct flash_bank *bank)
{
/* Not implemented */
return ERROR_OK;
}
static int get_ath79_info(struct flash_bank *bank, char *buf, int buf_size)
{
struct ath79_flash_bank *ath79_info = bank->driver_priv;
if (!ath79_info->probed) {
snprintf(buf, buf_size,
"\nATH79 flash bank not probed yet\n");
return ERROR_OK;
}
snprintf(buf, buf_size, "\nATH79 flash information:\n"
" Device \'%s\' (ID 0x%08" PRIx32 ")\n",
ath79_info->dev->name, ath79_info->dev->device_id);
return ERROR_OK;
}
struct flash_driver ath79_flash = {
.name = "ath79",
.flash_bank_command = ath79_flash_bank_command,
.erase = ath79_erase,
.protect = ath79_protect,
.write = ath79_write,
.read = ath79_read,
.probe = ath79_probe,
.auto_probe = ath79_auto_probe,
.erase_check = ath79_flash_blank_check,
.protect_check = ath79_protect_check,
.info = get_ath79_info,
};
+3
View File
@@ -363,6 +363,9 @@ static int samv_probe(struct flash_bank *bank)
uint8_t nvm_size_code = (device_id >> 8) & 0xf;
switch (nvm_size_code) {
case 10:
bank->size = 512 * 1024;
break;
case 12:
bank->size = 1024 * 1024;
break;
+1
View File
@@ -66,6 +66,7 @@ static const struct avrf_type avft_chips_info[] = {
* eeprom_page_size, eeprom_page_num
*/
{"atmega128", 0x9702, 256, 512, 8, 512},
{"atmega128rfa1", 0xa701, 128, 512, 8, 512},
{"at90can128", 0x9781, 256, 512, 8, 512},
{"at90usb128", 0x9782, 256, 512, 8, 512},
{"atmega164p", 0x940a, 128, 128, 4, 128},
+30 -30
View File
@@ -1312,7 +1312,7 @@ static int cfi_intel_write_block(struct flash_bank *bank, const uint8_t *buffer,
busy_pattern_val = cfi_command_val(bank, 0x80);
error_pattern_val = cfi_command_val(bank, 0x7e);
LOG_DEBUG("Using target buffer at 0x%08" PRIx32 " and of size 0x%04" PRIx32,
LOG_DEBUG("Using target buffer at " TARGET_ADDR_FMT " and of size 0x%04" PRIx32,
source->address, buffer_size);
/* Programming main loop */
@@ -1424,50 +1424,50 @@ static int cfi_spansion_write_block_mips(struct flash_bank *bank, const uint8_t
static const uint32_t mips_word_16_code[] = {
/* start: */
MIPS32_LHU(9, 0, 4), /* lhu $t1, ($a0) ; out = &saddr */
MIPS32_ADDI(4, 4, 2), /* addi $a0, $a0, 2 ; saddr += 2 */
MIPS32_SH(13, 0, 12), /* sh $t5, ($t4) ; *fl_unl_addr1 = fl_unl_cmd1 */
MIPS32_SH(15, 0, 14), /* sh $t7, ($t6) ; *fl_unl_addr2 = fl_unl_cmd2 */
MIPS32_SH(7, 0, 12), /* sh $a3, ($t4) ; *fl_unl_addr1 = fl_write_cmd */
MIPS32_SH(9, 0, 5), /* sh $t1, ($a1) ; *daddr = out */
MIPS32_LHU(0, 9, 0, 4), /* lhu $t1, ($a0) ; out = &saddr */
MIPS32_ADDI(0, 4, 4, 2), /* addi $a0, $a0, 2 ; saddr += 2 */
MIPS32_SH(0, 13, 0, 12), /* sh $t5, ($t4) ; *fl_unl_addr1 = fl_unl_cmd1 */
MIPS32_SH(0, 15, 0, 14), /* sh $t7, ($t6) ; *fl_unl_addr2 = fl_unl_cmd2 */
MIPS32_SH(0, 7, 0, 12), /* sh $a3, ($t4) ; *fl_unl_addr1 = fl_write_cmd */
MIPS32_SH(0, 9, 0, 5), /* sh $t1, ($a1) ; *daddr = out */
MIPS32_NOP, /* nop */
/* busy: */
MIPS32_LHU(10, 0, 5), /* lhu $t2, ($a1) ; temp1 = *daddr */
MIPS32_XOR(11, 9, 10), /* xor $t3, $a0, $t2 ; temp2 = out ^ temp1; */
MIPS32_AND(11, 8, 11), /* and $t3, $t0, $t3 ; temp2 = temp2 & DQ7mask */
MIPS32_BNE(11, 8, 13), /* bne $t3, $t0, cont ; if (temp2 != DQ7mask) goto cont */
MIPS32_NOP, /* nop */
MIPS32_LHU(0, 10, 0, 5), /* lhu $t2, ($a1) ; temp1 = *daddr */
MIPS32_XOR(0, 11, 9, 10), /* xor $t3, $a0, $t2 ; temp2 = out ^ temp1; */
MIPS32_AND(0, 11, 8, 11), /* and $t3, $t0, $t3 ; temp2 = temp2 & DQ7mask */
MIPS32_BNE(0, 11, 8, 13), /* bne $t3, $t0, cont ; if (temp2 != DQ7mask) goto cont */
MIPS32_NOP, /* nop */
MIPS32_SRL(10, 8, 2), /* srl $t2,$t0,2 ; temp1 = DQ7mask >> 2 */
MIPS32_AND(11, 10, 11), /* and $t3, $t2, $t3 ; temp2 = temp2 & temp1 */
MIPS32_BNE(11, 10, NEG16(8)), /* bne $t3, $t2, busy ; if (temp2 != temp1) goto busy */
MIPS32_NOP, /* nop */
MIPS32_SRL(0, 10, 8, 2), /* srl $t2,$t0,2 ; temp1 = DQ7mask >> 2 */
MIPS32_AND(0, 11, 10, 11), /* and $t3, $t2, $t3 ; temp2 = temp2 & temp1 */
MIPS32_BNE(0, 11, 10, NEG16(8)), /* bne $t3, $t2, busy ; if (temp2 != temp1) goto busy */
MIPS32_NOP, /* nop */
MIPS32_LHU(10, 0, 5), /* lhu $t2, ($a1) ; temp1 = *daddr */
MIPS32_XOR(11, 9, 10), /* xor $t3, $a0, $t2 ; temp2 = out ^ temp1; */
MIPS32_AND(11, 8, 11), /* and $t3, $t0, $t3 ; temp2 = temp2 & DQ7mask */
MIPS32_BNE(11, 8, 4), /* bne $t3, $t0, cont ; if (temp2 != DQ7mask) goto cont */
MIPS32_LHU(0, 10, 0, 5), /* lhu $t2, ($a1) ; temp1 = *daddr */
MIPS32_XOR(0, 11, 9, 10), /* xor $t3, $a0, $t2 ; temp2 = out ^ temp1; */
MIPS32_AND(0, 11, 8, 11), /* and $t3, $t0, $t3 ; temp2 = temp2 & DQ7mask */
MIPS32_BNE(0, 11, 8, 4), /* bne $t3, $t0, cont ; if (temp2 != DQ7mask) goto cont */
MIPS32_NOP, /* nop */
MIPS32_XOR(9, 9, 9), /* xor $t1, $t1, $t1 ; out = 0 */
MIPS32_BEQ(9, 0, 11), /* beq $t1, $zero, done ; if (out == 0) goto done */
MIPS32_XOR(0, 9, 9, 9), /* xor $t1, $t1, $t1 ; out = 0 */
MIPS32_BEQ(0, 9, 0, 11), /* beq $t1, $zero, done ; if (out == 0) goto done */
MIPS32_NOP, /* nop */
/* cont: */
MIPS32_ADDI(6, 6, NEG16(1)), /* addi, $a2, $a2, -1 ; numwrites-- */
MIPS32_BNE(6, 0, 5), /* bne $a2, $zero, cont2 ; if (numwrite != 0) goto cont2 */
MIPS32_ADDI(0, 6, 6, NEG16(1)), /* addi, $a2, $a2, -1 ; numwrites-- */
MIPS32_BNE(0, 6, 0, 5), /* bne $a2, $zero, cont2 ; if (numwrite != 0) goto cont2 */
MIPS32_NOP, /* nop */
MIPS32_LUI(9, 0), /* lui $t1, 0 */
MIPS32_ORI(9, 9, 0x80), /* ori $t1, $t1, 0x80 ; out = 0x80 */
MIPS32_LUI(0, 9, 0), /* lui $t1, 0 */
MIPS32_ORI(0, 9, 9, 0x80), /* ori $t1, $t1, 0x80 ; out = 0x80 */
MIPS32_B(4), /* b done ; goto done */
MIPS32_B(0, 4), /* b done ; goto done */
MIPS32_NOP, /* nop */
/* cont2: */
MIPS32_ADDI(5, 5, 2), /* addi $a0, $a0, 2 ; daddr += 2 */
MIPS32_B(NEG16(33)), /* b start ; goto start */
MIPS32_ADDI(0, 5, 5, 2), /* addi $a0, $a0, 2 ; daddr += 2 */
MIPS32_B(0, NEG16(33)), /* b start ; goto start */
MIPS32_NOP, /* nop */
/* done: */
MIPS32_SDBBP, /* sdbbp ; break(); */
MIPS32_SDBBP(0), /* sdbbp ; break(); */
};
mips32_info.common_magic = MIPS32_COMMON_MAGIC;
+14 -7
View File
@@ -50,10 +50,17 @@ int flash_driver_erase(struct flash_bank *bank, int first, int last)
int flash_driver_protect(struct flash_bank *bank, int set, int first, int last)
{
int retval;
int num_blocks;
if (bank->num_prot_blocks)
num_blocks = bank->num_prot_blocks;
else
num_blocks = bank->num_sectors;
/* callers may not supply illegal parameters ... */
if (first < 0 || first > last || last >= bank->num_sectors) {
LOG_ERROR("illegal sector range");
if (first < 0 || first > last || last >= num_blocks) {
LOG_ERROR("illegal protection block range");
return ERROR_FAIL;
}
@@ -69,11 +76,11 @@ int flash_driver_protect(struct flash_bank *bank, int set, int first, int last)
* the target could have reset, power cycled, been hot plugged,
* the application could have run, etc.
*
* Drivers only receive valid sector range.
* Drivers only receive valid protection block range.
*/
retval = bank->driver->protect(bank, set, first, last);
if (retval != ERROR_OK)
LOG_ERROR("failed setting protection for areas %d to %d", first, last);
LOG_ERROR("failed setting protection for blocks %d to %d", first, last);
return retval;
}
@@ -288,7 +295,7 @@ static int default_flash_mem_blank_check(struct flash_bank *bank)
goto done;
for (nBytes = 0; nBytes < chunk; nBytes++) {
if (buffer[nBytes] != 0xFF) {
if (buffer[nBytes] != bank->erased_value) {
bank->sectors[i].is_erased = 0;
break;
}
@@ -319,12 +326,12 @@ int default_flash_blank_check(struct flash_bank *bank)
uint32_t address = bank->base + bank->sectors[i].offset;
uint32_t size = bank->sectors[i].size;
retval = target_blank_check_memory(target, address, size, &blank);
retval = target_blank_check_memory(target, address, size, &blank, bank->erased_value);
if (retval != ERROR_OK) {
fast_check = 0;
break;
}
if (blank == 0xFF)
if (blank == bank->erased_value)
bank->sectors[i].is_erased = 1;
else
bank->sectors[i].is_erased = 0;
+3
View File
@@ -90,6 +90,9 @@ struct flash_bank {
int chip_width; /**< Width of the chip in bytes (1,2,4 bytes) */
int bus_width; /**< Maximum bus width, in bytes (1,2,4 bytes) */
/** Erased value. Defaults to 0xFF. */
uint8_t erased_value;
/** Default padded value used, normally this matches the flash
* erased value. Defaults to 0xFF. */
uint8_t default_padded_value;
+2
View File
@@ -28,6 +28,7 @@ extern struct flash_driver at91sam4_flash;
extern struct flash_driver at91sam4l_flash;
extern struct flash_driver at91sam7_flash;
extern struct flash_driver at91samd_flash;
extern struct flash_driver ath79_flash;
extern struct flash_driver atsamv_flash;
extern struct flash_driver avr_flash;
extern struct flash_driver cfi_flash;
@@ -81,6 +82,7 @@ static struct flash_driver *flash_drivers[] = {
&at91sam4l_flash,
&at91sam7_flash,
&at91samd_flash,
&ath79_flash,
&atsamv_flash,
&avr_flash,
&cfi_flash,
+3 -3
View File
@@ -456,10 +456,10 @@ static int efm32x_read_lock_data(struct flash_bank *bank)
uint32_t *ptr = NULL;
int ret = 0;
assert(!(bank->num_sectors & 0x1f));
assert(bank->num_sectors > 0);
data_size = bank->num_sectors / 8; /* number of data bytes */
data_size /= 4; /* ...and data dwords */
/* calculate the number of 32-bit words to read (one lock bit per sector) */
data_size = (bank->num_sectors + 31) / 32;
ptr = efm32x_info->lb_page;
+5
View File
@@ -702,6 +702,11 @@ static int em357_probe(struct flash_bank *bank)
num_pages = 128;
page_size = 2048;
break;
case 0x80000:
/* 512k -- 256 2k pages */
num_pages = 256;
page_size = 2048;
break;
default:
LOG_WARNING("No size specified for em357 flash driver, assuming 192k!");
num_pages = 96;
+1 -1
View File
@@ -272,7 +272,7 @@ static int fm4_flash_write(struct flash_bank *bank, const uint8_t *buffer,
uint32_t halfwords = MIN(halfword_count, data_workarea->size / 2);
uint32_t addr = bank->base + offset;
LOG_DEBUG("copying %" PRId32 " bytes to SRAM 0x%08" PRIx32,
LOG_DEBUG("copying %" PRId32 " bytes to SRAM 0x%08" TARGET_PRIxADDR,
MIN(halfwords * 2, byte_count), data_workarea->address);
retval = target_write_buffer(target, data_workarea->address,
+76 -120
View File
@@ -102,6 +102,7 @@
#define WDOG_STCTRH 0x40052000
#define SMC_PMCTRL 0x4007E001
#define SMC_PMSTAT 0x4007E003
#define MCM_PLACR 0xF000300C
/* Values */
#define PM_STAT_RUN 0x01
@@ -206,6 +207,7 @@
#define KINETIS_SDID_FAMILYID_K4X 0x40000000
#define KINETIS_SDID_FAMILYID_K6X 0x60000000
#define KINETIS_SDID_FAMILYID_K7X 0x70000000
#define KINETIS_SDID_FAMILYID_K8X 0x80000000
struct kinetis_flash_bank {
bool probed;
@@ -231,7 +233,8 @@ struct kinetis_flash_bank {
FS_PROGRAM_SECTOR = 1,
FS_PROGRAM_LONGWORD = 2,
FS_PROGRAM_PHRASE = 4, /* Unsupported */
FS_INVALIDATE_CACHE = 8,
FS_INVALIDATE_CACHE_K = 8,
FS_INVALIDATE_CACHE_L = 0x10,
} flash_support;
};
@@ -609,6 +612,9 @@ COMMAND_HANDLER(kinetis_check_flash_security_status)
return ERROR_OK;
}
if (!dap->ops)
return ERROR_OK; /* too early to check, in JTAG mode ops may not be initialised */
uint32_t val;
int retval;
@@ -623,7 +629,7 @@ COMMAND_HANDLER(kinetis_check_flash_security_status)
}
if (val == 0)
return ERROR_OK;
return ERROR_OK; /* dap not yet initialised */
bool found = false;
for (size_t i = 0; i < ARRAY_SIZE(kinetis_known_mdm_ids); i++) {
@@ -862,65 +868,7 @@ static int kinetis_ftfx_prepare(struct target *target)
/* Kinetis Program-LongWord Microcodes */
static const uint8_t kinetis_flash_write_code[] = {
/* Params:
* r0 - workarea buffer
* r1 - target address
* r2 - wordcount
* Clobbered:
* r4 - tmp
* r5 - tmp
* r6 - tmp
* r7 - tmp
*/
/* .L1: */
/* for(register uint32_t i=0;i<wcount;i++){ */
0x04, 0x1C, /* mov r4, r0 */
0x00, 0x23, /* mov r3, #0 */
/* .L2: */
0x0E, 0x1A, /* sub r6, r1, r0 */
0xA6, 0x19, /* add r6, r4, r6 */
0x93, 0x42, /* cmp r3, r2 */
0x16, 0xD0, /* beq .L9 */
/* .L5: */
/* while((FTFx_FSTAT&FTFA_FSTAT_CCIF_MASK) != FTFA_FSTAT_CCIF_MASK){}; */
0x0B, 0x4D, /* ldr r5, .L10 */
0x2F, 0x78, /* ldrb r7, [r5] */
0x7F, 0xB2, /* sxtb r7, r7 */
0x00, 0x2F, /* cmp r7, #0 */
0xFA, 0xDA, /* bge .L5 */
/* FTFx_FSTAT = FTFA_FSTAT_ACCERR_MASK|FTFA_FSTAT_FPVIOL_MASK|FTFA_FSTAT_RDCO */
0x70, 0x27, /* mov r7, #112 */
0x2F, 0x70, /* strb r7, [r5] */
/* FTFx_FCCOB3 = faddr; */
0x09, 0x4F, /* ldr r7, .L10+4 */
0x3E, 0x60, /* str r6, [r7] */
0x06, 0x27, /* mov r7, #6 */
/* FTFx_FCCOB0 = 0x06; */
0x08, 0x4E, /* ldr r6, .L10+8 */
0x37, 0x70, /* strb r7, [r6] */
/* FTFx_FCCOB7 = *pLW; */
0x80, 0xCC, /* ldmia r4!, {r7} */
0x08, 0x4E, /* ldr r6, .L10+12 */
0x37, 0x60, /* str r7, [r6] */
/* FTFx_FSTAT = FTFA_FSTAT_CCIF_MASK; */
0x80, 0x27, /* mov r7, #128 */
0x2F, 0x70, /* strb r7, [r5] */
/* .L4: */
/* while((FTFx_FSTAT&FTFA_FSTAT_CCIF_MASK) != FTFA_FSTAT_CCIF_MASK){}; */
0x2E, 0x78, /* ldrb r6, [r5] */
0x77, 0xB2, /* sxtb r7, r6 */
0x00, 0x2F, /* cmp r7, #0 */
0xFB, 0xDA, /* bge .L4 */
0x01, 0x33, /* add r3, r3, #1 */
0xE4, 0xE7, /* b .L2 */
/* .L9: */
0x00, 0xBE, /* bkpt #0 */
/* .L10: */
0x00, 0x00, 0x02, 0x40, /* .word 1073872896 */
0x04, 0x00, 0x02, 0x40, /* .word 1073872900 */
0x07, 0x00, 0x02, 0x40, /* .word 1073872903 */
0x08, 0x00, 0x02, 0x40, /* .word 1073872904 */
#include "../../../contrib/loaders/flash/kinetis/kinetis_flash.inc"
};
/* Program LongWord Block Write */
@@ -933,20 +881,11 @@ static int kinetis_write_block(struct flash_bank *bank, const uint8_t *buffer,
struct working_area *source;
struct kinetis_flash_bank *kinfo = bank->driver_priv;
uint32_t address = kinfo->prog_base + offset;
struct reg_param reg_params[3];
uint32_t end_address;
struct reg_param reg_params[5];
struct armv7m_algorithm armv7m_info;
int retval = ERROR_OK;
/* Params:
* r0 - workarea buffer
* r1 - target address
* r2 - wordcount
* Clobbered:
* r4 - tmp
* r5 - tmp
* r6 - tmp
* r7 - tmp
*/
int retval;
uint8_t fstat;
/* Increase buffer_size if needed */
if (buffer_size < (target->working_area_size/2))
@@ -979,35 +918,39 @@ static int kinetis_write_block(struct flash_bank *bank, const uint8_t *buffer,
armv7m_info.common_magic = ARMV7M_COMMON_MAGIC;
armv7m_info.core_mode = ARM_MODE_THREAD;
init_reg_param(&reg_params[0], "r0", 32, PARAM_OUT); /* *pLW (*buffer) */
init_reg_param(&reg_params[1], "r1", 32, PARAM_OUT); /* faddr */
init_reg_param(&reg_params[2], "r2", 32, PARAM_OUT); /* number of words to program */
init_reg_param(&reg_params[0], "r0", 32, PARAM_IN_OUT); /* address */
init_reg_param(&reg_params[1], "r1", 32, PARAM_OUT); /* word count */
init_reg_param(&reg_params[2], "r2", 32, PARAM_OUT);
init_reg_param(&reg_params[3], "r3", 32, PARAM_OUT);
init_reg_param(&reg_params[4], "r4", 32, PARAM_OUT);
/* write code buffer and use Flash programming code within kinetis */
/* Set breakpoint to 0 with time-out of 1000 ms */
while (wcount > 0) {
uint32_t thisrun_count = (wcount > (buffer_size / 4)) ? (buffer_size / 4) : wcount;
buf_set_u32(reg_params[0].value, 0, 32, address);
buf_set_u32(reg_params[1].value, 0, 32, wcount);
buf_set_u32(reg_params[2].value, 0, 32, source->address);
buf_set_u32(reg_params[3].value, 0, 32, source->address + source->size);
buf_set_u32(reg_params[4].value, 0, 32, FTFx_FSTAT);
retval = target_write_buffer(target, source->address, thisrun_count * 4, buffer);
if (retval != ERROR_OK)
break;
retval = target_run_flash_async_algorithm(target, buffer, wcount, 4,
0, NULL,
5, reg_params,
source->address, source->size,
write_algorithm->address, 0,
&armv7m_info);
buf_set_u32(reg_params[0].value, 0, 32, source->address);
buf_set_u32(reg_params[1].value, 0, 32, address);
buf_set_u32(reg_params[2].value, 0, 32, thisrun_count);
if (retval == ERROR_FLASH_OPERATION_FAILED) {
end_address = buf_get_u32(reg_params[0].value, 0, 32);
retval = target_run_algorithm(target, 0, NULL, 3, reg_params,
write_algorithm->address, 0, 100000, &armv7m_info);
if (retval != ERROR_OK) {
LOG_ERROR("Error executing kinetis Flash programming algorithm");
retval = ERROR_FLASH_OPERATION_FAILED;
break;
LOG_ERROR("Error writing flash at %08" PRIx32, end_address);
retval = target_read_u8(target, FTFx_FSTAT, &fstat);
if (retval == ERROR_OK) {
retval = kinetis_ftfx_decode_error(fstat);
/* reset error flags */
target_write_u8(target, FTFx_FSTAT, 0x70);
}
buffer += thisrun_count * 4;
address += thisrun_count * 4;
wcount -= thisrun_count;
}
} else if (retval != ERROR_OK)
LOG_ERROR("Error executing kinetis Flash programming algorithm");
target_free_working_area(target, source);
target_free_working_area(target, write_algorithm);
@@ -1015,6 +958,8 @@ static int kinetis_write_block(struct flash_bank *bank, const uint8_t *buffer,
destroy_reg_param(&reg_params[0]);
destroy_reg_param(&reg_params[1]);
destroy_reg_param(&reg_params[2]);
destroy_reg_param(&reg_params[3]);
destroy_reg_param(&reg_params[4]);
return retval;
}
@@ -1236,12 +1181,13 @@ static int kinetis_check_run_mode(struct target *target)
static void kinetis_invalidate_flash_cache(struct flash_bank *bank)
{
struct kinetis_flash_bank *kinfo = bank->driver_priv;
uint8_t pfb01cr_byte2 = 0xf0;
if (!(kinfo->flash_support & FS_INVALIDATE_CACHE))
return;
if (kinfo->flash_support & FS_INVALIDATE_CACHE_K)
target_write_u8(bank->target, FMC_PFB01CR + 2, 0xf0);
else if (kinfo->flash_support & FS_INVALIDATE_CACHE_L)
target_write_u8(bank->target, MCM_PLACR + 1, 0x04);
target_write_memory(bank->target, FMC_PFB01CR + 2, 1, 1, &pfb01cr_byte2);
return;
}
@@ -1425,7 +1371,7 @@ static int kinetis_write_inner(struct flash_bank *bank, const uint8_t *buffer,
if (!(kinfo->flash_support & FS_PROGRAM_SECTOR)) {
/* fallback to longword write */
fallback = 1;
LOG_WARNING("This device supports Program Longword execution only.");
LOG_INFO("This device supports Program Longword execution only.");
} else {
result = kinetis_make_ram_ready(bank->target);
if (result != ERROR_OK) {
@@ -1604,7 +1550,7 @@ static int kinetis_probe(struct flash_bank *bank)
pflash_sector_size_bytes = 1<<10;
nvm_sector_size_bytes = 1<<10;
num_blocks = 2;
kinfo->flash_support = FS_PROGRAM_LONGWORD | FS_PROGRAM_SECTOR | FS_INVALIDATE_CACHE;
kinfo->flash_support = FS_PROGRAM_LONGWORD | FS_PROGRAM_SECTOR | FS_INVALIDATE_CACHE_K;
break;
case KINETIS_K_SDID_K10_M72:
case KINETIS_K_SDID_K20_M72:
@@ -1617,7 +1563,7 @@ static int kinetis_probe(struct flash_bank *bank)
pflash_sector_size_bytes = 2<<10;
nvm_sector_size_bytes = 1<<10;
num_blocks = 2;
kinfo->flash_support = FS_PROGRAM_LONGWORD | FS_PROGRAM_SECTOR | FS_INVALIDATE_CACHE;
kinfo->flash_support = FS_PROGRAM_LONGWORD | FS_PROGRAM_SECTOR | FS_INVALIDATE_CACHE_K;
kinfo->max_flash_prog_size = 1<<10;
break;
case KINETIS_K_SDID_K10_M100:
@@ -1633,7 +1579,7 @@ static int kinetis_probe(struct flash_bank *bank)
pflash_sector_size_bytes = 2<<10;
nvm_sector_size_bytes = 2<<10;
num_blocks = 2;
kinfo->flash_support = FS_PROGRAM_LONGWORD | FS_PROGRAM_SECTOR | FS_INVALIDATE_CACHE;
kinfo->flash_support = FS_PROGRAM_LONGWORD | FS_PROGRAM_SECTOR | FS_INVALIDATE_CACHE_K;
break;
case KINETIS_K_SDID_K21_M120:
case KINETIS_K_SDID_K22_M120:
@@ -1642,7 +1588,7 @@ static int kinetis_probe(struct flash_bank *bank)
kinfo->max_flash_prog_size = 1<<10;
nvm_sector_size_bytes = 4<<10;
num_blocks = 2;
kinfo->flash_support = FS_PROGRAM_PHRASE | FS_PROGRAM_SECTOR | FS_INVALIDATE_CACHE;
kinfo->flash_support = FS_PROGRAM_PHRASE | FS_PROGRAM_SECTOR | FS_INVALIDATE_CACHE_K;
break;
case KINETIS_K_SDID_K10_M120:
case KINETIS_K_SDID_K20_M120:
@@ -1652,7 +1598,7 @@ static int kinetis_probe(struct flash_bank *bank)
pflash_sector_size_bytes = 4<<10;
nvm_sector_size_bytes = 4<<10;
num_blocks = 4;
kinfo->flash_support = FS_PROGRAM_PHRASE | FS_PROGRAM_SECTOR | FS_INVALIDATE_CACHE;
kinfo->flash_support = FS_PROGRAM_PHRASE | FS_PROGRAM_SECTOR | FS_INVALIDATE_CACHE_K;
break;
default:
LOG_ERROR("Unsupported K-family FAMID");
@@ -1666,7 +1612,7 @@ static int kinetis_probe(struct flash_bank *bank)
/* K02FN64, K02FN128: FTFA, 2kB sectors */
pflash_sector_size_bytes = 2<<10;
num_blocks = 1;
kinfo->flash_support = FS_PROGRAM_LONGWORD | FS_INVALIDATE_CACHE;
kinfo->flash_support = FS_PROGRAM_LONGWORD | FS_INVALIDATE_CACHE_K;
break;
case KINETIS_SDID_FAMILYID_K2X | KINETIS_SDID_SUBFAMID_KX2: {
@@ -1681,7 +1627,7 @@ static int kinetis_probe(struct flash_bank *bank)
/* MK24FN1M */
pflash_sector_size_bytes = 4<<10;
num_blocks = 2;
kinfo->flash_support = FS_PROGRAM_PHRASE | FS_PROGRAM_SECTOR | FS_INVALIDATE_CACHE;
kinfo->flash_support = FS_PROGRAM_PHRASE | FS_PROGRAM_SECTOR | FS_INVALIDATE_CACHE_K;
kinfo->max_flash_prog_size = 1<<10;
break;
}
@@ -1691,7 +1637,7 @@ static int kinetis_probe(struct flash_bank *bank)
/* K22 with new-style SDID - smaller pflash with FTFA, 2kB sectors */
pflash_sector_size_bytes = 2<<10;
/* autodetect 1 or 2 blocks */
kinfo->flash_support = FS_PROGRAM_LONGWORD | FS_INVALIDATE_CACHE;
kinfo->flash_support = FS_PROGRAM_LONGWORD | FS_INVALIDATE_CACHE_K;
break;
}
LOG_ERROR("Unsupported Kinetis K22 DIEID");
@@ -1702,12 +1648,12 @@ static int kinetis_probe(struct flash_bank *bank)
if ((kinfo->sim_sdid & (KINETIS_SDID_DIEID_MASK)) == KINETIS_SDID_DIEID_K24FN256) {
/* K24FN256 - smaller pflash with FTFA */
num_blocks = 1;
kinfo->flash_support = FS_PROGRAM_LONGWORD | FS_INVALIDATE_CACHE;
kinfo->flash_support = FS_PROGRAM_LONGWORD | FS_INVALIDATE_CACHE_K;
break;
}
/* K24FN1M without errata 7534 */
num_blocks = 2;
kinfo->flash_support = FS_PROGRAM_PHRASE | FS_PROGRAM_SECTOR | FS_INVALIDATE_CACHE;
kinfo->flash_support = FS_PROGRAM_PHRASE | FS_PROGRAM_SECTOR | FS_INVALIDATE_CACHE_K;
kinfo->max_flash_prog_size = 1<<10;
break;
@@ -1721,7 +1667,7 @@ static int kinetis_probe(struct flash_bank *bank)
nvm_sector_size_bytes = 4<<10;
kinfo->max_flash_prog_size = 1<<10;
num_blocks = 2;
kinfo->flash_support = FS_PROGRAM_PHRASE | FS_PROGRAM_SECTOR | FS_INVALIDATE_CACHE;
kinfo->flash_support = FS_PROGRAM_PHRASE | FS_PROGRAM_SECTOR | FS_INVALIDATE_CACHE_K;
break;
case KINETIS_SDID_FAMILYID_K2X | KINETIS_SDID_SUBFAMID_KX6:
@@ -1732,8 +1678,18 @@ static int kinetis_probe(struct flash_bank *bank)
nvm_sector_size_bytes = 4<<10;
kinfo->max_flash_prog_size = 1<<10;
num_blocks = 4;
kinfo->flash_support = FS_PROGRAM_PHRASE | FS_PROGRAM_SECTOR | FS_INVALIDATE_CACHE;
kinfo->flash_support = FS_PROGRAM_PHRASE | FS_PROGRAM_SECTOR | FS_INVALIDATE_CACHE_K;
break;
case KINETIS_SDID_FAMILYID_K8X | KINETIS_SDID_SUBFAMID_KX0:
case KINETIS_SDID_FAMILYID_K8X | KINETIS_SDID_SUBFAMID_KX1:
case KINETIS_SDID_FAMILYID_K8X | KINETIS_SDID_SUBFAMID_KX2:
/* K80FN256, K81FN256, K82FN256 */
pflash_sector_size_bytes = 4<<10;
num_blocks = 1;
kinfo->flash_support = FS_PROGRAM_LONGWORD | FS_INVALIDATE_CACHE_K;
break;
default:
LOG_ERROR("Unsupported Kinetis FAMILYID SUBFAMID");
}
@@ -1744,7 +1700,7 @@ static int kinetis_probe(struct flash_bank *bank)
pflash_sector_size_bytes = 1<<10;
nvm_sector_size_bytes = 1<<10;
/* autodetect 1 or 2 blocks */
kinfo->flash_support = FS_PROGRAM_LONGWORD;
kinfo->flash_support = FS_PROGRAM_LONGWORD | FS_INVALIDATE_CACHE_L;
break;
case KINETIS_SDID_SERIESID_KV:
@@ -1754,14 +1710,14 @@ static int kinetis_probe(struct flash_bank *bank)
/* KV10: FTFA, 1kB sectors */
pflash_sector_size_bytes = 1<<10;
num_blocks = 1;
kinfo->flash_support = FS_PROGRAM_LONGWORD;
kinfo->flash_support = FS_PROGRAM_LONGWORD | FS_INVALIDATE_CACHE_L;
break;
case KINETIS_SDID_FAMILYID_K1X | KINETIS_SDID_SUBFAMID_KX1:
/* KV11: FTFA, 2kB sectors */
pflash_sector_size_bytes = 2<<10;
num_blocks = 1;
kinfo->flash_support = FS_PROGRAM_LONGWORD;
kinfo->flash_support = FS_PROGRAM_LONGWORD | FS_INVALIDATE_CACHE_L;
break;
case KINETIS_SDID_FAMILYID_K3X | KINETIS_SDID_SUBFAMID_KX0:
@@ -1770,7 +1726,7 @@ static int kinetis_probe(struct flash_bank *bank)
/* KV31: FTFA, 2kB sectors, 2 blocks */
pflash_sector_size_bytes = 2<<10;
/* autodetect 1 or 2 blocks */
kinfo->flash_support = FS_PROGRAM_LONGWORD | FS_INVALIDATE_CACHE;
kinfo->flash_support = FS_PROGRAM_LONGWORD | FS_INVALIDATE_CACHE_K;
break;
case KINETIS_SDID_FAMILYID_K4X | KINETIS_SDID_SUBFAMID_KX2:
@@ -1779,7 +1735,7 @@ static int kinetis_probe(struct flash_bank *bank)
/* KV4x: FTFA, 4kB sectors */
pflash_sector_size_bytes = 4<<10;
num_blocks = 1;
kinfo->flash_support = FS_PROGRAM_LONGWORD | FS_INVALIDATE_CACHE;
kinfo->flash_support = FS_PROGRAM_LONGWORD | FS_INVALIDATE_CACHE_K;
break;
default:
+13 -4
View File
@@ -259,6 +259,8 @@
#define IAP_CODE_LEN 0x34
#define LPC11xx_REG_SECTORS 24
typedef enum {
lpc2000_v1,
lpc2000_v2,
@@ -554,14 +556,21 @@ static int lpc2000_build_sector_list(struct flash_bank *bank)
exit(-1);
}
lpc2000_info->cmd51_max_buffer = 512; /* smallest MCU in the series, LPC1110, has 1 kB of SRAM */
bank->num_sectors = bank->size / 4096;
unsigned int large_sectors = 0;
unsigned int normal_sectors = bank->size / 4096;
if (normal_sectors > LPC11xx_REG_SECTORS) {
large_sectors = (normal_sectors - LPC11xx_REG_SECTORS) / 8;
normal_sectors = LPC11xx_REG_SECTORS;
}
bank->num_sectors = normal_sectors + large_sectors;
bank->sectors = malloc(sizeof(struct flash_sector) * bank->num_sectors);
for (int i = 0; i < bank->num_sectors; i++) {
bank->sectors[i].offset = offset;
/* all sectors are 4kB-sized */
bank->sectors[i].size = 4 * 1024;
bank->sectors[i].size = (i < LPC11xx_REG_SECTORS ? 4 : 32) * 1024;
offset += bank->sectors[i].size;
bank->sectors[i].is_erased = -1;
bank->sectors[i].is_protected = 1;
@@ -679,7 +688,7 @@ static int lpc2000_iap_working_area_init(struct flash_bank *bank, struct working
int retval = target_write_memory(target, (*iap_working_area)->address, 4, 2, jump_gate);
if (retval != ERROR_OK) {
LOG_ERROR("Write memory at address 0x%8.8" PRIx32 " failed (check work_area definition)",
LOG_ERROR("Write memory at address 0x%8.8" TARGET_PRIxADDR " failed (check work_area definition)",
(*iap_working_area)->address);
target_free_working_area(target, *iap_working_area);
}
+1 -1
View File
@@ -186,7 +186,7 @@ static int lpcspifi_set_hw_mode(struct flash_bank *bank)
return retval;
}
LOG_DEBUG("Writing algorithm to working area at 0x%08" PRIx32,
LOG_DEBUG("Writing algorithm to working area at 0x%08" TARGET_PRIxADDR,
spifi_init_algorithm->address);
/* Write algorithm to working area */
retval = target_write_buffer(target,
+2 -1
View File
@@ -171,7 +171,8 @@ static int mdr_erase(struct flash_bank *bank, int first, int last)
if (retval != ERROR_OK)
goto reset_pg_and_lock;
if ((first == 0) && (last == (bank->num_sectors - 1))) {
if ((first == 0) && (last == (bank->num_sectors - 1)) &&
!mdr_info->mem_type) {
retval = mdr_mass_erase(bank);
goto reset_pg_and_lock;
}
+61 -15
View File
@@ -108,7 +108,6 @@ enum nrf51_nvmc_config_bits {
struct nrf51_info {
uint32_t code_page_size;
uint32_t code_memory_size;
struct {
bool probed;
@@ -121,6 +120,7 @@ struct nrf51_info {
struct nrf51_device_spec {
uint16_t hwid;
const char *part;
const char *variant;
const char *build_code;
unsigned int flash_size_kb;
@@ -142,30 +142,35 @@ static const struct nrf51_device_spec nrf51_known_devices_table[] = {
/* nRF51822 Devices (IC rev 1). */
{
.hwid = 0x001D,
.part = "51822",
.variant = "QFAA",
.build_code = "CA/C0",
.flash_size_kb = 256,
},
{
.hwid = 0x0026,
.part = "51822",
.variant = "QFAB",
.build_code = "AA",
.flash_size_kb = 128,
},
{
.hwid = 0x0027,
.part = "51822",
.variant = "QFAB",
.build_code = "A0",
.flash_size_kb = 128,
},
{
.hwid = 0x0020,
.part = "51822",
.variant = "CEAA",
.build_code = "BA",
.flash_size_kb = 256,
},
{
.hwid = 0x002F,
.part = "51822",
.variant = "CEAA",
.build_code = "B0",
.flash_size_kb = 256,
@@ -174,54 +179,63 @@ static const struct nrf51_device_spec nrf51_known_devices_table[] = {
/* nRF51822 Devices (IC rev 2). */
{
.hwid = 0x002A,
.part = "51822",
.variant = "QFAA",
.build_code = "FA0",
.flash_size_kb = 256,
},
{
.hwid = 0x0044,
.part = "51822",
.variant = "QFAA",
.build_code = "GC0",
.flash_size_kb = 256,
},
{
.hwid = 0x003C,
.part = "51822",
.variant = "QFAA",
.build_code = "G0",
.flash_size_kb = 256,
},
{
.hwid = 0x0057,
.part = "51822",
.variant = "QFAA",
.build_code = "G2",
.flash_size_kb = 256,
},
{
.hwid = 0x0058,
.part = "51822",
.variant = "QFAA",
.build_code = "G3",
.flash_size_kb = 256,
},
{
.hwid = 0x004C,
.part = "51822",
.variant = "QFAB",
.build_code = "B0",
.flash_size_kb = 128,
},
{
.hwid = 0x0040,
.part = "51822",
.variant = "CEAA",
.build_code = "CA0",
.flash_size_kb = 256,
},
{
.hwid = 0x0047,
.part = "51822",
.variant = "CEAA",
.build_code = "DA0",
.flash_size_kb = 256,
},
{
.hwid = 0x004D,
.part = "51822",
.variant = "CEAA",
.build_code = "D00",
.flash_size_kb = 256,
@@ -230,62 +244,79 @@ static const struct nrf51_device_spec nrf51_known_devices_table[] = {
/* nRF51822 Devices (IC rev 3). */
{
.hwid = 0x0072,
.part = "51822",
.variant = "QFAA",
.build_code = "H0",
.flash_size_kb = 256,
},
{
.hwid = 0x007B,
.part = "51822",
.variant = "QFAB",
.build_code = "C0",
.flash_size_kb = 128,
},
{
.hwid = 0x0083,
.part = "51822",
.variant = "QFAC",
.build_code = "A0",
.flash_size_kb = 256,
},
{
.hwid = 0x0084,
.part = "51822",
.variant = "QFAC",
.build_code = "A1",
.flash_size_kb = 256,
},
{
.hwid = 0x007D,
.part = "51822",
.variant = "CDAB",
.build_code = "A0",
.flash_size_kb = 128,
},
{
.hwid = 0x0079,
.part = "51822",
.variant = "CEAA",
.build_code = "E0",
.flash_size_kb = 256,
},
{
.hwid = 0x0087,
.part = "51822",
.variant = "CFAC",
.build_code = "A0",
.flash_size_kb = 256,
},
{
.hwid = 0x008F,
.part = "51822",
.variant = "QFAA",
.build_code = "H1",
.flash_size_kb = 256,
},
/* nRF51422 Devices (IC rev 1). */
{
.hwid = 0x001E,
.part = "51422",
.variant = "QFAA",
.build_code = "CA",
.flash_size_kb = 256,
},
{
.hwid = 0x0024,
.part = "51422",
.variant = "QFAA",
.build_code = "C0",
.flash_size_kb = 256,
},
{
.hwid = 0x0031,
.part = "51422",
.variant = "CEAA",
.build_code = "A0A",
.flash_size_kb = 256,
@@ -294,24 +325,28 @@ static const struct nrf51_device_spec nrf51_known_devices_table[] = {
/* nRF51422 Devices (IC rev 2). */
{
.hwid = 0x002D,
.part = "51422",
.variant = "QFAA",
.build_code = "DAA",
.flash_size_kb = 256,
},
{
.hwid = 0x002E,
.part = "51422",
.variant = "QFAA",
.build_code = "E0",
.flash_size_kb = 256,
},
{
.hwid = 0x0061,
.part = "51422",
.variant = "QFAB",
.build_code = "A00",
.flash_size_kb = 128,
},
{
.hwid = 0x0050,
.part = "51422",
.variant = "CEAA",
.build_code = "B0",
.flash_size_kb = 256,
@@ -320,42 +355,49 @@ static const struct nrf51_device_spec nrf51_known_devices_table[] = {
/* nRF51422 Devices (IC rev 3). */
{
.hwid = 0x0073,
.part = "51422",
.variant = "QFAA",
.build_code = "F0",
.flash_size_kb = 256,
},
{
.hwid = 0x007C,
.part = "51422",
.variant = "QFAB",
.build_code = "B0",
.flash_size_kb = 128,
},
{
.hwid = 0x0085,
.part = "51422",
.variant = "QFAC",
.build_code = "A0",
.flash_size_kb = 256,
},
{
.hwid = 0x0086,
.part = "51422",
.variant = "QFAC",
.build_code = "A1",
.flash_size_kb = 256,
},
{
.hwid = 0x007E,
.part = "51422",
.variant = "CDAB",
.build_code = "A0",
.flash_size_kb = 128,
},
{
.hwid = 0x007A,
.part = "51422",
.variant = "CEAA",
.build_code = "C0",
.flash_size_kb = 256,
},
{
.hwid = 0x0088,
.part = "51422",
.variant = "CFAC",
.build_code = "A0",
.flash_size_kb = 256,
@@ -366,6 +408,7 @@ static const struct nrf51_device_spec nrf51_known_devices_table[] = {
in the nRF51 Series Compatibility Matrix V1.0. */
{
.hwid = 0x0071,
.part = "51822",
.variant = "QFAC",
.build_code = "AB",
.flash_size_kb = 256,
@@ -627,43 +670,46 @@ static int nrf51_probe(struct flash_bank *bank)
* bytes of the CONFIGID register */
const struct nrf51_device_spec *spec = NULL;
for (size_t i = 0; i < ARRAY_SIZE(nrf51_known_devices_table); i++)
for (size_t i = 0; i < ARRAY_SIZE(nrf51_known_devices_table); i++) {
if (hwid == nrf51_known_devices_table[i].hwid) {
spec = &nrf51_known_devices_table[i];
break;
}
}
if (!chip->bank[0].probed && !chip->bank[1].probed) {
if (spec)
LOG_INFO("nRF51822-%s(build code: %s) %ukB Flash",
spec->variant, spec->build_code, spec->flash_size_kb);
LOG_INFO("nRF%s-%s(build code: %s) %ukB Flash",
spec->part, spec->variant, spec->build_code,
spec->flash_size_kb);
else
LOG_WARNING("Unknown device (HWID 0x%08" PRIx32 ")", hwid);
}
if (bank->base == NRF51_FLASH_BASE) {
/* The value stored in NRF51_FICR_CODEPAGESIZE is the number of bytes in one page of FLASH. */
res = target_read_u32(chip->target, NRF51_FICR_CODEPAGESIZE,
&chip->code_page_size);
&chip->code_page_size);
if (res != ERROR_OK) {
LOG_ERROR("Couldn't read code page size");
return res;
}
res = target_read_u32(chip->target, NRF51_FICR_CODESIZE,
&chip->code_memory_size);
/* Note the register name is misleading,
* NRF51_FICR_CODESIZE is the number of pages in flash memory, not the number of bytes! */
uint32_t num_sectors;
res = target_read_u32(chip->target, NRF51_FICR_CODESIZE, &num_sectors);
if (res != ERROR_OK) {
LOG_ERROR("Couldn't read code memory size");
return res;
}
if (spec && chip->code_memory_size != spec->flash_size_kb) {
LOG_ERROR("Chip's reported Flash capacity does not match expected one");
return ERROR_FAIL;
}
bank->num_sectors = num_sectors;
bank->size = num_sectors * chip->code_page_size;
if (spec && bank->size / 1024 != spec->flash_size_kb)
LOG_WARNING("Chip's reported Flash capacity does not match expected one");
bank->size = chip->code_memory_size * 1024;
bank->num_sectors = bank->size / chip->code_page_size;
bank->sectors = calloc(bank->num_sectors,
sizeof((bank->sectors)[0]));
if (!bank->sectors)
@@ -1272,7 +1318,7 @@ static int nrf51_info(struct flash_bank *bank, char *buf, int buf_size)
"reset value for XTALFREQ: %"PRIx32"\n"
"firmware id: 0x%04"PRIx32,
ficr[0].value,
ficr[1].value,
(ficr[1].value * ficr[0].value) / 1024,
(ficr[2].value == 0xFFFFFFFF) ? 0 : ficr[2].value / 1024,
((ficr[3].value & 0xFF) == 0x00) ? "present" : "not present",
ficr[4].value,
+1 -2
View File
@@ -879,7 +879,6 @@ COMMAND_HANDLER(pic32mx_handle_pgm_word_command)
COMMAND_HANDLER(pic32mx_handle_unlock_command)
{
uint32_t mchip_cmd;
struct target *target = NULL;
struct mips_m4k_common *mips_m4k;
struct mips_ejtag *ejtag_info;
@@ -904,7 +903,7 @@ COMMAND_HANDLER(pic32mx_handle_unlock_command)
mips_ejtag_set_instr(ejtag_info, MTAP_COMMAND);
/* first check status of device */
mchip_cmd = MCHP_STATUS;
uint8_t mchip_cmd = MCHP_STATUS;
mips_ejtag_drscan_8(ejtag_info, &mchip_cmd);
if (mchip_cmd & (1 << 7)) {
/* device is not locked */
+6 -3
View File
@@ -110,6 +110,9 @@
#define FLASH_ERASE_TIMEOUT 10000
#define FLASH_WRITE_TIMEOUT 5
/* Mass erase time can be as high as 32 s in x8 mode. */
#define FLASH_MASS_ERASE_TIMEOUT 33000
#define STM32_FLASH_BASE 0x40023c00
#define STM32_FLASH_ACR 0x40023c00
#define STM32_FLASH_KEYR 0x40023c04
@@ -399,8 +402,8 @@ static int stm32x_write_options(struct flash_bank *bank)
if (retval != ERROR_OK)
return retval;
/* wait for completion */
retval = stm32x_wait_status_busy(bank, FLASH_ERASE_TIMEOUT);
/* wait for completion, this might trigger a security erase and take a while */
retval = stm32x_wait_status_busy(bank, FLASH_MASS_ERASE_TIMEOUT);
if (retval != ERROR_OK)
return retval;
@@ -1257,7 +1260,7 @@ static int stm32x_mass_erase(struct flash_bank *bank)
if (retval != ERROR_OK)
return retval;
retval = stm32x_wait_status_busy(bank, 30000);
retval = stm32x_wait_status_busy(bank, FLASH_MASS_ERASE_TIMEOUT);
if (retval != ERROR_OK)
return retval;
+32 -9
View File
@@ -27,18 +27,22 @@
/* STM32L4xxx series for reference.
*
* RM0351
* http://www.st.com/st-web-ui/static/active/en/resource/technical/document/reference_manual/DM00083560.pdf
* RM0351 (STM32L4x5/STM32L4x6)
* http://www.st.com/resource/en/reference_manual/dm00083560.pdf
*
* RM0394 (STM32L43x/44x/45x/46x)
* http://www.st.com/resource/en/reference_manual/dm00151940.pdf
*
* STM32L476RG Datasheet (for erase timing)
* http://www.st.com/st-web-ui/static/active/en/resource/technical/document/datasheet/DM00108832.pdf
* http://www.st.com/resource/en/datasheet/stm32l476rg.pdf
*
*
* The device has normally two banks, but on 512 and 256 kiB devices an
* option byte is available to map all sectors to the first bank.
* The RM0351 devices have normally two banks, but on 512 and 256 kiB devices
* an option byte is available to map all sectors to the first bank.
* Both STM32 banks are treated as one OpenOCD bank, as other STM32 devices
* handlers do!
*
* RM0394 devices have a single bank only.
*
*/
/* Erase time can be as high as 25ms, 10x this and assume it's toast... */
@@ -614,9 +618,16 @@ static int stm32l4_probe(struct flash_bank *bank)
/* set max flash size depending on family */
switch (device_id & 0xfff) {
case 0x461:
case 0x415:
max_flash_size_in_kb = 1024;
break;
case 0x462:
max_flash_size_in_kb = 512;
break;
case 0x435:
max_flash_size_in_kb = 256;
break;
default:
LOG_WARNING("Cannot identify target as a STM32L4 family.");
return ERROR_FAIL;
@@ -698,7 +709,7 @@ static int get_stm32l4_info(struct flash_bank *bank, char *buf, int buf_size)
if (retval != ERROR_OK)
return retval;
uint16_t device_id = dbgmcu_idcode & 0xffff;
uint16_t device_id = dbgmcu_idcode & 0xfff;
uint8_t rev_id = dbgmcu_idcode >> 28;
uint8_t rev_minor = 0;
int i;
@@ -713,8 +724,20 @@ static int get_stm32l4_info(struct flash_bank *bank, char *buf, int buf_size)
const char *device_str;
switch (device_id) {
case 0x6415:
device_str = "STM32L4xx";
case 0x461:
device_str = "STM32L496/4A6";
break;
case 0x415:
device_str = "STM32L475/476/486";
break;
case 0x462:
device_str = "STM32L45x/46x";
break;
case 0x435:
device_str = "STM32L43x/44x";
break;
default:
+73 -116
View File
@@ -105,6 +105,7 @@ static int stm32lx_lock(struct flash_bank *bank);
static int stm32lx_unlock(struct flash_bank *bank);
static int stm32lx_mass_erase(struct flash_bank *bank);
static int stm32lx_wait_until_bsy_clear_timeout(struct flash_bank *bank, int timeout);
static int stm32lx_update_part_info(struct flash_bank *bank, uint16_t flash_size_in_kb);
struct stm32lx_rev {
uint16_t rev;
@@ -132,7 +133,7 @@ struct stm32lx_flash_bank {
uint32_t user_bank_size;
uint32_t flash_base;
const struct stm32lx_part_info *part_info;
struct stm32lx_part_info part_info;
};
static const struct stm32lx_rev stm32_416_revs[] = {
@@ -245,7 +246,7 @@ static const struct stm32lx_part_info stm32lx_parts[] = {
.page_size = 256,
.pages_per_sector = 16,
.max_flash_size_kb = 512,
.first_bank_size_kb = 256,
.first_bank_size_kb = 0, /* determined in runtime */
.has_dual_banks = true,
.flash_base = 0x40023C00,
.fsize_base = 0x1FF800CC,
@@ -258,8 +259,8 @@ static const struct stm32lx_part_info stm32lx_parts[] = {
.page_size = 128,
.pages_per_sector = 32,
.max_flash_size_kb = 192,
.first_bank_size_kb = 128,
.has_dual_banks = true,
.first_bank_size_kb = 0, /* determined in runtime */
.has_dual_banks = false, /* determined in runtime */
.flash_base = 0x40022000,
.fsize_base = 0x1FF8007C,
},
@@ -300,7 +301,7 @@ FLASH_BANK_COMMAND_HANDLER(stm32lx_flash_bank_command)
stm32lx_info->user_bank_size = bank->size;
/* the stm32l erased value is 0x00 */
bank->default_padded_value = 0x00;
bank->default_padded_value = bank->erased_value = 0x00;
return ERROR_OK;
}
@@ -436,7 +437,7 @@ static int stm32lx_write_half_pages(struct flash_bank *bank, const uint8_t *buff
struct target *target = bank->target;
struct stm32lx_flash_bank *stm32lx_info = bank->driver_priv;
uint32_t hp_nb = stm32lx_info->part_info->page_size / 2;
uint32_t hp_nb = stm32lx_info->part_info.page_size / 2;
uint32_t buffer_size = 16384;
struct working_area *write_algorithm;
struct working_area *source;
@@ -450,19 +451,7 @@ static int stm32lx_write_half_pages(struct flash_bank *bank, const uint8_t *buff
/* see contib/loaders/flash/stm32lx.S for src */
static const uint8_t stm32lx_flash_write_code[] = {
/* write_word: */
0x00, 0x23, /* movs r3, #0 */
0x04, 0xe0, /* b test_done */
/* write_word: */
0x51, 0xf8, 0x04, 0xcb, /* ldr ip, [r1], #4 */
0x40, 0xf8, 0x04, 0xcb, /* str ip, [r0], #4 */
0x01, 0x33, /* adds r3, #1 */
/* test_done: */
0x93, 0x42, /* cmp r3, r2 */
0xf8, 0xd3, /* bcc write_word */
0x00, 0xbe, /* bkpt 0 */
0x92, 0x00, 0x8A, 0x18, 0x01, 0xE0, 0x08, 0xC9, 0x08, 0xC0, 0x91, 0x42, 0xFB, 0xD1, 0x00, 0xBE
};
/* Make sure we're performing a half-page aligned write. */
@@ -495,7 +484,7 @@ static int stm32lx_write_half_pages(struct flash_bank *bank, const uint8_t *buff
else
buffer_size /= 2;
if (buffer_size <= stm32lx_info->part_info->page_size) {
if (buffer_size <= stm32lx_info->part_info.page_size) {
/* we already allocated the writing code, but failed to get a
* buffer, free the algorithm */
target_free_working_area(target, write_algorithm);
@@ -588,7 +577,7 @@ static int stm32lx_write_half_pages(struct flash_bank *bank, const uint8_t *buff
* is reduced by 50% using this slower method.
*/
LOG_WARNING("couldn't use loader, falling back to page memory writes");
LOG_WARNING("Couldn't use loader, falling back to page memory writes");
while (count > 0) {
uint32_t this_count;
@@ -629,7 +618,7 @@ static int stm32lx_write(struct flash_bank *bank, const uint8_t *buffer,
struct target *target = bank->target;
struct stm32lx_flash_bank *stm32lx_info = bank->driver_priv;
uint32_t hp_nb = stm32lx_info->part_info->page_size / 2;
uint32_t hp_nb = stm32lx_info->part_info.page_size / 2;
uint32_t halfpages_number;
uint32_t bytes_remaining = 0;
uint32_t address = bank->base + offset;
@@ -759,9 +748,9 @@ static int stm32lx_probe(struct flash_bank *bank)
uint32_t device_id;
uint32_t base_address = FLASH_BANK0_ADDRESS;
uint32_t second_bank_base;
unsigned int n;
stm32lx_info->probed = 0;
stm32lx_info->part_info = NULL;
int retval = stm32lx_read_id_code(bank->target, &device_id);
if (retval != ERROR_OK)
@@ -771,22 +760,24 @@ static int stm32lx_probe(struct flash_bank *bank)
LOG_DEBUG("device id = 0x%08" PRIx32 "", device_id);
for (unsigned int n = 0; n < ARRAY_SIZE(stm32lx_parts); n++) {
if ((device_id & 0xfff) == stm32lx_parts[n].id)
stm32lx_info->part_info = &stm32lx_parts[n];
for (n = 0; n < ARRAY_SIZE(stm32lx_parts); n++) {
if ((device_id & 0xfff) == stm32lx_parts[n].id) {
stm32lx_info->part_info = stm32lx_parts[n];
break;
}
}
if (!stm32lx_info->part_info) {
if (n == ARRAY_SIZE(stm32lx_parts)) {
LOG_WARNING("Cannot identify target as a STM32L family.");
return ERROR_FAIL;
} else {
LOG_INFO("Device: %s", stm32lx_info->part_info->device_str);
LOG_INFO("Device: %s", stm32lx_info->part_info.device_str);
}
stm32lx_info->flash_base = stm32lx_info->part_info->flash_base;
stm32lx_info->flash_base = stm32lx_info->part_info.flash_base;
/* Get the flash size from target. */
retval = target_read_u16(target, stm32lx_info->part_info->fsize_base,
retval = target_read_u16(target, stm32lx_info->part_info.fsize_base,
&flash_size_in_kb);
/* 0x436 devices report their flash size as a 0 or 1 code indicating 384K
@@ -803,29 +794,34 @@ static int stm32lx_probe(struct flash_bank *bank)
* default to max target family */
if (retval != ERROR_OK || flash_size_in_kb == 0xffff || flash_size_in_kb == 0) {
LOG_WARNING("STM32L flash size failed, probe inaccurate - assuming %dk flash",
stm32lx_info->part_info->max_flash_size_kb);
flash_size_in_kb = stm32lx_info->part_info->max_flash_size_kb;
} else if (flash_size_in_kb > stm32lx_info->part_info->max_flash_size_kb) {
stm32lx_info->part_info.max_flash_size_kb);
flash_size_in_kb = stm32lx_info->part_info.max_flash_size_kb;
} else if (flash_size_in_kb > stm32lx_info->part_info.max_flash_size_kb) {
LOG_WARNING("STM32L probed flash size assumed incorrect since FLASH_SIZE=%dk > %dk, - assuming %dk flash",
flash_size_in_kb, stm32lx_info->part_info->max_flash_size_kb,
stm32lx_info->part_info->max_flash_size_kb);
flash_size_in_kb = stm32lx_info->part_info->max_flash_size_kb;
flash_size_in_kb, stm32lx_info->part_info.max_flash_size_kb,
stm32lx_info->part_info.max_flash_size_kb);
flash_size_in_kb = stm32lx_info->part_info.max_flash_size_kb;
}
if (stm32lx_info->part_info->has_dual_banks) {
/* Overwrite default dual-bank configuration */
retval = stm32lx_update_part_info(bank, flash_size_in_kb);
if (retval != ERROR_OK)
return ERROR_FAIL;
if (stm32lx_info->part_info.has_dual_banks) {
/* Use the configured base address to determine if this is the first or second flash bank.
* Verify that the base address is reasonably correct and determine the flash bank size
*/
second_bank_base = base_address +
stm32lx_info->part_info->first_bank_size_kb * 1024;
stm32lx_info->part_info.first_bank_size_kb * 1024;
if (bank->base == second_bank_base || !bank->base) {
/* This is the second bank */
base_address = second_bank_base;
flash_size_in_kb = flash_size_in_kb -
stm32lx_info->part_info->first_bank_size_kb;
stm32lx_info->part_info.first_bank_size_kb;
} else if (bank->base == base_address) {
/* This is the first bank */
flash_size_in_kb = stm32lx_info->part_info->first_bank_size_kb;
flash_size_in_kb = stm32lx_info->part_info.first_bank_size_kb;
} else {
LOG_WARNING("STM32L flash bank base address config is incorrect."
" 0x%" PRIx32 " but should rather be 0x%" PRIx32 " or 0x%" PRIx32,
@@ -884,60 +880,13 @@ static int stm32lx_auto_probe(struct flash_bank *bank)
return stm32lx_probe(bank);
}
static int stm32lx_erase_check(struct flash_bank *bank)
{
struct target *target = bank->target;
const int buffer_size = 4096;
int i;
uint32_t nBytes;
int retval = ERROR_OK;
if (bank->target->state != TARGET_HALTED) {
LOG_ERROR("Target not halted");
return ERROR_TARGET_NOT_HALTED;
}
uint8_t *buffer = malloc(buffer_size);
if (buffer == NULL) {
LOG_ERROR("failed to allocate read buffer");
return ERROR_FAIL;
}
for (i = 0; i < bank->num_sectors; i++) {
uint32_t j;
bank->sectors[i].is_erased = 1;
/* Loop chunk by chunk over the sector */
for (j = 0; j < bank->sectors[i].size; j += buffer_size) {
uint32_t chunk;
chunk = buffer_size;
if (chunk > (j - bank->sectors[i].size))
chunk = (j - bank->sectors[i].size);
retval = target_read_memory(target, bank->base
+ bank->sectors[i].offset + j, 4, chunk / 4, buffer);
if (retval != ERROR_OK)
break;
for (nBytes = 0; nBytes < chunk; nBytes++) {
if (buffer[nBytes] != 0x00) {
bank->sectors[i].is_erased = 0;
break;
}
}
}
if (retval != ERROR_OK)
break;
}
free(buffer);
return retval;
}
/* This method must return a string displaying information about the bank */
static int stm32lx_get_info(struct flash_bank *bank, char *buf, int buf_size)
{
struct stm32lx_flash_bank *stm32lx_info = bank->driver_priv;
const struct stm32lx_part_info *info = &stm32lx_info->part_info;
uint16_t rev_id = stm32lx_info->idcode >> 16;
const char *rev_str = NULL;
if (!stm32lx_info->probed) {
int retval = stm32lx_probe(bank);
@@ -948,32 +897,21 @@ static int stm32lx_get_info(struct flash_bank *bank, char *buf, int buf_size)
}
}
const struct stm32lx_part_info *info = stm32lx_info->part_info;
for (unsigned int i = 0; i < info->num_revs; i++)
if (rev_id == info->revs[i].rev)
rev_str = info->revs[i].str;
if (info) {
const char *rev_str = NULL;
uint16_t rev_id = stm32lx_info->idcode >> 16;
for (unsigned int i = 0; i < info->num_revs; i++)
if (rev_id == info->revs[i].rev)
rev_str = info->revs[i].str;
if (rev_str != NULL) {
snprintf(buf, buf_size,
"%s - Rev: %s",
stm32lx_info->part_info->device_str, rev_str);
} else {
snprintf(buf, buf_size,
"%s - Rev: unknown (0x%04x)",
stm32lx_info->part_info->device_str, rev_id);
}
return ERROR_OK;
if (rev_str != NULL) {
snprintf(buf, buf_size,
"%s - Rev: %s",
info->device_str, rev_str);
} else {
snprintf(buf, buf_size, "Cannot identify target as a STM32Lx");
return ERROR_FAIL;
snprintf(buf, buf_size,
"%s - Rev: unknown (0x%04x)",
info->device_str, rev_id);
}
return ERROR_OK;
}
static const struct command_registration stm32lx_exec_command_handlers[] = {
@@ -1022,7 +960,7 @@ struct flash_driver stm32lx_flash = {
.read = default_flash_read,
.probe = stm32lx_probe,
.auto_probe = stm32lx_auto_probe,
.erase_check = stm32lx_erase_check,
.erase_check = default_flash_blank_check,
.protect_check = stm32lx_protect_check,
.info = stm32lx_get_info,
};
@@ -1182,7 +1120,7 @@ static int stm32lx_erase_sector(struct flash_bank *bank, int sector)
if (retval != ERROR_OK)
return retval;
for (int page = 0; page < (int)stm32lx_info->part_info->pages_per_sector;
for (int page = 0; page < (int)stm32lx_info->part_info.pages_per_sector;
page++) {
reg32 = FLASH_PECR__PROG | FLASH_PECR__ERASE;
retval = target_write_u32(target,
@@ -1195,7 +1133,7 @@ static int stm32lx_erase_sector(struct flash_bank *bank, int sector)
return retval;
uint32_t addr = bank->base + bank->sectors[sector].offset + (page
* stm32lx_info->part_info->page_size);
* stm32lx_info->part_info.page_size);
retval = target_write_u32(target, addr, 0x0);
if (retval != ERROR_OK)
return retval;
@@ -1419,3 +1357,22 @@ static int stm32lx_mass_erase(struct flash_bank *bank)
return ERROR_OK;
}
static int stm32lx_update_part_info(struct flash_bank *bank, uint16_t flash_size_in_kb)
{
struct stm32lx_flash_bank *stm32lx_info = bank->driver_priv;
switch (stm32lx_info->part_info.id) {
case 0x447: /* STM32L0xx (Cat.5) devices */
if (flash_size_in_kb == 192 || flash_size_in_kb == 128) {
stm32lx_info->part_info.first_bank_size_kb = flash_size_in_kb / 2;
stm32lx_info->part_info.has_dual_banks = true;
}
break;
case 0x437: /* STM32L1xx (Cat.5/Cat.6) */
stm32lx_info->part_info.first_bank_size_kb = flash_size_in_kb / 2;
break;
}
return ERROR_OK;
}
+32 -23
View File
@@ -297,8 +297,8 @@ static int flash_check_sector_parameters(struct command_context *cmd_ctx,
}
if (!(last <= (num_sectors - 1))) {
command_print(cmd_ctx, "ERROR: last sector must be <= %d",
(int) num_sectors - 1);
command_print(cmd_ctx, "ERROR: last sector must be <= %" PRIu32,
num_sectors - 1);
return ERROR_FAIL;
}
@@ -341,7 +341,7 @@ COMMAND_HANDLER(handle_flash_erase_command)
"in %fs", first, last, p->bank_number, duration_elapsed(&bench));
}
return ERROR_OK;
return retval;
}
COMMAND_HANDLER(handle_flash_protect_command)
@@ -380,10 +380,9 @@ COMMAND_HANDLER(handle_flash_protect_command)
retval = flash_driver_protect(p, set, first, last);
if (retval == ERROR_OK) {
command_print(CMD_CTX, "%s protection for sectors %i "
"through %i on flash bank %d",
(set) ? "set" : "cleared", (int) first,
(int) last, p->bank_number);
command_print(CMD_CTX, "%s protection for sectors %" PRIu32
" through %" PRIu32 " on flash bank %d",
(set) ? "set" : "cleared", first, last, p->bank_number);
}
return retval;
@@ -600,7 +599,7 @@ COMMAND_HANDLER(handle_flash_write_bank_command)
COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], offset);
if (fileio_open(&fileio, CMD_ARGV[1], FILEIO_READ, FILEIO_BINARY) != ERROR_OK)
return ERROR_OK;
return ERROR_FAIL;
size_t filesize;
retval = fileio_size(fileio, &filesize);
@@ -619,7 +618,7 @@ COMMAND_HANDLER(handle_flash_write_bank_command)
if (fileio_read(fileio, filesize, buffer, &buf_cnt) != ERROR_OK) {
free(buffer);
fileio_close(fileio);
return ERROR_OK;
return ERROR_FAIL;
}
retval = flash_driver_write(p, buffer, offset, buf_cnt);
@@ -690,9 +689,9 @@ COMMAND_HANDLER(handle_flash_read_bank_command)
}
if (duration_measure(&bench) == ERROR_OK)
command_print(CMD_CTX, "wrote %ld bytes to file %s from flash bank %u"
command_print(CMD_CTX, "wrote %zd bytes to file %s from flash bank %u"
" at offset 0x%8.8" PRIx32 " in %fs (%0.3f KiB/s)",
(long)written, CMD_ARGV[1], p->bank_number, offset,
written, CMD_ARGV[1], p->bank_number, offset,
duration_elapsed(&bench), duration_kbps(&bench, written));
return retval;
@@ -708,7 +707,7 @@ COMMAND_HANDLER(handle_flash_verify_bank_command)
size_t filesize;
int differ;
if (CMD_ARGC != 3)
if (CMD_ARGC < 2 || CMD_ARGC > 3)
return ERROR_COMMAND_SYNTAX_ERROR;
struct duration bench;
@@ -719,7 +718,16 @@ COMMAND_HANDLER(handle_flash_verify_bank_command)
if (ERROR_OK != retval)
return retval;
COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], offset);
offset = 0;
if (CMD_ARGC > 2)
COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], offset);
if (offset > p->size) {
LOG_ERROR("Offset 0x%8.8" PRIx32 " is out of range of the flash bank",
offset);
return ERROR_COMMAND_ARGUMENT_INVALID;
}
retval = fileio_open(&fileio, CMD_ARGV[1], FILEIO_READ, FILEIO_BINARY);
if (retval != ERROR_OK) {
@@ -770,9 +778,9 @@ COMMAND_HANDLER(handle_flash_verify_bank_command)
}
if (duration_measure(&bench) == ERROR_OK)
command_print(CMD_CTX, "read %ld bytes from file %s and flash bank %u"
command_print(CMD_CTX, "read %zd bytes from file %s and flash bank %u"
" at offset 0x%8.8" PRIx32 " in %fs (%0.3f KiB/s)",
(long)read_cnt, CMD_ARGV[1], p->bank_number, offset,
read_cnt, CMD_ARGV[1], p->bank_number, offset,
duration_elapsed(&bench), duration_kbps(&bench, read_cnt));
differ = memcmp(buffer_file, buffer_flash, read_cnt);
@@ -927,19 +935,20 @@ static const struct command_registration flash_exec_command_handlers[] = {
.name = "verify_bank",
.handler = handle_flash_verify_bank_command,
.mode = COMMAND_EXEC,
.usage = "bank_id filename offset",
.help = "Read binary data from flash bank and file, "
"starting at specified byte offset from the "
"beginning of the bank. Compare the contents.",
.usage = "bank_id filename [offset]",
.help = "Compare the contents of a file with the contents of the "
"flash bank. Allow optional offset from beginning of the bank "
"(defaults to zero).",
},
{
.name = "protect",
.handler = handle_flash_protect_command,
.mode = COMMAND_EXEC,
.usage = "bank_id first_sector [last_sector|'last'] "
.usage = "bank_id first_block [last_block|'last'] "
"('on'|'off')",
.help = "Turn protection on or off for a range of sectors "
"in a given flash bank.",
.help = "Turn protection on or off for a range of protection "
"blocks or sectors in a given flash bank. "
"See 'flash info' output for a list of blocks.",
},
{
.name = "padded_value",
@@ -1012,7 +1021,7 @@ COMMAND_HANDLER(handle_flash_bank_command)
COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], c->size);
COMMAND_PARSE_NUMBER(int, CMD_ARGV[3], c->chip_width);
COMMAND_PARSE_NUMBER(int, CMD_ARGV[4], c->bus_width);
c->default_padded_value = 0xff;
c->default_padded_value = c->erased_value = 0xff;
c->num_sectors = 0;
c->sectors = NULL;
c->num_prot_blocks = 0;
+1
View File
@@ -44,6 +44,7 @@ static void virtual_update_bank_info(struct flash_bank *bank)
bank->size = master_bank->size;
bank->chip_width = master_bank->chip_width;
bank->bus_width = master_bank->bus_width;
bank->erased_value = master_bank->erased_value;
bank->default_padded_value = master_bank->default_padded_value;
bank->num_sectors = master_bank->num_sectors;
bank->sectors = master_bank->sectors;
+1 -1
View File
@@ -305,7 +305,7 @@ static int xmc1xxx_write(struct flash_bank *bank, const uint8_t *buffer,
uint32_t blocks = MIN(block_count, data_workarea->size / NVM_BLOCK_SIZE);
uint32_t addr = bank->base + offset;
LOG_DEBUG("copying %" PRId32 " bytes to SRAM 0x%08" PRIx32,
LOG_DEBUG("copying %" PRId32 " bytes to SRAM 0x%08" TARGET_PRIxADDR,
MIN(blocks * NVM_BLOCK_SIZE, byte_count),
data_workarea->address);
+13 -98
View File
@@ -183,7 +183,7 @@
/* Flash controller configuration values */
#define FLASH_ID_XMC4500 0xA2
#define FLASH_ID_XMC4700_4800 0x92
#define FLASH_ID_XMC4300_XMC4700_4800 0x92
#define FLASH_ID_XMC4100_4200 0x9C
#define FLASH_ID_XMC4400 0x9F
@@ -319,8 +319,8 @@ static int xmc4xxx_load_bank_layout(struct flash_bank *bank)
}
/* This part doesn't follow the typical standard of 0xff
* being the default padding value.*/
bank->default_padded_value = 0x00;
* being the erased value.*/
bank->default_padded_value = bank->erased_value = 0x00;
return ERROR_OK;
}
@@ -383,7 +383,7 @@ static int xmc4xxx_probe(struct flash_bank *bank)
bank->num_sectors = 12;
LOG_DEBUG("XMC4xxx: XMC4500 detected.");
break;
case FLASH_ID_XMC4700_4800:
case FLASH_ID_XMC4300_XMC4700_4800:
bank->num_sectors = 16;
LOG_DEBUG("XMC4xxx: XMC4700/4800 detected.");
break;
@@ -617,99 +617,6 @@ static int xmc4xxx_enter_page_mode(struct flash_bank *bank)
return res;
}
/* The logical erase value of an xmc4xxx memory cell is 0x00,
* therefore, we cannot use the built in flash blank check and must
* implement our own */
/** Checks whether a memory region is zeroed. */
static int xmc4xxx_blank_check_memory(struct target *target,
uint32_t address, uint32_t count, uint32_t *blank)
{
struct working_area *erase_check_algorithm;
struct reg_param reg_params[3];
struct armv7m_algorithm armv7m_info;
int retval;
static const uint8_t erase_check_code[] = {
#include "../../../contrib/loaders/erase_check/armv7m_0_erase_check.inc"
};
/* make sure we have a working area */
if (target_alloc_working_area(target, sizeof(erase_check_code),
&erase_check_algorithm) != ERROR_OK)
return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
retval = target_write_buffer(target, erase_check_algorithm->address,
sizeof(erase_check_code), (uint8_t *)erase_check_code);
if (retval != ERROR_OK)
goto cleanup;
armv7m_info.common_magic = ARMV7M_COMMON_MAGIC;
armv7m_info.core_mode = ARM_MODE_THREAD;
init_reg_param(&reg_params[0], "r0", 32, PARAM_OUT);
buf_set_u32(reg_params[0].value, 0, 32, address);
init_reg_param(&reg_params[1], "r1", 32, PARAM_OUT);
buf_set_u32(reg_params[1].value, 0, 32, count);
init_reg_param(&reg_params[2], "r2", 32, PARAM_IN_OUT);
buf_set_u32(reg_params[2].value, 0, 32, 0x00);
retval = target_run_algorithm(target,
0,
NULL,
3,
reg_params,
erase_check_algorithm->address,
erase_check_algorithm->address + (sizeof(erase_check_code) - 2),
10000,
&armv7m_info);
if (retval == ERROR_OK)
*blank = buf_get_u32(reg_params[2].value, 0, 32);
destroy_reg_param(&reg_params[0]);
destroy_reg_param(&reg_params[1]);
destroy_reg_param(&reg_params[2]);
cleanup:
target_free_working_area(target, erase_check_algorithm);
return retval;
}
static int xmc4xxx_flash_blank_check(struct flash_bank *bank)
{
struct target *target = bank->target;
int i;
int retval = ERROR_OK;
uint32_t blank;
if (bank->target->state != TARGET_HALTED) {
LOG_ERROR("Target not halted");
return ERROR_TARGET_NOT_HALTED;
}
for (i = 0; i < bank->num_sectors; i++) {
uint32_t address = bank->base + bank->sectors[i].offset;
uint32_t size = bank->sectors[i].size;
LOG_DEBUG("Erase checking 0x%08"PRIx32, address);
retval = xmc4xxx_blank_check_memory(target, address, size, &blank);
if (retval != ERROR_OK)
break;
if (blank == 0x00)
bank->sectors[i].is_erased = 1;
else
bank->sectors[i].is_erased = 0;
}
return retval;
}
static int xmc4xxx_write_page(struct flash_bank *bank, const uint8_t *pg_buf,
uint32_t offset, bool user_config)
{
@@ -944,6 +851,14 @@ static int xmc4xxx_get_info_command(struct flash_bank *bank, char *buf, int buf_
break;
}
break;
case 0x300:
dev_str = "XMC4300";
switch (rev_id) {
case 0x1:
rev_str = "AA";
}
break;
case 0x400:
dev_str = "XMC4400";
@@ -1437,7 +1352,7 @@ struct flash_driver xmc4xxx_flash = {
.read = default_flash_read,
.probe = xmc4xxx_probe,
.auto_probe = xmc4xxx_probe,
.erase_check = xmc4xxx_flash_blank_check,
.erase_check = default_flash_blank_check,
.info = xmc4xxx_get_info_command,
.protect_check = xmc4xxx_protect_check,
.protect = xmc4xxx_protect,
+38 -45
View File
@@ -1,56 +1,49 @@
include $(top_srcdir)/common.mk
noinst_LTLIBRARIES += %D%/libhelper.la
METASOURCES = AUTO
noinst_LTLIBRARIES = libhelper.la
%C%_libhelper_la_CPPFLAGS = $(AM_CPPFLAGS) $(LIBUSB1_CFLAGS)
CONFIGFILES = options.c time_support_common.c
libhelper_la_CPPFLAGS = $(AM_CPPFLAGS) $(LIBUSB1_CFLAGS)
libhelper_la_SOURCES = \
binarybuffer.c \
$(CONFIGFILES) \
configuration.c \
log.c \
command.c \
time_support.c \
replacements.c \
fileio.c \
util.c \
jep106.c \
jim-nvp.c
%C%_libhelper_la_SOURCES = \
%D%/binarybuffer.c \
%D%/options.c \
%D%/time_support_common.c \
%D%/configuration.c \
%D%/log.c \
%D%/command.c \
%D%/time_support.c \
%D%/replacements.c \
%D%/fileio.c \
%D%/util.c \
%D%/jep106.c \
%D%/jim-nvp.c \
%D%/binarybuffer.h \
%D%/configuration.h \
%D%/ioutil.h \
%D%/list.h \
%D%/util.h \
%D%/types.h \
%D%/log.h \
%D%/command.h \
%D%/time_support.h \
%D%/replacements.h \
%D%/fileio.h \
%D%/system.h \
%D%/jep106.h \
%D%/jep106.inc \
%D%/jim-nvp.h
if IOUTIL
libhelper_la_SOURCES += ioutil.c
%C%_libhelper_la_SOURCES += %D%/ioutil.c
else
libhelper_la_SOURCES += ioutil_stubs.c
%C%_libhelper_la_SOURCES += %D%/ioutil_stubs.c
endif
libhelper_la_CFLAGS =
%C%_libhelper_la_CFLAGS = $(AM_CFLAGS)
if IS_MINGW
# FD_* macros are sloppy with their signs on MinGW32 platform
libhelper_la_CFLAGS += -Wno-sign-compare
%C%_libhelper_la_CFLAGS += -Wno-sign-compare
endif
noinst_HEADERS = \
binarybuffer.h \
configuration.h \
ioutil.h \
list.h \
util.h \
types.h \
log.h \
command.h \
time_support.h \
replacements.h \
fileio.h \
system.h \
bin2char.sh \
jep106.h \
jep106.inc \
update_jep106.pl \
jim-nvp.h
EXTRA_DIST = startup.tcl
MAINTAINERCLEANFILES = $(srcdir)/Makefile.in
STARTUP_TCL_SRCS += %D%/startup.tcl
EXTRA_DIST += \
%D%/bin2char.sh \
%D%/update_jep106.pl
+61 -15
View File
@@ -45,6 +45,11 @@ static const unsigned char bit_reverse_table256[] = {
0x0F, 0x8F, 0x4F, 0xCF, 0x2F, 0xAF, 0x6F, 0xEF, 0x1F, 0x9F, 0x5F, 0xDF, 0x3F, 0xBF, 0x7F, 0xFF
};
static const char hex_digits[] = {
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
'a', 'b', 'c', 'd', 'e', 'f'
};
void *buf_cpy(const void *from, void *_to, unsigned size)
{
if (NULL == from || NULL == _to)
@@ -369,31 +374,72 @@ void bit_copy_discard(struct bit_copy_queue *q)
}
}
int unhexify(char *bin, const char *hex, int count)
/**
* Convert a string of hexadecimal pairs into its binary
* representation.
*
* @param[out] bin Buffer to store binary representation. The buffer size must
* be at least @p count.
* @param[in] hex String with hexadecimal pairs to convert into its binary
* representation.
* @param[in] count Number of hexadecimal pairs to convert.
*
* @return The number of converted hexadecimal pairs.
*/
size_t unhexify(uint8_t *bin, const char *hex, size_t count)
{
int i, tmp;
size_t i;
char tmp;
for (i = 0; i < count; i++) {
if (sscanf(hex + (2 * i), "%02x", &tmp) != 1)
return i;
bin[i] = tmp;
if (!bin || !hex)
return 0;
memset(bin, 0, count);
for (i = 0; i < 2 * count; i++) {
if (hex[i] >= 'a' && hex[i] <= 'f')
tmp = hex[i] - 'a' + 10;
else if (hex[i] >= 'A' && hex[i] <= 'F')
tmp = hex[i] - 'A' + 10;
else if (hex[i] >= '0' && hex[i] <= '9')
tmp = hex[i] - '0';
else
return i / 2;
bin[i / 2] |= tmp << (4 * ((i + 1) % 2));
}
return i;
return i / 2;
}
int hexify(char *hex, const char *bin, int count, int out_maxlen)
/**
* Convert binary data into a string of hexadecimal pairs.
*
* @param[out] hex Buffer to store string of hexadecimal pairs. The buffer size
* must be at least @p length.
* @param[in] bin Buffer with binary data to convert into hexadecimal pairs.
* @param[in] count Number of bytes to convert.
* @param[in] length Maximum number of characters, including null-terminator,
* to store into @p hex.
*
* @returns The length of the converted string excluding null-terminator.
*/
size_t hexify(char *hex, const uint8_t *bin, size_t count, size_t length)
{
int i, cmd_len = 0;
size_t i;
uint8_t tmp;
/* May use a length, or a null-terminated string as input. */
if (count == 0)
count = strlen(bin);
if (!length)
return 0;
for (i = 0; i < count; i++)
cmd_len += snprintf(hex + cmd_len, out_maxlen - cmd_len, "%02x", bin[i] & 0xff);
for (i = 0; i < length - 1 && i < 2 * count; i++) {
tmp = (bin[i / 2] >> (4 * ((i + 1) % 2))) & 0x0f;
hex[i] = hex_digits[tmp];
}
return cmd_len;
hex[i] = 0;
return i;
}
void buffer_shr(void *_buf, unsigned buf_len, unsigned count)
+2 -2
View File
@@ -234,8 +234,8 @@ void bit_copy_discard(struct bit_copy_queue *q);
/* functions to convert to/from hex encoded buffer
* used in ti-icdi driver and gdb server */
int unhexify(char *bin, const char *hex, int count);
int hexify(char *hex, const char *bin, int count, int out_maxlen);
size_t unhexify(uint8_t *bin, const char *hex, size_t count);
size_t hexify(char *hex, const uint8_t *bin, size_t count, size_t out_maxlen);
void buffer_shr(void *_buf, unsigned buf_len, unsigned count);
#endif /* OPENOCD_HELPER_BINARYBUFFER_H */
+2
View File
@@ -1410,6 +1410,8 @@ DEFINE_PARSE_ULONGLONG(_u32, uint32_t, 0, UINT32_MAX)
DEFINE_PARSE_ULONGLONG(_u16, uint16_t, 0, UINT16_MAX)
DEFINE_PARSE_ULONGLONG(_u8, uint8_t, 0, UINT8_MAX)
DEFINE_PARSE_ULONGLONG(_target_addr, target_addr_t, 0, TARGET_ADDR_MAX)
#define DEFINE_PARSE_LONGLONG(name, type, min, max) \
DEFINE_PARSE_WRAPPER(name, type, min, max, long long, _llong)
DEFINE_PARSE_LONGLONG(_int, int, n < INT_MIN, INT_MAX)
+6
View File
@@ -357,10 +357,13 @@ DECLARE_PARSE_WRAPPER(_u16, uint16_t);
DECLARE_PARSE_WRAPPER(_u8, uint8_t);
DECLARE_PARSE_WRAPPER(_int, int);
DECLARE_PARSE_WRAPPER(_s64, int64_t);
DECLARE_PARSE_WRAPPER(_s32, int32_t);
DECLARE_PARSE_WRAPPER(_s16, int16_t);
DECLARE_PARSE_WRAPPER(_s8, int8_t);
DECLARE_PARSE_WRAPPER(_target_addr, target_addr_t);
/**
* @brief parses the string @a in into @a out as a @a type, or prints
* a command error and passes the error code to the caller. If an error
@@ -382,6 +385,9 @@ DECLARE_PARSE_WRAPPER(_s8, int8_t);
} \
} while (0)
#define COMMAND_PARSE_ADDRESS(in, out) \
COMMAND_PARSE_NUMBER(target_addr, in, out)
/**
* Parse the string @c as a binary parameter, storing the boolean value
* in @c out. The strings @c on and @c off are used to match different
+41 -4
View File
@@ -884,7 +884,7 @@
[7][0x01 - 1] = "Siklu Communication Ltd.",
[7][0x02 - 1] = "A Force Manufacturing Ltd.",
[7][0x03 - 1] = "Strontium",
[7][0x04 - 1] = "Abilis Systems",
[7][0x04 - 1] = "ALi Corp (Abilis Systems)",
[7][0x05 - 1] = "Siglead, Inc.",
[7][0x06 - 1] = "Ubicom, Inc.",
[7][0x07 - 1] = "Unifosa Corporation",
@@ -893,7 +893,7 @@
[7][0x0a - 1] = "Visipro.",
[7][0x0b - 1] = "EKMemory",
[7][0x0c - 1] = "Microelectronics Institute ZTE",
[7][0x0d - 1] = "Cognovo Ltd.",
[7][0x0d - 1] = "u-blox AG",
[7][0x0e - 1] = "Carry Technology Co. Ltd.",
[7][0x0f - 1] = "Nokia",
[7][0x10 - 1] = "King Tiger Technology",
@@ -1101,12 +1101,12 @@
[8][0x5c - 1] = "Vitesse Enterprise Co.",
[8][0x5d - 1] = "Foxtronn International Corporation",
[8][0x5e - 1] = "Bretelon Inc.",
[8][0x5f - 1] = "Zbit Semiconductor, Inc.",
[8][0x5f - 1] = "Graphcore",
[8][0x60 - 1] = "Eoplex Inc",
[8][0x61 - 1] = "MaxLinear, Inc.",
[8][0x62 - 1] = "ETA Devices",
[8][0x63 - 1] = "LOKI",
[8][0x64 - 1] = "IMS Semiconductor Co., Ltd",
[8][0x64 - 1] = "IMS Electronics Co., Ltd.",
[8][0x65 - 1] = "Dosilicon Co., Ltd.",
[8][0x66 - 1] = "Dolphin Integration",
[8][0x67 - 1] = "Shenzhen Mic Electronics Technology",
@@ -1116,4 +1116,41 @@
[8][0x6b - 1] = "Kingred Electronic Technology Ltd.",
[8][0x6c - 1] = "Chao Yue Zhuo Computer Business Dept.",
[8][0x6d - 1] = "Guangzhou Si Nuo Electronic Technology.",
[8][0x6e - 1] = "Crocus Technology Inc.",
[8][0x6f - 1] = "Creative Chips GmbH",
[8][0x70 - 1] = "GE Aviation Systems LLC.",
[8][0x71 - 1] = "Asgard",
[8][0x72 - 1] = "Good Wealth Technology Ltd.",
[8][0x73 - 1] = "TriCor Technologies",
[8][0x74 - 1] = "Nova-Systems GmbH",
[8][0x75 - 1] = "JUHOR",
[8][0x76 - 1] = "Zhuhai Douke Commerce Co. Ltd.",
[8][0x77 - 1] = "DSL Memory",
[8][0x78 - 1] = "Anvo-Systems Dresden GmbH",
[8][0x79 - 1] = "Realtek",
[8][0x7a - 1] = "AltoBeam",
[8][0x7b - 1] = "Wave Computing",
[8][0x7c - 1] = "Beijing TrustNet Technology Co. Ltd.",
[8][0x7d - 1] = "Innovium, Inc.",
[8][0x7e - 1] = "Starsway Technology Limited",
[9][0x01 - 1] = "Weltronics Co. LTD",
[9][0x02 - 1] = "VMware, Inc.",
[9][0x03 - 1] = "Hewlett Packard Enterprise",
[9][0x04 - 1] = "INTENSO",
[9][0x05 - 1] = "Puya Semiconductor",
[9][0x06 - 1] = "MEMORFI",
[9][0x07 - 1] = "MSC Technologies GmbH",
[9][0x08 - 1] = "Txrui",
[9][0x09 - 1] = "SiFive, Inc.",
[9][0x0a - 1] = "Spreadtrum Communications",
[9][0x0b - 1] = "Paragon Technology (Shenzhen) Ltd.",
[9][0x0c - 1] = "UMAX Technology",
[9][0x0d - 1] = "Shenzhen Yong Sheng Technology",
[9][0x0e - 1] = "SNOAMOO (Shenzhen Kai Zhuo Yue)",
[9][0x0f - 1] = "Daten Tecnologia LTDA",
[9][0x10 - 1] = "Shenzhen XinRuiYan Electronics",
[9][0x11 - 1] = "Eta Compute",
[9][0x12 - 1] = "Energous",
[9][0x13 - 1] = "Raspberry Pi Trading Ltd.",
[9][0x14 - 1] = "Shenzhen Chixingzhe Tech Co. Ltd.",
/* EOF */
+34 -17
View File
@@ -191,6 +191,30 @@ void log_printf(enum log_levels level,
va_end(ap);
}
void log_vprintf_lf(enum log_levels level, const char *file, unsigned line,
const char *function, const char *format, va_list args)
{
char *tmp;
count++;
if (level > debug_level)
return;
tmp = alloc_vprintf(format, args);
if (!tmp)
return;
/*
* Note: alloc_vprintf() guarantees that the buffer is at least one
* character longer.
*/
strcat(tmp, "\n");
log_puts(level, file, line, function, tmp);
free(tmp);
}
void log_printf_lf(enum log_levels level,
const char *file,
unsigned line,
@@ -198,23 +222,10 @@ void log_printf_lf(enum log_levels level,
const char *format,
...)
{
char *string;
va_list ap;
count++;
if (level > debug_level)
return;
va_start(ap, format);
string = alloc_vprintf(format, ap);
if (string != NULL) {
strcat(string, "\n"); /* alloc_vprintf guaranteed the buffer to be at least one
*char longer */
log_puts(level, file, line, function, string);
free(string);
}
log_vprintf_lf(level, file, line, function, format, ap);
va_end(ap);
}
@@ -240,9 +251,15 @@ COMMAND_HANDLER(handle_log_output_command)
{
if (CMD_ARGC == 1) {
FILE *file = fopen(CMD_ARGV[0], "w");
if (file)
log_output = file;
if (file == NULL) {
LOG_ERROR("failed to open output log '%s'", CMD_ARGV[0]);
return ERROR_FAIL;
}
if (log_output != stderr && log_output != NULL) {
/* Close previous log file, if it was open and wasn't stderr. */
fclose(log_output);
}
log_output = file;
}
return ERROR_OK;
+2
View File
@@ -60,6 +60,8 @@ enum log_levels {
void log_printf(enum log_levels level, const char *file, unsigned line,
const char *function, const char *format, ...)
__attribute__ ((format (PRINTF_ATTRIBUTE_FORMAT, 5, 6)));
void log_vprintf_lf(enum log_levels level, const char *file, unsigned line,
const char *function, const char *format, va_list args);
void log_printf_lf(enum log_levels level, const char *file, unsigned line,
const char *function, const char *format, ...)
__attribute__ ((format (PRINTF_ATTRIBUTE_FORMAT, 5, 6)));
+139 -38
View File
@@ -29,6 +29,15 @@
#include <getopt.h>
#include <limits.h>
#include <stdlib.h>
#if IS_DARWIN
#include <libproc.h>
#endif
#ifdef HAVE_SYS_SYSCTL_H
#include <sys/sysctl.h>
#endif
static int help_flag, version_flag;
static const struct option long_options[] = {
@@ -50,52 +59,129 @@ int configuration_output_handler(struct command_context *context, const char *li
return ERROR_OK;
}
#ifdef _WIN32
static char *find_suffix(const char *text, const char *suffix)
/* Return the canonical path to the directory the openocd executable is in.
* The path should be absolute, use / as path separator and have all symlinks
* resolved. The returned string is malloc'd. */
static char *find_exe_path(void)
{
size_t text_len = strlen(text);
size_t suffix_len = strlen(suffix);
char *exepath = NULL;
if (suffix_len == 0)
return (char *)text + text_len;
do {
#if IS_WIN32 && !IS_CYGWIN
exepath = malloc(MAX_PATH);
if (exepath == NULL)
break;
GetModuleFileName(NULL, exepath, MAX_PATH);
if (suffix_len > text_len || strncmp(text + text_len - suffix_len, suffix, suffix_len) != 0)
return NULL; /* Not a suffix of text */
/* Convert path separators to UNIX style, should work on Windows also. */
for (char *p = exepath; *p; p++) {
if (*p == '\\')
*p = '/';
}
return (char *)text + text_len - suffix_len;
}
#elif IS_DARWIN
exepath = malloc(PROC_PIDPATHINFO_MAXSIZE);
if (exepath == NULL)
break;
if (proc_pidpath(getpid(), exepath, PROC_PIDPATHINFO_MAXSIZE) <= 0) {
free(exepath);
exepath = NULL;
}
#elif defined(CTL_KERN) && defined(KERN_PROC) && defined(KERN_PROC_PATHNAME) /* *BSD */
#ifndef PATH_MAX
#define PATH_MAX 1024
#endif
char *path = malloc(PATH_MAX);
if (path == NULL)
break;
int mib[] = { CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1 };
size_t size = PATH_MAX;
if (sysctl(mib, (u_int)ARRAY_SIZE(mib), path, &size, NULL, 0) != 0)
break;
#ifdef HAVE_REALPATH
exepath = realpath(path, NULL);
free(path);
#else
exepath = path;
#endif
#elif defined(HAVE_REALPATH) /* Assume POSIX.1-2008 */
/* Try Unices in order of likelihood. */
exepath = realpath("/proc/self/exe", NULL); /* Linux/Cygwin */
if (exepath == NULL)
exepath = realpath("/proc/self/path/a.out", NULL); /* Solaris */
if (exepath == NULL)
exepath = realpath("/proc/curproc/file", NULL); /* FreeBSD (Should be covered above) */
#endif
} while (0);
if (exepath != NULL) {
/* Strip executable file name, leaving path */
*strrchr(exepath, '/') = '\0';
} else {
LOG_WARNING("Could not determine executable path, using configured BINDIR.");
LOG_DEBUG("BINDIR = %s", BINDIR);
#ifdef HAVE_REALPATH
exepath = realpath(BINDIR, NULL);
#else
exepath = strdup(BINDIR);
#endif
}
return exepath;
}
static char *find_relative_path(const char *from, const char *to)
{
size_t i;
/* Skip common /-separated parts of from and to */
i = 0;
for (size_t n = 0; from[n] == to[n]; n++) {
if (from[n] == '\0') {
i = n;
break;
}
if (from[n] == '/')
i = n + 1;
}
from += i;
to += i;
/* Count number of /-separated non-empty parts of from */
i = 0;
while (from[0] != '\0') {
if (from[0] != '/')
i++;
char *next = strchr(from, '/');
if (next == NULL)
break;
from = next + 1;
}
/* Prepend that number of ../ in front of to */
char *relpath = malloc(i * 3 + strlen(to) + 1);
relpath[0] = '\0';
for (size_t n = 0; n < i; n++)
strcat(relpath, "../");
strcat(relpath, to);
return relpath;
}
static void add_default_dirs(void)
{
const char *run_prefix;
char *path;
#ifdef _WIN32
char strExePath[MAX_PATH];
GetModuleFileName(NULL, strExePath, MAX_PATH);
/* Strip executable file name, leaving path */
*strrchr(strExePath, '\\') = '\0';
/* Convert path separators to UNIX style, should work on Windows also. */
for (char *p = strExePath; *p; p++) {
if (*p == '\\')
*p = '/';
}
char *end_of_prefix = find_suffix(strExePath, BINDIR);
if (end_of_prefix != NULL)
*end_of_prefix = '\0';
run_prefix = strExePath;
#else
run_prefix = "";
#endif
char *exepath = find_exe_path();
char *bin2data = find_relative_path(BINDIR, PKGDATADIR);
LOG_DEBUG("bindir=%s", BINDIR);
LOG_DEBUG("pkgdatadir=%s", PKGDATADIR);
LOG_DEBUG("run_prefix=%s", run_prefix);
LOG_DEBUG("exepath=%s", exepath);
LOG_DEBUG("bin2data=%s", bin2data);
/*
* The directory containing OpenOCD-supplied scripts should be
@@ -129,17 +215,20 @@ static void add_default_dirs(void)
}
#endif
path = alloc_printf("%s%s%s", run_prefix, PKGDATADIR, "/site");
path = alloc_printf("%s/%s/%s", exepath, bin2data, "site");
if (path) {
add_script_search_dir(path);
free(path);
}
path = alloc_printf("%s%s%s", run_prefix, PKGDATADIR, "/scripts");
path = alloc_printf("%s/%s/%s", exepath, bin2data, "scripts");
if (path) {
add_script_search_dir(path);
free(path);
}
free(exepath);
free(bin2data);
}
int parse_cmdline_args(struct command_context *cmd_ctx, int argc, char *argv[])
@@ -178,8 +267,10 @@ int parse_cmdline_args(struct command_context *cmd_ctx, int argc, char *argv[])
case 'd': /* --debug | -d */
{
char *command = alloc_printf("debug_level %s", optarg ? optarg : "3");
command_run_line(cmd_ctx, command);
int retval = command_run_line(cmd_ctx, command);
free(command);
if (retval != ERROR_OK)
return retval;
break;
}
case 'l': /* --log_output | -l */
@@ -200,16 +291,26 @@ int parse_cmdline_args(struct command_context *cmd_ctx, int argc, char *argv[])
LOG_WARNING("deprecated option: -p/--pipe. Use '-c \"gdb_port pipe; "
"log_output openocd.log\"' instead.");
break;
default: /* '?' */
/* getopt will emit an error message, all we have to do is bail. */
return ERROR_FAIL;
}
}
if (optind < argc) {
/* Catch extra arguments on the command line. */
LOG_OUTPUT("Unexpected command line argument: %s\n", argv[optind]);
return ERROR_FAIL;
}
if (help_flag) {
LOG_OUTPUT("Open On-Chip Debugger\nLicensed under GNU GPL v2\n");
LOG_OUTPUT("--help | -h\tdisplay this help\n");
LOG_OUTPUT("--version | -v\tdisplay OpenOCD version\n");
LOG_OUTPUT("--file | -f\tuse configuration file <name>\n");
LOG_OUTPUT("--search | -s\tdir to search for config files and scripts\n");
LOG_OUTPUT("--debug | -d\tset debug level <0-3>\n");
LOG_OUTPUT("--debug | -d\tset debug level to 3\n");
LOG_OUTPUT(" | -d<n>\tset debug level to <level>\n");
LOG_OUTPUT("--log_output | -l\tredirect log output to file <name>\n");
LOG_OUTPUT("--command | -c\trun <command>\n");
exit(-1);
+28 -2
View File
@@ -296,14 +296,21 @@ static inline int parity_u32(uint32_t x)
*/
#if !defined(_STDINT_H)
#define PRIx32 "x"
#define PRId32 "d"
#define SCNx32 "x"
#define PRIi32 "i"
#define PRIo32 "o"
#define PRIu32 "u"
#define PRIx32 "x"
#define PRIX32 "X"
#define SCNx32 "x"
#define PRId8 PRId32
#define SCNx64 "llx"
#define PRId64 "lld"
#define PRIi64 "lli"
#define PRIo64 "llo"
#define PRIu64 "llu"
#define PRIx64 "llx"
#define PRIX64 "llX"
typedef CYG_ADDRWORD intptr_t;
typedef int64_t intmax_t;
@@ -337,4 +344,23 @@ typedef uint64_t uintmax_t;
#endif
#if BUILD_TARGET64
typedef uint64_t target_addr_t;
#define TARGET_ADDR_MAX UINT64_MAX
#define TARGET_PRIdADDR PRId64
#define TARGET_PRIuADDR PRIu64
#define TARGET_PRIoADDR PRIo64
#define TARGET_PRIxADDR PRIx64
#define TARGET_PRIXADDR PRIX64
#else
typedef uint32_t target_addr_t;
#define TARGET_ADDR_MAX UINT32_MAX
#define TARGET_PRIdADDR PRId32
#define TARGET_PRIuADDR PRIu32
#define TARGET_PRIoADDR PRIo32
#define TARGET_PRIxADDR PRIx32
#define TARGET_PRIXADDR PRIX32
#endif
#define TARGET_ADDR_FMT "0x%8.8" TARGET_PRIxADDR
#endif /* OPENOCD_HELPER_TYPES_H */
+40 -54
View File
@@ -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
View File
@@ -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
+2 -2
View File
@@ -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];
+1 -1
View File
@@ -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);
+10 -4
View File
@@ -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
View File
@@ -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
View File
@@ -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
+2 -2
View File
@@ -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);
+37 -15
View File
@@ -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
-55
View File
@@ -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 */
+552
View File
@@ -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
View File
@@ -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, &divider);
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
};
+967
View File
@@ -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
};
+3 -2
View File
@@ -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;
+1 -1
View File
@@ -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 */
+3 -1
View File
@@ -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;
+2 -1
View File
@@ -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 */
+2 -2
View File
@@ -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 */
+22 -6
View File
@@ -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
View File
@@ -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
};
-219
View File
@@ -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;
+1 -1
View File
@@ -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
+6 -5
View File
@@ -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)
+1 -1
View File
@@ -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);
+7 -18
View File
@@ -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
+2 -5
View File
@@ -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;
}
+3 -6
View File
@@ -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
View File
@@ -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
View File
@@ -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,
};
+8 -1
View File
@@ -45,8 +45,13 @@
#include <strings.h>
#endif
#ifdef PKGBLDDATE
#define OPENOCD_VERSION \
"Open On-Chip Debugger " VERSION RELSTR " (" PKGBLDDATE ")"
#else
#define OPENOCD_VERSION \
"Open On-Chip Debugger " VERSION RELSTR
#endif
static const char openocd_startup_tcl[] = {
#include "startup_tcl.inc"
@@ -292,8 +297,10 @@ static int openocd_thread(int argc, char *argv[], struct command_context *cmd_ct
if (init_at_startup) {
ret = command_run_line(cmd_ctx, "init");
if (ERROR_OK != ret)
if (ERROR_OK != ret) {
server_quit();
return ERROR_FAIL;
}
}
ret = server_loop(cmd_ctx);
+8 -8
View File
@@ -1,8 +1,8 @@
include $(top_srcdir)/common.mk
METASOURCES = AUTO
noinst_LTLIBRARIES = libpld.la
noinst_HEADERS = pld.h xilinx_bit.h virtex2.h
libpld_la_SOURCES = pld.c xilinx_bit.c virtex2.c
MAINTAINERCLEANFILES = $(srcdir)/Makefile.in
noinst_LTLIBRARIES += %D%/libpld.la
%C%_libpld_la_SOURCES = \
%D%/pld.c \
%D%/xilinx_bit.c \
%D%/virtex2.c \
%D%/pld.h \
%D%/xilinx_bit.h \
%D%/virtex2.h
+3 -3
View File
@@ -440,11 +440,11 @@ static int ChibiOS_update_threads(struct rtos *rtos)
if (threadState < CHIBIOS_NUM_STATES)
state_desc = ChibiOS_thread_states[threadState];
else
state_desc = "Unknown state";
state_desc = "Unknown";
curr_thrd_details->extra_info_str = malloc(strlen(
state_desc)+1);
strcpy(curr_thrd_details->extra_info_str, state_desc);
state_desc)+8);
sprintf(curr_thrd_details->extra_info_str, "State: %s", state_desc);
curr_thrd_details->exists = true;
+1 -1
View File
@@ -362,7 +362,7 @@ static int FreeRTOS_update_threads(struct rtos *rtos)
rtos->thread_details[tasks_found].exists = true;
if (rtos->thread_details[tasks_found].threadid == rtos->current_thread) {
char running_str[] = "Running";
char running_str[] = "State: Running";
rtos->thread_details[tasks_found].extra_info_str = malloc(
sizeof(running_str));
strcpy(rtos->thread_details[tasks_found].extra_info_str,
+29 -27
View File
@@ -1,32 +1,34 @@
# ***************************************************************************
# * Copyright (C) 2011 by Broadcom Corporation *
# * Evan Hunter - ehunter@broadcom.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/>. *
# ***************************************************************************
noinst_LTLIBRARIES += %D%/librtos.la
%C%_librtos_la_SOURCES = \
%D%/rtos.c \
%D%/rtos_standard_stackings.c \
%D%/rtos_ecos_stackings.c \
%D%/rtos_chibios_stackings.c \
%D%/rtos_embkernel_stackings.c \
%D%/rtos_mqx_stackings.c \
%D%/rtos_ucos_iii_stackings.c \
%D%/FreeRTOS.c \
%D%/ThreadX.c \
%D%/eCos.c \
%D%/linux.c \
%D%/ChibiOS.c \
%D%/embKernel.c \
%D%/mqx.c \
%D%/riscv_debug.c \
%D%/uCOS-III.c \
%D%/rtos.h \
%D%/rtos_standard_stackings.h \
%D%/rtos_ecos_stackings.h \
%D%/linux_header.h \
%D%/rtos_chibios_stackings.h \
%D%/rtos_embkernel_stackings.h \
%D%/rtos_mqx_stackings.h \
%D%/rtos_ucos_iii_stackings.h \
%D%/riscv_debug.h
include $(top_srcdir)/common.mk
%C%_librtos_la_CFLAGS = $(AM_CFLAGS)
METASOURCES = AUTO
noinst_LTLIBRARIES = librtos.la
noinst_HEADERS = rtos.h rtos_standard_stackings.h rtos_ecos_stackings.h linux_header.h rtos_chibios_stackings.h rtos_embkernel_stackings.h rtos_mqx_stackings.h riscv_debug.h
librtos_la_SOURCES = rtos.c rtos_standard_stackings.c rtos_ecos_stackings.c rtos_chibios_stackings.c rtos_embkernel_stackings.c rtos_mqx_stackings.c FreeRTOS.c ThreadX.c eCos.c linux.c ChibiOS.c embKernel.c mqx.c riscv_debug.c
librtos_la_CFLAGS =
if IS_MINGW
# FD_* macros are sloppy with their signs on MinGW32 platform
librtos_la_CFLAGS += -Wno-sign-compare
%C%_librtos_la_CFLAGS += -Wno-sign-compare
endif
MAINTAINERCLEANFILES = $(srcdir)/Makefile.in
+2 -2
View File
@@ -408,8 +408,8 @@ static int ThreadX_update_threads(struct rtos *rtos)
state_desc = "Unknown state";
rtos->thread_details[tasks_found].extra_info_str = malloc(strlen(
state_desc)+1);
strcpy(rtos->thread_details[tasks_found].extra_info_str, state_desc);
state_desc)+8);
sprintf(rtos->thread_details[tasks_found].extra_info_str, "State: %s", state_desc);
rtos->thread_details[tasks_found].exists = true;
+2 -2
View File
@@ -261,8 +261,8 @@ static int eCos_update_threads(struct rtos *rtos)
state_desc = "Unknown state";
rtos->thread_details[tasks_found].extra_info_str = malloc(strlen(
state_desc)+1);
strcpy(rtos->thread_details[tasks_found].extra_info_str, state_desc);
state_desc)+8);
sprintf(rtos->thread_details[tasks_found].extra_info_str, "State: %s", state_desc);
rtos->thread_details[tasks_found].exists = true;
+3 -3
View File
@@ -168,11 +168,11 @@ static int embKernel_get_tasks_details(struct rtos *rtos, int64_t iterable, cons
return retval;
details->extra_info_str = malloc(EMBKERNEL_MAX_THREAD_NAME_STR_SIZE);
if (task == rtos->current_thread) {
snprintf(details->extra_info_str, EMBKERNEL_MAX_THREAD_NAME_STR_SIZE, "Pri=%u, Running",
snprintf(details->extra_info_str, EMBKERNEL_MAX_THREAD_NAME_STR_SIZE, "State: Running, Priority: %u",
(unsigned int) priority);
} else {
snprintf(details->extra_info_str, EMBKERNEL_MAX_THREAD_NAME_STR_SIZE, "Pri=%u, %s", (unsigned int) priority,
state_str);
snprintf(details->extra_info_str, EMBKERNEL_MAX_THREAD_NAME_STR_SIZE, "State: %s, Priority: %u",
state_str, (unsigned int) priority);
}
LOG_OUTPUT("Getting task details: iterable=0x%08X, task=0x%08X, name=%s\n", (unsigned int)iterable,
+6 -7
View File
@@ -105,11 +105,11 @@ static int linux_os_dummy_update(struct rtos *rtos)
return 0;
}
static int linux_compute_virt2phys(struct target *target, uint32_t address)
static int linux_compute_virt2phys(struct target *target, target_addr_t address)
{
struct linux_os *linux_os = (struct linux_os *)
target->rtos->rtos_specific_params;
uint32_t pa = 0;
target_addr_t pa = 0;
int retval = target->type->virt2phys(target, address, &pa);
if (retval != ERROR_OK) {
LOG_ERROR("Cannot compute linux virt2phys translation");
@@ -1213,7 +1213,7 @@ int linux_thread_extra_info(struct target *target,
if (temp->threadid == threadid) {
char *pid = " PID: ";
char *pid_current = "*PID: ";
char *name = "NAME: ";
char *name = "Name: ";
int str_size = strlen(pid) + strlen(name);
char *tmp_str = calloc(1, str_size + 50);
char *tmp_str_ptr = tmp_str;
@@ -1225,13 +1225,12 @@ int linux_thread_extra_info(struct target *target,
else
tmp_str_ptr += sprintf(tmp_str_ptr, "%s", pid);
tmp_str_ptr +=
sprintf(tmp_str_ptr, "%d", (int)temp->pid);
tmp_str_ptr += sprintf(tmp_str_ptr, "%s", " | ");
tmp_str_ptr += sprintf(tmp_str_ptr, "%d, ", (int)temp->pid);
sprintf(tmp_str_ptr, "%s", name);
sprintf(tmp_str_ptr, "%s", temp->name);
char *hex_str = calloc(1, strlen(tmp_str) * 2 + 1);
int pkt_len = hexify(hex_str, tmp_str, 0, strlen(tmp_str) * 2 + 1);
size_t pkt_len = hexify(hex_str, (const uint8_t *)tmp_str,
strlen(tmp_str), strlen(tmp_str) * 2 + 1);
gdb_put_packet(connection, hex_str, pkt_len);
free(hex_str);
free(tmp_str);
+5 -5
View File
@@ -353,7 +353,7 @@ static int mqx_update_threads(
uint32_t task_name_addr = 0, task_id = 0, task_errno = 0;
uint32_t state_index = 0, state_max = 0;
uint32_t extra_info_length = 0;
char *state_name = "unknown state";
char *state_name = "Unknown";
/* set current taskpool address */
if (ERROR_OK != mqx_get_member(
@@ -435,13 +435,13 @@ static int mqx_update_threads(
* calculate length as:
* state length + address length + errno length + formatter length
*/
extra_info_length += strlen((void *)state_name) + 8 + 8 + 8;
extra_info_length += strlen((void *)state_name) + 7 + 13 + 8 + 15 + 8;
rtos->thread_details[i].extra_info_str = malloc(extra_info_length + 1);
if (NULL == rtos->thread_details[i].extra_info_str)
return ERROR_FAIL;
snprintf(
rtos->thread_details[i].extra_info_str, extra_info_length, "%s : 0x%"PRIx32 " : %" PRIu32,
state_name, task_addr, task_errno
snprintf(rtos->thread_details[i].extra_info_str, extra_info_length,
"State: %s, Address: 0x%" PRIx32 ", Error Code: %" PRIu32,
state_name, task_addr, task_errno
);
/* set active thread */
if (active_td_addr == task_addr)
+32 -13
View File
@@ -34,6 +34,7 @@ extern struct rtos_type Linux_os;
extern struct rtos_type ChibiOS_rtos;
extern struct rtos_type embKernel_rtos;
extern struct rtos_type mqx_rtos;
extern struct rtos_type uCOS_III_rtos;
extern struct rtos_type riscv_rtos;
static struct rtos_type *rtos_types[] = {
@@ -44,6 +45,7 @@ static struct rtos_type *rtos_types[] = {
&ChibiOS_rtos,
&embKernel_rtos,
&mqx_rtos,
&uCOS_III_rtos,
&riscv_rtos,
NULL
};
@@ -107,6 +109,7 @@ int rtos_create(Jim_GetOptInfo *goi, struct target *target)
int x;
const char *cp;
struct Jim_Obj *res;
int e;
if (!goi->isconfigure && goi->argc != 0) {
Jim_WrongNumArgs(goi->interp, goi->argc, goi->argv, "NO PARAMS");
@@ -115,7 +118,9 @@ int rtos_create(Jim_GetOptInfo *goi, struct target *target)
os_free(target);
Jim_GetOpt_String(goi, &cp, NULL);
e = Jim_GetOpt_String(goi, &cp, NULL);
if (e != JIM_OK)
return e;
if (0 == strcmp(cp, "auto")) {
/* Auto detect tries to look up all symbols for each RTOS,
@@ -216,7 +221,7 @@ int rtos_qsymbol(struct connection *connection, char const *packet, int packet_s
goto done;
/* Decode any symbol name in the packet*/
int len = unhexify(cur_sym, strchr(packet + 8, ':') + 1, strlen(strchr(packet + 8, ':') + 1));
size_t len = unhexify((uint8_t *)cur_sym, strchr(packet + 8, ':') + 1, strlen(strchr(packet + 8, ':') + 1));
cur_sym[len] = 0;
if ((strcmp(packet, "qSymbol::") != 0) && /* GDB is not offering symbol lookup for the first time */
@@ -264,7 +269,9 @@ int rtos_qsymbol(struct connection *connection, char const *packet, int packet_s
}
reply_len = snprintf(reply, sizeof(reply), "qSymbol:");
reply_len += hexify(reply + reply_len, next_sym->symbol_name, 0, sizeof(reply) - reply_len);
reply_len += hexify(reply + reply_len,
(const uint8_t *)next_sym->symbol_name, strlen(next_sym->symbol_name),
sizeof(reply) - reply_len);
done:
gdb_put_packet(connection, reply, reply_len);
@@ -304,14 +311,14 @@ int rtos_thread_packet(struct connection *connection, char const *packet, int pa
if (detail->extra_info_str != NULL)
str_size += strlen(detail->extra_info_str);
char *tmp_str = calloc(str_size + 4, sizeof(char));
char *tmp_str = calloc(str_size + 9, sizeof(char));
char *tmp_str_ptr = tmp_str;
if (detail->thread_name_str != NULL)
tmp_str_ptr += sprintf(tmp_str_ptr, "%s", detail->thread_name_str);
tmp_str_ptr += sprintf(tmp_str_ptr, "Name: %s", detail->thread_name_str);
if (detail->extra_info_str != NULL) {
if (tmp_str_ptr != tmp_str)
tmp_str_ptr += sprintf(tmp_str_ptr, " : ");
tmp_str_ptr += sprintf(tmp_str_ptr, ", ");
tmp_str_ptr += sprintf(tmp_str_ptr, "%s", detail->extra_info_str);
}
@@ -319,7 +326,8 @@ int rtos_thread_packet(struct connection *connection, char const *packet, int pa
(size_t) (tmp_str_ptr - tmp_str));
char *hex_str = malloc(strlen(tmp_str) * 2 + 1);
int pkt_len = hexify(hex_str, tmp_str, 0, strlen(tmp_str) * 2 + 1);
size_t pkt_len = hexify(hex_str, (const uint8_t *)tmp_str,
strlen(tmp_str), strlen(tmp_str) * 2 + 1);
gdb_put_packet(connection, hex_str, pkt_len);
free(hex_str);
@@ -400,9 +408,14 @@ int rtos_thread_packet(struct connection *connection, char const *packet, int pa
} else if (packet[0] == 'H') { /* Set current thread ( 'c' for step and continue, 'g' for
* all other operations ) */
if ((packet[1] == 'g') && (target->rtos != NULL)) {
sscanf(packet, "Hg%16" SCNx64, &target->rtos->current_threadid);
LOG_DEBUG("RTOS: GDB requested to set current thread to 0x%" PRIx64 "\r\n",
target->rtos->current_threadid);
threadid_t threadid;
sscanf(packet, "Hg%16" SCNx64, &threadid);
LOG_DEBUG("RTOS: GDB requested to set current thread to 0x%" PRIx64, threadid);
/* threadid of 0 indicates target should choose */
if (threadid == 0)
target->rtos->current_threadid = target->rtos->current_thread;
else
target->rtos->current_threadid = threadid;
}
gdb_put_packet(connection, "OK", 2);
return ERROR_OK;
@@ -426,9 +439,13 @@ int rtos_get_gdb_reg_list(struct connection *connection)
current_threadid,
target->rtos->current_thread);
target->rtos->type->get_thread_reg_list(target->rtos,
current_threadid,
&hex_reg_list);
int retval = target->rtos->type->get_thread_reg_list(target->rtos,
current_threadid,
&hex_reg_list);
if (retval != ERROR_OK) {
LOG_ERROR("RTOS: failed to get register list");
return retval;
}
if (hex_reg_list != NULL) {
gdb_put_packet(connection, hex_reg_list, strlen(hex_reg_list));
@@ -546,5 +563,7 @@ void rtos_free_threadlist(struct rtos *rtos)
free(rtos->thread_details);
rtos->thread_details = NULL;
rtos->thread_count = 0;
rtos->current_threadid = -1;
rtos->current_thread = 0;
}
}
+53
View File
@@ -0,0 +1,53 @@
/***************************************************************************
* Copyright (C) 2016 by Square, Inc. *
* Steven Stallion <stallion@squareup.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 "rtos.h"
#include "rtos_standard_stackings.h"
#include "target/armv7m.h"
static const struct stack_register_offset rtos_uCOS_III_Cortex_M_stack_offsets[ARMV7M_NUM_CORE_REGS] = {
{ 0x20, 32 }, /* r0 */
{ 0x24, 32 }, /* r1 */
{ 0x28, 32 }, /* r2 */
{ 0x2c, 32 }, /* r3 */
{ 0x00, 32 }, /* r4 */
{ 0x04, 32 }, /* r5 */
{ 0x08, 32 }, /* r6 */
{ 0x0c, 32 }, /* r7 */
{ 0x10, 32 }, /* r8 */
{ 0x14, 32 }, /* r9 */
{ 0x18, 32 }, /* r10 */
{ 0x1c, 32 }, /* r11 */
{ 0x30, 32 }, /* r12 */
{ -2, 32 }, /* sp */
{ 0x34, 32 }, /* lr */
{ 0x38, 32 }, /* pc */
{ 0x3c, 32 }, /* xPSR */
};
const struct rtos_register_stacking rtos_uCOS_III_Cortex_M_stacking = {
0x40, /* stack_registers_size */
-1, /* stack_growth_direction */
ARMV7M_NUM_CORE_REGS, /* num_output_registers */
rtos_generic_stack_align8, /* stack_alignment */
rtos_uCOS_III_Cortex_M_stack_offsets /* register_offsets */
};
@@ -1,6 +1,6 @@
/***************************************************************************
* Copyright (C) 2006 by Dominic Rath *
* Dominic.Rath@gmx.de *
* Copyright (C) 2016 by Square, Inc. *
* Steven Stallion <stallion@squareup.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 *
@@ -16,53 +16,15 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
***************************************************************************/
#define REG_R0 0
#define REG_R1 1
#define REG_R2 2
#define REG_R3 3
#define REG_R4 4
#define REG_R5 5
#define REG_R6 6
#define REG_R7 7
#define REG_R8 8
#define REG_R9 9
#define REG_R10 10
#define REG_R11 11
#define REG_R12 12
#define REG_R13 13
#define REG_R14 14
#define REG_R15 15
#define REG_CPSR 16
#define REG_SPSR 17
#ifndef OPENOCD_RTOS_RTOS_UCOS_III_STACKINGS_H
#define OPENOCD_RTOS_RTOS_UCOS_III_STACKINGS_H
#define MODE_USR 0x10
#define MODE_FIQ 0x11
#define MODE_IRQ 0x12
#define MODE_SVC 0x13
#define MODE_ABT 0x17
#define MODE_UND 0x1b
#define MODE_SYS 0x1f
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#define MODE_ANY 0x40
#define MODE_CURRENT 0x80
#include "rtos.h"
#define MODE_MASK 0x1f
#define PSR_I 0x80
#define PSR_F 0x40
#define PSR_T 0x20
extern const struct rtos_register_stacking rtos_uCOS_III_Cortex_M_stacking;
#define XSCALE_DBG_MAINID 0x0
#define XSCALE_DBG_CACHETYPE 0x1
#define XSCALE_DBG_CTRL 0x2
#define XSCALE_DBG_AUXCTRL 0x3
#define XSCALE_DBG_TTB 0x4
#define XSCALE_DBG_DAC 0x5
#define XSCALE_DBG_FSR 0x6
#define XSCALE_DBG_FAR 0x7
#define XSCALE_DBG_PID 0x8
#define XSCALE_DBG_CPACCESS 0x9
#define XSCALE_DBG_IBCR0 0xa
#define XSCALE_DBG_IBCR1 0xb
#define XSCALE_DBG_DBR0 0xc
#define XSCALE_DBG_DBR1 0xd
#define XSCALE_DBG_DBCON 0xe
#endif /* OPENOCD_RTOS_RTOS_UCOS_III_STACKINGS_H */
+509
View File
@@ -0,0 +1,509 @@
/***************************************************************************
* Copyright (C) 2016 by Square, Inc. *
* Steven Stallion <stallion@squareup.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 <helper/time_support.h>
#include <jtag/jtag.h>
#include "target/target.h"
#include "target/target_type.h"
#include "rtos.h"
#include "helper/log.h"
#include "helper/types.h"
#include "rtos/rtos_ucos_iii_stackings.h"
#ifndef UCOS_III_MAX_STRLEN
#define UCOS_III_MAX_STRLEN 64
#endif
#ifndef UCOS_III_MAX_THREADS
#define UCOS_III_MAX_THREADS 256
#endif
struct uCOS_III_params {
const char *target_name;
const unsigned char pointer_width;
symbol_address_t thread_stack_offset;
symbol_address_t thread_name_offset;
symbol_address_t thread_state_offset;
symbol_address_t thread_priority_offset;
symbol_address_t thread_prev_offset;
symbol_address_t thread_next_offset;
bool thread_offsets_updated;
size_t threadid_start;
const struct rtos_register_stacking *stacking_info;
size_t num_threads;
symbol_address_t threads[];
};
static const struct uCOS_III_params uCOS_III_params_list[] = {
{
"cortex_m", /* target_name */
sizeof(uint32_t), /* pointer_width */
0, /* thread_stack_offset */
0, /* thread_name_offset */
0, /* thread_state_offset */
0, /* thread_priority_offset */
0, /* thread_prev_offset */
0, /* thread_next_offset */
false, /* thread_offsets_updated */
1, /* threadid_start */
&rtos_uCOS_III_Cortex_M_stacking, /* stacking_info */
0, /* num_threads */
},
};
static const char * const uCOS_III_symbol_list[] = {
"OSRunning",
"OSTCBCurPtr",
"OSTaskDbgListPtr",
"OSTaskQty",
/* also see: contrib/rtos-helpers/uCOS-III-openocd.c */
"openocd_OS_TCB_StkPtr_offset",
"openocd_OS_TCB_NamePtr_offset",
"openocd_OS_TCB_TaskState_offset",
"openocd_OS_TCB_Prio_offset",
"openocd_OS_TCB_DbgPrevPtr_offset",
"openocd_OS_TCB_DbgNextPtr_offset",
NULL
};
enum uCOS_III_symbol_values {
uCOS_III_VAL_OSRunning,
uCOS_III_VAL_OSTCBCurPtr,
uCOS_III_VAL_OSTaskDbgListPtr,
uCOS_III_VAL_OSTaskQty,
/* also see: contrib/rtos-helpers/uCOS-III-openocd.c */
uCOS_III_VAL_OS_TCB_StkPtr_offset,
uCOS_III_VAL_OS_TCB_NamePtr_offset,
uCOS_III_VAL_OS_TCB_TaskState_offset,
uCOS_III_VAL_OS_TCB_Prio_offset,
uCOS_III_VAL_OS_TCB_DbgPrevPtr_offset,
uCOS_III_VAL_OS_TCB_DbgNextPtr_offset,
};
static const char * const uCOS_III_thread_state_list[] = {
"Ready",
"Delay",
"Pend",
"Pend Timeout",
"Suspended",
"Delay Suspended",
"Pend Suspended",
"Pend Timeout Suspended",
};
static int uCOS_III_find_or_create_thread(struct rtos *rtos, symbol_address_t thread_address,
threadid_t *threadid)
{
struct uCOS_III_params *params = rtos->rtos_specific_params;
size_t thread_index;
for (thread_index = 0; thread_index < params->num_threads; thread_index++)
if (params->threads[thread_index] == thread_address)
goto found;
if (params->num_threads == UCOS_III_MAX_THREADS) {
LOG_WARNING("uCOS-III: too many threads; increase UCOS_III_MAX_THREADS");
return ERROR_FAIL;
}
params->threads[thread_index] = thread_address;
params->num_threads++;
found:
*threadid = thread_index + params->threadid_start;
return ERROR_OK;
}
static int uCOS_III_find_thread_address(struct rtos *rtos, threadid_t threadid,
symbol_address_t *thread_address)
{
struct uCOS_III_params *params = rtos->rtos_specific_params;
size_t thread_index;
thread_index = threadid - params->threadid_start;
if (thread_index >= params->num_threads) {
LOG_ERROR("uCOS-III: failed to find thread address");
return ERROR_FAIL;
}
*thread_address = params->threads[thread_index];
return ERROR_OK;
}
static int uCOS_III_find_last_thread_address(struct rtos *rtos, symbol_address_t *thread_address)
{
struct uCOS_III_params *params = rtos->rtos_specific_params;
int retval;
/* read the thread list head */
symbol_address_t thread_list_address = 0;
retval = target_read_memory(rtos->target,
rtos->symbols[uCOS_III_VAL_OSTaskDbgListPtr].address,
params->pointer_width,
1,
(void *)&thread_list_address);
if (retval != ERROR_OK) {
LOG_ERROR("uCOS-III: failed to read thread list address");
return retval;
}
/* advance to end of thread list */
do {
*thread_address = thread_list_address;
retval = target_read_memory(rtos->target,
thread_list_address + params->thread_next_offset,
params->pointer_width,
1,
(void *)&thread_list_address);
if (retval != ERROR_OK) {
LOG_ERROR("uCOS-III: failed to read next thread address");
return retval;
}
} while (thread_list_address != 0);
return ERROR_OK;
}
static int uCOS_III_update_thread_offsets(struct rtos *rtos)
{
struct uCOS_III_params *params = rtos->rtos_specific_params;
if (params->thread_offsets_updated)
return ERROR_OK;
const struct thread_offset_map {
enum uCOS_III_symbol_values symbol_value;
symbol_address_t *thread_offset;
} thread_offset_maps[] = {
{
uCOS_III_VAL_OS_TCB_StkPtr_offset,
&params->thread_stack_offset,
},
{
uCOS_III_VAL_OS_TCB_NamePtr_offset,
&params->thread_name_offset,
},
{
uCOS_III_VAL_OS_TCB_TaskState_offset,
&params->thread_state_offset,
},
{
uCOS_III_VAL_OS_TCB_Prio_offset,
&params->thread_priority_offset,
},
{
uCOS_III_VAL_OS_TCB_DbgPrevPtr_offset,
&params->thread_prev_offset,
},
{
uCOS_III_VAL_OS_TCB_DbgNextPtr_offset,
&params->thread_next_offset,
},
};
for (size_t i = 0; i < ARRAY_SIZE(thread_offset_maps); i++) {
const struct thread_offset_map *thread_offset_map = &thread_offset_maps[i];
int retval = target_read_memory(rtos->target,
rtos->symbols[thread_offset_map->symbol_value].address,
params->pointer_width,
1,
(void *)thread_offset_map->thread_offset);
if (retval != ERROR_OK) {
LOG_ERROR("uCOS-III: failed to read thread offset");
return retval;
}
}
params->thread_offsets_updated = true;
return ERROR_OK;
}
static int uCOS_III_detect_rtos(struct target *target)
{
return target->rtos->symbols != NULL &&
target->rtos->symbols[uCOS_III_VAL_OSRunning].address != 0;
}
static int uCOS_III_reset_handler(struct target *target, enum target_reset_mode reset_mode, void *priv)
{
struct uCOS_III_params *params = target->rtos->rtos_specific_params;
params->thread_offsets_updated = false;
params->num_threads = 0;
return ERROR_OK;
}
static int uCOS_III_create(struct target *target)
{
struct uCOS_III_params *params;
for (size_t i = 0; i < ARRAY_SIZE(uCOS_III_params_list); i++)
if (strcmp(uCOS_III_params_list[i].target_name, target->type->name) == 0) {
params = malloc(sizeof(*params) +
UCOS_III_MAX_THREADS * sizeof(*params->threads));
if (params == NULL) {
LOG_ERROR("uCOS-III: out of memory");
return ERROR_FAIL;
}
memcpy(params, &uCOS_III_params_list[i], sizeof(uCOS_III_params_list[i]));
target->rtos->rtos_specific_params = (void *)params;
target_register_reset_callback(uCOS_III_reset_handler, NULL);
return ERROR_OK;
}
LOG_ERROR("uCOS-III: target not supported: %s", target->type->name);
return ERROR_FAIL;
}
static int uCOS_III_update_threads(struct rtos *rtos)
{
struct uCOS_III_params *params = rtos->rtos_specific_params;
int retval;
/* free previous thread details */
rtos_free_threadlist(rtos);
/* verify RTOS is running */
uint8_t rtos_running;
retval = target_read_u8(rtos->target,
rtos->symbols[uCOS_III_VAL_OSRunning].address,
&rtos_running);
if (retval != ERROR_OK) {
LOG_ERROR("uCOS-III: failed to read RTOS running");
return retval;
}
if (!rtos_running) {
rtos->thread_details = calloc(1, sizeof(struct thread_detail));
if (rtos->thread_details == NULL) {
LOG_ERROR("uCOS-III: out of memory");
return ERROR_FAIL;
}
rtos->thread_count = 1;
rtos->thread_details->threadid = 0;
rtos->thread_details->exists = true;
rtos->current_thread = 0;
return ERROR_OK;
}
/* update thread offsets */
retval = uCOS_III_update_thread_offsets(rtos);
if (retval != ERROR_OK) {
LOG_ERROR("uCOS-III: failed to update thread offsets");
return retval;
}
/* read current thread address */
symbol_address_t current_thread_address = 0;
retval = target_read_memory(rtos->target,
rtos->symbols[uCOS_III_VAL_OSTCBCurPtr].address,
params->pointer_width,
1,
(void *)&current_thread_address);
if (retval != ERROR_OK) {
LOG_ERROR("uCOS-III: failed to read current thread address");
return retval;
}
/* read number of tasks */
retval = target_read_u16(rtos->target,
rtos->symbols[uCOS_III_VAL_OSTaskQty].address,
(void *)&rtos->thread_count);
if (retval != ERROR_OK) {
LOG_ERROR("uCOS-III: failed to read thread count");
return retval;
}
rtos->thread_details = calloc(rtos->thread_count, sizeof(struct thread_detail));
if (rtos->thread_details == NULL) {
LOG_ERROR("uCOS-III: out of memory");
return ERROR_FAIL;
}
/*
* uC/OS-III adds tasks in LIFO order; advance to the end of the
* list and work backwards to preserve the intended order.
*/
symbol_address_t thread_address = 0;
retval = uCOS_III_find_last_thread_address(rtos, &thread_address);
if (retval != ERROR_OK) {
LOG_ERROR("uCOS-III: failed to find last thread address");
return retval;
}
for (int i = 0; i < rtos->thread_count; i++) {
struct thread_detail *thread_detail = &rtos->thread_details[i];
char thread_str_buffer[UCOS_III_MAX_STRLEN + 1];
/* find or create new threadid */
retval = uCOS_III_find_or_create_thread(rtos,
thread_address,
&thread_detail->threadid);
if (retval != ERROR_OK) {
LOG_ERROR("uCOS-III: failed to find or create thread");
return retval;
}
if (thread_address == current_thread_address)
rtos->current_thread = thread_detail->threadid;
thread_detail->exists = true;
/* read thread name */
symbol_address_t thread_name_address = 0;
retval = target_read_memory(rtos->target,
thread_address + params->thread_name_offset,
params->pointer_width,
1,
(void *)&thread_name_address);
if (retval != ERROR_OK) {
LOG_ERROR("uCOS-III: failed to name address");
return retval;
}
retval = target_read_buffer(rtos->target,
thread_name_address,
sizeof(thread_str_buffer),
(void *)thread_str_buffer);
if (retval != ERROR_OK) {
LOG_ERROR("uCOS-III: failed to read thread name");
return retval;
}
thread_str_buffer[sizeof(thread_str_buffer) - 1] = '\0';
thread_detail->thread_name_str = strdup(thread_str_buffer);
/* read thread extra info */
uint8_t thread_state;
uint8_t thread_priority;
retval = target_read_u8(rtos->target,
thread_address + params->thread_state_offset,
&thread_state);
if (retval != ERROR_OK) {
LOG_ERROR("uCOS-III: failed to read thread state");
return retval;
}
retval = target_read_u8(rtos->target,
thread_address + params->thread_priority_offset,
&thread_priority);
if (retval != ERROR_OK) {
LOG_ERROR("uCOS-III: failed to read thread priority");
return retval;
}
const char *thread_state_str;
if (thread_state < ARRAY_SIZE(uCOS_III_thread_state_list))
thread_state_str = uCOS_III_thread_state_list[thread_state];
else
thread_state_str = "Unknown";
snprintf(thread_str_buffer, sizeof(thread_str_buffer), "State: %s, Priority: %d",
thread_state_str, thread_priority);
thread_detail->extra_info_str = strdup(thread_str_buffer);
/* read previous thread address */
retval = target_read_memory(rtos->target,
thread_address + params->thread_prev_offset,
params->pointer_width,
1,
(void *)&thread_address);
if (retval != ERROR_OK) {
LOG_ERROR("uCOS-III: failed to read previous thread address");
return retval;
}
}
return ERROR_OK;
}
static int uCOS_III_get_thread_reg_list(struct rtos *rtos, threadid_t threadid, char **hex_reg_list)
{
struct uCOS_III_params *params = rtos->rtos_specific_params;
int retval;
/* find thread address for threadid */
symbol_address_t thread_address = 0;
retval = uCOS_III_find_thread_address(rtos, threadid, &thread_address);
if (retval != ERROR_OK) {
LOG_ERROR("uCOS-III: failed to find thread address");
return retval;
}
/* read thread stack address */
symbol_address_t stack_address = 0;
retval = target_read_memory(rtos->target,
thread_address + params->thread_stack_offset,
params->pointer_width,
1,
(void *)&stack_address);
if (retval != ERROR_OK) {
LOG_ERROR("uCOS-III: failed to read stack address");
return retval;
}
return rtos_generic_stack_read(rtos->target,
params->stacking_info,
stack_address,
hex_reg_list);
}
static int uCOS_III_get_symbol_list_to_lookup(symbol_table_elem_t *symbol_list[])
{
*symbol_list = calloc(ARRAY_SIZE(uCOS_III_symbol_list), sizeof(symbol_table_elem_t));
if (*symbol_list == NULL) {
LOG_ERROR("uCOS-III: out of memory");
return ERROR_FAIL;
}
for (size_t i = 0; i < ARRAY_SIZE(uCOS_III_symbol_list); i++)
(*symbol_list)[i].symbol_name = uCOS_III_symbol_list[i];
return ERROR_OK;
}
const struct rtos_type uCOS_III_rtos = {
.name = "uCOS-III",
.detect_rtos = uCOS_III_detect_rtos,
.create = uCOS_III_create,
.update_threads = uCOS_III_update_threads,
.get_thread_reg_list = uCOS_III_get_thread_reg_list,
.get_symbol_list_to_lookup = uCOS_III_get_symbol_list_to_lookup,
};
+14 -18
View File
@@ -1,23 +1,19 @@
include $(top_srcdir)/common.mk
noinst_LTLIBRARIES += %D%/libserver.la
%C%_libserver_la_SOURCES = \
%D%/server.c \
%D%/telnet_server.c \
%D%/gdb_server.c \
%D%/server.h \
%D%/telnet_server.h \
%D%/gdb_server.h \
%D%/server_stubs.c \
%D%/tcl_server.c \
%D%/tcl_server.h
METASOURCES = AUTO
noinst_LTLIBRARIES = libserver.la
noinst_HEADERS = server.h telnet_server.h gdb_server.h
libserver_la_SOURCES = server.c telnet_server.c gdb_server.c
libserver_la_SOURCES += server_stubs.c
libserver_la_CFLAGS =
%C%_libserver_la_CFLAGS = $(AM_CFLAGS)
if IS_MINGW
# FD_* macros are sloppy with their signs on MinGW32 platform
libserver_la_CFLAGS += -Wno-sign-compare
%C%_libserver_la_CFLAGS += -Wno-sign-compare
endif
# tcl server addons
noinst_HEADERS += tcl_server.h
libserver_la_SOURCES += tcl_server.c
EXTRA_DIST = \
startup.tcl
MAINTAINERCLEANFILES = $(srcdir)/Makefile.in
STARTUP_TCL_SRCS += %D%/startup.tcl
+179 -33
View File
@@ -90,6 +90,8 @@ struct gdb_connection {
bool attached;
/* temporarily used for target description support */
struct target_desc_format target_desc;
/* temporarily used for thread list support */
char *thread_list;
};
#if 0
@@ -695,7 +697,8 @@ static int gdb_output_con(struct connection *connection, const char *line)
return ERROR_GDB_BUFFER_TOO_SMALL;
hex_buffer[0] = 'O';
int pkt_len = hexify(hex_buffer + 1, line, bin_size, bin_size * 2 + 1);
size_t pkt_len = hexify(hex_buffer + 1, (const uint8_t *)line, bin_size,
bin_size * 2 + 1);
int retval = gdb_put_packet(connection, hex_buffer, pkt_len + 1);
free(hex_buffer);
@@ -732,22 +735,22 @@ static void gdb_signal_reply(struct target *target, struct connection *connectio
stop_reason[0] = '\0';
if (target->debug_reason == DBG_REASON_WATCHPOINT) {
enum watchpoint_rw hit_wp_type;
uint32_t hit_wp_address;
target_addr_t hit_wp_address;
if (watchpoint_hit(target, &hit_wp_type, &hit_wp_address) == ERROR_OK) {
switch (hit_wp_type) {
case WPT_WRITE:
snprintf(stop_reason, sizeof(stop_reason),
"watch:%08" PRIx32 ";", hit_wp_address);
"watch:%08" TARGET_PRIxADDR ";", hit_wp_address);
break;
case WPT_READ:
snprintf(stop_reason, sizeof(stop_reason),
"rwatch:%08" PRIx32 ";", hit_wp_address);
"rwatch:%08" TARGET_PRIxADDR ";", hit_wp_address);
break;
case WPT_ACCESS:
snprintf(stop_reason, sizeof(stop_reason),
"awatch:%08" PRIx32 ";", hit_wp_address);
"awatch:%08" TARGET_PRIxADDR ";", hit_wp_address);
break;
default:
break;
@@ -934,6 +937,7 @@ static int gdb_new_connection(struct connection *connection)
gdb_connection->attached = true;
gdb_connection->target_desc.tdesc = NULL;
gdb_connection->target_desc.tdesc_length = 0;
gdb_connection->thread_list = NULL;
/* send ACK to GDB for debug request */
gdb_write(connection, "+", 1);
@@ -1376,7 +1380,7 @@ static int gdb_read_memory_packet(struct connection *connection,
{
struct target *target = get_target_from_connection(connection);
char *separator;
uint32_t addr = 0;
uint64_t addr = 0;
uint32_t len = 0;
uint8_t *buffer;
@@ -1387,7 +1391,7 @@ static int gdb_read_memory_packet(struct connection *connection,
/* skip command character */
packet++;
addr = strtoul(packet, &separator, 16);
addr = strtoull(packet, &separator, 16);
if (*separator != ',') {
LOG_ERROR("incomplete read memory packet received, dropping connection");
@@ -1404,7 +1408,7 @@ static int gdb_read_memory_packet(struct connection *connection,
buffer = malloc(len);
LOG_DEBUG("addr: 0x%8.8" PRIx32 ", len: 0x%8.8" PRIx32 "", addr, len);
LOG_DEBUG("addr: 0x%16.16" PRIx64 ", len: 0x%8.8" PRIx32 "", addr, len);
retval = target_read_buffer(target, addr, len, buffer);
@@ -1429,7 +1433,7 @@ static int gdb_read_memory_packet(struct connection *connection,
if (retval == ERROR_OK) {
hex_buffer = malloc(len * 2 + 1);
int pkt_len = hexify(hex_buffer, (char *)buffer, len, len * 2 + 1);
size_t pkt_len = hexify(hex_buffer, buffer, len, len * 2 + 1);
gdb_put_packet(connection, hex_buffer, pkt_len);
@@ -1447,7 +1451,7 @@ static int gdb_write_memory_packet(struct connection *connection,
{
struct target *target = get_target_from_connection(connection);
char *separator;
uint32_t addr = 0;
uint64_t addr = 0;
uint32_t len = 0;
uint8_t *buffer;
@@ -1456,7 +1460,7 @@ static int gdb_write_memory_packet(struct connection *connection,
/* skip command character */
packet++;
addr = strtoul(packet, &separator, 16);
addr = strtoull(packet, &separator, 16);
if (*separator != ',') {
LOG_ERROR("incomplete write memory packet received, dropping connection");
@@ -1472,9 +1476,9 @@ static int gdb_write_memory_packet(struct connection *connection,
buffer = malloc(len);
LOG_DEBUG("addr: 0x%8.8" PRIx32 ", len: 0x%8.8" PRIx32 "", addr, len);
LOG_DEBUG("addr: 0x%" PRIx64 ", len: 0x%8.8" PRIx32 "", addr, len);
if (unhexify((char *)buffer, separator, len) != (int)len)
if (unhexify(buffer, separator, len) != len)
LOG_ERROR("unable to decode memory packet");
retval = target_write_buffer(target, addr, len, buffer);
@@ -1494,15 +1498,19 @@ static int gdb_write_memory_binary_packet(struct connection *connection,
{
struct target *target = get_target_from_connection(connection);
char *separator;
uint32_t addr = 0;
uint64_t addr = 0;
uint32_t len = 0;
int retval = ERROR_OK;
/* Packets larger than fast_limit bytes will be acknowledged instantly on
* the assumption that we're in a download and it's important to go as fast
* as possible. */
uint32_t fast_limit = 8;
/* skip command character */
packet++;
addr = strtoul(packet, &separator, 16);
addr = strtoull(packet, &separator, 16);
if (*separator != ',') {
LOG_ERROR("incomplete write memory binary packet received, dropping connection");
@@ -1518,31 +1526,44 @@ static int gdb_write_memory_binary_packet(struct connection *connection,
struct gdb_connection *gdb_connection = connection->priv;
if (gdb_connection->mem_write_error) {
if (gdb_connection->mem_write_error)
retval = ERROR_FAIL;
if (retval == ERROR_OK) {
if (len >= fast_limit) {
/* By replying the packet *immediately* GDB will send us a new packet
* while we write the last one to the target.
* We only do this for larger writes, so that users who do something like:
* p *((int*)0xdeadbeef)=8675309
* will get immediate feedback that that write failed.
*/
gdb_put_packet(connection, "OK", 2);
}
} else {
retval = gdb_error(connection, retval);
/* now that we have reported the memory write error, we can clear the condition */
gdb_connection->mem_write_error = false;
}
/* By replying the packet *immediately* GDB will send us a new packet
* while we write the last one to the target.
*/
if (retval == ERROR_OK)
gdb_put_packet(connection, "OK", 2);
else {
retval = gdb_error(connection, retval);
if (retval != ERROR_OK)
return retval;
}
if (len) {
LOG_DEBUG("addr: 0x%8.8" PRIx32 ", len: 0x%8.8" PRIx32 "", addr, len);
LOG_DEBUG("addr: 0x%" PRIx64 ", len: 0x%8.8" PRIx32 "", addr, len);
retval = target_write_buffer(target, addr, len, (uint8_t *)separator);
if (retval != ERROR_OK)
gdb_connection->mem_write_error = true;
}
if (len < fast_limit) {
if (retval != ERROR_OK) {
gdb_error(connection, retval);
gdb_connection->mem_write_error = false;
} else {
gdb_put_packet(connection, "OK", 2);
}
}
return ERROR_OK;
}
@@ -1551,13 +1572,13 @@ static int gdb_step_continue_packet(struct connection *connection,
{
struct target *target = get_target_from_connection(connection);
int current = 0;
uint32_t address = 0x0;
uint64_t address = 0x0;
int retval = ERROR_OK;
LOG_DEBUG("-");
if (packet_size > 1)
address = strtoul(packet + 1, NULL, 16);
address = strtoull(packet + 1, NULL, 16);
else
current = 1;
@@ -1581,7 +1602,7 @@ static int gdb_breakpoint_watchpoint_packet(struct connection *connection,
int type;
enum breakpoint_type bp_type = BKPT_SOFT /* dummy init to avoid warning */;
enum watchpoint_rw wp_type = WPT_READ /* dummy init to avoid warning */;
uint32_t address;
uint64_t address;
uint32_t size;
char *separator;
int retval;
@@ -1613,7 +1634,7 @@ static int gdb_breakpoint_watchpoint_packet(struct connection *connection,
return ERROR_SERVER_REMOTE_CLOSED;
}
address = strtoul(separator + 1, &separator, 16);
address = strtoull(separator + 1, &separator, 16);
if (*separator != ',') {
LOG_ERROR("incomplete breakpoint/watchpoint packet received, dropping connection");
@@ -2291,6 +2312,95 @@ error:
return retval;
}
static int gdb_generate_thread_list(struct target *target, char **thread_list_out)
{
struct rtos *rtos = target->rtos;
int retval = ERROR_OK;
char *thread_list = NULL;
int pos = 0;
int size = 0;
xml_printf(&retval, &thread_list, &pos, &size,
"<?xml version=\"1.0\"?>\n"
"<threads>\n");
if (rtos != NULL) {
for (int i = 0; i < rtos->thread_count; i++) {
struct thread_detail *thread_detail = &rtos->thread_details[i];
if (!thread_detail->exists)
continue;
xml_printf(&retval, &thread_list, &pos, &size,
"<thread id=\"%" PRIx64 "\">", thread_detail->threadid);
if (thread_detail->thread_name_str != NULL)
xml_printf(&retval, &thread_list, &pos, &size,
"Name: %s", thread_detail->thread_name_str);
if (thread_detail->extra_info_str != NULL) {
if (thread_detail->thread_name_str != NULL)
xml_printf(&retval, &thread_list, &pos, &size,
", ");
xml_printf(&retval, &thread_list, &pos, &size,
thread_detail->extra_info_str);
}
xml_printf(&retval, &thread_list, &pos, &size,
"</thread>\n");
}
}
xml_printf(&retval, &thread_list, &pos, &size,
"</threads>\n");
if (retval == ERROR_OK)
*thread_list_out = thread_list;
else
free(thread_list);
return retval;
}
static int gdb_get_thread_list_chunk(struct target *target, char **thread_list,
char **chunk, int32_t offset, uint32_t length)
{
if (*thread_list == NULL) {
int retval = gdb_generate_thread_list(target, thread_list);
if (retval != ERROR_OK) {
LOG_ERROR("Unable to Generate Thread List");
return ERROR_FAIL;
}
}
size_t thread_list_length = strlen(*thread_list);
char transfer_type;
length = MIN(length, thread_list_length - offset);
if (length < (thread_list_length - offset))
transfer_type = 'm';
else
transfer_type = 'l';
*chunk = malloc(length + 2);
if (*chunk == NULL) {
LOG_ERROR("Unable to allocate memory");
return ERROR_FAIL;
}
(*chunk)[0] = transfer_type;
strncpy((*chunk) + 1, (*thread_list) + offset, length);
(*chunk)[1 + length] = '\0';
/* After gdb-server sends out last chunk, invalidate thread list. */
if (transfer_type == 'l') {
free(*thread_list);
*thread_list = NULL;
}
return ERROR_OK;
}
static int gdb_query_packet(struct connection *connection,
char const *packet, int packet_size)
{
@@ -2302,7 +2412,7 @@ static int gdb_query_packet(struct connection *connection,
if (packet_size > 6) {
char *cmd;
cmd = malloc((packet_size - 6) / 2 + 1);
int len = unhexify(cmd, packet + 6, (packet_size - 6) / 2);
size_t len = unhexify((uint8_t *)cmd, packet + 6, (packet_size - 6) / 2);
cmd[len] = 0;
/* We want to print all debug output to GDB connection */
@@ -2380,7 +2490,7 @@ static int gdb_query_packet(struct connection *connection,
&buffer,
&pos,
&size,
"PacketSize=%x;qXfer:memory-map:read%c;qXfer:features:read%c;QStartNoAckMode+",
"PacketSize=%x;qXfer:memory-map:read%c;qXfer:features:read%c;qXfer:threads:read+;QStartNoAckMode+",
(GDB_BUFFER_SIZE - 1),
((gdb_use_memory_map == 1) && (flash_get_bank_count() > 0)) ? '+' : '-',
(gdb_target_desc_supported == 1) ? '+' : '-');
@@ -2426,6 +2536,37 @@ static int gdb_query_packet(struct connection *connection,
gdb_put_packet(connection, xml, strlen(xml));
free(xml);
return ERROR_OK;
} else if (strncmp(packet, "qXfer:threads:read:", 19) == 0) {
char *xml = NULL;
int retval = ERROR_OK;
int offset;
unsigned int length;
/* skip command character */
packet += 19;
if (decode_xfer_read(packet, NULL, &offset, &length) < 0) {
gdb_send_error(connection, 01);
return ERROR_OK;
}
/* Target should prepare correct thread list for annex.
* The first character of returned xml is 'm' or 'l'. 'm' for
* there are *more* chunks to transfer. 'l' for it is the *last*
* chunk of target description.
*/
retval = gdb_get_thread_list_chunk(target, &gdb_connection->thread_list,
&xml, offset, length);
if (retval != ERROR_OK) {
gdb_error(connection, retval);
return retval;
}
gdb_put_packet(connection, xml, strlen(xml));
free(xml);
return ERROR_OK;
} else if (strncmp(packet, "QStartNoAckMode", 15) == 0) {
@@ -2953,6 +3094,11 @@ static int gdb_target_start(struct target *target, const char *port)
static int gdb_target_add_one(struct target *target)
{
if (strcmp(gdb_port, "disabled") == 0) {
LOG_INFO("gdb port disabled");
return ERROR_OK;
}
/* one gdb instance per smp list */
if ((target->smp) && (target->gdb_service))
return ERROR_OK;
@@ -3146,7 +3292,7 @@ static const struct command_registration gdb_command_handlers[] = {
"server listens for the next port number after the "
"base port number specified. "
"No arguments reports GDB port. \"pipe\" means listen to stdin "
"output to stdout, an integer is base port number, \"disable\" disables "
"output to stdout, an integer is base port number, \"disabled\" disables "
"port. Any other string is are interpreted as named pipe to listen to. "
"Output pipe is the same name as input pipe, but with 'o' appended.",
.usage = "[port_num]",
+38 -13
View File
@@ -132,7 +132,9 @@ static int add_connection(struct service *service, struct command_context *cmd_c
free(out_file);
if (c->fd_out == -1) {
LOG_ERROR("could not open %s", service->port);
exit(1);
command_done(c->cmd_ctx);
free(c);
return ERROR_FAIL;
}
LOG_INFO("accepting '%s' connection from pipe %s", service->name, service->port);
@@ -191,7 +193,13 @@ static int remove_connection(struct service *service, struct connection *connect
return ERROR_OK;
}
/* FIX! make service return error instead of invoking exit() */
static void free_service(struct service *c)
{
free(c->name);
free(c->port);
free(c);
}
int add_service(char *name,
const char *port,
int max_connections,
@@ -235,7 +243,8 @@ int add_service(char *name,
c->fd = socket(AF_INET, SOCK_STREAM, 0);
if (c->fd == -1) {
LOG_ERROR("error creating socket: %s", strerror(errno));
exit(-1);
free_service(c);
return ERROR_FAIL;
}
setsockopt(c->fd,
@@ -255,7 +264,9 @@ int add_service(char *name,
hp = gethostbyname(bindto_name);
if (hp == NULL) {
LOG_ERROR("couldn't resolve bindto address: %s", bindto_name);
exit(-1);
close_socket(c->fd);
free_service(c);
return ERROR_FAIL;
}
memcpy(&c->sin.sin_addr, hp->h_addr_list[0], hp->h_length);
}
@@ -263,7 +274,9 @@ int add_service(char *name,
if (bind(c->fd, (struct sockaddr *)&c->sin, sizeof(c->sin)) == -1) {
LOG_ERROR("couldn't bind %s to socket: %s", name, strerror(errno));
exit(-1);
close_socket(c->fd);
free_service(c);
return ERROR_FAIL;
}
#ifndef _WIN32
@@ -281,7 +294,9 @@ int add_service(char *name,
if (listen(c->fd, 1) == -1) {
LOG_ERROR("couldn't listen on socket: %s", strerror(errno));
exit(-1);
close_socket(c->fd);
free_service(c);
return ERROR_FAIL;
}
} else if (c->type == CONNECTION_STDINOUT) {
c->fd = fileno(stdin);
@@ -302,13 +317,15 @@ int add_service(char *name,
/* we currenty do not support named pipes under win32
* so exit openocd for now */
LOG_ERROR("Named pipes currently not supported under this os");
exit(1);
free_service(c);
return ERROR_FAIL;
#else
/* Pipe we're reading from */
c->fd = open(c->port, O_RDONLY | O_NONBLOCK);
if (c->fd == -1) {
LOG_ERROR("could not open %s", c->port);
exit(1);
free_service(c);
return ERROR_FAIL;
}
#endif
}
@@ -425,7 +442,7 @@ int server_loop(struct command_context *command_context)
FD_ZERO(&read_fds);
else {
LOG_ERROR("error during select: %s", strerror(errno));
exit(-1);
return ERROR_FAIL;
}
#else
@@ -433,7 +450,7 @@ int server_loop(struct command_context *command_context)
FD_ZERO(&read_fds);
else {
LOG_ERROR("error during select: %s", strerror(errno));
exit(-1);
return ERROR_FAIL;
}
#endif
}
@@ -552,7 +569,7 @@ int server_preinit(void)
if (WSAStartup(wVersionRequested, &wsaData) != 0) {
LOG_ERROR("Failed to Open Winsock");
exit(-1);
return ERROR_FAIL;
}
/* register ctrl-c handler */
@@ -570,10 +587,18 @@ int server_preinit(void)
int server_init(struct command_context *cmd_ctx)
{
int ret = tcl_init();
if (ERROR_OK != ret)
if (ret != ERROR_OK)
return ret;
return telnet_init("Open On-Chip Debugger");
ret = telnet_init("Open On-Chip Debugger");
if (ret != ERROR_OK) {
remove_services();
return ret;
}
return ERROR_OK;
}
int server_quit(void)
+1 -1
View File
@@ -105,7 +105,7 @@ static int tcl_target_callback_trace_handler(struct target *target,
if (tclc->tc_trace) {
hex = malloc(hex_len);
buf = malloc(max_len);
hexify(hex, (const char *)data, len, hex_len);
hexify(hex, data, len, hex_len);
snprintf(buf, max_len, "%s%s%s", header, hex, trailer);
tcl_output(connection, buf, strlen(buf));
free(hex);
+12 -10
View File
@@ -573,7 +573,7 @@ static int telnet_input(struct connection *connection)
break;
default:
LOG_ERROR("unknown telnet state");
exit(-1);
return ERROR_FAIL;
}
bytes_read--;
@@ -624,9 +624,8 @@ int telnet_init(char *banner)
return ERROR_OK;
}
struct telnet_service *telnet_service;
telnet_service = malloc(sizeof(struct telnet_service));
struct telnet_service *telnet_service =
malloc(sizeof(struct telnet_service));
if (!telnet_service) {
LOG_ERROR("Failed to allocate telnet service.");
@@ -635,13 +634,16 @@ int telnet_init(char *banner)
telnet_service->banner = banner;
return add_service("telnet",
telnet_port,
CONNECTION_LIMIT_UNLIMITED,
telnet_new_connection,
telnet_input,
telnet_connection_closed,
int ret = add_service("telnet", telnet_port, CONNECTION_LIMIT_UNLIMITED,
telnet_new_connection, telnet_input, telnet_connection_closed,
telnet_service);
if (ret != ERROR_OK) {
free(telnet_service);
return ret;
}
return ERROR_OK;
}
/* daemon configuration command telnet_port */
+2 -8
View File
@@ -1,8 +1,2 @@
include $(top_srcdir)/common.mk
METASOURCES = AUTO
noinst_LTLIBRARIES = libsvf.la
noinst_HEADERS = svf.h
libsvf_la_SOURCES = svf.c
MAINTAINERCLEANFILES = $(srcdir)/Makefile.in
noinst_LTLIBRARIES += %D%/libsvf.la
%C%_libsvf_la_SOURCES = %D%/svf.c %D%/svf.h
+174 -175
View File
@@ -1,31 +1,15 @@
include $(top_srcdir)/common.mk
if OOCD_TRACE
OOCD_TRACE_FILES = oocd_trace.c
OOCD_TRACE_FILES = %D%/oocd_trace.c
else
OOCD_TRACE_FILES =
endif
SUBDIRS = openrisc
libtarget_la_LIBADD = $(top_builddir)/src/target/openrisc/libopenrisc.la
%C%_libtarget_la_LIBADD = %D%/openrisc/libopenrisc.la
BIN2C = $(top_srcdir)/src/helper/bin2char.sh
STARTUP_TCL_SRCS += %D%/startup.tcl
DEBUG_HANDLER = $(srcdir)/xscale/debug_handler.bin
EXTRA_DIST = \
startup.tcl \
$(wildcard $(srcdir)/xscale/*)
DEBUG_HEADER = xscale_debug.inc
BUILT_SOURCES = $(DEBUG_HEADER)
CLEANFILES = $(DEBUG_HEADER)
$(DEBUG_HEADER): $(DEBUG_HANDLER) $(BIN2C)
$(BIN2C) < $< > $@ || { rm -f $@; false; }
METASOURCES = AUTO
noinst_LTLIBRARIES = libtarget.la
libtarget_la_SOURCES = \
noinst_LTLIBRARIES += %D%/libtarget.la
%C%_libtarget_la_SOURCES = \
$(TARGET_CORE_SRC) \
$(ARM_DEBUG_SRC) \
$(ARMV4_5_SRC) \
@@ -37,185 +21,200 @@ libtarget_la_SOURCES = \
$(NDS32_SRC) \
$(INTEL_IA32_SRC) \
$(RISCV_SRC) \
avrt.c \
dsp563xx.c \
dsp563xx_once.c \
dsp5680xx.c \
hla_target.c
%D%/avrt.c \
%D%/dsp563xx.c \
%D%/dsp563xx_once.c \
%D%/dsp5680xx.c \
%D%/hla_target.c
if TARGET64
%C%_libtarget_la_SOURCES +=$(ARMV8_SRC)
endif
TARGET_CORE_SRC = \
algorithm.c \
register.c \
image.c \
breakpoints.c \
target.c \
target_request.c \
testee.c \
smp.c
%D%/algorithm.c \
%D%/register.c \
%D%/image.c \
%D%/breakpoints.c \
%D%/target.c \
%D%/target_request.c \
%D%/testee.c \
%D%/smp.c
ARMV4_5_SRC = \
armv4_5.c \
armv4_5_mmu.c \
armv4_5_cache.c \
%D%/armv4_5.c \
%D%/armv4_5_mmu.c \
%D%/armv4_5_cache.c \
$(ARM7_9_SRC)
ARM7_9_SRC = \
arm7_9_common.c \
arm7tdmi.c \
arm720t.c \
arm9tdmi.c \
arm920t.c \
arm966e.c \
arm946e.c \
arm926ejs.c \
feroceon.c
%D%/arm7_9_common.c \
%D%/arm7tdmi.c \
%D%/arm720t.c \
%D%/arm9tdmi.c \
%D%/arm920t.c \
%D%/arm966e.c \
%D%/arm946e.c \
%D%/arm926ejs.c \
%D%/feroceon.c
ARM_MISC_SRC = \
fa526.c \
xscale.c
%D%/fa526.c \
%D%/xscale.c
ARMV6_SRC = \
arm11.c \
arm11_dbgtap.c
%D%/arm11.c \
%D%/arm11_dbgtap.c
ARMV7_SRC = \
armv7m.c \
armv7m_trace.c \
cortex_m.c \
armv7a.c \
cortex_a.c \
ls1_sap.c
%D%/armv7m.c \
%D%/armv7m_trace.c \
%D%/cortex_m.c \
%D%/armv7a.c \
%D%/cortex_a.c \
%D%/ls1_sap.c
ARMV8_SRC = \
%D%/armv8_dpm.c \
%D%/armv8_opcodes.c \
%D%/aarch64.c \
%D%/armv8.c \
%D%/armv8_cache.c
ARM_DEBUG_SRC = \
arm_dpm.c \
arm_jtag.c \
arm_disassembler.c \
arm_simulator.c \
arm_semihosting.c \
arm_adi_v5.c \
armv7a_cache.c \
armv7a_cache_l2x.c \
adi_v5_jtag.c \
adi_v5_swd.c \
embeddedice.c \
trace.c \
etb.c \
etm.c \
%D%/arm_dpm.c \
%D%/arm_jtag.c \
%D%/arm_disassembler.c \
%D%/arm_simulator.c \
%D%/arm_semihosting.c \
%D%/arm_adi_v5.c \
%D%/armv7a_cache.c \
%D%/armv7a_cache_l2x.c \
%D%/adi_v5_jtag.c \
%D%/adi_v5_swd.c \
%D%/embeddedice.c \
%D%/trace.c \
%D%/etb.c \
%D%/etm.c \
$(OOCD_TRACE_FILES) \
etm_dummy.c
%D%/etm_dummy.c \
%D%/arm_cti.c
AVR32_SRC = \
avr32_ap7k.c \
avr32_jtag.c \
avr32_mem.c \
avr32_regs.c
%D%/avr32_ap7k.c \
%D%/avr32_jtag.c \
%D%/avr32_mem.c \
%D%/avr32_regs.c
MIPS32_SRC = \
mips32.c \
mips_m4k.c \
mips32_pracc.c \
mips32_dmaacc.c \
mips_ejtag.c
%D%/mips32.c \
%D%/mips_m4k.c \
%D%/mips32_pracc.c \
%D%/mips32_dmaacc.c \
%D%/mips_ejtag.c
NDS32_SRC = \
nds32.c \
nds32_reg.c \
nds32_cmd.c \
nds32_disassembler.c \
nds32_tlb.c \
nds32_v2.c \
nds32_v3_common.c \
nds32_v3.c \
nds32_v3m.c \
nds32_aice.c
%D%/nds32.c \
%D%/nds32_reg.c \
%D%/nds32_cmd.c \
%D%/nds32_disassembler.c \
%D%/nds32_tlb.c \
%D%/nds32_v2.c \
%D%/nds32_v3_common.c \
%D%/nds32_v3.c \
%D%/nds32_v3m.c \
%D%/nds32_aice.c
INTEL_IA32_SRC = \
quark_x10xx.c \
quark_d20xx.c \
lakemont.c \
x86_32_common.c
%D%/quark_x10xx.c \
%D%/quark_d20xx.c \
%D%/lakemont.c \
%D%/x86_32_common.c
RISCV_SRC = \
riscv/riscv-011.c \
riscv/riscv-013.c \
riscv/riscv.c \
riscv/program.c \
riscv/batch.c
%D%/riscv/riscv-011.c \
%D%/riscv/riscv-013.c \
%D%/riscv/riscv.c \
%D%/riscv/program.c \
%D%/riscv/batch.c
noinst_HEADERS = \
algorithm.h \
arm.h \
arm_dpm.h \
arm_jtag.h \
arm_adi_v5.h \
armv7a_cache.h \
armv7a_cache_l2x.h \
arm_disassembler.h \
arm_opcodes.h \
arm_simulator.h \
arm_semihosting.h \
arm7_9_common.h \
arm7tdmi.h \
arm720t.h \
arm9tdmi.h \
arm920t.h \
arm926ejs.h \
arm966e.h \
arm946e.h \
arm11.h \
arm11_dbgtap.h \
armv4_5.h \
armv4_5_mmu.h \
armv4_5_cache.h \
armv7a.h \
armv7m.h \
armv7m_trace.h \
avrt.h \
dsp563xx.h \
dsp563xx_once.h \
dsp5680xx.h \
breakpoints.h \
cortex_m.h \
cortex_a.h \
embeddedice.h \
etb.h \
etm.h \
etm_dummy.h \
image.h \
mips32.h \
mips_m4k.h \
mips_ejtag.h \
mips32_pracc.h \
mips32_dmaacc.h \
oocd_trace.h \
register.h \
target.h \
target_type.h \
trace.h \
target_request.h \
trace.h \
xscale.h \
smp.h \
avr32_ap7k.h \
avr32_jtag.h \
avr32_mem.h \
avr32_regs.h \
nds32.h \
nds32_cmd.h \
nds32_disassembler.h \
nds32_edm.h \
nds32_insn.h \
nds32_reg.h \
nds32_tlb.h \
nds32_v2.h \
nds32_v3_common.h \
nds32_v3.h \
nds32_v3m.h \
nds32_aice.h \
lakemont.h \
x86_32_common.h
%C%_libtarget_la_SOURCES += \
%D%/algorithm.h \
%D%/arm.h \
%D%/arm_dpm.h \
%D%/arm_jtag.h \
%D%/arm_adi_v5.h \
%D%/armv7a_cache.h \
%D%/armv7a_cache_l2x.h \
%D%/arm_disassembler.h \
%D%/arm_opcodes.h \
%D%/arm_simulator.h \
%D%/arm_semihosting.h \
%D%/arm7_9_common.h \
%D%/arm7tdmi.h \
%D%/arm720t.h \
%D%/arm9tdmi.h \
%D%/arm920t.h \
%D%/arm926ejs.h \
%D%/arm966e.h \
%D%/arm946e.h \
%D%/arm11.h \
%D%/arm11_dbgtap.h \
%D%/armv4_5.h \
%D%/armv4_5_mmu.h \
%D%/armv4_5_cache.h \
%D%/armv7a.h \
%D%/armv7m.h \
%D%/armv7m_trace.h \
%D%/armv8.h \
%D%/armv8_dpm.h \
%D%/armv8_opcodes.h \
%D%/armv8_cache.h \
%D%/avrt.h \
%D%/dsp563xx.h \
%D%/dsp563xx_once.h \
%D%/dsp5680xx.h \
%D%/breakpoints.h \
%D%/cortex_m.h \
%D%/cortex_a.h \
%D%/aarch64.h \
%D%/embeddedice.h \
%D%/etb.h \
%D%/etm.h \
%D%/etm_dummy.h \
%D%/image.h \
%D%/mips32.h \
%D%/mips_m4k.h \
%D%/mips_ejtag.h \
%D%/mips32_pracc.h \
%D%/mips32_dmaacc.h \
%D%/oocd_trace.h \
%D%/register.h \
%D%/target.h \
%D%/target_type.h \
%D%/trace.h \
%D%/target_request.h \
%D%/trace.h \
%D%/xscale.h \
%D%/smp.h \
%D%/avr32_ap7k.h \
%D%/avr32_jtag.h \
%D%/avr32_mem.h \
%D%/avr32_regs.h \
%D%/nds32.h \
%D%/nds32_cmd.h \
%D%/nds32_disassembler.h \
%D%/nds32_edm.h \
%D%/nds32_insn.h \
%D%/nds32_reg.h \
%D%/nds32_tlb.h \
%D%/nds32_v2.h \
%D%/nds32_v3_common.h \
%D%/nds32_v3.h \
%D%/nds32_v3m.h \
%D%/nds32_aice.h \
%D%/lakemont.h \
%D%/x86_32_common.h \
%D%/arm_cti.h
ocddatadir = $(pkglibdir)
nobase_dist_ocddata_DATA =
MAINTAINERCLEANFILES = $(srcdir)/Makefile.in
include %D%/openrisc/Makefile.am
+2452
View File
File diff suppressed because it is too large Load Diff
+69
View File
@@ -0,0 +1,69 @@
/***************************************************************************
* Copyright (C) 2015 by David Ung *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
***************************************************************************/
#ifndef OPENOCD_TARGET_AARCH64_H
#define OPENOCD_TARGET_AARCH64_H
#include "armv8.h"
#define AARCH64_COMMON_MAGIC 0x411fc082
#define CPUDBG_CPUID 0xD00
#define CPUDBG_CTYPR 0xD04
#define CPUDBG_TTYPR 0xD0C
#define ID_AA64PFR0_EL1 0xD20
#define ID_AA64DFR0_EL1 0xD28
#define CPUDBG_LOCKACCESS 0xFB0
#define CPUDBG_LOCKSTATUS 0xFB4
#define BRP_NORMAL 0
#define BRP_CONTEXT 1
#define AARCH64_PADDRDBG_CPU_SHIFT 13
struct aarch64_brp {
int used;
int type;
target_addr_t value;
uint32_t control;
uint8_t BRPn;
};
struct aarch64_common {
int common_magic;
/* Context information */
uint32_t system_control_reg;
uint32_t system_control_reg_curr;
/* Breakpoint register pairs */
int brp_num_context;
int brp_num;
int brp_num_available;
struct aarch64_brp *brp_list;
struct armv8_common armv8_common;
};
static inline struct aarch64_common *
target_to_aarch64(struct target *target)
{
return container_of(target->arch_info, struct aarch64_common, armv8_common.arm);
}
#endif /* OPENOCD_TARGET_AARCH64_H */
+1 -6
View File
@@ -574,8 +574,6 @@ static int jtagdp_transaction_endcheck(struct adiv5_dap *dap)
if ((ctrlstat & (CDBGPWRUPREQ | CDBGPWRUPACK | CSYSPWRUPREQ | CSYSPWRUPACK)) !=
(CDBGPWRUPREQ | CDBGPWRUPACK | CSYSPWRUPREQ | CSYSPWRUPACK)) {
LOG_ERROR("Debug regions are unpowered, an unexpected reset might have happened");
retval = ERROR_JTAG_DEVICE_ERROR;
goto done;
}
if (ctrlstat & SSTICKYERR)
@@ -590,10 +588,7 @@ static int jtagdp_transaction_endcheck(struct adiv5_dap *dap)
if (retval != ERROR_OK)
goto done;
if (ctrlstat & SSTICKYERR) {
retval = ERROR_JTAG_DEVICE_ERROR;
goto done;
}
retval = ERROR_JTAG_DEVICE_ERROR;
}
done:
+1 -1
View File
@@ -26,7 +26,7 @@ enum param_direction {
};
struct mem_param {
uint32_t address;
target_addr_t address;
uint32_t size;
uint8_t *value;
enum param_direction direction;

Some files were not shown because too many files have changed in this diff Show More