Compare commits
No commits in common. "jtaglib-cpux" and "master" have entirely different histories.
jtaglib-cp
...
master
|
@ -2,5 +2,3 @@
|
|||
*.o
|
||||
mspdebug
|
||||
mspdebug.exe
|
||||
inst/
|
||||
config.mk
|
||||
|
|
8
Makefile
8
Makefile
|
@ -21,8 +21,6 @@ INSTALL = /usr/bin/install
|
|||
PREFIX ?= /usr/local
|
||||
LDFLAGS ?= -s
|
||||
|
||||
-include config.mk
|
||||
|
||||
BINDIR = ${PREFIX}/bin/
|
||||
MANDIR = ${PREFIX}/share/man/man1
|
||||
LIBDIR = ${PREFIX}/lib/
|
||||
|
@ -173,7 +171,6 @@ OBJ=\
|
|||
transport/cp210x.o \
|
||||
transport/cdc_acm.o \
|
||||
transport/ftdi.o \
|
||||
transport/mehfet_xport.o \
|
||||
transport/ti3410.o \
|
||||
transport/comport.o \
|
||||
$(BSLHID_OBJ) \
|
||||
|
@ -197,11 +194,6 @@ OBJ=\
|
|||
drivers/jtdev_bus_pirate.o \
|
||||
drivers/jtdev_gpio.o \
|
||||
drivers/jtaglib.o \
|
||||
drivers/jtaglib_cpu16.o \
|
||||
drivers/jtaglib_cpux.o \
|
||||
drivers/jtaglib_cpuxv2.o \
|
||||
drivers/mehfet_proto.o \
|
||||
drivers/mehfet.o \
|
||||
drivers/pif.o \
|
||||
drivers/loadbsl.o \
|
||||
drivers/loadbsl_fw.o \
|
||||
|
|
7
README
7
README
|
@ -33,8 +33,7 @@ Compiling from source
|
|||
|
||||
Ensure that you have the necessary packages to compile programs that use
|
||||
libusb (on Debian or Ubuntu systems, you might need to do apt-get
|
||||
install libusb-dev | on Arch systems, you might need to do sudo
|
||||
pacman -S libusb-compact). After that, unpack and compile the source code
|
||||
install libusb-dev). After that, unpack and compile the source code
|
||||
with:
|
||||
|
||||
tar xvfz mspdebug-version.tar.gz
|
||||
|
@ -42,8 +41,8 @@ with:
|
|||
make
|
||||
|
||||
On Debian Ubuntu systems sudo apt-get install libreadline-dev may be
|
||||
required. On Arch systems sudo pacman -S readline may be required.
|
||||
If you don't want GNU readline support, you can invoke make with:
|
||||
required. If you don't want GNU readline support, you can invoke make
|
||||
with:
|
||||
|
||||
make WITHOUT_READLINE=1
|
||||
|
||||
|
|
166
chipinfo.db
166
chipinfo.db
|
@ -47335,7 +47335,7 @@ const struct chipinfo chipinfo_db[] = { {
|
|||
[0x18] = 0x3f,
|
||||
[0x19] = 0x3f,
|
||||
[0x1a] = 0x40,
|
||||
[0x1c] = 0x41/*0x50*/,
|
||||
[0x1c] = 0x50,
|
||||
[0x1d] = 0x42,
|
||||
[0x1e] = 0x43,
|
||||
[0x1f] = 0x44,
|
||||
|
@ -47633,7 +47633,7 @@ const struct chipinfo chipinfo_db[] = { {
|
|||
[0x18] = 0x3f,
|
||||
[0x19] = 0x3f,
|
||||
[0x1a] = 0x40,
|
||||
[0x1c] = 0x41/*0x50*/,
|
||||
[0x1c] = 0x50,
|
||||
[0x1d] = 0x42,
|
||||
[0x1e] = 0x43,
|
||||
[0x1f] = 0x44,
|
||||
|
@ -47931,7 +47931,7 @@ const struct chipinfo chipinfo_db[] = { {
|
|||
[0x18] = 0x3f,
|
||||
[0x19] = 0x3f,
|
||||
[0x1a] = 0x40,
|
||||
[0x1c] = 0x41/*0x50*/,
|
||||
[0x1c] = 0x50,
|
||||
[0x1d] = 0x42,
|
||||
[0x1e] = 0x43,
|
||||
[0x1f] = 0x44,
|
||||
|
@ -48229,7 +48229,7 @@ const struct chipinfo chipinfo_db[] = { {
|
|||
[0x18] = 0x3f,
|
||||
[0x19] = 0x3f,
|
||||
[0x1a] = 0x40,
|
||||
[0x1c] = 0x41/*0x50*/,
|
||||
[0x1c] = 0x50,
|
||||
[0x1d] = 0x42,
|
||||
[0x1e] = 0x43,
|
||||
[0x1f] = 0x44,
|
||||
|
@ -48527,7 +48527,7 @@ const struct chipinfo chipinfo_db[] = { {
|
|||
[0x18] = 0x3f,
|
||||
[0x19] = 0x3f,
|
||||
[0x1a] = 0x40,
|
||||
[0x1c] = 0x41/*0x50*/,
|
||||
[0x1c] = 0x50,
|
||||
[0x1d] = 0x42,
|
||||
[0x1e] = 0x43,
|
||||
[0x1f] = 0x44,
|
||||
|
@ -48825,7 +48825,7 @@ const struct chipinfo chipinfo_db[] = { {
|
|||
[0x18] = 0x3f,
|
||||
[0x19] = 0x3f,
|
||||
[0x1a] = 0x40,
|
||||
[0x1c] = 0x41/*0x50*/,
|
||||
[0x1c] = 0x50,
|
||||
[0x1d] = 0x42,
|
||||
[0x1e] = 0x43,
|
||||
[0x1f] = 0x44,
|
||||
|
@ -49123,7 +49123,7 @@ const struct chipinfo chipinfo_db[] = { {
|
|||
[0x18] = 0x3f,
|
||||
[0x19] = 0x3f,
|
||||
[0x1a] = 0x40,
|
||||
[0x1c] = 0x41/*0x50*/,
|
||||
[0x1c] = 0x50,
|
||||
[0x1d] = 0x42,
|
||||
[0x1e] = 0x43,
|
||||
[0x1f] = 0x44,
|
||||
|
@ -49421,7 +49421,7 @@ const struct chipinfo chipinfo_db[] = { {
|
|||
[0x18] = 0x3f,
|
||||
[0x19] = 0x3f,
|
||||
[0x1a] = 0x40,
|
||||
[0x1c] = 0x41/*0x50*/,
|
||||
[0x1c] = 0x50,
|
||||
[0x1d] = 0x42,
|
||||
[0x1e] = 0x43,
|
||||
[0x1f] = 0x44,
|
||||
|
@ -49719,7 +49719,7 @@ const struct chipinfo chipinfo_db[] = { {
|
|||
[0x18] = 0x3f,
|
||||
[0x19] = 0x3f,
|
||||
[0x1a] = 0x40,
|
||||
[0x1c] = 0x41/*0x50*/,
|
||||
[0x1c] = 0x50,
|
||||
[0x1d] = 0x42,
|
||||
[0x1e] = 0x43,
|
||||
[0x1f] = 0x44,
|
||||
|
@ -50017,7 +50017,7 @@ const struct chipinfo chipinfo_db[] = { {
|
|||
[0x18] = 0x3f,
|
||||
[0x19] = 0x3f,
|
||||
[0x1a] = 0x40,
|
||||
[0x1c] = 0x41/*0x50*/,
|
||||
[0x1c] = 0x50,
|
||||
[0x1d] = 0x42,
|
||||
[0x1e] = 0x43,
|
||||
[0x1f] = 0x44,
|
||||
|
@ -50315,7 +50315,7 @@ const struct chipinfo chipinfo_db[] = { {
|
|||
[0x18] = 0x3f,
|
||||
[0x19] = 0x3f,
|
||||
[0x1a] = 0x40,
|
||||
[0x1c] = 0x41/*0x50*/,
|
||||
[0x1c] = 0x50,
|
||||
[0x1d] = 0x42,
|
||||
[0x1e] = 0x43,
|
||||
[0x1f] = 0x44,
|
||||
|
@ -50613,7 +50613,7 @@ const struct chipinfo chipinfo_db[] = { {
|
|||
[0x18] = 0x3f,
|
||||
[0x19] = 0x3f,
|
||||
[0x1a] = 0x40,
|
||||
[0x1c] = 0x41/*0x50*/,
|
||||
[0x1c] = 0x50,
|
||||
[0x1d] = 0x42,
|
||||
[0x1e] = 0x43,
|
||||
[0x1f] = 0x44,
|
||||
|
@ -50911,7 +50911,7 @@ const struct chipinfo chipinfo_db[] = { {
|
|||
[0x18] = 0x3f,
|
||||
[0x19] = 0x3f,
|
||||
[0x1a] = 0x40,
|
||||
[0x1c] = 0x41/*0x50*/,
|
||||
[0x1c] = 0x50,
|
||||
[0x1d] = 0x42,
|
||||
[0x1e] = 0x43,
|
||||
[0x1f] = 0x44,
|
||||
|
@ -51209,7 +51209,7 @@ const struct chipinfo chipinfo_db[] = { {
|
|||
[0x18] = 0x3f,
|
||||
[0x19] = 0x3f,
|
||||
[0x1a] = 0x40,
|
||||
[0x1c] = 0x41/*0x50*/,
|
||||
[0x1c] = 0x50,
|
||||
[0x1d] = 0x42,
|
||||
[0x1e] = 0x43,
|
||||
[0x1f] = 0x44,
|
||||
|
@ -51507,7 +51507,7 @@ const struct chipinfo chipinfo_db[] = { {
|
|||
[0x18] = 0x3f,
|
||||
[0x19] = 0x3f,
|
||||
[0x1a] = 0x40,
|
||||
[0x1c] = 0x41/*0x50*/,
|
||||
[0x1c] = 0x50,
|
||||
[0x1d] = 0x42,
|
||||
[0x1e] = 0x43,
|
||||
[0x1f] = 0x44,
|
||||
|
@ -51805,7 +51805,7 @@ const struct chipinfo chipinfo_db[] = { {
|
|||
[0x18] = 0x3f,
|
||||
[0x19] = 0x3f,
|
||||
[0x1a] = 0x40,
|
||||
[0x1c] = 0x41/*0x50*/,
|
||||
[0x1c] = 0x50,
|
||||
[0x1d] = 0x42,
|
||||
[0x1e] = 0x43,
|
||||
[0x1f] = 0x44,
|
||||
|
@ -52103,7 +52103,7 @@ const struct chipinfo chipinfo_db[] = { {
|
|||
[0x18] = 0x3f,
|
||||
[0x19] = 0x3f,
|
||||
[0x1a] = 0x40,
|
||||
[0x1c] = 0x41/*0x50*/,
|
||||
[0x1c] = 0x50,
|
||||
[0x1d] = 0x42,
|
||||
[0x1e] = 0x43,
|
||||
[0x1f] = 0x44,
|
||||
|
@ -52401,7 +52401,7 @@ const struct chipinfo chipinfo_db[] = { {
|
|||
[0x18] = 0x3f,
|
||||
[0x19] = 0x3f,
|
||||
[0x1a] = 0x40,
|
||||
[0x1c] = 0x41/*0x50*/,
|
||||
[0x1c] = 0x50,
|
||||
[0x1d] = 0x42,
|
||||
[0x1e] = 0x43,
|
||||
[0x1f] = 0x44,
|
||||
|
@ -55325,7 +55325,7 @@ const struct chipinfo chipinfo_db[] = { {
|
|||
[0x18] = 0x3f,
|
||||
[0x19] = 0x3f,
|
||||
[0x1a] = 0x40,
|
||||
[0x1c] = 0x41/*0x50*/,
|
||||
[0x1c] = 0x50,
|
||||
[0x1d] = 0x42,
|
||||
[0x1e] = 0x43,
|
||||
[0x1f] = 0x44,
|
||||
|
@ -60873,7 +60873,7 @@ const struct chipinfo chipinfo_db[] = { {
|
|||
[0x18] = 0x3f,
|
||||
[0x19] = 0x3f,
|
||||
[0x1a] = 0x40,
|
||||
[0x1c] = 0x41/*0x50*/,
|
||||
[0x1c] = 0x50,
|
||||
[0x1d] = 0x42,
|
||||
[0x1e] = 0x43,
|
||||
[0x1f] = 0x44,
|
||||
|
@ -61171,7 +61171,7 @@ const struct chipinfo chipinfo_db[] = { {
|
|||
[0x18] = 0x3f,
|
||||
[0x19] = 0x3f,
|
||||
[0x1a] = 0x40,
|
||||
[0x1c] = 0x41/*0x50*/,
|
||||
[0x1c] = 0x50,
|
||||
[0x1d] = 0x42,
|
||||
[0x1e] = 0x43,
|
||||
[0x1f] = 0x44,
|
||||
|
@ -61469,7 +61469,7 @@ const struct chipinfo chipinfo_db[] = { {
|
|||
[0x18] = 0x3f,
|
||||
[0x19] = 0x3f,
|
||||
[0x1a] = 0x40,
|
||||
[0x1c] = 0x41/*0x50*/,
|
||||
[0x1c] = 0x50,
|
||||
[0x1d] = 0x42,
|
||||
[0x1e] = 0x43,
|
||||
[0x1f] = 0x44,
|
||||
|
@ -61767,7 +61767,7 @@ const struct chipinfo chipinfo_db[] = { {
|
|||
[0x18] = 0x3f,
|
||||
[0x19] = 0x3f,
|
||||
[0x1a] = 0x40,
|
||||
[0x1c] = 0x41/*0x50*/,
|
||||
[0x1c] = 0x50,
|
||||
[0x1d] = 0x42,
|
||||
[0x1e] = 0x43,
|
||||
[0x1f] = 0x44,
|
||||
|
@ -62065,7 +62065,7 @@ const struct chipinfo chipinfo_db[] = { {
|
|||
[0x18] = 0x3f,
|
||||
[0x19] = 0x3f,
|
||||
[0x1a] = 0x40,
|
||||
[0x1c] = 0x41/*0x50*/,
|
||||
[0x1c] = 0x50,
|
||||
[0x1d] = 0x42,
|
||||
[0x1e] = 0x43,
|
||||
[0x1f] = 0x44,
|
||||
|
@ -62363,7 +62363,7 @@ const struct chipinfo chipinfo_db[] = { {
|
|||
[0x18] = 0x3f,
|
||||
[0x19] = 0x3f,
|
||||
[0x1a] = 0x40,
|
||||
[0x1c] = 0x41/*0x50*/,
|
||||
[0x1c] = 0x50,
|
||||
[0x1d] = 0x42,
|
||||
[0x1e] = 0x43,
|
||||
[0x1f] = 0x44,
|
||||
|
@ -62661,7 +62661,7 @@ const struct chipinfo chipinfo_db[] = { {
|
|||
[0x18] = 0x3f,
|
||||
[0x19] = 0x3f,
|
||||
[0x1a] = 0x40,
|
||||
[0x1c] = 0x41/*0x50*/,
|
||||
[0x1c] = 0x50,
|
||||
[0x1d] = 0x42,
|
||||
[0x1e] = 0x43,
|
||||
[0x1f] = 0x44,
|
||||
|
@ -62959,7 +62959,7 @@ const struct chipinfo chipinfo_db[] = { {
|
|||
[0x18] = 0x3f,
|
||||
[0x19] = 0x3f,
|
||||
[0x1a] = 0x40,
|
||||
[0x1c] = 0x41/*0x50*/,
|
||||
[0x1c] = 0x50,
|
||||
[0x1d] = 0x42,
|
||||
[0x1e] = 0x43,
|
||||
[0x1f] = 0x44,
|
||||
|
@ -63257,7 +63257,7 @@ const struct chipinfo chipinfo_db[] = { {
|
|||
[0x18] = 0x3f,
|
||||
[0x19] = 0x3f,
|
||||
[0x1a] = 0x40,
|
||||
[0x1c] = 0x41/*0x50*/,
|
||||
[0x1c] = 0x50,
|
||||
[0x1d] = 0x42,
|
||||
[0x1e] = 0x43,
|
||||
[0x1f] = 0x44,
|
||||
|
@ -63555,7 +63555,7 @@ const struct chipinfo chipinfo_db[] = { {
|
|||
[0x18] = 0x3f,
|
||||
[0x19] = 0x3f,
|
||||
[0x1a] = 0x40,
|
||||
[0x1c] = 0x41/*0x50*/,
|
||||
[0x1c] = 0x50,
|
||||
[0x1d] = 0x42,
|
||||
[0x1e] = 0x43,
|
||||
[0x1f] = 0x44,
|
||||
|
@ -63853,7 +63853,7 @@ const struct chipinfo chipinfo_db[] = { {
|
|||
[0x18] = 0x3f,
|
||||
[0x19] = 0x3f,
|
||||
[0x1a] = 0x40,
|
||||
[0x1c] = 0x41/*0x50*/,
|
||||
[0x1c] = 0x50,
|
||||
[0x1d] = 0x42,
|
||||
[0x1e] = 0x43,
|
||||
[0x1f] = 0x44,
|
||||
|
@ -64151,7 +64151,7 @@ const struct chipinfo chipinfo_db[] = { {
|
|||
[0x18] = 0x3f,
|
||||
[0x19] = 0x3f,
|
||||
[0x1a] = 0x40,
|
||||
[0x1c] = 0x41/*0x50*/,
|
||||
[0x1c] = 0x50,
|
||||
[0x1d] = 0x42,
|
||||
[0x1e] = 0x43,
|
||||
[0x1f] = 0x44,
|
||||
|
@ -64449,7 +64449,7 @@ const struct chipinfo chipinfo_db[] = { {
|
|||
[0x18] = 0x3f,
|
||||
[0x19] = 0x3f,
|
||||
[0x1a] = 0x40,
|
||||
[0x1c] = 0x41/*0x50*/,
|
||||
[0x1c] = 0x50,
|
||||
[0x1d] = 0x42,
|
||||
[0x1e] = 0x43,
|
||||
[0x1f] = 0x44,
|
||||
|
@ -64747,7 +64747,7 @@ const struct chipinfo chipinfo_db[] = { {
|
|||
[0x18] = 0x3f,
|
||||
[0x19] = 0x3f,
|
||||
[0x1a] = 0x40,
|
||||
[0x1c] = 0x41/*0x50*/,
|
||||
[0x1c] = 0x50,
|
||||
[0x1d] = 0x42,
|
||||
[0x1e] = 0x43,
|
||||
[0x1f] = 0x44,
|
||||
|
@ -65045,7 +65045,7 @@ const struct chipinfo chipinfo_db[] = { {
|
|||
[0x18] = 0x3f,
|
||||
[0x19] = 0x3f,
|
||||
[0x1a] = 0x40,
|
||||
[0x1c] = 0x41/*0x50*/,
|
||||
[0x1c] = 0x50,
|
||||
[0x1d] = 0x42,
|
||||
[0x1e] = 0x43,
|
||||
[0x1f] = 0x44,
|
||||
|
@ -65343,7 +65343,7 @@ const struct chipinfo chipinfo_db[] = { {
|
|||
[0x18] = 0x3f,
|
||||
[0x19] = 0x3f,
|
||||
[0x1a] = 0x40,
|
||||
[0x1c] = 0x41/*0x50*/,
|
||||
[0x1c] = 0x50,
|
||||
[0x1d] = 0x42,
|
||||
[0x1e] = 0x43,
|
||||
[0x1f] = 0x44,
|
||||
|
@ -65641,7 +65641,7 @@ const struct chipinfo chipinfo_db[] = { {
|
|||
[0x18] = 0x3f,
|
||||
[0x19] = 0x3f,
|
||||
[0x1a] = 0x40,
|
||||
[0x1c] = 0x41/*0x50*/,
|
||||
[0x1c] = 0x50,
|
||||
[0x1d] = 0x42,
|
||||
[0x1e] = 0x43,
|
||||
[0x1f] = 0x44,
|
||||
|
@ -65939,7 +65939,7 @@ const struct chipinfo chipinfo_db[] = { {
|
|||
[0x18] = 0x3f,
|
||||
[0x19] = 0x3f,
|
||||
[0x1a] = 0x40,
|
||||
[0x1c] = 0x41/*0x50*/,
|
||||
[0x1c] = 0x50,
|
||||
[0x1d] = 0x42,
|
||||
[0x1e] = 0x43,
|
||||
[0x1f] = 0x44,
|
||||
|
@ -66237,7 +66237,7 @@ const struct chipinfo chipinfo_db[] = { {
|
|||
[0x18] = 0x3f,
|
||||
[0x19] = 0x3f,
|
||||
[0x1a] = 0x40,
|
||||
[0x1c] = 0x41/*0x50*/,
|
||||
[0x1c] = 0x50,
|
||||
[0x1d] = 0x42,
|
||||
[0x1e] = 0x43,
|
||||
[0x1f] = 0x44,
|
||||
|
@ -78736,7 +78736,7 @@ const struct chipinfo chipinfo_db[] = { {
|
|||
[0x18] = 0x3f,
|
||||
[0x19] = 0x3f,
|
||||
[0x1a] = 0x40,
|
||||
[0x1c] = 0x41/*0x50*/,
|
||||
[0x1c] = 0x50,
|
||||
[0x1d] = 0x42,
|
||||
[0x1e] = 0x43,
|
||||
[0x1f] = 0x44,
|
||||
|
@ -78933,7 +78933,7 @@ const struct chipinfo chipinfo_db[] = { {
|
|||
[0x18] = 0x3f,
|
||||
[0x19] = 0x3f,
|
||||
[0x1a] = 0x40,
|
||||
[0x1c] = 0x41/*0x50*/,
|
||||
[0x1c] = 0x50,
|
||||
[0x1d] = 0x42,
|
||||
[0x1e] = 0x43,
|
||||
[0x1f] = 0x44,
|
||||
|
@ -79130,7 +79130,7 @@ const struct chipinfo chipinfo_db[] = { {
|
|||
[0x18] = 0x3f,
|
||||
[0x19] = 0x3f,
|
||||
[0x1a] = 0x40,
|
||||
[0x1c] = 0x41/*0x50*/,
|
||||
[0x1c] = 0x50,
|
||||
[0x1d] = 0x42,
|
||||
[0x1e] = 0x43,
|
||||
[0x1f] = 0x44,
|
||||
|
@ -79327,7 +79327,7 @@ const struct chipinfo chipinfo_db[] = { {
|
|||
[0x18] = 0x3f,
|
||||
[0x19] = 0x3f,
|
||||
[0x1a] = 0x40,
|
||||
[0x1c] = 0x41/*0x50*/,
|
||||
[0x1c] = 0x50,
|
||||
[0x1d] = 0x42,
|
||||
[0x1e] = 0x43,
|
||||
[0x1f] = 0x44,
|
||||
|
@ -79524,7 +79524,7 @@ const struct chipinfo chipinfo_db[] = { {
|
|||
[0x18] = 0x3f,
|
||||
[0x19] = 0x3f,
|
||||
[0x1a] = 0x40,
|
||||
[0x1c] = 0x41/*0x50*/,
|
||||
[0x1c] = 0x50,
|
||||
[0x1d] = 0x42,
|
||||
[0x1e] = 0x43,
|
||||
[0x1f] = 0x44,
|
||||
|
@ -79721,7 +79721,7 @@ const struct chipinfo chipinfo_db[] = { {
|
|||
[0x18] = 0x3f,
|
||||
[0x19] = 0x3f,
|
||||
[0x1a] = 0x40,
|
||||
[0x1c] = 0x41/*0x50*/,
|
||||
[0x1c] = 0x50,
|
||||
[0x1d] = 0x42,
|
||||
[0x1e] = 0x43,
|
||||
[0x1f] = 0x44,
|
||||
|
@ -79918,7 +79918,7 @@ const struct chipinfo chipinfo_db[] = { {
|
|||
[0x18] = 0x3f,
|
||||
[0x19] = 0x3f,
|
||||
[0x1a] = 0x40,
|
||||
[0x1c] = 0x41/*0x50*/,
|
||||
[0x1c] = 0x50,
|
||||
[0x1d] = 0x42,
|
||||
[0x1e] = 0x43,
|
||||
[0x1f] = 0x44,
|
||||
|
@ -80115,7 +80115,7 @@ const struct chipinfo chipinfo_db[] = { {
|
|||
[0x18] = 0x3f,
|
||||
[0x19] = 0x3f,
|
||||
[0x1a] = 0x40,
|
||||
[0x1c] = 0x41/*0x50*/,
|
||||
[0x1c] = 0x50,
|
||||
[0x1d] = 0x42,
|
||||
[0x1e] = 0x43,
|
||||
[0x1f] = 0x44,
|
||||
|
@ -80312,7 +80312,7 @@ const struct chipinfo chipinfo_db[] = { {
|
|||
[0x18] = 0x3f,
|
||||
[0x19] = 0x3f,
|
||||
[0x1a] = 0x40,
|
||||
[0x1c] = 0x41/*0x50*/,
|
||||
[0x1c] = 0x50,
|
||||
[0x1d] = 0x42,
|
||||
[0x1e] = 0x43,
|
||||
[0x1f] = 0x44,
|
||||
|
@ -80509,7 +80509,7 @@ const struct chipinfo chipinfo_db[] = { {
|
|||
[0x18] = 0x3f,
|
||||
[0x19] = 0x3f,
|
||||
[0x1a] = 0x40,
|
||||
[0x1c] = 0x41/*0x50*/,
|
||||
[0x1c] = 0x50,
|
||||
[0x1d] = 0x42,
|
||||
[0x1e] = 0x43,
|
||||
[0x1f] = 0x44,
|
||||
|
@ -80706,7 +80706,7 @@ const struct chipinfo chipinfo_db[] = { {
|
|||
[0x18] = 0x3f,
|
||||
[0x19] = 0x3f,
|
||||
[0x1a] = 0x40,
|
||||
[0x1c] = 0x41/*0x50*/,
|
||||
[0x1c] = 0x50,
|
||||
[0x1d] = 0x42,
|
||||
[0x1e] = 0x43,
|
||||
[0x1f] = 0x44,
|
||||
|
@ -80903,7 +80903,7 @@ const struct chipinfo chipinfo_db[] = { {
|
|||
[0x18] = 0x3f,
|
||||
[0x19] = 0x3f,
|
||||
[0x1a] = 0x40,
|
||||
[0x1c] = 0x41/*0x50*/,
|
||||
[0x1c] = 0x50,
|
||||
[0x1d] = 0x42,
|
||||
[0x1e] = 0x43,
|
||||
[0x1f] = 0x44,
|
||||
|
@ -81100,7 +81100,7 @@ const struct chipinfo chipinfo_db[] = { {
|
|||
[0x18] = 0x3f,
|
||||
[0x19] = 0x3f,
|
||||
[0x1a] = 0x40,
|
||||
[0x1c] = 0x41/*0x50*/,
|
||||
[0x1c] = 0x50,
|
||||
[0x1d] = 0x42,
|
||||
[0x1e] = 0x43,
|
||||
[0x1f] = 0x44,
|
||||
|
@ -81297,7 +81297,7 @@ const struct chipinfo chipinfo_db[] = { {
|
|||
[0x18] = 0x3f,
|
||||
[0x19] = 0x3f,
|
||||
[0x1a] = 0x40,
|
||||
[0x1c] = 0x41/*0x50*/,
|
||||
[0x1c] = 0x50,
|
||||
[0x1d] = 0x42,
|
||||
[0x1e] = 0x43,
|
||||
[0x1f] = 0x44,
|
||||
|
@ -81494,7 +81494,7 @@ const struct chipinfo chipinfo_db[] = { {
|
|||
[0x18] = 0x3f,
|
||||
[0x19] = 0x3f,
|
||||
[0x1a] = 0x40,
|
||||
[0x1c] = 0x41/*0x50*/,
|
||||
[0x1c] = 0x50,
|
||||
[0x1d] = 0x42,
|
||||
[0x1e] = 0x43,
|
||||
[0x1f] = 0x44,
|
||||
|
@ -81691,7 +81691,7 @@ const struct chipinfo chipinfo_db[] = { {
|
|||
[0x18] = 0x3f,
|
||||
[0x19] = 0x3f,
|
||||
[0x1a] = 0x40,
|
||||
[0x1c] = 0x41/*0x50*/,
|
||||
[0x1c] = 0x50,
|
||||
[0x1d] = 0x42,
|
||||
[0x1e] = 0x43,
|
||||
[0x1f] = 0x44,
|
||||
|
@ -81888,7 +81888,7 @@ const struct chipinfo chipinfo_db[] = { {
|
|||
[0x18] = 0x3f,
|
||||
[0x19] = 0x3f,
|
||||
[0x1a] = 0x40,
|
||||
[0x1c] = 0x41/*0x50*/,
|
||||
[0x1c] = 0x50,
|
||||
[0x1d] = 0x42,
|
||||
[0x1e] = 0x43,
|
||||
[0x1f] = 0x44,
|
||||
|
@ -82085,7 +82085,7 @@ const struct chipinfo chipinfo_db[] = { {
|
|||
[0x18] = 0x3f,
|
||||
[0x19] = 0x3f,
|
||||
[0x1a] = 0x40,
|
||||
[0x1c] = 0x41/*0x50*/,
|
||||
[0x1c] = 0x50,
|
||||
[0x1d] = 0x42,
|
||||
[0x1e] = 0x43,
|
||||
[0x1f] = 0x44,
|
||||
|
@ -85045,7 +85045,7 @@ const struct chipinfo chipinfo_db[] = { {
|
|||
.id = {
|
||||
.ver_id = 0x82a1,
|
||||
.ver_sub_id = 0x0000,
|
||||
.revision = 0x21/*0x10*/,
|
||||
.revision = 0x10,
|
||||
.fab = 0x00,
|
||||
.self = 0x0000,
|
||||
.config = 0x00,
|
||||
|
@ -85084,7 +85084,7 @@ const struct chipinfo chipinfo_db[] = { {
|
|||
[0x18] = 0x3f,
|
||||
[0x19] = 0x3f,
|
||||
[0x1a] = 0x40,
|
||||
[0x1c] = 0x41/*0x50*/,
|
||||
[0x1c] = 0x50,
|
||||
[0x1d] = 0x42,
|
||||
[0x1e] = 0x43,
|
||||
[0x1f] = 0x44,
|
||||
|
@ -85314,7 +85314,7 @@ const struct chipinfo chipinfo_db[] = { {
|
|||
[0x18] = 0x3f,
|
||||
[0x19] = 0x3f,
|
||||
[0x1a] = 0x40,
|
||||
[0x1c] = 0x41/*0x50*/,
|
||||
[0x1c] = 0x50,
|
||||
[0x1d] = 0x42,
|
||||
[0x1e] = 0x43,
|
||||
[0x1f] = 0x44,
|
||||
|
@ -85544,7 +85544,7 @@ const struct chipinfo chipinfo_db[] = { {
|
|||
[0x18] = 0x3f,
|
||||
[0x19] = 0x3f,
|
||||
[0x1a] = 0x40,
|
||||
[0x1c] = 0x41/*0x50*/,
|
||||
[0x1c] = 0x50,
|
||||
[0x1d] = 0x42,
|
||||
[0x1e] = 0x43,
|
||||
[0x1f] = 0x44,
|
||||
|
@ -85774,7 +85774,7 @@ const struct chipinfo chipinfo_db[] = { {
|
|||
[0x18] = 0x3f,
|
||||
[0x19] = 0x3f,
|
||||
[0x1a] = 0x40,
|
||||
[0x1c] = 0x41/*0x50*/,
|
||||
[0x1c] = 0x50,
|
||||
[0x1d] = 0x42,
|
||||
[0x1e] = 0x43,
|
||||
[0x1f] = 0x44,
|
||||
|
@ -85971,7 +85971,7 @@ const struct chipinfo chipinfo_db[] = { {
|
|||
[0x18] = 0x3f,
|
||||
[0x19] = 0x3f,
|
||||
[0x1a] = 0x40,
|
||||
[0x1c] = 0x41/*0x50*/,
|
||||
[0x1c] = 0x50,
|
||||
[0x1d] = 0x42,
|
||||
[0x1e] = 0x43,
|
||||
[0x1f] = 0x44,
|
||||
|
@ -86168,7 +86168,7 @@ const struct chipinfo chipinfo_db[] = { {
|
|||
[0x18] = 0x3f,
|
||||
[0x19] = 0x3f,
|
||||
[0x1a] = 0x40,
|
||||
[0x1c] = 0x41/*0x50*/,
|
||||
[0x1c] = 0x50,
|
||||
[0x1d] = 0x42,
|
||||
[0x1e] = 0x43,
|
||||
[0x1f] = 0x44,
|
||||
|
@ -86409,7 +86409,7 @@ const struct chipinfo chipinfo_db[] = { {
|
|||
[0x18] = 0x3f,
|
||||
[0x19] = 0x3f,
|
||||
[0x1a] = 0x40,
|
||||
[0x1c] = 0x41/*0x50*/,
|
||||
[0x1c] = 0x50,
|
||||
[0x1d] = 0x42,
|
||||
[0x1e] = 0x43,
|
||||
[0x1f] = 0x44,
|
||||
|
@ -86650,7 +86650,7 @@ const struct chipinfo chipinfo_db[] = { {
|
|||
[0x18] = 0x3f,
|
||||
[0x19] = 0x3f,
|
||||
[0x1a] = 0x40,
|
||||
[0x1c] = 0x41/*0x50*/,
|
||||
[0x1c] = 0x50,
|
||||
[0x1d] = 0x42,
|
||||
[0x1e] = 0x43,
|
||||
[0x1f] = 0x44,
|
||||
|
@ -86891,7 +86891,7 @@ const struct chipinfo chipinfo_db[] = { {
|
|||
[0x18] = 0x3f,
|
||||
[0x19] = 0x3f,
|
||||
[0x1a] = 0x40,
|
||||
[0x1c] = 0x41/*0x50*/,
|
||||
[0x1c] = 0x50,
|
||||
[0x1d] = 0x42,
|
||||
[0x1e] = 0x43,
|
||||
[0x1f] = 0x44,
|
||||
|
@ -87132,7 +87132,7 @@ const struct chipinfo chipinfo_db[] = { {
|
|||
[0x18] = 0x3f,
|
||||
[0x19] = 0x3f,
|
||||
[0x1a] = 0x40,
|
||||
[0x1c] = 0x41/*0x50*/,
|
||||
[0x1c] = 0x50,
|
||||
[0x1d] = 0x42,
|
||||
[0x1e] = 0x43,
|
||||
[0x1f] = 0x44,
|
||||
|
@ -87373,7 +87373,7 @@ const struct chipinfo chipinfo_db[] = { {
|
|||
[0x18] = 0x3f,
|
||||
[0x19] = 0x3f,
|
||||
[0x1a] = 0x40,
|
||||
[0x1c] = 0x41/*0x50*/,
|
||||
[0x1c] = 0x50,
|
||||
[0x1d] = 0x42,
|
||||
[0x1e] = 0x43,
|
||||
[0x1f] = 0x44,
|
||||
|
@ -87592,7 +87592,7 @@ const struct chipinfo chipinfo_db[] = { {
|
|||
[0x18] = 0x3f,
|
||||
[0x19] = 0x3f,
|
||||
[0x1a] = 0x40,
|
||||
[0x1c] = 0x41/*0x50*/,
|
||||
[0x1c] = 0x50,
|
||||
[0x1d] = 0x42,
|
||||
[0x1e] = 0x43,
|
||||
[0x1f] = 0x44,
|
||||
|
@ -87811,7 +87811,7 @@ const struct chipinfo chipinfo_db[] = { {
|
|||
[0x18] = 0x3f,
|
||||
[0x19] = 0x3f,
|
||||
[0x1a] = 0x40,
|
||||
[0x1c] = 0x41/*0x50*/,
|
||||
[0x1c] = 0x50,
|
||||
[0x1d] = 0x42,
|
||||
[0x1e] = 0x43,
|
||||
[0x1f] = 0x44,
|
||||
|
@ -88030,7 +88030,7 @@ const struct chipinfo chipinfo_db[] = { {
|
|||
[0x18] = 0x3f,
|
||||
[0x19] = 0x3f,
|
||||
[0x1a] = 0x40,
|
||||
[0x1c] = 0x41/*0x50*/,
|
||||
[0x1c] = 0x50,
|
||||
[0x1d] = 0x42,
|
||||
[0x1e] = 0x43,
|
||||
[0x1f] = 0x44,
|
||||
|
@ -88249,7 +88249,7 @@ const struct chipinfo chipinfo_db[] = { {
|
|||
[0x18] = 0x3f,
|
||||
[0x19] = 0x3f,
|
||||
[0x1a] = 0x40,
|
||||
[0x1c] = 0x41/*0x50*/,
|
||||
[0x1c] = 0x50,
|
||||
[0x1d] = 0x42,
|
||||
[0x1e] = 0x43,
|
||||
[0x1f] = 0x44,
|
||||
|
@ -88490,7 +88490,7 @@ const struct chipinfo chipinfo_db[] = { {
|
|||
[0x18] = 0x3f,
|
||||
[0x19] = 0x3f,
|
||||
[0x1a] = 0x40,
|
||||
[0x1c] = 0x41/*0x50*/,
|
||||
[0x1c] = 0x50,
|
||||
[0x1d] = 0x42,
|
||||
[0x1e] = 0x43,
|
||||
[0x1f] = 0x44,
|
||||
|
@ -88731,7 +88731,7 @@ const struct chipinfo chipinfo_db[] = { {
|
|||
[0x18] = 0x3f,
|
||||
[0x19] = 0x3f,
|
||||
[0x1a] = 0x40,
|
||||
[0x1c] = 0x41/*0x50*/,
|
||||
[0x1c] = 0x50,
|
||||
[0x1d] = 0x42,
|
||||
[0x1e] = 0x43,
|
||||
[0x1f] = 0x44,
|
||||
|
@ -88950,7 +88950,7 @@ const struct chipinfo chipinfo_db[] = { {
|
|||
[0x18] = 0x3f,
|
||||
[0x19] = 0x3f,
|
||||
[0x1a] = 0x40,
|
||||
[0x1c] = 0x41/*0x50*/,
|
||||
[0x1c] = 0x50,
|
||||
[0x1d] = 0x42,
|
||||
[0x1e] = 0x43,
|
||||
[0x1f] = 0x44,
|
||||
|
@ -90291,7 +90291,7 @@ const struct chipinfo chipinfo_db[] = { {
|
|||
[0x18] = 0x3f,
|
||||
[0x19] = 0x3f,
|
||||
[0x1a] = 0x40,
|
||||
[0x1c] = 0x41/*0x50*/,
|
||||
[0x1c] = 0x50,
|
||||
[0x1d] = 0x42,
|
||||
[0x1e] = 0x43,
|
||||
[0x1f] = 0x44,
|
||||
|
@ -90906,7 +90906,7 @@ const struct chipinfo chipinfo_db[] = { {
|
|||
[0x18] = 0x3f,
|
||||
[0x19] = 0x3f,
|
||||
[0x1a] = 0x40,
|
||||
[0x1c] = 0x41/*0x50*/,
|
||||
[0x1c] = 0x50,
|
||||
[0x1d] = 0x42,
|
||||
[0x1e] = 0x43,
|
||||
[0x1f] = 0x44,
|
||||
|
@ -91147,7 +91147,7 @@ const struct chipinfo chipinfo_db[] = { {
|
|||
[0x18] = 0x3f,
|
||||
[0x19] = 0x3f,
|
||||
[0x1a] = 0x40,
|
||||
[0x1c] = 0x41/*0x50*/,
|
||||
[0x1c] = 0x50,
|
||||
[0x1d] = 0x42,
|
||||
[0x1e] = 0x43,
|
||||
[0x1f] = 0x44,
|
||||
|
@ -91388,7 +91388,7 @@ const struct chipinfo chipinfo_db[] = { {
|
|||
[0x18] = 0x3f,
|
||||
[0x19] = 0x3f,
|
||||
[0x1a] = 0x40,
|
||||
[0x1c] = 0x41/*0x50*/,
|
||||
[0x1c] = 0x50,
|
||||
[0x1d] = 0x42,
|
||||
[0x1e] = 0x43,
|
||||
[0x1f] = 0x44,
|
||||
|
@ -91629,7 +91629,7 @@ const struct chipinfo chipinfo_db[] = { {
|
|||
[0x18] = 0x3f,
|
||||
[0x19] = 0x3f,
|
||||
[0x1a] = 0x40,
|
||||
[0x1c] = 0x41/*0x50*/,
|
||||
[0x1c] = 0x50,
|
||||
[0x1d] = 0x42,
|
||||
[0x1e] = 0x43,
|
||||
[0x1f] = 0x44,
|
||||
|
@ -91870,7 +91870,7 @@ const struct chipinfo chipinfo_db[] = { {
|
|||
[0x18] = 0x3f,
|
||||
[0x19] = 0x3f,
|
||||
[0x1a] = 0x40,
|
||||
[0x1c] = 0x41/*0x50*/,
|
||||
[0x1c] = 0x50,
|
||||
[0x1d] = 0x42,
|
||||
[0x1e] = 0x43,
|
||||
[0x1f] = 0x44,
|
||||
|
@ -93948,7 +93948,7 @@ const struct chipinfo chipinfo_db[] = { {
|
|||
[0x18] = 0x3f,
|
||||
[0x19] = 0x3f,
|
||||
[0x1a] = 0x40,
|
||||
[0x1c] = 0x41/*0x50*/,
|
||||
[0x1c] = 0x50,
|
||||
[0x1d] = 0x42,
|
||||
[0x1e] = 0x43,
|
||||
[0x1f] = 0x44,
|
||||
|
@ -94189,7 +94189,7 @@ const struct chipinfo chipinfo_db[] = { {
|
|||
[0x18] = 0x3f,
|
||||
[0x19] = 0x3f,
|
||||
[0x1a] = 0x40,
|
||||
[0x1c] = 0x41/*0x50*/,
|
||||
[0x1c] = 0x50,
|
||||
[0x1d] = 0x42,
|
||||
[0x1e] = 0x43,
|
||||
[0x1f] = 0x44,
|
||||
|
|
|
@ -364,8 +364,7 @@ static device_t bsl_open(const struct device_args *args)
|
|||
if (args->flags & DEVICE_FLAG_TTY)
|
||||
dev->serial = comport_open(args->path, 460800);
|
||||
else
|
||||
dev->serial = ti3410_open(args->path, args->requested_serial,
|
||||
(args->flags & DEVICE_FLAG_HAS_VID_PID), args->vid, args->pid);
|
||||
dev->serial = ti3410_open(args->path, args->requested_serial);
|
||||
|
||||
if (!dev->serial) {
|
||||
free(dev);
|
||||
|
|
|
@ -75,7 +75,6 @@ struct device_breakpoint {
|
|||
#define DEVICE_FLAG_DO_FWUPDATE 0x10
|
||||
#define DEVICE_FLAG_SKIP_CLOSE 0x20
|
||||
#define DEVICE_FLAG_BSL_NME 0x40 /* BSL no-mass-erase */
|
||||
#define DEVICE_FLAG_HAS_VID_PID 0x80
|
||||
|
||||
struct device_args {
|
||||
int flags;
|
||||
|
@ -89,7 +88,6 @@ struct device_args {
|
|||
int bsl_gpio_rts;
|
||||
int bsl_gpio_dtr;
|
||||
uint8_t bsl_entry_password[32];
|
||||
uint16_t vid, pid;
|
||||
};
|
||||
|
||||
struct device_class {
|
||||
|
|
|
@ -44,11 +44,9 @@ static device_t fet_open_rf2500(const struct device_args *args)
|
|||
}
|
||||
|
||||
#if defined(__APPLE__)
|
||||
trans = rf2500hidapi_open(args->path, args->requested_serial,
|
||||
(args->flags & DEVICE_FLAG_HAS_VID_PID), args->vid, args->pid);
|
||||
trans = rf2500hidapi_open(args->path, args->requested_serial);
|
||||
#else
|
||||
trans = rf2500_open(args->path, args->requested_serial,
|
||||
(args->flags & DEVICE_FLAG_HAS_VID_PID), args->vid, args->pid);
|
||||
trans = rf2500_open(args->path, args->requested_serial);
|
||||
#endif
|
||||
if (!trans)
|
||||
return NULL;
|
||||
|
@ -81,9 +79,8 @@ static device_t fet_open_olimex_iso_mk2(const struct device_args *args)
|
|||
if (args->flags & DEVICE_FLAG_TTY)
|
||||
trans = comport_open(args->path, 115200);
|
||||
else
|
||||
trans = cdc_acm_open(args->path, args->requested_serial, 115200,
|
||||
(args->flags & DEVICE_FLAG_HAS_VID_PID) ? args->vid : 0x15ba,
|
||||
(args->flags & DEVICE_FLAG_HAS_VID_PID) ? args->pid : 0x0100);
|
||||
trans = cdc_acm_open(args->path, args->requested_serial,
|
||||
115200, 0x15ba, 0x0100);
|
||||
|
||||
if (!trans)
|
||||
return NULL;
|
||||
|
@ -103,9 +100,9 @@ static device_t fet_open_olimex_iso_mk2(const struct device_args *args)
|
|||
if (args->flags & DEVICE_FLAG_TTY)
|
||||
trans = comport_open(args->path, 115200);
|
||||
else
|
||||
trans = cdc_acm_open(args->path, args->requested_serial, 115200,
|
||||
(args->flags & DEVICE_FLAG_HAS_VID_PID) ? args->vid : 0x15ba,
|
||||
(args->flags & DEVICE_FLAG_HAS_VID_PID) ? args->pid : 0x0100);
|
||||
trans = cdc_acm_open(args->path,
|
||||
args->requested_serial,
|
||||
115200, 0x15ba, 0x0100);
|
||||
|
||||
if (!trans)
|
||||
return NULL;
|
||||
|
@ -144,9 +141,8 @@ static device_t fet_open_olimex(const struct device_args *args)
|
|||
if (args->flags & DEVICE_FLAG_TTY)
|
||||
trans = comport_open(args->path, 115200);
|
||||
else
|
||||
trans = cdc_acm_open(args->path, args->requested_serial, 115200,
|
||||
(args->flags & DEVICE_FLAG_HAS_VID_PID) ? args->vid : 0x15ba,
|
||||
(args->flags & DEVICE_FLAG_HAS_VID_PID) ? args->pid : 0x0031);
|
||||
trans = cdc_acm_open(args->path, args->requested_serial,
|
||||
115200, 0x15ba, 0x0031);
|
||||
|
||||
if (!trans)
|
||||
return NULL;
|
||||
|
@ -181,9 +177,8 @@ static device_t fet_open_olimex_v1(const struct device_args *args)
|
|||
if (args->flags & DEVICE_FLAG_TTY)
|
||||
trans = comport_open(args->path, 500000);
|
||||
else
|
||||
trans = cp210x_open(args->path, args->requested_serial, 500000,
|
||||
(args->flags & DEVICE_FLAG_HAS_VID_PID) ? args->vid : 0x15ba,
|
||||
(args->flags & DEVICE_FLAG_HAS_VID_PID) ? args->pid : 0x0002);
|
||||
trans = cp210x_open(args->path, args->requested_serial,
|
||||
500000, 0x15ba, 0x0002);
|
||||
|
||||
if (!trans)
|
||||
return NULL;
|
||||
|
@ -218,9 +213,7 @@ static device_t fet_open_olimex_iso(const struct device_args *args)
|
|||
trans = comport_open(args->path, 200000);
|
||||
else
|
||||
trans = ftdi_open(args->path, args->requested_serial,
|
||||
(args->flags & DEVICE_FLAG_HAS_VID_PID) ? args->vid : 0x15ba,
|
||||
(args->flags & DEVICE_FLAG_HAS_VID_PID) ? args->pid : 0x0008,
|
||||
200000);
|
||||
0x15ba, 0x0008, 200000);
|
||||
|
||||
if (!trans)
|
||||
return NULL;
|
||||
|
@ -255,8 +248,7 @@ static device_t fet_open_uif(const struct device_args *args)
|
|||
if (args->flags & DEVICE_FLAG_TTY)
|
||||
trans = comport_open(args->path, 460800);
|
||||
else
|
||||
trans = ti3410_open(args->path, args->requested_serial,
|
||||
(args->flags & DEVICE_FLAG_HAS_VID_PID), args->vid, args->pid);
|
||||
trans = ti3410_open(args->path, args->requested_serial);
|
||||
|
||||
if (!trans)
|
||||
return NULL;
|
||||
|
|
|
@ -31,35 +31,6 @@ void hal_proto_init(struct hal_proto *p, transport_t trans,
|
|||
p->ref_id = 0;
|
||||
}
|
||||
|
||||
static int hal_proto_send_common(struct hal_proto *p, hal_proto_type_t type,
|
||||
uint8_t* buf, size_t len)
|
||||
{
|
||||
if (len & 1)
|
||||
buf[len++] = 0;
|
||||
|
||||
if (p->flags & HAL_PROTO_CHECKSUM) {
|
||||
size_t i;
|
||||
uint8_t sum_l = 0xff;
|
||||
uint8_t sum_h = 0xff;
|
||||
|
||||
for (i = 0; i < len; i += 2) {
|
||||
sum_l ^= buf[i];
|
||||
sum_h ^= buf[i + 1];
|
||||
}
|
||||
|
||||
buf[len++] = sum_l;
|
||||
buf[len++] = sum_h;
|
||||
}
|
||||
|
||||
if (p->trans->ops->send(p->trans, buf, len) < 0) {
|
||||
printc_err("hal_proto_send_common: type: 0x%02x\n", type);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int hal_proto_send(struct hal_proto *p, hal_proto_type_t type,
|
||||
const uint8_t *data, int length)
|
||||
{
|
||||
|
@ -81,35 +52,31 @@ int hal_proto_send(struct hal_proto *p, hal_proto_type_t type,
|
|||
memcpy(buf + len, data, length);
|
||||
len += length;
|
||||
|
||||
return hal_proto_send_common(p, type, buf, len);
|
||||
}
|
||||
if (len & 1)
|
||||
buf[len++] = 0;
|
||||
|
||||
if (p->flags & HAL_PROTO_CHECKSUM) {
|
||||
size_t i;
|
||||
uint8_t sum_l = 0xff;
|
||||
uint8_t sum_h = 0xff;
|
||||
|
||||
static int hal_proto_send_ack(struct hal_proto *p, hal_proto_type_t type,
|
||||
const uint8_t *data, int length)
|
||||
{
|
||||
uint8_t buf[512];
|
||||
size_t len = 0;
|
||||
for (i = 0; i < len; i += 2) {
|
||||
sum_l ^= buf[i];
|
||||
sum_h ^= buf[i + 1];
|
||||
}
|
||||
|
||||
if (length > HAL_MAX_PAYLOAD) {
|
||||
printc_err("hal_proto_send_ack: payload too long: %d\n", length);
|
||||
buf[len++] = sum_l;
|
||||
buf[len++] = sum_h;
|
||||
}
|
||||
|
||||
if (p->trans->ops->send(p->trans, buf, len) < 0) {
|
||||
printc_err("hal_proto_send: type: 0x%02x\n", type);
|
||||
return -1;
|
||||
}
|
||||
|
||||
buf[len++] = length + 3;
|
||||
buf[len++] = type;
|
||||
buf[len++] = (p->ref_id - 1) & 0xff;
|
||||
buf[len++] = 0;
|
||||
|
||||
/*p->ref_id = (p->ref_id + 1) & 0x7f;*/
|
||||
|
||||
memcpy(buf + len, data, length);
|
||||
len += length;
|
||||
|
||||
return hal_proto_send_common(p, type, buf, len);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int hal_proto_receive(struct hal_proto *p, uint8_t *buf, int max_len)
|
||||
{
|
||||
uint8_t rx_buf[512];
|
||||
|
@ -180,8 +147,7 @@ int hal_proto_execute(struct hal_proto *p, uint8_t fid,
|
|||
uint8_t fdata[HAL_MAX_PAYLOAD];
|
||||
|
||||
if (len + 2 > HAL_MAX_PAYLOAD) {
|
||||
printc_err("hal_proto_execute: fid 0x%02x: payload too big: %d\n",
|
||||
fid, len);
|
||||
printc_err("hal_proto_execute: payload too big: %d\n", len);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -202,8 +168,8 @@ int hal_proto_execute(struct hal_proto *p, uint8_t fid,
|
|||
goto fail;
|
||||
|
||||
if ((p->type == HAL_PROTO_TYPE_EXCEPTION) && (r >= 2)) {
|
||||
printc_err("hal_proto_execute: fid 0x%02x: HAL exception: 0x%04x\n",
|
||||
fid, LE_WORD(p->payload, p->length));
|
||||
printc_err("hal_proto_execute: HAL exception: 0x%04x\n",
|
||||
LE_WORD(p->payload, p->length));
|
||||
goto fail;
|
||||
}
|
||||
|
||||
|
@ -211,12 +177,12 @@ int hal_proto_execute(struct hal_proto *p, uint8_t fid,
|
|||
break;
|
||||
|
||||
if (p->type != HAL_PROTO_TYPE_DATA) {
|
||||
printc_err("hal_proto_execute: fid 0x%02x: no data "
|
||||
"(got type 0x%02x)\n", fid, p->type);
|
||||
printc_err("hal_proto_execute: no data "
|
||||
"(got type 0x%02x)\n", p->type);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (hal_proto_send_ack(p, HAL_PROTO_TYPE_ACKNOWLEDGE, NULL, 0) < 0)
|
||||
if (hal_proto_send(p, HAL_PROTO_TYPE_ACKNOWLEDGE, NULL, 0) < 0)
|
||||
goto fail;
|
||||
|
||||
p->length += r;
|
||||
|
@ -225,6 +191,6 @@ int hal_proto_execute(struct hal_proto *p, uint8_t fid,
|
|||
return 0;
|
||||
|
||||
fail:
|
||||
printc_err("hal_proto_execute: fid: 0x%02x: failed\n", fid);
|
||||
printc_err("hal_proto_execute: fid: 0x%02x\n", fid);
|
||||
return -1;
|
||||
}
|
||||
|
|
|
@ -37,11 +37,6 @@ typedef enum {
|
|||
HAL_PROTO_TYPE_DCDC_POWER_DOWN = 0x60,
|
||||
HAL_PROTO_TYPE_DCDC_SET_VCC = 0x61,
|
||||
HAL_PROTO_TYPE_DCDC_RESTART = 0x62,
|
||||
HAL_PROTO_TYPE_CORE_SET_VCC = 0x63,
|
||||
HAL_PROTO_TYPE_CORE_GET_VCC = 0x64,
|
||||
HAL_PROTO_TYPE_CORE_SWITCH_FET = 0x65,
|
||||
HAL_PROTO_TYPE_CMP_VERSIONS = 0x66,
|
||||
|
||||
HAL_PROTO_TYPE_CMD_LEGACY = 0x7e,
|
||||
HAL_PROTO_TYPE_CMD_SYNC = 0x80,
|
||||
HAL_PROTO_TYPE_CMD_EXECUTE = 0x81,
|
||||
|
@ -57,9 +52,6 @@ typedef enum {
|
|||
HAL_PROTO_TYPE_CMD_COM_RESET = 0x8b,
|
||||
HAL_PROTO_TYPE_CMD_PAUSE_LOOP = 0x8c,
|
||||
HAL_PROTO_TYPE_CMD_RESUME_LOOP = 0x8d,
|
||||
HAL_PROTO_TYPE_CMD_KILL_ALL = 0x8e,
|
||||
HAL_PROTO_TYPE_CMD_OVER_CURRENT = 0x8f,
|
||||
|
||||
HAL_PROTO_TYPE_ACKNOWLEDGE = 0x91,
|
||||
HAL_PROTO_TYPE_EXCEPTION = 0x92,
|
||||
HAL_PROTO_TYPE_DATA = 0x93,
|
||||
|
@ -71,121 +63,6 @@ typedef enum {
|
|||
HAL_PROTO_CHECKSUM = 0x01
|
||||
} hal_proto_flags_t;
|
||||
|
||||
typedef enum {
|
||||
HAL_PROTO_ERR_NONE = 0x00,
|
||||
HAL_PROTO_ERR_UNDEFINED = 0xffff,
|
||||
|
||||
HAL_PROTO_ERR_EXECUTE_FUNCLET_NO_RAM_START = 0xFFFE,
|
||||
HAL_PROTO_ERR_EXECUTE_FUNCLET_NO_RAM_SIZE = 0xFFFD,
|
||||
HAL_PROTO_ERR_EXECUTE_FUNCLET_NO_OFFSET = 0xFFFC,
|
||||
HAL_PROTO_ERR_EXECUTE_FUNCLET_NO_ADDRESS = 0xFFFB,
|
||||
HAL_PROTO_ERR_EXECUTE_FUNCLET_NO_LENGTH = 0xFFFA,
|
||||
HAL_PROTO_ERR_EXECUTE_FUNCLET_NO_TYPE = 0xFFF9,
|
||||
HAL_PROTO_ERR_EXECUTE_FUNCLET_NO_LOCKA = 0xFFF8,
|
||||
HAL_PROTO_ERR_EXECUTE_FUNCLET_EXECUTION_TIMEOUT = 0xFFF7,
|
||||
HAL_PROTO_ERR_EXECUTE_FUNCLET_EXECUTION_ERROR = 0xFFF6,
|
||||
|
||||
HAL_PROTO_ERR_WRITE_MEM_WORD_NO_RAM_ADDRESS = 0xFFF5,
|
||||
HAL_PROTO_ERR_WRITE_MEM_WORD_NO_RAM_SIZE = 0xFFF4,
|
||||
HAL_PROTO_ERR_WRITE_MEM_WORD_UNKNOWN = 0xFFF3,
|
||||
|
||||
HAL_PROTO_ERR_WRITE_MEM_BYTES_NO_RAM_ADDRESS = 0xFFF2,
|
||||
HAL_PROTO_ERR_WRITE_MEM_BYTES_NO_RAM_SIZE = 0xFFF1,
|
||||
HAL_PROTO_ERR_WRITE_MEM_BYTES_UNKNOWN = 0xFFF0,
|
||||
|
||||
HAL_PROTO_ERR_WRITE_FLASH_WORD_NO_FLASH_ADDRESS = 0xFFEF,
|
||||
HAL_PROTO_ERR_WRITE_FLASH_WORD_NO_FLASH_SIZE = 0xFFEE,
|
||||
HAL_PROTO_ERR_WRITE_FLASH_WORD_UNKNOWN = 0xFFED,
|
||||
|
||||
HAL_PROTO_ERR_WRITE_FLASH_QUICK_UNKNOWN = 0xFFEC,
|
||||
|
||||
HAL_PROTO_ERR_START_JTAG_NO_PROTOCOL = 0xFFEB,
|
||||
HAL_PROTO_ERR_START_JTAG_PROTOCOL_UNKNOWN = 0xFFEA,
|
||||
|
||||
HAL_PROTO_ERR_SET_CHAIN_CONFIGURATION_STREAM = 0xFFE9,
|
||||
|
||||
HAL_PROTO_ERR_RESTORECONTEXT_RELEASE_JTAG_NO_WDT_ADDRESS = 0xFFE8,
|
||||
HAL_PROTO_ERR_RESTORECONTEXT_RELEASE_JTAG_NO_WDT_VALUE = 0xFFE7,
|
||||
HAL_PROTO_ERR_RESTORECONTEXT_RELEASE_JTAG_NO_PC = 0xFFE6,
|
||||
HAL_PROTO_ERR_RESTORECONTEXT_RELEASE_JTAG_NO_SR = 0xFFE5,
|
||||
HAL_PROTO_ERR_RESTORECONTEXT_RELEASE_JTAG_NO_CONTROL_MASK = 0xFFE4,
|
||||
HAL_PROTO_ERR_RESTORECONTEXT_RELEASE_JTAG_NO_MDB = 0xFFE3,
|
||||
|
||||
HAL_PROTO_ERR_READ_MEM_WORD_NO_ADDRESS = 0xFFF2,
|
||||
HAL_PROTO_ERR_READ_MEM_WORD_NO_SIZE = 0xFFF1,
|
||||
|
||||
HAL_PROTO_ERR_READ_MEM_UNKNOWN = 0xFFE0,
|
||||
|
||||
HAL_PROTO_ERR_READ_MEM_BYTES_NO_ADDRESS = 0xFFDF,
|
||||
HAL_PROTO_ERR_READ_MEM_BYTES_NO_SIZE = 0xFFDE,
|
||||
|
||||
HAL_PROTO_ERR_PSA_NO_ADDRESS = 0xFFDD,
|
||||
HAL_PROTO_ERR_PSA_NO_SIZE = 0xFFDC,
|
||||
|
||||
HAL_PROTO_ERR_SYNC_JTAG_ASSERT_POR_JTAG_TIMEOUT = 0xFFDB,
|
||||
HAL_PROTO_ERR_SYNC_JTAG_ASSERT_POR_NO_WDT_ADDRESS = 0xFFDA,
|
||||
HAL_PROTO_ERR_SYNC_JTAG_ASSERT_POR_NO_WDT_VALUE = 0xFFD9,
|
||||
|
||||
HAL_PROTO_ERR_WRITE_ALL_CPU_REGISTERS_STREAM = 0xFFD8,
|
||||
|
||||
HAL_PROTO_ERR_WRITE_MEM_WORD_XV2_NO_RAM_ADDRESS = 0xFFD7,
|
||||
HAL_PROTO_ERR_WRITE_MEM_WORD_XV2_NO_RAM_SIZE = 0xFFD6,
|
||||
|
||||
HAL_PROTO_ERR_SECURE_NO_TGT_HAS_TEST_PIN = 0xFFD5,
|
||||
|
||||
HAL_PROTO_ERR_SYNC_JTAG_CONDITIONAL_JTAG_TIMEOUT = 0xFFD4,
|
||||
HAL_PROTO_ERR_SYNC_JTAG_CONDITIONAL_NO_WDT_ADDRESS = 0xFFD3,
|
||||
HAL_PROTO_ERR_SYNC_JTAG_CONDITIONAL_NO_WDT_VALUE = 0xFFD2,
|
||||
|
||||
HAL_PROTO_ERR_INSTRUCTION_BOUNDARY_ERROR = 0xFFD1,
|
||||
HAL_PROTO_ERR_JTAG_VERSION_MISMATCH = 0xFFD0,
|
||||
|
||||
HAL_PROTO_ERR_JTAG_MAILBOX_IN_TIMOUT = 0xFFCF,
|
||||
HAL_PROTO_ERR_JTAG_PASSWORD_WRONG = 0xFFCE,
|
||||
|
||||
HAL_PROTO_ERR_START_JTAG_NO_ACTIVATION_CODE = 0xFFCD,
|
||||
HAL_PROTO_ERR_SINGLESTEP_WAITFOREEM_TIMEOUT = 0xFFCC,
|
||||
|
||||
HAL_PROTO_ERR_CONFIG_NO_PARAMETER = 0xFFCB,
|
||||
HAL_PROTO_ERR_CONFIG_NO_VALUE = 0xFFCA,
|
||||
HAL_PROTO_ERR_CONFIG_PARAM_UNKNOWN_PARAMETER = 0xFFC9,
|
||||
|
||||
HAL_PROTO_ERR_NO_NUM_BITS = 0xFFC8,
|
||||
HAL_PROTO_ERR_ARRAY_SIZE_MISMATCH = 0xFFC7,
|
||||
|
||||
HAL_PROTO_ERR_NO_COMMAND = 0xFFC6,
|
||||
HAL_PROTO_ERR_UNKNOWN_COMMAND = 0xFFC5,
|
||||
HAL_PROTO_ERR_NO_DATA = 0xFFC4,
|
||||
HAL_PROTO_ERR_NO_BIT_SIZE = 0xFFC3,
|
||||
HAL_PROTO_ERR_INVALID_BIT_SIZE = 0xFFC2,
|
||||
|
||||
HAL_PROTO_ERR_UNLOCK_NO_PASSWORD_LENGTH = 0xFFC1,
|
||||
HAL_PROTO_ERR_UNLOCK_INVALID_PASSWORD_LENGTH = 0xFFC0,
|
||||
|
||||
HAL_PROTO_ERR_EXECUTE_FUNCLET_FINISH_TIMEOUT = 0xFFBF,
|
||||
|
||||
HAL_PROTO_ERR_EXECUTE_FUNCLET_NO_MAXRSEL = 0xFFBE,
|
||||
|
||||
HAL_PROTO_ERR_API_CALL_NOT_SUPPORTED = 0xFFBD,
|
||||
|
||||
HAL_PROTO_ERR_MAGIC_PATTERN = 0xFFBC,
|
||||
HAL_PROTO_ERR_MAGIC_PATTERN_BOOT_DATA_CRC_WRONG = 0xFFBB,
|
||||
HAL_PROTO_ERR_DAP_NACK = 0xFFBA,
|
||||
|
||||
HAL_PROTO_MESSAGE_NO_RESPONSE = 0x8000,
|
||||
HAL_PROTO_EXCEPTION_NOT_IMPLEMENT_ERR = 0x8001,
|
||||
HAL_PROTO_EXCEPTION_MSGID_ERR = 0x8002,
|
||||
HAL_PROTO_EXCEPTION_CRC_ERR = 0x8003,
|
||||
HAL_PROTO_EXCEPTION_RX_TIMEOUT_ERR = 0x8004,
|
||||
HAL_PROTO_EXCEPTION_TX_TIMEOUT_ERR = 0x8005,
|
||||
HAL_PROTO_EXCEPTION_RX_OVERFLOW_ERR = 0x8006,
|
||||
HAL_PROTO_EXCEPTION_TX_NO_BUFFER = 0x8007,
|
||||
HAL_PROTO_EXCEPTION_COM_RESET = 0x8008,
|
||||
HAL_PROTO_EXCEPTION_RX_NO_BUFFER = 0x8009,
|
||||
HAL_PROTO_EXCEPTION_RX_TO_SMALL_BUFFER = 0x800A,
|
||||
HAL_PROTO_EXCEPTION_RX_LENGTH = 0x800B,
|
||||
} hal_proto_error_t;
|
||||
|
||||
#define HAL_MAX_PAYLOAD 253
|
||||
|
||||
struct hal_proto {
|
||||
|
|
1607
drivers/jtaglib.c
1607
drivers/jtaglib.c
File diff suppressed because it is too large
Load Diff
|
@ -34,56 +34,15 @@
|
|||
#ifndef JTAGLIB_H_
|
||||
#define JTAGLIB_H_
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "device.h"
|
||||
#include "jtdev.h"
|
||||
#include "util.h"
|
||||
|
||||
/* Colleciton of functions that need different implementation for different
|
||||
* CPU types (that is, 16-bit vs CPUX vs Xv2) */
|
||||
struct jtaglib_funcs {
|
||||
unsigned int (*jlf_get_device)(struct jtdev *p);
|
||||
|
||||
uint16_t (*jlf_read_mem)(struct jtdev *p, unsigned int format, address_t address);
|
||||
void (*jlf_read_mem_quick)(struct jtdev *p, address_t start_address,
|
||||
unsigned int word_count, uint16_t* data);
|
||||
void (*jlf_write_mem)(struct jtdev *p, unsigned int format,
|
||||
address_t address, uint16_t data);
|
||||
void (*jlf_write_mem_quick)(struct jtdev *p, address_t start_address,
|
||||
unsigned int word_count, const uint16_t* data);
|
||||
|
||||
unsigned int (*jlf_execute_puc)(struct jtdev *p);
|
||||
void (*jlf_release_device)(struct jtdev *p, address_t address);
|
||||
|
||||
int (*jlf_verify_mem)(struct jtdev *p, address_t start_address,
|
||||
unsigned int length, const uint16_t *data);
|
||||
int (*jlf_erase_check)(struct jtdev *p, address_t start_address,
|
||||
unsigned int length);
|
||||
|
||||
void (*jlf_write_flash)(struct jtdev *p, address_t start_address,
|
||||
unsigned int word_count, const uint16_t *data);
|
||||
void (*jlf_erase_flash)(struct jtdev *p, unsigned int erase_mode,
|
||||
address_t erase_address);
|
||||
|
||||
address_t (*jlf_read_reg)(struct jtdev *p, int reg);
|
||||
void (*jlf_write_reg)(struct jtdev *p, int reg, address_t value);
|
||||
void (*jlf_single_step)(struct jtdev *p);
|
||||
unsigned int (*jlf_set_breakpoint)(struct jtdev *p, int bp_num,
|
||||
address_t bp_addr);
|
||||
unsigned int (*jlf_cpu_state)(struct jtdev *p);
|
||||
int (*jlf_get_config_fuses)(struct jtdev *p);
|
||||
|
||||
void (*jlf_context_save)(struct jtdev *p, bool after_puc);
|
||||
void (*jlf_context_restore)(struct jtdev *p);
|
||||
void (*jlf_regs_update)(struct jtdev *p);
|
||||
void (*jlf_regs_flush)(struct jtdev *p);
|
||||
};
|
||||
|
||||
extern const struct jtaglib_funcs jlf_cpu16;
|
||||
extern const struct jtaglib_funcs jlf_cpux;
|
||||
extern const struct jtaglib_funcs jlf_cpuxv2;
|
||||
/* Flash erasing modes */
|
||||
#define JTAG_ERASE_MASS 0xA506
|
||||
#define JTAG_ERASE_MAIN 0xA504
|
||||
#define JTAG_ERASE_SGMT 0xA502
|
||||
|
||||
/* Take target device under JTAG control. */
|
||||
unsigned int jtag_init(struct jtdev *p);
|
||||
|
@ -158,35 +117,4 @@ unsigned int jtag_set_breakpoint(struct jtdev *p,
|
|||
unsigned int jtag_cpu_state(struct jtdev *p);
|
||||
int jtag_get_config_fuses(struct jtdev *p);
|
||||
|
||||
void jtag_dev_context_save(struct jtdev *p, bool after_puc);
|
||||
void jtag_dev_context_restore(struct jtdev *p);
|
||||
void jtag_dev_regs_update(struct jtdev *p);
|
||||
void jtag_dev_regs_flush(struct jtdev *p);
|
||||
|
||||
/* Default low-level JTAG routines for jtdev implementations that don't have
|
||||
* their own implementations of these routines */
|
||||
uint8_t jtag_default_ir_shift(struct jtdev *p, uint8_t ir);
|
||||
uint8_t jtag_default_dr_shift_8(struct jtdev *p, uint8_t dr);
|
||||
uint16_t jtag_default_dr_shift_16(struct jtdev *p, uint16_t dr);
|
||||
uint32_t jtag_default_dr_shift_20(struct jtdev *p, uint32_t dr);
|
||||
void jtag_default_tms_sequence(struct jtdev *p, int bits, unsigned int value);
|
||||
void jtag_default_init_dap(struct jtdev *p);
|
||||
|
||||
void jtag_dev_default_context_save(struct jtdev *p, bool after_puc);
|
||||
void jtag_dev_default_context_restore(struct jtdev *p);
|
||||
void jtag_dev_default_regs_update(struct jtdev *p);
|
||||
void jtag_dev_default_regs_flush(struct jtdev *p);
|
||||
|
||||
int jtag_refresh_bps(device_t dev, struct jtdev *p);
|
||||
|
||||
int jtag_dev_readmem(device_t dev_base, address_t addr, uint8_t *mem, address_t len);
|
||||
int jtag_dev_writemem(device_t dev_base, address_t addr, const uint8_t *mem, address_t len);
|
||||
int jtag_dev_getregs(device_t dev_base, address_t *regs);
|
||||
int jtag_dev_setregs(device_t dev_base, const address_t *regs);
|
||||
int jtag_dev_ctl(device_t dev_base, device_ctl_t type);
|
||||
device_status_t jtag_dev_poll(device_t dev_base);
|
||||
int jtag_dev_erase(device_t dev_base, device_erase_type_t, address_t addr);
|
||||
int jtag_dev_getconfigfuses(device_t dev_base);
|
||||
int jtag_dev_init(struct jtdev *p);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,883 +0,0 @@
|
|||
|
||||
#include "jtaglib.h"
|
||||
#include "jtaglib_defs.h"
|
||||
#include "output.h"
|
||||
|
||||
#ifdef DEBUG_JTAGLIB
|
||||
#define dbg_printc(fmt, ...) printc_dbg("jlf16: %s:%d " fmt, __func__, __LINE__, ##__VA_ARGS__)
|
||||
#else
|
||||
#define dbg_printc(fmt, ...) do{}while(0)
|
||||
#endif
|
||||
|
||||
/* Set target CPU JTAG state machine into the instruction fetch state
|
||||
* return: 1 - instruction fetch was set
|
||||
* 0 - otherwise
|
||||
*/
|
||||
static int jlf16_set_instruction_fetch(struct jtdev *p)
|
||||
{ // SLAU320AJ name: SetInstrFetch / SyncJtag?
|
||||
unsigned int loop_counter;
|
||||
|
||||
// SyncJtag: has CTLR_SIG_16BIT=0x2401 here
|
||||
|
||||
jtag_ir_shift(p, IR_CNTRL_SIG_CAPTURE);
|
||||
/* Wait until CPU is in instruction fetch state
|
||||
* timeout after limited attempts
|
||||
*/
|
||||
for (loop_counter = 50; loop_counter > 0; loop_counter--) {
|
||||
if ((jtag_dr_shift_16(p, 0x0000) & 0x0080) == 0x0080)
|
||||
return 1;
|
||||
|
||||
jtag_tclk_clr(p); /* The TCLK pulse befor jtag_dr_shift_16 leads to */
|
||||
jtag_tclk_set(p); /* problems at MEM_QUICK_READ, it's from SLAU265 */
|
||||
}
|
||||
|
||||
printc_err("jlf16_set_instruction_fetch: failed\n");
|
||||
p->failed = 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Set the CPU into a controlled stop state */
|
||||
static void jlf16_halt_cpu(struct jtdev *p)
|
||||
{ // SLAU320AJ name: HaltCPU
|
||||
/* Set CPU into instruction fetch mode */
|
||||
dbg_printc("halt cpu\n");
|
||||
|
||||
jlf16_set_instruction_fetch(p);
|
||||
|
||||
/* Set device into JTAG mode + read */
|
||||
jtag_ir_shift(p, IR_CNTRL_SIG_16BIT);
|
||||
jtag_dr_shift_16(p, 0x2401);
|
||||
|
||||
/* Send JMP $ instruction to keep CPU from changing the state */
|
||||
jtag_ir_shift(p, IR_DATA_16BIT);
|
||||
jtag_dr_shift_16(p, 0x3FFF);
|
||||
jtag_tclk_set(p); // TODO: ???
|
||||
jtag_tclk_clr(p);
|
||||
|
||||
/* Set JTAG_HALT bit */
|
||||
jtag_ir_shift(p, IR_CNTRL_SIG_16BIT);
|
||||
jtag_dr_shift_16(p, 0x2409);
|
||||
jtag_tclk_set(p);
|
||||
}
|
||||
|
||||
/* Release the target CPU from the controlled stop state */
|
||||
static void jlf16_release_cpu(struct jtdev *p)
|
||||
{ // SLAU320AJ name: ReleaseCPU
|
||||
dbg_printc("release cpu\n");
|
||||
|
||||
jtag_tclk_clr(p);
|
||||
|
||||
/* clear the HALT_JTAG bit */
|
||||
jtag_ir_shift(p, IR_CNTRL_SIG_16BIT);
|
||||
jtag_dr_shift_16(p, 0x2401);
|
||||
jtag_ir_shift(p, IR_ADDR_CAPTURE);
|
||||
jtag_tclk_set(p);
|
||||
}
|
||||
|
||||
/* Compares the computed PSA (Pseudo Signature Analysis) value to the PSA
|
||||
* value shifted out from the target device. It is used for very fast data
|
||||
* block write or erasure verification.
|
||||
* start_address: start of data
|
||||
* length : number of data
|
||||
* data : pointer to data, 0 for erase check
|
||||
* RETURN : 1 - comparison was successful
|
||||
* 0 - otherwise
|
||||
*/
|
||||
static int jlf16_verify_mem(struct jtdev *p,
|
||||
unsigned int start_address,
|
||||
unsigned int length,
|
||||
const uint16_t *data)
|
||||
{ // SLAU320AJ name: VerifyMem/VerifyPSA
|
||||
unsigned int psa_value;
|
||||
unsigned int index;
|
||||
|
||||
/* Polynom value for PSA calculation */
|
||||
unsigned int polynom = 0x0805;
|
||||
/* Start value for PSA calculation */
|
||||
unsigned int psa_crc = start_address-2;
|
||||
|
||||
dbg_printc("verify: %04x..%04x\n", start_address, start_address+length*2);
|
||||
|
||||
jtag_execute_puc(p);
|
||||
jtag_ir_shift(p, IR_CNTRL_SIG_16BIT);
|
||||
jtag_dr_shift_16(p, 0x2401);
|
||||
jlf16_set_instruction_fetch(p);
|
||||
jtag_ir_shift(p, IR_DATA_16BIT);
|
||||
jtag_dr_shift_16(p, 0x4030);
|
||||
jtag_tclk_set(p);
|
||||
jtag_tclk_clr(p);
|
||||
jtag_dr_shift_16(p, start_address-2);
|
||||
jtag_tclk_set(p);
|
||||
jtag_tclk_clr(p);
|
||||
jtag_tclk_set(p);
|
||||
jtag_tclk_clr(p);
|
||||
jtag_tclk_set(p);
|
||||
jtag_tclk_clr(p);
|
||||
jtag_ir_shift(p, IR_ADDR_CAPTURE);
|
||||
jtag_dr_shift_16(p, 0x0000);
|
||||
jtag_ir_shift(p, IR_DATA_PSA);
|
||||
|
||||
for (index = 0; index < length; index++) {
|
||||
/* Calculate the PSA value */
|
||||
if ((psa_crc & 0x8000) == 0x8000) {
|
||||
psa_crc ^= polynom;
|
||||
psa_crc <<= 1;
|
||||
psa_crc |= 0x0001;
|
||||
} else
|
||||
psa_crc <<= 1;
|
||||
|
||||
if (data == 0)
|
||||
/* use erase check mask */
|
||||
psa_crc ^= 0xFFFF;
|
||||
else
|
||||
/* use data */
|
||||
psa_crc ^= data[index];
|
||||
|
||||
/* Clock through the PSA */
|
||||
jtag_tclk_set(p);
|
||||
|
||||
/* Go through DR path without shifting data in/out */
|
||||
jtag_tms_sequence(p, 6, 0x19); /* TMS=1 0 0 1 1 0 ; 6 clocks */
|
||||
|
||||
jtag_tclk_clr(p);
|
||||
}
|
||||
|
||||
/* Read out the PSA value */
|
||||
jtag_ir_shift(p, IR_SHIFT_OUT_PSA);
|
||||
psa_value = jtag_dr_shift_16(p, 0x0000);
|
||||
jtag_tclk_set(p);
|
||||
|
||||
return (psa_value == psa_crc) ? 1 : 0;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
static int jlf16_erase_check(struct jtdev *p, unsigned int start_address,
|
||||
unsigned int length)
|
||||
{
|
||||
return jlf16_verify_mem(p, start_address, length, NULL);
|
||||
}
|
||||
|
||||
static unsigned int jlf16_get_device(struct jtdev *p)
|
||||
{ // SLAU320AJ name: GetDevice
|
||||
unsigned int jtag_id = 0;
|
||||
unsigned int loop_counter;
|
||||
|
||||
/* Set device into JTAG mode + read */
|
||||
jtag_ir_shift(p, IR_CNTRL_SIG_16BIT);
|
||||
jtag_dr_shift_16(p, 0x2401);
|
||||
|
||||
/* Wait until CPU is synchronized,
|
||||
* timeout after a limited number of attempts
|
||||
*/
|
||||
jtag_id = jtag_ir_shift(p, IR_CNTRL_SIG_CAPTURE);
|
||||
for ( loop_counter = 50; loop_counter > 0; loop_counter--) {
|
||||
if ( (jtag_dr_shift_16(p, 0x0000) & 0x0200) == 0x0200 ) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
dbg_printc("get device: jtag id=%02x\n", jtag_id);
|
||||
|
||||
if (loop_counter == 0) {
|
||||
printc_err("jlf16_get_device: timed out\n");
|
||||
p->failed = 1;
|
||||
/* timeout reached */
|
||||
return 0;
|
||||
}
|
||||
|
||||
return jtag_id;
|
||||
}
|
||||
|
||||
/* Reads one byte/word from a given address
|
||||
* format : 8-byte, 16-word
|
||||
* address: address of memory
|
||||
* return : content of memory
|
||||
*/
|
||||
static uint16_t jlf16_read_mem(struct jtdev *p, unsigned int format, address_t address)
|
||||
{ // SLAU320AJ name: ReadMem
|
||||
uint16_t content;
|
||||
|
||||
dbg_printc("%dbit %04x\n", format, address);
|
||||
|
||||
jlf16_halt_cpu(p);
|
||||
jtag_tclk_clr(p);
|
||||
jtag_ir_shift(p, IR_CNTRL_SIG_16BIT);
|
||||
if (format == 16) {
|
||||
/* set word read */
|
||||
jtag_dr_shift_16(p, 0x2409);
|
||||
} else {
|
||||
/* set byte read */
|
||||
jtag_dr_shift_16(p, 0x2419);
|
||||
}
|
||||
/* set address */
|
||||
jtag_ir_shift(p, IR_ADDR_16BIT);
|
||||
jtag_dr_shift_16(p, address);
|
||||
jtag_ir_shift(p, IR_DATA_TO_ADDR);
|
||||
jtag_tclk_set(p);
|
||||
jtag_tclk_clr(p);
|
||||
|
||||
/* shift out 16 bits */
|
||||
content = jtag_dr_shift_16(p, 0x0000);
|
||||
jtag_tclk_set(p); /* is also the first instruction in jtag_release_cpu() */
|
||||
jlf16_release_cpu(p);
|
||||
if (format == 8)
|
||||
content &= 0x00ff;
|
||||
|
||||
dbg_printc("%dbit %04x -> %04x\n", format, address, content);
|
||||
|
||||
return content;
|
||||
}
|
||||
|
||||
/* Reads an array of words from target memory
|
||||
* address: address to read from
|
||||
* length : number of word to read
|
||||
* data : memory to write to
|
||||
*/
|
||||
static void jlf16_read_mem_quick(struct jtdev *p, address_t address,
|
||||
unsigned int length, uint16_t *data)
|
||||
{ // SLAU320AJ name: ReadMemQuick
|
||||
unsigned int index;
|
||||
address_t pc_bak;
|
||||
|
||||
dbg_printc("%04x..%04x\n", address, address+length*2);
|
||||
|
||||
pc_bak = jtag_read_reg(p, 0);
|
||||
|
||||
/* Initialize reading: */
|
||||
jtag_write_reg(p, 0, address-4);
|
||||
jlf16_halt_cpu(p);
|
||||
jtag_tclk_clr(p);
|
||||
|
||||
/* set RW to read */
|
||||
jtag_ir_shift(p, IR_CNTRL_SIG_16BIT);
|
||||
jtag_dr_shift_16(p, 0x2409);
|
||||
jtag_ir_shift(p, IR_DATA_QUICK);
|
||||
|
||||
for (index = 0; index < length; index++) {
|
||||
jtag_tclk_set(p);
|
||||
jtag_tclk_clr(p); // TODO: ???
|
||||
/* shift out the data from the target */
|
||||
data[index] = jtag_dr_shift_16(p, 0x0000);
|
||||
//jtag_tclk_clr(p); // TODO: ???
|
||||
}
|
||||
|
||||
jtag_tclk_set(p);
|
||||
jlf16_release_cpu(p);
|
||||
jtag_write_reg(p, 0, pc_bak);
|
||||
}
|
||||
|
||||
/* Writes one byte/word at a given address
|
||||
* format : 8-byte, 16-word
|
||||
* address: address to be written
|
||||
* data : data to write
|
||||
*/
|
||||
static void jlf16_write_mem(struct jtdev *p, unsigned int format,
|
||||
address_t address, uint16_t data)
|
||||
{ // SLAU320AJ name: WriteMem
|
||||
dbg_printc("%dbit %04x <- %04x\n", format, address, data);
|
||||
|
||||
jlf16_halt_cpu(p);
|
||||
jtag_tclk_clr(p);
|
||||
jtag_ir_shift(p, IR_CNTRL_SIG_16BIT);
|
||||
|
||||
if (format == 16)
|
||||
/* Set word write */
|
||||
jtag_dr_shift_16(p, 0x2408);
|
||||
else
|
||||
/* Set byte write */
|
||||
jtag_dr_shift_16(p, 0x2418);
|
||||
|
||||
jtag_ir_shift(p, IR_ADDR_16BIT);
|
||||
|
||||
/* Set addr */
|
||||
jtag_dr_shift_16(p, address);
|
||||
jtag_ir_shift(p, IR_DATA_TO_ADDR);
|
||||
|
||||
/* Shift in 16 bits */
|
||||
jtag_dr_shift_16(p, data);
|
||||
jtag_tclk_set(p);
|
||||
jlf16_release_cpu(p);
|
||||
}
|
||||
|
||||
/* Writes an array of words into target memory
|
||||
* address: address to write to
|
||||
* length : number of word to write
|
||||
* data : data to write
|
||||
*/
|
||||
static void jlf16_write_mem_quick(struct jtdev *p, address_t address,
|
||||
unsigned int length, const uint16_t *data)
|
||||
{ // SLAU320AJ name: WriteMemQuick
|
||||
unsigned int index;
|
||||
|
||||
dbg_printc("%04x..%04x\n", address, address+length*2);
|
||||
|
||||
/* Initialize writing */
|
||||
jtag_write_reg(p, 0, address-4);
|
||||
jlf16_halt_cpu(p);
|
||||
jtag_tclk_clr(p);
|
||||
jtag_ir_shift(p, IR_CNTRL_SIG_16BIT);
|
||||
|
||||
/* Set RW to write */
|
||||
jtag_dr_shift_16(p, 0x2408);
|
||||
jtag_ir_shift(p, IR_DATA_QUICK);
|
||||
// TODO: ^ in start of loop?
|
||||
|
||||
for (index = 0; index < length; index++) {
|
||||
/* Write data */
|
||||
jtag_dr_shift_16(p, data[index]);
|
||||
|
||||
/* Increment PC by 2 */
|
||||
jtag_tclk_set(p);
|
||||
jtag_tclk_clr(p);
|
||||
}
|
||||
|
||||
jtag_tclk_set(p);
|
||||
jlf16_release_cpu(p);
|
||||
}
|
||||
|
||||
/* Execute a Power-Up Clear (PUC) using JTAG CNTRL SIG register
|
||||
* return: JTAG ID
|
||||
*/
|
||||
static unsigned int jlf16_execute_puc(struct jtdev *p)
|
||||
{ // SLAU320AJ name: ExecutePOR
|
||||
unsigned int jtag_id;
|
||||
|
||||
dbg_printc("\n");
|
||||
|
||||
jtag_ir_shift(p, IR_CNTRL_SIG_16BIT);
|
||||
|
||||
/* Apply and remove reset */
|
||||
jtag_dr_shift_16(p, 0x2C01);
|
||||
jtag_dr_shift_16(p, 0x2401);
|
||||
jtag_tclk_clr(p);
|
||||
jtag_tclk_set(p);
|
||||
jtag_tclk_clr(p);
|
||||
jtag_tclk_set(p);
|
||||
jtag_tclk_clr(p);
|
||||
jtag_tclk_set(p); // TODO: ???
|
||||
|
||||
/* Read jtag id */
|
||||
jtag_id = jtag_ir_shift(p, IR_ADDR_CAPTURE);
|
||||
|
||||
//jtag_tclk_set(p); // TODO: ???
|
||||
|
||||
/* Disable watchdog on target device */
|
||||
//jtag_write_mem(p, 16, 0x0120, 0x5A80); // FIXME
|
||||
|
||||
return jtag_id;
|
||||
}
|
||||
|
||||
/* Release the target device from JTAG control
|
||||
* address: 0xFFFE - perform Reset,
|
||||
* load Reset Vector into PC
|
||||
* 0xFFFF - start execution at current
|
||||
* PC position
|
||||
* other - load Address into PC
|
||||
*/
|
||||
static void jlf16_release_device(struct jtdev *p, address_t address)
|
||||
{ // SLAU320AJ name: ReleaseDevice
|
||||
switch (address) {
|
||||
case 0xffff: /* Nothing to do */
|
||||
dbg_printc("BOR\n");
|
||||
break;
|
||||
case 0xfffe: /* Perform reset */
|
||||
dbg_printc("SRST\n");
|
||||
/* delete all breakpoints */
|
||||
jtag_set_breakpoint(p,-1,0);
|
||||
/* issue reset */
|
||||
jtag_ir_shift(p, IR_CNTRL_SIG_16BIT);
|
||||
jtag_dr_shift_16(p, 0x2C01);
|
||||
jtag_dr_shift_16(p, 0x2401);
|
||||
break;
|
||||
default: /* Set target CPU's PC */
|
||||
dbg_printc("PC: %04x\n", address);
|
||||
jtag_write_reg(p, 0, address);
|
||||
break;
|
||||
}
|
||||
|
||||
jlf16_set_instruction_fetch(p);
|
||||
|
||||
jtag_ir_shift(p, IR_EMEX_DATA_EXCHANGE);
|
||||
jtag_dr_shift_16(p, BREAKREACT + READ);
|
||||
jtag_dr_shift_16(p, 0x0000);
|
||||
|
||||
jtag_ir_shift(p, IR_EMEX_WRITE_CONTROL);
|
||||
jtag_dr_shift_16(p, 0x000f);
|
||||
|
||||
jtag_ir_shift(p, IR_CNTRL_SIG_RELEASE);
|
||||
}
|
||||
|
||||
/* Programs/verifies an array of words into a FLASH by using the
|
||||
* FLASH controller. The JTAG FLASH register isn't needed.
|
||||
* start_address: start in FLASH
|
||||
* length : number of words
|
||||
* data : pointer to data
|
||||
*/
|
||||
static void jlf16_write_flash(struct jtdev *p, address_t start_address,
|
||||
unsigned int length, const uint16_t *data)
|
||||
{ // SLAU320AJ name: WriteFLASH
|
||||
unsigned int index;
|
||||
unsigned int address;
|
||||
|
||||
dbg_printc("%04x..%04x\n", address, address+length*2);
|
||||
|
||||
address = start_address;
|
||||
jlf16_halt_cpu(p);
|
||||
jtag_tclk_clr(p);
|
||||
|
||||
/* Set RW to write */
|
||||
jtag_ir_shift(p, IR_CNTRL_SIG_16BIT);
|
||||
jtag_dr_shift_16(p, 0x2408);
|
||||
|
||||
/* FCTL1 register */
|
||||
jtag_ir_shift(p, IR_ADDR_16BIT);
|
||||
jtag_dr_shift_16(p, 0x0128); // FIXME
|
||||
|
||||
/* Enable FLASH write */
|
||||
jtag_ir_shift(p, IR_DATA_TO_ADDR);
|
||||
jtag_dr_shift_16(p, 0xA540);
|
||||
jtag_tclk_set(p);
|
||||
jtag_tclk_clr(p);
|
||||
|
||||
/* FCTL2 register */
|
||||
jtag_ir_shift(p, IR_ADDR_16BIT);
|
||||
jtag_dr_shift_16(p, 0x012A); // FIXME
|
||||
|
||||
/* Select MCLK as source, DIV=1 */
|
||||
jtag_ir_shift(p, IR_DATA_TO_ADDR);
|
||||
jtag_dr_shift_16(p, 0xA540);
|
||||
jtag_tclk_set(p);
|
||||
jtag_tclk_clr(p);
|
||||
|
||||
/* FCTL3 register */
|
||||
jtag_ir_shift(p, IR_ADDR_16BIT);
|
||||
jtag_dr_shift_16(p, 0x012C); // FIXME
|
||||
|
||||
/* Clear FCTL3 register */
|
||||
jtag_ir_shift(p, IR_DATA_TO_ADDR);
|
||||
jtag_dr_shift_16(p, 0xA500);
|
||||
jtag_tclk_set(p);
|
||||
jtag_tclk_clr(p);
|
||||
|
||||
for (index = 0; index < length; index++) {
|
||||
/* Set RW to write */
|
||||
jtag_ir_shift(p, IR_CNTRL_SIG_16BIT);
|
||||
jtag_dr_shift_16(p, 0x2408);
|
||||
|
||||
/* Set address */
|
||||
jtag_ir_shift(p, IR_ADDR_16BIT);
|
||||
jtag_dr_shift_16(p, address);
|
||||
|
||||
/* Set data */
|
||||
jtag_ir_shift(p, IR_DATA_TO_ADDR);
|
||||
jtag_dr_shift_16(p, data[index]);
|
||||
jtag_tclk_set(p);
|
||||
jtag_tclk_clr(p);
|
||||
|
||||
/* Set RW to read */
|
||||
jtag_ir_shift(p, IR_CNTRL_SIG_16BIT);
|
||||
jtag_dr_shift_16(p, 0x2409);
|
||||
|
||||
/* provide TCLKs
|
||||
* min. 33 for F149 and F449
|
||||
*/
|
||||
p->f->jtdev_tclk_strobe(p, 35);
|
||||
address += 2;
|
||||
|
||||
if (p->failed)
|
||||
break;
|
||||
}
|
||||
|
||||
/* Set RW to write */
|
||||
jtag_ir_shift(p, IR_CNTRL_SIG_16BIT);
|
||||
jtag_dr_shift_16(p, 0x2408);
|
||||
|
||||
/* FCTL1 register */
|
||||
jtag_ir_shift(p, IR_ADDR_16BIT);
|
||||
jtag_dr_shift_16(p, 0x0128); // FIXME
|
||||
|
||||
/* Disable FLASH write */
|
||||
jtag_ir_shift(p, IR_DATA_TO_ADDR);
|
||||
jtag_dr_shift_16(p, 0xA500);
|
||||
jtag_tclk_set(p);
|
||||
jtag_tclk_clr(p);
|
||||
|
||||
/* Reset FCTL3 */
|
||||
jtag_ir_shift(p, IR_ADDR_16BIT);
|
||||
jtag_dr_shift_16(p, 0x012C); // FIXME
|
||||
jtag_ir_shift(p, IR_DATA_TO_ADDR);
|
||||
jtag_dr_shift_16(p, 0xA510);
|
||||
jtag_tclk_set(p);
|
||||
}
|
||||
|
||||
/* Performs a mass erase (with and w/o info memory) or a segment erase of a
|
||||
* FLASH module specified by the given mode and address. Large memory devices
|
||||
* get additional mass erase operations to meet the spec.
|
||||
* erase_mode : ERASE_MASS, ERASE_MAIN, ERASE_SGMT
|
||||
* erase_address: address within the selected segment
|
||||
*/
|
||||
static void jlf16_erase_flash(struct jtdev *p, unsigned int erase_mode,
|
||||
address_t erase_address)
|
||||
{ // SLAU320AJ name: EraseFLASH
|
||||
unsigned int number_of_strobes = 4820; /* default for segment erase */
|
||||
unsigned int loop_counter;
|
||||
unsigned int max_loop_count = 1; /* erase cycle repeating for mass erase */
|
||||
|
||||
dbg_printc("%04x: %04x\n", erase_mode, erase_address);
|
||||
|
||||
if ((erase_mode == JTAG_ERASE_MASS) || (erase_mode == JTAG_ERASE_MAIN)) {
|
||||
number_of_strobes = 5300; /* Larger Flash memories require */
|
||||
max_loop_count = 19; /* additional cycles for erase. */
|
||||
erase_address = 0xfffe; /* overwrite given address */
|
||||
}
|
||||
|
||||
for (loop_counter = max_loop_count; loop_counter > 0; loop_counter--) {
|
||||
jlf16_halt_cpu(p);
|
||||
jtag_tclk_clr(p);
|
||||
|
||||
/* Set RW to write */
|
||||
jtag_ir_shift(p, IR_CNTRL_SIG_16BIT);
|
||||
jtag_dr_shift_16(p, 0x2408);
|
||||
|
||||
/* FCTL1 address */
|
||||
jtag_ir_shift(p, IR_ADDR_16BIT);
|
||||
jtag_dr_shift_16(p, 0x0128); // FIXME
|
||||
|
||||
/* Enable erase mode */
|
||||
jtag_ir_shift(p, IR_DATA_TO_ADDR);
|
||||
jtag_dr_shift_16(p, erase_mode); // FIXME?
|
||||
jtag_tclk_set(p);
|
||||
jtag_tclk_clr(p);
|
||||
|
||||
/* FCTL2 address */
|
||||
jtag_ir_shift(p, IR_ADDR_16BIT);
|
||||
jtag_dr_shift_16(p, 0x012A); // FIXME
|
||||
|
||||
/* MCLK is source, DIV=1 */
|
||||
jtag_ir_shift(p, IR_DATA_TO_ADDR);
|
||||
jtag_dr_shift_16(p, 0xA540);
|
||||
jtag_tclk_set(p);
|
||||
jtag_tclk_clr(p);
|
||||
|
||||
/* FCTL3 address */
|
||||
jtag_ir_shift(p, IR_ADDR_16BIT);
|
||||
jtag_dr_shift_16(p, 0x012C); // FIXME
|
||||
|
||||
/* Clear FCTL3 */
|
||||
jtag_ir_shift(p, IR_DATA_TO_ADDR);
|
||||
jtag_dr_shift_16(p, 0xA500);
|
||||
jtag_tclk_set(p);
|
||||
jtag_tclk_clr(p);
|
||||
|
||||
/* Set erase address */
|
||||
jtag_ir_shift(p, IR_ADDR_16BIT);
|
||||
jtag_dr_shift_16(p, erase_address);
|
||||
|
||||
/* Dummy write to start erase */
|
||||
jtag_ir_shift(p, IR_DATA_TO_ADDR);
|
||||
jtag_dr_shift_16(p, 0x55AA);
|
||||
jtag_tclk_set(p);
|
||||
jtag_tclk_clr(p);
|
||||
|
||||
/* Set RW to read */
|
||||
jtag_ir_shift(p, IR_CNTRL_SIG_16BIT);
|
||||
jtag_dr_shift_16(p, 0x2409);
|
||||
|
||||
/* provide TCLKs */
|
||||
p->f->jtdev_tclk_strobe(p, number_of_strobes);
|
||||
|
||||
/* Set RW to write */
|
||||
jtag_ir_shift(p, IR_CNTRL_SIG_16BIT);
|
||||
jtag_dr_shift_16(p, 0x2408);
|
||||
|
||||
/* FCTL1 address */
|
||||
jtag_ir_shift(p, IR_ADDR_16BIT);
|
||||
jtag_dr_shift_16(p, 0x0128); // FIXME
|
||||
|
||||
/* Disable erase */
|
||||
jtag_ir_shift(p, IR_DATA_TO_ADDR);
|
||||
jtag_dr_shift_16(p, 0xA500);
|
||||
jtag_tclk_set(p);
|
||||
jtag_tclk_clr(p);
|
||||
|
||||
/* Reset FCTL3 */
|
||||
jtag_ir_shift(p, IR_ADDR_16BIT);
|
||||
jtag_dr_shift_16(p, 0x012C); // FIXME
|
||||
jtag_ir_shift(p, IR_DATA_TO_ADDR);
|
||||
jtag_dr_shift_16(p, 0xA510);
|
||||
jtag_tclk_set(p);
|
||||
|
||||
jlf16_release_cpu(p);
|
||||
}
|
||||
}
|
||||
|
||||
/* Reads a register from the target CPU */
|
||||
static address_t jlf16_read_reg(struct jtdev *p, int reg)
|
||||
{ // libmsp430 BIOS name: ReadCpuReg
|
||||
unsigned int value;
|
||||
|
||||
dbg_printc("%d\n", reg);
|
||||
|
||||
/* Set CPU into instruction fetch mode */
|
||||
jlf16_set_instruction_fetch(p);
|
||||
|
||||
/* CPU controls RW & BYTE */
|
||||
jtag_ir_shift(p, IR_CNTRL_SIG_16BIT);
|
||||
jtag_dr_shift_16(p, 0x3401);
|
||||
|
||||
jtag_ir_shift(p, IR_DATA_16BIT);
|
||||
|
||||
/* "jmp $-4" instruction */
|
||||
/* PC - 4 -> PC */
|
||||
/* needs 2 clock cycles */
|
||||
jtag_dr_shift_16(p, 0x3ffd);
|
||||
jtag_tclk_clr(p);
|
||||
jtag_tclk_set(p);
|
||||
jtag_tclk_clr(p);
|
||||
jtag_tclk_set(p);
|
||||
|
||||
/* "mov Rn,&0x01fe" instruction
|
||||
* Rn -> &0x01fe
|
||||
* PC is advanced 4 bytes by this instruction
|
||||
* needs 4 clock cycles
|
||||
* it's a ROM address, write has no effect, but
|
||||
* the registers value is placed on the databus
|
||||
*/
|
||||
jtag_dr_shift_16(p, 0x4082 | (((unsigned int)reg << 8) & 0x0f00) );
|
||||
jtag_tclk_clr(p);
|
||||
//jtag_ir_shift(p, IR_DATA_CAPTURE); // TODO: ???
|
||||
jtag_tclk_set(p);
|
||||
//jtag_ir_shift(p, IR_DATA_16BIT); // TODO: ???
|
||||
jtag_dr_shift_16(p, 0x01fe);
|
||||
jtag_tclk_clr(p);
|
||||
jtag_tclk_set(p);
|
||||
jtag_tclk_clr(p);
|
||||
jtag_tclk_set(p);
|
||||
/* older code did an extra clock cycle -- don't do this! will put the
|
||||
* current instruction word on the data bus instead of the register value
|
||||
* on the G2452, making it useless. the clock cycles are still required to
|
||||
* move to the next instruction, but those should be done later. */
|
||||
/*jtag_tclk_clr(p);
|
||||
jtag_tclk_set(p);*/
|
||||
|
||||
/* Read databus which contains the registers value */
|
||||
jtag_ir_shift(p, IR_DATA_CAPTURE);
|
||||
value = jtag_dr_shift_16(p, 0x0000);
|
||||
|
||||
jtag_tclk_clr(p);
|
||||
|
||||
/* JTAG controls RW & BYTE */
|
||||
jtag_ir_shift(p, IR_CNTRL_SIG_16BIT);
|
||||
jtag_dr_shift_16(p, 0x2401);
|
||||
|
||||
jtag_tclk_set(p);
|
||||
|
||||
dbg_printc("%d -> %04x\n", reg, value);
|
||||
|
||||
/* Return value read from register */
|
||||
return value;
|
||||
}
|
||||
|
||||
/* Writes a value into a register of the target CPU */
|
||||
static void jlf16_write_reg(struct jtdev *p, int reg, address_t value)
|
||||
{ // SLAU320AJ name: SetPC
|
||||
/* Set CPU into instruction fetch mode */
|
||||
dbg_printc("%d <- %04x\n", reg, value);
|
||||
|
||||
jlf16_set_instruction_fetch(p);
|
||||
|
||||
/* CPU controls RW & BYTE */
|
||||
jtag_ir_shift(p, IR_CNTRL_SIG_16BIT);
|
||||
jtag_dr_shift_16(p, 0x3401);
|
||||
|
||||
jtag_ir_shift(p, IR_DATA_16BIT);
|
||||
|
||||
/* "jmp $-4" instruction */
|
||||
/* PC - 4 -> PC */
|
||||
/* needs 4 clock cycles */
|
||||
jtag_dr_shift_16(p, 0x3ffd);
|
||||
jtag_tclk_clr(p);
|
||||
jtag_tclk_set(p);
|
||||
jtag_tclk_clr(p);
|
||||
jtag_tclk_set(p);
|
||||
|
||||
/* "mov #value,Rn" instruction
|
||||
* value -> Rn
|
||||
* PC is advanced 4 bytes by this instruction
|
||||
* needs 2 clock cycles
|
||||
*/
|
||||
jtag_dr_shift_16(p, 0x4030 | (reg & 0x000f) );
|
||||
jtag_tclk_clr(p);
|
||||
jtag_tclk_set(p);
|
||||
jtag_dr_shift_16(p, value);
|
||||
jtag_tclk_clr(p);
|
||||
jtag_tclk_set(p);
|
||||
|
||||
// TODO: ???
|
||||
//jtag_ir_shift(p, IR_ADDR_CAPTURE);
|
||||
//jtag_tclk_clr(p);
|
||||
|
||||
/* JTAG controls RW & BYTE */
|
||||
jtag_ir_shift(p, IR_CNTRL_SIG_16BIT);
|
||||
jtag_dr_shift_16(p, 0x2401);
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------*/
|
||||
static void jlf16_single_step( struct jtdev *p )
|
||||
{ // libmsp430 BIOS name: SingleStep
|
||||
unsigned int loop_counter;
|
||||
|
||||
dbg_printc("\n");
|
||||
|
||||
jlf16_set_instruction_fetch(p);
|
||||
|
||||
/* CPU controls RW & BYTE */
|
||||
jtag_ir_shift(p, IR_CNTRL_SIG_16BIT);
|
||||
jtag_dr_shift_16(p, 0x3401);
|
||||
|
||||
/* clock CPU until next instruction fetch cycle */
|
||||
/* failure after 10 clock cycles */
|
||||
/* this is more than for the longest instruction */
|
||||
jtag_ir_shift(p, IR_CNTRL_SIG_CAPTURE);
|
||||
for (loop_counter = 10; loop_counter > 0; loop_counter--) {
|
||||
jtag_tclk_clr(p);
|
||||
jtag_tclk_set(p);
|
||||
if ((jtag_dr_shift_16(p, 0x0000) & 0x0080) == 0x0080) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* JTAG controls RW & BYTE */
|
||||
jtag_ir_shift(p, IR_CNTRL_SIG_16BIT);
|
||||
jtag_dr_shift_16(p, 0x2401);
|
||||
|
||||
jlf16_set_instruction_fetch(p);
|
||||
|
||||
if (loop_counter == 0) {
|
||||
/* timeout reached */
|
||||
printc_err("jtaglib_cpu16: single step failed\n");
|
||||
p->failed = 1;
|
||||
}
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------*/
|
||||
static unsigned int jlf16_set_breakpoint( struct jtdev *p,int bp_num, address_t bp_addr )
|
||||
{
|
||||
/* The breakpoint logic is explained in 'SLAU414c EEM.pdf' */
|
||||
/* A good overview is given with Figure 1-1 */
|
||||
/* MBx is TBx in EEM_defs.h */
|
||||
/* CPU Stop is BREAKREACT in EEM_defs.h */
|
||||
/* State Storage is STOR_REACT in EEM_defs.h */
|
||||
/* Cycle Counter is EVENT_REACT in EEM_defs.h */
|
||||
|
||||
unsigned int breakreact;
|
||||
|
||||
if (bp_num >= 8) {
|
||||
/* there are no more than 8 breakpoints in EEM */
|
||||
printc_err("jlf16_set_breakpoint: failed setting "
|
||||
"breakpoint %d at %04x\n", bp_num, bp_addr);
|
||||
p->failed = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
dbg_printc("num=%d addr=%04x\n", bp_num, bp_addr);
|
||||
|
||||
if (bp_num < 0) {
|
||||
/* disable all breakpoints by deleting the BREAKREACT
|
||||
* register */
|
||||
jtag_ir_shift(p, IR_EMEX_DATA_EXCHANGE);
|
||||
jtag_dr_shift_16(p, BREAKREACT + WRITE);
|
||||
jtag_dr_shift_16(p, 0x0000);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* set breakpoint */
|
||||
jtag_ir_shift(p, IR_EMEX_DATA_EXCHANGE);
|
||||
jtag_dr_shift_16(p, GENCTRL + WRITE);
|
||||
jtag_dr_shift_16(p, EEM_EN + CLEAR_STOP + EMU_CLK_EN + EMU_FEAT_EN);
|
||||
|
||||
jtag_ir_shift(p, IR_EMEX_DATA_EXCHANGE); //repeating may not needed
|
||||
jtag_dr_shift_16(p, 8*bp_num + MBTRIGxVAL + WRITE);
|
||||
jtag_dr_shift_16(p, bp_addr);
|
||||
|
||||
jtag_ir_shift(p, IR_EMEX_DATA_EXCHANGE); //repeating may not needed
|
||||
jtag_dr_shift_16(p, 8*bp_num + MBTRIGxCTL + WRITE);
|
||||
jtag_dr_shift_16(p, MAB + TRIG_0 + CMP_EQUAL);
|
||||
|
||||
jtag_ir_shift(p, IR_EMEX_DATA_EXCHANGE); //repeating may not needed
|
||||
jtag_dr_shift_16(p, 8*bp_num + MBTRIGxMSK + WRITE);
|
||||
jtag_dr_shift_16(p, NO_MASK);
|
||||
|
||||
jtag_ir_shift(p, IR_EMEX_DATA_EXCHANGE); //repeating may not needed
|
||||
jtag_dr_shift_16(p, 8*bp_num + MBTRIGxCMB + WRITE);
|
||||
jtag_dr_shift_16(p, 1<<bp_num);
|
||||
|
||||
/* read the actual setting of the BREAKREACT register */
|
||||
/* while reading a 1 is automatically shifted into LSB */
|
||||
/* this will be undone and the bit for the new breakpoint set */
|
||||
/* then the updated value is stored back */
|
||||
jtag_ir_shift(p, IR_EMEX_DATA_EXCHANGE); //repeating may not needed
|
||||
breakreact = jtag_dr_shift_16(p, BREAKREACT + READ);
|
||||
breakreact += jtag_dr_shift_16(p, 0x000);
|
||||
breakreact = (breakreact >> 1) | (1 << bp_num);
|
||||
jtag_dr_shift_16(p, BREAKREACT + WRITE);
|
||||
jtag_dr_shift_16(p, breakreact);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------*/
|
||||
static unsigned int jlf16_cpu_state( struct jtdev *p )
|
||||
{ // libmsp430 BIOS name: WaitForEem(?)
|
||||
jtag_ir_shift(p, IR_EMEX_READ_CONTROL);
|
||||
|
||||
if ((jtag_dr_shift_16(p, 0x0000) & 0x0080) == 0x0080) {
|
||||
dbg_printc("halted\n");
|
||||
return 1; /* halted */
|
||||
} else {
|
||||
dbg_printc("running\n");
|
||||
return 0; /* running */
|
||||
}
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------*/
|
||||
static int jlf16_get_config_fuses( struct jtdev *p )
|
||||
{ // always the same?
|
||||
jtag_ir_shift(p, IR_CONFIG_FUSES);
|
||||
|
||||
return jtag_dr_shift_8(p, 0);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
const struct jtaglib_funcs jlf_cpu16 = {
|
||||
.jlf_get_device = jlf16_get_device,
|
||||
|
||||
.jlf_read_mem = jlf16_read_mem,
|
||||
.jlf_read_mem_quick = jlf16_read_mem_quick,
|
||||
.jlf_write_mem = jlf16_write_mem,
|
||||
.jlf_write_mem_quick = jlf16_write_mem_quick,
|
||||
|
||||
.jlf_execute_puc = jlf16_execute_puc,
|
||||
.jlf_release_device = jlf16_release_device,
|
||||
|
||||
.jlf_verify_mem = jlf16_verify_mem,
|
||||
.jlf_erase_check = jlf16_erase_check,
|
||||
|
||||
.jlf_write_flash = jlf16_write_flash,
|
||||
.jlf_erase_flash = jlf16_erase_flash,
|
||||
|
||||
.jlf_context_save = jtag_dev_default_context_save,
|
||||
.jlf_context_restore = jtag_dev_default_context_restore,
|
||||
.jlf_regs_update = jtag_dev_default_regs_update,
|
||||
.jlf_regs_flush = jtag_dev_default_regs_flush,
|
||||
|
||||
.jlf_read_reg = jlf16_read_reg,
|
||||
.jlf_write_reg = jlf16_write_reg,
|
||||
.jlf_single_step = jlf16_single_step,
|
||||
.jlf_set_breakpoint = jlf16_set_breakpoint,
|
||||
.jlf_cpu_state = jlf16_cpu_state,
|
||||
.jlf_get_config_fuses = jlf16_get_config_fuses,
|
||||
};
|
||||
|
|
@ -1,7 +0,0 @@
|
|||
|
||||
#include "jtaglib.h"
|
||||
#include "jtaglib_defs.h"
|
||||
#include "output.h"
|
||||
|
||||
const struct jtaglib_funcs jlf_cpux;
|
||||
|
|
@ -1,889 +0,0 @@
|
|||
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "jtaglib.h"
|
||||
#include "jtaglib_defs.h"
|
||||
#include "output.h"
|
||||
|
||||
#define SAFE_FRAM_PC 0x0004
|
||||
|
||||
#ifdef DEBUG_JTAGLIB
|
||||
#define dbg_printc(fmt, ...) printc_dbg("jlfxv2: %s:%d " fmt, __func__, __LINE__, ##__VA_ARGS__)
|
||||
#else
|
||||
#define dbg_printc(fmt, ...) do{}while(0)
|
||||
#endif
|
||||
|
||||
static address_t jlfxv2_read_reg(struct jtdev *p, int reg);
|
||||
static void jlfxv2_write_reg(struct jtdev *p, int reg, address_t value);
|
||||
|
||||
// FIXME:
|
||||
// * context save/restore:
|
||||
// * pc gets written correctly on single-step
|
||||
// * pc does NOT get written on 'run'
|
||||
// * pc does NOT get read properly on run break
|
||||
// * implement flash write, erase, verify stuff
|
||||
// * check how ^ works in practice on flash & FRAM devices
|
||||
// * single step: not working!
|
||||
// * breakpoints are a big TODO
|
||||
|
||||
static int jlfxv2_check_full_emu_state_ex(struct jtdev *p, const char* fnname)
|
||||
{ // see SLAU320AJ ExecutePOR
|
||||
uint16_t dr;
|
||||
uint8_t jtag_id;
|
||||
|
||||
for (int i = 0; i < 1/*10*/; ++i) {
|
||||
jtag_id = jtag_ir_shift(p, IR_CNTRL_SIG_CAPTURE);
|
||||
if (((dr = jtag_dr_shift_16(p, 0)) & 0x0301) == 0x0301) {
|
||||
return 1; // OK
|
||||
}
|
||||
|
||||
printc_err("jlfxv2: %s: not in full emu state, while expected!"
|
||||
" (dr=%04x jid=%02x)\n", fnname, dr, jtag_id);
|
||||
}
|
||||
p->failed = 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
#define jlfxv2_check_full_emu_state(p) jlfxv2_check_full_emu_state_ex((p), __func__)
|
||||
|
||||
static int jlfxv2_wait_sync_ex(struct jtdev *p, const char* fnname) {
|
||||
uint16_t dr;
|
||||
uint8_t jtag_id;
|
||||
|
||||
jtag_id = jtag_ir_shift(p, IR_CNTRL_SIG_CAPTURE);
|
||||
for (int i = 0; i < 50; ++i) {
|
||||
if ((dr = jtag_dr_shift_16(p, 0)) & 0x0200)
|
||||
return 1;
|
||||
}
|
||||
|
||||
printc_err("jlfxv2: %s: couldn't sync! (dr=%04x jid=%02x)\n", fnname, dr, jtag_id);
|
||||
return 0;
|
||||
}
|
||||
#define jlfxv2_wait_sync(p) jlfxv2_wait_sync_ex((p), __func__)
|
||||
|
||||
|
||||
static uint8_t bitswap_nyb(uint8_t in) {
|
||||
return ((in >> 3) & 1) | ((in >> 1) & 2) | ((in << 1) & 4) | ((in << 3) & 8);
|
||||
}
|
||||
static uint8_t bitswap(uint8_t in) {
|
||||
return (bitswap_nyb(in&0xf) << 4) | bitswap_nyb(in>>4);
|
||||
}
|
||||
static address_t demangle_mab(address_t mab) {
|
||||
address_t page = mab & 0xf0000;
|
||||
address_t bot = mab & 0x0ff00;
|
||||
address_t top = mab & 0x000ff;
|
||||
|
||||
address_t ret = page | (bot >> 8) | ((address_t)bitswap(top) << 8);
|
||||
//dbg_printc("demangle: %05x -> %05x\n", mab, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int jlfxv2_set_pc(struct jtdev *p, address_t addr)
|
||||
{
|
||||
address_t addr_rb;
|
||||
|
||||
dbg_printc("set pc %05x\n", addr);
|
||||
|
||||
if (!jlfxv2_wait_sync(p)) return -1;
|
||||
/*jtag_ir_shift(p, IR_CNTRL_SIG_CAPTURE);
|
||||
jtag_dr_shift_16(p, 0);*/
|
||||
jtag_tclk_clr(p);
|
||||
|
||||
jtag_ir_shift(p, IR_DATA_16BIT);
|
||||
jtag_tclk_set(p);
|
||||
jtag_dr_shift_16(p, 0x0080 | ((addr >> 8) & 0x0f00));
|
||||
jtag_tclk_clr(p);
|
||||
|
||||
jtag_ir_shift(p, IR_CNTRL_SIG_16BIT);
|
||||
jtag_dr_shift_16(p, 0x1400);
|
||||
|
||||
jtag_ir_shift(p, IR_DATA_16BIT);
|
||||
jtag_tclk_clr(p);
|
||||
jtag_tclk_set(p);
|
||||
jtag_dr_shift_16(p, addr & 0xffff);
|
||||
jtag_tclk_clr(p);
|
||||
jtag_tclk_set(p);
|
||||
|
||||
jtag_dr_shift_16(p, 0x4303);
|
||||
jtag_tclk_clr(p);
|
||||
jtag_ir_shift(p, IR_ADDR_CAPTURE);
|
||||
addr_rb = demangle_mab(jtag_dr_shift_20(p, 0));
|
||||
dbg_printc("set pc MAB -> %05x%s\n", addr_rb,
|
||||
(addr!=addr_rb)?", aieee!":"");
|
||||
|
||||
return (addr == addr_rb) ? 0 : -1;
|
||||
}
|
||||
/*static address_t jlfxv2_get_pc(struct jtdev *p)
|
||||
{
|
||||
jtag_ir_shift(p, IR_CNTRL_SIG_CAPTURE);
|
||||
jtag_dr_shift_16(p, 0);
|
||||
jtag_ir_shift(p, IR_ADDR_CAPTURE);
|
||||
jtag_dr_shift_20(p, 0);
|
||||
|
||||
address_t addr = jtag_dr_shift_20(p, 0);
|
||||
|
||||
dbg_printc("get pc %05x\n", addr);
|
||||
|
||||
return addr;
|
||||
}*/
|
||||
|
||||
/* Compares the computed PSA (Pseudo Signature Analysis) value to the PSA
|
||||
* value shifted out from the target device. It is used for very fast data
|
||||
* block write or erasure verification.
|
||||
* start_address: start of data
|
||||
* length : number of data
|
||||
* data : pointer to data, 0 for erase check
|
||||
* RETURN : 1 - comparison was successful
|
||||
* 0 - otherwise
|
||||
*/
|
||||
static int jlfxv2_verify_mem(struct jtdev *p,
|
||||
unsigned int start_address,
|
||||
unsigned int length,
|
||||
const uint16_t *data)
|
||||
{ // SLAU320AJ name: VerifyMem/VerifyPSA
|
||||
uint16_t crc, psaval;
|
||||
|
||||
jtag_execute_puc(p);
|
||||
|
||||
crc = start_address - 2;
|
||||
if (jlfxv2_set_pc(p, start_address) < 0) return -1;
|
||||
|
||||
jtag_tclk_set(p);
|
||||
jtag_ir_shift(p, IR_CNTRL_SIG_16BIT);
|
||||
jtag_dr_shift_16(p, 0x0501);
|
||||
jtag_ir_shift(p, IR_DATA_16BIT);
|
||||
jtag_dr_shift_16(p, start_address - 2);
|
||||
jtag_ir_shift(p, IR_DATA_PSA);
|
||||
|
||||
for (unsigned int addr = 0; addr < length; ++addr) {
|
||||
if (crc & 0x8000) {
|
||||
crc ^= 0x0805;
|
||||
crc <<= 1;
|
||||
crc |= 1;
|
||||
} else {
|
||||
crc <<= 1;
|
||||
}
|
||||
|
||||
if (data) crc ^= data[addr];
|
||||
else crc ^= 0xffff;
|
||||
|
||||
jtag_tclk_clr(p);
|
||||
/* Go through DR path without shifting data in/out */
|
||||
jtag_tms_sequence(p, 6, 0x19); /* TMS=1 0 0 1 1 0 ; 6 clocks */
|
||||
jtag_tclk_set(p);
|
||||
}
|
||||
|
||||
jtag_ir_shift(p, IR_SHIFT_OUT_PSA);
|
||||
psaval = jtag_dr_shift_16(p, 0);
|
||||
|
||||
jtag_execute_puc(p);
|
||||
|
||||
return (psaval == crc) ? 1 : 0;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
static int jlfxv2_erase_check(struct jtdev *p, unsigned int start_address,
|
||||
unsigned int length)
|
||||
{
|
||||
return jlfxv2_verify_mem(p, start_address, length, NULL);
|
||||
}
|
||||
|
||||
static unsigned int jlfxv2_get_device(struct jtdev *p)
|
||||
{ // SLAU320AJ name: GetDevice (and SyncJtag_AssertPor)
|
||||
unsigned int jtag_id = 0;
|
||||
int i;
|
||||
|
||||
dbg_printc("jlfxv2: get_device\n");
|
||||
jtag_ir_shift(p, IR_CNTRL_SIG_16BIT);
|
||||
jtag_dr_shift_16(p, 0x1501);
|
||||
|
||||
jtag_ir_shift(p, IR_CNTRL_SIG_CAPTURE);
|
||||
for (i = 0; i < 50; ++i) {
|
||||
if ((jtag_dr_shift_16(p, 0) & (1<<9)) == (1<<9))
|
||||
break;
|
||||
}
|
||||
|
||||
if (i == 50) {
|
||||
printc_err("jlfxv2_get_device: failed\n");
|
||||
p->failed = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
jtag_id = jtag_execute_puc(p);
|
||||
return jtag_id;
|
||||
}
|
||||
|
||||
static void jlfxv2_read_mem_quick(struct jtdev *p, address_t address,
|
||||
unsigned int length, uint16_t *data);
|
||||
|
||||
/* Reads one byte/word from a given address
|
||||
* format : 8-byte, 16-word
|
||||
* address: address of memory
|
||||
* return : content of memory
|
||||
*/
|
||||
static uint16_t jlfxv2_read_mem(struct jtdev *p, unsigned int format, address_t address)
|
||||
{ // SLAU320AJ name: ReadMem
|
||||
uint16_t r = 0;
|
||||
|
||||
dbg_printc("read mem %05x\n", address);
|
||||
if (!jlfxv2_check_full_emu_state(p))
|
||||
return 0;
|
||||
|
||||
// the code below (an attempt at implementing the real read_mem) doesn't
|
||||
// work, so let's use read_mem_quick as a backup
|
||||
jlfxv2_read_mem_quick(p, address ^ (address & 1), 1, &r);
|
||||
if (format == 8) {
|
||||
if (address & 1) return (r >> 8) & 0xff;
|
||||
else return r & 0xff;
|
||||
} else return r;
|
||||
|
||||
/*//jtag_ir_shift(p, IR_CNTRL_SIG_CAPTURE);
|
||||
//uint16_t dr = jtag_dr_shift_16(p, 0);
|
||||
jtag_tclk_clr(p);
|
||||
//jtag_ir_shift(p, IR_CNTRL_SIG_16BIT);
|
||||
//jtag_dr_shift_16(p, (format == 16) ? 0x0501 : 0x0511);
|
||||
jtag_ir_shift(p, IR_ADDR_16BIT);
|
||||
jtag_dr_shift_20(p, address ^ (address & 1));
|
||||
//jtag_ir_shift(p, IR_DATA_TO_ADDR);
|
||||
jtag_tclk_set(p);
|
||||
jtag_tclk_clr(p);
|
||||
jtag_ir_shift(p, IR_DATA_CAPTURE);
|
||||
|
||||
r = jtag_dr_shift_16(p, 0);
|
||||
|
||||
jtag_tclk_set(p);
|
||||
jtag_tclk_clr(p);
|
||||
jtag_tclk_set(p);
|
||||
|
||||
if (format == 8) {
|
||||
if (address & 1) return (r >> 8) & 0xff;
|
||||
else return r & 0xff;
|
||||
} else return r;*/
|
||||
}
|
||||
|
||||
/* Reads an array of words from target memory
|
||||
* address: address to read from
|
||||
* length : number of word to read
|
||||
* data : memory to write to
|
||||
*/
|
||||
static void jlfxv2_read_mem_quick(struct jtdev *p, address_t address,
|
||||
unsigned int length, uint16_t *data)
|
||||
{ // SLAU320AJ name: ReadMemQuick
|
||||
if (!jlfxv2_check_full_emu_state(p))
|
||||
return;
|
||||
|
||||
dbg_printc("read mem quick %05x..%05x\n", address, address+length*2);
|
||||
if (jlfxv2_set_pc(p, address) < 0) return;
|
||||
|
||||
//jtag_tclk_set(p);
|
||||
jtag_ir_shift(p, IR_CNTRL_SIG_16BIT);
|
||||
jtag_dr_shift_16(p, 0x0501);
|
||||
jtag_tclk_set(p);
|
||||
jtag_ir_shift(p, IR_ADDR_CAPTURE);
|
||||
jtag_ir_shift(p, IR_DATA_QUICK);
|
||||
|
||||
for (unsigned int i = 0; i < length; ++i) {
|
||||
jtag_tclk_set(p);
|
||||
jtag_tclk_clr(p);
|
||||
data[i] = jtag_dr_shift_16(p, 0);
|
||||
}
|
||||
|
||||
jtag_ir_shift(p, IR_CNTRL_SIG_CAPTURE);
|
||||
jtag_dr_shift_16(p, 0);
|
||||
|
||||
jlfxv2_set_pc(p, SAFE_FRAM_PC);
|
||||
jtag_ir_shift(p, IR_CNTRL_SIG_16BIT);
|
||||
jtag_dr_shift_16(p, 0x0501);
|
||||
jtag_tclk_set(p);
|
||||
jtag_ir_shift(p, IR_ADDR_CAPTURE);
|
||||
}
|
||||
|
||||
static void jlfxv2_write_mem_quick(struct jtdev *p, address_t address,
|
||||
unsigned int length, const uint16_t *data);
|
||||
|
||||
/* Writes one byte/word at a given address
|
||||
* format : 8-byte, 16-word
|
||||
* address: address to be written
|
||||
* data : data to write
|
||||
*/
|
||||
static void jlfxv2_write_mem(struct jtdev *p, unsigned int format,
|
||||
address_t address, uint16_t data)
|
||||
{ // SLAU320AJ name: WriteMem
|
||||
dbg_printc("write mem: %d %06x <- %04x\n", format, address, data);
|
||||
|
||||
if (format == 8) {
|
||||
p->failed = 1;
|
||||
printc_err("jlfxv2 write mem: byte access not yet implemented!\n");
|
||||
return;
|
||||
}
|
||||
|
||||
// same story as with read_mem
|
||||
jlfxv2_write_mem_quick(p, address, 1, &data);
|
||||
|
||||
if (!jlfxv2_check_full_emu_state(p))
|
||||
return;
|
||||
|
||||
/*jtag_ir_shift(p, IR_CNTRL_SIG_CAPTURE);
|
||||
uint16_t dr = jtag_dr_shift_16(p, 0);
|
||||
|
||||
dbg_printc("write mem %d: %06x<-%04x: dr=%04x\n", format, address, data, dr);
|
||||
|
||||
jtag_tclk_clr(p);
|
||||
jtag_ir_shift(p, IR_CNTRL_SIG_16BIT);
|
||||
jtag_dr_shift_16(p, (format == 16) ? 0x0500 : 0x0510);
|
||||
jtag_ir_shift(p, IR_ADDR_16BIT);
|
||||
jtag_dr_shift_20(p, address);
|
||||
jtag_tclk_set(p);
|
||||
jtag_ir_shift(p, IR_DATA_TO_ADDR);
|
||||
jtag_dr_shift_16(p, data);
|
||||
jtag_tclk_clr(p);
|
||||
jtag_ir_shift(p, IR_CNTRL_SIG_16BIT);
|
||||
jtag_dr_shift_16(p, 0x0501);
|
||||
|
||||
jtag_tclk_set(p);
|
||||
jtag_tclk_clr(p);
|
||||
jtag_tclk_set(p);*/
|
||||
}
|
||||
|
||||
/* Writes an array of words into target memory
|
||||
* address: address to write to
|
||||
* length : number of word to write
|
||||
* data : data to write
|
||||
*/
|
||||
static void jlfxv2_write_mem_quick(struct jtdev *p, address_t address,
|
||||
unsigned int length, const uint16_t *data)
|
||||
{ // SLAU320AJ name: WriteMemQuick
|
||||
/*for (unsigned int i = 0; i < length; ++i) {
|
||||
jlfxv2_write_mem(p, 16, address + i*2, data[i]);
|
||||
}*/
|
||||
|
||||
dbg_printc("write mem quick: %05x..%05x\n", address, address+length*2);
|
||||
|
||||
if (!jlfxv2_check_full_emu_state(p))
|
||||
return;
|
||||
|
||||
if (jlfxv2_set_pc(p, address) < 0) return;
|
||||
jtag_ir_shift(p, IR_CNTRL_SIG_16BIT);
|
||||
jtag_dr_shift_16(p, 0x0500);
|
||||
jtag_tclk_set(p);
|
||||
|
||||
jtag_ir_shift(p, IR_DATA_QUICK);
|
||||
|
||||
|
||||
for (unsigned int i = 0; i < length; ++i) {
|
||||
jtag_tclk_set(p);
|
||||
jtag_dr_shift_16(p, data[i]);
|
||||
jtag_tclk_clr(p);
|
||||
}
|
||||
|
||||
jtag_ir_shift(p, IR_CNTRL_SIG_16BIT);
|
||||
jtag_dr_shift_16(p, 0x0501);
|
||||
jtag_tclk_set(p);
|
||||
|
||||
jlfxv2_set_pc(p, SAFE_FRAM_PC);
|
||||
jtag_ir_shift(p, IR_CNTRL_SIG_16BIT);
|
||||
jtag_dr_shift_16(p, 0x0501);
|
||||
jtag_tclk_set(p);
|
||||
jtag_ir_shift(p, IR_ADDR_CAPTURE);
|
||||
}
|
||||
|
||||
/* Execute a Power-Up Clear (PUC) using JTAG CNTRL SIG register
|
||||
* return: JTAG ID
|
||||
*/
|
||||
static unsigned int jlfxv2_execute_puc(struct jtdev *p)
|
||||
{ // SLAU320AJ name: ExecutePOR
|
||||
unsigned int jtag_id;
|
||||
|
||||
dbg_printc("execute_puc\n");
|
||||
|
||||
jtag_ir_shift(p, IR_CNTRL_SIG_16BIT);
|
||||
jtag_dr_shift_16(p, 0x1501);
|
||||
|
||||
if (!jlfxv2_wait_sync(p)) return -1;
|
||||
|
||||
jtag_id = jtag_ir_shift(p, IR_CNTRL_SIG_CAPTURE);
|
||||
|
||||
// empty CPU pipeline
|
||||
jtag_tclk_clr(p);
|
||||
jtag_tclk_set(p);
|
||||
|
||||
jtag_ir_shift(p, IR_CNTRL_SIG_16BIT);
|
||||
|
||||
/* Apply and remove reset */
|
||||
jtag_dr_shift_16(p, 0x0C01);
|
||||
delay_ms(40);
|
||||
jtag_dr_shift_16(p, 0x0401);
|
||||
|
||||
if (jtag_id == 0x91 || jtag_id == 0X99 || jtag_id == 0x98) {
|
||||
jtag_ir_shift(p, IR_DATA_16BIT);
|
||||
|
||||
jtag_tclk_clr(p);
|
||||
jtag_tclk_set(p);
|
||||
jtag_tclk_clr(p);
|
||||
jtag_tclk_set(p);
|
||||
|
||||
jtag_dr_shift_16(p, SAFE_FRAM_PC);
|
||||
|
||||
jtag_tclk_clr(p);
|
||||
jtag_tclk_set(p);
|
||||
|
||||
if (jtag_id == 0x91) {
|
||||
jtag_tclk_clr(p);
|
||||
jtag_tclk_set(p);
|
||||
}
|
||||
|
||||
jtag_ir_shift(p, IR_DATA_CAPTURE);
|
||||
} else { // TODO: this if jtag_id == 0x91, else other branch?
|
||||
jtag_tclk_clr(p);
|
||||
jtag_tclk_set(p);
|
||||
jtag_tclk_clr(p);
|
||||
jtag_tclk_set(p);
|
||||
jtag_tclk_clr(p);
|
||||
jtag_tclk_set(p);
|
||||
}
|
||||
|
||||
// two more cycles to release CPU internal POR delay signals
|
||||
jtag_tclk_clr(p);
|
||||
jtag_tclk_set(p);
|
||||
jtag_tclk_clr(p);
|
||||
jtag_tclk_set(p);
|
||||
|
||||
jtag_ir_shift(p, IR_CNTRL_SIG_16BIT);
|
||||
jtag_dr_shift_16(p, 0x0501);
|
||||
jtag_tclk_clr(p);
|
||||
jtag_tclk_set(p);
|
||||
|
||||
return jtag_id;
|
||||
}
|
||||
|
||||
/* Release the target device from JTAG control
|
||||
* address: 0xFFFE - perform Reset,
|
||||
* load Reset Vector into PC
|
||||
* 0xFFFF - start execution at current
|
||||
* PC position
|
||||
* other - load Address into PC
|
||||
*/
|
||||
static void jlfxv2_release_device(struct jtdev *p, address_t address)
|
||||
{ // SLAU320AJ name: ReleaseDevice. from Replicator430 code, not in the PDF
|
||||
switch (address) {
|
||||
case 0xffff: // BOR
|
||||
dbg_printc("jlfxv2: release device: BOR\n");
|
||||
|
||||
jtag_ir_shift(p, IR_TEST_REG);
|
||||
jtag_dr_shift_16(p, 0x0200);
|
||||
delay_ms(5);
|
||||
break;
|
||||
case 0xfffe: // reset
|
||||
dbg_printc("jlfxv2: release device: SRST\n");
|
||||
|
||||
jtag_ir_shift(p, IR_CNTRL_SIG_16BIT);
|
||||
jtag_dr_shift_16(p, 0x0C01);
|
||||
delay_ms(40);
|
||||
jtag_dr_shift_16(p, 0x0401);
|
||||
jtag_ir_shift(p, IR_CNTRL_SIG_RELEASE);
|
||||
break;
|
||||
default:
|
||||
dbg_printc("jlfxv2: release device: PC=%05x\n", address);
|
||||
|
||||
jlfxv2_set_pc(p, address);
|
||||
jtag_tclk_set(p);
|
||||
jtag_ir_shift(p, IR_CNTRL_SIG_16BIT);
|
||||
jtag_dr_shift_16(p, 0x0401);
|
||||
jtag_ir_shift(p, IR_ADDR_CAPTURE);
|
||||
|
||||
jtag_ir_shift(p, IR_CNTRL_SIG_CAPTURE);
|
||||
jtag_tclk_clr(p);
|
||||
if (jtag_dr_shift_16(p, 0) & 2/*CNTRL_SIG_HALT*/) {
|
||||
jtag_ir_shift(p, IR_CNTRL_SIG_16BIT);
|
||||
jtag_dr_shift_16(p, 0x0403);
|
||||
}
|
||||
jtag_tclk_set(p);
|
||||
|
||||
jtag_ir_shift(p, IR_CNTRL_SIG_RELEASE);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Programs/verifies an array of words into a FLASH by using the
|
||||
* FLASH controller. The JTAG FLASH register isn't needed.
|
||||
* start_address: start in FLASH
|
||||
* length : number of words
|
||||
* data : pointer to data
|
||||
*/
|
||||
static void jlfxv2_write_flash(struct jtdev *p, address_t start_address,
|
||||
unsigned int length, const uint16_t *data)
|
||||
{ // SLAU320AJ name: WriteFLASH
|
||||
// TODO: implement!
|
||||
}
|
||||
|
||||
/* Performs a mass erase (with and w/o info memory) or a segment erase of a
|
||||
* FLASH module specified by the given mode and address. Large memory devices
|
||||
* get additional mass erase operations to meet the spec.
|
||||
* erase_mode : ERASE_MASS, ERASE_MAIN, ERASE_SGMT
|
||||
* erase_address: address within the selected segment
|
||||
*/
|
||||
static void jlfxv2_erase_flash(struct jtdev *p, unsigned int erase_mode,
|
||||
address_t erase_address)
|
||||
{ // SLAU320AJ name: EraseFLASH
|
||||
// TODO: implement!
|
||||
}
|
||||
|
||||
/* Reads a register from the target CPU */
|
||||
static address_t jlfxv2_read_reg(struct jtdev *p, int reg)
|
||||
{ // libmsp430 BIOS name: ReadCpuReg
|
||||
uint16_t reglo, reghi;
|
||||
uint16_t jtag_id, jmb_addr;
|
||||
const bool alt_addr = false;//true;
|
||||
|
||||
if (reg == 3) return 0; // CG
|
||||
|
||||
dbg_printc("read reg %d\n", reg);
|
||||
if (!jlfxv2_check_full_emu_state(p))
|
||||
return 0;
|
||||
|
||||
jtag_id = jtag_ir_shift(p, IR_CNTRL_SIG_CAPTURE);
|
||||
jtag_tclk_clr(p);
|
||||
jtag_ir_shift(p, IR_DATA_16BIT);
|
||||
jtag_tclk_set(p);
|
||||
jtag_dr_shift_16(p, ((reg << 8) & 0x0f00) | 0x0060);
|
||||
jtag_ir_shift(p, IR_CNTRL_SIG_16BIT);
|
||||
jtag_dr_shift_16(p, 0x1401);
|
||||
jtag_ir_shift(p, IR_DATA_16BIT);
|
||||
jtag_tclk_clr(p);
|
||||
jtag_tclk_set(p);
|
||||
|
||||
if (alt_addr) {
|
||||
jtag_dr_shift_16(p, 0x0ff6);
|
||||
} else {
|
||||
jmb_addr = (jtag_id == 0x98) ? 0x14c : 0x18c;
|
||||
jtag_dr_shift_16(p, jmb_addr);
|
||||
}
|
||||
jtag_tclk_clr(p);
|
||||
jtag_tclk_set(p);
|
||||
jtag_dr_shift_16(p, 0x3ffd);
|
||||
jtag_tclk_clr(p);
|
||||
|
||||
if (alt_addr) {
|
||||
jtag_ir_shift(p, IR_CNTRL_SIG_16BIT);
|
||||
jtag_dr_shift_16(p, 0x0501);
|
||||
}
|
||||
|
||||
jtag_ir_shift(p, IR_DATA_CAPTURE);
|
||||
jtag_tclk_set(p);
|
||||
reglo = jtag_dr_shift_16(p, 0);
|
||||
jtag_tclk_clr(p);
|
||||
jtag_tclk_set(p);
|
||||
reghi = jtag_dr_shift_16(p, 0);
|
||||
jtag_tclk_clr(p);
|
||||
jtag_tclk_set(p);
|
||||
jtag_tclk_clr(p);
|
||||
jtag_tclk_set(p);
|
||||
jtag_tclk_clr(p);
|
||||
jtag_tclk_set(p);
|
||||
|
||||
if (!alt_addr) {
|
||||
jtag_ir_shift(p, IR_CNTRL_SIG_16BIT);
|
||||
jtag_dr_shift_16(p, 0x0501);
|
||||
}
|
||||
|
||||
jtag_tclk_clr(p);
|
||||
jtag_ir_shift(p, IR_DATA_CAPTURE);
|
||||
jtag_tclk_set(p);
|
||||
|
||||
dbg_printc("read reg %d: lo=%04x hi=%04x\n", reg, reglo, reghi);
|
||||
|
||||
jlfxv2_set_pc(p, SAFE_FRAM_PC);
|
||||
jtag_ir_shift(p, IR_CNTRL_SIG_16BIT);
|
||||
jtag_dr_shift_16(p, 0x0501);
|
||||
jtag_tclk_set(p);
|
||||
jtag_ir_shift(p, IR_ADDR_CAPTURE);
|
||||
|
||||
return reglo | ((address_t)reghi << 16);
|
||||
}
|
||||
|
||||
/* Writes a value into a register of the target CPU */
|
||||
static void jlfxv2_write_reg(struct jtdev *p, int reg, address_t value)
|
||||
{ // SLAU320AJ name: SetPC
|
||||
if (reg == 0 || reg == 3) return; // pc, cg
|
||||
|
||||
dbg_printc("write reg %d %06x\n", reg, value);
|
||||
|
||||
if (!jlfxv2_check_full_emu_state(p)) return;
|
||||
|
||||
/*jtag_ir_shift(p, IR_CNTRL_SIG_CAPTURE);
|
||||
jtag_dr_shift_16(p, 0);*/
|
||||
|
||||
jtag_tclk_clr(p);
|
||||
jtag_ir_shift(p, IR_DATA_16BIT);
|
||||
jtag_tclk_set(p);
|
||||
jtag_dr_shift_16(p, 0x0080 | ((value >> 8) & 0x0f00) | (reg & 0xf));
|
||||
|
||||
//jtag_tclk_clr(p);
|
||||
jtag_ir_shift(p, IR_CNTRL_SIG_16BIT);
|
||||
jtag_dr_shift_16(p, 0x1401/*1400*/);
|
||||
jtag_ir_shift(p, IR_DATA_16BIT);
|
||||
jtag_tclk_clr(p);
|
||||
jtag_tclk_set(p);
|
||||
jtag_dr_shift_16(p, value & 0xffff);
|
||||
jtag_tclk_clr(p);
|
||||
jtag_tclk_set(p);
|
||||
|
||||
jtag_dr_shift_16(p, 0x3ffd); // rewind PC
|
||||
jtag_tclk_clr(p);
|
||||
jtag_tclk_set(p);
|
||||
jtag_tclk_clr(p);
|
||||
|
||||
jtag_ir_shift(p, IR_ADDR_CAPTURE);
|
||||
jtag_dr_shift_20(p, 0);
|
||||
jtag_tclk_set(p);
|
||||
|
||||
jtag_ir_shift(p, IR_CNTRL_SIG_16BIT);
|
||||
jtag_dr_shift_16(p, 0x0501);
|
||||
jtag_tclk_clr(p);
|
||||
jtag_tclk_set(p);
|
||||
jtag_tclk_clr(p);
|
||||
|
||||
jtag_ir_shift(p, IR_DATA_CAPTURE);
|
||||
jtag_tclk_set(p);
|
||||
//jtag_dr_shift_20(p, 0);
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------*/
|
||||
static void jlfxv2_single_step( struct jtdev *p )
|
||||
{ // libmsp430 BIOS name: SingleStep
|
||||
|
||||
int i, timeout;
|
||||
uint16_t tmp;
|
||||
dbg_printc("single step\n");
|
||||
|
||||
// TODO: fix this. it only performs an instruction fetch but not much else
|
||||
|
||||
/*jtag_ir_shift(p, IR_EMEX_READ_CONTROL);
|
||||
timeout = 3000;
|
||||
for (i = 0; i < timeout; ++i)
|
||||
if (jtag_dr_shift_16(p, 0) & EEM_STOPPED)
|
||||
break;
|
||||
if (i == timeout) {
|
||||
printc_err("jlfxv2_single_step: EEM timeout\n");
|
||||
goto err;
|
||||
}*/
|
||||
|
||||
jtag_ir_shift(p, IR_EMEX_WRITE_CONTROL);
|
||||
jtag_dr_shift_16(p, EMU_CLK_EN | EEM_EN);
|
||||
|
||||
jtag_ir_shift(p, IR_CNTRL_SIG_16BIT);
|
||||
jtag_dr_shift_16(p, 0x1501);
|
||||
jtag_ir_shift(p, IR_CNTRL_SIG_CAPTURE);
|
||||
timeout = 50;
|
||||
for (i = 0; i < timeout; ++i) {
|
||||
tmp = jtag_dr_shift_16(p, 0);
|
||||
if (tmp != 0xffff && (tmp & 0x200) == 0x0200)
|
||||
break;
|
||||
}
|
||||
if (i == timeout) {
|
||||
printc_err("jlfxv2_single_step: JTAG sync timeout\n");
|
||||
goto err;
|
||||
}
|
||||
|
||||
jtag_ir_shift(p, IR_EMEX_WRITE_CONTROL);
|
||||
jtag_dr_shift_16(p, EMU_CLK_EN | CLEAR_STOP);
|
||||
jtag_dr_shift_16(p, EMU_CLK_EN | CLEAR_STOP | EEM_EN);
|
||||
|
||||
jtag_ir_shift(p, IR_CNTRL_SIG_16BIT);
|
||||
jtag_dr_shift_16(p, 0x1501);
|
||||
|
||||
jtag_ir_shift(p, IR_CNTRL_SIG_CAPTURE);
|
||||
timeout = 30000;
|
||||
for (i = 0; i < timeout; ++i) {
|
||||
if ((jtag_dr_shift_16(p, 0) & 8) == 0) break;
|
||||
|
||||
jtag_tclk_clr(p);
|
||||
jtag_tclk_set(p);
|
||||
|
||||
jtag_ir_shift(p, IR_CNTRL_SIG_CAPTURE);
|
||||
}
|
||||
if (i == timeout) {
|
||||
printc_err("jlfxv2_single_step: single-step timeout\n");
|
||||
goto err;
|
||||
}
|
||||
|
||||
jtag_ir_shift(p, IR_CNTRL_SIG_CAPTURE);
|
||||
timeout = 10000;
|
||||
for (i = 0; i < timeout; ++i) {
|
||||
jtag_tclk_clr(p);
|
||||
tmp = jtag_dr_shift_16(p, 0);
|
||||
jtag_tclk_set(p);
|
||||
|
||||
if ((tmp & CNTRL_SIG_CPUSUSP) == CNTRL_SIG_CPUSUSP) break;
|
||||
}
|
||||
if (i == timeout) {
|
||||
printc_err("jlfxv2_single_step: pipeline empty timeout\n");
|
||||
goto err;
|
||||
}
|
||||
|
||||
jtag_ir_shift(p, IR_CNTRL_SIG_16BIT);
|
||||
jtag_dr_shift_16(p, 0x0501);
|
||||
|
||||
return;
|
||||
err:
|
||||
p->failed = 1;
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------*/
|
||||
static unsigned int jlfxv2_set_breakpoint( struct jtdev *p,int bp_num, address_t bp_addr )
|
||||
{
|
||||
/* The breakpoint logic is explained in 'SLAU414c EEM.pdf' */
|
||||
/* A good overview is given with Figure 1-1 */
|
||||
/* MBx is TBx in EEM_defs.h */
|
||||
/* CPU Stop is BREAKREACT in EEM_defs.h */
|
||||
/* State Storage is STOR_REACT in EEM_defs.h */
|
||||
/* Cycle Counter is EVENT_REACT in EEM_defs.h */
|
||||
|
||||
// TODO: implement
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------*/
|
||||
static unsigned int jlfxv2_cpu_state( struct jtdev *p )
|
||||
{ // libmsp430 BIOS name: WaitForEem(?)
|
||||
jtag_ir_shift(p, IR_EMEX_READ_CONTROL);
|
||||
|
||||
if ((jtag_dr_shift_16(p, 0x0000) & EEM_STOPPED) == EEM_STOPPED) {
|
||||
dbg_printc("cpu_state: halted\n");
|
||||
return 1; /* halted */
|
||||
} else {
|
||||
dbg_printc("cpu_state: running\n");
|
||||
return 0; /* running */
|
||||
}
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------*/
|
||||
static int jlfxv2_get_config_fuses( struct jtdev *p )
|
||||
{ // always the same?
|
||||
jtag_ir_shift(p, IR_CONFIG_FUSES);
|
||||
|
||||
return jtag_dr_shift_8(p, 0);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
static void jlfxv2_context_save(struct jtdev *p, bool after_puc) {
|
||||
address_t wdtctl_a = (p->jtag_id == 0x89) ? 0x0120 : 0x015c,
|
||||
rst_vec = 0x0fffe,
|
||||
mab, entrypt_addr;
|
||||
|
||||
dbg_printc("context save, %s\n", after_puc?"after PUC":"normal");
|
||||
|
||||
jtag_ir_shift(p, IR_EMEX_WRITE_CONTROL);
|
||||
jtag_dr_shift_16(p, EMU_FEAT_EN | EMU_CLK_EN | CLEAR_STOP);
|
||||
jtag_ir_shift(p, IR_CNTRL_SIG_CAPTURE);
|
||||
jtag_dr_shift_16(p, 0);
|
||||
|
||||
/* ReadMemWordXv2 */
|
||||
jtag_tclk_clr(p);
|
||||
jtag_ir_shift(p, IR_ADDR_16BIT);
|
||||
jtag_dr_shift_20(p, wdtctl_a);
|
||||
jtag_tclk_set(p);
|
||||
jtag_tclk_clr(p);
|
||||
jtag_ir_shift(p, IR_DATA_CAPTURE);
|
||||
p->wdtctl = jtag_dr_shift_16(p, 0) & 0xff;
|
||||
jtag_tclk_set(p);
|
||||
jtag_tclk_clr(p);
|
||||
jtag_tclk_set(p);
|
||||
dbg_printc("WDTCTL: %04x\n", p->wdtctl);
|
||||
/* ReadMemWordXv2 */
|
||||
/* actually not using the result for this, but adding this makes it work
|
||||
* somehow */
|
||||
jtag_tclk_clr(p);
|
||||
jtag_ir_shift(p, IR_ADDR_16BIT);
|
||||
jtag_dr_shift_20(p, rst_vec);
|
||||
jtag_tclk_set(p);
|
||||
jtag_tclk_clr(p);
|
||||
jtag_ir_shift(p, IR_DATA_CAPTURE);
|
||||
entrypt_addr = jtag_dr_shift_16(p, 0);
|
||||
jtag_tclk_set(p);
|
||||
jtag_tclk_clr(p);
|
||||
jtag_tclk_set(p);
|
||||
dbg_printc("ENTRYPOINT: %04x\n", entrypt_addr);
|
||||
|
||||
jtag_ir_shift(p, IR_ADDR_CAPTURE);
|
||||
mab = demangle_mab(jtag_dr_shift_20(p, 0));
|
||||
dbg_printc("PC MAB: %05x\n", mab);
|
||||
//mab = rst_vec + 4;
|
||||
|
||||
/* back up program counter */
|
||||
if (after_puc) {
|
||||
p->regs[0] = rst_vec; /* yeah.. */
|
||||
} else {
|
||||
p->regs[0] = mab - 4;
|
||||
}
|
||||
|
||||
if (p->regs[0] == rst_vec) {
|
||||
p->regs[0] = jtag_read_mem(p, 16, rst_vec);
|
||||
dbg_printc("ENTRY TRY1: %04x\n", p->regs[0]);
|
||||
if (p->regs[0] == 0xffff || p->regs[0] == 0x3fff) {
|
||||
p->regs[0] = jtag_read_mem(p, 16, rst_vec);
|
||||
dbg_printc("ENTRY TRY2: %04x\n", p->regs[0]);
|
||||
}
|
||||
}
|
||||
|
||||
/* disable watchdog */
|
||||
//p->wdtctl = jtag_read_mem(p, 16, wdtctl_a) & 0xff;
|
||||
dbg_printc("WDTCTL: %04x\n", p->wdtctl);
|
||||
jtag_write_mem(p, 16, wdtctl_a, p->wdtctl | 0x5a80);
|
||||
|
||||
/* also back up stack pointer & status register */
|
||||
p->regs[1] = jtag_read_reg(p, 1);
|
||||
p->regs[2] = jtag_read_reg(p, 2);
|
||||
|
||||
const static uint16_t data[] = {0x3fff,0x3fff,0x3fff};
|
||||
jtag_write_mem_quick(p, 0x00004, sizeof(data)/sizeof(*data), data);
|
||||
}
|
||||
static void jlfxv2_context_restore(struct jtdev *p) {
|
||||
dbg_printc("context restore\n");
|
||||
|
||||
/* basically the inverse of context_save */
|
||||
address_t wdtctl_a = (p->jtag_id == 0x89) ? 0x0120 : 0x015c;
|
||||
|
||||
jtag_write_reg(p, 1, p->regs[1]);
|
||||
jtag_write_reg(p, 2, p->regs[2]);
|
||||
|
||||
jtag_write_mem(p, 16, wdtctl_a, p->wdtctl | 0x5a00);
|
||||
|
||||
jlfxv2_set_pc(p, p->regs[0]);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
const struct jtaglib_funcs jlf_cpuxv2 = {
|
||||
.jlf_get_device = jlfxv2_get_device,
|
||||
|
||||
.jlf_read_mem = jlfxv2_read_mem,
|
||||
.jlf_read_mem_quick = jlfxv2_read_mem_quick,
|
||||
.jlf_write_mem = jlfxv2_write_mem,
|
||||
.jlf_write_mem_quick = jlfxv2_write_mem_quick,
|
||||
|
||||
.jlf_execute_puc = jlfxv2_execute_puc,
|
||||
.jlf_release_device = jlfxv2_release_device,
|
||||
|
||||
.jlf_verify_mem = jlfxv2_verify_mem,
|
||||
.jlf_erase_check = jlfxv2_erase_check,
|
||||
|
||||
.jlf_write_flash = jlfxv2_write_flash,
|
||||
.jlf_erase_flash = jlfxv2_erase_flash,
|
||||
|
||||
.jlf_context_save = jlfxv2_context_save,
|
||||
.jlf_context_restore = jlfxv2_context_restore,
|
||||
.jlf_regs_update = jtag_dev_default_regs_update,
|
||||
.jlf_regs_flush = jtag_dev_default_regs_flush,
|
||||
|
||||
.jlf_read_reg = jlfxv2_read_reg,
|
||||
.jlf_write_reg = jlfxv2_write_reg,
|
||||
.jlf_single_step = jlfxv2_single_step,
|
||||
.jlf_set_breakpoint = jlfxv2_set_breakpoint,
|
||||
.jlf_cpu_state = jlfxv2_cpu_state,
|
||||
.jlf_get_config_fuses = jlfxv2_get_config_fuses,
|
||||
};
|
||||
|
|
@ -1,77 +0,0 @@
|
|||
|
||||
#include "jtaglib.h"
|
||||
#include "eem_defs.h"
|
||||
|
||||
/* Flash erasing modes */
|
||||
#define JTAG_ERASE_MASS 0xA506
|
||||
#define JTAG_ERASE_MAIN 0xA504
|
||||
#define JTAG_ERASE_SGMT 0xA502
|
||||
|
||||
#define JTAG_ID_IS_XV2(x) ((x)==0x91||(x)==0x95||(x)==0x98||(x)==0x99)
|
||||
|
||||
/* Instructions for the JTAG control signal register in reverse bit order
|
||||
*/
|
||||
#define IR_CNTRL_SIG_16BIT 0xC8 /* 0x13 */
|
||||
#define IR_CNTRL_SIG_CAPTURE 0x28 /* 0x14 */
|
||||
#define IR_CNTRL_SIG_RELEASE 0xA8 /* 0x15 */
|
||||
#define IR_COREIP_ID 0xE8 /* 0x17 */
|
||||
/* Instructions for the JTAG data register */
|
||||
#define IR_DATA_16BIT 0x82 /* 0x41 */
|
||||
#define IR_DATA_CAPTURE 0x42 /* 0x42 */
|
||||
#define IR_DATA_QUICK 0xC2 /* 0x43 */
|
||||
/* Instructions for the JTAG address register */
|
||||
#define IR_ADDR_16BIT 0xC1 /* 0x83 */
|
||||
#define IR_ADDR_CAPTURE 0x21 /* 0x84 */
|
||||
#define IR_DATA_TO_ADDR 0xA1 /* 0x85 */
|
||||
#define IR_DEVICE_ID 0xE1 /* 0x87 */
|
||||
/* Instructions for the JTAG PSA mode */
|
||||
#define IR_DATA_PSA 0x22 /* 0x44 */
|
||||
#define IR_SHIFT_OUT_PSA 0x62 /* 0x46 */
|
||||
/* Instructions for the JTAG Fuse */
|
||||
#define IR_PREPARE_BLOW 0x44 /* 0x22 */
|
||||
#define IR_EX_BLOW 0x24 /* 0x24 */
|
||||
/* Instructions for the JTAG mailbox */
|
||||
#define IR_TEST_REG 0x54 /* 0x2A */
|
||||
/* Instructions for the Configuration Fuse */
|
||||
#define IR_CONFIG_FUSES 0x94
|
||||
/* Bypass instruction */
|
||||
#define IR_BYPASS 0xFF /* 0xFF */
|
||||
/* Instructions for the EEM */
|
||||
#define IR_EMEX_DATA_EXCHANGE 0x90 /* 0x09 */
|
||||
#define IR_EMEX_WRITE_CONTROL 0x30 /* 0x0C */
|
||||
#define IR_EMEX_READ_CONTROL 0xD0 /* 0x0B */
|
||||
|
||||
/* EEM stuff */
|
||||
#define EEM_STOPPED 0x0080
|
||||
#define EEM_EN 0x0001
|
||||
#define CLEAR_STOP 0x0002
|
||||
#define EMU_CLK_EN 0x0004
|
||||
|
||||
#define CNTRL_SIG_CPUSUSP (1<<8)
|
||||
|
||||
#define jtag_tms_set(p) p->f->jtdev_tms(p, 1)
|
||||
#define jtag_tms_clr(p) p->f->jtdev_tms(p, 0)
|
||||
#define jtag_tck_set(p) p->f->jtdev_tck(p, 1)
|
||||
#define jtag_tck_clr(p) p->f->jtdev_tck(p, 0)
|
||||
#define jtag_tdi_set(p) p->f->jtdev_tdi(p, 1)
|
||||
#define jtag_tdi_clr(p) p->f->jtdev_tdi(p, 0)
|
||||
#define jtag_tclk_set(p) p->f->jtdev_tclk(p, 1)
|
||||
#define jtag_tclk_clr(p) p->f->jtdev_tclk(p, 0)
|
||||
#define jtag_rst_set(p) p->f->jtdev_rst(p, 1)
|
||||
#define jtag_rst_clr(p) p->f->jtdev_rst(p, 0)
|
||||
#define jtag_tst_set(p) p->f->jtdev_tst(p, 1)
|
||||
#define jtag_tst_clr(p) p->f->jtdev_tst(p, 0)
|
||||
|
||||
#define jtag_led_green_on(p) p->f->jtdev_led_green(p, 1)
|
||||
#define jtag_led_green_off(p) p->f->jtdev_led_green(p, 0)
|
||||
#define jtag_led_red_on(p) p->f->jtdev_led_red(p, 1)
|
||||
#define jtag_led_red_off(p) p->f->jtdev_led_red(p, 0)
|
||||
|
||||
#define jtag_ir_shift(p, ir) p->f->jtdev_ir_shift(p, ir)
|
||||
#define jtag_dr_shift_8(p, dr) p->f->jtdev_dr_shift_8(p, dr)
|
||||
#define jtag_dr_shift_16(p, dr) p->f->jtdev_dr_shift_16(p, dr)
|
||||
#define jtag_dr_shift_20(p, dr) p->f->jtdev_dr_shift_20(p, dr)
|
||||
#define jtag_tms_sequence(p, bits, tms) p->f->jtdev_tms_sequence(p, bits, tms)
|
||||
#define jtag_init_dap(p) p->f->jtdev_init_dap(p)
|
||||
|
||||
|
|
@ -22,7 +22,7 @@
|
|||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include "jtaglib.h"
|
||||
#include "jtdev.h"
|
||||
#include "output.h"
|
||||
|
||||
#if defined(__linux__) || \
|
||||
|
@ -354,13 +354,6 @@ const struct jtdev_func jtdev_func_pif = {
|
|||
.jtdev_tclk_get = jtpif_tclk_get,
|
||||
.jtdev_tclk_strobe = jtpif_tclk_strobe,
|
||||
.jtdev_led_green = jtpif_led_green,
|
||||
.jtdev_led_red = jtpif_led_red,
|
||||
|
||||
.jtdev_ir_shift = jtag_default_ir_shift,
|
||||
.jtdev_dr_shift_8 = jtag_default_dr_shift_8,
|
||||
.jtdev_dr_shift_16 = jtag_default_dr_shift_16,
|
||||
.jtdev_dr_shift_20 = jtag_default_dr_shift_20,
|
||||
.jtdev_tms_sequence= jtag_default_tms_sequence,
|
||||
.jtdev_init_dap = jtag_default_init_dap
|
||||
.jtdev_led_red = jtpif_led_red
|
||||
};
|
||||
|
||||
|
|
|
@ -22,25 +22,16 @@
|
|||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "device.h"
|
||||
#include "jtaglib_defs.h"
|
||||
|
||||
struct jtdev_func;
|
||||
struct jtdev {
|
||||
struct device base;
|
||||
int port;
|
||||
uint8_t data_register;
|
||||
uint8_t control_register;
|
||||
uint8_t jtag_id;
|
||||
uint8_t cpu_type;
|
||||
int failed;
|
||||
const struct jtdev_func * f;
|
||||
|
||||
address_t regs[DEVICE_NUM_REGS];
|
||||
uint16_t wdtctl;
|
||||
};
|
||||
|
||||
struct jtdev_func {
|
||||
struct jtdev_func{
|
||||
/* Initialize/destroy a parallel-port JTAG interface. jtdev_open()
|
||||
* returns 0 on success or -1 if an error occurs.
|
||||
*
|
||||
|
@ -73,13 +64,6 @@ struct jtdev_func {
|
|||
void (*jtdev_led_green)(struct jtdev *p, int out);
|
||||
void (*jtdev_led_red)(struct jtdev *p, int out);
|
||||
|
||||
/* Optional functions implementing higher-level stuff */
|
||||
uint8_t (*jtdev_ir_shift)(struct jtdev *p, uint8_t ir);
|
||||
uint8_t (*jtdev_dr_shift_8)(struct jtdev *p, uint8_t dr);
|
||||
uint16_t (*jtdev_dr_shift_16)(struct jtdev *p, uint16_t dr);
|
||||
uint32_t (*jtdev_dr_shift_20)(struct jtdev *p, uint32_t dr);
|
||||
void (*jtdev_tms_sequence)(struct jtdev *p, int bits, unsigned int value);
|
||||
void (*jtdev_init_dap)(struct jtdev *p);
|
||||
};
|
||||
|
||||
extern const struct jtdev_func jtdev_func_pif;
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include "jtaglib.h"
|
||||
#include "jtdev.h"
|
||||
#include "output.h"
|
||||
|
||||
#if defined(__linux__)
|
||||
|
@ -186,8 +186,7 @@ static void jtbp_close(struct jtdev *p)
|
|||
|
||||
out_buff = 0x0f;
|
||||
// Don't care if this fails, user can just power cycle the bus pirate
|
||||
if(write(p->port, &out_buff, 1))
|
||||
;
|
||||
if(write(p->port, &out_buff, 1));
|
||||
|
||||
close(p->port);
|
||||
}
|
||||
|
@ -352,13 +351,6 @@ const struct jtdev_func jtdev_func_bp = {
|
|||
.jtdev_tclk_get = jtbp_tclk_get,
|
||||
.jtdev_tclk_strobe = jtbp_tclk_strobe,
|
||||
.jtdev_led_green = jtbp_led_green,
|
||||
.jtdev_led_red = jtbp_led_red,
|
||||
|
||||
.jtdev_ir_shift = jtag_default_ir_shift,
|
||||
.jtdev_dr_shift_8 = jtag_default_dr_shift_8,
|
||||
.jtdev_dr_shift_16 = jtag_default_dr_shift_16,
|
||||
.jtdev_dr_shift_20 = jtag_default_dr_shift_20,
|
||||
.jtdev_tms_sequence= jtag_default_tms_sequence,
|
||||
.jtdev_init_dap = jtag_default_init_dap
|
||||
.jtdev_led_red = jtbp_led_red
|
||||
};
|
||||
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include "jtaglib.h"
|
||||
#include "jtdev.h"
|
||||
#include "output.h"
|
||||
|
||||
#if defined(__linux__) || \
|
||||
|
@ -263,12 +263,5 @@ const struct jtdev_func jtdev_func_gpio = {
|
|||
.jtdev_tclk_get = jtgpio_tclk_get,
|
||||
.jtdev_tclk_strobe = jtgpio_tclk_strobe,
|
||||
.jtdev_led_green = jtgpio_led_green,
|
||||
.jtdev_led_red = jtgpio_led_red,
|
||||
|
||||
.jtdev_ir_shift = jtag_default_ir_shift,
|
||||
.jtdev_dr_shift_8 = jtag_default_dr_shift_8,
|
||||
.jtdev_dr_shift_16 = jtag_default_dr_shift_16,
|
||||
.jtdev_dr_shift_20 = jtag_default_dr_shift_20,
|
||||
.jtdev_tms_sequence= jtag_default_tms_sequence,
|
||||
.jtdev_init_dap = jtag_default_init_dap
|
||||
.jtdev_led_red = jtgpio_led_red
|
||||
};
|
||||
|
|
379
drivers/mehfet.c
379
drivers/mehfet.c
|
@ -1,379 +0,0 @@
|
|||
/* MSPDebug - debugging tool for MSP430 MCUs
|
||||
* Copyright (C) 2021 sys64738@disroot.org
|
||||
*
|
||||
* 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "util.h"
|
||||
#include "output.h"
|
||||
#include "ctrlc.h"
|
||||
#include "jtaglib.h"
|
||||
#include "mehfet_proto.h"
|
||||
#include "mehfet_xport.h"
|
||||
|
||||
#include "mehfet.h"
|
||||
|
||||
|
||||
struct mehfet_device {
|
||||
struct jtdev jtag;
|
||||
transport_t trans;
|
||||
enum mehfet_conn connstat;
|
||||
};
|
||||
|
||||
|
||||
/*extern void __builtin_trap(void);*/
|
||||
#define NO_LL_JTAG_BP 0
|
||||
#define no_ll_jtag() \
|
||||
do { \
|
||||
printc_err("mehfet: %s: low-lewel JTAG function not implemented!\n", __func__); \
|
||||
p->failed = 1; \
|
||||
if (NO_LL_JTAG_BP) /*__builtin_trap()*/; \
|
||||
} while (0) \
|
||||
|
||||
|
||||
#define JTMF_GET_DEV(p) ((struct mehfet_device*)((size_t)(p) - \
|
||||
offsetof(struct mehfet_device, jtag))) \
|
||||
|
||||
|
||||
static int jtmf_open(struct jtdev* p, const char* device)
|
||||
{
|
||||
printc_err("mehfet: %s should not get called.\n", __func__);
|
||||
p->failed = 1;
|
||||
return -1;
|
||||
}
|
||||
static void jtmf_close(struct jtdev* p)
|
||||
{
|
||||
printc_err("mehfet: %s should not get called.\n", __func__);
|
||||
p->failed = 1;
|
||||
}
|
||||
static void jtmf_power_on(struct jtdev* p)
|
||||
{
|
||||
printc_err("mehfet: %s should not get called.\n", __func__);
|
||||
p->failed = 1;
|
||||
}
|
||||
static void jtmf_power_off(struct jtdev* p)
|
||||
{
|
||||
printc_err("mehfet: %s should not get called.\n", __func__);
|
||||
p->failed = 1;
|
||||
}
|
||||
static void jtmf_connect(struct jtdev* p)
|
||||
{
|
||||
printc_err("mehfet: %s should not get called.\n", __func__);
|
||||
p->failed = 1;
|
||||
}
|
||||
static void jtmf_release(struct jtdev* p)
|
||||
{
|
||||
printc_err("mehfet: %s should not get called.\n", __func__);
|
||||
p->failed = 1;
|
||||
}
|
||||
|
||||
static void jtmf_tck(struct jtdev* p, int _) { (void)_; no_ll_jtag(); }
|
||||
static void jtmf_tms(struct jtdev* p, int _) { (void)_; no_ll_jtag(); }
|
||||
static void jtmf_tdi(struct jtdev* p, int _) { (void)_; no_ll_jtag(); }
|
||||
static void jtmf_rst(struct jtdev* p, int _) { (void)_; no_ll_jtag(); }
|
||||
static void jtmf_tst(struct jtdev* p, int _) { (void)_; no_ll_jtag(); }
|
||||
static int jtmf_tdo_get(struct jtdev* p) { no_ll_jtag(); return 0; }
|
||||
|
||||
static void jtmf_tclk(struct jtdev* p, int out)
|
||||
{
|
||||
struct mehfet_device* d = JTMF_GET_DEV(p);
|
||||
|
||||
int r = mehfet_cmd_tclk_edge(d->trans, out);
|
||||
if (r < 0) p->failed = 1;
|
||||
}
|
||||
static int jtmf_tclk_get(struct jtdev* p)
|
||||
{
|
||||
struct mehfet_device* d = JTMF_GET_DEV(p);
|
||||
int ret = 1;
|
||||
|
||||
enum mehfet_lines lines = 0;
|
||||
int r = mehfet_cmd_get_old_lines(d->trans, &lines);
|
||||
if (r < 0) {
|
||||
p->failed = 1;
|
||||
} else {
|
||||
ret = (lines & mehfet_line_tclk) ? 1 : 0;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
static void jtmf_tclk_strobe(struct jtdev* p, unsigned int count)
|
||||
{
|
||||
struct mehfet_device* d = JTMF_GET_DEV(p);
|
||||
|
||||
int r = mehfet_cmd_tclk_burst(d->trans, count);
|
||||
if (r < 0) p->failed = 1;
|
||||
}
|
||||
|
||||
/* MehFET has no leds */
|
||||
static void jtmf_led_green(struct jtdev* p, int out) { (void)p; (void)out; }
|
||||
static void jtmf_led_red (struct jtdev* p, int out) { (void)p; (void)out; }
|
||||
|
||||
static uint8_t jtmf_ir_shift(struct jtdev *p, uint8_t ir)
|
||||
{
|
||||
struct mehfet_device* d = JTMF_GET_DEV(p);
|
||||
|
||||
uint8_t ret = 0;
|
||||
int r = mehfet_cmd_irshift(d->trans, ir, &ret);
|
||||
if (r < 0) p->failed = 1;
|
||||
|
||||
return ret;
|
||||
}
|
||||
static uint8_t jtmf_dr_shift_8(struct jtdev *p, uint8_t dr)
|
||||
{
|
||||
struct mehfet_device* d = JTMF_GET_DEV(p);
|
||||
|
||||
uint8_t ret = 0;
|
||||
int r = mehfet_cmd_drshift(d->trans, 8, &dr, &ret);
|
||||
if (r < 0) p->failed = 1;
|
||||
|
||||
return ret;
|
||||
}
|
||||
static uint16_t jtmf_dr_shift_16(struct jtdev *p, uint16_t dr)
|
||||
{
|
||||
struct mehfet_device* d = JTMF_GET_DEV(p);
|
||||
|
||||
uint8_t inbuf[2] = { dr & 0xff, (dr >> 8) & 0xff };
|
||||
uint8_t outbuf[2];
|
||||
int r = mehfet_cmd_drshift(d->trans, 16, inbuf, outbuf);
|
||||
if (r < 0) p->failed = 1;
|
||||
|
||||
return outbuf[0] | ((uint16_t)outbuf[1] << 8);
|
||||
}
|
||||
static uint32_t jtmf_dr_shift_20(struct jtdev *p, uint32_t dr)
|
||||
{
|
||||
struct mehfet_device* d = JTMF_GET_DEV(p);
|
||||
|
||||
uint8_t inbuf[3] = { dr & 0xff, (dr >> 8) & 0xff, (dr >> 16) & 0x0f };
|
||||
uint8_t outbuf[3];
|
||||
int r = mehfet_cmd_drshift(d->trans, 20, inbuf, outbuf);
|
||||
if (r < 0) p->failed = 1;
|
||||
|
||||
return outbuf[0] | ((uint32_t)outbuf[1] << 8) | ((uint32_t)outbuf[2] << 16);
|
||||
}
|
||||
static void jtmf_tms_sequence(struct jtdev *p, int bits, unsigned int value)
|
||||
{
|
||||
struct mehfet_device* d = JTMF_GET_DEV(p);
|
||||
|
||||
enum mehfet_lines lines = 0;
|
||||
int r = mehfet_cmd_get_old_lines(d->trans, &lines);
|
||||
if (r < 0) {
|
||||
p->failed = 1;
|
||||
return;
|
||||
}
|
||||
|
||||
uint8_t dbuf[4] = { value & 0xff, (value >> 8) & 0xff,
|
||||
(value >> 16) & 0xff, (value >> 24) & 0xff };
|
||||
r = mehfet_cmd_tms_seq(d->trans, lines & mehfet_line_tdi, bits, dbuf);
|
||||
if (r < 0) p->failed = 1;
|
||||
}
|
||||
static void jtmf_init_dap(struct jtdev *p)
|
||||
{
|
||||
struct mehfet_device* dev = JTMF_GET_DEV(p);
|
||||
|
||||
enum mehfet_resettap_status stat = 0;
|
||||
int r = mehfet_cmd_reset_tap(dev->trans, mehfet_rsttap_do_reset
|
||||
| mehfet_rsttap_fuse_do, &stat);
|
||||
|
||||
if (r < 0) p->failed = 1;
|
||||
}
|
||||
|
||||
|
||||
static const struct jtdev_func jtdev_func_mehfet = {
|
||||
.jtdev_open = jtmf_open,
|
||||
.jtdev_close = jtmf_close,
|
||||
.jtdev_power_on = jtmf_power_on,
|
||||
.jtdev_power_off = jtmf_power_off,
|
||||
.jtdev_connect = jtmf_connect,
|
||||
.jtdev_release = jtmf_release,
|
||||
.jtdev_tck = jtmf_tck,
|
||||
.jtdev_tms = jtmf_tms,
|
||||
.jtdev_tdi = jtmf_tdi,
|
||||
.jtdev_rst = jtmf_rst,
|
||||
.jtdev_tst = jtmf_tst,
|
||||
.jtdev_tdo_get = jtmf_tdo_get,
|
||||
.jtdev_tclk = jtmf_tclk,
|
||||
.jtdev_tclk_get = jtmf_tclk_get,
|
||||
.jtdev_tclk_strobe = jtmf_tclk_strobe,
|
||||
.jtdev_led_green = jtmf_led_green,
|
||||
.jtdev_led_red = jtmf_led_red,
|
||||
|
||||
.jtdev_ir_shift = jtmf_ir_shift,
|
||||
.jtdev_dr_shift_8 = jtmf_dr_shift_8,
|
||||
.jtdev_dr_shift_16 = jtmf_dr_shift_16,
|
||||
.jtdev_dr_shift_20 = jtmf_dr_shift_20,
|
||||
.jtdev_tms_sequence= jtmf_tms_sequence,
|
||||
.jtdev_init_dap = jtmf_init_dap
|
||||
};
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
static int check_dev_ok(struct mehfet_device* dev, const struct device_args* args,
|
||||
enum mehfet_conn* useconn) {
|
||||
transport_t t = dev->trans;
|
||||
struct mehfet_info info;
|
||||
int r;
|
||||
|
||||
r = mehfet_cmd_info(t, &info);
|
||||
if (r < 0) return r;
|
||||
|
||||
printc_dbg("mehfet: MehFET %s\n", info.devicename);
|
||||
free(info.devicename);
|
||||
|
||||
if (info.proto_version < MEHFET_PROTO_VER_MIN_SUPPORTED) {
|
||||
printc_err("mehfet: device has protocol version %04x, "
|
||||
"need at least %04x\n", info.proto_version,
|
||||
MEHFET_PROTO_VER_MIN_SUPPORTED);
|
||||
return -1;
|
||||
}
|
||||
if (info.proto_version > MEHFET_PROTO_VER) {
|
||||
printc_err("mehfet: device has newer protocol version %04x "
|
||||
"supporting at most %04x\n", info.proto_version,
|
||||
MEHFET_PROTO_VER);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (args->flags & DEVICE_FLAG_JTAG) {
|
||||
if (!(info.caps & (mehfet_cap_jtag_noentry | mehfet_cap_jtag_entryseq))) {
|
||||
printc_err("mehfet: Cannot do JTAG, device doesn't have the capability\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
// devices that don't need one will probably work when given an entry
|
||||
// sequence. no good way of doing a proper autodetect sadly
|
||||
if (info.caps & mehfet_cap_jtag_entryseq)
|
||||
*useconn = mehfet_conn_jtag_entryseq;
|
||||
else
|
||||
*useconn = mehfet_conn_jtag_noentry;
|
||||
} else {
|
||||
if (!(info.caps & mehfet_cap_sbw_entryseq)) {
|
||||
printc_err("mehfet: Cannot do Spy-Bi-Wire, device doesn't have the capability\n");
|
||||
return -1;
|
||||
}
|
||||
*useconn = mehfet_conn_sbw_entryseq;
|
||||
}
|
||||
|
||||
if (args->flags & DEVICE_FLAG_FORCE_RESET)
|
||||
*useconn |= mehfet_conn_nrstmask;
|
||||
|
||||
mehfet_transport_set_buf_size(t, (int)info.packet_buf_size);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void mehfet_destroy(device_t dev_base) {
|
||||
struct mehfet_device* dev = (struct mehfet_device*)dev_base;
|
||||
|
||||
if (!dev) return;
|
||||
|
||||
#ifdef DEBUG_MEHFET_DRIVER
|
||||
printc_dbg("mehfet: releasing device & disconnecting\n");
|
||||
#endif
|
||||
|
||||
if (dev->trans) {
|
||||
jtag_release_device(&dev->jtag, 0xfffe); // 0xfffe=reset address : POR
|
||||
|
||||
mehfet_cmd_disconnect(dev->trans);
|
||||
|
||||
dev->trans->ops->destroy(dev->trans);
|
||||
dev->trans = NULL;
|
||||
}
|
||||
|
||||
free(dev);
|
||||
}
|
||||
|
||||
static device_t mehfet_open(const struct device_args* args) {
|
||||
struct mehfet_device* dev;
|
||||
int r;
|
||||
|
||||
if ((args->flags & DEVICE_FLAG_TTY)) {
|
||||
printc_err("mehfet: this driver does not support TTY access\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
dev = calloc(1, sizeof(*dev));
|
||||
if (!dev) {
|
||||
printc_err("mehfet: malloc: %s\n", last_error());
|
||||
return NULL;
|
||||
}
|
||||
|
||||
dev->jtag.base.type = &device_mehfet;
|
||||
dev->jtag.base.max_breakpoints = 2; // TODO
|
||||
dev->jtag.base.need_probe = 1; // TODO
|
||||
dev->jtag.f = &jtdev_func_mehfet;
|
||||
|
||||
// the MehFET currently doesn't have a designated PID, so we can't really
|
||||
// default to one.
|
||||
dev->trans = mehfet_transport_open(args->path,
|
||||
((args->flags & DEVICE_FLAG_HAS_VID_PID) ? &args->vid : NULL),
|
||||
((args->flags & DEVICE_FLAG_HAS_VID_PID) ? &args->pid : NULL),
|
||||
args->requested_serial);
|
||||
if (!dev->trans) goto FAIL;
|
||||
|
||||
enum mehfet_conn useconn;
|
||||
r = check_dev_ok(dev, args, &useconn);
|
||||
if (r < 0) goto FAIL;
|
||||
|
||||
r = mehfet_cmd_connect(dev->trans, useconn);
|
||||
if (r < 0) goto FAIL;
|
||||
|
||||
r = mehfet_cmd_status(dev->trans, &dev->connstat);
|
||||
if (r < 0) goto FAIL;
|
||||
|
||||
if (dev->connstat != (useconn & mehfet_conn_typemask)) {
|
||||
printc_err("mehfet: could not create connection to device\n");
|
||||
goto FAIL;
|
||||
}
|
||||
|
||||
r = jtag_dev_init(&dev->jtag);
|
||||
if (r < 0) goto FAIL;
|
||||
|
||||
// JTAG fuse check has been performed, so we can now switch to a
|
||||
// higher-speed physical transport suitable for ~350 kHz TCLK strobes used
|
||||
// in (and required for) flash programming
|
||||
r = mehfet_cmd_set_clkspeed(dev->trans, true);
|
||||
if (r < 0) goto FAIL;
|
||||
|
||||
#ifdef DEBUG_MEHFET_DRIVER
|
||||
printc_dbg("mehfet: device opened\n");
|
||||
#endif
|
||||
|
||||
return (device_t)dev;
|
||||
|
||||
FAIL:
|
||||
mehfet_destroy((device_t)dev);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const struct device_class device_mehfet = {
|
||||
.name = "mehfet",
|
||||
.help = "MehFET USB JTAG/SBW device",
|
||||
.open = mehfet_open,
|
||||
.destroy = mehfet_destroy,
|
||||
.readmem = jtag_dev_readmem,
|
||||
.writemem = jtag_dev_writemem,
|
||||
.getregs = jtag_dev_getregs,
|
||||
.setregs = jtag_dev_setregs,
|
||||
.ctl = jtag_dev_ctl,
|
||||
.poll = jtag_dev_poll,
|
||||
.erase = jtag_dev_erase,
|
||||
.getconfigfuses = jtag_dev_getconfigfuses
|
||||
};
|
||||
|
|
@ -1,27 +0,0 @@
|
|||
/* MSPDebug - debugging tool for MSP430 MCUs
|
||||
* Copyright (C) 2021, sys64738@disroot.org
|
||||
*
|
||||
* 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef MEHFET_H_
|
||||
#define MEHFET_H_
|
||||
|
||||
#include "device.h"
|
||||
|
||||
extern const struct device_class device_mehfet;
|
||||
|
||||
#endif
|
||||
|
|
@ -1,561 +0,0 @@
|
|||
/* MSPDebug - debugging tool for MSP430 MCUs
|
||||
* Copyright (C) 2021 sys64738@disroot.org
|
||||
*
|
||||
* 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "mehfet_xport.h"
|
||||
#include "output.h"
|
||||
#include "util.h"
|
||||
|
||||
#include "mehfet_proto.h"
|
||||
|
||||
// TODO: replace '64' by transport buf size
|
||||
|
||||
int mehfet_cmd_info(transport_t t, struct mehfet_info* info) {
|
||||
if (!info) return -1;
|
||||
|
||||
uint8_t buf[64];
|
||||
int r;
|
||||
|
||||
r = mehfet_send_raw(t, mehfet_info, 0, NULL);
|
||||
if (r < 0) return r;
|
||||
|
||||
uint8_t stat = 0;
|
||||
int len = sizeof buf;
|
||||
r = mehfet_recv_raw(t, &stat, &len, buf);
|
||||
if (r < 0) return r;
|
||||
r = mehfet_err_on_stat("Info", stat, len, buf);
|
||||
if (r < 0) return r;
|
||||
|
||||
if (len < 8) {
|
||||
printc_err("mehfet: Info response too short: %d < 8\n", len);
|
||||
return -1;
|
||||
}
|
||||
|
||||
info->caps = buf[0] | ((uint32_t)buf[1] << 8)
|
||||
| ((uint32_t)buf[2] << 16) | ((uint32_t)buf[3] << 24);
|
||||
info->proto_version = buf[4] | ((uint16_t)buf[5] << 8);
|
||||
info->packet_buf_size = 1u << buf[6];
|
||||
// buf[7]: reserved
|
||||
|
||||
if (len > 9) { // len includes the null terminator
|
||||
char* str = calloc(len - 8, 1);
|
||||
memcpy(str, &buf[8], len - 8);
|
||||
str[len - 9] = 0;
|
||||
|
||||
info->devicename = str;
|
||||
}
|
||||
|
||||
#ifdef DEBUG_MEHFET_PROTO_DRIVER
|
||||
printc_dbg("mehfet: Info(): '%s' caps=0x%x, protover=0x%04x, pktsize=0x%x\n",
|
||||
info->devicename ? info->devicename : "<none>",
|
||||
info->caps, info->proto_version, info->packet_buf_size);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
int mehfet_cmd_status(transport_t t, enum mehfet_conn* ret) {
|
||||
if (!ret) return -1;
|
||||
|
||||
uint8_t buf[64];
|
||||
int r;
|
||||
|
||||
r = mehfet_send_raw(t, mehfet_status, 0, NULL);
|
||||
if (r < 0) return r;
|
||||
|
||||
uint8_t stat = 0;
|
||||
int len = sizeof buf;
|
||||
r = mehfet_recv_raw(t, &stat, &len, buf);
|
||||
if (r < 0) return r;
|
||||
r = mehfet_err_on_stat("Status", stat, len, buf);
|
||||
if (r < 0) return r;
|
||||
|
||||
if (len != 1) {
|
||||
printc_err("mehfet: Status response wrong length: %d != 1\n", len);
|
||||
return -1;
|
||||
}
|
||||
|
||||
*ret = buf[0];
|
||||
|
||||
#ifdef DEBUG_MEHFET_PROTO_DRIVER
|
||||
printc_dbg("mehfet: Status(): %hhu\n", *ret);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
int mehfet_cmd_connect(transport_t t, enum mehfet_conn conn) {
|
||||
uint8_t buf[64];
|
||||
int r;
|
||||
|
||||
buf[0] = conn;
|
||||
r = mehfet_send_raw(t, mehfet_connect, 1, buf);
|
||||
if (r < 0) return r;
|
||||
|
||||
uint8_t stat = 0;
|
||||
int len = sizeof buf;
|
||||
r = mehfet_recv_raw(t, &stat, &len, buf);
|
||||
if (r < 0) return r;
|
||||
r = mehfet_err_on_stat("Connect", stat, len, buf);
|
||||
if (r < 0) return r;
|
||||
|
||||
if (len != 0) {
|
||||
printc_err("mehfet: Connect response wrong length: %d != 0\n", len);
|
||||
return -1;
|
||||
}
|
||||
|
||||
#ifdef DEBUG_MEHFET_PROTO_DRIVER
|
||||
printc_dbg("mehfet: Connect(0x%x)\n", conn);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
int mehfet_cmd_disconnect(transport_t t) {
|
||||
uint8_t buf[64];
|
||||
int r;
|
||||
|
||||
r = mehfet_send_raw(t, mehfet_disconnect, 0, NULL);
|
||||
if (r < 0) return r;
|
||||
|
||||
uint8_t stat = 0;
|
||||
int len = sizeof buf;
|
||||
r = mehfet_recv_raw(t, &stat, &len, buf);
|
||||
if (r < 0) return r;
|
||||
r = mehfet_err_on_stat("Disconnect", stat, len, buf);
|
||||
if (r < 0) return r;
|
||||
|
||||
if (len != 0) {
|
||||
printc_err("mehfet: Disconnect response wrong length: %d != 0\n", len);
|
||||
return -1;
|
||||
}
|
||||
|
||||
#ifdef DEBUG_MEHFET_PROTO_DRIVER
|
||||
printc_dbg("mehfet: Disconnect()\n");
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
int mehfet_cmd_delay(transport_t t, bool us, bool exact, uint32_t time) {
|
||||
if (time >= (1u << 30)) return -1; // too large
|
||||
|
||||
uint8_t buf[64];
|
||||
int r;
|
||||
|
||||
for (size_t i = 0; i < 4; ++i) buf[i] = (time >> (i*8)) & 0xff;
|
||||
if (us) buf[3] |= 0x40;
|
||||
if (exact) buf[3] |= 0x80;
|
||||
|
||||
r = mehfet_send_raw(t, mehfet_delay, 4, buf);
|
||||
if (r < 0) return r;
|
||||
|
||||
uint8_t stat = 0;
|
||||
int len = sizeof buf;
|
||||
r = mehfet_recv_raw(t, &stat, &len, buf);
|
||||
if (r < 0) return r;
|
||||
r = mehfet_err_on_stat("Delay", stat, len, buf);
|
||||
if (r < 0) return r;
|
||||
|
||||
if (len != 0) {
|
||||
printc_err("mehfet: Delay response wrong length: %d != 0\n", len);
|
||||
return -1;
|
||||
}
|
||||
|
||||
#ifdef DEBUG_MEHFET_PROTO_DRIVER
|
||||
printc_dbg("mehfet: Delay(us=%c exact=%c time=%u)\n",
|
||||
us?'t':'f', exact?'t':'f', time);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
int mehfet_cmd_set_clkspeed(transport_t t, bool fast) {
|
||||
uint8_t buf[64];
|
||||
int r;
|
||||
|
||||
buf[0] = fast ? 0xff : 0;
|
||||
r = mehfet_send_raw(t, mehfet_set_clkspeed, 1, buf);
|
||||
if (r < 0) return r;
|
||||
|
||||
uint8_t stat = 0;
|
||||
int len = sizeof buf;
|
||||
r = mehfet_recv_raw(t, &stat, &len, buf);
|
||||
if (r < 0) return r;
|
||||
r = mehfet_err_on_stat("SetClkSpeed", stat, len, buf);
|
||||
if (r < 0) return r;
|
||||
|
||||
if (len != 0) {
|
||||
printc_err("mehfet: SetClkSpeed response wrong length: %d != 0\n", len);
|
||||
return -1;
|
||||
}
|
||||
|
||||
#ifdef DEBUG_MEHFET_PROTO_DRIVER
|
||||
printc_dbg("mehfet: SetClkSpeed(%s)\n", fast?"fast":"slow");
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
int mehfet_cmd_get_old_lines(transport_t t, enum mehfet_lines* lines) {
|
||||
if (!lines) return -1;
|
||||
|
||||
uint8_t buf[64];
|
||||
int r;
|
||||
|
||||
r = mehfet_send_raw(t, mehfet_get_old_lines, 0, NULL);
|
||||
if (r < 0) return r;
|
||||
|
||||
uint8_t stat = 0;
|
||||
int len = sizeof buf;
|
||||
r = mehfet_recv_raw(t, &stat, &len, buf);
|
||||
if (r < 0) return r;
|
||||
r = mehfet_err_on_stat("GetOldLines", stat, len, buf);
|
||||
if (r < 0) return r;
|
||||
|
||||
if (len != 1) {
|
||||
printc_err("mehfet: GetOldLines response wrong length: %d != 1\n", len);
|
||||
return -1;
|
||||
}
|
||||
|
||||
*lines = buf[0];
|
||||
|
||||
#ifdef DEBUG_MEHFET_PROTO_DRIVER
|
||||
printc_dbg("mehfet: GetOldLines(): 0x%x\n", *lines);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mehfet_cmd_tdio_seq(transport_t t, uint32_t nbits, bool tms, const uint8_t* tdi, uint8_t* tdo) {
|
||||
if (!tdi || !tdo || !nbits) return -1;
|
||||
|
||||
int r;
|
||||
uint32_t nbytes = (nbits + 7) >> 3;
|
||||
uint8_t buf[(nbytes + 5) < 64 ? 64 : (nbytes + 5)]; // need min for recv
|
||||
|
||||
for (size_t i = 0; i < 4; ++i) buf[i] = (nbits >> (i*8)) & 0xff;
|
||||
buf[4] = tms ? 0xff : 0;
|
||||
memcpy(&buf[5], tdi, nbytes);
|
||||
|
||||
r = mehfet_send_raw(t, mehfet_tdio_seq, nbytes + 5, buf);
|
||||
if (r < 0) return r;
|
||||
|
||||
uint8_t stat = 0;
|
||||
int len = sizeof buf; // is a max len
|
||||
r = mehfet_recv_raw(t, &stat, &len, buf);
|
||||
if (r < 0) return r;
|
||||
r = mehfet_err_on_stat("TdioSequence", stat, len, buf);
|
||||
if (r < 0) return r;
|
||||
|
||||
if (len != nbytes) {
|
||||
printc_err("mehfet: TdioSequence response wrong length: %d != %d\n",
|
||||
len, nbytes);
|
||||
return -1;
|
||||
}
|
||||
|
||||
memcpy(tdo, buf, nbytes);
|
||||
|
||||
#ifdef DEBUG_MEHFET_PROTO_DRIVER
|
||||
printc_dbg("mehfet: TdioSequence(%u, TMS=%c):\n", nbits, tms?'1':'0');
|
||||
debug_hexdump("\tTDI", tdi, nbytes);
|
||||
debug_hexdump("\tTDO", tdo, nbytes);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
int mehfet_cmd_tms_seq(transport_t t, uint32_t nbits, bool tdi, const uint8_t* tms) {
|
||||
if (!tms || !nbits) return -1;
|
||||
|
||||
int r;
|
||||
uint32_t nbytes = (nbits + 7) >> 3;
|
||||
uint8_t buf[(nbytes + 5) < 64 ? 64 : (nbytes + 5)]; // need min for recv
|
||||
|
||||
for (size_t i = 0; i < 4; ++i) buf[i] = (nbits >> (i*8)) & 0xff;
|
||||
buf[4] = tdi ? 0xff : 0;
|
||||
memcpy(&buf[5], tms, nbytes);
|
||||
|
||||
r = mehfet_send_raw(t, mehfet_tdio_seq, sizeof buf, buf);
|
||||
if (r < 0) return r;
|
||||
|
||||
uint8_t stat = 0;
|
||||
int len = sizeof buf; // is a max len
|
||||
r = mehfet_recv_raw(t, &stat, &len, buf);
|
||||
if (r < 0) return r;
|
||||
r = mehfet_err_on_stat("TmsSequence", stat, len, buf);
|
||||
if (r < 0) return r;
|
||||
|
||||
if (len != 0) {
|
||||
printc_err("mehfet: TmsSequence response wrong length: %d != 0\n", len);
|
||||
return -1;
|
||||
}
|
||||
|
||||
#ifdef DEBUG_MEHFET_PROTO_DRIVER
|
||||
printc_dbg("mehfet: TmsSequence(%u, TDI=%c):\n", nbits, tdi?'1':'0');
|
||||
debug_hexdump("\tTMS", tms, nbytes);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
int mehfet_cmd_tclk_edge(transport_t t, bool newtclk) {
|
||||
uint8_t buf[64];
|
||||
int r;
|
||||
|
||||
buf[0] = newtclk ? 0xff : 0;
|
||||
r = mehfet_send_raw(t, mehfet_tclk_edge, 1, buf);
|
||||
if (r < 0) return r;
|
||||
|
||||
uint8_t stat = 0;
|
||||
int len = sizeof buf;
|
||||
r = mehfet_recv_raw(t, &stat, &len, buf);
|
||||
if (r < 0) return r;
|
||||
r = mehfet_err_on_stat("TclkEdge", stat, len, buf);
|
||||
if (r < 0) return r;
|
||||
|
||||
if (len != 0) {
|
||||
printc_err("mehfet: TclkEdge response wrong length: %d != 0\n", len);
|
||||
return -1;
|
||||
}
|
||||
|
||||
#ifdef DEBUG_MEHFET_PROTO_DRIVER
|
||||
printc_dbg("mehfet: TclkEdge(TCLK=%c)\n", newtclk?'H':'L');
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
int mehfet_cmd_tclk_burst(transport_t t, uint32_t ncyc) {
|
||||
uint8_t buf[64];
|
||||
int r;
|
||||
|
||||
for (size_t i = 0; i < 4; ++i) buf[i] = (ncyc >> (i*8)) & 0xff;
|
||||
r = mehfet_send_raw(t, mehfet_tclk_burst, 4, buf);
|
||||
if (r < 0) return r;
|
||||
|
||||
uint8_t stat = 0;
|
||||
int len = sizeof buf;
|
||||
r = mehfet_recv_raw(t, &stat, &len, buf);
|
||||
if (r < 0) return r;
|
||||
r = mehfet_err_on_stat("TclkBurst", stat, len, buf);
|
||||
if (r < 0) return r;
|
||||
|
||||
if (len != 0) {
|
||||
printc_err("mehfet: TclkBurst response wrong length: %d != 0\n", len);
|
||||
return -1;
|
||||
}
|
||||
|
||||
#ifdef DEBUG_MEHFET_PROTO_DRIVER
|
||||
printc_dbg("mehfet: TclkBurst(ncyc=%u)\n", ncyc);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mehfet_cmd_reset_tap(transport_t t, enum mehfet_resettap_flags flags,
|
||||
enum mehfet_resettap_status* tstat) {
|
||||
if (!tstat) return -1;
|
||||
|
||||
uint8_t buf[64];
|
||||
int r;
|
||||
|
||||
buf[0] = flags;
|
||||
r = mehfet_send_raw(t, mehfet_reset_tap, 1, buf);
|
||||
if (r < 0) return r;
|
||||
|
||||
uint8_t stat = 0;
|
||||
int len = sizeof buf;
|
||||
r = mehfet_recv_raw(t, &stat, &len, buf);
|
||||
if (r < 0) return r;
|
||||
r = mehfet_err_on_stat("ResetTAP", stat, len, buf);
|
||||
if (r < 0) return r;
|
||||
|
||||
if (len != 1) {
|
||||
printc_err("mehfet: ResetTAP response wrong length: %d != 1\n", len);
|
||||
return -1;
|
||||
}
|
||||
|
||||
*tstat = buf[0];
|
||||
|
||||
#ifdef DEBUG_MEHFET_PROTO_DRIVER
|
||||
printc_dbg("mehfet: ResetTAP(flags=0x%x) = 0x%x\n", flags, *tstat);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static uint8_t bitswap_nyb(uint8_t in) {
|
||||
return ((in >> 3) & 1) | ((in >> 1) & 2) | ((in << 1) & 4) | ((in << 3) & 8);
|
||||
}
|
||||
static uint8_t bitswap(uint8_t in) {
|
||||
return (bitswap_nyb(in&0xf) << 4) | bitswap_nyb(in>>4);
|
||||
}
|
||||
|
||||
#ifdef DEBUG_MEHFET_PROTO_DRIVER
|
||||
static const char* get_ir_name(uint8_t ir) {
|
||||
switch (ir) {
|
||||
case 0x09: return "EMEX_DATA_EXCHANGE";
|
||||
case 0x0a: return "EMEX_READ_TRIGGER";
|
||||
case 0x0b: return "EMEX_READ_CONTROL";
|
||||
case 0x0c: return "EMEX_WRITE_CONTROL";
|
||||
case 0x0d: return "EMEX_READ_CONTROL_2";
|
||||
case 0x0e: return "EMEX_WRITE_CONTROL_2";
|
||||
|
||||
case 0x11: return "CNTRL_SIG_HIGH_BYTE";
|
||||
case 0x12: return "CNTRL_SIG_LOW_BYTE";
|
||||
case 0x13: return "CNTRL_SIG_16BIT";
|
||||
case 0x14: return "CNTRL_SIG_CAPTURE";
|
||||
case 0x15: return "CNTRL_SIG_RELEASE";
|
||||
case 0x17: return "COREIP_ID";
|
||||
|
||||
case 0x19: return "FLASH_16BIT_UPDATE";
|
||||
case 0x1a: return "FLASH_CAPTURE";
|
||||
case 0x1b: return "FLASH_16BIT_IN";
|
||||
case 0x1c: return "FLASH_UPDATE";
|
||||
|
||||
case 0x21: return "CNTRL";
|
||||
case 0x22: return "PREPARE_BLOW";
|
||||
case 0x24: return "EX_BLOX";
|
||||
case 0x29: return "CONFIG_FUSES";
|
||||
case 0x2a: return "TEST_REG";
|
||||
case 0x2f: return "TEST_3V_REG";
|
||||
|
||||
case 0x31: return "DUAL_8BIT";
|
||||
case 0x32: return "DUAL_CAPTURE";
|
||||
case 0x33: return "SELECT_MAIN";
|
||||
case 0x34: return "SELECT_ESP";
|
||||
|
||||
case 0x41: return "DATA_16BIT";
|
||||
case 0x42: return "DATA_CAPTURE";
|
||||
case 0x43: return "DATA_QUICK";
|
||||
case 0x44: return "DATA_PSA";
|
||||
case 0x45: return "DATA_16BIT_OPT";
|
||||
case 0x46: return "SHIFT_OUT_PSA";
|
||||
case 0x47: return "DTA";
|
||||
|
||||
case 0x59: return "ACCEPT_KEY";
|
||||
|
||||
case 0x61: return "JMB_EXCHANGE";
|
||||
case 0x62: return "JSTATE_ID";
|
||||
case 0x64: return "TDO_EVENT";
|
||||
case 0x65: return "TDO_EVENT_CTL";
|
||||
|
||||
case 0x81: return "ADDR_HIGH_BYTE";
|
||||
case 0x82: return "ADDR_LOW_BYTE";
|
||||
case 0x83: return "ADDR_16BIT";
|
||||
case 0x84: return "ADDR_CAPTURE";
|
||||
|
||||
case 0x85: return "DATA_TO_ADDR";
|
||||
case 0x86: return "CAPTURE_CPU_REG";
|
||||
case 0x87: return "DEVICE_ID";
|
||||
case 0x88: return "JMB_WRITE_32BIT_MODE";
|
||||
|
||||
case 0xFF: return "BYPASS";
|
||||
|
||||
default: return NULL;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
int mehfet_cmd_irshift(transport_t t, uint8_t newir, uint8_t* oldir) {
|
||||
if (!oldir) return -1;
|
||||
|
||||
// NOTE: jtaglib.c uses bitswapped IR values, while MehFET uses values from
|
||||
// the SLAU320 PDF, so we need to perform a bitswap here
|
||||
newir = bitswap(newir);
|
||||
|
||||
uint8_t buf[64];
|
||||
int r;
|
||||
|
||||
buf[0] = newir;
|
||||
r = mehfet_send_raw(t, mehfet_irshift, 1, buf);
|
||||
if (r < 0) return r;
|
||||
|
||||
uint8_t stat = 0;
|
||||
int len = sizeof buf;
|
||||
r = mehfet_recv_raw(t, &stat, &len, buf);
|
||||
if (r < 0) return r;
|
||||
r = mehfet_err_on_stat("IRshift", stat, len, buf);
|
||||
if (r < 0) return r;
|
||||
|
||||
if (len != 1) {
|
||||
printc_err("mehfet: IRshift response wrong length: %d != 1\n", len);
|
||||
return -1;
|
||||
}
|
||||
|
||||
*oldir = buf[0];
|
||||
|
||||
#ifdef DEBUG_MEHFET_PROTO_DRIVER
|
||||
const char* s = get_ir_name(newir);
|
||||
if (s) {
|
||||
printc_dbg("mehfet: IRshift(new=IR_%s) = 0x%02x\n", s, *oldir);
|
||||
} else {
|
||||
printc_dbg("mehfet: IRshift(new=0x%02x) = 0x%02x\n", newir, *oldir);
|
||||
}
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
int mehfet_cmd_drshift(transport_t t, uint32_t nbits, const uint8_t* newdr, uint8_t* olddr) {
|
||||
if (!newdr || !olddr) return -1;
|
||||
|
||||
uint32_t nbytes = (nbits + 7) >> 3;
|
||||
uint8_t buf[(nbytes + 4) < 64 ? 64 : (nbytes + 4)];
|
||||
int r;
|
||||
|
||||
for (size_t i = 0; i < 4; ++i) buf[i] = (nbits >> (i * 8)) & 0xff;
|
||||
memcpy(&buf[4], newdr, nbytes);
|
||||
r = mehfet_send_raw(t, mehfet_drshift, nbytes + 4, buf);
|
||||
if (r < 0) return r;
|
||||
|
||||
uint8_t stat = 0;
|
||||
int len = sizeof buf;
|
||||
r = mehfet_recv_raw(t, &stat, &len, buf);
|
||||
if (r < 0) return r;
|
||||
r = mehfet_err_on_stat("DRshift", stat, len, buf);
|
||||
if (r < 0) return r;
|
||||
|
||||
if (len != (int)nbytes) {
|
||||
printc_err("mehfet: DRshift response wrong length: %d != %u\n", len, nbytes);
|
||||
return -1;
|
||||
}
|
||||
|
||||
memcpy(olddr, buf, nbytes);
|
||||
|
||||
#ifdef DEBUG_MEHFET_PROTO_DRIVER
|
||||
if (nbits == 16) {
|
||||
uint16_t in, out;
|
||||
in = newdr[0] | ((uint16_t)newdr[1] << 8);
|
||||
out= olddr[0] | ((uint16_t)olddr[1] << 8);
|
||||
printc_dbg("mehfet: DRshift(nbits=%u): in: %04x, out: %04x\n", nbits, in, out);
|
||||
} else if (nbits == 20) {
|
||||
uint32_t in, out;
|
||||
in = newdr[0] | ((uint32_t)newdr[1] << 8) | ((uint32_t)newdr[2] << 16);
|
||||
out= olddr[0] | ((uint32_t)olddr[1] << 8) | ((uint32_t)olddr[2] << 16);
|
||||
printc_dbg("mehfet: DRshift(nbits=%u): in: %05x, out: %05x\n", nbits, in, out);
|
||||
} else if (nbits == 32) {
|
||||
uint32_t in, out;
|
||||
in = newdr[0] | ((uint32_t)newdr[1] << 8) | ((uint32_t)newdr[2] << 16) | ((uint32_t)newdr[3] << 24);
|
||||
out= olddr[0] | ((uint32_t)olddr[1] << 8) | ((uint32_t)olddr[2] << 16) | ((uint32_t)olddr[3] << 24);
|
||||
printc_dbg("mehfet: DRshift(nbits=%u): in: %08x, out: %08x\n", nbits, in, out);
|
||||
} else {
|
||||
printc_dbg("mehfet: DRshift(nbits=%u):\n", nbits);
|
||||
debug_hexdump("\tin ", newdr, nbytes);
|
||||
debug_hexdump("\tout", olddr, nbytes);
|
||||
}
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -1,108 +0,0 @@
|
|||
/* MSPDebug - debugging tool for MSP430 MCUs
|
||||
* Copyright (C) 2021 sys64738@disroot.org
|
||||
*
|
||||
* 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef MEHFET_PROTO_H_
|
||||
#define MEHFET_PROTO_H_
|
||||
|
||||
#include "transport.h"
|
||||
|
||||
#define MEHFET_PROTO_VER 0x0001
|
||||
#define MEHFET_PROTO_VER_MIN_SUPPORTED 0x0001
|
||||
|
||||
enum mehfet_cmd {
|
||||
mehfet_info = 0x01,
|
||||
mehfet_status = 0x02,
|
||||
mehfet_connect = 0x03,
|
||||
mehfet_disconnect = 0x04,
|
||||
mehfet_delay = 0x05,
|
||||
mehfet_set_clkspeed = 0x06,
|
||||
mehfet_get_old_lines = 0x07,
|
||||
mehfet_tdio_seq = 0x08,
|
||||
mehfet_tms_seq = 0x09,
|
||||
mehfet_tclk_edge = 0x0a,
|
||||
mehfet_tclk_burst = 0x0b,
|
||||
mehfet_reset_tap = 0x0c,
|
||||
mehfet_irshift = 0x0d,
|
||||
mehfet_drshift = 0x0e,
|
||||
};
|
||||
|
||||
enum mehfet_caps {
|
||||
mehfet_cap_jtag_noentry = 1<<0,
|
||||
mehfet_cap_jtag_entryseq = 1<<1,
|
||||
mehfet_cap_sbw_entryseq = 1<<2,
|
||||
|
||||
mehfet_cap_has_reset_tap = 1<< 8,
|
||||
mehfet_cap_has_irshift = 1<< 9,
|
||||
mehfet_cap_has_drshift = 1<<10,
|
||||
mehfet_cap_has_loop = 1<<11,
|
||||
};
|
||||
|
||||
enum mehfet_conn {
|
||||
mehfet_conn_none = 0,
|
||||
mehfet_conn_auto = 0,
|
||||
|
||||
mehfet_conn_jtag_noentry = 1,
|
||||
mehfet_conn_jtag_entryseq = 2,
|
||||
mehfet_conn_sbw_entryseq = 3,
|
||||
|
||||
mehfet_conn_typemask = 0x7f,
|
||||
mehfet_conn_nrstmask = 0x80
|
||||
};
|
||||
|
||||
enum mehfet_lines {
|
||||
mehfet_line_tclk = 1<<0,
|
||||
mehfet_line_tms = 1<<1,
|
||||
mehfet_line_tdi = 1<<2
|
||||
};
|
||||
|
||||
enum mehfet_resettap_flags {
|
||||
mehfet_rsttap_do_reset = 1<<0, // reset TAP to run-test/idle state
|
||||
mehfet_rsttap_fuse_do = 1<<1, // perform fuse check procedure (TMS pulses) on target
|
||||
mehfet_rsttap_fuse_read = 1<<2, // check whether the JTAG fuse has been blown
|
||||
};
|
||||
enum mehfet_resettap_status {
|
||||
mehfet_rsttap_fuse_blown = 0x80
|
||||
};
|
||||
|
||||
struct mehfet_info {
|
||||
char* devicename;
|
||||
enum mehfet_caps caps;
|
||||
uint32_t packet_buf_size;
|
||||
uint16_t proto_version;
|
||||
};
|
||||
|
||||
|
||||
int mehfet_cmd_info(transport_t t, struct mehfet_info* info);
|
||||
int mehfet_cmd_status(transport_t t, enum mehfet_conn* stat);
|
||||
int mehfet_cmd_connect(transport_t t, enum mehfet_conn conn);
|
||||
int mehfet_cmd_disconnect(transport_t t);
|
||||
int mehfet_cmd_delay(transport_t t, bool us, bool exact, uint32_t time);
|
||||
int mehfet_cmd_set_clkspeed(transport_t t, bool fast);
|
||||
int mehfet_cmd_get_old_lines(transport_t t, enum mehfet_lines* lines);
|
||||
|
||||
int mehfet_cmd_tdio_seq(transport_t t, uint32_t nbits, bool tms, const uint8_t* tdi, uint8_t* tdo);
|
||||
int mehfet_cmd_tms_seq(transport_t t, uint32_t nbits, bool tdi, const uint8_t* tms);
|
||||
int mehfet_cmd_tclk_edge(transport_t t, bool newtclk);
|
||||
int mehfet_cmd_tclk_burst(transport_t t, uint32_t ncyc);
|
||||
|
||||
int mehfet_cmd_reset_tap(transport_t t, enum mehfet_resettap_flags flags, enum mehfet_resettap_status* stat);
|
||||
int mehfet_cmd_irshift(transport_t t, uint8_t newir, uint8_t* oldir);
|
||||
int mehfet_cmd_drshift(transport_t t, uint32_t nbits, const uint8_t* newdr, uint8_t* olddr);
|
||||
|
||||
#endif
|
||||
|
359
drivers/pif.c
359
drivers/pif.c
|
@ -35,10 +35,293 @@
|
|||
#include "ctrlc.h"
|
||||
|
||||
struct pif_device {
|
||||
struct device base;
|
||||
struct jtdev jtag;
|
||||
};
|
||||
|
||||
/*============================================================================*/
|
||||
/* pif MSP430 JTAG operations */
|
||||
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Read a word-aligned block from any kind of memory
|
||||
* returns the number of bytes read or -1 on failure
|
||||
*/
|
||||
static int read_words(device_t dev, const struct chipinfo_memory *m,
|
||||
address_t addr, address_t len, uint8_t *data)
|
||||
{
|
||||
struct pif_device *pif = (struct pif_device *)dev;
|
||||
struct jtdev *p = &pif->jtag;
|
||||
unsigned int index;
|
||||
unsigned int word;
|
||||
|
||||
for ( index = 0; index < len; index += 2 ) {
|
||||
word = jtag_read_mem( p, 16, addr+index );
|
||||
data[index] = word & 0x00ff;
|
||||
data[index+1] = (word >> 8) & 0x00ff;
|
||||
}
|
||||
|
||||
return p->failed ? -1 : len;
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Write a word to RAM */
|
||||
static int write_ram_word( struct jtdev *p, address_t addr,
|
||||
uint16_t value )
|
||||
{
|
||||
jtag_write_mem( p, 16, addr, value );
|
||||
|
||||
return p->failed ? -1 : 0;
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Write a word-aligned flash block. */
|
||||
/* The starting address must be within the flash memory range. */
|
||||
|
||||
static int write_flash_block( struct jtdev *p, address_t addr,
|
||||
address_t len,
|
||||
const uint8_t *data)
|
||||
{
|
||||
unsigned int i;
|
||||
uint16_t *word;
|
||||
|
||||
word = malloc( len / 2 * sizeof(*word) );
|
||||
if (!word) {
|
||||
pr_error("pif: failed to allocate memory");
|
||||
return -1;
|
||||
}
|
||||
|
||||
for(i = 0; i < len/2; i++) {
|
||||
word[i]=data[2*i] + (((uint16_t)data[2*i+1]) << 8);
|
||||
}
|
||||
jtag_write_flash( p, addr, len/2, word );
|
||||
|
||||
free(word);
|
||||
|
||||
return p->failed ? -1 : 0;
|
||||
}
|
||||
|
||||
/* Write a word-aligned block to any kind of memory.
|
||||
* returns the number of bytes written or -1 on failure
|
||||
*/
|
||||
static int write_words(device_t dev, const struct chipinfo_memory *m,
|
||||
address_t addr, address_t len, const uint8_t *data)
|
||||
{
|
||||
struct pif_device *pif = (struct pif_device *)dev;
|
||||
struct jtdev *p = &pif->jtag;
|
||||
int r;
|
||||
|
||||
if (m->type != CHIPINFO_MEMTYPE_FLASH) {
|
||||
len = 2;
|
||||
r = write_ram_word(p, addr, r16le(data));
|
||||
} else {
|
||||
r = write_flash_block(p, addr, len, data);
|
||||
}
|
||||
|
||||
if (r < 0) {
|
||||
printc_err("pif: write_words at address 0x%x failed\n", addr);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------*/
|
||||
static int init_device(struct jtdev *p)
|
||||
{
|
||||
unsigned int jtag_id;
|
||||
|
||||
printc_dbg("Starting JTAG\n");
|
||||
jtag_id = jtag_init(p);
|
||||
printc("JTAG ID: 0x%02x\n", jtag_id);
|
||||
if (jtag_id != 0x89 && jtag_id != 0x91) {
|
||||
printc_err("pif: unexpected JTAG ID: 0x%02x\n", jtag_id);
|
||||
jtag_release_device(p, 0xfffe);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*===== MSPDebug Device interface ============================================*/
|
||||
|
||||
/*----------------------------------------------------------------------------*/
|
||||
static int refresh_bps(struct pif_device *dev)
|
||||
{
|
||||
int i;
|
||||
int ret;
|
||||
struct device_breakpoint *bp;
|
||||
address_t addr;
|
||||
ret = 0;
|
||||
|
||||
for (i = 0; i < dev->base.max_breakpoints; i++) {
|
||||
bp = &dev->base.breakpoints[i];
|
||||
|
||||
printc_dbg("refresh breakpoint %d: type=%d "
|
||||
"addr=%04x flags=%04x\n",
|
||||
i, bp->type, bp->addr, bp->flags);
|
||||
|
||||
if ( (bp->flags & DEVICE_BP_DIRTY) &&
|
||||
(bp->type == DEVICE_BPTYPE_BREAK) ) {
|
||||
addr = bp->addr;
|
||||
|
||||
if ( !(bp->flags & DEVICE_BP_ENABLED) ) {
|
||||
addr = 0;
|
||||
}
|
||||
|
||||
if ( jtag_set_breakpoint (&dev->jtag, i, addr) == 0) {
|
||||
printc_err("pif: failed to refresh "
|
||||
"breakpoint #%d\n", i);
|
||||
ret = -1;
|
||||
} else {
|
||||
bp->flags &= ~DEVICE_BP_DIRTY;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------*/
|
||||
static int pif_readmem( device_t dev_base,
|
||||
address_t addr,
|
||||
uint8_t* mem,
|
||||
address_t len )
|
||||
{
|
||||
struct pif_device *dev = (struct pif_device *)dev_base;
|
||||
dev->jtag.failed = 0;
|
||||
return readmem(dev_base, addr, mem, len, read_words);
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------*/
|
||||
static int pif_writemem( device_t dev_base,
|
||||
address_t addr,
|
||||
const uint8_t* mem,
|
||||
address_t len )
|
||||
{
|
||||
struct pif_device *dev = (struct pif_device *)dev_base;
|
||||
dev->jtag.failed = 0;
|
||||
return writemem(dev_base, addr, mem, len, write_words, read_words);
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------*/
|
||||
static int pif_getregs(device_t dev_base, address_t *regs)
|
||||
{
|
||||
struct pif_device *dev = (struct pif_device *)dev_base;
|
||||
int i;
|
||||
|
||||
dev->jtag.failed = 0;
|
||||
|
||||
for (i = 0; i < DEVICE_NUM_REGS; i++)
|
||||
regs[i] = jtag_read_reg(&dev->jtag, i);
|
||||
|
||||
return dev->jtag.failed ? -1 : 0;
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------*/
|
||||
static int pif_setregs( device_t dev_base, const address_t* regs )
|
||||
{
|
||||
struct pif_device *dev = (struct pif_device *)dev_base;
|
||||
int i;
|
||||
|
||||
dev->jtag.failed = 0;
|
||||
|
||||
for (i = 0; i < DEVICE_NUM_REGS; i++) {
|
||||
jtag_write_reg( &dev->jtag, i, regs[i] );
|
||||
}
|
||||
return dev->jtag.failed ? -1 : 0;
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------*/
|
||||
static int pif_ctl(device_t dev_base, device_ctl_t type)
|
||||
{
|
||||
struct pif_device *dev = (struct pif_device *)dev_base;
|
||||
|
||||
dev->jtag.failed = 0;
|
||||
|
||||
switch (type) {
|
||||
case DEVICE_CTL_RESET:
|
||||
/* perform soft reset */
|
||||
jtag_execute_puc(&dev->jtag);
|
||||
break;
|
||||
|
||||
case DEVICE_CTL_RUN:
|
||||
/* transfer changed breakpoints to device */
|
||||
if (refresh_bps(dev) < 0) {
|
||||
return -1;
|
||||
}
|
||||
/* start program execution at current PC */
|
||||
jtag_release_device(&dev->jtag, 0xffff);
|
||||
break;
|
||||
|
||||
case DEVICE_CTL_HALT:
|
||||
/* take device under JTAG control */
|
||||
jtag_get_device(&dev->jtag);
|
||||
break;
|
||||
|
||||
case DEVICE_CTL_STEP:
|
||||
/* execute next instruction at current PC */
|
||||
jtag_single_step(&dev->jtag);
|
||||
break;
|
||||
|
||||
default:
|
||||
printc_err("pif: unsupported operation\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return dev->jtag.failed ? -1 : 0;
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------*/
|
||||
static device_status_t pif_poll(device_t dev_base)
|
||||
{
|
||||
struct pif_device *dev = (struct pif_device *)dev_base;
|
||||
|
||||
if (delay_ms(100) < 0 || ctrlc_check())
|
||||
return DEVICE_STATUS_INTR;
|
||||
|
||||
if (jtag_cpu_state(&dev->jtag) == 1) {
|
||||
return DEVICE_STATUS_HALTED;
|
||||
}
|
||||
|
||||
return DEVICE_STATUS_RUNNING;
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------*/
|
||||
static int pif_erase( device_t dev_base,
|
||||
device_erase_type_t type,
|
||||
address_t addr )
|
||||
{
|
||||
struct pif_device *dev = (struct pif_device *)dev_base;
|
||||
|
||||
dev->jtag.failed = 0;
|
||||
|
||||
switch(type) {
|
||||
case DEVICE_ERASE_MAIN:
|
||||
jtag_erase_flash ( &dev->jtag, JTAG_ERASE_MAIN, addr );
|
||||
break;
|
||||
case DEVICE_ERASE_ALL:
|
||||
jtag_erase_flash ( &dev->jtag, JTAG_ERASE_MASS, addr );
|
||||
break;
|
||||
case DEVICE_ERASE_SEGMENT:
|
||||
jtag_erase_flash ( &dev->jtag, JTAG_ERASE_SGMT, addr );
|
||||
break;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
|
||||
return dev->jtag.failed ? -1 : 0;
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------*/
|
||||
static int pif_getconfigfuses(device_t dev_base)
|
||||
{
|
||||
struct pif_device *dev = (struct pif_device *)dev_base;
|
||||
|
||||
return jtag_get_config_fuses(&dev->jtag);
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
static device_t pif_open(const struct device_args *args)
|
||||
{
|
||||
|
@ -61,9 +344,9 @@ static device_t pif_open(const struct device_args *args)
|
|||
}
|
||||
|
||||
memset(dev, 0, sizeof(*dev));
|
||||
dev->jtag.base.type = &device_pif;
|
||||
dev->jtag.base.max_breakpoints = 2; //supported by all devices
|
||||
dev->jtag.base.need_probe = 1;
|
||||
dev->base.type = &device_pif;
|
||||
dev->base.max_breakpoints = 2; //supported by all devices
|
||||
dev->base.need_probe = 1;
|
||||
(&dev->jtag)->f = &jtdev_func_pif;
|
||||
|
||||
if ((&dev->jtag)->f->jtdev_open(&dev->jtag, args->path) < 0) {
|
||||
|
@ -72,13 +355,13 @@ static device_t pif_open(const struct device_args *args)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
if (jtag_dev_init(&dev->jtag) < 0) {
|
||||
if (init_device(&dev->jtag) < 0) {
|
||||
printc_err("pif: initialization failed\n");
|
||||
free(dev);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return &dev->jtag.base;
|
||||
return &dev->base;
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------*/
|
||||
|
@ -105,8 +388,8 @@ static device_t gpio_open(const struct device_args *args)
|
|||
}
|
||||
|
||||
memset(dev, 0, sizeof(*dev));
|
||||
dev->jtag.base.type = &device_pif;
|
||||
dev->jtag.base.max_breakpoints = 0;
|
||||
dev->base.type = &device_pif;
|
||||
dev->base.max_breakpoints = 0;
|
||||
(&dev->jtag)->f = &jtdev_func_gpio;
|
||||
|
||||
if ((&dev->jtag)->f->jtdev_open(&dev->jtag, args->path) < 0) {
|
||||
|
@ -115,13 +398,13 @@ static device_t gpio_open(const struct device_args *args)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
if (jtag_dev_init(&dev->jtag) < 0) {
|
||||
if (init_device(&dev->jtag) < 0) {
|
||||
printc_err("gpio: initialization failed\n");
|
||||
free(dev);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return &dev->jtag.base;
|
||||
return &dev->base;
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------*/
|
||||
|
@ -148,9 +431,9 @@ static device_t bp_open(const struct device_args *args)
|
|||
}
|
||||
|
||||
memset(dev, 0, sizeof(*dev));
|
||||
dev->jtag.base.type = &device_pif;
|
||||
dev->jtag.base.max_breakpoints = 2; //supported by all devices
|
||||
dev->jtag.base.need_probe = 1;
|
||||
dev->base.type = &device_pif;
|
||||
dev->base.max_breakpoints = 2; //supported by all devices
|
||||
dev->base.need_probe = 1;
|
||||
(&dev->jtag)->f = &jtdev_func_bp;
|
||||
|
||||
if ((&dev->jtag)->f->jtdev_open(&dev->jtag, args->path) < 0) {
|
||||
|
@ -159,13 +442,13 @@ static device_t bp_open(const struct device_args *args)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
if (jtag_dev_init(&dev->jtag) < 0) {
|
||||
if (init_device(&dev->jtag) < 0) {
|
||||
printc_err("bp: initialization failed\n");
|
||||
free(dev);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return &dev->jtag.base;
|
||||
return &dev->base;
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------*/
|
||||
|
@ -186,14 +469,14 @@ const struct device_class device_pif = {
|
|||
.help = "Parallel Port JTAG",
|
||||
.open = pif_open,
|
||||
.destroy = pif_destroy,
|
||||
.readmem = jtag_dev_readmem,
|
||||
.writemem = jtag_dev_writemem,
|
||||
.getregs = jtag_dev_getregs,
|
||||
.setregs = jtag_dev_setregs,
|
||||
.ctl = jtag_dev_ctl,
|
||||
.poll = jtag_dev_poll,
|
||||
.erase = jtag_dev_erase,
|
||||
.getconfigfuses = jtag_dev_getconfigfuses
|
||||
.readmem = pif_readmem,
|
||||
.writemem = pif_writemem,
|
||||
.getregs = pif_getregs,
|
||||
.setregs = pif_setregs,
|
||||
.ctl = pif_ctl,
|
||||
.poll = pif_poll,
|
||||
.erase = pif_erase,
|
||||
.getconfigfuses = pif_getconfigfuses
|
||||
};
|
||||
|
||||
const struct device_class device_gpio = {
|
||||
|
@ -201,14 +484,14 @@ const struct device_class device_gpio = {
|
|||
.help = "/sys/class/gpio direct connect",
|
||||
.open = gpio_open,
|
||||
.destroy = pif_destroy,
|
||||
.readmem = jtag_dev_readmem,
|
||||
.writemem = jtag_dev_writemem,
|
||||
.getregs = jtag_dev_getregs,
|
||||
.setregs = jtag_dev_setregs,
|
||||
.ctl = jtag_dev_ctl,
|
||||
.poll = jtag_dev_poll,
|
||||
.erase = jtag_dev_erase,
|
||||
.getconfigfuses = jtag_dev_getconfigfuses
|
||||
.readmem = pif_readmem,
|
||||
.writemem = pif_writemem,
|
||||
.getregs = pif_getregs,
|
||||
.setregs = pif_setregs,
|
||||
.ctl = pif_ctl,
|
||||
.poll = pif_poll,
|
||||
.erase = pif_erase,
|
||||
.getconfigfuses = pif_getconfigfuses
|
||||
};
|
||||
|
||||
const struct device_class device_bp = {
|
||||
|
@ -216,12 +499,12 @@ const struct device_class device_bp = {
|
|||
.help = "Bus Pirate JTAG, MISO-TDO, MOSI-TDI, CS-TMS, AUX-RESET, CLK-TCK",
|
||||
.open = bp_open,
|
||||
.destroy = pif_destroy,
|
||||
.readmem = jtag_dev_readmem,
|
||||
.writemem = jtag_dev_writemem,
|
||||
.getregs = jtag_dev_getregs,
|
||||
.setregs = jtag_dev_setregs,
|
||||
.ctl = jtag_dev_ctl,
|
||||
.poll = jtag_dev_poll,
|
||||
.erase = jtag_dev_erase,
|
||||
.getconfigfuses = jtag_dev_getconfigfuses
|
||||
.readmem = pif_readmem,
|
||||
.writemem = pif_writemem,
|
||||
.getregs = pif_getregs,
|
||||
.setregs = pif_setregs,
|
||||
.ctl = pif_ctl,
|
||||
.poll = pif_poll,
|
||||
.erase = pif_erase,
|
||||
.getconfigfuses = pif_getconfigfuses
|
||||
};
|
||||
|
|
459
drivers/v3hil.c
459
drivers/v3hil.c
|
@ -16,7 +16,6 @@
|
|||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
#include "bytes.h"
|
||||
#include "v3hil.h"
|
||||
|
@ -24,12 +23,6 @@
|
|||
#include "output.h"
|
||||
#include "opdb.h"
|
||||
|
||||
#ifdef DEBUG_V3HIL
|
||||
#define dbg_printc(fmt, ...) printc_dbg("v3hil: %s:%d: " fmt, __func__, __LINE__, ##__VA_ARGS__)
|
||||
#else
|
||||
#define dbg_printc(fmt, ...) do{}while(0)
|
||||
#endif
|
||||
|
||||
/* HAL function IDs */
|
||||
typedef enum {
|
||||
HAL_PROTO_FID_INIT = 0x01,
|
||||
|
@ -48,99 +41,73 @@ typedef enum {
|
|||
HAL_PROTO_FID_SET_CHAIN_CONFIGURATION = 0x0e,
|
||||
HAL_PROTO_FID_GET_NUM_DEVICES = 0x0f,
|
||||
HAL_PROTO_FID_GET_INTERFACE_MODE = 0x10,
|
||||
HAL_PROTO_FID_GET_DEVICE_ID_PTR = 0x11,
|
||||
HAL_PROTO_FID_SJ_ASSERT_POR_SC ,
|
||||
HAL_PROTO_FID_SJ_CONDITIONAL_SC ,
|
||||
HAL_PROTO_FID_RC_RELEASE_JTAG ,
|
||||
HAL_PROTO_FID_READ_MEM_BYTES ,
|
||||
HAL_PROTO_FID_READ_MEM_WORDS ,
|
||||
HAL_PROTO_FID_READ_MEM_QUICK ,
|
||||
HAL_PROTO_FID_WRITE_MEM_BYTES ,
|
||||
HAL_PROTO_FID_WRITE_MEM_WORDS ,
|
||||
HAL_PROTO_FID_EEM_DX ,
|
||||
HAL_PROTO_FID_EEM_DX_AFE2XX ,
|
||||
HAL_PROTO_FID_SINGLE_STEP ,
|
||||
HAL_PROTO_FID_READ_ALL_CPU_REGS ,
|
||||
HAL_PROTO_FID_WRITE_ALL_CPU_REGS ,
|
||||
HAL_PROTO_FID_PSA ,
|
||||
HAL_PROTO_FID_EXECUTE_FUNCLET , /* 0x20 */
|
||||
HAL_PROTO_FID_EXECUTE_FUNCLET_JTAG ,
|
||||
HAL_PROTO_FID_GET_DCO_FREQUENCY ,
|
||||
HAL_PROTO_FID_GET_DCO_FREQUENCY_JTAG ,
|
||||
HAL_PROTO_FID_GET_FLL_FREQUENCY ,
|
||||
HAL_PROTO_FID_GET_FLL_FREQUENCY_JTAG ,
|
||||
HAL_PROTO_FID_WAIT_FOR_STORAGE ,
|
||||
HAL_PROTO_FID_SJ_ASSERT_POR_SC_X ,
|
||||
HAL_PROTO_FID_SJ_CONDITIONAL_SC_X ,
|
||||
HAL_PROTO_FID_RC_RELEASE_JTAG_X ,
|
||||
HAL_PROTO_FID_READ_MEM_BYTES_X ,
|
||||
HAL_PROTO_FID_READ_MEM_WORDS_X ,
|
||||
HAL_PROTO_FID_READ_MEM_QUICK_X ,
|
||||
HAL_PROTO_FID_WRITE_MEM_BYTES_X ,
|
||||
HAL_PROTO_FID_WRITE_MEM_WORDS_X ,
|
||||
HAL_PROTO_FID_EEM_DX_X ,
|
||||
HAL_PROTO_FID_SINGLE_STEP_X ,
|
||||
HAL_PROTO_FID_READ_ALL_CPU_REGS_X ,
|
||||
HAL_PROTO_FID_WRITE_ALL_CPU_REGS_X , /* 0x30 */
|
||||
HAL_PROTO_FID_PSA_X ,
|
||||
HAL_PROTO_FID_EXECUTE_FUNCLET_X ,
|
||||
HAL_PROTO_FID_GET_DCO_FREQUENCY_X ,
|
||||
HAL_PROTO_FID_GET_FLL_FREQUENCY_X ,
|
||||
HAL_PROTO_FID_WAIT_FOR_STORAGE_X ,
|
||||
HAL_PROTO_FID_BLOW_FUSE_XV2 ,
|
||||
HAL_PROTO_FID_BLOW_FUSE_FRAM ,
|
||||
HAL_PROTO_FID_SJ_ASSERT_POR_SC_XV2 ,
|
||||
HAL_PROTO_FID_SJ_CONDITIONAL_SC_XV2 ,
|
||||
HAL_PROTO_FID_RC_RELEASE_JTAG_XV2 ,
|
||||
HAL_PROTO_FID_READ_MEM_WORDS_XV2 ,
|
||||
HAL_PROTO_FID_READ_MEM_QUICK_XV2 ,
|
||||
HAL_PROTO_FID_WRITE_MEM_WORDS_XV2 ,
|
||||
HAL_PROTO_FID_EEM_DX_XV2 ,
|
||||
HAL_PROTO_FID_SINGLE_STEP_XV2 , /* 0x40 */
|
||||
HAL_PROTO_FID_READ_ALL_CPU_REGS_XV2 ,
|
||||
HAL_PROTO_FID_WRITE_ALL_CPU_REGS_XV2 ,
|
||||
HAL_PROTO_FID_PSA_XV2 ,
|
||||
HAL_PROTO_FID_EXECUTE_FUNCLET_XV2 ,
|
||||
HAL_PROTO_FID_UNLOCK_DEVICE_XV2 ,
|
||||
HAL_PROTO_FID_MAGIC_PATTERN ,
|
||||
HAL_PROTO_FID_UNLOCK_C092 ,
|
||||
HAL_PROTO_FID_HIL_COMMAND ,
|
||||
HAL_PROTO_FID_POLL_JSTATE_REG ,
|
||||
HAL_PROTO_FID_POLL_JSTATE_REG_FR57XX ,
|
||||
HAL_PROTO_FID_IS_JTAG_FUSE_BLOWN ,
|
||||
HAL_PROTO_FID_RESET_XV2 ,
|
||||
HAL_PROTO_FID_WRITE_FRAM_QUICK_XV2 ,
|
||||
HAL_PROTO_FID_SEND_JTAG_MAILBOX_XV2 ,
|
||||
HAL_PROTO_FID_SINGLE_STEP_JSTATE_XV2 ,
|
||||
HAL_PROTO_FID_POLL_JSTATE_REG_ET8 ,
|
||||
HAL_PROTO_FID_RESET_STATIC_GLOBAL_VARS , /* 0x50 */
|
||||
HAL_PROTO_FID_RESET_430I ,
|
||||
HAL_PROTO_FID_POLL_JSTATE_REG_430I ,
|
||||
HAL_PROTO_FID_POLL_JSTATE_REG_20 ,
|
||||
HAL_PROTO_FID_SWITCH_MOSFET ,
|
||||
HAL_PROTO_FID_RESET_L092 ,
|
||||
HAL_PROTO_FID_DUMMY_MACRO ,
|
||||
HAL_PROTO_FID_RESET_5438XV2 ,
|
||||
HAL_PROTO_FID_LEA_SYNC_COND ,
|
||||
HAL_PROTO_FID_GET_JTAG_ID_CODE_ARM ,
|
||||
HAL_PROTO_FID_SCAN_AP_ARM ,
|
||||
HAL_PROTO_FID_MEM_AP_TRANSACTION_ARM ,
|
||||
HAL_PROTO_FID_READ_ALL_CPU_REGS_ARM ,
|
||||
HAL_PROTO_FID_WRITE_ALL_CPU_REGS_ARM ,
|
||||
HAL_PROTO_FID_ENABLE_DEBUG_ARM ,
|
||||
HAL_PROTO_FID_DISABLE_DEBUG_ARM ,
|
||||
HAL_PROTO_FID_RUN_ARM , /* 0x60 */
|
||||
HAL_PROTO_FID_HALT_ARM ,
|
||||
HAL_PROTO_FID_RESET_ARM ,
|
||||
HAL_PROTO_FID_SINGLE_STEP_ARM ,
|
||||
HAL_PROTO_FID_WAIT_FOR_DEBUG_HALT_ARM ,
|
||||
HAL_PROTO_FID_MEM_AP_TRANSACTION_ARM_SWD,
|
||||
HAL_PROTO_FID_GET_ITF_MODE_ARM ,
|
||||
HAL_PROTO_FID_POLL_DSTATE_PCREG_ET ,
|
||||
HAL_PROTO_FID_GET_CPU_ID_ARM ,
|
||||
HAL_PROTO_FID_CHECK_DAP_LOCK_ARM ,
|
||||
HAL_PROTO_FID_UNLOCK_DAP ,
|
||||
HAL_PROTO_FID_USS_SYNC_COND , /* 0x6b */
|
||||
HAL_PROTO_FID_SJ_ASSERT_POR_SC = 0x11,
|
||||
HAL_PROTO_FID_SJ_CONDITIONAL_SC = 0x12,
|
||||
HAL_PROTO_FID_RC_RELEASE_JTAG = 0x13,
|
||||
HAL_PROTO_FID_READ_MEM_BYTES = 0x14,
|
||||
HAL_PROTO_FID_READ_MEM_WORDS = 0x15,
|
||||
HAL_PROTO_FID_READ_MEM_QUICK = 0x16,
|
||||
HAL_PROTO_FID_WRITE_MEM_BYTES = 0x17,
|
||||
HAL_PROTO_FID_WRITE_MEM_WORDS = 0x18,
|
||||
HAL_PROTO_FID_EEM_DX = 0x19,
|
||||
HAL_PROTO_FID_EEM_DX_AFE2XX = 0x1a,
|
||||
HAL_PROTO_FID_SINGLE_STEP = 0x1b,
|
||||
HAL_PROTO_FID_READ_ALL_CPU_REGS = 0x1c,
|
||||
HAL_PROTO_FID_WRITE_ALL_CPU_REGS = 0x1d,
|
||||
HAL_PROTO_FID_PSA = 0x1e,
|
||||
HAL_PROTO_FID_EXECUTE_FUNCLET = 0x1f,
|
||||
HAL_PROTO_FID_EXECUTE_FUNCLET_JTAG = 0x20,
|
||||
HAL_PROTO_FID_GET_DCO_FREQUENCY = 0x21,
|
||||
HAL_PROTO_FID_GET_DCO_FREQUENCY_JTAG = 0x22,
|
||||
HAL_PROTO_FID_GET_FLL_FREQUENCY = 0x23,
|
||||
HAL_PROTO_FID_GET_FLL_FREQUENCY_JTAG = 0x24,
|
||||
HAL_PROTO_FID_WAIT_FOR_STORAGE = 0x25,
|
||||
HAL_PROTO_FID_SJ_ASSERT_POR_SC_X = 0x26,
|
||||
HAL_PROTO_FID_SJ_CONDITIONAL_SC_X = 0x27,
|
||||
HAL_PROTO_FID_RC_RELEASE_JTAG_X = 0x28,
|
||||
HAL_PROTO_FID_READ_MEM_BYTES_X = 0x29,
|
||||
HAL_PROTO_FID_READ_MEM_WORDS_X = 0x2a,
|
||||
HAL_PROTO_FID_READ_MEM_QUICK_X = 0x2b,
|
||||
HAL_PROTO_FID_WRITE_MEM_BYTES_X = 0x2c,
|
||||
HAL_PROTO_FID_WRITE_MEM_WORDS_X = 0x2d,
|
||||
HAL_PROTO_FID_EEM_DX_X = 0x2e,
|
||||
HAL_PROTO_FID_SINGLE_STEP_X = 0x2f,
|
||||
HAL_PROTO_FID_READ_ALL_CPU_REGS_X = 0x30,
|
||||
HAL_PROTO_FID_WRITE_ALL_CPU_REGS_X = 0x31,
|
||||
HAL_PROTO_FID_PSA_X = 0x32,
|
||||
HAL_PROTO_FID_EXECUTE_FUNCLET_X = 0x33,
|
||||
HAL_PROTO_FID_GET_DCO_FREQUENCY_X = 0x34,
|
||||
HAL_PROTO_FID_GET_FLL_FREQUENCY_X = 0x35,
|
||||
HAL_PROTO_FID_WAIT_FOR_STORAGE_X = 0x36,
|
||||
HAL_PROTO_FID_BLOW_FUSE_XV2 = 0x37,
|
||||
HAL_PROTO_FID_BLOW_FUSE_FRAM = 0x38,
|
||||
HAL_PROTO_FID_SJ_ASSERT_POR_SC_XV2 = 0x39,
|
||||
HAL_PROTO_FID_SJ_CONDITIONAL_SC_XV2 = 0x3a,
|
||||
HAL_PROTO_FID_RC_RELEASE_JTAG_XV2 = 0x3b,
|
||||
HAL_PROTO_FID_READ_MEM_WORDS_XV2 = 0x3c,
|
||||
HAL_PROTO_FID_READ_MEM_QUICK_XV2 = 0x3d,
|
||||
HAL_PROTO_FID_WRITE_MEM_WORDS_XV2 = 0x3e,
|
||||
HAL_PROTO_FID_EEM_DX_XV2 = 0x3f,
|
||||
HAL_PROTO_FID_SINGLE_STEP_XV2 = 0x40,
|
||||
HAL_PROTO_FID_READ_ALL_CPU_REGS_XV2 = 0x41,
|
||||
HAL_PROTO_FID_WRITE_ALL_CPU_REGS_XV2 = 0x42,
|
||||
HAL_PROTO_FID_PSA_XV2 = 0x43,
|
||||
HAL_PROTO_FID_EXECUTE_FUNCLET_XV2 = 0x44,
|
||||
HAL_PROTO_FID_UNLOCK_DEVICE_XV2 = 0x45,
|
||||
HAL_PROTO_FID_MAGIC_PATTERN = 0x46,
|
||||
HAL_PROTO_FID_UNLOCK_C092 = 0x47,
|
||||
HAL_PROTO_FID_HIL_COMMAND = 0x48,
|
||||
HAL_PROTO_FID_POLL_JSTATE_REG = 0x49,
|
||||
HAL_PROTO_FID_POLL_JSTATE_REG_FR57XX = 0x4a,
|
||||
HAL_PROTO_FID_IS_JTAG_FUSE_BLOWN = 0x4b,
|
||||
HAL_PROTO_FID_RESET_XV2 = 0x4c,
|
||||
HAL_PROTO_FID_WRITE_FRAM_QUICK_XV2 = 0x4d,
|
||||
HAL_PROTO_FID_SEND_JTAG_MAILBOX_XV2 = 0x4e,
|
||||
HAL_PROTO_FID_SINGLE_STEP_JSTATE_XV2 = 0x4f,
|
||||
HAL_PROTO_FID_POLL_JSTATE_REG_ET8 = 0x50,
|
||||
HAL_PROTO_FID_RESET_STATIC_GLOBAL_VARS = 0x51,
|
||||
HAL_PROTO_FID_RESET_430I = 0x52,
|
||||
HAL_PROTO_FID_POLL_JSTATE_REG_430I = 0x53
|
||||
} hal_proto_fid_t;
|
||||
|
||||
/* Argument types for HAL_PROTO_FID_CONFIGURE */
|
||||
|
@ -159,41 +126,14 @@ typedef enum {
|
|||
HAL_PROTO_CONFIG_SFLLDEH = 0x0c,
|
||||
HAL_PROTO_CONFIG_NO_BSL = 0x0d,
|
||||
HAL_PROTO_CONFIG_ALT_ROM_ADDR_FOR_CPU_READ = 0x0e,
|
||||
HAL_PROTO_CONFIG_ASSERT_BSL_VALID_BIT = 0x0f,
|
||||
HAL_PROTO_CONFIG_POWER_TESTREG_DEFAULT = 0x10,
|
||||
HAL_PROTO_CONFIG_POWER_TESTREGV3_DEFAULT = 0x11,
|
||||
HAL_PROTO_CONFIG_WDT_ADDRESS_5XX = 0x12,
|
||||
HAL_PROTO_CONFIG_SCS_BASE_ADDRESS = 0x13,
|
||||
HAL_PROTO_CONFIG_FPB_BASE_ADDRESS = 0x14,
|
||||
HAL_PROTO_CONFIG_INTERRUPT_OPTIONS = 0x15,
|
||||
HAL_PROTO_CONFIG_ULP_MSP432 = 0x16,
|
||||
HAL_PROTO_CONFIG_JTAG_LOCK_5XX = 0x17,
|
||||
HAL_PROTO_CONFIG_ASSERT_BSL_VALID_BIT = 0x0f
|
||||
} hal_proto_config_t;
|
||||
|
||||
static hal_proto_fid_t map_ver(const struct v3hil *h, hal_proto_fid_t src)
|
||||
{
|
||||
hal_proto_fid_t dst;
|
||||
|
||||
if (h->proto_ver < 0x0300 && src > HAL_PROTO_FID_GET_DEVICE_ID_PTR) {
|
||||
dst = src - 1;
|
||||
} else {
|
||||
dst = src;
|
||||
}
|
||||
|
||||
dbg_printc("map ver: %02x -> %02x\n", src, dst);
|
||||
return dst;
|
||||
}
|
||||
|
||||
static hal_proto_fid_t map_fid(const struct v3hil *h, hal_proto_fid_t src)
|
||||
{
|
||||
hal_proto_fid_t dst = h->chip->v3_functions[src];
|
||||
|
||||
if (dst == 0) {
|
||||
dst = src;
|
||||
}
|
||||
|
||||
dbg_printc("map fid: %02x -> %02x\n", src, dst);
|
||||
return map_ver(h, dst);
|
||||
return dst ? dst : src;
|
||||
}
|
||||
|
||||
void v3hil_init(struct v3hil *h, transport_t trans,
|
||||
|
@ -208,8 +148,7 @@ int v3hil_set_vcc(struct v3hil *h, int vcc_mv)
|
|||
uint8_t data[2];
|
||||
|
||||
w16le(data, vcc_mv);
|
||||
dbg_printc("Setting VCC...\n");
|
||||
return hal_proto_execute(&h->hal, map_ver(h, HAL_PROTO_FID_SET_VCC), data, 2);
|
||||
return hal_proto_execute(&h->hal, HAL_PROTO_FID_SET_VCC, data, 2);
|
||||
}
|
||||
|
||||
int v3hil_comm_init(struct v3hil *h)
|
||||
|
@ -224,43 +163,6 @@ int v3hil_comm_init(struct v3hil *h)
|
|||
return -1;
|
||||
if (h->hal.length < 8) {
|
||||
printc_err("warning: v3hil: short reply to version request\n");
|
||||
} else if (h->hal.length == 40) {
|
||||
#ifdef DEBUG_V3HIL
|
||||
printc_dbg("v3hil: Version:");
|
||||
for (int i = 0; i < h->hal.length; i++)
|
||||
printc_dbg(" %02x", h->hal.payload[i]);
|
||||
printc_dbg("\n");
|
||||
#endif
|
||||
const uint16_t sw_version = r32le(h->hal.payload + 0);
|
||||
const uint16_t sw_build = r32le(h->hal.payload + 2);
|
||||
const uint32_t hw_thing = r32le(h->hal.payload + 4);
|
||||
const uint32_t tool_id = r16le(h->hal.payload + 8);
|
||||
const uint16_t core_version = r16le(h->hal.payload + 10);
|
||||
const uint16_t hil_version = r16le(h->hal.payload + 12);
|
||||
const uint16_t dcdc_layer_version = r16le(h->hal.payload + 14);
|
||||
const uint16_t dcdc_mcu_version = r16le(h->hal.payload + 16);
|
||||
const uint16_t com_version = r16le(h->hal.payload + 18);
|
||||
|
||||
const uint16_t hil_crc = r16le(h->hal.payload + 20);
|
||||
const uint16_t hal_crc = r16le(h->hal.payload + 22);
|
||||
const uint16_t dcdc_crc = r16le(h->hal.payload + 24);
|
||||
const uint16_t core_crc = r16le(h->hal.payload + 26);
|
||||
const uint16_t com_crc = r16le(h->hal.payload + 28);
|
||||
|
||||
const uint16_t fpga_version = r16le(h->hal.payload + 30);
|
||||
const uint16_t n_rx_queues = r16le(h->hal.payload + 32);
|
||||
const uint16_t rx_queue_size = r16le(h->hal.payload + 34);
|
||||
|
||||
const uint8_t major = (sw_version >> 14) + 1;
|
||||
const uint8_t minor = (sw_version >> 8) & 0x3f;
|
||||
const uint8_t patch = sw_version & 0xff;
|
||||
const uint8_t build = sw_build;
|
||||
|
||||
printc_dbg("Version: %d.%d.%d.%d Core version: 0x%02x, HIL version: 0x%02x, HW: 0x%04x\n",
|
||||
major, minor, patch, build,
|
||||
core_version, hil_version, hw_thing);
|
||||
|
||||
h->proto_ver = (major << 8) | minor;
|
||||
} else {
|
||||
const uint8_t major = h->hal.payload[1] >> 6;
|
||||
const uint8_t minor = h->hal.payload[1] & 0x3f;
|
||||
|
@ -270,13 +172,11 @@ int v3hil_comm_init(struct v3hil *h)
|
|||
printc_dbg("Version: %d.%d.%d.%d, HW: 0x%04x\n",
|
||||
major, minor, patch, flavour,
|
||||
r32le(h->hal.payload + 4));
|
||||
|
||||
h->proto_ver = (major << 8) | minor;
|
||||
}
|
||||
|
||||
printc_dbg("Reset firmware...\n");
|
||||
if (hal_proto_execute(&h->hal,
|
||||
map_ver(h, HAL_PROTO_FID_RESET_STATIC_GLOBAL_VARS), NULL, 0) < 0)
|
||||
HAL_PROTO_FID_RESET_STATIC_GLOBAL_VARS, NULL, 0) < 0)
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
|
@ -287,8 +187,7 @@ int v3hil_start_jtag(struct v3hil *h, v3hil_jtag_type_t type)
|
|||
uint8_t data = type;
|
||||
uint8_t chain_id[2] = {0, 0};
|
||||
|
||||
dbg_printc("Start JTAG...\n");
|
||||
if (hal_proto_execute(&h->hal, map_ver(h, HAL_PROTO_FID_START_JTAG),
|
||||
if (hal_proto_execute(&h->hal, HAL_PROTO_FID_START_JTAG,
|
||||
&data, 1) < 0)
|
||||
return -1;
|
||||
|
||||
|
@ -303,30 +202,18 @@ int v3hil_start_jtag(struct v3hil *h, v3hil_jtag_type_t type)
|
|||
}
|
||||
|
||||
printc_dbg("Device count: %d\n", h->hal.payload[0]);
|
||||
return hal_proto_execute(&h->hal,
|
||||
map_ver(h, HAL_PROTO_FID_SET_DEVICE_CHAIN_INFO), chain_id, 2);
|
||||
return hal_proto_execute(&h->hal, HAL_PROTO_FID_SET_DEVICE_CHAIN_INFO,
|
||||
chain_id, 2);
|
||||
}
|
||||
|
||||
int v3hil_stop_jtag(struct v3hil *h)
|
||||
{
|
||||
dbg_printc("Stop JTAG...\n");
|
||||
if (hal_proto_execute(&h->hal, map_ver(h, HAL_PROTO_FID_STOP_JTAG), NULL, 0) < 0)
|
||||
return -1;
|
||||
|
||||
dbg_printc("Reset communications...\n");
|
||||
h->hal.ref_id = 0;
|
||||
if (hal_proto_send(&h->hal, HAL_PROTO_TYPE_EXCEPTION, NULL, 0) < 0) {
|
||||
h->hal.ref_id = 0;
|
||||
return -1;
|
||||
}
|
||||
h->hal.ref_id = 0;
|
||||
|
||||
return 0;
|
||||
return hal_proto_execute(&h->hal, HAL_PROTO_FID_STOP_JTAG, NULL, 0);
|
||||
}
|
||||
|
||||
int v3hil_sync(struct v3hil *h)
|
||||
{
|
||||
uint8_t data[32], datalen = 21;
|
||||
uint8_t data[32];
|
||||
|
||||
h->cal.is_cal = 0;
|
||||
|
||||
|
@ -341,21 +228,8 @@ int v3hil_sync(struct v3hil *h)
|
|||
if (h->chip) {
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 16; i++) {
|
||||
dbg_printc("clock map %d = %02x -> %d\n",
|
||||
i, h->chip->clock_map[i].value, 20-i);
|
||||
data[16 + 4 - i] = h->chip->clock_map[i].value;
|
||||
}
|
||||
|
||||
if (h->proto_ver >= 0x0308) {
|
||||
datalen = 21+16;
|
||||
|
||||
for (i = 16; i < 32; i++) {
|
||||
dbg_printc("clock map2 %d = %02x -> %d\n",
|
||||
i, h->chip->clock_map[i].value, 16+4+16*2 - i);
|
||||
data[16+4+16*2 - i] = h->chip->clock_map[i].value;
|
||||
}
|
||||
}
|
||||
for (i = 0; i < 16; i++)
|
||||
data[i + 20 - i] = h->chip->clock_map[i].value;
|
||||
} else {
|
||||
data[5] = 1;
|
||||
data[15] = 40;
|
||||
|
@ -364,36 +238,12 @@ int v3hil_sync(struct v3hil *h)
|
|||
/* We can't use map_fid() because h->chip might be NULL -- this
|
||||
* function will be called before identification is complete.
|
||||
*/
|
||||
hal_proto_fid_t cmdid = (h->jtag_id == 0x89/*0x90*/)
|
||||
? HAL_PROTO_FID_SJ_ASSERT_POR_SC
|
||||
: HAL_PROTO_FID_SJ_ASSERT_POR_SC_XV2;
|
||||
|
||||
dbg_printc("Sync: assert POR\n");
|
||||
if (h->chip) {
|
||||
if (hal_proto_execute(&h->hal, map_fid(h, cmdid), data, datalen) < 0) {
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
/* Need to do something for X/Xv2 devices, so try each in turn... */
|
||||
cmdid = map_ver(h, cmdid);
|
||||
if (hal_proto_execute(&h->hal, cmdid, data, datalen) < 0) {
|
||||
cmdid = map_ver(h, HAL_PROTO_FID_SJ_ASSERT_POR_SC_X);
|
||||
if (hal_proto_execute(&h->hal, cmdid, data, datalen) < 0) {
|
||||
cmdid = map_ver(h, HAL_PROTO_FID_SJ_ASSERT_POR_SC_XV2);
|
||||
if (hal_proto_execute(&h->hal, cmdid, data, datalen) < 0) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef DEBUG_V3HIL
|
||||
printc_dbg("v3hil: POR result: (len %d) ", h->hal.length);
|
||||
for (int i = 0; i < h->hal.length; ++i) {
|
||||
printc_dbg("%02x%s", h->hal.payload[i],
|
||||
(i == h->hal.length - 1) ? "\n" : " ");
|
||||
}
|
||||
#endif
|
||||
if (hal_proto_execute(&h->hal,
|
||||
(h->jtag_id == 0x89)
|
||||
? HAL_PROTO_FID_SJ_ASSERT_POR_SC
|
||||
: HAL_PROTO_FID_SJ_ASSERT_POR_SC_XV2,
|
||||
data, 21) < 0)
|
||||
return -1;
|
||||
|
||||
if (h->hal.length < 8) {
|
||||
printc_err("v3hil: short reply: %d\n", h->hal.length);
|
||||
|
@ -424,7 +274,6 @@ int v3hil_read(struct v3hil *h, address_t addr,
|
|||
w32le(req + 4, (m->bits == 8) ? size : (size >> 1));
|
||||
w32le(req + 8, h->regs[MSP430_REG_PC]);
|
||||
|
||||
dbg_printc("do read\n");
|
||||
if (hal_proto_execute(&h->hal,
|
||||
map_fid(h, (m->bits == 8) ? HAL_PROTO_FID_READ_MEM_BYTES :
|
||||
HAL_PROTO_FID_READ_MEM_WORDS),
|
||||
|
@ -483,7 +332,6 @@ static int calibrate_dco(struct v3hil *h, uint8_t max_bcs)
|
|||
w16le(data, ram->offset);
|
||||
w16le(data + 2, max_bcs);
|
||||
|
||||
dbg_printc("calibrate dco: get freq\n");
|
||||
if (hal_proto_execute(&h->hal,
|
||||
map_fid(h, HAL_PROTO_FID_GET_DCO_FREQUENCY),
|
||||
data, 6) < 0)
|
||||
|
@ -502,7 +350,6 @@ static int calibrate_dco(struct v3hil *h, uint8_t max_bcs)
|
|||
mem_write[9] = data[2]; /* BCS1 */
|
||||
mem_write[10] = data[4]; /* BCS2 */
|
||||
mem_write[11] = 0; /* pad */
|
||||
dbg_printc("calibrate dco: write\n");
|
||||
if (hal_proto_execute(&h->hal,
|
||||
map_fid(h, HAL_PROTO_FID_WRITE_MEM_BYTES),
|
||||
mem_write, 12) < 0) {
|
||||
|
@ -531,7 +378,6 @@ static int calibrate_fll(struct v3hil *h)
|
|||
w16le(data, ram->offset);
|
||||
w16le(data + 2, 0);
|
||||
|
||||
dbg_printc("calibrate fll: get dco freq\n");
|
||||
if (hal_proto_execute(&h->hal,
|
||||
map_fid(h, HAL_PROTO_FID_GET_DCO_FREQUENCY),
|
||||
data, 10) < 0)
|
||||
|
@ -553,7 +399,6 @@ static int calibrate_fll(struct v3hil *h)
|
|||
mem_write[12] = data[8]; /* FLLCTL1 */
|
||||
mem_write[13] = 0; /* pad */
|
||||
|
||||
dbg_printc("calibrate fll: write\n");
|
||||
if (hal_proto_execute(&h->hal,
|
||||
map_fid(h, HAL_PROTO_FID_WRITE_MEM_BYTES),
|
||||
mem_write, 14) < 0) {
|
||||
|
@ -625,7 +470,6 @@ static int upload_funclet(struct v3hil *h,
|
|||
for (i = 0; i < n; i++)
|
||||
w16le(data + 8 + i * 2, code[i]);
|
||||
|
||||
dbg_printc("upload funclet: %d\n", n);
|
||||
if (hal_proto_execute(&h->hal,
|
||||
map_fid(h, HAL_PROTO_FID_WRITE_MEM_WORDS),
|
||||
data, n * 2 + 8) < 0) {
|
||||
|
@ -659,10 +503,8 @@ static int write_flash(struct v3hil *h, address_t addr,
|
|||
return -1;
|
||||
}
|
||||
|
||||
dbg_printc("write flash: calibrate\n");
|
||||
if (calibrate(h) < 0)
|
||||
return -1;
|
||||
dbg_printc("write flash: upload funclet\n");
|
||||
if (upload_funclet(h, ram, f) < 0)
|
||||
return -1;
|
||||
|
||||
|
@ -687,7 +529,6 @@ static int write_flash(struct v3hil *h, address_t addr,
|
|||
w16le(data + 20, h->cal.cal1);
|
||||
memcpy(data + 22, mem, size);
|
||||
|
||||
dbg_printc("exec write flash funclet\n");
|
||||
if (hal_proto_execute(&h->hal,
|
||||
map_fid(h, HAL_PROTO_FID_EXECUTE_FUNCLET),
|
||||
data, size + 22) < 0) {
|
||||
|
@ -703,24 +544,16 @@ static int write_ram(struct v3hil *h, const struct chipinfo_memory *m,
|
|||
address_t addr, const uint8_t *mem, address_t size)
|
||||
{
|
||||
uint8_t data[256];
|
||||
bool fram = false;
|
||||
if (h->chip->features & CHIPINFO_FEATURE_FRAM) {
|
||||
if (!strcmp(m->name, "Main") || !strcmp(m->name, "Info")) {
|
||||
dbg_printc("write ram: to FRAM!\n");
|
||||
fram = true;
|
||||
}
|
||||
}
|
||||
|
||||
w32le(data, addr);
|
||||
w32le(data + 4, (m->bits == 8 || fram) ? size : (size >> 1));
|
||||
w32le(data + 4, (m->bits == 8) ? size : (size >> 1));
|
||||
|
||||
memcpy(data + 8, mem, size);
|
||||
|
||||
dbg_printc("write ram\n");
|
||||
hal_proto_fid_t fid = (m->bits == 8) ? HAL_PROTO_FID_WRITE_MEM_BYTES
|
||||
: HAL_PROTO_FID_WRITE_MEM_WORDS;
|
||||
if (fram) fid = HAL_PROTO_FID_WRITE_FRAM_QUICK_XV2;
|
||||
if (hal_proto_execute(&h->hal, map_fid(h, fid), data, size + 8) < 0) {
|
||||
if (hal_proto_execute(&h->hal,
|
||||
map_fid(h, (m->bits == 8) ? HAL_PROTO_FID_WRITE_MEM_BYTES
|
||||
: HAL_PROTO_FID_WRITE_MEM_WORDS),
|
||||
data, size + 8) < 0) {
|
||||
printc_err("v3hil: failed writing %d bytes to 0x%05x\n",
|
||||
size, addr);
|
||||
return -1;
|
||||
|
@ -743,12 +576,9 @@ int v3hil_write(struct v3hil *h, address_t addr,
|
|||
if (size > 128)
|
||||
size = 128;
|
||||
|
||||
if (m->type == CHIPINFO_MEMTYPE_FLASH) {
|
||||
dbg_printc("write: call write flash\n");
|
||||
if (m->type == CHIPINFO_MEMTYPE_FLASH)
|
||||
return write_flash(h, addr, mem, size);
|
||||
}
|
||||
|
||||
dbg_printc("write: call write ram\n");
|
||||
return write_ram(h, m, addr, mem, size);
|
||||
}
|
||||
|
||||
|
@ -773,7 +603,6 @@ static int call_erase(struct v3hil *h,
|
|||
w16le(data + 20, h->cal.cal1);
|
||||
w32le(data + 22, 0xdeadbeef);
|
||||
|
||||
dbg_printc("erase: call funclet\n");
|
||||
if (hal_proto_execute(&h->hal,
|
||||
map_fid(h, HAL_PROTO_FID_EXECUTE_FUNCLET),
|
||||
data, 26) < 0) {
|
||||
|
@ -807,10 +636,8 @@ int v3hil_erase(struct v3hil *h, address_t segment)
|
|||
if (!flash)
|
||||
printc_err("v3hil: can't find appropriate flash region\n");
|
||||
|
||||
dbg_printc("erase: calibrate\n");
|
||||
if (calibrate(h) < 0)
|
||||
return -1;
|
||||
dbg_printc("erase: upload funclet\n");
|
||||
if (upload_funclet(h, ram, f) < 0)
|
||||
return -1;
|
||||
|
||||
|
@ -821,13 +648,10 @@ int v3hil_erase(struct v3hil *h, address_t segment)
|
|||
if (flash->banks)
|
||||
bank_size /= flash->banks;
|
||||
|
||||
for (i = flash->banks; i >= 0; i--) {
|
||||
dbg_printc("Erase bank %d\n", i);
|
||||
|
||||
for (i = flash->banks; i >= 0; i--)
|
||||
if (call_erase(h, ram, f,
|
||||
flash->offset + i * bank_size - 2, 0xa502) < 0)
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
segment &= ~(flash->seg_size - 1);
|
||||
segment |= flash->seg_size - 2;
|
||||
|
@ -841,15 +665,12 @@ int v3hil_erase(struct v3hil *h, address_t segment)
|
|||
|
||||
int v3hil_update_regs(struct v3hil *h)
|
||||
{
|
||||
const hal_proto_fid_t fid = map_fid(h, HAL_PROTO_FID_READ_ALL_CPU_REGS);
|
||||
const int reg_size = (fid == HAL_PROTO_FID_READ_ALL_CPU_REGS
|
||||
|| fid == HAL_PROTO_FID_READ_ALL_CPU_REGS - 1)
|
||||
? 2 : 3;
|
||||
|
||||
const hal_proto_fid_t fid =
|
||||
map_fid(h, HAL_PROTO_FID_READ_ALL_CPU_REGS);
|
||||
const int reg_size = (fid == HAL_PROTO_FID_READ_ALL_CPU_REGS) ? 2 : 3;
|
||||
int i;
|
||||
int sptr = 0;
|
||||
|
||||
dbg_printc("Read regs\n");
|
||||
if (hal_proto_execute(&h->hal, fid, NULL, 0) < 0) {
|
||||
printc_err("v3hil: can't read CPU registers\n");
|
||||
return -1;
|
||||
|
@ -881,10 +702,9 @@ int v3hil_update_regs(struct v3hil *h)
|
|||
|
||||
int v3hil_flush_regs(struct v3hil *h)
|
||||
{
|
||||
const hal_proto_fid_t fid = map_fid(h, HAL_PROTO_FID_WRITE_ALL_CPU_REGS);
|
||||
const int reg_size = (fid == HAL_PROTO_FID_WRITE_ALL_CPU_REGS
|
||||
|| fid == HAL_PROTO_FID_WRITE_ALL_CPU_REGS - 1)
|
||||
? 2 : 3;
|
||||
const hal_proto_fid_t fid =
|
||||
map_fid(h, HAL_PROTO_FID_WRITE_ALL_CPU_REGS);
|
||||
const int reg_size = (fid == HAL_PROTO_FID_WRITE_ALL_CPU_REGS) ? 2 : 3;
|
||||
int i;
|
||||
int dptr = 0;
|
||||
uint8_t data[64];
|
||||
|
@ -904,7 +724,6 @@ int v3hil_flush_regs(struct v3hil *h)
|
|||
}
|
||||
}
|
||||
|
||||
dbg_printc("Write regs\n");
|
||||
if (hal_proto_execute(&h->hal, fid, data, reg_size * 13) < 0) {
|
||||
printc_err("v3hil: can't write CPU registers\n");
|
||||
return -1;
|
||||
|
@ -928,7 +747,6 @@ int v3hil_context_restore(struct v3hil *h, int free)
|
|||
data[10] = free ? 7 : 6;
|
||||
data[14] = free ? 1 : 0;
|
||||
|
||||
dbg_printc("Context restore\n");
|
||||
if (hal_proto_execute(&h->hal,
|
||||
map_fid(h, HAL_PROTO_FID_RC_RELEASE_JTAG),
|
||||
data, 18) < 0) {
|
||||
|
@ -951,7 +769,6 @@ int v3hil_context_save(struct v3hil *h)
|
|||
data[2] = h->wdtctl | 0x80;
|
||||
data[3] = 0x5a; /* WDTPW */
|
||||
|
||||
dbg_printc("Context save\n");
|
||||
if (hal_proto_execute(&h->hal,
|
||||
map_fid(h, HAL_PROTO_FID_SJ_CONDITIONAL_SC),
|
||||
data, 8) < 0)
|
||||
|
@ -983,7 +800,6 @@ int v3hil_single_step(struct v3hil *h)
|
|||
data[9] = h->regs[MSP430_REG_SR] >> 8;
|
||||
data[10] = 7;
|
||||
|
||||
dbg_printc("Single-stepping...\n");
|
||||
if (hal_proto_execute(&h->hal,
|
||||
map_fid(h, HAL_PROTO_FID_SINGLE_STEP),
|
||||
data, 18) < 0) {
|
||||
|
@ -1018,9 +834,7 @@ static int set_param(struct v3hil *fet, hal_proto_config_t cfg,
|
|||
}
|
||||
|
||||
data[0] = cfg;
|
||||
|
||||
dbg_printc("Set param 0x%02x to 0x%08x\n", cfg, value);
|
||||
if (hal_proto_execute(&fet->hal, map_ver(fet, HAL_PROTO_FID_CONFIGURE),
|
||||
if (hal_proto_execute(&fet->hal, HAL_PROTO_FID_CONFIGURE,
|
||||
data, 8) < 0) {
|
||||
printc_err("v3hil: can't set param 0x%02x to 0x%08x\n",
|
||||
cfg, value);
|
||||
|
@ -1040,7 +854,7 @@ static int idproc_89(struct v3hil *fet, uint32_t id_data_addr,
|
|||
memset(data, 0, 8);
|
||||
w32le(data, id_data_addr);
|
||||
data[4] = 8;
|
||||
if (hal_proto_execute(&fet->hal, map_ver(fet, HAL_PROTO_FID_READ_MEM_WORDS),
|
||||
if (hal_proto_execute(&fet->hal, HAL_PROTO_FID_READ_MEM_WORDS,
|
||||
data, 8) < 0)
|
||||
return -1;
|
||||
if (fet->hal.length < 16) {
|
||||
|
@ -1056,7 +870,7 @@ static int idproc_89(struct v3hil *fet, uint32_t id_data_addr,
|
|||
id->config = fet->hal.payload[13] & 0x7f;
|
||||
|
||||
printc_dbg("Read fuses...\n");
|
||||
if (hal_proto_execute(&fet->hal, map_ver(fet, HAL_PROTO_FID_GET_FUSES), NULL, 0) < 0)
|
||||
if (hal_proto_execute(&fet->hal, HAL_PROTO_FID_GET_FUSES, NULL, 0) < 0)
|
||||
return -1;
|
||||
if (!fet->hal.length) {
|
||||
printc_err("v3hil: short reply: %d\n", fet->hal.length);
|
||||
|
@ -1080,7 +894,7 @@ static int idproc_9x(struct v3hil *fet, uint32_t dev_id_ptr,
|
|||
memset(data, 0, 8);
|
||||
w32le(data, dev_id_ptr);
|
||||
data[4] = 4;
|
||||
if (hal_proto_execute(&fet->hal, map_ver(fet, HAL_PROTO_FID_READ_MEM_QUICK_XV2),
|
||||
if (hal_proto_execute(&fet->hal, HAL_PROTO_FID_READ_MEM_QUICK_XV2,
|
||||
data, 8) < 0)
|
||||
return -1;
|
||||
if (fet->hal.length < 8) {
|
||||
|
@ -1104,7 +918,7 @@ static int idproc_9x(struct v3hil *fet, uint32_t dev_id_ptr,
|
|||
w32le(data, dev_id_ptr);
|
||||
w32le(data + 4, tlv_size >> 1);
|
||||
w32le(data + 8, fet->regs[MSP430_REG_PC]);
|
||||
if (hal_proto_execute(&fet->hal, map_ver(fet, HAL_PROTO_FID_READ_MEM_QUICK_XV2),
|
||||
if (hal_proto_execute(&fet->hal, HAL_PROTO_FID_READ_MEM_QUICK_XV2,
|
||||
data, 8) < 0)
|
||||
return -1;
|
||||
if (fet->hal.length < tlv_size) {
|
||||
|
@ -1121,11 +935,8 @@ static int idproc_9x(struct v3hil *fet, uint32_t dev_id_ptr,
|
|||
if (tag == 0xff)
|
||||
break;
|
||||
|
||||
if ((tag == 0x14) && (len >= 2)) {
|
||||
// FIXME: this looks like it's reading from the wrong address?
|
||||
if ((tag == 0x14) && (len >= 2))
|
||||
id->ver_sub_id = r16le(fet->hal.payload);
|
||||
// FIXME: break here?
|
||||
}
|
||||
|
||||
i += len;
|
||||
}
|
||||
|
@ -1141,56 +952,26 @@ int v3hil_identify(struct v3hil *fet)
|
|||
int i;
|
||||
|
||||
printc_dbg("Fetching JTAG ID...\n");
|
||||
if (hal_proto_execute(&fet->hal, map_ver(fet, HAL_PROTO_FID_GET_JTAG_ID),
|
||||
if (hal_proto_execute(&fet->hal, HAL_PROTO_FID_GET_JTAG_ID,
|
||||
NULL, 0) < 0)
|
||||
return -1;
|
||||
|
||||
if (fet->hal.length < 12) {
|
||||
printc_err("v3hil: short reply: %d\n", fet->hal.length);
|
||||
return -1;
|
||||
}
|
||||
|
||||
printc_dbg("ID:");
|
||||
for (i = 0; i < fet->hal.length; i++)
|
||||
printc_dbg(" %02x", fet->hal.payload[i]);
|
||||
printc_dbg("\n");
|
||||
|
||||
if (fet->hal.length < 12) {
|
||||
if (fet->hal.length == 2) {
|
||||
fet->jtag_id = fet->hal.payload[0];
|
||||
|
||||
if (hal_proto_execute(&fet->hal, map_ver(fet, HAL_PROTO_FID_GET_DEVICE_ID_PTR),
|
||||
NULL, 0) < 0)
|
||||
return -1;
|
||||
|
||||
#ifdef DEBUG_V3HIL
|
||||
dbg_printc("len: %d\n", fet->hal.length);
|
||||
printc_dbg("v3hil: IDPtr:");
|
||||
for (i = 0; i < fet->hal.length; i++)
|
||||
printc_dbg(" %02x", fet->hal.payload[i]);
|
||||
printc_dbg("\n");
|
||||
#endif
|
||||
|
||||
if (fet->hal.length < 10) {
|
||||
printc_err("v3hil: short reply: %d\n", fet->hal.length);
|
||||
return -1;
|
||||
} else {
|
||||
dev_id_ptr = r32le(fet->hal.payload + 0);
|
||||
|
||||
if (dev_id_ptr == 0) {
|
||||
/* welp sometimes it's this instead (JTAG ID == 0x89?) */
|
||||
dev_id_ptr = r32le(fet->hal.payload + 4);
|
||||
}
|
||||
|
||||
id_data_addr = dev_id_ptr; /* idk */
|
||||
}
|
||||
} else {
|
||||
printc_err("v3hil: short reply: %d\n", fet->hal.length);
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
/* Byte at 0 is JTAG ID. 0x91, 0x95, 0x99 means CPUxV2. 0x89
|
||||
* means old CPU.
|
||||
*/
|
||||
fet->jtag_id = fet->hal.payload[0];
|
||||
dev_id_ptr = r32le(fet->hal.payload + 4);
|
||||
id_data_addr = r32le(fet->hal.payload + 8);
|
||||
}
|
||||
/* Byte at 0 is JTAG ID. 0x91, 0x95, 0x99 means CPUxV2. 0x89
|
||||
* means old CPU.
|
||||
*/
|
||||
fet->jtag_id = fet->hal.payload[0];
|
||||
dev_id_ptr = r32le(fet->hal.payload + 4);
|
||||
id_data_addr = r32le(fet->hal.payload + 8);
|
||||
|
||||
/* Pick fail-safe configuration */
|
||||
printc_dbg("Reset parameters...\n");
|
||||
|
@ -1201,12 +982,12 @@ int v3hil_identify(struct v3hil *fet)
|
|||
set_param(fet, HAL_PROTO_CONFIG_PSA_TCKL_HIGH, 0) < 0 ||
|
||||
set_param(fet, HAL_PROTO_CONFIG_POWER_TESTREG_MASK, 0) < 0 ||
|
||||
set_param(fet, HAL_PROTO_CONFIG_POWER_TESTREG3V_MASK, 0) < 0 ||
|
||||
set_param(fet, HAL_PROTO_CONFIG_NO_BSL, 0) < 0 ||
|
||||
set_param(fet, HAL_PROTO_CONFIG_ALT_ROM_ADDR_FOR_CPU_READ, 0) < 0)
|
||||
return -1;
|
||||
set_param(fet, HAL_PROTO_CONFIG_NO_BSL, 0); /* is allowed to fail */
|
||||
|
||||
printc_dbg("Check JTAG fuse...\n");
|
||||
if (hal_proto_execute(&fet->hal, map_ver(fet, HAL_PROTO_FID_IS_JTAG_FUSE_BLOWN),
|
||||
if (hal_proto_execute(&fet->hal, HAL_PROTO_FID_IS_JTAG_FUSE_BLOWN,
|
||||
NULL, 0) < 0)
|
||||
return -1;
|
||||
if ((fet->hal.length >= 2) &&
|
||||
|
@ -1275,13 +1056,13 @@ int v3hil_configure(struct v3hil *fet)
|
|||
fet->chip->power.enable_lpm5_3v) < 0 ||
|
||||
set_param(fet, HAL_PROTO_CONFIG_TESTREG3V_DISABLE_LPMX5,
|
||||
fet->chip->power.disable_lpm5_3v) < 0 ||
|
||||
set_param(fet, HAL_PROTO_CONFIG_NO_BSL,
|
||||
(fet->chip->features &
|
||||
CHIPINFO_FEATURE_NO_BSL) ? 1 : 0) < 0 ||
|
||||
set_param(fet, HAL_PROTO_CONFIG_ALT_ROM_ADDR_FOR_CPU_READ,
|
||||
(fet->chip->features &
|
||||
CHIPINFO_FEATURE_1337) ? 1 : 0) < 0)
|
||||
return -1;
|
||||
/* is allowed to fail */
|
||||
set_param(fet, HAL_PROTO_CONFIG_NO_BSL,
|
||||
(fet->chip->features & CHIPINFO_FEATURE_NO_BSL) ? 1 : 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -44,9 +44,6 @@ struct v3hil {
|
|||
/* Lower 8 bits of saved WDTCTL */
|
||||
uint8_t wdtctl;
|
||||
|
||||
/* Is this a v2 or v3 firmware running on the eZ-FET? */
|
||||
uint16_t proto_ver;
|
||||
|
||||
/* Register cache: this must be flushed before restoring context
|
||||
* and updated after saving context.
|
||||
*/
|
||||
|
|
|
@ -247,10 +247,8 @@ static int feed_section(struct elf32_info *info,
|
|||
ch.data = buf;
|
||||
ch.len = len;
|
||||
|
||||
if (cb(user_data, &ch) < 0) {
|
||||
pr_error("elf32: misc error");
|
||||
if (cb(user_data, &ch) < 0)
|
||||
return -1;
|
||||
}
|
||||
|
||||
size -= len;
|
||||
offset += len;
|
||||
|
@ -333,7 +331,7 @@ int elf32_extract(FILE *in, binfile_imgcb_t cb, void *user_data)
|
|||
Elf32_Shdr *s = &info.file_shdrs[i];
|
||||
|
||||
if ((s->sh_type == SHT_PROGBITS || s->sh_type == SHT_INIT_ARRAY) &&
|
||||
(s->sh_flags & SHF_ALLOC) && s->sh_size > 0 &&
|
||||
s->sh_flags & SHF_ALLOC &&
|
||||
feed_section(&info, in, s, cb, user_data) < 0) {
|
||||
ret = -1;
|
||||
break;
|
||||
|
|
14
mspdebug.man
14
mspdebug.man
|
@ -52,10 +52,6 @@ section \fBDRIVERS\fR below for details.
|
|||
.IP "\-U \fIbus\fR:\fIdevice\fR"
|
||||
Specify a particular USB device to connect to. Without this option,
|
||||
the first device of the appropriate type is opened.
|
||||
.IP "\-V \fIvid\fR:\fIpid\fR"
|
||||
Specify a VID and PID of the USB device to connect to, or override the
|
||||
default VID and PID. Some drives, such as \fBmehfet\fR, require this option,
|
||||
while others have a default VID and PID which can be overridden.
|
||||
.IP "\-s \fIserial\fR"
|
||||
Specify a particular USB device serial number to connect to. Use this
|
||||
option to distinguish between multiple devices of the same type.
|
||||
|
@ -234,13 +230,6 @@ There are reports of this operation causing an erase of info A in some
|
|||
devices. Use at your own risk.
|
||||
.IP "\fBbus-pirate\fR"
|
||||
Raw JTAG using Bus Pirate devices.
|
||||
.IP "\fBmehfet\fR"
|
||||
Connect to a MehFET USB-based debugging protocol-capable device. It can
|
||||
support both JTAG and Spy-Bi-Wire. For now, only 16-bit CPUs (that is,
|
||||
non-430X or Xv2) are suppored, as with the \fBpif\fR, \fBgpio\fR,
|
||||
\fBbus-pirate\fR and \fBgoodfet\fR rivers.
|
||||
|
||||
For documentation on the USB protocol, see the \fBSEE ALSO\fR section.
|
||||
.SH COMMANDS
|
||||
MSPDebug can accept commands either through an interactive prompt, or
|
||||
non-interactively when specified on the command line. The supported
|
||||
|
@ -837,9 +826,6 @@ Firmware image for the TI3410 USB interface chip. This file is only
|
|||
required for raw USB access to FET430UIF or eZ430 devices.
|
||||
.SH SEE ALSO
|
||||
\fBnm\fR(1), \fBgdb\fR(1), \fBobjcopy\fR(1)
|
||||
|
||||
\fBmehfet\fR protocol documentation can be found at the following URL:
|
||||
https://git.lain.faith/sys64738/DragonProbe/wiki/MehFET-USB-protocol
|
||||
.SH BUGS
|
||||
If you find any bugs, you should report them to the author at
|
||||
dlbeer@gmail.com. It would help if you could include a transcript
|
||||
|
|
|
@ -1,406 +0,0 @@
|
|||
/* MSPDebug - debugging tool for MSP430 MCUs
|
||||
* Copyright (C) 2021 sys64738@disroot.org
|
||||
*
|
||||
* 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "mehfet_xport.h"
|
||||
#include "util.h"
|
||||
#include "usbutil.h"
|
||||
#include "output.h"
|
||||
|
||||
struct mehfet_transport {
|
||||
struct transport base;
|
||||
struct usb_dev_handle *handle;
|
||||
int epin, epout;
|
||||
int buf_size;
|
||||
};
|
||||
|
||||
|
||||
#define TIMEOUT_S 30
|
||||
#define REQ_TIMEOUT_MS 100
|
||||
|
||||
|
||||
static int open_device(struct mehfet_transport *tr, struct usb_device *dev)
|
||||
{
|
||||
#ifdef __linux__
|
||||
int driver;
|
||||
char drv_name[128];
|
||||
#endif
|
||||
|
||||
// first, find the right interface (and associated endpoints) of the USB device
|
||||
|
||||
int config = 0, itf = 0;
|
||||
bool has = false;
|
||||
|
||||
for (config = 0; config < dev->descriptor.bNumConfigurations; ++config) {
|
||||
struct usb_config_descriptor* cd = &dev->config[config];
|
||||
|
||||
for (itf = 0; itf < cd->bNumInterfaces; ++itf) {
|
||||
struct usb_interface_descriptor* id = &cd->interface[itf].altsetting[0];
|
||||
|
||||
if (id->bInterfaceClass == USB_CLASS_VENDOR_SPEC
|
||||
&& id->bInterfaceSubClass == '4'
|
||||
&& id->bInterfaceProtocol == '3') {
|
||||
// here I'd like to check for the "MehFET" substring in the
|
||||
// interface's iInterface string, but I can't really figure out
|
||||
// how to do that, so I'll just assume this is enough checking.
|
||||
|
||||
if (id->bNumEndpoints != 2) continue; // this should be 2
|
||||
for (size_t i = 0; i < id->bNumEndpoints; ++i) {
|
||||
struct usb_endpoint_descriptor* ed = &id->endpoint[i];
|
||||
|
||||
if ((ed->bmAttributes & USB_ENDPOINT_TYPE_MASK)
|
||||
!= USB_ENDPOINT_TYPE_BULK)
|
||||
break;
|
||||
|
||||
if (ed->bEndpointAddress & USB_ENDPOINT_DIR_MASK)
|
||||
tr->epin = ed->bEndpointAddress; // input endpoint
|
||||
else
|
||||
tr->epout = ed->bEndpointAddress; // output endpoint
|
||||
}
|
||||
|
||||
if (tr->epin != 0 && tr->epout != 0) {
|
||||
has = true;
|
||||
goto break_outer;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break_outer:
|
||||
|
||||
if (!has) {
|
||||
printc_err("mehfet transport: USB device %s has no MehFET interface.\n",
|
||||
dev->filename);
|
||||
return -1;
|
||||
}
|
||||
|
||||
printc_dbg("mehfet transport: trying to open %s\n", dev->filename);
|
||||
tr->handle = usb_open(dev);
|
||||
if (!tr->handle) {
|
||||
printc_err("mehfet transport: can't open device: %s\n",
|
||||
usb_strerror());
|
||||
return -1;
|
||||
}
|
||||
|
||||
#ifdef __linux__
|
||||
driver = usb_get_driver_np(tr->handle, itf, drv_name, sizeof(drv_name));
|
||||
if (driver >= 0) {
|
||||
printc_dbg("Detaching kernel driver \"%s\"\n", drv_name);
|
||||
if (usb_detach_kernel_driver_np(tr->handle, itf) < 0)
|
||||
printc_err("warning: mehfet transport: can't detach "
|
||||
"kernel driver: %s\n", usb_strerror());
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef __Windows__
|
||||
if (usb_set_configuration(tr->handle, config) < 0) {
|
||||
printc_err("mehfet transport: can't set configuration: %s\n",
|
||||
usb_strerror());
|
||||
usb_close(tr->handle);
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (usb_claim_interface(tr->handle, itf) < 0) {
|
||||
printc_err("mehfet transport: can't claim interface: %s\n",
|
||||
usb_strerror());
|
||||
usb_close(tr->handle);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void tr_destroy(transport_t tr_base)
|
||||
{
|
||||
struct mehfet_transport *tr = (struct mehfet_transport *)tr_base;
|
||||
|
||||
usb_close(tr->handle);
|
||||
free(tr);
|
||||
}
|
||||
|
||||
static int tr_recv(transport_t tr_base, uint8_t *databuf, int max_len)
|
||||
{
|
||||
struct mehfet_transport *tr = (struct mehfet_transport *)tr_base;
|
||||
time_t deadline = time(NULL) + TIMEOUT_S;
|
||||
char tmpbuf[tr->buf_size];
|
||||
|
||||
if (max_len > tr->buf_size)
|
||||
max_len = tr->buf_size;
|
||||
|
||||
while (time(NULL) < deadline) {
|
||||
int r = usb_bulk_read(tr->handle, tr->epin,
|
||||
tmpbuf, max_len,
|
||||
TIMEOUT_S * 1000);
|
||||
|
||||
if (r <= 0) {
|
||||
printc_err("mehfet transport: usb_bulk_read: %s\n",
|
||||
usb_strerror());
|
||||
return -1;
|
||||
}
|
||||
|
||||
memcpy(databuf, tmpbuf, r);
|
||||
#ifdef DEBUG_MEHFET_TRANSPORT
|
||||
printc_dbg("mehfet transport: tr_recv: flags = %02x %02x\n",
|
||||
tmpbuf[0], tmpbuf[1]);
|
||||
debug_hexdump("mehfet transport: tr_recv", databuf, r);
|
||||
#endif
|
||||
return r;
|
||||
}
|
||||
|
||||
printc_err("mehfet transport: timed out while receiving data\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int tr_send(transport_t tr_base, const uint8_t *databuf, int len)
|
||||
{
|
||||
struct mehfet_transport *tr = (struct mehfet_transport *)tr_base;
|
||||
|
||||
#ifdef DEBUG_MEHFET
|
||||
debug_hexdump("mehfet transport: tr_send", databuf, len);
|
||||
#endif
|
||||
while (len) {
|
||||
int r = usb_bulk_write(tr->handle, tr->epout,
|
||||
(char *)databuf, len,
|
||||
TIMEOUT_S * 1000);
|
||||
|
||||
if (r <= 0) {
|
||||
printc_err("mehfet transport: usb_bulk_write: %s\n",
|
||||
usb_strerror());
|
||||
return -1;
|
||||
}
|
||||
|
||||
databuf += r;
|
||||
len -= r;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tr_flush(transport_t tr_base)
|
||||
{
|
||||
(void)tr_base;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tr_set_modem(transport_t tr_base, transport_modem_t state)
|
||||
{
|
||||
(void)tr_base; (void)state;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct transport_class mehfet_class = {
|
||||
.destroy = tr_destroy,
|
||||
.send = tr_send,
|
||||
.recv = tr_recv,
|
||||
.flush = tr_flush,
|
||||
.set_modem = tr_set_modem
|
||||
};
|
||||
|
||||
transport_t mehfet_transport_open(const char *devpath,
|
||||
const uint16_t* vendor, const uint16_t* product,
|
||||
const char *requested_serial)
|
||||
{
|
||||
struct mehfet_transport *tr = malloc(sizeof(*tr));
|
||||
struct usb_device *dev = NULL;
|
||||
|
||||
if (!tr) {
|
||||
pr_error("mehfet transport: can't allocate memory");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
tr->base.ops = &mehfet_class;
|
||||
|
||||
usb_init();
|
||||
usb_find_busses();
|
||||
usb_find_devices();
|
||||
|
||||
if (devpath)
|
||||
dev = usbutil_find_by_loc(devpath);
|
||||
else if (vendor && product)
|
||||
dev = usbutil_find_by_id(*vendor, *product, requested_serial);
|
||||
|
||||
if (!dev) {
|
||||
printc_err("mehfet: no USB device found.%s\n",
|
||||
vendor ? "" : " (Did you forget to specify a VID:PID?)");
|
||||
free(tr);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
tr->buf_size = 64; // initial conservative value, will get updated later
|
||||
|
||||
if (open_device(tr, dev) < 0) {
|
||||
printc_err("mehfet: failed to open device\n");
|
||||
free(tr);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return &tr->base;
|
||||
}
|
||||
|
||||
|
||||
void mehfet_transport_set_buf_size(transport_t tr_base, int buf_size)
|
||||
{
|
||||
struct mehfet_transport *tr = (struct mehfet_transport *)tr_base;
|
||||
|
||||
tr->buf_size = buf_size;
|
||||
}
|
||||
int mehfet_transport_get_buf_size(transport_t tr_base)
|
||||
{
|
||||
struct mehfet_transport *tr = (struct mehfet_transport *)tr_base;
|
||||
|
||||
return tr->buf_size;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int mehfet_send_raw(transport_t xport, uint8_t cmd, int datalen, const void* data) {
|
||||
if (datalen < 0) return -1;
|
||||
if (data && !datalen) return -1;
|
||||
if (!data && datalen) return -1;
|
||||
|
||||
uint8_t buf[1+4+datalen];
|
||||
|
||||
buf[0] = cmd;
|
||||
int i, len2;
|
||||
for (i = 0, len2 = datalen; i < 4 && len2; ++i, len2 >>= 7) {
|
||||
buf[0] |= 0x80; // command has payload data
|
||||
|
||||
if (i == 3) {
|
||||
buf[i+1] = len2;
|
||||
} else {
|
||||
buf[i+1] = len2 & 0x7f;
|
||||
if (len2 >> 7) buf[i+1] |= 0x80;
|
||||
}
|
||||
}
|
||||
|
||||
if (data && datalen) memcpy(&buf[i+1], data, datalen);
|
||||
|
||||
return xport->ops->send(xport, buf, datalen + 1 + i);
|
||||
}
|
||||
|
||||
int mehfet_recv_raw(transport_t xport, uint8_t* stat, int* datalen, void* data) {
|
||||
struct mehfet_transport *tr = (struct mehfet_transport *)xport;
|
||||
uint8_t rawbuf[tr->buf_size];
|
||||
|
||||
int nmax = 5, ndata = 0, nfetch;
|
||||
if (datalen) {
|
||||
ndata = *datalen;
|
||||
nmax = ndata + 5;
|
||||
}
|
||||
nfetch = nmax;
|
||||
if (nmax > tr->buf_size) {
|
||||
nmax = tr->buf_size;
|
||||
/*printc_err("mehfet transport: bug: asking for more data (%d) than "
|
||||
"in the device buffer size (%d)\n", nmax, tr->buf_size);
|
||||
return -1;*/
|
||||
}
|
||||
|
||||
int r = xport->ops->recv(xport, rawbuf, nfetch);
|
||||
if (r < 0) return r;
|
||||
if (r < 1) {
|
||||
printc_err("mehfet transport: no status byte received\n");
|
||||
return -1;
|
||||
}
|
||||
assert(r <= nfetch);
|
||||
|
||||
uint8_t statv = rawbuf[0];
|
||||
|
||||
uint32_t reallen = 0;
|
||||
uint8_t lastbyte = statv;
|
||||
int i;
|
||||
for (i = 0; i < 4 && (lastbyte & 0x80) /*&& i + 1 < r*/; ++i) {
|
||||
if (r < i + 2) {
|
||||
printc_err("mehfet transport: not enough lenght bytes received (%d)\n", r);
|
||||
return -1;
|
||||
}
|
||||
|
||||
lastbyte = rawbuf[i + 1];
|
||||
|
||||
uint8_t mask = (i == 3) ? 0xff : 0x7f;
|
||||
reallen |= (lastbyte & mask) << (i * 7);
|
||||
}
|
||||
|
||||
if ((int)reallen > nmax && data) {
|
||||
printc_err("mehfet transport: too much data returned (%d vs %d)\n",
|
||||
(int)reallen, nmax);
|
||||
return -1;
|
||||
}
|
||||
|
||||
int nrecvdata = r - 1 - i;
|
||||
assert(nrecvdata >= 0);
|
||||
|
||||
if (nrecvdata && data) memcpy(data, &rawbuf[i+1], nrecvdata);
|
||||
// now we can use rawbuf for other purposes
|
||||
|
||||
int off = r;
|
||||
int ntodo = (int)reallen - nrecvdata;
|
||||
while (ntodo > 0) { // more data bytes following in this logical packet
|
||||
int thisblock = tr->buf_size;
|
||||
if (thisblock > ntodo) thisblock = ntodo;
|
||||
|
||||
r = xport->ops->recv(xport, rawbuf, thisblock);
|
||||
if (r < 0) return r;
|
||||
assert(r < thisblock);
|
||||
|
||||
memcpy(&((char*)data)[off], rawbuf, thisblock);
|
||||
ntodo -= r;
|
||||
off += r;
|
||||
}
|
||||
|
||||
if (stat) *stat = statv & 0x7f;
|
||||
if (datalen) *datalen = (int)reallen;
|
||||
|
||||
return (int)reallen;
|
||||
}
|
||||
|
||||
int mehfet_err_on_stat(const char* pre, uint8_t stat, int datalen, const void* data) {
|
||||
if (stat == mehfet_ok) return 0;
|
||||
|
||||
const char* d = (const char*)data;
|
||||
switch (stat) {
|
||||
case mehfet_badargs:
|
||||
printc_err("mehfet: %s: %s\n", pre,
|
||||
datalen ? d : "bad argument sent to command");
|
||||
break;
|
||||
case mehfet_nocaps:
|
||||
printc_err("mehfet: %s: %s\n", pre,
|
||||
datalen ? d : "device doesn't have the command capability");
|
||||
break;
|
||||
case mehfet_badstate:
|
||||
printc_err("mehfet: %s: %s\n", pre,
|
||||
datalen ? d : "device in wrong state to execute command");
|
||||
break;
|
||||
case mehfet_invalidcmd:
|
||||
printc_err("mehfet: %s: %s\n", pre,
|
||||
datalen ? d : "invalid command");
|
||||
break;
|
||||
case mehfet_error:
|
||||
printc_err("mehfet: %s: %s\n", pre, datalen ? d : "unspecified error");
|
||||
break;
|
||||
default:
|
||||
printc_err("mehfet: %s: unknown error %hhu\n", pre, stat);
|
||||
break;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
|
@ -1,52 +0,0 @@
|
|||
/* MSPDebug - debugging tool for MSP430 MCUs
|
||||
* Copyright (C) 2021 sys64738@disroot.org
|
||||
*
|
||||
* 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef MEHFET_TRANSPORT_H_
|
||||
#define MEHFET_TRANSPORT_H_
|
||||
|
||||
#include "transport.h"
|
||||
|
||||
enum mehfet_status {
|
||||
mehfet_ok = 0x00,
|
||||
|
||||
mehfet_badargs = 0x7b,
|
||||
mehfet_nocaps = 0x7c,
|
||||
mehfet_badstate = 0x7d,
|
||||
mehfet_invalidcmd = 0x7e,
|
||||
mehfet_error = 0x7f
|
||||
};
|
||||
|
||||
|
||||
/* Search the USB bus for the first MehFET device and initialize it.
|
||||
* If successful, return a transport object. Otherwise, return NULL.
|
||||
*
|
||||
* A particular USB device or serial number may be specified.
|
||||
*/
|
||||
transport_t mehfet_transport_open(const char *usb_device,
|
||||
const uint16_t* vendor, const uint16_t* product,
|
||||
const char *requested_serial);
|
||||
|
||||
int mehfet_transport_get_buf_size(transport_t xport);
|
||||
void mehfet_transport_set_buf_size(transport_t xport, int buf_size);
|
||||
|
||||
int mehfet_send_raw(transport_t xport, uint8_t cmd, int datalen, const void* data);
|
||||
int mehfet_recv_raw(transport_t xport, uint8_t* stat, int* datalen, void* data);
|
||||
|
||||
int mehfet_err_on_stat(const char* pre, uint8_t stat, int datalen, const void* data);
|
||||
|
||||
#endif
|
|
@ -228,8 +228,7 @@ static const struct transport_class rf2500_transport = {
|
|||
.set_modem = usbtr_set_modem
|
||||
};
|
||||
|
||||
transport_t rf2500_open(const char *devpath, const char *requested_serial,
|
||||
int has_vid_pid, uint16_t vid, uint16_t pid)
|
||||
transport_t rf2500_open(const char *devpath, const char *requested_serial)
|
||||
{
|
||||
struct rf2500_transport *tr = malloc(sizeof(*tr));
|
||||
struct usb_device *dev;
|
||||
|
@ -249,9 +248,8 @@ transport_t rf2500_open(const char *devpath, const char *requested_serial,
|
|||
if (devpath)
|
||||
dev = usbutil_find_by_loc(devpath);
|
||||
else
|
||||
dev = usbutil_find_by_id(has_vid_pid ? vid : USB_FET_VENDOR,
|
||||
has_vid_pid ? pid : USB_FET_PRODUCT,
|
||||
requested_serial);
|
||||
dev = usbutil_find_by_id(USB_FET_VENDOR, USB_FET_PRODUCT,
|
||||
requested_serial);
|
||||
|
||||
if (!dev) {
|
||||
free(tr);
|
||||
|
|
|
@ -27,9 +27,7 @@
|
|||
*
|
||||
* A particular device may be specified in bus:dev form.
|
||||
*/
|
||||
transport_t rf2500_open(const char *dev_path, const char *requested_serial,
|
||||
int has_vid_pid, uint16_t vid, uint16_t pid);
|
||||
transport_t rf2500hidapi_open(const char *dev_path, const char *requested_serial,
|
||||
int has_vid_pid, uint16_t vid, uint16_t pid);
|
||||
transport_t rf2500_open(const char *dev_path, const char *requested_serial);
|
||||
transport_t rf2500hidapi_open(const char *dev_path, const char *requested_serial);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -161,8 +161,7 @@ static const wchar_t * get_wc(const char *c)
|
|||
return wc;
|
||||
}
|
||||
|
||||
transport_t rf2500hidapi_open(const char *devpath, const char *requested_serial,
|
||||
int has_vid_pid, uint16_t vid, uint16_t pid)
|
||||
transport_t rf2500hidapi_open(const char *devpath, const char *requested_serial)
|
||||
{
|
||||
struct rf2500_transport *tr = malloc(sizeof(*tr));
|
||||
hid_device *handle;
|
||||
|
@ -187,9 +186,7 @@ transport_t rf2500hidapi_open(const char *devpath, const char *requested_serial,
|
|||
} else {
|
||||
wc_serial = NULL;
|
||||
}
|
||||
handle = hid_open(has_vid_pid ? vid : USB_FET_VENDOR,
|
||||
has_vid_pid ? pid : USB_FET_PRODUCT, wc_serial);
|
||||
|
||||
handle = hid_open(USB_FET_VENDOR, USB_FET_PRODUCT, wc_serial);
|
||||
if ( wc_serial ) {
|
||||
free((wchar_t *)wc_serial);
|
||||
}
|
||||
|
@ -200,7 +197,7 @@ transport_t rf2500hidapi_open(const char *devpath, const char *requested_serial,
|
|||
free(tr);
|
||||
hid_exit();
|
||||
printc_err("rf2500: fallback to libusb backend\n");
|
||||
return rf2500_open(devpath, requested_serial, has_vid_pid, vid, pid);
|
||||
return rf2500_open(devpath, requested_serial);
|
||||
}
|
||||
|
||||
tr->handle = handle;
|
||||
|
|
|
@ -559,8 +559,7 @@ static const struct transport_class ti3410_transport = {
|
|||
.set_modem = ti3410_set_modem
|
||||
};
|
||||
|
||||
transport_t ti3410_open(const char *devpath, const char *requested_serial,
|
||||
int has_vid_pid, uint16_t vid, uint16_t pid)
|
||||
transport_t ti3410_open(const char *devpath, const char *requested_serial)
|
||||
{
|
||||
struct ti3410_transport *tr = malloc(sizeof(*tr));
|
||||
struct usb_device *dev;
|
||||
|
@ -579,9 +578,8 @@ transport_t ti3410_open(const char *devpath, const char *requested_serial,
|
|||
if (devpath)
|
||||
dev = usbutil_find_by_loc(devpath);
|
||||
else
|
||||
dev = usbutil_find_by_id(has_vid_pid ? vid : USB_FET_VENDOR,
|
||||
has_vid_pid ? pid : USB_FET_PRODUCT,
|
||||
requested_serial);
|
||||
dev = usbutil_find_by_id(USB_FET_VENDOR, USB_FET_PRODUCT,
|
||||
requested_serial);
|
||||
|
||||
if (!dev) {
|
||||
free(tr);
|
||||
|
|
|
@ -24,8 +24,6 @@
|
|||
/* This function is for opening an eZ430-F2013 or FET430UIF device via
|
||||
* libusb.
|
||||
*/
|
||||
transport_t ti3410_open(const char *dev_path, const char *requested_serial,
|
||||
int has_vid_pid, uint16_t vid, uint16_t pid);
|
||||
|
||||
transport_t ti3410_open(const char *dev_path, const char *requested_serial);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -190,12 +190,11 @@ const struct cmddb_record commands[] = {
|
|||
.func = cmd_erase,
|
||||
.help =
|
||||
"erase [all|segment] [address]\n"
|
||||
"erase segrange <address> <total-size> <seg-size>\n"
|
||||
"erase segrange <address> <size> <seg-size>\n"
|
||||
" Erase the device under test. With no arguments, erases all of main\n"
|
||||
" memory. Specify arguments to perform a mass erase, or to erase\n"
|
||||
" individual segments. The \"segrange\" mode is used to erase an\n"
|
||||
" address range via a series of segment erases, 'total-size' being"
|
||||
" a multiple of 'seg-size'.\n"
|
||||
" address range via a series of segment erases.\n"
|
||||
},
|
||||
{
|
||||
.name = "step",
|
||||
|
|
|
@ -207,12 +207,6 @@ int cmd_erase(char **arg)
|
|||
"0x%x\n", segment_size);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (total_size % segment_size != 0) {
|
||||
printc_err("erase: total size must be a multiple of the "
|
||||
"segment size!\n");
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
printc_err("erase: unknown erase type: %s\n",
|
||||
type_text);
|
||||
|
|
21
ui/main.c
21
ui/main.c
|
@ -58,7 +58,6 @@
|
|||
#include "fet3.h"
|
||||
#include "rom_bsl.h"
|
||||
#include "chipinfo.h"
|
||||
#include "mehfet.h"
|
||||
|
||||
#ifdef __CYGWIN__
|
||||
#include <sys/cygwin.h>
|
||||
|
@ -93,8 +92,7 @@ static const struct device_class *const driver_table[] = {
|
|||
&device_loadbsl,
|
||||
&device_ezfet,
|
||||
&device_rom_bsl,
|
||||
&device_bp,
|
||||
&device_mehfet
|
||||
&device_bp
|
||||
};
|
||||
|
||||
static const char *version_text =
|
||||
|
@ -116,9 +114,6 @@ static void usage(const char *progname)
|
|||
" Connect via the given tty device, rather than USB.\n"
|
||||
" -U bus:dev\n"
|
||||
" Specify a particular USB device to connect to.\n"
|
||||
" -V vid:pid\n"
|
||||
" Specify a particular vid:pid par of a USB to connect to, instead of\n"
|
||||
" a driver-specific default.\n"
|
||||
" -s serial\n"
|
||||
" Specify a particular device serial number to connect to.\n"
|
||||
" -j\n"
|
||||
|
@ -333,7 +328,7 @@ static int parse_cmdline_args(int argc, char **argv,
|
|||
int opt;
|
||||
int want_usb = 0;
|
||||
|
||||
while ((opt = getopt_long(argc, argv, "d:jv:nUV:s:qC:",
|
||||
while ((opt = getopt_long(argc, argv, "d:jv:nU:s:qC:",
|
||||
longopts, NULL)) >= 0)
|
||||
switch (opt) {
|
||||
case 'C':
|
||||
|
@ -403,18 +398,6 @@ static int parse_cmdline_args(int argc, char **argv,
|
|||
want_usb = 1;
|
||||
break;
|
||||
|
||||
case 'V':
|
||||
/* optarg is in "vid:pid" format, which we now need to parse */
|
||||
if (sscanf(optarg, "%04hx:%04hx", &args->devarg.vid, &args->devarg.pid) == 2) {
|
||||
args->devarg.flags |= DEVICE_FLAG_HAS_VID_PID;
|
||||
want_usb = 1;
|
||||
} else {
|
||||
printc("Invalid -V option specified: %s."
|
||||
"Format should be '<vid>:<pid>'\n", optarg);
|
||||
exit(1);
|
||||
}
|
||||
break;
|
||||
|
||||
case 's':
|
||||
args->devarg.requested_serial = optarg;
|
||||
break;
|
||||
|
|
|
@ -54,7 +54,7 @@ static int addr_exp_data(struct addr_exp_state *s, const char *text)
|
|||
}
|
||||
|
||||
/* Hex value */
|
||||
if (*text == '0' && (text[1] == 'x' || text[1] == 'X')) {
|
||||
if (*text == '0' && text[1] == 'x') {
|
||||
value = strtoul(text + 2, NULL, 16);
|
||||
} else if (*text == '0' && text[1] == 'd') {
|
||||
value = atoi(text + 2);
|
||||
|
|
Loading…
Reference in New Issue