forked from auracaster/openocd
Compare commits
195 Commits
v0.4.0-rc1
...
v0.4.0-rc2
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a0a1be5cd6 | ||
|
|
f7a6e62776 | ||
|
|
747a607aef | ||
|
|
d4d4b11a77 | ||
|
|
ff404da155 | ||
|
|
32188c5004 | ||
|
|
527e073bba | ||
|
|
65cc81ddb6 | ||
|
|
84ac6bb0d9 | ||
|
|
c646b76797 | ||
|
|
f899c2aa97 | ||
|
|
885a2f5b96 | ||
|
|
6f262b69f4 | ||
|
|
41d0901115 | ||
|
|
ff5deeeeaa | ||
|
|
3ea9e62189 | ||
|
|
e380930478 | ||
|
|
709f08f17a | ||
|
|
8b049fdba5 | ||
|
|
95ed9c4393 | ||
|
|
18969466c9 | ||
|
|
5750e899e0 | ||
|
|
cc440ca1d4 | ||
|
|
503f6139c7 | ||
|
|
3d2d5dcc9c | ||
|
|
bef37ceba2 | ||
|
|
91e3268737 | ||
|
|
82f2492138 | ||
|
|
02731cf78b | ||
|
|
f68dff6690 | ||
|
|
e11ce3e6b0 | ||
|
|
695666d294 | ||
|
|
46b6d5bfe6 | ||
|
|
3d3128a8f5 | ||
|
|
2248c387f2 | ||
|
|
303b493c22 | ||
|
|
cd3017cffa | ||
|
|
804c0b2ad3 | ||
|
|
5dcf7898f6 | ||
|
|
75cfda4cd1 | ||
|
|
465a06dfdc | ||
|
|
3172be80a3 | ||
|
|
d44f1aaeff | ||
|
|
2b5c444a32 | ||
|
|
30365886da | ||
|
|
9e52957efc | ||
|
|
33fc60befc | ||
|
|
1dad2ee602 | ||
|
|
9ff16575d2 | ||
|
|
718ee762e7 | ||
|
|
82c3c47825 | ||
|
|
b7fa16eeac | ||
|
|
4960c9018f | ||
|
|
08b0be94b5 | ||
|
|
f06148612b | ||
|
|
98f7c2127b | ||
|
|
dfba7fa949 | ||
|
|
bc088b302b | ||
|
|
1350b6aad0 | ||
|
|
60cb5bdd30 | ||
|
|
dbecb13b24 | ||
|
|
2a0c9b08d7 | ||
|
|
22d25e6921 | ||
|
|
6f2b88448f | ||
|
|
d036f17001 | ||
|
|
87cb29dcfe | ||
|
|
ff976cdb29 | ||
|
|
0c3a4b4d81 | ||
|
|
20d1ef70e8 | ||
|
|
44aaba3d08 | ||
|
|
bf1e9a83c8 | ||
|
|
4f310aa0c9 | ||
|
|
fb4239866c | ||
|
|
924bf27596 | ||
|
|
c795b0d8f1 | ||
|
|
cdcb9b0885 | ||
|
|
5ab34b28ce | ||
|
|
56d2c86500 | ||
|
|
0b641dac71 | ||
|
|
daa1ff3535 | ||
|
|
183765707f | ||
|
|
6c4a643d63 | ||
|
|
187ccb60ee | ||
|
|
0f7cea2847 | ||
|
|
8e1b5c3138 | ||
|
|
1d140c4dcd | ||
|
|
000a1cfd01 | ||
|
|
24653c950a | ||
|
|
e1679a29f0 | ||
|
|
e2d3266ff1 | ||
|
|
b60dd35e33 | ||
|
|
73566405b6 | ||
|
|
d91941d5a0 | ||
|
|
b8e930e3bf | ||
|
|
ee519ab356 | ||
|
|
dc793455e9 | ||
|
|
3e33393078 | ||
|
|
6c75f5249c | ||
|
|
b4a4d5c731 | ||
|
|
1de107a5a2 | ||
|
|
e5349bfb49 | ||
|
|
fb71a0a0dd | ||
|
|
6d8604de37 | ||
|
|
c74ca40e09 | ||
|
|
8c730aaee2 | ||
|
|
88907cc7f9 | ||
|
|
d746dee833 | ||
|
|
c8267930c7 | ||
|
|
5e221fa3a7 | ||
|
|
ab4307e693 | ||
|
|
5cb1dcfad3 | ||
|
|
0811f6b192 | ||
|
|
ad5fd39063 | ||
|
|
ff647e6bb4 | ||
|
|
1dd5277ba3 | ||
|
|
1c5c57ec8e | ||
|
|
70738bd75d | ||
|
|
fc9a2d0e6f | ||
|
|
aafd3877e6 | ||
|
|
973cd9a299 | ||
|
|
2a76c1bcf9 | ||
|
|
ae71005929 | ||
|
|
b800eb0336 | ||
|
|
1a2c258ed4 | ||
|
|
c1cb20971e | ||
|
|
296a011db5 | ||
|
|
12c143d594 | ||
|
|
82c0fb5277 | ||
|
|
e7965cd3eb | ||
|
|
a42bea654c | ||
|
|
e0b6e5deef | ||
|
|
199abf49ea | ||
|
|
48d51e1719 | ||
|
|
17921f51ab | ||
|
|
e19fe9ad09 | ||
|
|
dd8f679aa2 | ||
|
|
7c3aee96b2 | ||
|
|
991d030fcc | ||
|
|
c68c2751f3 | ||
|
|
2d450b9033 | ||
|
|
2bc7446bb8 | ||
|
|
844b5eb49d | ||
|
|
fccb812f82 | ||
|
|
adf2a9a267 | ||
|
|
9d83df72dc | ||
|
|
ba96fc3e9d | ||
|
|
f6412d9c7b | ||
|
|
faad9e5923 | ||
|
|
03e8649bc6 | ||
|
|
95f86e8e05 | ||
|
|
6d4abe906f | ||
|
|
1b3f15d51e | ||
|
|
237a707f96 | ||
|
|
e1258c703b | ||
|
|
50fb3a5129 | ||
|
|
4aedb02fcd | ||
|
|
e0338293b8 | ||
|
|
d9508b30e0 | ||
|
|
4ed5b45097 | ||
|
|
858226aae2 | ||
|
|
6105f2bc4a | ||
|
|
e60c164cdb | ||
|
|
ec88ccc51c | ||
|
|
b3bf1d12b2 | ||
|
|
9d167d62f2 | ||
|
|
be01786186 | ||
|
|
668f20d0ab | ||
|
|
384e9193e9 | ||
|
|
7cef6d650c | ||
|
|
3ed254c18a | ||
|
|
7c5acf8660 | ||
|
|
17fb7ead4b | ||
|
|
c116d8f6bc | ||
|
|
20354a66b9 | ||
|
|
2cf6d47375 | ||
|
|
272c33c190 | ||
|
|
bd3700e89d | ||
|
|
12618e4c6d | ||
|
|
d4bef466c3 | ||
|
|
aa81462618 | ||
|
|
6b1eeb92fe | ||
|
|
37cc6c495f | ||
|
|
ec297e4bf1 | ||
|
|
cba1813d5c | ||
|
|
3ace333663 | ||
|
|
155a6a2c0b | ||
|
|
84dbf8ab5a | ||
|
|
900d745567 | ||
|
|
3a84436afb | ||
|
|
e7f81c11c9 | ||
|
|
df58812b52 | ||
|
|
396b0f3012 | ||
|
|
08a890e4aa | ||
|
|
f9d203d1e6 | ||
|
|
4e2b15fc93 |
6
.gitignore
vendored
6
.gitignore
vendored
@@ -66,6 +66,10 @@ stamp-vti
|
||||
INSTALL
|
||||
NOTES
|
||||
|
||||
# coexist with quilt
|
||||
patches
|
||||
|
||||
# Eclipse stuff
|
||||
.project
|
||||
|
||||
.cproject
|
||||
.settings
|
||||
|
||||
14
BUGS
14
BUGS
@@ -6,6 +6,12 @@ posting a message with your report:
|
||||
|
||||
openocd-development@lists.berlios.de
|
||||
|
||||
Also, please check the Trac bug database to see if a ticket for
|
||||
the bug has already been opened. You might be asked to open
|
||||
such a ticket, or to update an existing ticket with more data.
|
||||
|
||||
https://sourceforge.net/apps/trac/openocd/
|
||||
|
||||
To minimize work for OpenOCD developers, you should try to include
|
||||
all of the information listed below. If you feel that some of the
|
||||
items below are unnecessary for a clear bug report, you may leave
|
||||
@@ -22,12 +28,12 @@ that may be important.
|
||||
- If the report is for a regression:
|
||||
- Include logs for both working and broken versions.
|
||||
- Find the precise version that caused the regression by binary search.
|
||||
You can use "git bisect" to expedite this binary search:
|
||||
You can use "git bisect" to expedite this binary search:
|
||||
http://www.kernel.org/pub/software/scm/git/docs/git-bisect.html
|
||||
|
||||
If possible, please develop and attach a patch that helps to expose or
|
||||
solve the reported problem. See the PATCHES file for more information
|
||||
for that process.
|
||||
solve the reported problem. See the PATCHES.txt file for information
|
||||
about that process.
|
||||
|
||||
Attach all files directly to your posting. The mailing list knows to
|
||||
transform attachments to links, but attachments must be less than 300KB
|
||||
@@ -36,7 +42,7 @@ in total.
|
||||
@section bugscrashdump Obtaining Crash Backtraces
|
||||
|
||||
If OpenOCD is crashing, there are two very effective things you can do to
|
||||
improve your chances of getting help on the development mailing list.
|
||||
improve your chances of getting help on the development mailing list.
|
||||
|
||||
Try to reproduce the problem using the dummy JTAG interface to allow other developers to replicate
|
||||
your problem robustly and use GDB to get a trace:@par
|
||||
|
||||
12
Doxyfile.in
12
Doxyfile.in
@@ -384,7 +384,7 @@ HIDE_SCOPE_NAMES = NO
|
||||
# will put a list of the files that are included by a file in the documentation
|
||||
# of that file.
|
||||
|
||||
SHOW_INCLUDE_FILES = YES
|
||||
SHOW_INCLUDE_FILES = NO
|
||||
|
||||
# If the INLINE_INFO tag is set to YES (the default) then a tag [inline]
|
||||
# is inserted in the documentation for inline members.
|
||||
@@ -403,7 +403,7 @@ SORT_MEMBER_DOCS = YES
|
||||
# by member name. If set to NO (the default) the members will appear in
|
||||
# declaration order.
|
||||
|
||||
SORT_BRIEF_DOCS = NO
|
||||
SORT_BRIEF_DOCS = YES
|
||||
|
||||
# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the
|
||||
# hierarchy of group names into alphabetical order. If set to NO (the default)
|
||||
@@ -567,9 +567,9 @@ WARN_LOGFILE =
|
||||
INPUT = @srcdir@/doc/manual \
|
||||
@srcdir@/TODO \
|
||||
@srcdir@/BUGS \
|
||||
@srcdir@/PATCHES \
|
||||
@srcdir@/PATCHES.txt \
|
||||
@srcdir@/src \
|
||||
@srcdir@/config.h
|
||||
@builddir@/config.h
|
||||
|
||||
# This tag can be used to specify the character encoding of the source files
|
||||
# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is
|
||||
@@ -692,13 +692,13 @@ SOURCE_BROWSER = YES
|
||||
# Setting the INLINE_SOURCES tag to YES will include the body
|
||||
# of functions and classes directly in the documentation.
|
||||
|
||||
INLINE_SOURCES = YES
|
||||
INLINE_SOURCES = NO
|
||||
|
||||
# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct
|
||||
# doxygen to hide any special comment blocks from generated source code
|
||||
# fragments. Normal C and C++ comments will always remain visible.
|
||||
|
||||
STRIP_CODE_COMMENTS = NO
|
||||
STRIP_CODE_COMMENTS = YES
|
||||
|
||||
# If the REFERENCED_BY_RELATION tag is set to YES
|
||||
# then for each documented function all documented
|
||||
|
||||
@@ -26,6 +26,7 @@ Doxyfile: $(srcdir)/Doxyfile.in
|
||||
echo "### @@@ -= DO NOT EDIT THIS FILE =- @@@ ###" && \
|
||||
echo "### @@@ Make changes to Doxyfile.in @@@ ###" && \
|
||||
sed -e 's,@srcdir\@,$(srcdir),' \
|
||||
-e 's,@builddir\@,$(builddir),' \
|
||||
-e 's,@doxygen_as_html\@,$(doxygen_as_html),' \
|
||||
-e 's,@doxygen_as_pdf\@,$(doxygen_as_pdf),' $< \
|
||||
) > $@
|
||||
|
||||
42
NEWS
42
NEWS
@@ -5,36 +5,46 @@ and other issues not mentioned here.
|
||||
|
||||
JTAG Layer:
|
||||
Support KT-Link JTAG adapter.
|
||||
Support USB-JTAG, Altera USB-Blaster and compatibles.
|
||||
|
||||
Boundary Scan:
|
||||
|
||||
Target Layer:
|
||||
General
|
||||
- new "reset-assert" event, for systems without SRST
|
||||
ARM
|
||||
- supports "reset-assert" event (except on Cortex-M3)
|
||||
- renamed "armv4_5" command prefix as "arm"
|
||||
- recognize TrustZone "Secure Monitor" mode
|
||||
- "arm regs" command output changed
|
||||
- register names use "sp" not "r13"
|
||||
- add top-level "mcr" and "mrc" commands, replacing
|
||||
various core-specific operations
|
||||
- basic semihosting support
|
||||
- basic semihosting support (ARM7/ARM9 only, for now)
|
||||
ARM11
|
||||
- Preliminary ETM and ETB hookup
|
||||
- accelerated "flash erase_check"
|
||||
- accelerated GDB memory checksum
|
||||
- support "arm regs" command
|
||||
- can access all core modes and registers
|
||||
- watchpoint support
|
||||
- Should act much more like other ARM cores:
|
||||
* Preliminary ETM and ETB hookup
|
||||
* accelerated "flash erase_check"
|
||||
* accelerated GDB memory checksum
|
||||
* support "arm regs" command
|
||||
* can access all core modes and registers
|
||||
* watchpoint support
|
||||
- Shares some core debug code with Cortex-A8
|
||||
Cortex-A8
|
||||
- support "arm regs" command
|
||||
- can access all core modes and registers
|
||||
- supports "reset-assert" event (used on OMAP3530)
|
||||
- watchpoint support
|
||||
- Should act much more like other ARM cores:
|
||||
* support "arm regs" command
|
||||
* can access all core modes and registers
|
||||
* watchpoint support
|
||||
- Shares some core debug code with ARM11
|
||||
Cortex-M3
|
||||
- Exposed DWT registers like cycle counter
|
||||
- vector_catch settings not clobbered by resets
|
||||
- no longer interferes with firmware's fault handling
|
||||
ETM, ETB
|
||||
- "trigger_percent" command moved ETM --> ETB
|
||||
- "etm trigger_debug" command added
|
||||
MIPS
|
||||
- use fastdata writes
|
||||
Freescale DSP563xx cores (partial support)
|
||||
|
||||
Flash Layer:
|
||||
@@ -44,13 +54,19 @@ Flash Layer:
|
||||
- <driver_name>[.N]: reference the driver's Nth bank
|
||||
New 'nand verify' command to check bank against an image file.
|
||||
The "flash erase_address" command now rejects partial sectors;
|
||||
previously it would silently erase extra data.
|
||||
previously it would silently erase extra data. If you
|
||||
want to erase the rest of the first and/or last sectors
|
||||
instead of failing, you must pass an explicit "pad" flag.
|
||||
New at91sam9 NAND controller driver.
|
||||
New s3c64xx NAND controller driver.
|
||||
|
||||
Board, Target, and Interface Configuration Scripts:
|
||||
ARM9
|
||||
- ETM and ETB hookup for iMX2* targets
|
||||
Add $HOME/.openocd to the search path.
|
||||
Handle Rev C of LM3S811 eval boards.
|
||||
- use "luminary-lm3s811.cfg" for older boards
|
||||
- use "luminary.cfg" for RevC and newer
|
||||
|
||||
Core Jim/TCL Scripting:
|
||||
New 'usage' command to provide terse command help.
|
||||
@@ -77,4 +93,4 @@ For older NEWS, see the NEWS files associated with each release
|
||||
|
||||
For more information about contributing test reports, bug fixes, or new
|
||||
features and device support, please read the new Developer Manual (or
|
||||
the BUGS and PATCHES files in the source archive).
|
||||
the BUGS and PATCHES.txt files in the source archive).
|
||||
|
||||
@@ -9,7 +9,7 @@ must past stricter value checks, and many more error conditions have
|
||||
been handled correctly. These efforts helped to make the 0.2.0 release
|
||||
more stable and robust, though some changes may expose latent bugs in
|
||||
your existing configuration scripts.
|
||||
|
||||
|
||||
This release does not maintain backward compatibility in all respects,
|
||||
so some target or configuration scripts may need to be updated. In some
|
||||
cases, you may also see warnings; resolve those, because they indicate
|
||||
@@ -20,7 +20,7 @@ The following areas of OpenOCD functionality changed in this release:
|
||||
JTAG Layer:
|
||||
- Improves modularity: core, TCL, driver commands, and interface have
|
||||
been separated, encapsulated, and documented for developers. Mostly.
|
||||
- Improves JTAG TAP transition tables:
|
||||
- Improves JTAG TAP transition tables:
|
||||
* Makes TAP paths variable length, rather than being fixed at 7 steps.
|
||||
* Fixes problems with some targets that did not like longer paths.
|
||||
- Improves JTAG driver/minidriver modularity and encapsulation.
|
||||
|
||||
12
NEWTAPS
12
NEWTAPS
@@ -30,7 +30,7 @@ Version Number Changes:
|
||||
not a big deal. Please do report this information. We'd like to
|
||||
know about it.
|
||||
|
||||
For example
|
||||
For example
|
||||
|
||||
Error: ERROR: Tap: s3c4510.cpu - Expected id: 0x3f0f0f0f, Got: 0x1f0f0f0f
|
||||
Error: ERROR: expected: mfg: 0x787, part: 0xf0f0, ver: 0x3
|
||||
@@ -39,7 +39,7 @@ Error: ERROR: got: mfg: 0x787, part: 0xf0f0, ver: 0x1
|
||||
========================================
|
||||
|
||||
Updating the Tap ID number your self
|
||||
|
||||
|
||||
Why do this? You just want the warning to go away. And don't want
|
||||
to update your version/instance of OpenOCD.
|
||||
|
||||
@@ -79,11 +79,11 @@ Examples:
|
||||
0x3f0f0f0f - is a newer ARM7TDMI
|
||||
0x3ba00477 - is an ARM cortex M3
|
||||
|
||||
Some chips have multiple JTAG taps - be sure to list
|
||||
Some chips have multiple JTAG taps - be sure to list
|
||||
each one individually - ORDER is important!
|
||||
|
||||
========================================
|
||||
B) The maker of the part
|
||||
B) The maker of the part
|
||||
|
||||
Examples:
|
||||
Xilinx, Atmel, ST Micro Systems, Freescale
|
||||
@@ -94,7 +94,7 @@ C) The family of parts it belongs to
|
||||
Examples:
|
||||
"NXP LPC Series"
|
||||
"Atmel SAM7 Series"
|
||||
|
||||
|
||||
========================================
|
||||
|
||||
D) The actual part number on the package
|
||||
@@ -121,7 +121,7 @@ For example: A consumer GPS unit or a cellphone
|
||||
ie: Olimex, LogicPD, Freescale(eval board)
|
||||
|
||||
========================================
|
||||
|
||||
|
||||
(G) Identifying information on the board.
|
||||
|
||||
Not good: "iar red ST eval board"
|
||||
|
||||
@@ -32,7 +32,7 @@ in response to feedback.
|
||||
Add yourself to the GPL copyright for non-trivial changes.
|
||||
|
||||
To create a patch from the command line:
|
||||
@code
|
||||
@code
|
||||
git diff >mypatch.txt
|
||||
@endcode
|
||||
|
||||
@@ -27,8 +27,8 @@ based JTAG debuggers.
|
||||
|
||||
http://sourceforge.net/projects/libusb-win32/
|
||||
|
||||
You need to download the libusb-win32-device-bin-0.1.12.2.tar.gz
|
||||
package. Extract this file into a temp directory.
|
||||
You need to download the libusb-win32-device-bin-0.1.12.2.tar.gz
|
||||
package. Extract this file into a temp directory.
|
||||
|
||||
Copy the file libusb-win32-device-bin-0.1.12.2\include\usb.h
|
||||
to your MinGW include directory.
|
||||
@@ -59,10 +59,10 @@ released source tarball or the git tree.
|
||||
If you are using the git tree, the following are the instructions from
|
||||
README.mingw. You will need to have the cmake utility installed.
|
||||
|
||||
- Edit Toolchain-mingw32.cmake to point to the correct MinGW
|
||||
- Edit Toolchain-mingw32.cmake to point to the correct MinGW
|
||||
installation.
|
||||
- Create a build directory like "mkdir build-win32", e.g in ../libftdi/
|
||||
- cd into that directory and run
|
||||
- cd into that directory and run
|
||||
"cmake -DCMAKE_TOOLCHAIN_FILE=../Toolchain-mingw32.cmake .."
|
||||
- Copy src/ftdi.h to your MinGW include directory.
|
||||
- Copy build-win32/src/*.a to your MinGW lib directory.
|
||||
|
||||
42
TODO
42
TODO
@@ -27,8 +27,8 @@ This section provides possible things to improve with OpenOCD's TCL support.
|
||||
parameters. Currently variables assigned through one such parameter
|
||||
command/script are unset before the next one is invoked.
|
||||
|
||||
- Isolate all TCL command support:
|
||||
- Pure C CLI implementations using --disable-builtin-tcl.
|
||||
- Isolate all TCL command support:
|
||||
- Pure C CLI implementations using --disable-builtin-tcl.
|
||||
- Allow developers to build new dongles using OpenOCD's JTAG core.
|
||||
- At first, provide only low-level JTAG support; target layer and
|
||||
above rely heavily on scripting event mechanisms.
|
||||
@@ -112,7 +112,7 @@ TCP/IP packets handled by the server.
|
||||
|
||||
@section thelistswd Serial Wire Debug
|
||||
|
||||
- implement Serial Wire Debug interface
|
||||
- implement Serial Wire Debug interface
|
||||
|
||||
@section thelistbs Boundary Scan Support
|
||||
|
||||
@@ -142,6 +142,8 @@ Once the above are completed:
|
||||
https://lists.berlios.de/pipermail/openocd-development/2009-May/006590.html
|
||||
- regression: "reset halt" between 729(works) and 788(fails): @par
|
||||
https://lists.berlios.de/pipermail/openocd-development/2009-July/009206.html
|
||||
- registers
|
||||
- add flush-value operation, call them all on resume/reset
|
||||
- mcr/mrc target->type support
|
||||
- missing from ARM920t, ARM966e, XScale.
|
||||
It's possible that the current syntax is unable to support read-modify-write
|
||||
@@ -163,17 +165,25 @@ https://lists.berlios.de/pipermail/openocd-development/2009-October/011506.html
|
||||
use hardware stepping if available.
|
||||
- mdb can return garbage data if read byte operation fails for
|
||||
a memory region(16 & 32 byte access modes may be supported). Is this
|
||||
a bug in the .MX31 PDK init script? Try on i.MX31 PDK:
|
||||
a bug in the .MX31 PDK init script? Try on i.MX31 PDK:
|
||||
mdw 0xb80005f0 0x8, mdh 0xb80005f0 0x10, mdb 0xb80005f0 0x20. mdb returns
|
||||
garabage.
|
||||
- implement missing functionality (grep FNC_INFO_NOTIMPLEMENTED ...)
|
||||
- Thumb2 single stepping: ARM1156T2 needs simulator support
|
||||
- Cortex A8 support (ML)
|
||||
- add target implementation (ML)
|
||||
- Cortex M3 support
|
||||
- when stepping, only write dirtied registers (be faster)
|
||||
- when connecting to halted core, fetch registers (startup is quirky)
|
||||
- Generic ARM run_algorithm() interface
|
||||
- tagged struct wrapping ARM instructions and metadata
|
||||
- not revision-specific (current: ARMv4+ARMv5 -or- ARMv6 -or- ARMv7)
|
||||
- usable with at least arm_nandwrite() and generic CFI drivers
|
||||
- ETM
|
||||
- don't show FIFOFULL registers if they're not supported
|
||||
- use comparators to get more breakpoints and watchpoints
|
||||
- add "etm drivers" command
|
||||
- trace driver init() via examine() paths only, not setup()/reset
|
||||
- MC1322x support (JW/DE?)
|
||||
- integrate and test support from JW (and DE?)
|
||||
- get working with a known good interface (i.e. not today's jlink)
|
||||
@@ -197,8 +207,8 @@ https://lists.berlios.de/pipermail/openocd-development/2009-October/011506.html
|
||||
|
||||
@section thelistsvf SVF/XSVF
|
||||
|
||||
- develop SVF unit tests
|
||||
- develop XSVF unit tests
|
||||
- develop SVF unit tests
|
||||
- develop XSVF unit tests
|
||||
|
||||
@section thelistflash Flash Support
|
||||
|
||||
@@ -209,6 +219,16 @@ https://lists.berlios.de/pipermail/openocd-development/2009-October/011506.html
|
||||
- ocl
|
||||
- str9xpec
|
||||
|
||||
- Don't expect writing all-ones to be a safe way to write without
|
||||
changing bit values. Minimally it loses on flash modules with
|
||||
internal ECC, where it may change the ECC.
|
||||
- NOR flash_write_unlock() does that between sectors
|
||||
- there may be other cases too
|
||||
|
||||
- Make sure all commands accept either a bank name or a bank number,
|
||||
and be sure both identifiers show up in "flash banks" and "nand list".
|
||||
Right now the user-friendly names are pretty much hidden...
|
||||
|
||||
@subsection thelistflashcfi CFI
|
||||
|
||||
- finish implementing bus width/chip width handling (suggested by NC)
|
||||
@@ -328,7 +348,7 @@ at the bottom of the list below. Example, on amd64:
|
||||
from unaligned memory addresses
|
||||
- libopenocd support: @par
|
||||
https://lists.berlios.de/pipermail/openocd-development/2009-May/006405.html
|
||||
- review and clean up interface/target/flash APIs
|
||||
- review and clean up interface/target/flash APIs
|
||||
|
||||
The following strategic tasks will require ambition, knowledge, and time
|
||||
to complete:
|
||||
@@ -346,9 +366,11 @@ to complete:
|
||||
- Develop milestone and release guidelines, processes, and scripts.
|
||||
- Develop "style" guidelines (and scripts) for maintainers:
|
||||
- reviewing patches
|
||||
- committing to Subversion
|
||||
- Review The Guide for OpenOCD Users for documentation errors or omissions
|
||||
- Update The Manual for OpenOCD Developers:
|
||||
- committing to git
|
||||
- Review Users' Guide for documentation errors or omissions
|
||||
- "capture" and "ocd_find" commands
|
||||
- "ocd_" prefix on various stuff
|
||||
- Update Developer's Manual (doxygen output)
|
||||
- Add documentation describing the architecture of each module
|
||||
- Provide more Technical Primers to bootstrap contributor knowledge
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#!/bin/sh -e
|
||||
# Run the autotools bootstrap sequence to create the configure script
|
||||
|
||||
# Stop execution as soon as we have an unknown command
|
||||
# Stop execution as soon as we have an unknown command
|
||||
set -e
|
||||
|
||||
if libtoolize --version >/dev/null 2>&1; then
|
||||
|
||||
30
configure.in
30
configure.in
@@ -1,5 +1,5 @@
|
||||
AC_PREREQ(2.60)
|
||||
AC_INIT([openocd], [0.4.0-rc1],
|
||||
AC_INIT([openocd], [0.4.0-rc2],
|
||||
[OpenOCD Mailing List <openocd-development@lists.berlios.de>])
|
||||
AC_CONFIG_SRCDIR([src/openocd.c])
|
||||
|
||||
@@ -392,6 +392,14 @@ AC_ARG_ENABLE(ft2232_ftd2xx,
|
||||
AS_HELP_STRING([--enable-ft2232_ftd2xx], [Enable building support for FT2232 based devices using the FTD2XX driver from ftdichip.com]),
|
||||
[build_ft2232_ftd2xx=$enableval], [build_ft2232_ftd2xx=no])
|
||||
|
||||
AC_ARG_ENABLE(usb_blaster_libftdi,
|
||||
AS_HELP_STRING([--enable-usb_blaster_libftdi], [Enable building support for the Altera USB-Blaster using the libftdi driver, opensource alternate of FTD2XX]),
|
||||
[build_usb_blaster_libftdi=$enableval], [build_usb_blaster_libftdi=no])
|
||||
|
||||
AC_ARG_ENABLE(usb_blaster_ftd2xx,
|
||||
AS_HELP_STRING([--enable-usb_blaster_ftd2xx], [Enable building support for the Altera USB-Blaster using the FTD2XX driver from ftdichip.com]),
|
||||
[build_usb_blaster_ftd2xx=$enableval], [build_usb_blaster_ftd2xx=no])
|
||||
|
||||
AC_ARG_ENABLE(amtjtagaccel,
|
||||
AS_HELP_STRING([--enable-amtjtagaccel], [Enable building the Amontec JTAG-Accelerator driver]),
|
||||
[build_amtjtagaccel=$enableval], [build_amtjtagaccel=no])
|
||||
@@ -551,7 +559,7 @@ case $host in
|
||||
AC_MSG_WARN([--disable-parport-giveio is not supported by MinGW32 hosts])
|
||||
fi
|
||||
parport_use_giveio=yes
|
||||
|
||||
|
||||
CFLAGS="$CFLAGS -D__USE_MINGW_ANSI_STDIO"
|
||||
|
||||
AC_DEFINE(IS_MINGW, 1, [1 if building for MinGW.])
|
||||
@@ -651,6 +659,20 @@ else
|
||||
AC_DEFINE(BUILD_FT2232_FTD2XX, 0, [0 if you don't want ftd2xx ft2232.])
|
||||
fi
|
||||
|
||||
if test $build_usb_blaster_libftdi = yes; then
|
||||
build_bitbang=yes
|
||||
AC_DEFINE(BUILD_USB_BLASTER_LIBFTDI, 1, [1 if you want libftdi usb_blaster.])
|
||||
else
|
||||
AC_DEFINE(BUILD_USB_BLASTER_LIBFTDI, 0, [0 if you don't want libftdi usb_blaster.])
|
||||
fi
|
||||
|
||||
if test $build_usb_blaster_ftd2xx = yes; then
|
||||
build_bitbang=yes
|
||||
AC_DEFINE(BUILD_USB_BLASTER_FTD2XX, 1, [1 if you want ftd2xx usb_blaster.])
|
||||
else
|
||||
AC_DEFINE(BUILD_USB_BLASTER_FTD2XX, 0, [0 if you don't want ftd2xx usb_blaster.])
|
||||
fi
|
||||
|
||||
if test $build_amtjtagaccel = yes; then
|
||||
AC_DEFINE(BUILD_AMTJTAGACCEL, 1, [1 if you want the Amontec JTAG-Accelerator driver.])
|
||||
else
|
||||
@@ -727,7 +749,7 @@ then
|
||||
AC_MSG_ERROR([The option: with_ftd2xx_linux_tardir is for LINUX only.])
|
||||
fi
|
||||
|
||||
if test $build_ft2232_ftd2xx = yes -o $build_presto_ftd2xx = yes ; then
|
||||
if test $build_ft2232_ftd2xx = yes -o $build_presto_ftd2xx = yes -o $build_usb_blaster_ftd2xx = yes ; then
|
||||
AC_MSG_CHECKING([for ftd2xx.lib exists (win32)])
|
||||
|
||||
# if we are given a zipdir...
|
||||
@@ -1001,6 +1023,8 @@ AM_CONDITIONAL(AT91RM9200, test $build_at91rm9200 = yes)
|
||||
AM_CONDITIONAL(BITBANG, test $build_bitbang = yes)
|
||||
AM_CONDITIONAL(FT2232_LIBFTDI, test $build_ft2232_libftdi = yes)
|
||||
AM_CONDITIONAL(FT2232_DRIVER, test $build_ft2232_ftd2xx = yes -o $build_ft2232_libftdi = yes)
|
||||
AM_CONDITIONAL(USB_BLASTER_LIBFTDI, test $build_usb_blaster_libftdi = yes)
|
||||
AM_CONDITIONAL(USB_BLASTER_DRIVER, test $build_usb_blaster_ftd2xx = yes -o $build_usb_blaster_libftdi = yes)
|
||||
AM_CONDITIONAL(AMTJTAGACCEL, test $build_amtjtagaccel = yes)
|
||||
AM_CONDITIONAL(GW16012, test $build_gw16012 = yes)
|
||||
AM_CONDITIONAL(PRESTO_LIBFTDI, test $build_presto_libftdi = yes)
|
||||
|
||||
@@ -1,60 +1,68 @@
|
||||
BUS!="usb", ACTION!="add", SUBSYSTEM!=="usb_device", GOTO="openocd_rules_end"
|
||||
ACTION!="add|change", GOTO="openocd_rules_end"
|
||||
SUBSYSTEM!="usb", GOTO="openocd_rules_end"
|
||||
ENV{DEVTYPE}!="usb_device", GOTO="openocd_rules_end"
|
||||
|
||||
# Olimex ARM-USB-OCD
|
||||
SYSFS{idVendor}=="15ba", SYSFS{idProduct}=="0003", MODE="664", GROUP="plugdev"
|
||||
ATTRS{idVendor}=="15ba", ATTRS{idProduct}=="0003", MODE="664", GROUP="plugdev"
|
||||
|
||||
# Olimex ARM-USB-OCD-TINY
|
||||
SYSFS{idVendor}=="15ba", SYSFS{idProduct}=="0004", MODE="664", GROUP="plugdev"
|
||||
ATTRS{idVendor}=="15ba", ATTRS{idProduct}=="0004", MODE="664", GROUP="plugdev"
|
||||
|
||||
# Olimex ARM-JTAG-EW
|
||||
SYSFS{idVendor}=="15ba", SYSFS{idProduct}=="001e", MODE="664", GROUP="plugdev"
|
||||
ATTRS{idVendor}=="15ba", ATTRS{idProduct}=="001e", MODE="664", GROUP="plugdev"
|
||||
|
||||
# Olimex ARM-USB-OCD-TINY-H
|
||||
ATTRS{idVendor}=="15ba", ATTRS{idProduct}=="002a", MODE="664", GROUP="plugdev"
|
||||
|
||||
# USBprog with OpenOCD firmware
|
||||
SYSFS{idVendor}=="1781", SYSFS{idProduct}=="0c63", MODE="664", GROUP="plugdev"
|
||||
ATTRS{idVendor}=="1781", ATTRS{idProduct}=="0c63", MODE="664", GROUP="plugdev"
|
||||
|
||||
# Amontec JTAGkey and JTAGkey-tiny
|
||||
SYSFS{idVendor}=="0403", SYSFS{idProduct}=="cff8", MODE="664", GROUP="plugdev"
|
||||
ATTRS{idVendor}=="0403", ATTRS{idProduct}=="cff8", MODE="664", GROUP="plugdev"
|
||||
|
||||
# Amontec JTAGkey-HiSpeed
|
||||
SYSFS{idVendor}=="0fbb", SYSFS{idProduct}=="1000", MODE="664", GROUP="plugdev"
|
||||
ATTRS{idVendor}=="0fbb", ATTRS{idProduct}=="1000", MODE="664", GROUP="plugdev"
|
||||
|
||||
# Axiom AXM-0432 Link (Symphony SoundBite?)
|
||||
# Calao Systems USB-A9260-C01
|
||||
# TinCanTools Flyswatter
|
||||
# OOCD-Link
|
||||
# Marvell Sheevaplug (early development versions)
|
||||
SYSFS{idVendor}=="0403", SYSFS{idProduct}=="6010", MODE="664", GROUP="plugdev"
|
||||
ATTRS{idVendor}=="0403", ATTRS{idProduct}=="6010", MODE="664", GROUP="plugdev"
|
||||
|
||||
# Calao Systems USB-A9260-C02
|
||||
SYSFS{idVendor}=="0403", SYSFS{idProduct}=="6001", MODE="664", GROUP="plugdev"
|
||||
ATTRS{idVendor}=="0403", ATTRS{idProduct}=="6001", MODE="664", GROUP="plugdev"
|
||||
|
||||
# IAR J-Link USB
|
||||
SYSFS{idVendor}=="1366", SYSFS{idProduct}=="0101", MODE="664", GROUP="plugdev"
|
||||
ATTRS{idVendor}=="1366", ATTRS{idProduct}=="0101", MODE="664", GROUP="plugdev"
|
||||
|
||||
# Raisonance RLink
|
||||
SYSFS{idVendor}=="138e", SYSFS{idProduct}=="9000", MODE="664", GROUP="plugdev"
|
||||
ATTRS{idVendor}=="138e", ATTRS{idProduct}=="9000", MODE="664", GROUP="plugdev"
|
||||
|
||||
# Hitex STR9-comStick
|
||||
SYSFS{idVendor}=="0640", SYSFS{idProduct}=="002c", MODE="664", GROUP="plugdev"
|
||||
ATTRS{idVendor}=="0640", ATTRS{idProduct}=="002c", MODE="664", GROUP="plugdev"
|
||||
|
||||
# Hitex STM32-PerformanceStick
|
||||
SYSFS{idVendor}=="0640", SYSFS{idProduct}=="002d", MODE="664", GROUP="plugdev"
|
||||
ATTRS{idVendor}=="0640", ATTRS{idProduct}=="002d", MODE="664", GROUP="plugdev"
|
||||
|
||||
# Luminary Micro Stellaris/LM3S811
|
||||
SYSFS{idVendor}=="0403", SYSFS{idProduct}=="bcd9", MODE="664", GROUP="plugdev"
|
||||
# TI/Luminary Stellaris Evaluation Board (several)
|
||||
ATTRS{idVendor}=="0403", ATTRS{idProduct}=="bcd9", MODE="664", GROUP="plugdev"
|
||||
|
||||
# TI/Luminary Stellaris In-Circuit Debug Interface (ICDI) Board
|
||||
ATTRS{idVendor}=="0403", ATTRS{idProduct}=="bcda", MODE="664", GROUP="plugdev"
|
||||
|
||||
# Xverve Signalyzer Tool (DT-USB-ST)
|
||||
SYSFS{idVendor}=="0403", SYSFS{idProduct}=="bca0", MODE="664", GROUP="plugdev"
|
||||
ATTRS{idVendor}=="0403", ATTRS{idProduct}=="bca0", MODE="664", GROUP="plugdev"
|
||||
|
||||
# egnite Turtelizer 2
|
||||
SYSFS{idVendor}=="0403", SYSFS{idProduct}=="bdc8", MODE="664", GROUP="plugdev"
|
||||
ATTRS{idVendor}=="0403", ATTRS{idProduct}=="bdc8", MODE="664", GROUP="plugdev"
|
||||
|
||||
# Marvell Sheevaplug
|
||||
SYSFS{idVendor}=="9e88", SYSFS{idProduct}=="9e8f", MODE="664", GROUP="plugdev"
|
||||
ATTRS{idVendor}=="9e88", ATTRS{idProduct}=="9e8f", MODE="664", GROUP="plugdev"
|
||||
|
||||
# Section5 ICEbear
|
||||
SYSFS{idVendor}=="0403", SYSFS{idProduct}=="c140", MODE="664", GROUP="plugdev"
|
||||
SYSFS{idVendor}=="0403", SYSFS{idProduct}=="c141", MODE="664", GROUP="plugdev"
|
||||
ATTRS{idVendor}=="0403", ATTRS{idProduct}=="c140", MODE="664", GROUP="plugdev"
|
||||
ATTRS{idVendor}=="0403", ATTRS{idProduct}=="c141", MODE="664", GROUP="plugdev"
|
||||
|
||||
LABEL="openocd_rules_end"
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/** @mainpage OpenOCD Reference Manual
|
||||
/** @mainpage OpenOCD Developer's Guide
|
||||
|
||||
Welcome to the OpenOCD Reference Manual -- the developer's resource for
|
||||
Welcome to the OpenOCD Developer's Guide -- the developer's resource for
|
||||
learning about the internal architecture of the OpenOCD project. @par
|
||||
|
||||
In addition, this document contains the tactical and strategic plans
|
||||
|
||||
@@ -55,7 +55,7 @@ static COMMAND_HELPER(handle_hello_args, const char **sep, const char **name)
|
||||
@endcode
|
||||
|
||||
Of course, you may also call other macros or functions, but that extends
|
||||
beyond the scope of this tutorial on writing commands.
|
||||
beyond the scope of this tutorial on writing commands.
|
||||
|
||||
@section primercmdreg Command Registration
|
||||
|
||||
@@ -68,9 +68,9 @@ static const struct command_registration hello_command_handlers[] = {
|
||||
{
|
||||
.name = "hello",
|
||||
.mode = COMMAND_ANY,
|
||||
.handler = &handle_hello_command,
|
||||
.help = "print a warm greetings",
|
||||
.usage = "[<name>]",
|
||||
.handler = handle_hello_command,
|
||||
.help = "print a warm greeting",
|
||||
.usage = "[name]",
|
||||
},
|
||||
{
|
||||
.chain = foo_command_handlers,
|
||||
@@ -84,7 +84,12 @@ int hello_register_commands(struct command_context_s *cmd_ctx)
|
||||
}
|
||||
@endcode
|
||||
|
||||
That's it! The command should now be registered and avaiable to scripts.
|
||||
Note that the "usage" text should use the same EBNF that's found
|
||||
in the User's Guide: literals in 'single quotes', sequences of
|
||||
optional parameters in [square brackets], and alternatives in
|
||||
(parentheses|with|vertical bars), and so forth. No angle brackets.
|
||||
|
||||
That's it! The command should now be registered and available to scripts.
|
||||
|
||||
@section primercmdchain Command Chaining
|
||||
|
||||
|
||||
@@ -399,7 +399,7 @@ affect its behavior:
|
||||
|
||||
@section releasetutorial Release Tutorials
|
||||
|
||||
This section should contain a brief tutorial for using the Release
|
||||
This section should contain a brief tutorial for using the Release
|
||||
Script to perform release tasks, but the new script needs to be
|
||||
used for 0.3.0.
|
||||
|
||||
|
||||
@@ -320,6 +320,6 @@ openocd -s /usr/local/share/openocd -f httpd/httpd.tcl -f interface/dummy.cfg -f
|
||||
|
||||
Navigate to: http://localhost:8888/
|
||||
|
||||
|
||||
|
||||
|
||||
*/
|
||||
|
||||
@@ -308,7 +308,7 @@ For technical reference material:
|
||||
- Else it's a "Config Command" if it must be used before the
|
||||
configuration stage completes.
|
||||
- For a "Driver", list its name.
|
||||
- Use BNF style regular expressions to define parameters:
|
||||
- Use EBNF style regular expressions to define parameters:
|
||||
brackets around zero-or-one choices, parentheses around
|
||||
exactly-one choices.
|
||||
- Use \@option, \@file, \@var and other mechanisms where appropriate.
|
||||
|
||||
@@ -22,19 +22,23 @@ please check the \fIopenocd\fR info page for the complete list.
|
||||
.SH "OPTIONS"
|
||||
.TP
|
||||
.B "\-f, \-\-file <filename>"
|
||||
Use configuration file
|
||||
.BR <filename> .
|
||||
This is a shortcut for a \fB\-c "[script \fI<filename>\fB]"\fR
|
||||
command, using a search path to load the configuration file
|
||||
.IR <filename> .
|
||||
In order to specify multiple config files, you can use multiple
|
||||
.B \-\-file
|
||||
arguments. If this option is omitted, the config file
|
||||
arguments. If no such \fB\-c\fR
|
||||
options are included, the first config file
|
||||
.B openocd.cfg
|
||||
in the current working directory will be used.
|
||||
in the search path will be used.
|
||||
.TP
|
||||
.B "\-s, \-\-search <dirname>"
|
||||
Search for config files and scripts in the directory
|
||||
.BR <dirname> .
|
||||
If this option is omitted, OpenOCD searches for config files and scripts
|
||||
in the current directory.
|
||||
Add
|
||||
.I <dirname>
|
||||
to the search path used for config files and scripts.
|
||||
The search path begins with the current directory,
|
||||
then includes these additional directories before other
|
||||
components such as the standard OpenOCD script libraries.
|
||||
.TP
|
||||
.B "\-d, \-\-debug <debuglevel>"
|
||||
Set debug level. Possible values are:
|
||||
@@ -52,13 +56,17 @@ The default level is
|
||||
.TP
|
||||
.B "\-l, \-\-log_output <filename>"
|
||||
Redirect log output to the file
|
||||
.BR <filename> .
|
||||
.IR <filename> .
|
||||
Per default the log output is printed on
|
||||
.BR stderr .
|
||||
.TP
|
||||
.B "\-c, \-\-command <cmd>"
|
||||
Run the command
|
||||
.BR <cmd> .
|
||||
Add the command
|
||||
.I <cmd>
|
||||
to a list of commands executed on server startup.
|
||||
Note that you will need to explicitly invoke
|
||||
.I init
|
||||
if the command requires access to a target or flash.
|
||||
.TP
|
||||
.B "\-p, \-\-pipe"
|
||||
Use pipes when talking to gdb.
|
||||
@@ -88,9 +96,6 @@ and
|
||||
programs are properly installed at your site, the command
|
||||
.B info openocd
|
||||
should give you access to the complete manual.
|
||||
.PP
|
||||
Also, the OpenOCD wiki contains some more information and examples:
|
||||
.B http://openfacts.berlios.de/index-en.phtml?title=Open_On-Chip_Debugger
|
||||
.SH "AUTHORS"
|
||||
Please see the file AUTHORS.
|
||||
.PP
|
||||
|
||||
623
doc/openocd.texi
623
doc/openocd.texi
File diff suppressed because it is too large
Load Diff
@@ -1,4 +1,4 @@
|
||||
Some of these binaries are build & linked using eCos.
|
||||
Some of these binaries are build & linked using eCos.
|
||||
|
||||
For source for the flash drivers, see:
|
||||
|
||||
|
||||
@@ -60,12 +60,16 @@ endif
|
||||
if FT2232_LIBFTDI
|
||||
FTDI2232LIB = -lftdi -lusb
|
||||
else
|
||||
if USB_BLASTER_LIBFTDI
|
||||
FTDI2232LIB = -lftdi -lusb
|
||||
else
|
||||
if PRESTO_LIBFTDI
|
||||
FTDI2232LIB = -lftdi -lusb
|
||||
else
|
||||
FTDI2232LIB =
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
if USBPROG
|
||||
LIBUSB = -lusb
|
||||
|
||||
@@ -62,6 +62,7 @@
|
||||
#include "rom.h"
|
||||
|
||||
#ifdef CYGPKG_HAL_NIOS2
|
||||
#include <cyg/hal/io.h>
|
||||
#define ZY1000_SER_DEV "/dev/uart_0"
|
||||
#else
|
||||
#define ZY1000_SER_DEV "/dev/ser0"
|
||||
@@ -145,7 +146,14 @@ static void zylinjtag_reboot(cyg_addrword_t data)
|
||||
diag_printf("Unmounting /config..\n");
|
||||
umount("/config");
|
||||
diag_printf("Rebooting..\n");
|
||||
#ifdef CYGPKG_HAL_NIOS2
|
||||
/* This will reboot & reconfigure the FPGA from the bootloader
|
||||
* and on.
|
||||
*/
|
||||
IOWR(REMOTE_UPDATE_BASE, 0x20, 0x1);
|
||||
#else
|
||||
HAL_PLATFORM_RESET();
|
||||
#endif
|
||||
}
|
||||
static cyg_thread zylinjtag_thread_object;
|
||||
static cyg_handle_t zylinjtag_thread_handle;
|
||||
@@ -839,7 +847,7 @@ static int zylinjtag_Jim_Command_uart(Jim_Interp *interp, int argc,
|
||||
static int current_baud = 38400;
|
||||
if (argc == 1)
|
||||
{
|
||||
command_print(cmd_ctx, "%d", current_baud);
|
||||
Jim_SetResult(interp, Jim_NewIntObj(interp, current_baud));
|
||||
return JIM_OK;
|
||||
}
|
||||
else if (argc != 2)
|
||||
@@ -875,8 +883,8 @@ static int zylinjtag_Jim_Command_uart(Jim_Interp *interp, int argc,
|
||||
baud = CYGNUM_SERIAL_BAUD_230400;
|
||||
break;
|
||||
default:
|
||||
command_print(cmd_ctx, "unsupported baudrate");
|
||||
return ERROR_INVALID_ARGUMENTS;
|
||||
Jim_SetResult(interp, Jim_NewStringObj(interp, "unsupported baudrate", -1));
|
||||
return JIM_ERR;
|
||||
}
|
||||
|
||||
cyg_serial_info_t buf;
|
||||
@@ -889,7 +897,7 @@ static int zylinjtag_Jim_Command_uart(Jim_Interp *interp, int argc,
|
||||
err = cyg_io_lookup(ZY1000_SER_DEV, &serial_handle);
|
||||
if (err != ENOERR)
|
||||
{
|
||||
LOG_ERROR("Could not open serial port\n");
|
||||
Jim_SetResult(interp, Jim_NewStringObj(interp, "Could not open serial port", -1));
|
||||
return JIM_ERR;
|
||||
}
|
||||
|
||||
@@ -899,7 +907,7 @@ static int zylinjtag_Jim_Command_uart(Jim_Interp *interp, int argc,
|
||||
&len);
|
||||
if (err != ENOERR)
|
||||
{
|
||||
LOG_ERROR("Failed to get serial port settings %d", err);
|
||||
Jim_SetResult(interp, Jim_NewStringObj(interp, "Failed to get serial port settings", -1));
|
||||
return JIM_ERR;
|
||||
}
|
||||
buf.baud = baud;
|
||||
@@ -908,7 +916,7 @@ static int zylinjtag_Jim_Command_uart(Jim_Interp *interp, int argc,
|
||||
&len);
|
||||
if (err != ENOERR)
|
||||
{
|
||||
LOG_ERROR("Failed to set serial port settings %d", err);
|
||||
Jim_SetResult(interp, Jim_NewStringObj(interp, "Failed to set serial port settings", -1));
|
||||
return JIM_ERR;
|
||||
}
|
||||
|
||||
@@ -948,7 +956,11 @@ int main(int argc, char *argv[])
|
||||
|
||||
diag_init_putc(_zylinjtag_diag_write_char);
|
||||
// We want this in the log.
|
||||
diag_printf("Zylin ZY1000.\n");
|
||||
#ifdef CYGPKG_HAL_NIOS2
|
||||
diag_printf("Zylin ZY1000 PCB revc.\n");
|
||||
#else
|
||||
diag_printf("Zylin ZY1000 PCB revb.\n");
|
||||
#endif
|
||||
|
||||
err = mount("", "/ram", "ramfs");
|
||||
if (err < 0)
|
||||
@@ -987,6 +999,20 @@ int main(int argc, char *argv[])
|
||||
|
||||
copydir("/rom", "/ram/cgi");
|
||||
|
||||
#ifdef CYGPKG_HAL_NIOS2
|
||||
cyg_flashaddr_t err_address;
|
||||
#define UNCACHED_EXT_FLASH_BASE (0x80000000 + EXT_FLASH_BASE)
|
||||
/* The revc flash is locked upon reset, unlock it */
|
||||
#ifdef CYGHWR_IO_FLASH_BLOCK_LOCKING
|
||||
if ((err = flash_unlock((void *) UNCACHED_EXT_FLASH_BASE, EXT_FLASH_SPAN,
|
||||
(void **) &err_address)) != 0)
|
||||
{
|
||||
diag_printf("Error: could not unlock flash\n");
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
err = mount("/dev/flash1", "/config", "jffs2");
|
||||
if (err < 0)
|
||||
{
|
||||
@@ -1075,7 +1101,7 @@ int main(int argc, char *argv[])
|
||||
NULL, NULL);
|
||||
#endif
|
||||
|
||||
Jim_CreateCommand(httpstate.jim_interp, "uart", zylinjtag_Jim_Command_uart, NULL, NULL);
|
||||
Jim_CreateCommand(httpstate.jim_interp, "zy1000_uart", zylinjtag_Jim_Command_uart, NULL, NULL);
|
||||
|
||||
|
||||
log_init();
|
||||
|
||||
@@ -751,8 +751,8 @@ COMMAND_HANDLER(mg_write_cmd)
|
||||
|
||||
if (duration_measure(&bench) == ERROR_OK)
|
||||
{
|
||||
command_print(CMD_CTX, "wrote %zu byte from file %s "
|
||||
"in %fs (%0.3f kB/s)", fileio.size, CMD_ARGV[1],
|
||||
command_print(CMD_CTX, "wrote %ld bytes from file %s "
|
||||
"in %fs (%0.3f kB/s)", (long)fileio.size, CMD_ARGV[1],
|
||||
duration_elapsed(&bench), duration_kbps(&bench, fileio.size));
|
||||
}
|
||||
|
||||
@@ -762,7 +762,7 @@ COMMAND_HANDLER(mg_write_cmd)
|
||||
return ERROR_OK;
|
||||
|
||||
mg_write_cmd_err:
|
||||
free(buffer);
|
||||
free(buffer);
|
||||
fileio_close(&fileio);
|
||||
|
||||
return ret;
|
||||
@@ -829,7 +829,7 @@ COMMAND_HANDLER(mg_dump_cmd)
|
||||
return ERROR_OK;
|
||||
|
||||
mg_dump_cmd_err:
|
||||
free(buffer);
|
||||
free(buffer);
|
||||
fileio_close(&fileio);
|
||||
|
||||
return ret;
|
||||
@@ -1271,30 +1271,33 @@ COMMAND_HANDLER(mg_config_cmd)
|
||||
static const struct command_registration mflash_exec_command_handlers[] = {
|
||||
{
|
||||
.name = "probe",
|
||||
.handler = &mg_probe_cmd,
|
||||
.handler = mg_probe_cmd,
|
||||
.mode = COMMAND_EXEC,
|
||||
.help = "Detect bank configuration information",
|
||||
},
|
||||
{
|
||||
.name = "write",
|
||||
.handler = &mg_write_cmd,
|
||||
.handler = mg_write_cmd,
|
||||
.mode = COMMAND_EXEC,
|
||||
.usage = "<num> <file> <address>",
|
||||
.help = "Write a file at the specified address",
|
||||
/* FIXME bank_num is unused */
|
||||
.usage = "bank_num filename address",
|
||||
.help = "Write binary file at the specified address.",
|
||||
},
|
||||
{
|
||||
.name = "dump",
|
||||
.handler = &mg_dump_cmd,
|
||||
.handler = mg_dump_cmd,
|
||||
.mode = COMMAND_EXEC,
|
||||
.usage = "<num> <file> <address> <size>",
|
||||
.help = "Dump to a file from the specified address",
|
||||
/* FIXME bank_num is unused */
|
||||
.usage = "bank_num filename address size",
|
||||
.help = "Write specified number of bytes from a binary file "
|
||||
"to the specified, address.",
|
||||
},
|
||||
{
|
||||
.name = "config",
|
||||
.handler = &mg_config_cmd,
|
||||
.handler = mg_config_cmd,
|
||||
.mode = COMMAND_EXEC,
|
||||
.usage = "<num> <stage>",
|
||||
.help = "Dump to a file from the specified address",
|
||||
.help = "Configure MFLASH options.",
|
||||
.usage = "('boot'|'storage'|'pll' frequency)",
|
||||
},
|
||||
COMMAND_REGISTRATION_DONE
|
||||
};
|
||||
@@ -1345,7 +1348,8 @@ COMMAND_HANDLER(mg_bank_cmd)
|
||||
char *str;
|
||||
mflash_bank->rst_pin.num = strtoul(CMD_ARGV[2], &str, 0);
|
||||
if (*str)
|
||||
mflash_bank->rst_pin.port[0] = (uint16_t)tolower(str[0]);
|
||||
mflash_bank->rst_pin.port[0] = (uint16_t)
|
||||
tolower((unsigned)str[0]);
|
||||
|
||||
mflash_bank->target = target;
|
||||
|
||||
@@ -1366,15 +1370,15 @@ COMMAND_HANDLER(mg_bank_cmd)
|
||||
static const struct command_registration mflash_config_command_handlers[] = {
|
||||
{
|
||||
.name = "bank",
|
||||
.handler = &mg_bank_cmd,
|
||||
.handler = mg_bank_cmd,
|
||||
.mode = COMMAND_CONFIG,
|
||||
.help = "configure a mflash device bank",
|
||||
.usage = "<soc> <base> <RST pin> <target #>",
|
||||
.usage = "soc_type base_addr pin_id target",
|
||||
},
|
||||
{
|
||||
.name = "init",
|
||||
.mode = COMMAND_CONFIG,
|
||||
.handler = &handle_mflash_init_command,
|
||||
.handler = handle_mflash_init_command,
|
||||
.help = "initialize mflash devices",
|
||||
},
|
||||
COMMAND_REGISTRATION_DONE
|
||||
|
||||
@@ -25,6 +25,7 @@ NAND_DRIVERS = \
|
||||
s3c2412.c \
|
||||
s3c2440.c \
|
||||
s3c2443.c \
|
||||
s3c6400.c \
|
||||
at91sam9.c
|
||||
|
||||
noinst_HEADERS = \
|
||||
|
||||
@@ -697,28 +697,30 @@ static const struct command_registration at91sam9_sub_command_handlers[] = {
|
||||
.handler = handle_at91sam9_cle_command,
|
||||
.mode = COMMAND_CONFIG,
|
||||
.help = "set command latch enable address line (default is 22)",
|
||||
.usage = "<device_id> <address_line>",
|
||||
.usage = "bank_id address_line",
|
||||
},
|
||||
{
|
||||
.name = "ale",
|
||||
.handler = handle_at91sam9_ale_command,
|
||||
.mode = COMMAND_CONFIG,
|
||||
.help = "set address latch enable address line (default is 21)",
|
||||
.usage = "<device_id> <address_line>",
|
||||
.usage = "bank_id address_line",
|
||||
},
|
||||
{
|
||||
.name = "rdy_busy",
|
||||
.handler = handle_at91sam9_rdy_busy_command,
|
||||
.mode = COMMAND_CONFIG,
|
||||
.help = "set the input pin connected to RDY/~BUSY signal (no default)",
|
||||
.usage = "<device_id> <base_pioc> <pin_num>",
|
||||
.help = "set the GPIO input pin connected to "
|
||||
"the RDY/~BUSY signal (no default)",
|
||||
.usage = "bank_id pio_base_addr pin_num",
|
||||
},
|
||||
{
|
||||
.name = "ce",
|
||||
.handler = handle_at91sam9_ce_command,
|
||||
.mode = COMMAND_CONFIG,
|
||||
.help = "set the output pin connected to chip enable signal (no default)",
|
||||
.usage = "<device_id> <base_pioc> <pin_num>",
|
||||
.help = "set the GPIO output pin connected to "
|
||||
"the chip enable signal (no default)",
|
||||
.usage = "bank_id pio_base_addr pin_num",
|
||||
},
|
||||
COMMAND_REGISTRATION_DONE
|
||||
};
|
||||
|
||||
@@ -36,6 +36,7 @@ extern struct nand_flash_controller s3c2410_nand_controller;
|
||||
extern struct nand_flash_controller s3c2412_nand_controller;
|
||||
extern struct nand_flash_controller s3c2440_nand_controller;
|
||||
extern struct nand_flash_controller s3c2443_nand_controller;
|
||||
extern struct nand_flash_controller s3c6400_nand_controller;
|
||||
extern struct nand_flash_controller imx31_nand_flash_controller;
|
||||
extern struct nand_flash_controller at91sam9_nand_controller;
|
||||
|
||||
@@ -51,6 +52,7 @@ static struct nand_flash_controller *nand_flash_controllers[] =
|
||||
&s3c2412_nand_controller,
|
||||
&s3c2440_nand_controller,
|
||||
&s3c2443_nand_controller,
|
||||
&s3c6400_nand_controller,
|
||||
&imx31_nand_flash_controller,
|
||||
&at91sam9_nand_controller,
|
||||
/* &boundary_scan_nand_controller, */
|
||||
|
||||
@@ -500,9 +500,10 @@ static int lpc3180_write_page(struct nand_device *nand, uint32_t page, uint8_t *
|
||||
return ERROR_NAND_OPERATION_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
if (oob && (oob_size > 6))
|
||||
if (oob && (oob_size > 24))
|
||||
{
|
||||
LOG_ERROR("LPC3180 MLC controller can't write more than 6 bytes of OOB data");
|
||||
LOG_ERROR("LPC3180 MLC controller can't write more "
|
||||
"than 6 bytes for each quarter's OOB data");
|
||||
return ERROR_NAND_OPERATION_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
@@ -559,10 +560,10 @@ static int lpc3180_write_page(struct nand_device *nand, uint32_t page, uint8_t *
|
||||
data += thisrun_data_size;
|
||||
}
|
||||
|
||||
memset(oob_buffer, 0xff, (nand->page_size == 512) ? 6 : 24);
|
||||
memset(oob_buffer, 0xff, 6);
|
||||
if (oob)
|
||||
{
|
||||
memcpy(page_buffer, oob, thisrun_oob_size);
|
||||
memcpy(oob_buffer, oob, thisrun_oob_size);
|
||||
oob_size -= thisrun_oob_size;
|
||||
oob += thisrun_oob_size;
|
||||
}
|
||||
@@ -570,8 +571,10 @@ static int lpc3180_write_page(struct nand_device *nand, uint32_t page, uint8_t *
|
||||
/* write MLC_ECC_ENC_REG to start encode cycle */
|
||||
target_write_u32(target, 0x200b8008, 0x0);
|
||||
|
||||
target_write_memory(target, 0x200a8000, 4, 128, page_buffer + (quarter * 512));
|
||||
target_write_memory(target, 0x200a8000, 1, 6, oob_buffer + (quarter * 6));
|
||||
target_write_memory(target, 0x200a8000,
|
||||
4, 128, page_buffer);
|
||||
target_write_memory(target, 0x200a8000,
|
||||
1, 6, oob_buffer);
|
||||
|
||||
/* write MLC_ECC_AUTO_ENC_REG to start auto encode */
|
||||
target_write_u32(target, 0x200b8010, 0x0);
|
||||
@@ -760,7 +763,6 @@ static int lpc3180_controller_ready(struct nand_device *nand, int timeout)
|
||||
{
|
||||
struct lpc3180_nand_controller *lpc3180_info = nand->controller_priv;
|
||||
struct target *target = lpc3180_info->target;
|
||||
uint8_t status = 0x0;
|
||||
|
||||
if (target->state != TARGET_HALTED)
|
||||
{
|
||||
@@ -768,20 +770,35 @@ static int lpc3180_controller_ready(struct nand_device *nand, int timeout)
|
||||
return ERROR_NAND_OPERATION_FAILED;
|
||||
}
|
||||
|
||||
LOG_DEBUG("lpc3180_controller_ready count start=%d", timeout);
|
||||
|
||||
do
|
||||
{
|
||||
if (lpc3180_info->selected_controller == LPC3180_MLC_CONTROLLER)
|
||||
{
|
||||
uint8_t status;
|
||||
|
||||
/* Read MLC_ISR, wait for controller to become ready */
|
||||
target_read_u8(target, 0x200b8048, &status);
|
||||
|
||||
if (status & 2)
|
||||
if (status & 2) {
|
||||
LOG_DEBUG("lpc3180_controller_ready count=%d",
|
||||
timeout);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
else if (lpc3180_info->selected_controller == LPC3180_SLC_CONTROLLER)
|
||||
{
|
||||
/* we pretend that the SLC controller is always ready */
|
||||
return 1;
|
||||
uint32_t status;
|
||||
|
||||
/* Read SLC_STAT and check READY bit */
|
||||
target_read_u32(target, 0x20020018, &status);
|
||||
|
||||
if (status & 1) {
|
||||
LOG_DEBUG("lpc3180_controller_ready count=%d",
|
||||
timeout);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
alive_sleep(1);
|
||||
@@ -801,6 +818,8 @@ static int lpc3180_nand_ready(struct nand_device *nand, int timeout)
|
||||
return ERROR_NAND_OPERATION_FAILED;
|
||||
}
|
||||
|
||||
LOG_DEBUG("lpc3180_nand_ready count start=%d", timeout);
|
||||
|
||||
do
|
||||
{
|
||||
if (lpc3180_info->selected_controller == LPC3180_MLC_CONTROLLER)
|
||||
@@ -810,8 +829,11 @@ static int lpc3180_nand_ready(struct nand_device *nand, int timeout)
|
||||
/* Read MLC_ISR, wait for NAND flash device to become ready */
|
||||
target_read_u8(target, 0x200b8048, &status);
|
||||
|
||||
if (status & 1)
|
||||
if (status & 1) {
|
||||
LOG_DEBUG("lpc3180_nand_ready count end=%d",
|
||||
timeout);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
else if (lpc3180_info->selected_controller == LPC3180_SLC_CONTROLLER)
|
||||
{
|
||||
@@ -820,8 +842,11 @@ static int lpc3180_nand_ready(struct nand_device *nand, int timeout)
|
||||
/* Read SLC_STAT and check READY bit */
|
||||
target_read_u32(target, 0x20020018, &status);
|
||||
|
||||
if (status & 1)
|
||||
if (status & 1) {
|
||||
LOG_DEBUG("lpc3180_nand_ready count end=%d",
|
||||
timeout);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
alive_sleep(1);
|
||||
@@ -844,7 +869,7 @@ COMMAND_HANDLER(handle_lpc3180_select_command)
|
||||
}
|
||||
|
||||
unsigned num;
|
||||
COMMAND_PARSE_NUMBER(uint, CMD_ARGV[1], num);
|
||||
COMMAND_PARSE_NUMBER(uint, CMD_ARGV[0], num);
|
||||
struct nand_device *nand = get_nand_device_by_num(num);
|
||||
if (!nand)
|
||||
{
|
||||
@@ -878,10 +903,10 @@ COMMAND_HANDLER(handle_lpc3180_select_command)
|
||||
static const struct command_registration lpc3180_exec_command_handlers[] = {
|
||||
{
|
||||
.name = "select",
|
||||
.handler = &handle_lpc3180_select_command,
|
||||
.handler = handle_lpc3180_select_command,
|
||||
.mode = COMMAND_EXEC,
|
||||
.help = "select <'mlc'|'slc'> controller (default is mlc)",
|
||||
.usage = "<device_id> (mlc|slc)",
|
||||
.help = "select MLC or SLC controller (default is MLC)",
|
||||
.usage = "bank_id ['mlc'|'slc']",
|
||||
},
|
||||
COMMAND_REGISTRATION_DONE
|
||||
};
|
||||
@@ -896,17 +921,17 @@ static const struct command_registration lpc3180_command_handler[] = {
|
||||
};
|
||||
|
||||
struct nand_flash_controller lpc3180_nand_controller = {
|
||||
.name = "lpc3180",
|
||||
.commands = lpc3180_command_handler,
|
||||
.nand_device_command = lpc3180_nand_device_command,
|
||||
.init = lpc3180_init,
|
||||
.reset = lpc3180_reset,
|
||||
.command = lpc3180_command,
|
||||
.address = lpc3180_address,
|
||||
.write_data = lpc3180_write_data,
|
||||
.read_data = lpc3180_read_data,
|
||||
.write_page = lpc3180_write_page,
|
||||
.read_page = lpc3180_read_page,
|
||||
.controller_ready = lpc3180_controller_ready,
|
||||
.nand_ready = lpc3180_nand_ready,
|
||||
};
|
||||
.name = "lpc3180",
|
||||
.commands = lpc3180_command_handler,
|
||||
.nand_device_command = lpc3180_nand_device_command,
|
||||
.init = lpc3180_init,
|
||||
.reset = lpc3180_reset,
|
||||
.command = lpc3180_command,
|
||||
.address = lpc3180_address,
|
||||
.write_data = lpc3180_write_data,
|
||||
.read_data = lpc3180_read_data,
|
||||
.write_page = lpc3180_write_page,
|
||||
.read_page = lpc3180_read_page,
|
||||
.controller_ready = lpc3180_controller_ready,
|
||||
.nand_ready = lpc3180_nand_ready,
|
||||
};
|
||||
|
||||
76
src/flash/nand/s3c6400.c
Normal file
76
src/flash/nand/s3c6400.c
Normal file
@@ -0,0 +1,76 @@
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2010 by Peter Korsgaard <jacmet@sunsite.dk> *
|
||||
* Heavily based on s3c2412.c by Ben Dooks <ben@fluff.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., *
|
||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||
***************************************************************************/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "s3c24xx.h"
|
||||
/* s3c64xx uses another base address for the nand controller than 24xx */
|
||||
#undef S3C2410_NFREG
|
||||
#define S3C2410_NFREG(x) ((x) + 0x70200000)
|
||||
|
||||
NAND_DEVICE_COMMAND_HANDLER(s3c6400_nand_device_command)
|
||||
{
|
||||
struct s3c24xx_nand_controller *info;
|
||||
CALL_S3C24XX_DEVICE_COMMAND(nand, &info);
|
||||
|
||||
/* fill in the address fields for the core device */
|
||||
info->cmd = S3C2440_NFCMD;
|
||||
info->addr = S3C2440_NFADDR;
|
||||
info->data = S3C2440_NFDATA;
|
||||
info->nfstat = S3C2412_NFSTAT;
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
static int s3c6400_init(struct nand_device *nand)
|
||||
{
|
||||
struct s3c24xx_nand_controller *s3c24xx_info = nand->controller_priv;
|
||||
struct target *target = s3c24xx_info->target;
|
||||
|
||||
target_write_u32(target, S3C2410_NFCONF,
|
||||
S3C2440_NFCONF_TACLS(3) |
|
||||
S3C2440_NFCONF_TWRPH0(7) |
|
||||
S3C2440_NFCONF_TWRPH1(7) | 4);
|
||||
|
||||
target_write_u32(target, S3C2440_NFCONT,
|
||||
S3C2412_NFCONT_INIT_MAIN_ECC |
|
||||
S3C2440_NFCONT_ENABLE);
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
struct nand_flash_controller s3c6400_nand_controller = {
|
||||
.name = "s3c6400",
|
||||
.nand_device_command = &s3c6400_nand_device_command,
|
||||
.init = &s3c6400_init,
|
||||
.reset = &s3c24xx_reset,
|
||||
.command = &s3c24xx_command,
|
||||
.address = &s3c24xx_address,
|
||||
.write_data = &s3c24xx_write_data,
|
||||
.read_data = &s3c24xx_read_data,
|
||||
.write_page = s3c24xx_write_page,
|
||||
.read_page = s3c24xx_read_page,
|
||||
.write_block_data = &s3c2440_write_block_data,
|
||||
.read_block_data = &s3c2440_read_block_data,
|
||||
.controller_ready = &s3c24xx_controller_ready,
|
||||
.nand_ready = &s3c2440_nand_ready,
|
||||
};
|
||||
@@ -409,8 +409,8 @@ COMMAND_HANDLER(handle_nand_dump_command)
|
||||
|
||||
if (nand_fileio_finish(&s) == ERROR_OK)
|
||||
{
|
||||
command_print(CMD_CTX, "dumped %zu bytes in %fs (%0.3f kb/s)",
|
||||
s.fileio.size, duration_elapsed(&s.bench),
|
||||
command_print(CMD_CTX, "dumped %ld bytes in %fs (%0.3f kb/s)",
|
||||
(long)s.fileio.size, duration_elapsed(&s.bench),
|
||||
duration_kbps(&s.bench, s.fileio.size));
|
||||
}
|
||||
return ERROR_OK;
|
||||
@@ -446,68 +446,67 @@ COMMAND_HANDLER(handle_nand_raw_access_command)
|
||||
static const struct command_registration nand_exec_command_handlers[] = {
|
||||
{
|
||||
.name = "list",
|
||||
.handler = &handle_nand_list_command,
|
||||
.handler = handle_nand_list_command,
|
||||
.mode = COMMAND_EXEC,
|
||||
.help = "list configured NAND flash devices",
|
||||
},
|
||||
{
|
||||
.name = "info",
|
||||
.handler = &handle_nand_info_command,
|
||||
.handler = handle_nand_info_command,
|
||||
.mode = COMMAND_EXEC,
|
||||
.usage = "<bank>",
|
||||
.help = "print info about a NAND flash device",
|
||||
.usage = "[banknum | first_bank_num last_bank_num]",
|
||||
.help = "print info about one or more NAND flash devices",
|
||||
},
|
||||
{
|
||||
.name = "probe",
|
||||
.handler = &handle_nand_probe_command,
|
||||
.handler = handle_nand_probe_command,
|
||||
.mode = COMMAND_EXEC,
|
||||
.usage = "<bank>",
|
||||
.help = "identify NAND flash device <num>",
|
||||
|
||||
.usage = "bank_id",
|
||||
.help = "identify NAND flash device",
|
||||
},
|
||||
{
|
||||
.name = "check_bad_blocks",
|
||||
.handler = &handle_nand_check_bad_blocks_command,
|
||||
.handler = handle_nand_check_bad_blocks_command,
|
||||
.mode = COMMAND_EXEC,
|
||||
.usage = "<bank> [<offset> <length>]",
|
||||
.help = "check NAND flash device <num> for bad blocks",
|
||||
.usage = "bank_id [offset length]",
|
||||
.help = "check all or part of NAND flash device for bad blocks",
|
||||
},
|
||||
{
|
||||
.name = "erase",
|
||||
.handler = &handle_nand_erase_command,
|
||||
.handler = handle_nand_erase_command,
|
||||
.mode = COMMAND_EXEC,
|
||||
.usage = "<bank> [<offset> <length>]",
|
||||
.help = "erase blocks on NAND flash device",
|
||||
.usage = "bank_id [offset length]",
|
||||
.help = "erase all or subset of blocks on NAND flash device",
|
||||
},
|
||||
{
|
||||
.name = "dump",
|
||||
.handler = &handle_nand_dump_command,
|
||||
.handler = handle_nand_dump_command,
|
||||
.mode = COMMAND_EXEC,
|
||||
.usage = "<bank> <filename> <offset> <length> "
|
||||
"[oob_raw | oob_only]",
|
||||
.usage = "bank_id filename offset length "
|
||||
"['oob_raw'|'oob_only']",
|
||||
.help = "dump from NAND flash device",
|
||||
},
|
||||
{
|
||||
.name = "verify",
|
||||
.handler = &handle_nand_verify_command,
|
||||
.handler = handle_nand_verify_command,
|
||||
.mode = COMMAND_EXEC,
|
||||
.usage = "<bank> <filename> <offset> "
|
||||
"[oob_raw | oob_only | oob_softecc | oob_softecc_kw]",
|
||||
.usage = "bank_id filename offset "
|
||||
"['oob_raw'|'oob_only'|'oob_softecc'|'oob_softecc_kw']",
|
||||
.help = "verify NAND flash device",
|
||||
},
|
||||
{
|
||||
.name = "write",
|
||||
.handler = &handle_nand_write_command,
|
||||
.handler = handle_nand_write_command,
|
||||
.mode = COMMAND_EXEC,
|
||||
.usage = "<bank> <filename> <offset> "
|
||||
"[oob_raw | oob_only | oob_softecc | oob_softecc_kw]",
|
||||
.usage = "bank_id filename offset "
|
||||
"['oob_raw'|'oob_only'|'oob_softecc'|'oob_softecc_kw']",
|
||||
.help = "write to NAND flash device",
|
||||
},
|
||||
{
|
||||
.name = "raw_access",
|
||||
.handler = &handle_nand_raw_access_command,
|
||||
.handler = handle_nand_raw_access_command,
|
||||
.mode = COMMAND_EXEC,
|
||||
.usage = "<num> ['enable'|'disable']",
|
||||
.usage = "bank_id ['enable'|'disable']",
|
||||
.help = "raw access to NAND flash device",
|
||||
},
|
||||
COMMAND_REGISTRATION_DONE
|
||||
@@ -614,6 +613,7 @@ static const struct command_registration nand_config_command_handlers[] = {
|
||||
.handler = &handle_nand_device_command,
|
||||
.mode = COMMAND_CONFIG,
|
||||
.help = "defines a new NAND bank",
|
||||
.usage = "bank_id driver target [driver_options ...]",
|
||||
},
|
||||
{
|
||||
.name = "drivers",
|
||||
|
||||
@@ -412,14 +412,14 @@ static int aduc702x_check_flash_completion(struct target* target, unsigned int t
|
||||
}
|
||||
|
||||
struct flash_driver aduc702x_flash = {
|
||||
.name = "aduc702x",
|
||||
.flash_bank_command = &aduc702x_flash_bank_command,
|
||||
.erase = &aduc702x_erase,
|
||||
.protect = &aduc702x_protect,
|
||||
.write = &aduc702x_write,
|
||||
.probe = &aduc702x_probe,
|
||||
.auto_probe = &aduc702x_probe,
|
||||
.erase_check = &default_flash_blank_check,
|
||||
.protect_check = &aduc702x_protect_check,
|
||||
.info = &aduc702x_info
|
||||
};
|
||||
.name = "aduc702x",
|
||||
.flash_bank_command = aduc702x_flash_bank_command,
|
||||
.erase = aduc702x_erase,
|
||||
.protect = aduc702x_protect,
|
||||
.write = aduc702x_write,
|
||||
.probe = aduc702x_probe,
|
||||
.auto_probe = aduc702x_probe,
|
||||
.erase_check = default_flash_blank_check,
|
||||
.protect_check = aduc702x_protect_check,
|
||||
.info = aduc702x_info
|
||||
};
|
||||
|
||||
@@ -2288,7 +2288,7 @@ COMMAND_HANDLER(sam3_handle_info_command)
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
}
|
||||
// above garentees the "chip details" structure is valid
|
||||
// above guarantees the "chip details" structure is valid
|
||||
// and thus, bank private areas are valid
|
||||
// and we have a SAM3 chip, what a concept!
|
||||
|
||||
@@ -2386,7 +2386,7 @@ COMMAND_HANDLER(sam3_handle_gpnvm_command)
|
||||
|
||||
if (0 == strcmp("show", CMD_ARGV[0])) {
|
||||
if (who == -1) {
|
||||
showall:
|
||||
showall:
|
||||
r = ERROR_OK;
|
||||
for (x = 0 ; x < pChip->details.n_gpnvms ; x++) {
|
||||
r = FLASHD_GetGPNVM(&(pChip->details.bank[0]), x, &v);
|
||||
@@ -2466,24 +2466,27 @@ COMMAND_HANDLER(sam3_handle_slowclk_command)
|
||||
static const struct command_registration at91sam3_exec_command_handlers[] = {
|
||||
{
|
||||
.name = "gpnvm",
|
||||
.handler = &sam3_handle_gpnvm_command,
|
||||
.handler = sam3_handle_gpnvm_command,
|
||||
.mode = COMMAND_EXEC,
|
||||
.usage = "[(set|clear) [<bit_id>]]",
|
||||
.help = "Without arguments, shows the gpnvm register; "
|
||||
"otherwise, sets or clear the specified bit.",
|
||||
.usage = "[('clr'|'set'|'show') bitnum]",
|
||||
.help = "Without arguments, shows all bits in the gpnvm "
|
||||
"register. Otherwise, clears, sets, or shows one "
|
||||
"General Purpose Non-Volatile Memory (gpnvm) bit.",
|
||||
},
|
||||
{
|
||||
.name = "info",
|
||||
.handler = &sam3_handle_info_command,
|
||||
.handler = sam3_handle_info_command,
|
||||
.mode = COMMAND_EXEC,
|
||||
.help = "print information about the current sam3 chip",
|
||||
.help = "Print information about the current at91sam3 chip"
|
||||
"and its flash configuration.",
|
||||
},
|
||||
{
|
||||
.name = "slowclk",
|
||||
.handler = &sam3_handle_slowclk_command,
|
||||
.handler = sam3_handle_slowclk_command,
|
||||
.mode = COMMAND_EXEC,
|
||||
.usage = "<value>",
|
||||
.help = "set the slowclock frequency (default 32768hz)",
|
||||
.usage = "[clock_hz]",
|
||||
.help = "Display or set the slowclock frequency "
|
||||
"(default 32768 Hz).",
|
||||
},
|
||||
COMMAND_REGISTRATION_DONE
|
||||
};
|
||||
@@ -2498,15 +2501,15 @@ static const struct command_registration at91sam3_command_handlers[] = {
|
||||
};
|
||||
|
||||
struct flash_driver at91sam3_flash = {
|
||||
.name = "at91sam3",
|
||||
.commands = at91sam3_command_handlers,
|
||||
.flash_bank_command = &sam3_flash_bank_command,
|
||||
.erase = &sam3_erase,
|
||||
.protect = &sam3_protect,
|
||||
.write = &sam3_write,
|
||||
.probe = &sam3_probe,
|
||||
.auto_probe = &sam3_auto_probe,
|
||||
.erase_check = &sam3_erase_check,
|
||||
.protect_check = &sam3_protect_check,
|
||||
.info = &sam3_info,
|
||||
};
|
||||
.name = "at91sam3",
|
||||
.commands = at91sam3_command_handlers,
|
||||
.flash_bank_command = sam3_flash_bank_command,
|
||||
.erase = sam3_erase,
|
||||
.protect = sam3_protect,
|
||||
.write = sam3_write,
|
||||
.probe = sam3_probe,
|
||||
.auto_probe = sam3_auto_probe,
|
||||
.erase_check = sam3_erase_check,
|
||||
.protect_check = sam3_protect_check,
|
||||
.info = sam3_info,
|
||||
};
|
||||
|
||||
@@ -1182,10 +1182,11 @@ COMMAND_HANDLER(at91sam7_handle_gpnvm_command)
|
||||
static const struct command_registration at91sam7_exec_command_handlers[] = {
|
||||
{
|
||||
.name = "gpnvm",
|
||||
.handler = &at91sam7_handle_gpnvm_command,
|
||||
.handler = at91sam7_handle_gpnvm_command,
|
||||
.mode = COMMAND_EXEC,
|
||||
.usage = "gpnvm <bit> set | clear, "
|
||||
"set or clear one gpnvm bit",
|
||||
.help = "set or clear one General Purpose Non-Volatile Memory "
|
||||
"(gpnvm) bit",
|
||||
.usage = "bitnum ('set'|'clear')",
|
||||
},
|
||||
COMMAND_REGISTRATION_DONE
|
||||
};
|
||||
@@ -1200,15 +1201,15 @@ static const struct command_registration at91sam7_command_handlers[] = {
|
||||
};
|
||||
|
||||
struct flash_driver at91sam7_flash = {
|
||||
.name = "at91sam7",
|
||||
.commands = at91sam7_command_handlers,
|
||||
.flash_bank_command = &at91sam7_flash_bank_command,
|
||||
.erase = &at91sam7_erase,
|
||||
.protect = &at91sam7_protect,
|
||||
.write = &at91sam7_write,
|
||||
.probe = &at91sam7_probe,
|
||||
.auto_probe = &at91sam7_probe,
|
||||
.erase_check = &at91sam7_erase_check,
|
||||
.protect_check = &at91sam7_protect_check,
|
||||
.info = &at91sam7_info,
|
||||
};
|
||||
.name = "at91sam7",
|
||||
.commands = at91sam7_command_handlers,
|
||||
.flash_bank_command = at91sam7_flash_bank_command,
|
||||
.erase = at91sam7_erase,
|
||||
.protect = at91sam7_protect,
|
||||
.write = at91sam7_write,
|
||||
.probe = at91sam7_probe,
|
||||
.auto_probe = at91sam7_probe,
|
||||
.erase_check = at91sam7_erase_check,
|
||||
.protect_check = at91sam7_protect_check,
|
||||
.info = at91sam7_info,
|
||||
};
|
||||
|
||||
@@ -452,7 +452,7 @@ COMMAND_HANDLER(avrf_handle_mass_erase_command)
|
||||
static const struct command_registration avrf_exec_command_handlers[] = {
|
||||
{
|
||||
.name = "mass_erase",
|
||||
.handler = &avrf_handle_mass_erase_command,
|
||||
.handler = avrf_handle_mass_erase_command,
|
||||
.mode = COMMAND_EXEC,
|
||||
.help = "erase entire device",
|
||||
},
|
||||
@@ -469,15 +469,15 @@ static const struct command_registration avrf_command_handlers[] = {
|
||||
};
|
||||
|
||||
struct flash_driver avr_flash = {
|
||||
.name = "avr",
|
||||
.commands = avrf_command_handlers,
|
||||
.flash_bank_command = &avrf_flash_bank_command,
|
||||
.erase = &avrf_erase,
|
||||
.protect = &avrf_protect,
|
||||
.write = &avrf_write,
|
||||
.probe = &avrf_probe,
|
||||
.auto_probe = &avrf_auto_probe,
|
||||
.erase_check = &default_flash_mem_blank_check,
|
||||
.protect_check = &avrf_protect_check,
|
||||
.info = &avrf_info,
|
||||
};
|
||||
.name = "avr",
|
||||
.commands = avrf_command_handlers,
|
||||
.flash_bank_command = avrf_flash_bank_command,
|
||||
.erase = avrf_erase,
|
||||
.protect = avrf_protect,
|
||||
.write = avrf_write,
|
||||
.probe = avrf_probe,
|
||||
.auto_probe = avrf_auto_probe,
|
||||
.erase_check = default_flash_mem_blank_check,
|
||||
.protect_check = avrf_protect_check,
|
||||
.info = avrf_info,
|
||||
};
|
||||
|
||||
@@ -2618,14 +2618,14 @@ static int cfi_info(struct flash_bank *bank, char *buf, int buf_size)
|
||||
}
|
||||
|
||||
struct flash_driver cfi_flash = {
|
||||
.name = "cfi",
|
||||
.flash_bank_command = &cfi_flash_bank_command,
|
||||
.erase = &cfi_erase,
|
||||
.protect = &cfi_protect,
|
||||
.write = &cfi_write,
|
||||
.probe = &cfi_probe,
|
||||
.auto_probe = &cfi_auto_probe,
|
||||
.erase_check = &default_flash_blank_check,
|
||||
.protect_check = &cfi_protect_check,
|
||||
.info = &cfi_info,
|
||||
};
|
||||
.name = "cfi",
|
||||
.flash_bank_command = cfi_flash_bank_command,
|
||||
.erase = cfi_erase,
|
||||
.protect = cfi_protect,
|
||||
.write = cfi_write,
|
||||
.probe = cfi_probe,
|
||||
.auto_probe = cfi_auto_probe,
|
||||
.erase_check = default_flash_blank_check,
|
||||
.protect_check = cfi_protect_check,
|
||||
.info = cfi_info,
|
||||
};
|
||||
|
||||
@@ -29,6 +29,13 @@
|
||||
#include <target/image.h>
|
||||
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Upper level of NOR flash framework.
|
||||
* The lower level interfaces are to drivers. These upper level ones
|
||||
* primarily support access from Tcl scripts or from GDB.
|
||||
*/
|
||||
|
||||
struct flash_bank *flash_banks;
|
||||
|
||||
int flash_driver_erase(struct flash_bank *bank, int first, int last)
|
||||
@@ -280,9 +287,22 @@ int default_flash_blank_check(struct flash_bank *bank)
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
/* erase given flash region, selects proper bank according to target and address */
|
||||
/* Manipulate given flash region, selecting the bank according to target
|
||||
* and address. Maps an address range to a set of sectors, and issues
|
||||
* the callback() on that set ... e.g. to erase or unprotect its members.
|
||||
*
|
||||
* (Note a current bad assumption: that protection operates on the same
|
||||
* size sectors as erase operations use.)
|
||||
*
|
||||
* The "pad_reason" parameter is a kind of boolean: when it's NULL, the
|
||||
* range must fit those sectors exactly. This is clearly safe; it can't
|
||||
* erase data which the caller said to leave alone, for example. If it's
|
||||
* non-NULL, rather than failing, extra data in the first and/or last
|
||||
* sectors will be added to the range, and that reason string is used when
|
||||
* warning about those additions.
|
||||
*/
|
||||
static int flash_iterate_address_range(struct target *target,
|
||||
uint32_t addr, uint32_t length,
|
||||
char *pad_reason, uint32_t addr, uint32_t length,
|
||||
int (*callback)(struct flash_bank *bank, int first, int last))
|
||||
{
|
||||
struct flash_bank *c;
|
||||
@@ -304,34 +324,76 @@ static int flash_iterate_address_range(struct target *target,
|
||||
{
|
||||
/* special case, erase whole bank when length is zero */
|
||||
if (addr != c->base)
|
||||
{
|
||||
LOG_ERROR("Whole bank access must start at beginning of bank.");
|
||||
return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
|
||||
}
|
||||
|
||||
return callback(c, 0, c->num_sectors - 1);
|
||||
}
|
||||
|
||||
/* check whether it all fits in this bank */
|
||||
if (addr + length - 1 > c->base + c->size - 1)
|
||||
{
|
||||
LOG_ERROR("Flash access does not fit into bank.");
|
||||
return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
|
||||
}
|
||||
|
||||
/** @todo: handle erasures that cross into adjacent banks */
|
||||
|
||||
addr -= c->base;
|
||||
last_addr -= c->base;
|
||||
|
||||
for (i = 0; i < c->num_sectors; i++)
|
||||
{
|
||||
struct flash_sector *f = c->sectors + i;
|
||||
uint32_t end = f->offset + f->size;
|
||||
|
||||
/* start only on a sector boundary */
|
||||
if (first < 0) {
|
||||
/* scanned past the first sector? */
|
||||
if (addr < f->offset)
|
||||
break;
|
||||
|
||||
/* is this the first sector? */
|
||||
if (addr == f->offset)
|
||||
first = i;
|
||||
else if (addr < f->offset)
|
||||
break;
|
||||
|
||||
/* Does this need head-padding? If so, pad and warn;
|
||||
* or else force an error.
|
||||
*
|
||||
* Such padding can make trouble, since *WE* can't
|
||||
* ever know if that data was in use. The warning
|
||||
* should help users sort out messes later.
|
||||
*/
|
||||
else if (addr < end && pad_reason) {
|
||||
/* FIXME say how many bytes (e.g. 80 KB) */
|
||||
LOG_WARNING("Adding extra %s range, "
|
||||
"%#8.8x to %#8.8x",
|
||||
pad_reason,
|
||||
(unsigned) f->offset,
|
||||
(unsigned) addr - 1);
|
||||
first = i;
|
||||
} else
|
||||
continue;
|
||||
}
|
||||
|
||||
/* is this (also?) the last sector? */
|
||||
if (last_addr == f->offset + f->size) {
|
||||
if (last_addr == end) {
|
||||
last = i;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Does this need tail-padding? If so, pad and warn;
|
||||
* or else force an error.
|
||||
*/
|
||||
if (last_addr < end && pad_reason) {
|
||||
/* FIXME say how many bytes (e.g. 80 KB) */
|
||||
LOG_WARNING("Adding extra %s range, "
|
||||
"%#8.8x to %#8.8x",
|
||||
pad_reason,
|
||||
(unsigned) last_addr,
|
||||
(unsigned) end - 1);
|
||||
last = i;
|
||||
break;
|
||||
}
|
||||
@@ -346,22 +408,21 @@ static int flash_iterate_address_range(struct target *target,
|
||||
LOG_ERROR("address range 0x%8.8x .. 0x%8.8x "
|
||||
"is not sector-aligned",
|
||||
(unsigned) (c->base + addr),
|
||||
(unsigned) (last_addr - 1));
|
||||
(unsigned) (c->base + last_addr - 1));
|
||||
return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
|
||||
}
|
||||
|
||||
/* The NOR driver may trim this range down, based on
|
||||
* whether or not a given sector is already erased.
|
||||
*
|
||||
* REVISIT should *we* trim it... ?
|
||||
/* The NOR driver may trim this range down, based on what
|
||||
* sectors are already erased/unprotected. GDB currently
|
||||
* blocks such optimizations.
|
||||
*/
|
||||
return callback(c, first, last);
|
||||
}
|
||||
|
||||
int flash_erase_address_range(struct target *target,
|
||||
uint32_t addr, uint32_t length)
|
||||
bool pad, uint32_t addr, uint32_t length)
|
||||
{
|
||||
return flash_iterate_address_range(target,
|
||||
return flash_iterate_address_range(target, pad ? "erase" : NULL,
|
||||
addr, length, &flash_driver_erase);
|
||||
}
|
||||
|
||||
@@ -372,7 +433,11 @@ static int flash_driver_unprotect(struct flash_bank *bank, int first, int last)
|
||||
|
||||
static int flash_unlock_address_range(struct target *target, uint32_t addr, uint32_t length)
|
||||
{
|
||||
return flash_iterate_address_range(target,
|
||||
/* By default, pad to sector boundaries ... the real issue here
|
||||
* is that our (only) caller *permanently* removes protection,
|
||||
* and doesn't restore it.
|
||||
*/
|
||||
return flash_iterate_address_range(target, "unprotect",
|
||||
addr, length, &flash_driver_unprotect);
|
||||
}
|
||||
|
||||
@@ -386,6 +451,12 @@ int flash_write_unlock(struct target *target, struct image *image,
|
||||
struct flash_bank *c;
|
||||
int *padding;
|
||||
|
||||
/* REVISIT do_pad should perhaps just be another parameter.
|
||||
* GDB wouldn't ever need it, since it erases separately.
|
||||
* But "flash write_image" commands might want that option.
|
||||
*/
|
||||
bool do_pad = false;
|
||||
|
||||
section = 0;
|
||||
section_offset = 0;
|
||||
|
||||
@@ -401,7 +472,7 @@ int flash_write_unlock(struct target *target, struct image *image,
|
||||
}
|
||||
|
||||
/* allocate padding array */
|
||||
padding = malloc(image->num_sections * sizeof(padding));
|
||||
padding = calloc(image->num_sections, sizeof(*padding));
|
||||
|
||||
/* loop until we reach end of the image */
|
||||
while (section < image->num_sections)
|
||||
@@ -439,10 +510,31 @@ int flash_write_unlock(struct target *target, struct image *image,
|
||||
{
|
||||
if (image->sections[section_last + 1].base_address < (run_address + run_size))
|
||||
{
|
||||
LOG_DEBUG("section %d out of order(very slightly surprising, but supported)", section_last + 1);
|
||||
LOG_DEBUG("section %d out of order "
|
||||
"(surprising, but supported)",
|
||||
section_last + 1);
|
||||
/* REVISIT this can break with autoerase ...
|
||||
* clobbering data after it's written.
|
||||
*/
|
||||
break;
|
||||
}
|
||||
/* if we have multiple sections within our image, flash programming could fail due to alignment issues
|
||||
|
||||
/* FIXME This needlessly touches sectors BETWEEN the
|
||||
* sections it's writing. Without auto erase, it just
|
||||
* writes ones. That WILL INVALIDATE data in cases
|
||||
* like Stellaris Tempest chips, corrupting internal
|
||||
* ECC codes; and at least FreeScale suggests issues
|
||||
* with that approach (in HC11 documentation).
|
||||
*
|
||||
* With auto erase enabled, data in those sectors will
|
||||
* be needlessly destroyed; and some of the limited
|
||||
* number of flash erase cycles will be wasted...
|
||||
*
|
||||
* In both cases, the extra writes slow things down.
|
||||
*/
|
||||
|
||||
/* if we have multiple sections within our image,
|
||||
* flash programming could fail due to alignment issues
|
||||
* attempt to rebuild a consecutive buffer for the flash loader */
|
||||
pad_bytes = (image->sections[section_last + 1].base_address) - (run_address + run_size);
|
||||
if ((run_address + run_size + pad_bytes) > (c->base + c->size))
|
||||
@@ -450,7 +542,6 @@ int flash_write_unlock(struct target *target, struct image *image,
|
||||
padding[section_last] = pad_bytes;
|
||||
run_size += image->sections[++section_last].size;
|
||||
run_size += pad_bytes;
|
||||
padding[section_last] = 0;
|
||||
|
||||
LOG_INFO("Padding image section %d with %d bytes", section_last-1, pad_bytes);
|
||||
}
|
||||
@@ -458,11 +549,35 @@ int flash_write_unlock(struct target *target, struct image *image,
|
||||
/* fit the run into bank constraints */
|
||||
if (run_address + run_size - 1 > c->base + c->size - 1)
|
||||
{
|
||||
/* REVISIT isn't this superfluous, given the while()
|
||||
* loop conditions above??
|
||||
*/
|
||||
LOG_WARNING("writing %d bytes only - as image section is %d bytes and bank is only %d bytes", \
|
||||
(int)(c->base + c->size - run_address), (int)(run_size), (int)(c->size));
|
||||
run_size = c->base + c->size - run_address;
|
||||
}
|
||||
|
||||
/* If we're applying any sector automagic, then pad this
|
||||
* (maybe-combined) segment to the end of its last sector.
|
||||
*/
|
||||
if (unlock || erase) {
|
||||
int sector;
|
||||
uint32_t offset_start = run_address - c->base;
|
||||
uint32_t offset_end = offset_start + run_size;
|
||||
uint32_t end = offset_end, delta;
|
||||
|
||||
for (sector = 0; sector < c->num_sectors; sector++) {
|
||||
end = c->sectors[sector].offset
|
||||
+ c->sectors[sector].size;
|
||||
if (offset_end <= end)
|
||||
break;
|
||||
}
|
||||
|
||||
delta = end - offset_end;
|
||||
padding[section_last] += delta;
|
||||
run_size += delta;
|
||||
}
|
||||
|
||||
/* allocate buffer */
|
||||
buffer = malloc(run_size);
|
||||
buffer_size = 0;
|
||||
@@ -509,7 +624,8 @@ int flash_write_unlock(struct target *target, struct image *image,
|
||||
if (erase)
|
||||
{
|
||||
/* calculate and erase sectors */
|
||||
retval = flash_erase_address_range(target, run_address, run_size);
|
||||
retval = flash_erase_address_range(target,
|
||||
do_pad, run_address, run_size);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -24,6 +24,11 @@
|
||||
|
||||
#include <flash/common.h>
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Upper level NOR flash interfaces.
|
||||
*/
|
||||
|
||||
struct image;
|
||||
|
||||
#define FLASH_MAX_ERROR_STR (128)
|
||||
@@ -97,10 +102,14 @@ int flash_init_drivers(struct command_context *cmd_ctx);
|
||||
|
||||
/**
|
||||
* Erases @a length bytes in the @a target flash, starting at @a addr.
|
||||
* The range @a addr to @a addr + @a length - 1 must be strictly
|
||||
* sector aligned, unless @a pad is true. Setting @a pad true extends
|
||||
* the range, at beginning and/or end, if needed for sector alignment.
|
||||
* @returns ERROR_OK if successful; otherwise, an error code.
|
||||
*/
|
||||
int flash_erase_address_range(struct target *target,
|
||||
uint32_t addr, uint32_t length);
|
||||
bool pad, uint32_t addr, uint32_t length);
|
||||
|
||||
/**
|
||||
* Writes @a image into the @a target flash. The @a written parameter
|
||||
* will contain the
|
||||
|
||||
@@ -431,14 +431,14 @@ static int ecosflash_handle_gpnvm_command(struct command_context *cmd_ctx, char
|
||||
#endif
|
||||
|
||||
struct flash_driver ecosflash_flash = {
|
||||
.name = "ecosflash",
|
||||
.flash_bank_command = &ecosflash_flash_bank_command,
|
||||
.erase = &ecosflash_erase,
|
||||
.protect = &ecosflash_protect,
|
||||
.write = &ecosflash_write,
|
||||
.probe = &ecosflash_probe,
|
||||
.auto_probe = &ecosflash_probe,
|
||||
.erase_check = &default_flash_blank_check,
|
||||
.protect_check = &ecosflash_protect_check,
|
||||
.info = &ecosflash_info
|
||||
};
|
||||
.name = "ecosflash",
|
||||
.flash_bank_command = ecosflash_flash_bank_command,
|
||||
.erase = ecosflash_erase,
|
||||
.protect = ecosflash_protect,
|
||||
.write = ecosflash_write,
|
||||
.probe = ecosflash_probe,
|
||||
.auto_probe = ecosflash_probe,
|
||||
.erase_check = default_flash_blank_check,
|
||||
.protect_check = ecosflash_protect_check,
|
||||
.info = ecosflash_info
|
||||
};
|
||||
|
||||
@@ -135,15 +135,15 @@ static const struct command_registration faux_command_handlers[] = {
|
||||
};
|
||||
|
||||
struct flash_driver faux_flash = {
|
||||
.name = "faux",
|
||||
.commands = faux_command_handlers,
|
||||
.flash_bank_command = &faux_flash_bank_command,
|
||||
.erase = &faux_erase,
|
||||
.protect = &faux_protect,
|
||||
.write = &faux_write,
|
||||
.probe = &faux_probe,
|
||||
.auto_probe = &faux_probe,
|
||||
.erase_check = &default_flash_blank_check,
|
||||
.protect_check = &faux_protect_check,
|
||||
.info = &faux_info
|
||||
};
|
||||
.name = "faux",
|
||||
.commands = faux_command_handlers,
|
||||
.flash_bank_command = faux_flash_bank_command,
|
||||
.erase = faux_erase,
|
||||
.protect = faux_protect,
|
||||
.write = faux_write,
|
||||
.probe = faux_probe,
|
||||
.auto_probe = faux_probe,
|
||||
.erase_check = default_flash_blank_check,
|
||||
.protect_check = faux_protect_check,
|
||||
.info = faux_info
|
||||
};
|
||||
|
||||
@@ -783,7 +783,7 @@ COMMAND_HANDLER(lpc2000_handle_part_id_command)
|
||||
static const struct command_registration lpc2000_exec_command_handlers[] = {
|
||||
{
|
||||
.name = "part_id",
|
||||
.handler = &lpc2000_handle_part_id_command,
|
||||
.handler = lpc2000_handle_part_id_command,
|
||||
.mode = COMMAND_EXEC,
|
||||
.help = "print part id of lpc2000 flash bank <num>",
|
||||
},
|
||||
@@ -800,17 +800,15 @@ static const struct command_registration lpc2000_command_handlers[] = {
|
||||
};
|
||||
|
||||
struct flash_driver lpc2000_flash = {
|
||||
.name = "lpc2000",
|
||||
.commands = lpc2000_command_handlers,
|
||||
.flash_bank_command = &lpc2000_flash_bank_command,
|
||||
.erase = &lpc2000_erase,
|
||||
.protect = &lpc2000_protect,
|
||||
.write = &lpc2000_write,
|
||||
.probe = &lpc2000_probe,
|
||||
.auto_probe = &lpc2000_probe,
|
||||
.erase_check = &lpc2000_erase_check,
|
||||
.protect_check = &lpc2000_protect_check,
|
||||
.info = &lpc2000_info,
|
||||
};
|
||||
|
||||
|
||||
.name = "lpc2000",
|
||||
.commands = lpc2000_command_handlers,
|
||||
.flash_bank_command = lpc2000_flash_bank_command,
|
||||
.erase = lpc2000_erase,
|
||||
.protect = lpc2000_protect,
|
||||
.write = lpc2000_write,
|
||||
.probe = lpc2000_probe,
|
||||
.auto_probe = lpc2000_probe,
|
||||
.erase_check = lpc2000_erase_check,
|
||||
.protect_check = lpc2000_protect_check,
|
||||
.info = lpc2000_info,
|
||||
};
|
||||
|
||||
@@ -473,14 +473,14 @@ static int lpc288x_protect(struct flash_bank *bank, int set, int first, int last
|
||||
}
|
||||
|
||||
struct flash_driver lpc288x_flash = {
|
||||
.name = "lpc288x",
|
||||
.flash_bank_command = &lpc288x_flash_bank_command,
|
||||
.erase = &lpc288x_erase,
|
||||
.protect = &lpc288x_protect,
|
||||
.write = &lpc288x_write,
|
||||
.probe = &lpc288x_probe,
|
||||
.auto_probe = &lpc288x_probe,
|
||||
.erase_check = &lpc288x_erase_check,
|
||||
.protect_check = &lpc288x_protect_check,
|
||||
.info = &lpc288x_info,
|
||||
};
|
||||
.name = "lpc288x",
|
||||
.flash_bank_command = lpc288x_flash_bank_command,
|
||||
.erase = lpc288x_erase,
|
||||
.protect = lpc288x_protect,
|
||||
.write = lpc288x_write,
|
||||
.probe = lpc288x_probe,
|
||||
.auto_probe = lpc288x_probe,
|
||||
.erase_check = lpc288x_erase_check,
|
||||
.protect_check = lpc288x_protect_check,
|
||||
.info = lpc288x_info,
|
||||
};
|
||||
|
||||
@@ -951,45 +951,49 @@ COMMAND_HANDLER(lpc2900_handle_secure_jtag_command)
|
||||
static const struct command_registration lpc2900_exec_command_handlers[] = {
|
||||
{
|
||||
.name = "signature",
|
||||
.handler = &lpc2900_handle_signature_command,
|
||||
.handler = lpc2900_handle_signature_command,
|
||||
.mode = COMMAND_EXEC,
|
||||
.usage = "<bank>",
|
||||
.help = "print device signature of flash bank",
|
||||
.usage = "bank_id",
|
||||
.help = "Calculate and display signature of flash bank.",
|
||||
},
|
||||
{
|
||||
.name = "read_custom",
|
||||
.handler = &lpc2900_handle_read_custom_command,
|
||||
.handler = lpc2900_handle_read_custom_command,
|
||||
.mode = COMMAND_EXEC,
|
||||
.usage = "<bank> <filename>",
|
||||
.help = "read customer information from index sector to file",
|
||||
.usage = "bank_id filename",
|
||||
.help = "Copies 912 bytes of customer information "
|
||||
"from index sector into file.",
|
||||
},
|
||||
{
|
||||
.name = "password",
|
||||
.handler = &lpc2900_handle_password_command,
|
||||
.handler = lpc2900_handle_password_command,
|
||||
.mode = COMMAND_EXEC,
|
||||
.usage = "<bank> <password>",
|
||||
.help = "enter password to enable 'dangerous' options",
|
||||
.usage = "bank_id password",
|
||||
.help = "Enter fixed password to enable 'dangerous' options.",
|
||||
},
|
||||
{
|
||||
.name = "write_custom",
|
||||
.handler = &lpc2900_handle_write_custom_command,
|
||||
.handler = lpc2900_handle_write_custom_command,
|
||||
.mode = COMMAND_EXEC,
|
||||
.usage = "<bank> <filename> [<type>]",
|
||||
.help = "write customer info from file to index sector",
|
||||
.usage = "bank_id filename ('bin'|'ihex'|'elf'|'s19')",
|
||||
.help = "Copies 912 bytes of customer info from file "
|
||||
"to index sector.",
|
||||
},
|
||||
{
|
||||
.name = "secure_sector",
|
||||
.handler = &lpc2900_handle_secure_sector_command,
|
||||
.handler = lpc2900_handle_secure_sector_command,
|
||||
.mode = COMMAND_EXEC,
|
||||
.usage = "<bank> <first> <last>",
|
||||
.help = "activate sector security for a range of sectors",
|
||||
.usage = "bank_id first_sector last_sector",
|
||||
.help = "Activate sector security for a range of sectors. "
|
||||
"It will be effective after a power cycle.",
|
||||
},
|
||||
{
|
||||
.name = "secure_jtag",
|
||||
.handler = &lpc2900_handle_secure_jtag_command,
|
||||
.handler = lpc2900_handle_secure_jtag_command,
|
||||
.mode = COMMAND_EXEC,
|
||||
.usage = "<bank> <level>",
|
||||
.help = "activate JTAG security",
|
||||
.usage = "bank_id",
|
||||
.help = "Disable the JTAG port. "
|
||||
"It will be effective after a power cycle.",
|
||||
},
|
||||
COMMAND_REGISTRATION_DONE
|
||||
};
|
||||
|
||||
@@ -348,14 +348,14 @@ static int ocl_auto_probe(struct flash_bank *bank)
|
||||
}
|
||||
|
||||
struct flash_driver ocl_flash = {
|
||||
.name = "ocl",
|
||||
.flash_bank_command = &ocl_flash_bank_command,
|
||||
.erase = &ocl_erase,
|
||||
.protect = &ocl_protect,
|
||||
.write = &ocl_write,
|
||||
.probe = &ocl_probe,
|
||||
.erase_check = &ocl_erase_check,
|
||||
.protect_check = &ocl_protect_check,
|
||||
.info = &ocl_info,
|
||||
.auto_probe = &ocl_auto_probe,
|
||||
};
|
||||
.name = "ocl",
|
||||
.flash_bank_command = ocl_flash_bank_command,
|
||||
.erase = ocl_erase,
|
||||
.protect = ocl_protect,
|
||||
.write = ocl_write,
|
||||
.probe = ocl_probe,
|
||||
.erase_check = ocl_erase_check,
|
||||
.protect_check = ocl_protect_check,
|
||||
.info = ocl_info,
|
||||
.auto_probe = ocl_auto_probe,
|
||||
};
|
||||
|
||||
@@ -886,13 +886,13 @@ COMMAND_HANDLER(pic32mx_handle_pgm_word_command)
|
||||
static const struct command_registration pic32mx_exec_command_handlers[] = {
|
||||
{
|
||||
.name = "chip_erase",
|
||||
.handler = &pic32mx_handle_chip_erase_command,
|
||||
.handler = pic32mx_handle_chip_erase_command,
|
||||
.mode = COMMAND_EXEC,
|
||||
.help = "erase device",
|
||||
},
|
||||
{
|
||||
.name = "pgm_word",
|
||||
.handler = &pic32mx_handle_pgm_word_command,
|
||||
.handler = pic32mx_handle_pgm_word_command,
|
||||
.mode = COMMAND_EXEC,
|
||||
.help = "program a word",
|
||||
},
|
||||
@@ -909,15 +909,15 @@ static const struct command_registration pic32mx_command_handlers[] = {
|
||||
};
|
||||
|
||||
struct flash_driver pic32mx_flash = {
|
||||
.name = "pic32mx",
|
||||
.commands = pic32mx_command_handlers,
|
||||
.flash_bank_command = &pic32mx_flash_bank_command,
|
||||
.erase = &pic32mx_erase,
|
||||
.protect = &pic32mx_protect,
|
||||
.write = &pic32mx_write,
|
||||
.probe = &pic32mx_probe,
|
||||
.auto_probe = &pic32mx_auto_probe,
|
||||
.erase_check = &default_flash_mem_blank_check,
|
||||
.protect_check = &pic32mx_protect_check,
|
||||
.info = &pic32mx_info,
|
||||
};
|
||||
.name = "pic32mx",
|
||||
.commands = pic32mx_command_handlers,
|
||||
.flash_bank_command = pic32mx_flash_bank_command,
|
||||
.erase = pic32mx_erase,
|
||||
.protect = pic32mx_protect,
|
||||
.write = pic32mx_write,
|
||||
.probe = pic32mx_probe,
|
||||
.auto_probe = pic32mx_auto_probe,
|
||||
.erase_check = default_flash_mem_blank_check,
|
||||
.protect_check = pic32mx_protect_check,
|
||||
.info = pic32mx_info,
|
||||
};
|
||||
|
||||
@@ -1173,7 +1173,7 @@ COMMAND_HANDLER(stellaris_handle_mass_erase_command)
|
||||
static const struct command_registration stellaris_exec_command_handlers[] = {
|
||||
{
|
||||
.name = "mass_erase",
|
||||
.handler = &stellaris_handle_mass_erase_command,
|
||||
.handler = stellaris_handle_mass_erase_command,
|
||||
.mode = COMMAND_EXEC,
|
||||
.help = "erase entire device",
|
||||
},
|
||||
@@ -1182,7 +1182,7 @@ static const struct command_registration stellaris_exec_command_handlers[] = {
|
||||
static const struct command_registration stellaris_command_handlers[] = {
|
||||
{
|
||||
.name = "stellaris",
|
||||
.mode = COMMAND_ANY,
|
||||
.mode = COMMAND_EXEC,
|
||||
.help = "Stellaris flash command group",
|
||||
.chain = stellaris_exec_command_handlers,
|
||||
},
|
||||
|
||||
@@ -978,7 +978,9 @@ COMMAND_HANDLER(stm32x_handle_unlock_command)
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
command_print(CMD_CTX, "stm32x unlocked");
|
||||
command_print(CMD_CTX, "stm32x unlocked.\n"
|
||||
"INFO: a reset or power cycle is required "
|
||||
"for the new settings to take effect.");
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
@@ -1066,29 +1068,36 @@ COMMAND_HANDLER(stm32x_handle_options_write_command)
|
||||
return ERROR_TARGET_NOT_HALTED;
|
||||
}
|
||||
|
||||
/* REVISIT: ignores some options which we will display...
|
||||
* and doesn't insist on the specified syntax.
|
||||
*/
|
||||
|
||||
/* OPT_RDWDGSW */
|
||||
if (strcmp(CMD_ARGV[1], "SWWDG") == 0)
|
||||
{
|
||||
optionbyte |= (1 << 0);
|
||||
}
|
||||
else
|
||||
else /* REVISIT must be "HWWDG" then ... */
|
||||
{
|
||||
optionbyte &= ~(1 << 0);
|
||||
}
|
||||
|
||||
/* OPT_RDRSTSTDBY */
|
||||
if (strcmp(CMD_ARGV[2], "NORSTSTNDBY") == 0)
|
||||
{
|
||||
optionbyte |= (1 << 1);
|
||||
}
|
||||
else
|
||||
else /* REVISIT must be "RSTSTNDBY" then ... */
|
||||
{
|
||||
optionbyte &= ~(1 << 1);
|
||||
}
|
||||
|
||||
/* OPT_RDRSTSTOP */
|
||||
if (strcmp(CMD_ARGV[3], "NORSTSTOP") == 0)
|
||||
{
|
||||
optionbyte |= (1 << 2);
|
||||
}
|
||||
else
|
||||
else /* REVISIT must be "RSTSTOP" then ... */
|
||||
{
|
||||
optionbyte &= ~(1 << 2);
|
||||
}
|
||||
@@ -1107,7 +1116,9 @@ COMMAND_HANDLER(stm32x_handle_options_write_command)
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
command_print(CMD_CTX, "stm32x write options complete");
|
||||
command_print(CMD_CTX, "stm32x write options complete.\n"
|
||||
"INFO: a reset or power cycle is required "
|
||||
"for the new settings to take effect.");
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
@@ -1186,33 +1197,40 @@ COMMAND_HANDLER(stm32x_handle_mass_erase_command)
|
||||
static const struct command_registration stm32x_exec_command_handlers[] = {
|
||||
{
|
||||
.name = "lock",
|
||||
.handler = &stm32x_handle_lock_command,
|
||||
.handler = stm32x_handle_lock_command,
|
||||
.mode = COMMAND_EXEC,
|
||||
.help = "lock device",
|
||||
.usage = "bank_id",
|
||||
.help = "Lock entire flash device.",
|
||||
},
|
||||
{
|
||||
.name = "unlock",
|
||||
.handler = &stm32x_handle_unlock_command,
|
||||
.handler = stm32x_handle_unlock_command,
|
||||
.mode = COMMAND_EXEC,
|
||||
.help = "unlock protected device",
|
||||
.usage = "bank_id",
|
||||
.help = "Unlock entire protected flash device.",
|
||||
},
|
||||
{
|
||||
.name = "mass_erase",
|
||||
.handler = &stm32x_handle_mass_erase_command,
|
||||
.handler = stm32x_handle_mass_erase_command,
|
||||
.mode = COMMAND_EXEC,
|
||||
.help = "mass erase device",
|
||||
.usage = "bank_id",
|
||||
.help = "Erase entire flash device.",
|
||||
},
|
||||
{
|
||||
.name = "options_read",
|
||||
.handler = &stm32x_handle_options_read_command,
|
||||
.handler = stm32x_handle_options_read_command,
|
||||
.mode = COMMAND_EXEC,
|
||||
.help = "read device option bytes",
|
||||
.usage = "bank_id",
|
||||
.help = "Read and display device option byte.",
|
||||
},
|
||||
{
|
||||
.name = "options_write",
|
||||
.handler = &stm32x_handle_options_write_command,
|
||||
.handler = stm32x_handle_options_write_command,
|
||||
.mode = COMMAND_EXEC,
|
||||
.help = "write device option bytes",
|
||||
.usage = "bank_id ('SWWDG'|'HWWDG') "
|
||||
"('RSTSTNDBY'|'NORSTSTNDBY') "
|
||||
"('RSTSTOP'|'NORSTSTOP')",
|
||||
.help = "Replace bits in device option byte.",
|
||||
},
|
||||
COMMAND_REGISTRATION_DONE
|
||||
};
|
||||
@@ -1227,15 +1245,15 @@ static const struct command_registration stm32x_command_handlers[] = {
|
||||
};
|
||||
|
||||
struct flash_driver stm32x_flash = {
|
||||
.name = "stm32x",
|
||||
.commands = stm32x_command_handlers,
|
||||
.flash_bank_command = &stm32x_flash_bank_command,
|
||||
.erase = &stm32x_erase,
|
||||
.protect = &stm32x_protect,
|
||||
.write = &stm32x_write,
|
||||
.probe = &stm32x_probe,
|
||||
.auto_probe = &stm32x_auto_probe,
|
||||
.erase_check = &default_flash_mem_blank_check,
|
||||
.protect_check = &stm32x_protect_check,
|
||||
.info = &stm32x_info,
|
||||
};
|
||||
.name = "stm32x",
|
||||
.commands = stm32x_command_handlers,
|
||||
.flash_bank_command = stm32x_flash_bank_command,
|
||||
.erase = stm32x_erase,
|
||||
.protect = stm32x_protect,
|
||||
.write = stm32x_write,
|
||||
.probe = stm32x_probe,
|
||||
.auto_probe = stm32x_auto_probe,
|
||||
.erase_check = default_flash_mem_blank_check,
|
||||
.protect_check = stm32x_protect_check,
|
||||
.info = stm32x_info,
|
||||
};
|
||||
|
||||
@@ -93,7 +93,10 @@ static int str7x_build_block_list(struct flash_bank *bank)
|
||||
bank->sectors[num_sectors].offset = mem_layout_str7bank0[i].sector_start;
|
||||
bank->sectors[num_sectors].size = mem_layout_str7bank0[i].sector_size;
|
||||
bank->sectors[num_sectors].is_erased = -1;
|
||||
bank->sectors[num_sectors].is_protected = 1;
|
||||
/* the reset_init handler marks all the sectors unprotected,
|
||||
* matching hardware after reset; keep the driver in sync
|
||||
*/
|
||||
bank->sectors[num_sectors].is_protected = 0;
|
||||
str7x_info->sector_bits[num_sectors++] = mem_layout_str7bank0[i].sector_bit;
|
||||
}
|
||||
|
||||
@@ -102,7 +105,10 @@ static int str7x_build_block_list(struct flash_bank *bank)
|
||||
bank->sectors[num_sectors].offset = mem_layout_str7bank1[i].sector_start;
|
||||
bank->sectors[num_sectors].size = mem_layout_str7bank1[i].sector_size;
|
||||
bank->sectors[num_sectors].is_erased = -1;
|
||||
bank->sectors[num_sectors].is_protected = 1;
|
||||
/* the reset_init handler marks all the sectors unprotected,
|
||||
* matching hardware after reset; keep the driver in sync
|
||||
*/
|
||||
bank->sectors[num_sectors].is_protected = 0;
|
||||
str7x_info->sector_bits[num_sectors++] = mem_layout_str7bank1[i].sector_bit;
|
||||
}
|
||||
|
||||
@@ -600,6 +606,12 @@ COMMAND_HANDLER(str7x_handle_part_id_command)
|
||||
static int str7x_info(struct flash_bank *bank, char *buf, int buf_size)
|
||||
{
|
||||
snprintf(buf, buf_size, "str7x flash driver info");
|
||||
/* STR7x flash doesn't support sector protection interrogation.
|
||||
* FLASH_NVWPAR acts as a write only register; its read value
|
||||
* doesn't reflect the actual protection state of the sectors.
|
||||
*/
|
||||
LOG_WARNING("STR7x flash lock information might not be correct "
|
||||
"due to hardware limitations.");
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
@@ -676,7 +688,7 @@ COMMAND_HANDLER(str7x_handle_disable_jtag_command)
|
||||
static const struct command_registration str7x_exec_command_handlers[] = {
|
||||
{
|
||||
.name = "disable_jtag",
|
||||
.handler = &str7x_handle_disable_jtag_command,
|
||||
.handler = str7x_handle_disable_jtag_command,
|
||||
.mode = COMMAND_EXEC,
|
||||
.help = "disable jtag access",
|
||||
},
|
||||
@@ -693,15 +705,15 @@ static const struct command_registration str7x_command_handlers[] = {
|
||||
};
|
||||
|
||||
struct flash_driver str7x_flash = {
|
||||
.name = "str7x",
|
||||
.commands = str7x_command_handlers,
|
||||
.flash_bank_command = &str7x_flash_bank_command,
|
||||
.erase = &str7x_erase,
|
||||
.protect = &str7x_protect,
|
||||
.write = &str7x_write,
|
||||
.probe = &str7x_probe,
|
||||
.auto_probe = &str7x_probe,
|
||||
.erase_check = &default_flash_blank_check,
|
||||
.protect_check = &str7x_protect_check,
|
||||
.info = &str7x_info,
|
||||
};
|
||||
.name = "str7x",
|
||||
.commands = str7x_command_handlers,
|
||||
.flash_bank_command = str7x_flash_bank_command,
|
||||
.erase = str7x_erase,
|
||||
.protect = str7x_protect,
|
||||
.write = str7x_write,
|
||||
.probe = str7x_probe,
|
||||
.auto_probe = str7x_probe,
|
||||
.erase_check = default_flash_blank_check,
|
||||
.protect_check = str7x_protect_check,
|
||||
.info = str7x_info,
|
||||
};
|
||||
|
||||
@@ -230,17 +230,9 @@ static int str9x_erase(struct flash_bank *bank, int first, int last)
|
||||
return ERROR_TARGET_NOT_HALTED;
|
||||
}
|
||||
|
||||
/* Check if we erase whole bank */
|
||||
if ((first == 0) && (last == (bank->num_sectors - 1)))
|
||||
{
|
||||
/* Optimize to run erase bank command instead of sector */
|
||||
erase_cmd = 0x80;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Erase sector command */
|
||||
erase_cmd = 0x20;
|
||||
}
|
||||
/*A slower but stable way of erasing*/
|
||||
/* Erase sector command */
|
||||
erase_cmd = 0x20;
|
||||
|
||||
for (i = first; i <= last; i++)
|
||||
{
|
||||
@@ -296,10 +288,6 @@ static int str9x_erase(struct flash_bank *bank, int first, int last)
|
||||
LOG_ERROR("error erasing flash bank, status: 0x%x", status);
|
||||
return ERROR_FLASH_OPERATION_FAILED;
|
||||
}
|
||||
|
||||
/* If we ran erase bank command, we are finished */
|
||||
if (erase_cmd == 0x80)
|
||||
break;
|
||||
}
|
||||
|
||||
for (i = first; i <= last; i++)
|
||||
@@ -679,11 +667,12 @@ COMMAND_HANDLER(str9x_handle_flash_config_command)
|
||||
|
||||
static const struct command_registration str9x_config_command_handlers[] = {
|
||||
{
|
||||
.name = "disable_jtag",
|
||||
.handler = &str9x_handle_flash_config_command,
|
||||
.name = "flash_config",
|
||||
.handler = str9x_handle_flash_config_command,
|
||||
.mode = COMMAND_EXEC,
|
||||
.help = "configure str9x flash controller",
|
||||
.usage = "<bank_id> <BBSR> <NBBSR> <BBADR> <NBBADR>",
|
||||
.help = "Configure str9x flash controller, prior to "
|
||||
"programming the flash.",
|
||||
.usage = "bank_id BBSR NBBSR BBADR NBBADR",
|
||||
},
|
||||
COMMAND_REGISTRATION_DONE
|
||||
};
|
||||
@@ -698,15 +687,15 @@ static const struct command_registration str9x_command_handlers[] = {
|
||||
};
|
||||
|
||||
struct flash_driver str9x_flash = {
|
||||
.name = "str9x",
|
||||
.commands = str9x_command_handlers,
|
||||
.flash_bank_command = &str9x_flash_bank_command,
|
||||
.erase = &str9x_erase,
|
||||
.protect = &str9x_protect,
|
||||
.write = &str9x_write,
|
||||
.probe = &str9x_probe,
|
||||
.auto_probe = &str9x_probe,
|
||||
.erase_check = &default_flash_blank_check,
|
||||
.protect_check = &str9x_protect_check,
|
||||
.info = &str9x_info,
|
||||
};
|
||||
.name = "str9x",
|
||||
.commands = str9x_command_handlers,
|
||||
.flash_bank_command = str9x_flash_bank_command,
|
||||
.erase = str9x_erase,
|
||||
.protect = str9x_protect,
|
||||
.write = str9x_write,
|
||||
.probe = str9x_probe,
|
||||
.auto_probe = str9x_probe,
|
||||
.erase_check = default_flash_blank_check,
|
||||
.protect_check = str9x_protect_check,
|
||||
.info = str9x_info,
|
||||
};
|
||||
|
||||
@@ -915,6 +915,10 @@ COMMAND_HANDLER(str9xpec_handle_flash_options_write_command)
|
||||
if ((status & ISC_STATUS_ERROR) != STR9XPEC_ISC_SUCCESS)
|
||||
return ERROR_FLASH_OPERATION_FAILED;
|
||||
|
||||
command_print(CMD_CTX, "str9xpec write options complete.\n"
|
||||
"INFO: a reset or power cycle is required "
|
||||
"for the new settings to take effect.");
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
@@ -1077,6 +1081,10 @@ COMMAND_HANDLER(str9xpec_handle_flash_unlock_command)
|
||||
if ((status & ISC_STATUS_ERROR) != STR9XPEC_ISC_SUCCESS)
|
||||
return ERROR_FLASH_OPERATION_FAILED;
|
||||
|
||||
command_print(CMD_CTX, "str9xpec unlocked.\n"
|
||||
"INFO: a reset or power cycle is required "
|
||||
"for the new settings to take effect.");
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
@@ -1244,15 +1252,15 @@ static const struct command_registration str9xpec_command_handlers[] = {
|
||||
};
|
||||
|
||||
struct flash_driver str9xpec_flash = {
|
||||
.name = "str9xpec",
|
||||
.commands = str9xpec_command_handlers,
|
||||
.flash_bank_command = &str9xpec_flash_bank_command,
|
||||
.erase = &str9xpec_erase,
|
||||
.protect = &str9xpec_protect,
|
||||
.write = &str9xpec_write,
|
||||
.probe = &str9xpec_probe,
|
||||
.auto_probe = &str9xpec_probe,
|
||||
.erase_check = &str9xpec_erase_check,
|
||||
.protect_check = &str9xpec_protect_check,
|
||||
.info = &str9xpec_info,
|
||||
};
|
||||
.name = "str9xpec",
|
||||
.commands = str9xpec_command_handlers,
|
||||
.flash_bank_command = str9xpec_flash_bank_command,
|
||||
.erase = str9xpec_erase,
|
||||
.protect = str9xpec_protect,
|
||||
.write = str9xpec_write,
|
||||
.probe = str9xpec_probe,
|
||||
.auto_probe = str9xpec_probe,
|
||||
.erase_check = str9xpec_erase_check,
|
||||
.protect_check = str9xpec_protect_check,
|
||||
.info = str9xpec_info,
|
||||
};
|
||||
|
||||
@@ -26,6 +26,11 @@
|
||||
#include <helper/time_support.h>
|
||||
#include <target/image.h>
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Implements Tcl commands used to access NOR flash facilities.
|
||||
*/
|
||||
|
||||
COMMAND_HELPER(flash_command_get_bank, unsigned name_index,
|
||||
struct flash_bank **bank)
|
||||
{
|
||||
@@ -198,14 +203,29 @@ COMMAND_HANDLER(handle_flash_erase_address_command)
|
||||
int retval;
|
||||
int address;
|
||||
int length;
|
||||
|
||||
bool do_pad = false;
|
||||
struct target *target = get_current_target(CMD_CTX);
|
||||
|
||||
if (CMD_ARGC != 2)
|
||||
switch (CMD_ARGC) {
|
||||
case 3:
|
||||
/* Optionally pad out the address range to block/sector
|
||||
* boundaries. We can't know if there's data in that part
|
||||
* of the flash; only do padding if we're told to.
|
||||
*/
|
||||
if (strcmp("pad", CMD_ARGV[0]) != 0)
|
||||
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||
do_pad = true;
|
||||
CMD_ARGC--;
|
||||
CMD_ARGV++;
|
||||
/* FALL THROUGH */
|
||||
case 2:
|
||||
COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], address);
|
||||
COMMAND_PARSE_NUMBER(int, CMD_ARGV[1], length);
|
||||
break;
|
||||
default:
|
||||
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||
}
|
||||
|
||||
COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], address);
|
||||
COMMAND_PARSE_NUMBER(int, CMD_ARGV[1], length);
|
||||
if (length <= 0)
|
||||
{
|
||||
command_print(CMD_CTX, "Length must be >0");
|
||||
@@ -224,7 +244,7 @@ COMMAND_HANDLER(handle_flash_erase_address_command)
|
||||
struct duration bench;
|
||||
duration_start(&bench);
|
||||
|
||||
retval = flash_erase_address_range(target, address, length);
|
||||
retval = flash_erase_address_range(target, do_pad, address, length);
|
||||
|
||||
if ((ERROR_OK == retval) && (duration_measure(&bench) == ERROR_OK))
|
||||
{
|
||||
@@ -439,7 +459,7 @@ COMMAND_HANDLER(handle_flash_write_image_command)
|
||||
|
||||
if ((ERROR_OK == retval) && (duration_measure(&bench) == ERROR_OK))
|
||||
{
|
||||
command_print(CMD_CTX, "wrote %" PRIu32 " byte from file %s "
|
||||
command_print(CMD_CTX, "wrote %" PRIu32 " bytes from file %s "
|
||||
"in %fs (%0.3f kb/s)", written, CMD_ARGV[0],
|
||||
duration_elapsed(&bench), duration_kbps(&bench, written));
|
||||
}
|
||||
@@ -625,9 +645,9 @@ COMMAND_HANDLER(handle_flash_write_bank_command)
|
||||
|
||||
if ((ERROR_OK == retval) && (duration_measure(&bench) == ERROR_OK))
|
||||
{
|
||||
command_print(CMD_CTX, "wrote %zu byte from file %s to flash bank %u"
|
||||
command_print(CMD_CTX, "wrote %ld bytes from file %s to flash bank %u"
|
||||
" at offset 0x%8.8" PRIx32 " in %fs (%0.3f kb/s)",
|
||||
fileio.size, CMD_ARGV[1], p->bank_number, offset,
|
||||
(long)fileio.size, CMD_ARGV[1], p->bank_number, offset,
|
||||
duration_elapsed(&bench), duration_kbps(&bench, fileio.size));
|
||||
}
|
||||
|
||||
@@ -654,89 +674,102 @@ void flash_set_dirty(void)
|
||||
static const struct command_registration flash_exec_command_handlers[] = {
|
||||
{
|
||||
.name = "probe",
|
||||
.handler = &handle_flash_probe_command,
|
||||
.handler = handle_flash_probe_command,
|
||||
.mode = COMMAND_EXEC,
|
||||
.usage = "<bank>",
|
||||
.help = "identify flash bank",
|
||||
.usage = "bank_id",
|
||||
.help = "Identify a flash bank.",
|
||||
},
|
||||
{
|
||||
.name = "info",
|
||||
.handler = &handle_flash_info_command,
|
||||
.handler = handle_flash_info_command,
|
||||
.mode = COMMAND_EXEC,
|
||||
.usage = "<bank>",
|
||||
.help = "print bank information",
|
||||
.usage = "bank_id",
|
||||
.help = "Print information about a flash bank.",
|
||||
},
|
||||
{
|
||||
.name = "erase_check",
|
||||
.handler = &handle_flash_erase_check_command,
|
||||
.handler = handle_flash_erase_check_command,
|
||||
.mode = COMMAND_EXEC,
|
||||
.usage = "<bank>",
|
||||
.help = "check erase state of sectors",
|
||||
.usage = "bank_id",
|
||||
.help = "Check erase state of all blocks in a "
|
||||
"flash bank.",
|
||||
},
|
||||
{
|
||||
.name = "protect_check",
|
||||
.handler = &handle_flash_protect_check_command,
|
||||
.handler = handle_flash_protect_check_command,
|
||||
.mode = COMMAND_EXEC,
|
||||
.usage = "<bank>",
|
||||
.help = "check protection state of sectors",
|
||||
.usage = "bank_id",
|
||||
.help = "Check protection state of all blocks in a "
|
||||
"flash bank.",
|
||||
},
|
||||
{
|
||||
.name = "erase_sector",
|
||||
.handler = &handle_flash_erase_command,
|
||||
.handler = handle_flash_erase_command,
|
||||
.mode = COMMAND_EXEC,
|
||||
.usage = "<bank> <first> <last>",
|
||||
.help = "erase sectors",
|
||||
.usage = "bank_id first_sector_num last_sector_num",
|
||||
.help = "Erase a range of sectors in a flash bank.",
|
||||
},
|
||||
{
|
||||
.name = "erase_address",
|
||||
.handler = &handle_flash_erase_address_command,
|
||||
.handler = handle_flash_erase_address_command,
|
||||
.mode = COMMAND_EXEC,
|
||||
.usage = "<address> <length>",
|
||||
.help = "erase address range",
|
||||
|
||||
.usage = "['pad'] address length",
|
||||
.help = "Erase flash sectors starting at address and "
|
||||
"continuing for length bytes. If 'pad' is specified, "
|
||||
"data outside that range may also be erased: the start "
|
||||
"address may be decreased, and length increased, so "
|
||||
"that all of the first and last sectors are erased.",
|
||||
},
|
||||
{
|
||||
.name = "fillw",
|
||||
.handler = &handle_flash_fill_command,
|
||||
.handler = handle_flash_fill_command,
|
||||
.mode = COMMAND_EXEC,
|
||||
.usage = "<address> <word_pattern> <count>",
|
||||
.help = "fill with pattern (no autoerase)",
|
||||
.usage = "address value n",
|
||||
.help = "Fill n words with 32-bit value, starting at "
|
||||
"word address. (No autoerase.)",
|
||||
},
|
||||
{
|
||||
.name = "fillh",
|
||||
.handler = &handle_flash_fill_command,
|
||||
.handler = handle_flash_fill_command,
|
||||
.mode = COMMAND_EXEC,
|
||||
.usage = "<address> <halfword_pattern> <count>",
|
||||
.help = "fill with pattern",
|
||||
.usage = "address value n",
|
||||
.help = "Fill n halfwords with 16-bit value, starting at "
|
||||
"word address. (No autoerase.)",
|
||||
},
|
||||
{
|
||||
.name = "fillb",
|
||||
.handler = &handle_flash_fill_command,
|
||||
.handler = handle_flash_fill_command,
|
||||
.mode = COMMAND_EXEC,
|
||||
.usage = "<address> <byte_pattern> <count>",
|
||||
.help = "fill with pattern",
|
||||
|
||||
.usage = "address value n",
|
||||
.help = "Fill n bytes with 8-bit value, starting at "
|
||||
"word address. (No autoerase.)",
|
||||
},
|
||||
{
|
||||
.name = "write_bank",
|
||||
.handler = &handle_flash_write_bank_command,
|
||||
.handler = handle_flash_write_bank_command,
|
||||
.mode = COMMAND_EXEC,
|
||||
.usage = "<bank> <file> <offset>",
|
||||
.help = "write binary data",
|
||||
.usage = "bank_id filename offset",
|
||||
.help = "Write binary data from file to flash bank, "
|
||||
"starting at specified byte offset from the "
|
||||
"beginning of the bank.",
|
||||
},
|
||||
{
|
||||
.name = "write_image",
|
||||
.handler = &handle_flash_write_image_command,
|
||||
.handler = handle_flash_write_image_command,
|
||||
.mode = COMMAND_EXEC,
|
||||
.usage = "[erase] [unlock] <file> [offset] [type]",
|
||||
.help = "write an image to flash"
|
||||
.usage = "[erase] [unlock] filename [offset [file_type]]",
|
||||
.help = "Write an image to flash. Optionally first unprotect "
|
||||
"and/or erase the region to be used. Allow optional "
|
||||
"offset from beginning of bank (defaults to zero)",
|
||||
},
|
||||
{
|
||||
.name = "protect",
|
||||
.handler = &handle_flash_protect_command,
|
||||
.handler = handle_flash_protect_command,
|
||||
.mode = COMMAND_EXEC,
|
||||
.usage = "<bank> <first> <last> <on | off>",
|
||||
.help = "set protection of sectors",
|
||||
.usage = "bank_id first_sector [last_sector|'last'] "
|
||||
"('on'|'off')",
|
||||
.help = "Turn protection on or off for a range of sectors "
|
||||
"in a given flash bank.",
|
||||
},
|
||||
COMMAND_REGISTRATION_DONE
|
||||
};
|
||||
@@ -891,10 +924,10 @@ COMMAND_HANDLER(handle_flash_init_command)
|
||||
static const struct command_registration flash_config_command_handlers[] = {
|
||||
{
|
||||
.name = "bank",
|
||||
.handler = &handle_flash_bank_command,
|
||||
.handler = handle_flash_bank_command,
|
||||
.mode = COMMAND_CONFIG,
|
||||
.usage = "<name> <driver> <base> <size> "
|
||||
"<chip_width> <bus_width> <target> "
|
||||
.usage = "bank_id driver_name base_address size_bytes "
|
||||
"chip_width_bytes bus_width_bytes target "
|
||||
"[driver_options ...]",
|
||||
.help = "Define a new bank with the given name, "
|
||||
"using the specified NOR flash driver.",
|
||||
@@ -902,20 +935,20 @@ static const struct command_registration flash_config_command_handlers[] = {
|
||||
{
|
||||
.name = "init",
|
||||
.mode = COMMAND_CONFIG,
|
||||
.handler = &handle_flash_init_command,
|
||||
.help = "initialize flash devices",
|
||||
.handler = handle_flash_init_command,
|
||||
.help = "Initialize flash devices.",
|
||||
},
|
||||
{
|
||||
.name = "banks",
|
||||
.mode = COMMAND_ANY,
|
||||
.handler = &handle_flash_banks_command,
|
||||
.help = "return readable information about the flash banks",
|
||||
.handler = handle_flash_banks_command,
|
||||
.help = "Display table with information about flash banks.",
|
||||
},
|
||||
{
|
||||
.name = "list",
|
||||
.mode = COMMAND_ANY,
|
||||
.jim_handler = &jim_flash_list,
|
||||
.help = "returns a list of details about the flash banks",
|
||||
.jim_handler = jim_flash_list,
|
||||
.help = "Returns a list of details about the flash banks.",
|
||||
},
|
||||
COMMAND_REGISTRATION_DONE
|
||||
};
|
||||
|
||||
@@ -821,19 +821,19 @@ static int tms470_erase_sector(struct flash_bank *bank, int sector)
|
||||
static const struct command_registration tms470_any_command_handlers[] = {
|
||||
{
|
||||
.name = "flash_keyset",
|
||||
.handler = &tms470_handle_flash_keyset_command,
|
||||
.handler = tms470_handle_flash_keyset_command,
|
||||
.mode = COMMAND_ANY,
|
||||
.help = "tms470 flash_keyset <key0> <key1> <key2> <key3>",
|
||||
},
|
||||
{
|
||||
.name = "osc_megahertz",
|
||||
.handler = &tms470_handle_osc_megahertz_command,
|
||||
.handler = tms470_handle_osc_megahertz_command,
|
||||
.mode = COMMAND_ANY,
|
||||
.help = "tms470 osc_megahertz <MHz>",
|
||||
},
|
||||
{
|
||||
.name = "plldis",
|
||||
.handler = &tms470_handle_plldis_command,
|
||||
.handler = tms470_handle_plldis_command,
|
||||
.mode = COMMAND_ANY,
|
||||
.help = "tms470 plldis <0/1>",
|
||||
},
|
||||
@@ -1258,15 +1258,15 @@ FLASH_BANK_COMMAND_HANDLER(tms470_flash_bank_command)
|
||||
}
|
||||
|
||||
struct flash_driver tms470_flash = {
|
||||
.name = "tms470",
|
||||
.commands = tms470_command_handlers,
|
||||
.flash_bank_command = &tms470_flash_bank_command,
|
||||
.erase = &tms470_erase,
|
||||
.protect = &tms470_protect,
|
||||
.write = &tms470_write,
|
||||
.probe = &tms470_probe,
|
||||
.auto_probe = &tms470_auto_probe,
|
||||
.erase_check = &tms470_erase_check,
|
||||
.protect_check = &tms470_protect_check,
|
||||
.info = &tms470_info,
|
||||
};
|
||||
.name = "tms470",
|
||||
.commands = tms470_command_handlers,
|
||||
.flash_bank_command = tms470_flash_bank_command,
|
||||
.erase = tms470_erase,
|
||||
.protect = tms470_protect,
|
||||
.write = tms470_write,
|
||||
.probe = tms470_probe,
|
||||
.auto_probe = tms470_auto_probe,
|
||||
.erase_check = tms470_erase_check,
|
||||
.protect_check = tms470_protect_check,
|
||||
.info = tms470_info,
|
||||
};
|
||||
|
||||
@@ -58,14 +58,14 @@ static const struct command_registration foo_command_handlers[] = {
|
||||
.name = "bar",
|
||||
.handler = &handle_foo_command,
|
||||
.mode = COMMAND_ANY,
|
||||
.usage = "<address> [enable|disable]",
|
||||
.usage = "address ['enable'|'disable']",
|
||||
.help = "an example command",
|
||||
},
|
||||
{
|
||||
.name = "baz",
|
||||
.handler = &handle_foo_command,
|
||||
.mode = COMMAND_ANY,
|
||||
.usage = "<address> [enable|disable]",
|
||||
.usage = "address ['enable'|'disable']",
|
||||
.help = "a sample command",
|
||||
},
|
||||
{
|
||||
@@ -107,10 +107,10 @@ COMMAND_HANDLER(handle_hello_command)
|
||||
const struct command_registration hello_command_handlers[] = {
|
||||
{
|
||||
.name = "hello",
|
||||
.handler = &handle_hello_command,
|
||||
.handler = handle_hello_command,
|
||||
.mode = COMMAND_ANY,
|
||||
.help = "prints a warm welcome",
|
||||
.usage = "[<name>]",
|
||||
.usage = "[name]",
|
||||
},
|
||||
{
|
||||
.name = "foo",
|
||||
|
||||
@@ -108,10 +108,15 @@ static int command_retval_set(Jim_Interp *interp, int retval)
|
||||
|
||||
extern struct command_context *global_cmd_ctx;
|
||||
|
||||
/* dump a single line to the log for the command.
|
||||
* Do nothing in case we are not at debug level 3 */
|
||||
void script_debug(Jim_Interp *interp, const char *name,
|
||||
unsigned argc, Jim_Obj *const *argv)
|
||||
{
|
||||
LOG_DEBUG("command - %s", name);
|
||||
if (debug_level < LOG_LVL_DEBUG)
|
||||
return;
|
||||
|
||||
char * dbg = alloc_printf("command - %s", name);
|
||||
for (unsigned i = 0; i < argc; i++)
|
||||
{
|
||||
int len;
|
||||
@@ -121,8 +126,12 @@ void script_debug(Jim_Interp *interp, const char *name,
|
||||
if (*w == '#')
|
||||
break;
|
||||
|
||||
LOG_DEBUG("%s - argv[%d]=%s", name, i, w);
|
||||
char * t = alloc_printf("%s %s", dbg, w);
|
||||
free (dbg);
|
||||
dbg = t;
|
||||
}
|
||||
LOG_DEBUG("%s", dbg);
|
||||
free(dbg);
|
||||
}
|
||||
|
||||
static void script_command_args_free(const char **words, unsigned nwords)
|
||||
@@ -349,7 +358,7 @@ static int register_command_handler(struct command_context *cmd_ctx,
|
||||
if (NULL == override_name)
|
||||
return JIM_ERR;
|
||||
|
||||
retval = Jim_Eval_Named(interp, override_name, __FILE__, __LINE__);
|
||||
retval = Jim_Eval_Named(interp, override_name, __THIS__FILE__ , __LINE__);
|
||||
free((void *)override_name);
|
||||
|
||||
return retval;
|
||||
@@ -366,7 +375,10 @@ struct command* register_command(struct command_context *context,
|
||||
struct command *c = command_find(*head, name);
|
||||
if (NULL != c)
|
||||
{
|
||||
LOG_ERROR("command '%s' is already registered in '%s' context",
|
||||
/* TODO: originally we treated attempting to register a cmd twice as an error
|
||||
* Sometimes we need this behaviour, such as with flash banks.
|
||||
* http://www.mail-archive.com/openocd-development@lists.berlios.de/msg11152.html */
|
||||
LOG_DEBUG("command '%s' is already registered in '%s' context",
|
||||
name, parent ? parent->name : "<global>");
|
||||
return c;
|
||||
}
|
||||
@@ -580,6 +592,7 @@ static int run_command(struct command_context *context,
|
||||
|
||||
struct command_invocation cmd = {
|
||||
.ctx = context,
|
||||
.current = c,
|
||||
.name = c->name,
|
||||
.argc = num_words - 1,
|
||||
.argv = words + 1,
|
||||
@@ -913,7 +926,7 @@ static COMMAND_HELPER(command_help_show, struct command *c, unsigned n,
|
||||
bool is_match = (strstr(cmd_name, match) != NULL) ||
|
||||
((c->usage != NULL) && (strstr(c->usage, match) != NULL)) ||
|
||||
((c->help != NULL) && (strstr(c->help, match) != NULL));
|
||||
|
||||
|
||||
if (is_match)
|
||||
{
|
||||
command_help_show_indent(n);
|
||||
@@ -933,15 +946,27 @@ static COMMAND_HELPER(command_help_show, struct command *c, unsigned n,
|
||||
|
||||
if (is_match && show_help)
|
||||
{
|
||||
const char *stage_msg;
|
||||
switch (c->mode) {
|
||||
case COMMAND_CONFIG: stage_msg = "CONFIG"; break;
|
||||
case COMMAND_EXEC: stage_msg = "EXEC"; break;
|
||||
case COMMAND_ANY: stage_msg = "CONFIG or EXEC"; break;
|
||||
default: stage_msg = "***UNKNOWN***"; break;
|
||||
}
|
||||
char *msg = alloc_printf("%s%sValid Modes: %s",
|
||||
c->help ? : "", c->help ? " " : "", stage_msg);
|
||||
char *msg;
|
||||
|
||||
/* Normal commands are runtime-only; highlight exceptions */
|
||||
if (c->mode != COMMAND_EXEC) {
|
||||
const char *stage_msg = "";
|
||||
|
||||
switch (c->mode) {
|
||||
case COMMAND_CONFIG:
|
||||
stage_msg = " (configuration command)";
|
||||
break;
|
||||
case COMMAND_ANY:
|
||||
stage_msg = " (command valid any time)";
|
||||
break;
|
||||
default:
|
||||
stage_msg = " (?mode error?)";
|
||||
break;
|
||||
}
|
||||
msg = alloc_printf("%s%s", c->help ? : "", stage_msg);
|
||||
} else
|
||||
msg = alloc_printf("%s", c->help ? : "");
|
||||
|
||||
if (NULL != msg)
|
||||
{
|
||||
command_help_show_wrap(msg, n + 3, n + 3);
|
||||
@@ -959,18 +984,45 @@ static COMMAND_HELPER(command_help_show, struct command *c, unsigned n,
|
||||
COMMAND_HANDLER(handle_help_command)
|
||||
{
|
||||
bool full = strcmp(CMD_NAME, "help") == 0;
|
||||
|
||||
int retval;
|
||||
struct command *c = CMD_CTX->commands;
|
||||
char *match = NULL;
|
||||
|
||||
const char *match = "";
|
||||
if (CMD_ARGC == 0)
|
||||
match = "";
|
||||
else if (CMD_ARGC == 1)
|
||||
match = CMD_ARGV[0];
|
||||
else
|
||||
else if (CMD_ARGC >= 1) {
|
||||
unsigned i;
|
||||
|
||||
for (i = 0; i < CMD_ARGC; ++i) {
|
||||
if (NULL != match) {
|
||||
char *prev = match;
|
||||
|
||||
match = alloc_printf("%s %s", match,
|
||||
CMD_ARGV[i]);
|
||||
free(prev);
|
||||
if (NULL == match) {
|
||||
LOG_ERROR("unable to build "
|
||||
"search string");
|
||||
return -ENOMEM;
|
||||
}
|
||||
} else {
|
||||
match = alloc_printf("%s", CMD_ARGV[i]);
|
||||
if (NULL == match) {
|
||||
LOG_ERROR("unable to build "
|
||||
"search string");
|
||||
return -ENOMEM;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else
|
||||
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||
|
||||
return CALL_COMMAND_HANDLER(command_help_show_list, c, 0, full, match);
|
||||
|
||||
retval = CALL_COMMAND_HANDLER(command_help_show_list,
|
||||
c, 0, full, match);
|
||||
|
||||
if (CMD_ARGC >= 1)
|
||||
free(match);
|
||||
return retval;
|
||||
}
|
||||
|
||||
static int command_unknown_find(unsigned argc, Jim_Obj *const *argv,
|
||||
@@ -1047,6 +1099,7 @@ static int jim_command_mode(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
|
||||
{
|
||||
struct command_context *cmd_ctx = current_command_context(interp);
|
||||
enum command_mode mode;
|
||||
|
||||
if (argc > 1)
|
||||
{
|
||||
struct command *c = cmd_ctx->commands;
|
||||
@@ -1183,7 +1236,7 @@ COMMAND_HANDLER(handle_help_add_command)
|
||||
return help_add_command(CMD_CTX, c, cmd_name, help, usage);
|
||||
}
|
||||
|
||||
/* sleep command sleeps for <n> miliseconds
|
||||
/* sleep command sleeps for <n> milliseconds
|
||||
* this is useful in target startup scripts
|
||||
*/
|
||||
COMMAND_HANDLER(handle_sleep_command)
|
||||
@@ -1223,19 +1276,22 @@ static const struct command_registration command_subcommand_handlers[] = {
|
||||
{
|
||||
.name = "mode",
|
||||
.mode = COMMAND_ANY,
|
||||
.jim_handler = &jim_command_mode,
|
||||
.usage = "[<name> ...]",
|
||||
.jim_handler = jim_command_mode,
|
||||
.usage = "[command_name ...]",
|
||||
.help = "Returns the command modes allowed by a command:"
|
||||
"'any', 'config', or 'exec'. If no command is"
|
||||
"specified, returns the current command mode.",
|
||||
"specified, returns the current command mode. "
|
||||
"Returns 'unknown' if an unknown command is given. "
|
||||
"Command can be multiple tokens.",
|
||||
},
|
||||
{
|
||||
.name = "type",
|
||||
.mode = COMMAND_ANY,
|
||||
.jim_handler = &jim_command_type,
|
||||
.usage = "<name> ...",
|
||||
.jim_handler = jim_command_type,
|
||||
.usage = "command_name [...]",
|
||||
.help = "Returns the type of built-in command:"
|
||||
"'native', 'simple', 'group', or 'unknown'",
|
||||
"'native', 'simple', 'group', or 'unknown'. "
|
||||
"Command can be multiple tokens.",
|
||||
},
|
||||
COMMAND_REGISTRATION_DONE
|
||||
};
|
||||
@@ -1243,39 +1299,43 @@ static const struct command_registration command_subcommand_handlers[] = {
|
||||
static const struct command_registration command_builtin_handlers[] = {
|
||||
{
|
||||
.name = "add_help_text",
|
||||
.handler = &handle_help_add_command,
|
||||
.handler = handle_help_add_command,
|
||||
.mode = COMMAND_ANY,
|
||||
.help = "add new command help text",
|
||||
.usage = "<command> [...] <help_text>]",
|
||||
.help = "Add new command help text; "
|
||||
"Command can be multiple tokens.",
|
||||
.usage = "command_name helptext_string",
|
||||
},
|
||||
{
|
||||
.name = "add_usage_text",
|
||||
.handler = &handle_help_add_command,
|
||||
.handler = handle_help_add_command,
|
||||
.mode = COMMAND_ANY,
|
||||
.help = "add new command usage text",
|
||||
.usage = "<command> [...] <usage_text>]",
|
||||
.help = "Add new command usage text; "
|
||||
"command can be multiple tokens.",
|
||||
.usage = "command_name usage_string",
|
||||
},
|
||||
{
|
||||
.name = "sleep",
|
||||
.handler = &handle_sleep_command,
|
||||
.handler = handle_sleep_command,
|
||||
.mode = COMMAND_ANY,
|
||||
.help = "sleep for n milliseconds. "
|
||||
"\"busy\" will busy wait",
|
||||
.usage = "<n> [busy]",
|
||||
.help = "Sleep for specified number of milliseconds. "
|
||||
"\"busy\" will busy wait instead (avoid this).",
|
||||
.usage = "milliseconds ['busy']",
|
||||
},
|
||||
{
|
||||
.name = "help",
|
||||
.handler = &handle_help_command,
|
||||
.handler = handle_help_command,
|
||||
.mode = COMMAND_ANY,
|
||||
.help = "show full command help",
|
||||
.usage = "[<command> ...]",
|
||||
.help = "Show full command help; "
|
||||
"command can be multiple tokens.",
|
||||
.usage = "[command_name]",
|
||||
},
|
||||
{
|
||||
.name = "usage",
|
||||
.handler = &handle_help_command,
|
||||
.handler = handle_help_command,
|
||||
.mode = COMMAND_ANY,
|
||||
.help = "show basic command usage",
|
||||
.usage = "[<command> ...]",
|
||||
.help = "Show basic command usage; "
|
||||
"command can be multiple tokens.",
|
||||
.usage = "[command_name]",
|
||||
},
|
||||
{
|
||||
.name = "command",
|
||||
@@ -1310,6 +1370,7 @@ struct command_context* command_init(const char *startup_tcl, Jim_Interp *interp
|
||||
#endif
|
||||
context->interp = interp;
|
||||
|
||||
/* Stick to lowercase for HostOS strings. */
|
||||
#if defined(_MSC_VER)
|
||||
/* WinXX - is generic, the forward
|
||||
* looking problem is this:
|
||||
@@ -1321,7 +1382,7 @@ struct command_context* command_init(const char *startup_tcl, Jim_Interp *interp
|
||||
HostOs = "winxx";
|
||||
#elif defined(__linux__)
|
||||
HostOs = "linux";
|
||||
#elif defined(__DARWIN__)
|
||||
#elif defined(__APPLE__) || defined(__DARWIN__)
|
||||
HostOs = "darwin";
|
||||
#elif defined(__CYGWIN__)
|
||||
HostOs = "cygwin";
|
||||
@@ -1329,8 +1390,10 @@ struct command_context* command_init(const char *startup_tcl, Jim_Interp *interp
|
||||
HostOs = "mingw32";
|
||||
#elif defined(__ECOS)
|
||||
HostOs = "ecos";
|
||||
#elif defined(__FreeBSD__)
|
||||
HostOs = "freebsd";
|
||||
#else
|
||||
#warn unrecognized host OS...
|
||||
#warning "Unrecognized host OS..."
|
||||
HostOs = "other";
|
||||
#endif
|
||||
Jim_SetGlobalVariableStr(interp, "ocd_HOSTOS",
|
||||
|
||||
@@ -115,8 +115,10 @@ int parse_config_file(struct command_context *cmd_ctx)
|
||||
int retval;
|
||||
char **cfg;
|
||||
|
||||
if (!config_file_names)
|
||||
add_config_command ("script openocd.cfg");
|
||||
if (!config_file_names) {
|
||||
command_run_line(cmd_ctx, "script openocd.cfg");
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
cfg = config_file_names;
|
||||
|
||||
|
||||
@@ -191,6 +191,7 @@ COMMAND_HANDLER(handle_append_command)
|
||||
|
||||
int retval = ERROR_FAIL;
|
||||
FILE *config_file = NULL;
|
||||
|
||||
config_file = fopen(CMD_ARGV[0], "a");
|
||||
if (config_file != NULL)
|
||||
{
|
||||
@@ -199,7 +200,8 @@ COMMAND_HANDLER(handle_append_command)
|
||||
unsigned i;
|
||||
for (i = 1; i < CMD_ARGC; i++)
|
||||
{
|
||||
if (fwrite(CMD_ARGV[i], 1, strlen(CMD_ARGV[i]), config_file) != strlen(CMD_ARGV[i]))
|
||||
if (fwrite(CMD_ARGV[i], 1, strlen(CMD_ARGV[i]),
|
||||
config_file) != strlen(CMD_ARGV[i]))
|
||||
break;
|
||||
if (i != CMD_ARGC - 1)
|
||||
{
|
||||
@@ -208,9 +210,8 @@ COMMAND_HANDLER(handle_append_command)
|
||||
}
|
||||
}
|
||||
if ((i == CMD_ARGC) && (fwrite("\n", 1, 1, config_file) == 1))
|
||||
{
|
||||
retval = ERROR_OK;
|
||||
}
|
||||
|
||||
fclose(config_file);
|
||||
}
|
||||
|
||||
@@ -619,76 +620,86 @@ static int zylinjtag_Jim_Command_mac(Jim_Interp *interp, int argc,
|
||||
static const struct command_registration ioutil_command_handlers[] = {
|
||||
{
|
||||
.name = "cat",
|
||||
.handler = &handle_cat_command,
|
||||
.handler = handle_cat_command,
|
||||
.mode = COMMAND_ANY,
|
||||
.help = "display file content",
|
||||
.usage= "<file_name>",
|
||||
.help = "display text file content",
|
||||
.usage= "file_name",
|
||||
},
|
||||
{
|
||||
.name = "trunc",
|
||||
.handler = &handle_trunc_command,
|
||||
.handler = handle_trunc_command,
|
||||
.mode = COMMAND_ANY,
|
||||
.help = "truncate a file 0 size",
|
||||
.usage= "<file_name>",
|
||||
.help = "truncate a file to zero length",
|
||||
.usage= "file_name",
|
||||
},
|
||||
{
|
||||
.name = "cp",
|
||||
.handler = &handle_cp_command,
|
||||
.handler = handle_cp_command,
|
||||
.mode = COMMAND_ANY,
|
||||
.help = "copy a file",
|
||||
.usage = "<src> <dst>",
|
||||
.usage = "src_file_name dst_file_name",
|
||||
},
|
||||
{
|
||||
.name = "append_file",
|
||||
.handler = &handle_append_command,
|
||||
.handler = handle_append_command,
|
||||
.mode = COMMAND_ANY,
|
||||
.help = "append a variable number of strings to a file",
|
||||
.usage= "<file_name> [<string> ...]",
|
||||
.usage= "file_name [string ...]",
|
||||
},
|
||||
{
|
||||
.name = "meminfo",
|
||||
.handler = &handle_meminfo_command,
|
||||
.handler = handle_meminfo_command,
|
||||
.mode = COMMAND_ANY,
|
||||
.help = "display available ram memory",
|
||||
.help = "display free heap space",
|
||||
},
|
||||
{
|
||||
.name = "rm",
|
||||
.mode = COMMAND_ANY,
|
||||
.handler = &handle_rm_command,
|
||||
.help = "remove a file",
|
||||
.usage = "<file>",
|
||||
.handler = handle_rm_command,
|
||||
.help = "remove a directory or file",
|
||||
.usage = "file_name",
|
||||
},
|
||||
|
||||
/*
|
||||
* REVISIT shouldn't most, or all, these zylinjtag_*()
|
||||
* entries be #ifdef ZY1000? If not, why so they have
|
||||
* those names?
|
||||
*
|
||||
* Peek and poke are security holes -- they manipulate
|
||||
* server-internal addresses.
|
||||
*/
|
||||
|
||||
// jim handlers
|
||||
{
|
||||
.name = "peek",
|
||||
.mode = COMMAND_ANY,
|
||||
.jim_handler = &zylinjtag_Jim_Command_peek,
|
||||
.jim_handler = zylinjtag_Jim_Command_peek,
|
||||
.help = "peek at a memory address",
|
||||
.usage = "<addr>",
|
||||
.usage = "address",
|
||||
},
|
||||
{
|
||||
.name = "poke",
|
||||
.mode = COMMAND_ANY,
|
||||
.jim_handler = &zylinjtag_Jim_Command_poke,
|
||||
.jim_handler = zylinjtag_Jim_Command_poke,
|
||||
.help = "poke at a memory address",
|
||||
.usage = "<addr> <value>",
|
||||
.usage = "address value",
|
||||
},
|
||||
{
|
||||
.name = "ls",
|
||||
.mode = COMMAND_ANY,
|
||||
.jim_handler = &zylinjtag_Jim_Command_ls,
|
||||
.jim_handler = zylinjtag_Jim_Command_ls,
|
||||
.help = "show a listing of files",
|
||||
.usage = "<dir>",
|
||||
.usage = "dirname",
|
||||
},
|
||||
{
|
||||
.name = "mac",
|
||||
.mode = COMMAND_ANY,
|
||||
.jim_handler = &zylinjtag_Jim_Command_mac,
|
||||
.jim_handler = zylinjtag_Jim_Command_mac,
|
||||
.help = "show MAC address",
|
||||
},
|
||||
{
|
||||
.name = "ip",
|
||||
.jim_handler = &zylinjtag_Jim_Command_ip,
|
||||
.jim_handler = zylinjtag_Jim_Command_ip,
|
||||
.mode = COMMAND_ANY,
|
||||
.help = "show IP address",
|
||||
},
|
||||
|
||||
@@ -2217,7 +2217,7 @@ static Jim_Obj *JimStringToLower(Jim_Interp *interp, Jim_Obj *strObjPtr)
|
||||
|
||||
memcpy(buf, strObjPtr->bytes, strObjPtr->length + 1);
|
||||
for (i = 0; i < strObjPtr->length; i++)
|
||||
buf[i] = tolower(buf[i]);
|
||||
buf[i] = tolower((unsigned)buf[i]);
|
||||
return Jim_NewStringObjNoAlloc(interp, buf, strObjPtr->length);
|
||||
}
|
||||
|
||||
@@ -2233,7 +2233,7 @@ static Jim_Obj *JimStringToUpper(Jim_Interp *interp, Jim_Obj *strObjPtr)
|
||||
|
||||
memcpy(buf, strObjPtr->bytes, strObjPtr->length + 1);
|
||||
for (i = 0; i < strObjPtr->length; i++)
|
||||
buf[i] = toupper(buf[i]);
|
||||
buf[i] = toupper((unsigned)buf[i]);
|
||||
return Jim_NewStringObjNoAlloc(interp, buf, strObjPtr->length);
|
||||
}
|
||||
|
||||
@@ -2347,7 +2347,7 @@ static Jim_Obj *Jim_FormatString_Inner(Jim_Interp *interp, Jim_Obj *fmtObjPtr,
|
||||
case '8':
|
||||
case '9':
|
||||
accum = 0;
|
||||
while (isdigit(*fmt) && (fmtLen > 0)) {
|
||||
while (isdigit((unsigned)*fmt) && (fmtLen > 0)) {
|
||||
accum = (accum * 10) + (*fmt - '0');
|
||||
fmt++; fmtLen--;
|
||||
}
|
||||
|
||||
@@ -286,13 +286,16 @@ COMMAND_HANDLER(handle_debug_level_command)
|
||||
|
||||
if (debug_level >= LOG_LVL_DEBUG && server_use_pipes == 1)
|
||||
{
|
||||
/* if we are enabling debug info then we need to write to a log file
|
||||
* otherwise the pipe will get full and cause issues with gdb */
|
||||
/* if we are enabling debug info then we need to write to a
|
||||
* log file otherwise the pipe will get full and cause issues
|
||||
* with gdb
|
||||
*/
|
||||
FILE* file = fopen("openocd.log", "w");
|
||||
if (file)
|
||||
{
|
||||
log_output = file;
|
||||
LOG_WARNING("enabling log output as we are using pipes");
|
||||
LOG_WARNING("enabling logfile output because "
|
||||
"we are using pipes to talk to GDB.");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -319,17 +322,19 @@ COMMAND_HANDLER(handle_log_output_command)
|
||||
static struct command_registration log_command_handlers[] = {
|
||||
{
|
||||
.name = "log_output",
|
||||
.handler = &handle_log_output_command,
|
||||
.handler = handle_log_output_command,
|
||||
.mode = COMMAND_ANY,
|
||||
.help = "redirect logging to a file (default: stderr)",
|
||||
.usage = "<file_name>",
|
||||
.usage = "file_name",
|
||||
},
|
||||
{
|
||||
.name = "debug_level",
|
||||
.handler = &handle_debug_level_command,
|
||||
.handler = handle_debug_level_command,
|
||||
.mode = COMMAND_ANY,
|
||||
.help = "sets the verbosity level of debugging output",
|
||||
.usage = "<level:0-3>",
|
||||
.help = "Sets the verbosity level of debugging output. "
|
||||
"0 shows errors only; 1 adds warnings; "
|
||||
"2 (default) adds other info; 3 adds debugging.",
|
||||
.usage = "number",
|
||||
},
|
||||
COMMAND_REGISTRATION_DONE
|
||||
};
|
||||
|
||||
@@ -111,7 +111,12 @@ extern int debug_level;
|
||||
#define LOG_LEVEL_IS(FOO) ((debug_level) >= (FOO))
|
||||
|
||||
#define LOG_DEBUG(expr ...) \
|
||||
((debug_level >= LOG_LVL_DEBUG) ? log_printf_lf (LOG_LVL_DEBUG, __FILE__, __LINE__, __FUNCTION__, expr) , 0 : 0)
|
||||
do { \
|
||||
if (debug_level >= LOG_LVL_DEBUG) \
|
||||
log_printf_lf(LOG_LVL_DEBUG, \
|
||||
__FILE__, __LINE__, __func__, \
|
||||
expr); \
|
||||
} while (0)
|
||||
|
||||
#define LOG_INFO(expr ...) \
|
||||
log_printf_lf (LOG_LVL_INFO, __FILE__, __LINE__, __FUNCTION__, expr)
|
||||
|
||||
@@ -74,21 +74,21 @@ static void add_default_dirs(void)
|
||||
add_script_search_dir(strExePath);
|
||||
}
|
||||
/*
|
||||
* Add support for the default (as of 20080121) layout when
|
||||
* using autotools and cygwin to build native MinGW binary.
|
||||
* Add support for the default (as of 20091118) layout when
|
||||
* using autotools and cygwin/MinGW to build native binary.
|
||||
* Path separator is converted to UNIX style so that MinGW is
|
||||
* pleased.
|
||||
*
|
||||
* bin/openocd.exe
|
||||
* lib/openocd/event/at91eb40a_reset.cfg
|
||||
* lib/openocd/target/at91eb40a.cfg
|
||||
* share/openocd/scripts/interface/dummy.cfg
|
||||
* share/openocd/scripts/target/at91eb40a.cfg
|
||||
*/
|
||||
{
|
||||
char strExePath [MAX_PATH];
|
||||
char *p;
|
||||
GetModuleFileName (NULL, strExePath, MAX_PATH);
|
||||
*strrchr(strExePath, '\\') = 0;
|
||||
strcat(strExePath, "/../lib/"PACKAGE);
|
||||
strcat(strExePath, "/../share/"PACKAGE"/scripts");
|
||||
for (p = strExePath; *p; p++) {
|
||||
if (*p == '\\')
|
||||
*p = '/';
|
||||
|
||||
@@ -40,6 +40,12 @@
|
||||
#define ENOTSUP 134 /* Not supported */
|
||||
#endif
|
||||
|
||||
/* for systems that do not support O_BINARY
|
||||
* linux being one of them */
|
||||
#ifndef O_BINARY
|
||||
#define O_BINARY 0
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_SYS_TIME_H
|
||||
|
||||
#ifndef _TIMEVAL_DEFINED
|
||||
|
||||
@@ -50,6 +50,8 @@
|
||||
#ifdef _WIN32
|
||||
#include <winsock2.h>
|
||||
#include <ws2tcpip.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#endif
|
||||
// --- platform specific headers ---
|
||||
|
||||
@@ -83,4 +85,9 @@
|
||||
#include <fcntl.h>
|
||||
#endif
|
||||
|
||||
#ifndef true
|
||||
#define true 1
|
||||
#define false 0
|
||||
#endif
|
||||
|
||||
#endif // SYSTEM_H
|
||||
|
||||
@@ -172,6 +172,7 @@ static inline void h_u16_to_be(uint8_t* buf, int val)
|
||||
#define SCNx32 "x"
|
||||
#define PRIi32 "i"
|
||||
#define PRIu32 "u"
|
||||
#define PRId8 PRId32
|
||||
|
||||
typedef CYG_ADDRWORD intptr_t;
|
||||
typedef int64_t intmax_t;
|
||||
|
||||
@@ -530,10 +530,12 @@ int jtag_add_statemove(tap_state_t goal_state)
|
||||
{
|
||||
tap_state_t cur_state = cmd_queue_cur_state;
|
||||
|
||||
LOG_DEBUG("cur_state=%s goal_state=%s",
|
||||
tap_state_name(cur_state),
|
||||
tap_state_name(goal_state));
|
||||
|
||||
if (goal_state != cur_state)
|
||||
{
|
||||
LOG_DEBUG("cur_state=%s goal_state=%s",
|
||||
tap_state_name(cur_state),
|
||||
tap_state_name(goal_state));
|
||||
}
|
||||
|
||||
/* If goal is RESET, be paranoid and force that that transition
|
||||
* (e.g. five TCK cycles, TMS high). Else trust "cur_state".
|
||||
@@ -1621,6 +1623,13 @@ bool jtag_will_verify_capture_ir()
|
||||
|
||||
int jtag_power_dropout(int *dropout)
|
||||
{
|
||||
if (jtag == NULL)
|
||||
{
|
||||
/* TODO: as the jtag interface is not valid all
|
||||
* we can do at the moment is exit OpenOCD */
|
||||
LOG_ERROR("No Valid JTAG Interface Configured.");
|
||||
exit(-1);
|
||||
}
|
||||
return jtag->power_dropout(dropout);
|
||||
}
|
||||
|
||||
|
||||
@@ -28,6 +28,9 @@ endif
|
||||
if FT2232_DRIVER
|
||||
DRIVERFILES += ft2232.c
|
||||
endif
|
||||
if USB_BLASTER_DRIVER
|
||||
DRIVERFILES += usb_blaster.c
|
||||
endif
|
||||
if AMTJTAGACCEL
|
||||
DRIVERFILES += amt_jtagaccel.c
|
||||
endif
|
||||
|
||||
@@ -22,8 +22,6 @@
|
||||
#endif
|
||||
|
||||
#include <jtag/interface.h>
|
||||
#include <jtag/commands.h>
|
||||
|
||||
|
||||
#if PARPORT_USE_PPDEV == 1
|
||||
#include <linux/parport.h>
|
||||
@@ -41,6 +39,15 @@
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Support the Amontec Chameleon POD with JTAG Accelerator support.
|
||||
* This is a parallel port JTAG adapter with a CPLD between the
|
||||
* parallel port and the JTAG connection. VHDL code running in the
|
||||
* CPLD significantly accelerates JTAG operations compared to the
|
||||
* bitbanging "Wiggler" style of most parallel port adapters.
|
||||
*/
|
||||
|
||||
/* configuration */
|
||||
static uint16_t amt_jtagaccel_port;
|
||||
|
||||
@@ -55,13 +62,41 @@ static int rtck_enabled = 0;
|
||||
#if PARPORT_USE_PPDEV == 1
|
||||
static int device_handle;
|
||||
|
||||
static int addr_mode = IEEE1284_MODE_EPP | IEEE1284_ADDR ;
|
||||
#define AMT_AW(val) do { ioctl(device_handle, PPSETMODE, &addr_mode); write(device_handle, &val, 1); } while (0)
|
||||
#define AMT_AR(val) do { ioctl(device_handle, PPSETMODE, &addr_mode); read(device_handle, &val, 1); } while (0)
|
||||
static const int addr_mode = IEEE1284_MODE_EPP | IEEE1284_ADDR;
|
||||
|
||||
static int data_mode = IEEE1284_MODE_EPP | IEEE1284_DATA ;
|
||||
#define AMT_DW(val) do { ioctl(device_handle, PPSETMODE, &data_mode); write(device_handle, &val, 1); } while (0)
|
||||
#define AMT_DR(val) do { ioctl(device_handle, PPSETMODE, &data_mode); read(device_handle, &val, 1); } while (0)
|
||||
/* FIXME do something sane when these ioctl/read/write calls fail. */
|
||||
|
||||
#define AMT_AW(val) \
|
||||
do { \
|
||||
int __retval; \
|
||||
\
|
||||
__retval = ioctl(device_handle, PPSETMODE, &addr_mode); \
|
||||
__retval = write(device_handle, &val, 1); \
|
||||
} while (0)
|
||||
#define AMT_AR(val) \
|
||||
do { \
|
||||
int __retval; \
|
||||
\
|
||||
__retval = ioctl(device_handle, PPSETMODE, &addr_mode); \
|
||||
__retval = read(device_handle, &val, 1); \
|
||||
} while (0)
|
||||
|
||||
static const int data_mode = IEEE1284_MODE_EPP | IEEE1284_DATA;
|
||||
|
||||
#define AMT_DW(val) \
|
||||
do { \
|
||||
int __retval; \
|
||||
\
|
||||
__retval = ioctl(device_handle, PPSETMODE, &data_mode); \
|
||||
__retval = write(device_handle, &val, 1); \
|
||||
} while (0)
|
||||
#define AMT_DR(val) \
|
||||
do { \
|
||||
int __retval; \
|
||||
\
|
||||
__retval = ioctl(device_handle, PPSETMODE, &data_mode); \
|
||||
__retval = read(device_handle, &val, 1); \
|
||||
} while (0)
|
||||
|
||||
#else
|
||||
|
||||
@@ -545,24 +580,31 @@ static const struct command_registration amtjtagaccel_command_handlers[] = {
|
||||
.name = "parport_port",
|
||||
.handler = &amt_jtagaccel_handle_parport_port_command,
|
||||
.mode = COMMAND_CONFIG,
|
||||
.help = "configure the parallel port to use",
|
||||
.usage = "<port_num>",
|
||||
.help = "configure or display the parallel port to use",
|
||||
.usage = "[port_num]",
|
||||
},
|
||||
{
|
||||
.name = "parport_port",
|
||||
/**
|
||||
* @todo Remove this "rtck" command; just use the standard
|
||||
* mechanism to enable/disable adaptive clocking. First
|
||||
* implement the standard mechanism and deprecate "rtck";
|
||||
* after a year or so, it'll be safe to remove this.
|
||||
*/
|
||||
.name = "rtck",
|
||||
.handler = &amt_jtagaccel_handle_rtck_command,
|
||||
.mode = COMMAND_CONFIG,
|
||||
.help = "enable RTCK",
|
||||
.usage = "<enable|disable>",
|
||||
.help = "configure or display RTCK support",
|
||||
.usage = "[enable|disable]",
|
||||
},
|
||||
COMMAND_REGISTRATION_DONE
|
||||
};
|
||||
|
||||
struct jtag_interface amt_jtagaccel_interface = {
|
||||
.name = "amt_jtagaccel",
|
||||
.commands = amtjtagaccel_command_handlers,
|
||||
.init = &amt_jtagaccel_init,
|
||||
.quit = &amt_jtagaccel_quit,
|
||||
.speed = &amt_jtagaccel_speed,
|
||||
.execute_queue = &amt_jtagaccel_execute_queue,
|
||||
};
|
||||
.name = "amt_jtagaccel",
|
||||
.commands = amtjtagaccel_command_handlers,
|
||||
|
||||
.init = amt_jtagaccel_init,
|
||||
.quit = amt_jtagaccel_quit,
|
||||
.speed = amt_jtagaccel_speed,
|
||||
.execute_queue = amt_jtagaccel_execute_queue,
|
||||
};
|
||||
|
||||
@@ -513,17 +513,15 @@ static const struct command_registration armjtagew_command_handlers[] = {
|
||||
};
|
||||
|
||||
struct jtag_interface armjtagew_interface = {
|
||||
.name = "arm-jtag-ew",
|
||||
.name = "arm-jtag-ew",
|
||||
.commands = armjtagew_command_handlers,
|
||||
|
||||
.commands = armjtagew_command_handlers,
|
||||
|
||||
.execute_queue = &armjtagew_execute_queue,
|
||||
.speed = &armjtagew_speed,
|
||||
.khz = &armjtagew_khz,
|
||||
|
||||
.init = &armjtagew_init,
|
||||
.quit = &armjtagew_quit,
|
||||
};
|
||||
.execute_queue = armjtagew_execute_queue,
|
||||
.speed = armjtagew_speed,
|
||||
.khz = armjtagew_khz,
|
||||
.init = armjtagew_init,
|
||||
.quit = armjtagew_quit,
|
||||
};
|
||||
|
||||
/***************************************************************************/
|
||||
/* ARM-JTAG-EW tap functions */
|
||||
|
||||
@@ -215,7 +215,10 @@ int interface_jtag_add_dr_scan(int in_num_fields, const struct scan_field *in_fi
|
||||
|
||||
if (!tap->bypass)
|
||||
{
|
||||
struct scan_field * start_field = field; /* keep initial position for assert() */
|
||||
#ifndef NDEBUG
|
||||
/* remember initial position for assert() */
|
||||
struct scan_field *start_field = field;
|
||||
#endif /* NDEBUG */
|
||||
|
||||
for (int j = 0; j < in_num_fields; j++)
|
||||
{
|
||||
|
||||
@@ -27,13 +27,40 @@
|
||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||
***************************************************************************/
|
||||
|
||||
/* This code uses information contained in the MPSSE specification which was
|
||||
/**
|
||||
* @file
|
||||
* JTAG adapters based on the FT2232 full and high speed USB parts are
|
||||
* popular low cost JTAG debug solutions. Many FT2232 based JTAG adapters
|
||||
* are discrete, but development boards may integrate them as alternatives
|
||||
* to more capable (and expensive) third party JTAG pods. Since JTAG uses
|
||||
* only one of the two ports on these devices, on integrated boards the
|
||||
* second port often serves as a USB-to-serial adapter for the target's
|
||||
* console UART even when the JTAG port is not in use. (Systems which
|
||||
* support ARM's SWD in addition to JTAG, or instead of it, may use that
|
||||
* second port for reading SWV trace data.)
|
||||
*
|
||||
* FT2232 based JTAG adapters are "dumb" not "smart", because most JTAG
|
||||
* request/response interactions involve round trips over the USB link.
|
||||
* A "smart" JTAG adapter has intelligence close to the scan chain, so it
|
||||
* can for example poll quickly for a status change (usually taking on the
|
||||
* order of microseconds not milliseconds) before beginning a queued
|
||||
* transaction which require the previous one to have completed.
|
||||
*
|
||||
* There are dozens of adapters of this type, differing in details which
|
||||
* this driver needs to understand. Those "layout" details are required
|
||||
* as part of FT2232 driver configuration.
|
||||
*
|
||||
* This code uses information contained in the MPSSE specification which was
|
||||
* found here:
|
||||
* http://www.ftdichip.com/Documents/AppNotes/AN2232C-01_MPSSE_Cmnd.pdf
|
||||
* Hereafter this is called the "MPSSE Spec".
|
||||
*
|
||||
* The datasheet for the ftdichip.com's FT2232D part is here:
|
||||
* http://www.ftdichip.com/Documents/DataSheets/DS_FT2232D.pdf
|
||||
*
|
||||
* Also note the issue with code 0x4b (clock data to TMS) noted in
|
||||
* http://developer.intra2net.com/mailarchive/html/libftdi/2009/msg00292.html
|
||||
* which can affect longer JTAG state paths.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
@@ -42,7 +69,6 @@
|
||||
|
||||
/* project specific includes */
|
||||
#include <jtag/interface.h>
|
||||
#include <jtag/commands.h>
|
||||
#include <helper/time_support.h>
|
||||
|
||||
#if IS_CYGWIN == 1
|
||||
@@ -2182,6 +2208,11 @@ static int usbjtag_init(void)
|
||||
}
|
||||
else if (strcmp(ft2232_layout, "evb_lm3s811") == 0)
|
||||
{
|
||||
/* There are multiple revisions of LM3S811 eval boards:
|
||||
* - Rev B (and older?) boards have no SWO trace support.
|
||||
* - Rev C boards add ADBUS_6 DBG_ENn and BDBUS_4 SWO_EN;
|
||||
* they should use the "luminary_icdi" layout instead.
|
||||
*/
|
||||
nTRST = 0x0;
|
||||
nTRSTnOE = 0x00;
|
||||
nSRST = 0x20;
|
||||
@@ -2191,6 +2222,9 @@ static int usbjtag_init(void)
|
||||
}
|
||||
else if (strcmp(ft2232_layout, "luminary_icdi") == 0)
|
||||
{
|
||||
/* Most Luminary eval boards support SWO trace output,
|
||||
* and should use this "luminary_icdi" layout.
|
||||
*/
|
||||
nTRST = 0x0;
|
||||
nTRSTnOE = 0x00;
|
||||
nSRST = 0x20;
|
||||
@@ -3975,14 +4009,14 @@ static const struct command_registration ft2232_command_handlers[] = {
|
||||
.handler = &ft2232_handle_device_desc_command,
|
||||
.mode = COMMAND_CONFIG,
|
||||
.help = "set the USB device description of the FTDI FT2232 device",
|
||||
.usage = "<description>",
|
||||
.usage = "description_string",
|
||||
},
|
||||
{
|
||||
.name = "ft2232_serial",
|
||||
.handler = &ft2232_handle_serial_command,
|
||||
.mode = COMMAND_CONFIG,
|
||||
.help = "set the serial number of the FTDI FT2232 device",
|
||||
.usage = "<serial#>",
|
||||
.usage = "serial_string",
|
||||
},
|
||||
{
|
||||
.name = "ft2232_layout",
|
||||
@@ -3990,32 +4024,33 @@ static const struct command_registration ft2232_command_handlers[] = {
|
||||
.mode = COMMAND_CONFIG,
|
||||
.help = "set the layout of the FT2232 GPIO signals used "
|
||||
"to control output-enables and reset signals",
|
||||
.usage = "<layout>",
|
||||
.usage = "layout_name",
|
||||
},
|
||||
{
|
||||
.name = "ft2232_vid_pid",
|
||||
.handler = &ft2232_handle_vid_pid_command,
|
||||
.mode = COMMAND_CONFIG,
|
||||
.help = "the vendor ID and product ID of the FTDI FT2232 device",
|
||||
.usage = "<vid> <pid> [...]",
|
||||
.usage = "(vid pid)* ",
|
||||
},
|
||||
{
|
||||
.name = "ft2232_latency",
|
||||
.handler = &ft2232_handle_latency_command,
|
||||
.mode = COMMAND_CONFIG,
|
||||
.help = "set the FT2232 latency timer to a new value",
|
||||
.usage = "<vid> <pid> [...]",
|
||||
.usage = "value",
|
||||
},
|
||||
COMMAND_REGISTRATION_DONE
|
||||
};
|
||||
|
||||
struct jtag_interface ft2232_interface = {
|
||||
.name = "ft2232",
|
||||
.commands = ft2232_command_handlers,
|
||||
.init = &ft2232_init,
|
||||
.quit = &ft2232_quit,
|
||||
.speed = &ft2232_speed,
|
||||
.speed_div = &ft2232_speed_div,
|
||||
.khz = &ft2232_khz,
|
||||
.execute_queue = &ft2232_execute_queue,
|
||||
};
|
||||
.name = "ft2232",
|
||||
.commands = ft2232_command_handlers,
|
||||
|
||||
.init = ft2232_init,
|
||||
.quit = ft2232_quit,
|
||||
.speed = ft2232_speed,
|
||||
.speed_div = ft2232_speed_div,
|
||||
.khz = ft2232_khz,
|
||||
.execute_queue = ft2232_execute_queue,
|
||||
};
|
||||
|
||||
@@ -565,19 +565,22 @@ COMMAND_HANDLER(gw16012_handle_parport_port_command)
|
||||
static const struct command_registration gw16012_command_handlers[] = {
|
||||
{
|
||||
.name = "parport_port",
|
||||
.handler = &gw16012_handle_parport_port_command,
|
||||
.handler = gw16012_handle_parport_port_command,
|
||||
.mode = COMMAND_CONFIG,
|
||||
.help = "configure the parallel port to use",
|
||||
.usage = "<port_num>",
|
||||
.help = "Display the address of the I/O port (e.g. 0x378) "
|
||||
"or the number of the '/dev/parport' device used. "
|
||||
"If a parameter is provided, first change that port.",
|
||||
.usage = "[port_number]",
|
||||
},
|
||||
COMMAND_REGISTRATION_DONE
|
||||
};
|
||||
|
||||
struct jtag_interface gw16012_interface = {
|
||||
.name = "gw16012",
|
||||
.commands = gw16012_command_handlers,
|
||||
.init = &gw16012_init,
|
||||
.quit = &gw16012_quit,
|
||||
.speed = &gw16012_speed,
|
||||
.execute_queue = &gw16012_execute_queue,
|
||||
};
|
||||
.name = "gw16012",
|
||||
.commands = gw16012_command_handlers,
|
||||
|
||||
.init = gw16012_init,
|
||||
.quit = gw16012_quit,
|
||||
.speed = gw16012_speed,
|
||||
.execute_queue = gw16012_execute_queue,
|
||||
};
|
||||
|
||||
@@ -29,6 +29,10 @@
|
||||
#include <jtag/commands.h>
|
||||
#include "usb_common.h"
|
||||
|
||||
/* See Segger's public documentation:
|
||||
* Reference manual for J-Link USB Protocol
|
||||
* Document RM08001-R6 Date: June 16, 2009
|
||||
*/
|
||||
|
||||
#define VID 0x1366
|
||||
#define PID 0x0101
|
||||
@@ -645,18 +649,16 @@ static const struct command_registration jlink_command_handlers[] = {
|
||||
};
|
||||
|
||||
struct jtag_interface jlink_interface = {
|
||||
.name = "jlink",
|
||||
.name = "jlink",
|
||||
.commands = jlink_command_handlers,
|
||||
|
||||
.commands = jlink_command_handlers,
|
||||
|
||||
.execute_queue = &jlink_execute_queue,
|
||||
.speed = &jlink_speed,
|
||||
.speed_div = &jlink_speed_div,
|
||||
.khz = &jlink_khz,
|
||||
|
||||
.init = &jlink_init,
|
||||
.quit = &jlink_quit,
|
||||
};
|
||||
.execute_queue = jlink_execute_queue,
|
||||
.speed = jlink_speed,
|
||||
.speed_div = jlink_speed_div,
|
||||
.khz = jlink_khz,
|
||||
.init = jlink_init,
|
||||
.quit = jlink_quit,
|
||||
};
|
||||
|
||||
/***************************************************************************/
|
||||
/* J-Link tap functions */
|
||||
|
||||
@@ -76,16 +76,15 @@ struct cable {
|
||||
|
||||
static struct cable cables[] =
|
||||
{
|
||||
/* name tdo trst tms tck tdi srst o_inv i_inv init exit led */
|
||||
/* name tdo trst tms tck tdi srst o_inv i_inv init exit led */
|
||||
{ "wiggler", 0x80, 0x10, 0x02, 0x04, 0x08, 0x01, 0x01, 0x80, 0x80, 0x80, 0x00 },
|
||||
{ "wiggler2", 0x80, 0x10, 0x02, 0x04, 0x08, 0x01, 0x01, 0x80, 0x80, 0x00, 0x20 },
|
||||
{ "wiggler_ntrst_inverted",
|
||||
0x80, 0x10, 0x02, 0x04, 0x08, 0x01, 0x11, 0x80, 0x80, 0x80, 0x00 },
|
||||
{ "old_amt_wiggler", 0x80, 0x01, 0x02, 0x04, 0x08, 0x10, 0x11, 0x80, 0x80, 0x80, 0x00 },
|
||||
{ "wiggler_ntrst_inverted", 0x80, 0x10, 0x02, 0x04, 0x08, 0x01, 0x11, 0x80, 0x80, 0x80, 0x00 },
|
||||
{ "old_amt_wiggler", 0x80, 0x01, 0x02, 0x04, 0x08, 0x10, 0x11, 0x80, 0x80, 0x80, 0x00 },
|
||||
{ "arm-jtag", 0x80, 0x01, 0x02, 0x04, 0x08, 0x10, 0x01, 0x80, 0x80, 0x80, 0x00 },
|
||||
{ "chameleon", 0x80, 0x00, 0x04, 0x01, 0x02, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00 },
|
||||
{ "dlc5", 0x10, 0x00, 0x04, 0x02, 0x01, 0x00, 0x00, 0x00, 0x10, 0x10, 0x00 },
|
||||
{ "triton", 0x80, 0x08, 0x04, 0x01, 0x02, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00 },
|
||||
{ "dlc5", 0x10, 0x00, 0x04, 0x02, 0x01, 0x00, 0x00, 0x00, 0x10, 0x10, 0x00 },
|
||||
{ "triton", 0x80, 0x08, 0x04, 0x01, 0x02, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00 },
|
||||
{ "lattice", 0x40, 0x10, 0x04, 0x02, 0x01, 0x08, 0x00, 0x00, 0x18, 0x18, 0x00 },
|
||||
{ "flashlink", 0x20, 0x10, 0x02, 0x01, 0x04, 0x20, 0x30, 0x20, 0x00, 0x00, 0x00 },
|
||||
/* Altium Universal JTAG cable. Set the cable to Xilinx Mode and wire to target as follows:
|
||||
@@ -425,7 +424,7 @@ COMMAND_HANDLER(parport_handle_parport_port_command)
|
||||
}
|
||||
}
|
||||
|
||||
command_print(CMD_CTX, "parport port = %u", parport_port);
|
||||
command_print(CMD_CTX, "parport port = 0x%" PRIx16 "", parport_port);
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
@@ -438,10 +437,13 @@ COMMAND_HANDLER(parport_handle_parport_cable_command)
|
||||
/* only if the cable name wasn't overwritten by cmdline */
|
||||
if (parport_cable == 0)
|
||||
{
|
||||
/* REVISIT first verify that it's listed in cables[] ... */
|
||||
parport_cable = malloc(strlen(CMD_ARGV[0]) + sizeof(char));
|
||||
strcpy(parport_cable, CMD_ARGV[0]);
|
||||
}
|
||||
|
||||
/* REVISIT it's probably worth returning the current value ... */
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
@@ -485,49 +487,49 @@ COMMAND_HANDLER(parport_handle_parport_toggling_time_command)
|
||||
static const struct command_registration parport_command_handlers[] = {
|
||||
{
|
||||
.name = "parport_port",
|
||||
.handler = &parport_handle_parport_port_command,
|
||||
.handler = parport_handle_parport_port_command,
|
||||
.mode = COMMAND_CONFIG,
|
||||
.help = "either the address of the I/O port "
|
||||
"or the number of the '/dev/parport' device",
|
||||
.usage = "[<port|devname>]",
|
||||
.help = "Display the address of the I/O port (e.g. 0x378) "
|
||||
"or the number of the '/dev/parport' device used. "
|
||||
"If a parameter is provided, first change that port.",
|
||||
.usage = "[port_number]",
|
||||
},
|
||||
{
|
||||
.name = "parport_cable",
|
||||
.handler = &parport_handle_parport_cable_command,
|
||||
.handler = parport_handle_parport_cable_command,
|
||||
.mode = COMMAND_CONFIG,
|
||||
.help = "the layout of the parallel port cable "
|
||||
"used to connect to the target",
|
||||
.usage = "[<layout>]",
|
||||
.help = "Set the layout of the parallel port cable "
|
||||
"used to connect to the target.",
|
||||
/* REVISIT there's no way to list layouts we know ... */
|
||||
.usage = "[layout]",
|
||||
},
|
||||
{
|
||||
.name = "parport_write_on_exit",
|
||||
.handler = &parport_handle_write_on_exit_command,
|
||||
.handler = parport_handle_write_on_exit_command,
|
||||
.mode = COMMAND_CONFIG,
|
||||
.help = "configure the parallel driver to write "
|
||||
"a known value to the parallel interface",
|
||||
.usage = "[<on|off>]",
|
||||
.help = "Configure the parallel driver to write "
|
||||
"a known value to the parallel interface on exit.",
|
||||
.usage = "('on'|'off')",
|
||||
},
|
||||
{
|
||||
.name = "parport_toggling_time",
|
||||
.handler = &parport_handle_parport_toggling_time_command,
|
||||
.handler = parport_handle_parport_toggling_time_command,
|
||||
.mode = COMMAND_CONFIG,
|
||||
.help = "time <ns> it takes for the hardware to toggle TCK",
|
||||
.usage = "[<ns>]",
|
||||
.help = "Displays or assigns how many nanoseconds it "
|
||||
"takes for the hardware to toggle TCK.",
|
||||
.usage = "[nanoseconds]",
|
||||
},
|
||||
COMMAND_REGISTRATION_DONE
|
||||
};
|
||||
|
||||
struct jtag_interface parport_interface = {
|
||||
.name = "parport",
|
||||
.name = "parport",
|
||||
.commands = parport_command_handlers,
|
||||
|
||||
.commands = parport_command_handlers,
|
||||
|
||||
.init = &parport_init,
|
||||
.quit = &parport_quit,
|
||||
|
||||
.khz = &parport_khz,
|
||||
.speed_div = &parport_speed_div,
|
||||
.speed = &parport_speed,
|
||||
|
||||
.execute_queue = &bitbang_execute_queue,
|
||||
};
|
||||
.init = parport_init,
|
||||
.quit = parport_quit,
|
||||
.khz = parport_khz,
|
||||
.speed_div = parport_speed_div,
|
||||
.speed = parport_speed,
|
||||
.execute_queue = bitbang_execute_queue,
|
||||
};
|
||||
|
||||
@@ -17,6 +17,12 @@
|
||||
* Free Software Foundation, Inc., *
|
||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||
***************************************************************************/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Holds driver for PRESTO programmer from ASIX.
|
||||
* http://tools.asix.net/prg_presto.htm
|
||||
*/
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
@@ -742,10 +748,10 @@ COMMAND_HANDLER(presto_handle_serial_command)
|
||||
static const struct command_registration presto_command_handlers[] = {
|
||||
{
|
||||
.name = "presto_serial",
|
||||
.handler = &presto_handle_serial_command,
|
||||
.handler = presto_handle_serial_command,
|
||||
.mode = COMMAND_CONFIG,
|
||||
.help = "configure serial port",
|
||||
.usage = "<devname>",
|
||||
.help = "Configure USB serial number of Presto device.",
|
||||
.usage = "serial_string",
|
||||
},
|
||||
COMMAND_REGISTRATION_DONE
|
||||
};
|
||||
@@ -786,15 +792,13 @@ static int presto_jtag_quit(void)
|
||||
}
|
||||
|
||||
struct jtag_interface presto_interface = {
|
||||
.name = "presto",
|
||||
.name = "presto",
|
||||
.commands = presto_command_handlers,
|
||||
|
||||
.commands = presto_command_handlers,
|
||||
|
||||
.execute_queue = &bitq_execute_queue,
|
||||
.speed = &presto_jtag_speed,
|
||||
.khz = &presto_jtag_khz,
|
||||
.speed_div = &presto_jtag_speed_div,
|
||||
|
||||
.init = &presto_jtag_init,
|
||||
.quit = &presto_jtag_quit,
|
||||
};
|
||||
.execute_queue = bitq_execute_queue,
|
||||
.speed = presto_jtag_speed,
|
||||
.khz = presto_jtag_khz,
|
||||
.speed_div = presto_jtag_speed_div,
|
||||
.init = presto_jtag_init,
|
||||
.quit = presto_jtag_quit,
|
||||
};
|
||||
|
||||
589
src/jtag/drivers/usb_blaster.c
Normal file
589
src/jtag/drivers/usb_blaster.c
Normal file
@@ -0,0 +1,589 @@
|
||||
/***************************************************************************
|
||||
* Driver for USB-JTAG, Altera USB-Blaster and compatibles *
|
||||
* Original code from Kolja Waschk's USB-JTAG project *
|
||||
* (http://www.ixo.de/info/usb_jtag/). *
|
||||
* Some updates by Anthony Liu (2006). *
|
||||
* Minor updates and cleanup by Catalin Patulea (2009). *
|
||||
* *
|
||||
* Copyright (C) 2009 Catalin Patulea *
|
||||
* cat@vv.carleton.ca *
|
||||
* *
|
||||
* Copyright (C) 2006 Kolja Waschk *
|
||||
* usbjtag@ixo.de *
|
||||
* *
|
||||
* Based on ft2232.c and bitbang.c, *
|
||||
* Copyright (C) 2004,2006 by Dominic Rath *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation; either version 2 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
* This program is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License *
|
||||
* along with this program; if not, write to the *
|
||||
* Free Software Foundation, Inc., *
|
||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||
***************************************************************************/
|
||||
|
||||
/*
|
||||
* The following information is originally from Kolja Waschk's USB-JTAG,
|
||||
* where it was obtained by reverse engineering an Altera USB-Blaster.
|
||||
* See http://www.ixo.de/info/usb_jtag/ for USB-Blaster block diagram and
|
||||
* usb_jtag-20080705-1200.zip#usb_jtag/host/openocd for protocol.
|
||||
*
|
||||
* The same information is also on the UrJTAG mediawiki, with some additional
|
||||
* notes on bits marked as "unknown" by usb_jtag.
|
||||
* (http://sourceforge.net/apps/mediawiki/urjtag/index.php?
|
||||
* title=Cable_Altera_USB-Blaster)
|
||||
*
|
||||
* USB-JTAG, Altera USB-Blaster and compatibles are typically implemented as
|
||||
* an FTDIChip FT245 followed by a CPLD which handles a two-mode protocol:
|
||||
*
|
||||
* _________
|
||||
* | |
|
||||
* | AT93C46 |
|
||||
* |_________|
|
||||
* __|__________ _________
|
||||
* | | | |
|
||||
* USB__| FTDI 245BM |__| EPM7064 |__JTAG (B_TDO,B_TDI,B_TMS,B_TCK)
|
||||
* |_____________| |_________|
|
||||
* __|__________ _|___________
|
||||
* | | | |
|
||||
* | 6 MHz XTAL | | 24 MHz Osc. |
|
||||
* |_____________| |_____________|
|
||||
*
|
||||
* Protocol details are given in the code below.
|
||||
*
|
||||
* It is also possible to emulate this configuration using a single-chip USB
|
||||
* controller like the Cypress FX2 (again, see usb_jtag for details).
|
||||
*/
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#if IS_CYGWIN == 1
|
||||
#include "windows.h"
|
||||
#undef LOG_ERROR
|
||||
#endif
|
||||
|
||||
/* project specific includes */
|
||||
#include <jtag/interface.h>
|
||||
#include <jtag/commands.h>
|
||||
#include <helper/time_support.h>
|
||||
|
||||
/* system includes */
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "bitbang.h"
|
||||
|
||||
#if (BUILD_USB_BLASTER_FTD2XX == 1 && BUILD_USB_BLASTER_LIBFTDI == 1)
|
||||
#error "BUILD_USB_BLASTER_FTD2XX && BUILD_USB_BLASTER_LIBFTDI "
|
||||
"are mutually exclusive"
|
||||
#elif (BUILD_USB_BLASTER_FTD2XX != 1 && BUILD_USB_BLASTER_LIBFTDI != 1)
|
||||
#error "BUILD_USB_BLASTER_FTD2XX || BUILD_USB_BLASTER_LIBFTDI must be chosen"
|
||||
#endif
|
||||
|
||||
/* USB_BLASTER access library includes */
|
||||
#if BUILD_USB_BLASTER_FTD2XX == 1
|
||||
#include <ftd2xx.h>
|
||||
#elif BUILD_USB_BLASTER_LIBFTDI == 1
|
||||
#include <ftdi.h>
|
||||
#endif
|
||||
|
||||
#include <sys/time.h>
|
||||
#include <time.h>
|
||||
|
||||
static char *usb_blaster_device_desc;
|
||||
static uint16_t usb_blaster_vid = 0x09fb; /* Altera */
|
||||
static uint16_t usb_blaster_pid = 0x6001; /* USB-Blaster */
|
||||
|
||||
/* last output byte in simple bit banging mode */
|
||||
static uint8_t out_value;
|
||||
|
||||
#if BUILD_USB_BLASTER_FTD2XX == 1
|
||||
static FT_HANDLE ftdih;
|
||||
#elif BUILD_USB_BLASTER_LIBFTDI == 1
|
||||
static struct ftdi_context ftdic;
|
||||
#endif
|
||||
|
||||
static int usb_blaster_buf_write(
|
||||
uint8_t *buf, int size, uint32_t *bytes_written)
|
||||
{
|
||||
#if BUILD_USB_BLASTER_FTD2XX == 1
|
||||
FT_STATUS status;
|
||||
DWORD dw_bytes_written;
|
||||
|
||||
#ifdef _DEBUG_JTAG_IO_
|
||||
LOG_DEBUG("usb_blaster_buf_write %02X (%d)\n", buf[0], size);
|
||||
#endif
|
||||
status = FT_Write(ftdih, buf, size, &dw_bytes_written);
|
||||
if (status != FT_OK)
|
||||
{
|
||||
*bytes_written = dw_bytes_written;
|
||||
LOG_ERROR("FT_Write returned: %lu", status);
|
||||
return ERROR_JTAG_DEVICE_ERROR;
|
||||
}
|
||||
*bytes_written = dw_bytes_written;
|
||||
return ERROR_OK;
|
||||
#elif BUILD_USB_BLASTER_LIBFTDI == 1
|
||||
int retval;
|
||||
#ifdef _DEBUG_JTAG_IO_
|
||||
LOG_DEBUG("usb_blaster_buf_write %02X (%d)\n", buf[0], size);
|
||||
#endif
|
||||
retval = ftdi_write_data(&ftdic, buf, size);
|
||||
if (retval < 0)
|
||||
{
|
||||
*bytes_written = 0;
|
||||
LOG_ERROR("ftdi_write_data: %s", ftdi_get_error_string(&ftdic));
|
||||
return ERROR_JTAG_DEVICE_ERROR;
|
||||
}
|
||||
*bytes_written = retval;
|
||||
return ERROR_OK;
|
||||
#endif
|
||||
}
|
||||
|
||||
static int
|
||||
usb_blaster_buf_read(uint8_t *buf, unsigned size, uint32_t *bytes_read)
|
||||
{
|
||||
#if BUILD_USB_BLASTER_FTD2XX == 1
|
||||
DWORD dw_bytes_read;
|
||||
FT_STATUS status;
|
||||
|
||||
status = FT_Read(ftdih, buf, size, &dw_bytes_read);
|
||||
if (status != FT_OK)
|
||||
{
|
||||
*bytes_read = dw_bytes_read;
|
||||
LOG_ERROR("FT_Read returned: %lu", status);
|
||||
return ERROR_JTAG_DEVICE_ERROR;
|
||||
}
|
||||
#ifdef _DEBUG_JTAG_IO_
|
||||
LOG_DEBUG("usb_blaster_buf_read %02X (%lu)\n", buf[0], dw_bytes_read);
|
||||
#endif
|
||||
*bytes_read = dw_bytes_read;
|
||||
return ERROR_OK;
|
||||
|
||||
#elif BUILD_USB_BLASTER_LIBFTDI == 1
|
||||
int retval;
|
||||
int timeout = 100;
|
||||
|
||||
*bytes_read = 0;
|
||||
while ((*bytes_read < size) && timeout--)
|
||||
{
|
||||
retval = ftdi_read_data(&ftdic, buf + *bytes_read,
|
||||
size - *bytes_read);
|
||||
if (retval < 0)
|
||||
{
|
||||
*bytes_read = 0;
|
||||
LOG_ERROR("ftdi_read_data: %s",
|
||||
ftdi_get_error_string(&ftdic));
|
||||
return ERROR_JTAG_DEVICE_ERROR;
|
||||
}
|
||||
*bytes_read += retval;
|
||||
}
|
||||
#ifdef _DEBUG_JTAG_IO_
|
||||
LOG_DEBUG("usb_blaster_buf_read %02X (%d)\n", buf[0], *bytes_read);
|
||||
#endif
|
||||
return ERROR_OK;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* The following code doesn't fully utilize the possibilities of the
|
||||
* USB-Blaster. It writes one byte per JTAG pin state change at a time; it
|
||||
* doesn't even try to buffer data up to the maximum packet size of 64 bytes.
|
||||
*
|
||||
* Actually, the USB-Blaster offers a byte-shift mode to transmit up to 504 data
|
||||
* bits (bidirectional) in a single USB packet. A header byte has to be sent as
|
||||
* the first byte in a packet with the following meaning:
|
||||
*
|
||||
* Bit 7 (0x80): Must be set to indicate byte-shift mode.
|
||||
* Bit 6 (0x40): If set, the USB-Blaster will also read data, not just write.
|
||||
* Bit 5..0: Define the number N of following bytes
|
||||
*
|
||||
* All N following bytes will then be clocked out serially on TDI. If Bit 6 was
|
||||
* set, it will afterwards return N bytes with TDO data read while clocking out
|
||||
* the TDI data. LSB of the first byte after the header byte will appear first
|
||||
* on TDI.
|
||||
*/
|
||||
|
||||
/* Simple bit banging mode:
|
||||
*
|
||||
* Bit 7 (0x80): Must be zero (see byte-shift mode above)
|
||||
* Bit 6 (0x40): If set, you will receive a byte indicating the state of TDO
|
||||
* in return.
|
||||
* Bit 5 (0x20): Output Enable/LED.
|
||||
* Bit 4 (0x10): TDI Output.
|
||||
* Bit 3 (0x08): nCS Output (not used in JTAG mode).
|
||||
* Bit 2 (0x04): nCE Output (not used in JTAG mode).
|
||||
* Bit 1 (0x02): TMS Output.
|
||||
* Bit 0 (0x01): TCK Output.
|
||||
*
|
||||
* For transmitting a single data bit, you need to write two bytes. Up to 64
|
||||
* bytes can be combined in a single USB packet (but this is not done in the
|
||||
* code below). It isn't possible to read a data without transmitting data.
|
||||
*/
|
||||
|
||||
#define TCK (1 << 0)
|
||||
#define TMS (1 << 1)
|
||||
#define NCE (1 << 2)
|
||||
#define NCS (1 << 3)
|
||||
#define TDI (1 << 4)
|
||||
#define LED (1 << 5)
|
||||
#define READ (1 << 6)
|
||||
#define SHMODE (1 << 7)
|
||||
#define OTHERS ((1 << 2) | (1 << 3) | (1 << 5))
|
||||
|
||||
#define READ_TDO (1 << 0)
|
||||
|
||||
static void usb_blaster_write_data(void)
|
||||
{
|
||||
uint32_t bytes_written;
|
||||
usb_blaster_buf_write(&out_value, 1, &bytes_written);
|
||||
}
|
||||
|
||||
static int usb_blaster_read_data(void)
|
||||
{
|
||||
int status;
|
||||
uint8_t buf[1];
|
||||
uint32_t bytes_read;
|
||||
|
||||
out_value |= READ;
|
||||
usb_blaster_write_data();
|
||||
out_value &= ~READ;
|
||||
|
||||
status = usb_blaster_buf_read(buf, 1, &bytes_read);
|
||||
if (status < 0)
|
||||
return 0;
|
||||
|
||||
return !!(buf[0] & READ_TDO);
|
||||
}
|
||||
|
||||
static void usb_blaster_write(int tck, int tms, int tdi)
|
||||
{
|
||||
#ifdef _DEBUG_JTAG_IO_
|
||||
LOG_DEBUG("---- usb_blaster_write(%d,%d,%d)\n", tck, tms, tdi);
|
||||
#endif
|
||||
out_value &= ~(TCK | TMS | TDI);
|
||||
if (tck)
|
||||
out_value |= TCK;
|
||||
if (tms)
|
||||
out_value |= TMS;
|
||||
if (tdi)
|
||||
out_value |= TDI;
|
||||
|
||||
usb_blaster_write_data();
|
||||
}
|
||||
|
||||
static int usb_blaster_speed(int speed)
|
||||
{
|
||||
#if BUILD_USB_BLASTER_FTD2XX == 1
|
||||
LOG_DEBUG("TODO: usb_blaster_speed() isn't implemented for libftd2xx!");
|
||||
#elif BUILD_USB_BLASTER_LIBFTDI == 1
|
||||
LOG_DEBUG("TODO: usb_blaster_speed() isn't optimally implemented!");
|
||||
|
||||
/* TODO: libftdi's ftdi_set_baudrate chokes on high rates, use lowlevel
|
||||
* usb function instead! And additionally allow user to throttle.
|
||||
*/
|
||||
if (ftdi_set_baudrate(&ftdic, 3000000 / 4) < 0)
|
||||
{
|
||||
LOG_ERROR("Can't set baud rate to max: %s",
|
||||
ftdi_get_error_string(&ftdic));
|
||||
return ERROR_JTAG_DEVICE_ERROR;
|
||||
};
|
||||
#endif
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
static void usb_blaster_reset(int trst, int srst)
|
||||
{
|
||||
LOG_DEBUG("TODO: usb_blaster_reset(%d,%d) isn't implemented!",
|
||||
trst, srst);
|
||||
}
|
||||
|
||||
static struct bitbang_interface usb_blaster_bitbang = {
|
||||
.read = usb_blaster_read_data,
|
||||
.write = usb_blaster_write,
|
||||
.reset = usb_blaster_reset,
|
||||
};
|
||||
|
||||
static int usb_blaster_init(void)
|
||||
{
|
||||
uint8_t latency_timer;
|
||||
|
||||
#if BUILD_USB_BLASTER_FTD2XX == 1
|
||||
FT_STATUS status;
|
||||
#endif
|
||||
|
||||
#if BUILD_USB_BLASTER_FTD2XX == 1
|
||||
LOG_DEBUG("'usb_blaster' interface using FTD2XX");
|
||||
#elif BUILD_USB_BLASTER_LIBFTDI == 1
|
||||
LOG_DEBUG("'usb_blaster' interface using libftdi");
|
||||
#endif
|
||||
|
||||
#if BUILD_USB_BLASTER_FTD2XX == 1
|
||||
/* Open by device description */
|
||||
if (usb_blaster_device_desc == NULL)
|
||||
{
|
||||
LOG_WARNING("no usb_blaster device description specified, "
|
||||
"using default 'USB-Blaster'");
|
||||
usb_blaster_device_desc = "USB-Blaster";
|
||||
}
|
||||
|
||||
#if IS_WIN32 == 0
|
||||
/* Add non-standard Vid/Pid to the linux driver */
|
||||
status = FT_SetVIDPID(usb_blaster_vid, usb_blaster_pid);
|
||||
if (status != FT_OK)
|
||||
{
|
||||
LOG_WARNING("couldn't add %4.4x:%4.4x",
|
||||
usb_blaster_vid, usb_blaster_pid);
|
||||
}
|
||||
#endif
|
||||
|
||||
status = FT_OpenEx(usb_blaster_device_desc, FT_OPEN_BY_DESCRIPTION,
|
||||
&ftdih);
|
||||
if (status != FT_OK)
|
||||
{
|
||||
DWORD num_devices;
|
||||
|
||||
LOG_ERROR("unable to open ftdi device: %lu", status);
|
||||
status = FT_ListDevices(&num_devices, NULL,
|
||||
FT_LIST_NUMBER_ONLY);
|
||||
if (status == FT_OK)
|
||||
{
|
||||
char **desc_array = malloc(sizeof(char *)
|
||||
* (num_devices + 1));
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < num_devices; i++)
|
||||
desc_array[i] = malloc(64);
|
||||
desc_array[num_devices] = NULL;
|
||||
|
||||
status = FT_ListDevices(desc_array, &num_devices,
|
||||
FT_LIST_ALL | FT_OPEN_BY_DESCRIPTION);
|
||||
|
||||
if (status == FT_OK)
|
||||
{
|
||||
LOG_ERROR("ListDevices: %lu\n", num_devices);
|
||||
for (i = 0; i < num_devices; i++)
|
||||
LOG_ERROR("%i: %s", i, desc_array[i]);
|
||||
}
|
||||
|
||||
for (i = 0; i < num_devices; i++)
|
||||
free(desc_array[i]);
|
||||
free(desc_array);
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("ListDevices: NONE\n");
|
||||
}
|
||||
return ERROR_JTAG_INIT_FAILED;
|
||||
}
|
||||
|
||||
status = FT_SetLatencyTimer(ftdih, 2);
|
||||
if (status != FT_OK)
|
||||
{
|
||||
LOG_ERROR("unable to set latency timer: %lu", status);
|
||||
return ERROR_JTAG_INIT_FAILED;
|
||||
}
|
||||
|
||||
status = FT_GetLatencyTimer(ftdih, &latency_timer);
|
||||
if (status != FT_OK)
|
||||
{
|
||||
LOG_ERROR("unable to get latency timer: %lu", status);
|
||||
return ERROR_JTAG_INIT_FAILED;
|
||||
}
|
||||
LOG_DEBUG("current latency timer: %i", latency_timer);
|
||||
|
||||
status = FT_SetBitMode(ftdih, 0x00, 0);
|
||||
if (status != FT_OK)
|
||||
{
|
||||
LOG_ERROR("unable to disable bit i/o mode: %lu", status);
|
||||
return ERROR_JTAG_INIT_FAILED;
|
||||
}
|
||||
#elif BUILD_USB_BLASTER_LIBFTDI == 1
|
||||
if (ftdi_init(&ftdic) < 0)
|
||||
return ERROR_JTAG_INIT_FAILED;
|
||||
|
||||
/* context, vendor id, product id */
|
||||
if (ftdi_usb_open(&ftdic, usb_blaster_vid, usb_blaster_pid) < 0)
|
||||
{
|
||||
LOG_ERROR("unable to open ftdi device: %s", ftdic.error_str);
|
||||
return ERROR_JTAG_INIT_FAILED;
|
||||
}
|
||||
|
||||
if (ftdi_usb_reset(&ftdic) < 0)
|
||||
{
|
||||
LOG_ERROR("unable to reset ftdi device");
|
||||
return ERROR_JTAG_INIT_FAILED;
|
||||
}
|
||||
|
||||
if (ftdi_set_latency_timer(&ftdic, 2) < 0)
|
||||
{
|
||||
LOG_ERROR("unable to set latency timer");
|
||||
return ERROR_JTAG_INIT_FAILED;
|
||||
}
|
||||
|
||||
if (ftdi_get_latency_timer(&ftdic, &latency_timer) < 0)
|
||||
{
|
||||
LOG_ERROR("unable to get latency timer");
|
||||
return ERROR_JTAG_INIT_FAILED;
|
||||
}
|
||||
LOG_DEBUG("current latency timer: %u", latency_timer);
|
||||
|
||||
ftdi_disable_bitbang(&ftdic);
|
||||
#endif
|
||||
|
||||
bitbang_interface = &usb_blaster_bitbang;
|
||||
|
||||
usb_blaster_speed(jtag_get_speed());
|
||||
|
||||
#if 0
|
||||
#if BUILD_USB_BLASTER_FTD2XX == 1
|
||||
if ((status = FT_Purge(ftdih, FT_PURGE_RX | FT_PURGE_TX)) != FT_OK)
|
||||
{
|
||||
LOG_ERROR("error purging ftd2xx device: %i", status);
|
||||
return ERROR_JTAG_INIT_FAILED;
|
||||
}
|
||||
#elif BUILD_USB_BLASTER_LIBFTDI == 1
|
||||
if (ftdi_usb_purge_buffers(&ftdic) < 0)
|
||||
{
|
||||
LOG_ERROR("ftdi_purge_buffers: %s", ftdic.error_str);
|
||||
return ERROR_JTAG_INIT_FAILED;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
static int usb_blaster_quit(void)
|
||||
{
|
||||
#if BUILD_USB_BLASTER_FTD2XX == 1
|
||||
FT_STATUS status;
|
||||
|
||||
status = FT_Close(ftdih);
|
||||
#elif BUILD_USB_BLASTER_LIBFTDI == 1
|
||||
ftdi_usb_close(&ftdic);
|
||||
ftdi_deinit(&ftdic);
|
||||
#endif
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
COMMAND_HANDLER(usb_blaster_handle_device_desc_command)
|
||||
{
|
||||
if (CMD_ARGC == 1)
|
||||
usb_blaster_device_desc = strdup(CMD_ARGV[0]);
|
||||
else
|
||||
LOG_ERROR("require exactly one argument to "
|
||||
"usb_blaster_device_desc <description>");
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
COMMAND_HANDLER(usb_blaster_handle_vid_pid_command)
|
||||
{
|
||||
if (CMD_ARGC > 2)
|
||||
{
|
||||
LOG_WARNING("ignoring extra IDs in ft2232_vid_pid "
|
||||
"(maximum is 1 pair)");
|
||||
CMD_ARGC = 2;
|
||||
}
|
||||
if (CMD_ARGC == 2)
|
||||
{
|
||||
COMMAND_PARSE_NUMBER(u16, CMD_ARGV[0], usb_blaster_vid);
|
||||
COMMAND_PARSE_NUMBER(u16, CMD_ARGV[1], usb_blaster_pid);
|
||||
}
|
||||
else
|
||||
LOG_WARNING("incomplete usb_blaster_vid_pid configuration");
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
COMMAND_HANDLER(usb_blaster_handle_pin_command)
|
||||
{
|
||||
if (CMD_ARGC == 2)
|
||||
{
|
||||
const char * const pin_name = CMD_ARGV[0];
|
||||
uint8_t mask;
|
||||
unsigned int state;
|
||||
|
||||
if (!strcmp(pin_name, "pin6"))
|
||||
mask = NCE;
|
||||
else if (!strcmp(pin_name, "pin8"))
|
||||
mask = NCS;
|
||||
else
|
||||
{
|
||||
LOG_ERROR("%s: pin name must be \"pin6\" or \"pin8\"",
|
||||
CMD_NAME);
|
||||
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||
}
|
||||
|
||||
COMMAND_PARSE_NUMBER(uint, CMD_ARGV[1], state);
|
||||
if (state == 0)
|
||||
{
|
||||
out_value &= ~mask;
|
||||
usb_blaster_write_data();
|
||||
}
|
||||
else if (state == 1)
|
||||
{
|
||||
out_value |= mask;
|
||||
usb_blaster_write_data();
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG_ERROR("%s: pin state must be 0 or 1", CMD_NAME);
|
||||
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||
}
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG_ERROR("%s takes exactly two arguments", CMD_NAME);
|
||||
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
static const struct command_registration usb_blaster_command_handlers[] = {
|
||||
{
|
||||
.name = "usb_blaster_device_desc",
|
||||
.handler = usb_blaster_handle_device_desc_command,
|
||||
.mode = COMMAND_CONFIG,
|
||||
.help = "set the USB device description of the USB-Blaster",
|
||||
.usage = "description-string",
|
||||
},
|
||||
{
|
||||
.name = "usb_blaster_vid_pid",
|
||||
.handler = usb_blaster_handle_vid_pid_command,
|
||||
.mode = COMMAND_CONFIG,
|
||||
.help = "the vendor ID and product ID of the USB-Blaster",
|
||||
.usage = "vid pid",
|
||||
},
|
||||
{
|
||||
.name = "usb_blaster",
|
||||
.handler = usb_blaster_handle_pin_command,
|
||||
.mode = COMMAND_ANY,
|
||||
.help = "set pin state for the unused GPIO pins",
|
||||
.usage = "(pin6|pin8) (0|1)",
|
||||
},
|
||||
COMMAND_REGISTRATION_DONE
|
||||
};
|
||||
|
||||
struct jtag_interface usb_blaster_interface = {
|
||||
.name = "usb_blaster",
|
||||
.commands = usb_blaster_command_handlers,
|
||||
|
||||
.execute_queue = bitbang_execute_queue,
|
||||
|
||||
.speed = usb_blaster_speed,
|
||||
.init = usb_blaster_init,
|
||||
.quit = usb_blaster_quit,
|
||||
};
|
||||
@@ -652,9 +652,10 @@ static void usbprog_jtag_tms_send(struct usbprog_jtag *usbprog_jtag)
|
||||
}
|
||||
|
||||
struct jtag_interface usbprog_interface = {
|
||||
.name = "usbprog",
|
||||
.execute_queue = &usbprog_execute_queue,
|
||||
.speed = &usbprog_speed,
|
||||
.init = &usbprog_init,
|
||||
.quit = &usbprog_quit
|
||||
};
|
||||
.name = "usbprog",
|
||||
|
||||
.execute_queue = usbprog_execute_queue,
|
||||
.speed = usbprog_speed,
|
||||
.init = usbprog_init,
|
||||
.quit = usbprog_quit
|
||||
};
|
||||
|
||||
@@ -476,6 +476,17 @@ static int vsllink_init(void)
|
||||
}
|
||||
VSLLINK_USB_TIMEOUT = to_tmp;
|
||||
|
||||
/* Some older firmware versions sometimes fail if the
|
||||
* voltage isn't read first.
|
||||
*/
|
||||
vsllink_simple_command(0x01);
|
||||
result = vsllink_usb_read(vsllink_handle);
|
||||
if (result != 2)
|
||||
LOG_WARNING("Fail to get target voltage");
|
||||
else
|
||||
LOG_INFO("Target runs at %d mV", vsllink_usb_in_buffer[0]
|
||||
+ (vsllink_usb_in_buffer[1] << 8));
|
||||
|
||||
// connect to vsllink
|
||||
vsllink_connect();
|
||||
// initialize function pointers
|
||||
@@ -1891,13 +1902,13 @@ static const struct command_registration vsllink_command_handlers[] = {
|
||||
};
|
||||
|
||||
struct jtag_interface vsllink_interface = {
|
||||
.name = "vsllink",
|
||||
.commands = vsllink_command_handlers,
|
||||
.name = "vsllink",
|
||||
.commands = vsllink_command_handlers,
|
||||
|
||||
.init = &vsllink_init,
|
||||
.quit = &vsllink_quit,
|
||||
.khz = &vsllink_khz,
|
||||
.speed = &vsllink_speed,
|
||||
.speed_div = &vsllink_speed_div,
|
||||
.execute_queue = &vsllink_execute_queue,
|
||||
};
|
||||
.init = vsllink_init,
|
||||
.quit = vsllink_quit,
|
||||
.khz = vsllink_khz,
|
||||
.speed = vsllink_speed,
|
||||
.speed_div = vsllink_speed_div,
|
||||
.execute_queue = vsllink_execute_queue,
|
||||
};
|
||||
|
||||
@@ -58,6 +58,9 @@ extern struct jtag_interface ft2232_interface;
|
||||
#if BUILD_FT2232_LIBFTDI == 1
|
||||
extern struct jtag_interface ft2232_interface;
|
||||
#endif
|
||||
#if BUILD_USB_BLASTER_LIBFTDI == 1 || BUILD_USB_BLASTER_FTD2XX == 1
|
||||
extern struct jtag_interface usb_blaster_interface;
|
||||
#endif
|
||||
#if BUILD_AMTJTAGACCEL == 1
|
||||
extern struct jtag_interface amt_jtagaccel_interface;
|
||||
#endif
|
||||
@@ -115,6 +118,9 @@ struct jtag_interface *jtag_interfaces[] = {
|
||||
#if BUILD_FT2232_LIBFTDI == 1
|
||||
&ft2232_interface,
|
||||
#endif
|
||||
#if BUILD_USB_BLASTER_LIBFTDI == 1 || BUILD_USB_BLASTER_FTD2XX == 1
|
||||
&usb_blaster_interface,
|
||||
#endif
|
||||
#if BUILD_AMTJTAGACCEL == 1
|
||||
&amt_jtagaccel_interface,
|
||||
#endif
|
||||
|
||||
@@ -525,8 +525,8 @@ int jtag_add_statemove(tap_state_t goal_state);
|
||||
* to @a endstate (unless it is also TAP_IDLE).
|
||||
*
|
||||
* @param num_cycles Number of cycles in TAP_IDLE state. This argument
|
||||
* may be 0, in which case this routine will navigate to @a endstate
|
||||
* via TAP_IDLE.
|
||||
* may be 0, in which case this routine will navigate to @a endstate
|
||||
* via TAP_IDLE.
|
||||
* @param endstate The final state.
|
||||
*/
|
||||
void jtag_add_runtest(int num_cycles, tap_state_t endstate);
|
||||
@@ -563,23 +563,22 @@ void jtag_add_reset(int req_tlr_or_trst, int srst);
|
||||
* Set a global variable to \a state if \a state != TAP_INVALID.
|
||||
*
|
||||
* Return the value of the global variable.
|
||||
*
|
||||
**/
|
||||
*/
|
||||
tap_state_t jtag_set_end_state(tap_state_t state);
|
||||
|
||||
/**
|
||||
* Function jtag_get_end_state
|
||||
*
|
||||
* Return the value of the global variable for end state
|
||||
*
|
||||
**/
|
||||
*/
|
||||
tap_state_t jtag_get_end_state(void);
|
||||
|
||||
void jtag_add_sleep(uint32_t us);
|
||||
|
||||
|
||||
/**
|
||||
* Function jtag_add_stable_clocks
|
||||
* Function jtag_add_clocks
|
||||
* first checks that the state in which the clocks are to be issued is
|
||||
* stable, then queues up clock_count clocks for transmission.
|
||||
* stable, then queues up num_cycles clocks for transmission.
|
||||
*/
|
||||
void jtag_add_clocks(int num_cycles);
|
||||
|
||||
|
||||
@@ -30,8 +30,18 @@ proc init_reset { mode } {
|
||||
# documented nor supported except on ZY1000.
|
||||
|
||||
proc power_restore {} {
|
||||
puts "Sensed power restore."
|
||||
puts "Sensed power restore, running reset init and halting GDB."
|
||||
reset init
|
||||
|
||||
# Halt GDB so user can deal with a detected power restore.
|
||||
#
|
||||
# After GDB is halted, then output is no longer forwarded
|
||||
# to the GDB console.
|
||||
set targets [target names]
|
||||
foreach t $targets {
|
||||
# New event script.
|
||||
$t invoke-event arp_halt_gdb
|
||||
}
|
||||
}
|
||||
|
||||
add_help_text power_restore "Overridable procedure run when power restore is detected. Runs 'reset init' by default."
|
||||
@@ -46,9 +56,20 @@ proc power_dropout {} {
|
||||
# documented nor supported except on ZY1000.
|
||||
|
||||
proc srst_deasserted {} {
|
||||
puts "Sensed nSRST deasserted."
|
||||
puts "Sensed nSRST deasserted, running reset init and halting GDB."
|
||||
reset init
|
||||
|
||||
# Halt GDB so user can deal with a detected reset.
|
||||
#
|
||||
# After GDB is halted, then output is no longer forwarded
|
||||
# to the GDB console.
|
||||
set targets [target names]
|
||||
foreach t $targets {
|
||||
# New event script.
|
||||
$t invoke-event arp_halt_gdb
|
||||
}
|
||||
}
|
||||
|
||||
add_help_text srst_deasserted "Overridable procedure run when srst deassert is detected. Runs 'reset init' by default."
|
||||
|
||||
proc srst_asserted {} {
|
||||
|
||||
193
src/jtag/tcl.c
193
src/jtag/tcl.c
@@ -269,26 +269,39 @@ static int Jim_Command_flush_count(Jim_Interp *interp, int argc, Jim_Obj *const
|
||||
return JIM_OK;
|
||||
}
|
||||
|
||||
/* REVISIT Just what about these should "move" ... ?
|
||||
* These registrations, into the main JTAG table?
|
||||
*
|
||||
* There's a minor compatibility issue, these all show up twice;
|
||||
* that's not desirable:
|
||||
* - jtag drscan ... NOT DOCUMENTED!
|
||||
* - drscan ...
|
||||
*
|
||||
* The "irscan" command (for example) doesn't show twice.
|
||||
*/
|
||||
static const struct command_registration jtag_command_handlers_to_move[] = {
|
||||
{
|
||||
.name = "drscan",
|
||||
.mode = COMMAND_EXEC,
|
||||
.jim_handler = &Jim_Command_drscan,
|
||||
.help = "execute DR scan <device> "
|
||||
"<num_bits> <value> <num_bits1> <value2> ...",
|
||||
.jim_handler = Jim_Command_drscan,
|
||||
.help = "Execute Data Register (DR) scan for one TAP. "
|
||||
"Other TAPs must be in BYPASS mode.",
|
||||
.usage = "tap_name [num_bits value]* ['-endstate' state_name]",
|
||||
},
|
||||
{
|
||||
.name = "flush_count",
|
||||
.mode = COMMAND_EXEC,
|
||||
.jim_handler = &Jim_Command_flush_count,
|
||||
.help = "returns number of times the JTAG queue has been flushed",
|
||||
.jim_handler = Jim_Command_flush_count,
|
||||
.help = "Returns the number of times the JTAG queue "
|
||||
"has been flushed.",
|
||||
},
|
||||
{
|
||||
.name = "pathmove",
|
||||
.mode = COMMAND_EXEC,
|
||||
.jim_handler = &Jim_Command_pathmove,
|
||||
.usage = "<state1>,<state2>,<state3>... ",
|
||||
.help = "move JTAG to state1 then to state2, state3, etc.",
|
||||
.jim_handler = Jim_Command_pathmove,
|
||||
.usage = "start_state state1 [state2 [state3 ...]]",
|
||||
.help = "Move JTAG state machine from current state "
|
||||
"(start_state) to state1, then state2, state3, etc.",
|
||||
},
|
||||
COMMAND_REGISTRATION_DONE
|
||||
};
|
||||
@@ -610,7 +623,7 @@ static int jim_newtap_cmd(Jim_GetOptInfo *goi)
|
||||
if (pTap->ir_length != 0)
|
||||
{
|
||||
jtag_tap_init(pTap);
|
||||
return ERROR_OK;
|
||||
return JIM_OK;
|
||||
}
|
||||
|
||||
Jim_SetResult_sprintf(goi->interp,
|
||||
@@ -658,7 +671,8 @@ static void jtag_tap_handle_event(struct jtag_tap *tap, enum jtag_event e)
|
||||
}
|
||||
}
|
||||
|
||||
static int jim_jtag_interface(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
|
||||
static int
|
||||
jim_jtag_interface(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
|
||||
{
|
||||
Jim_GetOptInfo goi;
|
||||
Jim_GetOpt_Setup(&goi, interp, argc-1, argv + 1);
|
||||
@@ -845,73 +859,88 @@ static const struct command_registration jtag_subcommand_handlers[] = {
|
||||
{
|
||||
.name = "init",
|
||||
.mode = COMMAND_ANY,
|
||||
.handler = &handle_jtag_init_command,
|
||||
.handler = handle_jtag_init_command,
|
||||
.help = "initialize jtag scan chain",
|
||||
},
|
||||
{
|
||||
.name = "interface",
|
||||
.mode = COMMAND_ANY,
|
||||
.jim_handler = &jim_jtag_interface,
|
||||
.help = "Returns the selected interface",
|
||||
.jim_handler = jim_jtag_interface,
|
||||
.help = "Returns the name of the currently selected interface.",
|
||||
},
|
||||
{
|
||||
.name = "arp_init",
|
||||
.mode = COMMAND_ANY,
|
||||
.jim_handler = &jim_jtag_arp_init,
|
||||
.jim_handler = jim_jtag_arp_init,
|
||||
.help = "Validates JTAG scan chain against the list of "
|
||||
"declared TAPs using just the four standard JTAG "
|
||||
"signals.",
|
||||
},
|
||||
{
|
||||
.name = "arp_init-reset",
|
||||
.mode = COMMAND_ANY,
|
||||
.jim_handler = &jim_jtag_arp_init_reset,
|
||||
.jim_handler = jim_jtag_arp_init_reset,
|
||||
.help = "Uses TRST and SRST to try resetting everything on "
|
||||
"the JTAG scan chain, then performs 'jtag arp_init'."
|
||||
},
|
||||
{
|
||||
.name = "newtap",
|
||||
.mode = COMMAND_CONFIG,
|
||||
.jim_handler = &jim_jtag_newtap,
|
||||
.help = "Create a new TAP instance",
|
||||
.usage = "<name> <type> -irlen <count> [-ircapture <count>] "
|
||||
"[-irmask <count>] [-enable|-disable]",
|
||||
.jim_handler = jim_jtag_newtap,
|
||||
.help = "Create a new TAP instance named basename.tap_type, "
|
||||
"and appends it to the scan chain.",
|
||||
.usage = "basename tap_type '-irlen' count "
|
||||
"['-enable'|'-disable'] "
|
||||
"['-expected_id' number] "
|
||||
"['-ignore-version'] "
|
||||
"['-ircapture' number] "
|
||||
"['-mask' number] ",
|
||||
},
|
||||
{
|
||||
.name = "tapisenabled",
|
||||
.mode = COMMAND_EXEC,
|
||||
.jim_handler = &jim_jtag_tap_enabler,
|
||||
.help = "Returns a integer indicating TAP state (0/1)",
|
||||
.usage = "<name>",
|
||||
.jim_handler = jim_jtag_tap_enabler,
|
||||
.help = "Returns a Tcl boolean (0/1) indicating whether "
|
||||
"the TAP is enabled (1) or not (0).",
|
||||
.usage = "tap_name",
|
||||
},
|
||||
{
|
||||
.name = "tapenable",
|
||||
.mode = COMMAND_EXEC,
|
||||
.jim_handler = &jim_jtag_tap_enabler,
|
||||
.help = "Enable the specified TAP",
|
||||
.usage = "<name>",
|
||||
.jim_handler = jim_jtag_tap_enabler,
|
||||
.help = "Try to enable the specified TAP using the "
|
||||
"'tap-enable' TAP event.",
|
||||
.usage = "tap_name",
|
||||
},
|
||||
{
|
||||
.name = "tapdisable",
|
||||
.mode = COMMAND_EXEC,
|
||||
.jim_handler = &jim_jtag_tap_enabler,
|
||||
.help = "Enable the specified TAP",
|
||||
.usage = "<name>",
|
||||
.jim_handler = jim_jtag_tap_enabler,
|
||||
.help = "Try to disable the specified TAP using the "
|
||||
"'tap-disable' TAP event.",
|
||||
.usage = "tap_name",
|
||||
},
|
||||
{
|
||||
.name = "configure",
|
||||
.mode = COMMAND_EXEC,
|
||||
.jim_handler = &jim_jtag_configure,
|
||||
.help = "Enable the specified TAP",
|
||||
.usage = "<name> [<key> <value> ...]",
|
||||
.jim_handler = jim_jtag_configure,
|
||||
.help = "Provide a Tcl handler for the specified "
|
||||
"TAP event.",
|
||||
.usage = "tap_name '-event' event_name handler",
|
||||
},
|
||||
{
|
||||
.name = "cget",
|
||||
.mode = COMMAND_EXEC,
|
||||
.jim_handler = &jim_jtag_configure,
|
||||
.help = "Enable the specified TAP",
|
||||
.usage = "<name> [<key> <value> ...]",
|
||||
.jim_handler = jim_jtag_configure,
|
||||
.help = "Return any Tcl handler for the specified "
|
||||
"TAP event.",
|
||||
.usage = "tap_name '-event' event_name",
|
||||
},
|
||||
{
|
||||
.name = "names",
|
||||
.mode = COMMAND_ANY,
|
||||
.jim_handler = &jim_jtag_names,
|
||||
.help = "Returns list of all JTAG tap names",
|
||||
.jim_handler = jim_jtag_names,
|
||||
.help = "Returns list of all JTAG tap names.",
|
||||
},
|
||||
{
|
||||
.chain = jtag_command_handlers_to_move,
|
||||
@@ -1574,34 +1603,38 @@ COMMAND_HANDLER(handle_tms_sequence_command)
|
||||
static const struct command_registration jtag_command_handlers[] = {
|
||||
{
|
||||
.name = "interface",
|
||||
.handler = &handle_interface_command,
|
||||
.handler = handle_interface_command,
|
||||
.mode = COMMAND_CONFIG,
|
||||
.help = "select a JTAG interface",
|
||||
.usage = "<driver_name>",
|
||||
.help = "Select a JTAG interface",
|
||||
.usage = "driver_name",
|
||||
},
|
||||
{
|
||||
.name = "interface_list",
|
||||
.handler = &handle_interface_list_command,
|
||||
.handler = handle_interface_list_command,
|
||||
.mode = COMMAND_ANY,
|
||||
.help = "list all built-in interfaces",
|
||||
.help = "List all built-in interfaces",
|
||||
},
|
||||
{
|
||||
.name = "jtag_khz",
|
||||
.handler = &handle_jtag_khz_command,
|
||||
.handler = handle_jtag_khz_command,
|
||||
.mode = COMMAND_ANY,
|
||||
.help = "set maximum jtag speed (if supported)",
|
||||
.usage = "<khz:0=rtck>",
|
||||
.help = "With an argument, change to the specified maximum "
|
||||
"jtag speed. Pass 0 to require adaptive clocking. "
|
||||
"With or without argument, display current setting.",
|
||||
.usage = "[khz]",
|
||||
},
|
||||
{
|
||||
.name = "jtag_rclk",
|
||||
.handler = &handle_jtag_rclk_command,
|
||||
.handler = handle_jtag_rclk_command,
|
||||
.mode = COMMAND_ANY,
|
||||
.help = "set JTAG speed to RCLK or use fallback speed",
|
||||
.usage = "<fallback_speed_khz>",
|
||||
.help = "With an argument, change to to use adaptive clocking "
|
||||
"if possible; else to use the fallback speed. "
|
||||
"With or without argument, display current setting.",
|
||||
.usage = "[fallback_speed_khz]",
|
||||
},
|
||||
{
|
||||
.name = "reset_config",
|
||||
.handler = &handle_reset_config_command,
|
||||
.handler = handle_reset_config_command,
|
||||
.mode = COMMAND_ANY,
|
||||
.help = "configure JTAG reset behavior",
|
||||
.usage = "[none|trst_only|srst_only|trst_and_srst] "
|
||||
@@ -1612,79 +1645,87 @@ static const struct command_registration jtag_command_handlers[] = {
|
||||
},
|
||||
{
|
||||
.name = "jtag_nsrst_delay",
|
||||
.handler = &handle_jtag_nsrst_delay_command,
|
||||
.handler = handle_jtag_nsrst_delay_command,
|
||||
.mode = COMMAND_ANY,
|
||||
.help = "delay after deasserting srst in ms",
|
||||
.usage = "<ms>",
|
||||
.usage = "[milliseconds]",
|
||||
},
|
||||
{
|
||||
.name = "jtag_ntrst_delay",
|
||||
.handler = &handle_jtag_ntrst_delay_command,
|
||||
.handler = handle_jtag_ntrst_delay_command,
|
||||
.mode = COMMAND_ANY,
|
||||
.help = "delay after deasserting trst in ms",
|
||||
.usage = "<ms>"
|
||||
.usage = "[milliseconds]",
|
||||
},
|
||||
{
|
||||
.name = "jtag_nsrst_assert_width",
|
||||
.handler = &handle_jtag_nsrst_assert_width_command,
|
||||
.handler = handle_jtag_nsrst_assert_width_command,
|
||||
.mode = COMMAND_ANY,
|
||||
.help = "delay after asserting srst in ms",
|
||||
.usage = "<ms>"
|
||||
.usage = "[milliseconds]",
|
||||
},
|
||||
{
|
||||
.name = "jtag_ntrst_assert_width",
|
||||
.handler = &handle_jtag_ntrst_assert_width_command,
|
||||
.handler = handle_jtag_ntrst_assert_width_command,
|
||||
.mode = COMMAND_ANY,
|
||||
.help = "delay after asserting trst in ms",
|
||||
.usage = "<ms>"
|
||||
.usage = "[milliseconds]",
|
||||
},
|
||||
{
|
||||
.name = "scan_chain",
|
||||
.handler = &handle_scan_chain_command,
|
||||
.mode = COMMAND_EXEC,
|
||||
.handler = handle_scan_chain_command,
|
||||
.mode = COMMAND_ANY,
|
||||
.help = "print current scan chain configuration",
|
||||
},
|
||||
{
|
||||
.name = "jtag_reset",
|
||||
.handler = &handle_jtag_reset_command,
|
||||
.handler = handle_jtag_reset_command,
|
||||
.mode = COMMAND_EXEC,
|
||||
.help = "toggle reset lines",
|
||||
.usage = "<trst> <srst>",
|
||||
.help = "Set reset line values. Value '1' is active, "
|
||||
"value '0' is inactive.",
|
||||
.usage = "trst_active srst_active",
|
||||
},
|
||||
{
|
||||
.name = "runtest",
|
||||
.handler = &handle_runtest_command,
|
||||
.handler = handle_runtest_command,
|
||||
.mode = COMMAND_EXEC,
|
||||
.help = "move to Run-Test/Idle, and execute <num_cycles>",
|
||||
.usage = "<num_cycles>"
|
||||
.help = "Move to Run-Test/Idle, and issue TCK for num_cycles.",
|
||||
.usage = "num_cycles"
|
||||
},
|
||||
{
|
||||
.name = "irscan",
|
||||
.handler = &handle_irscan_command,
|
||||
.handler = handle_irscan_command,
|
||||
.mode = COMMAND_EXEC,
|
||||
.help = "execute IR scan",
|
||||
.usage = "<device> <instr> [dev2] [instr2] ...",
|
||||
.help = "Execute Instruction Register (DR) scan. The "
|
||||
"specified opcodes are put into each TAP's IR, "
|
||||
"and other TAPs are put in BYPASS.",
|
||||
.usage = "[tap_name instruction]* ['-endstate' state_name]",
|
||||
},
|
||||
{
|
||||
.name = "verify_ircapture",
|
||||
.handler = &handle_verify_ircapture_command,
|
||||
.handler = handle_verify_ircapture_command,
|
||||
.mode = COMMAND_ANY,
|
||||
.help = "verify value captured during Capture-IR",
|
||||
.usage = "<enable | disable>",
|
||||
.help = "Display or assign flag controlling whether to "
|
||||
"verify values captured during Capture-IR.",
|
||||
.usage = "['enable'|'disable']",
|
||||
},
|
||||
{
|
||||
.name = "verify_jtag",
|
||||
.handler = &handle_verify_jtag_command,
|
||||
.handler = handle_verify_jtag_command,
|
||||
.mode = COMMAND_ANY,
|
||||
.help = "verify value capture",
|
||||
.usage = "<enable | disable>",
|
||||
.help = "Display or assign flag controlling whether to "
|
||||
"verify values captured during IR and DR scans.",
|
||||
.usage = "['enable'|'disable']",
|
||||
},
|
||||
{
|
||||
.name = "tms_sequence",
|
||||
.handler = &handle_tms_sequence_command,
|
||||
.handler = handle_tms_sequence_command,
|
||||
.mode = COMMAND_ANY,
|
||||
.help = "choose short(default) or long tms_sequence",
|
||||
.usage = "<short | long>",
|
||||
.help = "Display or change what style TMS sequences to use "
|
||||
"for JTAG state transitions: short (default) or "
|
||||
"long. Only for working around JTAG bugs.",
|
||||
/* Specifically for working around DRIVER bugs... */
|
||||
.usage = "['short'|'long']",
|
||||
},
|
||||
{
|
||||
.name = "jtag",
|
||||
|
||||
@@ -50,7 +50,7 @@ static __inline__ void waitQueue(void)
|
||||
// waitIdle();
|
||||
}
|
||||
|
||||
static void sampleShiftRegister(void)
|
||||
static __inline__ void sampleShiftRegister(void)
|
||||
{
|
||||
#if 0
|
||||
cyg_uint32 dummy;
|
||||
@@ -59,8 +59,7 @@ static void sampleShiftRegister(void)
|
||||
#endif
|
||||
}
|
||||
|
||||
/* -O3 will inline this for us */
|
||||
static void setCurrentState(enum tap_state state)
|
||||
static __inline__ void setCurrentState(enum tap_state state)
|
||||
{
|
||||
cyg_uint32 a;
|
||||
a = state;
|
||||
|
||||
@@ -55,6 +55,11 @@
|
||||
|
||||
#include <time.h>
|
||||
|
||||
#ifdef CYGPKG_HAL_NIOS2
|
||||
#include <cyg/hal/io.h>
|
||||
#include <cyg/firmwareutil/firmwareutil.h>
|
||||
#endif
|
||||
|
||||
#define ZYLIN_VERSION GIT_ZY1000_VERSION
|
||||
#define ZYLIN_DATE __DATE__
|
||||
#define ZYLIN_TIME __TIME__
|
||||
@@ -127,6 +132,13 @@ static int zy1000_power_dropout(int *dropout)
|
||||
void zy1000_reset(int trst, int srst)
|
||||
{
|
||||
LOG_DEBUG("zy1000 trst=%d, srst=%d", trst, srst);
|
||||
|
||||
/* flush the JTAG FIFO. Not flushing the queue before messing with
|
||||
* reset has such interesting bugs as causing hard to reproduce
|
||||
* RCLK bugs as RCLK will stop responding when TRST is asserted
|
||||
*/
|
||||
waitIdle();
|
||||
|
||||
if (!srst)
|
||||
{
|
||||
ZY1000_POKE(ZY1000_JTAG_BASE + 0x14, 0x00000001);
|
||||
@@ -151,7 +163,6 @@ void zy1000_reset(int trst, int srst)
|
||||
|
||||
if (trst||(srst && (jtag_get_reset_config() & RESET_SRST_PULLS_TRST)))
|
||||
{
|
||||
waitIdle();
|
||||
/* we're now in the RESET state until trst is deasserted */
|
||||
ZY1000_POKE(ZY1000_JTAG_BASE + 0x20, TAP_RESET);
|
||||
} else
|
||||
@@ -188,6 +199,9 @@ void zy1000_reset(int trst, int srst)
|
||||
|
||||
int zy1000_speed(int speed)
|
||||
{
|
||||
/* flush JTAG master FIFO before setting speed */
|
||||
waitIdle();
|
||||
|
||||
if (speed == 0)
|
||||
{
|
||||
/*0 means RCLK*/
|
||||
@@ -322,33 +336,57 @@ static int jim_zy1000_version(Jim_Interp *interp, int argc, Jim_Obj *const *argv
|
||||
|
||||
|
||||
#ifdef CYGPKG_HAL_NIOS2
|
||||
|
||||
|
||||
struct info_forward
|
||||
{
|
||||
void *data;
|
||||
struct cyg_upgrade_info *upgraded_file;
|
||||
};
|
||||
|
||||
static void report_info(void *data, const char * format, va_list args)
|
||||
{
|
||||
char *s = alloc_vprintf(format, args);
|
||||
LOG_USER_N("%s", s);
|
||||
free(s);
|
||||
}
|
||||
|
||||
struct cyg_upgrade_info firmware_info =
|
||||
{
|
||||
(cyg_uint8 *)0x84000000,
|
||||
"/ram/firmware.phi",
|
||||
"Firmware",
|
||||
0x0300000,
|
||||
0x1f00000 -
|
||||
0x0300000,
|
||||
"ZylinNiosFirmware\n",
|
||||
report_info,
|
||||
};
|
||||
|
||||
static int jim_zy1000_writefirmware(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
|
||||
{
|
||||
if (argc != 2)
|
||||
return JIM_ERR;
|
||||
|
||||
int length;
|
||||
int stat;
|
||||
const char *str = Jim_GetString(argv[1], &length);
|
||||
|
||||
/* BUG!!!! skip header! */
|
||||
void *firmware_address=0x4000000;
|
||||
int firmware_length=0x100000;
|
||||
|
||||
if (length>firmware_length)
|
||||
/* */
|
||||
int tmpFile;
|
||||
if ((tmpFile = open(firmware_info.file, O_RDWR | O_CREAT | O_TRUNC)) <= 0)
|
||||
{
|
||||
return JIM_ERR;
|
||||
}
|
||||
bool success;
|
||||
success = write(tmpFile, str, length) == length;
|
||||
close(tmpFile);
|
||||
if (!success)
|
||||
return JIM_ERR;
|
||||
|
||||
void *err_addr;
|
||||
if (!cyg_firmware_upgrade(NULL, firmware_info))
|
||||
return JIM_ERR;
|
||||
|
||||
if ((stat = flash_erase((void *)firmware_address, firmware_length, (void **)&err_addr)) != 0)
|
||||
{
|
||||
return JIM_ERR;
|
||||
}
|
||||
|
||||
if ((stat = flash_program(firmware_address, str, length, (void **)&err_addr)) != 0)
|
||||
return JIM_ERR;
|
||||
|
||||
return JIM_OK;
|
||||
return JIM_OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -803,29 +841,32 @@ void embeddedice_write_dcc(struct jtag_tap *tap, int reg_addr, uint8_t *buffer,
|
||||
static const struct command_registration zy1000_commands[] = {
|
||||
{
|
||||
.name = "power",
|
||||
.handler = &handle_power_command,
|
||||
.handler = handle_power_command,
|
||||
.mode = COMMAND_ANY,
|
||||
.help = "turn power switch to target on/off. No arguments - print status.",
|
||||
.usage = "power <on/off>",
|
||||
.help = "Turn power switch to target on/off. "
|
||||
"With no arguments, prints status.",
|
||||
.usage = "('on'|'off)",
|
||||
},
|
||||
{
|
||||
.name = "zy1000_version",
|
||||
.mode = COMMAND_ANY,
|
||||
.jim_handler = &jim_zy1000_version,
|
||||
.help = "print version info for zy1000",
|
||||
.jim_handler = jim_zy1000_version,
|
||||
.help = "Print version info for zy1000.",
|
||||
.usage = "['openocd'|'zy1000'|'date'|'time'|'pcb'|'fpga']",
|
||||
},
|
||||
{
|
||||
.name = "powerstatus",
|
||||
.mode = COMMAND_ANY,
|
||||
.jim_handler = & zylinjtag_Jim_Command_powerstatus,
|
||||
.help = "print power status of target",
|
||||
.jim_handler = zylinjtag_Jim_Command_powerstatus,
|
||||
.help = "Returns power status of target",
|
||||
},
|
||||
#ifdef CYGPKG_HAL_NIOS2
|
||||
{
|
||||
.name = "updatezy1000firmware",
|
||||
.mode = COMMAND_ANY,
|
||||
.jim_handler = &jim_zy1000_writefirmware,
|
||||
.jim_handler = jim_zy1000_writefirmware,
|
||||
.help = "writes firmware to flash",
|
||||
/* .usage = "some_string", */
|
||||
},
|
||||
#endif
|
||||
COMMAND_REGISTRATION_DONE
|
||||
|
||||
@@ -76,7 +76,7 @@ COMMAND_HANDLER(handle_pld_device_command)
|
||||
/* register pld specific commands */
|
||||
int retval;
|
||||
if (pld_drivers[i]->commands) {
|
||||
retval = register_commands(CMD_CTX, NULL,
|
||||
retval = register_commands(CMD_CTX, NULL,
|
||||
pld_drivers[i]->commands);
|
||||
if (ERROR_OK != retval)
|
||||
{
|
||||
@@ -89,10 +89,12 @@ COMMAND_HANDLER(handle_pld_device_command)
|
||||
c->driver = pld_drivers[i];
|
||||
c->next = NULL;
|
||||
|
||||
retval = CALL_COMMAND_HANDLER(pld_drivers[i]->pld_device_command, c);
|
||||
retval = CALL_COMMAND_HANDLER(
|
||||
pld_drivers[i]->pld_device_command, c);
|
||||
if (ERROR_OK != retval)
|
||||
{
|
||||
LOG_ERROR("'%s' driver rejected pld device", CMD_ARGV[0]);
|
||||
LOG_ERROR("'%s' driver rejected pld device",
|
||||
CMD_ARGV[0]);
|
||||
free(c);
|
||||
return ERROR_OK;
|
||||
}
|
||||
@@ -191,16 +193,16 @@ COMMAND_HANDLER(handle_pld_load_command)
|
||||
static const struct command_registration pld_exec_command_handlers[] = {
|
||||
{
|
||||
.name = "devices",
|
||||
.handler = &handle_pld_devices_command,
|
||||
.handler = handle_pld_devices_command,
|
||||
.mode = COMMAND_EXEC,
|
||||
.help = "list configured pld devices",
|
||||
},
|
||||
{
|
||||
.name = "load",
|
||||
.handler = &handle_pld_load_command,
|
||||
.handler = handle_pld_load_command,
|
||||
.mode = COMMAND_EXEC,
|
||||
.help = "load configuration file into PLD",
|
||||
.usage = "<device#> <file>",
|
||||
.usage = "pld_num filename",
|
||||
},
|
||||
COMMAND_REGISTRATION_DONE
|
||||
};
|
||||
@@ -234,14 +236,14 @@ static const struct command_registration pld_config_command_handlers[] = {
|
||||
{
|
||||
.name = "device",
|
||||
.mode = COMMAND_CONFIG,
|
||||
.handler = &handle_pld_device_command,
|
||||
.handler = handle_pld_device_command,
|
||||
.help = "configure a PLD device",
|
||||
.usage = "<driver> ...",
|
||||
.usage = "driver_name [driver_args ... ]",
|
||||
},
|
||||
{
|
||||
.name = "init",
|
||||
.mode = COMMAND_CONFIG,
|
||||
.handler = &handle_pld_init_command,
|
||||
.handler = handle_pld_init_command,
|
||||
.help = "initialize PLD devices",
|
||||
},
|
||||
COMMAND_REGISTRATION_DONE
|
||||
@@ -251,7 +253,6 @@ static const struct command_registration pld_command_handler[] = {
|
||||
.name = "pld",
|
||||
.mode = COMMAND_ANY,
|
||||
.help = "programmable logic device commands",
|
||||
|
||||
.chain = pld_config_command_handlers,
|
||||
},
|
||||
COMMAND_REGISTRATION_DONE
|
||||
|
||||
@@ -237,9 +237,9 @@ static const struct command_registration virtex2_exec_command_handlers[] = {
|
||||
{
|
||||
.name = "read_stat",
|
||||
.mode = COMMAND_EXEC,
|
||||
.handler = &virtex2_handle_read_stat_command,
|
||||
.handler = virtex2_handle_read_stat_command,
|
||||
.help = "read status register",
|
||||
.usage = "<device_id>",
|
||||
.usage = "pld_num",
|
||||
},
|
||||
COMMAND_REGISTRATION_DONE
|
||||
};
|
||||
|
||||
@@ -37,6 +37,15 @@
|
||||
#include <jtag/jtag.h>
|
||||
|
||||
|
||||
/**
|
||||
* @file
|
||||
* GDB server implementation.
|
||||
*
|
||||
* This implements the GDB Remote Serial Protocol, over TCP connections,
|
||||
* giving GDB access to the JTAG or other hardware debugging facilities
|
||||
* found in most modern embedded processors.
|
||||
*/
|
||||
|
||||
/* private connection data for GDB */
|
||||
struct gdb_connection
|
||||
{
|
||||
@@ -65,10 +74,10 @@ static struct gdb_connection *current_gdb_connection;
|
||||
static int gdb_breakpoint_override;
|
||||
static enum breakpoint_type gdb_breakpoint_override_type;
|
||||
|
||||
extern int gdb_error(struct connection *connection, int retval);
|
||||
static int gdb_error(struct connection *connection, int retval);
|
||||
static unsigned short gdb_port = 3333;
|
||||
static unsigned short gdb_port_next = 0;
|
||||
static const char *DIGITS = "0123456789abcdef";
|
||||
static const char DIGITS[16] = "0123456789abcdef";
|
||||
|
||||
static void gdb_log_callback(void *priv, const char *file, unsigned line,
|
||||
const char *function, const char *string);
|
||||
@@ -80,15 +89,17 @@ int gdb_actual_connections;
|
||||
/* set if we are sending a memory map to gdb
|
||||
* via qXfer:memory-map:read packet */
|
||||
/* enabled by default*/
|
||||
int gdb_use_memory_map = 1;
|
||||
static int gdb_use_memory_map = 1;
|
||||
/* enabled by default*/
|
||||
int gdb_flash_program = 1;
|
||||
static int gdb_flash_program = 1;
|
||||
|
||||
/* if set, data aborts cause an error to be reported in memory read packets
|
||||
* see the code in gdb_read_memory_packet() for further explanations */
|
||||
int gdb_report_data_abort = 0;
|
||||
* see the code in gdb_read_memory_packet() for further explanations.
|
||||
* Disabled by default.
|
||||
*/
|
||||
static int gdb_report_data_abort;
|
||||
|
||||
int gdb_last_signal(struct target *target)
|
||||
static int gdb_last_signal(struct target *target)
|
||||
{
|
||||
switch (target->debug_reason)
|
||||
{
|
||||
@@ -108,7 +119,8 @@ int gdb_last_signal(struct target *target)
|
||||
}
|
||||
}
|
||||
|
||||
int check_pending(struct connection *connection, int timeout_s, int *got_data)
|
||||
static int check_pending(struct connection *connection,
|
||||
int timeout_s, int *got_data)
|
||||
{
|
||||
/* a non-blocking socket will block if there is 0 bytes available on the socket,
|
||||
* but return with as many bytes as are available immediately
|
||||
@@ -275,14 +287,14 @@ static inline int gdb_get_char_fast(struct connection *connection, int* next_cha
|
||||
}
|
||||
|
||||
|
||||
int gdb_get_char(struct connection *connection, int* next_char)
|
||||
static int gdb_get_char(struct connection *connection, int* next_char)
|
||||
{
|
||||
struct gdb_connection *gdb_con = connection->priv;
|
||||
return gdb_get_char_fast(connection, next_char, &gdb_con->buf_p, &gdb_con->buf_cnt);
|
||||
}
|
||||
|
||||
|
||||
int gdb_putback_char(struct connection *connection, int last_char)
|
||||
static int gdb_putback_char(struct connection *connection, int last_char)
|
||||
{
|
||||
struct gdb_connection *gdb_con = connection->priv;
|
||||
|
||||
@@ -302,7 +314,7 @@ int gdb_putback_char(struct connection *connection, int last_char)
|
||||
/* The only way we can detect that the socket is closed is the first time
|
||||
* we write to it, we will fail. Subsequent write operations will
|
||||
* succeed. Shudder! */
|
||||
int gdb_write(struct connection *connection, void *data, int len)
|
||||
static int gdb_write(struct connection *connection, void *data, int len)
|
||||
{
|
||||
struct gdb_connection *gdb_con = connection->priv;
|
||||
if (gdb_con->closed)
|
||||
@@ -327,7 +339,8 @@ int gdb_write(struct connection *connection, void *data, int len)
|
||||
return ERROR_SERVER_REMOTE_CLOSED;
|
||||
}
|
||||
|
||||
int gdb_put_packet_inner(struct connection *connection, char *buffer, int len)
|
||||
static int gdb_put_packet_inner(struct connection *connection,
|
||||
char *buffer, int len)
|
||||
{
|
||||
int i;
|
||||
unsigned char my_checksum = 0;
|
||||
@@ -350,7 +363,8 @@ int gdb_put_packet_inner(struct connection *connection, char *buffer, int len)
|
||||
int gotdata;
|
||||
for (;;)
|
||||
{
|
||||
if ((retval = check_pending(connection, 0, &gotdata)) != ERROR_OK)
|
||||
retval = check_pending(connection, 0, &gotdata);
|
||||
if (retval != ERROR_OK)
|
||||
return retval;
|
||||
if (!gotdata)
|
||||
break;
|
||||
@@ -468,7 +482,7 @@ int gdb_put_packet_inner(struct connection *connection, char *buffer, int len)
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
int gdb_put_packet(struct connection *connection, char *buffer, int len)
|
||||
static int gdb_put_packet(struct connection *connection, char *buffer, int len)
|
||||
{
|
||||
struct gdb_connection *gdb_con = connection->priv;
|
||||
gdb_con->busy = 1;
|
||||
@@ -607,7 +621,8 @@ static __inline__ int fetch_packet(struct connection *connection, int *checksum_
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
int gdb_get_packet_inner(struct connection *connection, char *buffer, int *len)
|
||||
static int gdb_get_packet_inner(struct connection *connection,
|
||||
char *buffer, int *len)
|
||||
{
|
||||
int character;
|
||||
int retval;
|
||||
@@ -682,7 +697,7 @@ int gdb_get_packet_inner(struct connection *connection, char *buffer, int *len)
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
int gdb_get_packet(struct connection *connection, char *buffer, int *len)
|
||||
static int gdb_get_packet(struct connection *connection, char *buffer, int *len)
|
||||
{
|
||||
struct gdb_connection *gdb_con = connection->priv;
|
||||
gdb_con->busy = 1;
|
||||
@@ -691,7 +706,7 @@ int gdb_get_packet(struct connection *connection, char *buffer, int *len)
|
||||
return retval;
|
||||
}
|
||||
|
||||
int gdb_output_con(struct connection *connection, const char* line)
|
||||
static int gdb_output_con(struct connection *connection, const char* line)
|
||||
{
|
||||
char *hex_buffer;
|
||||
int i, bin_size;
|
||||
@@ -713,7 +728,7 @@ int gdb_output_con(struct connection *connection, const char* line)
|
||||
return retval;
|
||||
}
|
||||
|
||||
int gdb_output(struct command_context *context, const char* line)
|
||||
static int gdb_output(struct command_context *context, const char* line)
|
||||
{
|
||||
/* this will be dumped to the log and also sent as an O packet if possible */
|
||||
LOG_USER_N("%s", line);
|
||||
@@ -758,7 +773,8 @@ static void gdb_frontend_halted(struct target *target, struct connection *connec
|
||||
}
|
||||
}
|
||||
|
||||
int gdb_target_callback_event_handler(struct target *target, enum target_event event, void *priv)
|
||||
static int gdb_target_callback_event_handler(struct target *target,
|
||||
enum target_event event, void *priv)
|
||||
{
|
||||
int retval;
|
||||
struct connection *connection = priv;
|
||||
@@ -786,7 +802,7 @@ int gdb_target_callback_event_handler(struct target *target, enum target_event e
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
int gdb_new_connection(struct connection *connection)
|
||||
static int gdb_new_connection(struct connection *connection)
|
||||
{
|
||||
struct gdb_connection *gdb_connection = malloc(sizeof(struct gdb_connection));
|
||||
struct gdb_service *gdb_service = connection->service->priv;
|
||||
@@ -842,7 +858,7 @@ int gdb_new_connection(struct connection *connection)
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
int gdb_connection_closed(struct connection *connection)
|
||||
static int gdb_connection_closed(struct connection *connection)
|
||||
{
|
||||
struct gdb_service *gdb_service = connection->service->priv;
|
||||
struct gdb_connection *gdb_connection = connection->priv;
|
||||
@@ -889,14 +905,15 @@ int gdb_connection_closed(struct connection *connection)
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
void gdb_send_error(struct connection *connection, uint8_t the_error)
|
||||
static void gdb_send_error(struct connection *connection, uint8_t the_error)
|
||||
{
|
||||
char err[4];
|
||||
snprintf(err, 4, "E%2.2X", the_error);
|
||||
gdb_put_packet(connection, err, 3);
|
||||
}
|
||||
|
||||
int gdb_last_signal_packet(struct connection *connection, struct target *target, char* packet, int packet_size)
|
||||
static int gdb_last_signal_packet(struct connection *connection,
|
||||
struct target *target, char* packet, int packet_size)
|
||||
{
|
||||
char sig_reply[4];
|
||||
int signal;
|
||||
@@ -926,7 +943,8 @@ static int gdb_reg_pos(struct target *target, int pos, int len)
|
||||
* The format of reg->value is little endian
|
||||
*
|
||||
*/
|
||||
void gdb_str_to_target(struct target *target, char *tstr, struct reg *reg)
|
||||
static void gdb_str_to_target(struct target *target,
|
||||
char *tstr, struct reg *reg)
|
||||
{
|
||||
int i;
|
||||
|
||||
@@ -943,7 +961,7 @@ void gdb_str_to_target(struct target *target, char *tstr, struct reg *reg)
|
||||
}
|
||||
}
|
||||
|
||||
static int hextoint(char c)
|
||||
static int hextoint(int c)
|
||||
{
|
||||
if (c>='0'&&c<='9')
|
||||
{
|
||||
@@ -959,7 +977,8 @@ static int hextoint(char c)
|
||||
}
|
||||
|
||||
/* copy over in register buffer */
|
||||
void gdb_target_to_reg(struct target *target, char *tstr, int str_len, uint8_t *bin)
|
||||
static void gdb_target_to_reg(struct target *target,
|
||||
char *tstr, int str_len, uint8_t *bin)
|
||||
{
|
||||
if (str_len % 2)
|
||||
{
|
||||
@@ -978,7 +997,8 @@ void gdb_target_to_reg(struct target *target, char *tstr, int str_len, uint8_t *
|
||||
}
|
||||
}
|
||||
|
||||
int gdb_get_registers_packet(struct connection *connection, struct target *target, char* packet, int packet_size)
|
||||
static int gdb_get_registers_packet(struct connection *connection,
|
||||
struct target *target, char* packet, int packet_size)
|
||||
{
|
||||
struct reg **reg_list;
|
||||
int reg_list_size;
|
||||
@@ -1028,7 +1048,8 @@ int gdb_get_registers_packet(struct connection *connection, struct target *targe
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
int gdb_set_registers_packet(struct connection *connection, struct target *target, char *packet, int packet_size)
|
||||
static int gdb_set_registers_packet(struct connection *connection,
|
||||
struct target *target, char *packet, int packet_size)
|
||||
{
|
||||
int i;
|
||||
struct reg **reg_list;
|
||||
@@ -1086,7 +1107,8 @@ int gdb_set_registers_packet(struct connection *connection, struct target *targe
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
int gdb_get_register_packet(struct connection *connection, struct target *target, char *packet, int packet_size)
|
||||
static int gdb_get_register_packet(struct connection *connection,
|
||||
struct target *target, char *packet, int packet_size)
|
||||
{
|
||||
char *reg_packet;
|
||||
int reg_num = strtoul(packet + 1, NULL, 16);
|
||||
@@ -1121,7 +1143,8 @@ int gdb_get_register_packet(struct connection *connection, struct target *target
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
int gdb_set_register_packet(struct connection *connection, struct target *target, char *packet, int packet_size)
|
||||
static int gdb_set_register_packet(struct connection *connection,
|
||||
struct target *target, char *packet, int packet_size)
|
||||
{
|
||||
char *separator;
|
||||
uint8_t *bin_buf;
|
||||
@@ -1167,7 +1190,7 @@ int gdb_set_register_packet(struct connection *connection, struct target *target
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
int gdb_error(struct connection *connection, int retval)
|
||||
static int gdb_error(struct connection *connection, int retval)
|
||||
{
|
||||
switch (retval)
|
||||
{
|
||||
@@ -1198,7 +1221,8 @@ int gdb_error(struct connection *connection, int retval)
|
||||
*
|
||||
* 8191 bytes by the looks of it. Why 8191 bytes instead of 8192?????
|
||||
*/
|
||||
int gdb_read_memory_packet(struct connection *connection, struct target *target, char *packet, int packet_size)
|
||||
static int gdb_read_memory_packet(struct connection *connection,
|
||||
struct target *target, char *packet, int packet_size)
|
||||
{
|
||||
char *separator;
|
||||
uint32_t addr = 0;
|
||||
@@ -1272,7 +1296,8 @@ int gdb_read_memory_packet(struct connection *connection, struct target *target,
|
||||
return retval;
|
||||
}
|
||||
|
||||
int gdb_write_memory_packet(struct connection *connection, struct target *target, char *packet, int packet_size)
|
||||
static int gdb_write_memory_packet(struct connection *connection,
|
||||
struct target *target, char *packet, int packet_size)
|
||||
{
|
||||
char *separator;
|
||||
uint32_t addr = 0;
|
||||
@@ -1329,7 +1354,8 @@ int gdb_write_memory_packet(struct connection *connection, struct target *target
|
||||
return retval;
|
||||
}
|
||||
|
||||
int gdb_write_memory_binary_packet(struct connection *connection, struct target *target, char *packet, int packet_size)
|
||||
static int gdb_write_memory_binary_packet(struct connection *connection,
|
||||
struct target *target, char *packet, int packet_size)
|
||||
{
|
||||
char *separator;
|
||||
uint32_t addr = 0;
|
||||
@@ -1377,7 +1403,8 @@ int gdb_write_memory_binary_packet(struct connection *connection, struct target
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
int gdb_step_continue_packet(struct connection *connection, struct target *target, char *packet, int packet_size)
|
||||
static int gdb_step_continue_packet(struct connection *connection,
|
||||
struct target *target, char *packet, int packet_size)
|
||||
{
|
||||
int current = 0;
|
||||
uint32_t address = 0x0;
|
||||
@@ -1410,11 +1437,12 @@ int gdb_step_continue_packet(struct connection *connection, struct target *targe
|
||||
return retval;
|
||||
}
|
||||
|
||||
int gdb_breakpoint_watchpoint_packet(struct connection *connection, struct target *target, char *packet, int packet_size)
|
||||
static int gdb_breakpoint_watchpoint_packet(struct connection *connection,
|
||||
struct target *target, char *packet, int packet_size)
|
||||
{
|
||||
int type;
|
||||
enum breakpoint_type bp_type = BKPT_SOFT /* dummy init to avoid warning */;
|
||||
enum watchpoint_rw wp_type;
|
||||
enum watchpoint_rw wp_type = WPT_READ /* dummy init to avoid warning */;
|
||||
uint32_t address;
|
||||
uint32_t size;
|
||||
char *separator;
|
||||
@@ -1434,6 +1462,12 @@ int gdb_breakpoint_watchpoint_packet(struct connection *connection, struct targe
|
||||
wp_type = WPT_READ;
|
||||
else if (type == 4) /* access watchpoint */
|
||||
wp_type = WPT_ACCESS;
|
||||
else
|
||||
{
|
||||
LOG_ERROR("invalid gdb watch/breakpoint type(%d), dropping connection", type);
|
||||
return ERROR_SERVER_REMOTE_CLOSED;
|
||||
}
|
||||
|
||||
|
||||
if (gdb_breakpoint_override && ((bp_type == BKPT_SOFT)||(bp_type == BKPT_HARD)))
|
||||
{
|
||||
@@ -1484,7 +1518,7 @@ int gdb_breakpoint_watchpoint_packet(struct connection *connection, struct targe
|
||||
{
|
||||
if (packet[0] == 'Z')
|
||||
{
|
||||
if ((retval = watchpoint_add(target, address, size, type-2, 0, 0xffffffffu)) != ERROR_OK)
|
||||
if ((retval = watchpoint_add(target, address, size, wp_type, 0, 0xffffffffu)) != ERROR_OK)
|
||||
{
|
||||
if ((retval = gdb_error(connection, retval)) != ERROR_OK)
|
||||
return retval;
|
||||
@@ -1508,8 +1542,11 @@ int gdb_breakpoint_watchpoint_packet(struct connection *connection, struct targe
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
/* print out a string and allocate more space as needed, mainly used for XML at this point */
|
||||
void xml_printf(int *retval, char **xml, int *pos, int *size, const char *fmt, ...)
|
||||
/* print out a string and allocate more space as needed,
|
||||
* mainly used for XML at this point
|
||||
*/
|
||||
static void xml_printf(int *retval, char **xml, int *pos, int *size,
|
||||
const char *fmt, ...)
|
||||
{
|
||||
if (*retval != ERROR_OK)
|
||||
{
|
||||
@@ -1576,22 +1613,6 @@ static int decode_xfer_read(char *buf, char **annex, int *ofs, unsigned int *len
|
||||
return 0;
|
||||
}
|
||||
|
||||
int gdb_calc_blocksize(struct flash_bank *bank)
|
||||
{
|
||||
uint32_t i;
|
||||
uint32_t block_size = 0xffffffff;
|
||||
|
||||
/* loop through all sectors and return smallest sector size */
|
||||
|
||||
for (i = 0; i < (uint32_t)bank->num_sectors; i++)
|
||||
{
|
||||
if (bank->sectors[i].size < block_size)
|
||||
block_size = bank->sectors[i].size;
|
||||
}
|
||||
|
||||
return block_size;
|
||||
}
|
||||
|
||||
static int compare_bank (const void * a, const void * b)
|
||||
{
|
||||
struct flash_bank *b1, *b2;
|
||||
@@ -1610,7 +1631,151 @@ static int compare_bank (const void * a, const void * b)
|
||||
}
|
||||
}
|
||||
|
||||
int gdb_query_packet(struct connection *connection, struct target *target, char *packet, int packet_size)
|
||||
static int gdb_memory_map(struct connection *connection,
|
||||
struct target *target, char *packet, int packet_size)
|
||||
{
|
||||
/* We get away with only specifying flash here. Regions that are not
|
||||
* specified are treated as if we provided no memory map(if not we
|
||||
* could detect the holes and mark them as RAM).
|
||||
* Normally we only execute this code once, but no big deal if we
|
||||
* have to regenerate it a couple of times.
|
||||
*/
|
||||
|
||||
struct flash_bank *p;
|
||||
char *xml = NULL;
|
||||
int size = 0;
|
||||
int pos = 0;
|
||||
int retval = ERROR_OK;
|
||||
struct flash_bank **banks;
|
||||
int offset;
|
||||
int length;
|
||||
char *separator;
|
||||
uint32_t ram_start = 0;
|
||||
int i;
|
||||
|
||||
/* skip command character */
|
||||
packet += 23;
|
||||
|
||||
offset = strtoul(packet, &separator, 16);
|
||||
length = strtoul(separator + 1, &separator, 16);
|
||||
|
||||
xml_printf(&retval, &xml, &pos, &size, "<memory-map>\n");
|
||||
|
||||
/* Sort banks in ascending order. We need to report non-flash
|
||||
* memory as ram (or rather read/write) by default for GDB, since
|
||||
* it has no concept of non-cacheable read/write memory (i/o etc).
|
||||
*
|
||||
* FIXME Most non-flash addresses are *NOT* RAM! Don't lie.
|
||||
* Current versions of GDB assume unlisted addresses are RAM...
|
||||
*/
|
||||
banks = malloc(sizeof(struct flash_bank *)*flash_get_bank_count());
|
||||
|
||||
for (i = 0; i < flash_get_bank_count(); i++) {
|
||||
p = get_flash_bank_by_num(i);
|
||||
if (p == NULL) {
|
||||
free(banks);
|
||||
retval = ERROR_FAIL;
|
||||
gdb_send_error(connection, retval);
|
||||
return retval;
|
||||
}
|
||||
banks[i] = p;
|
||||
}
|
||||
|
||||
qsort(banks, flash_get_bank_count(), sizeof(struct flash_bank *),
|
||||
compare_bank);
|
||||
|
||||
for (i = 0; i < flash_get_bank_count(); i++) {
|
||||
int j;
|
||||
unsigned sector_size = 0;
|
||||
uint32_t start, end;
|
||||
|
||||
p = banks[i];
|
||||
start = p->base;
|
||||
end = p->base + p->size;
|
||||
|
||||
if (ram_start < p->base)
|
||||
xml_printf(&retval, &xml, &pos, &size,
|
||||
"<memory type=\"ram\" start=\"0x%x\" "
|
||||
"length=\"0x%x\"/>\n",
|
||||
ram_start, p->base - ram_start);
|
||||
|
||||
/* Report adjacent groups of same-size sectors. So for
|
||||
* example top boot CFI flash will list an initial region
|
||||
* with several large sectors (maybe 128KB) and several
|
||||
* smaller ones at the end (maybe 32KB). STR7 will have
|
||||
* regions with 8KB, 32KB, and 64KB sectors; etc.
|
||||
*/
|
||||
for (j = 0; j < p->num_sectors; j++) {
|
||||
unsigned group_len;
|
||||
|
||||
/* Maybe start a new group of sectors. */
|
||||
if (sector_size == 0) {
|
||||
start = p->base + p->sectors[j].offset;
|
||||
xml_printf(&retval, &xml, &pos, &size,
|
||||
"<memory type=\"flash\" "
|
||||
"start=\"0x%x\" ",
|
||||
start);
|
||||
sector_size = p->sectors[j].size;
|
||||
}
|
||||
|
||||
/* Does this finish a group of sectors?
|
||||
* If not, continue an already-started group.
|
||||
*/
|
||||
if (j == p->num_sectors -1)
|
||||
group_len = (p->base + p->size) - start;
|
||||
else if (p->sectors[j + 1].size != sector_size)
|
||||
group_len = p->base + p->sectors[j + 1].offset
|
||||
- start;
|
||||
else
|
||||
continue;
|
||||
|
||||
xml_printf(&retval, &xml, &pos, &size,
|
||||
"length=\"0x%x\">\n"
|
||||
"<property name=\"blocksize\">"
|
||||
"0x%x</property>\n"
|
||||
"</memory>\n",
|
||||
group_len,
|
||||
sector_size);
|
||||
sector_size = 0;
|
||||
}
|
||||
|
||||
ram_start = p->base + p->size;
|
||||
}
|
||||
|
||||
if (ram_start != 0)
|
||||
xml_printf(&retval, &xml, &pos, &size,
|
||||
"<memory type=\"ram\" start=\"0x%x\" "
|
||||
"length=\"0x%x\"/>\n",
|
||||
ram_start, 0-ram_start);
|
||||
/* ELSE a flash chip could be at the very end of the 32 bit address
|
||||
* space, in which case ram_start will be precisely 0
|
||||
*/
|
||||
|
||||
free(banks);
|
||||
banks = NULL;
|
||||
|
||||
xml_printf(&retval, &xml, &pos, &size, "</memory-map>\n");
|
||||
|
||||
if (retval != ERROR_OK) {
|
||||
gdb_send_error(connection, retval);
|
||||
return retval;
|
||||
}
|
||||
|
||||
if (offset + length > pos)
|
||||
length = pos - offset;
|
||||
|
||||
char *t = malloc(length + 1);
|
||||
t[0] = 'l';
|
||||
memcpy(t + 1, xml + offset, length);
|
||||
gdb_put_packet(connection, t, length + 1);
|
||||
|
||||
free(t);
|
||||
free(xml);
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
static int gdb_query_packet(struct connection *connection,
|
||||
struct target *target, char *packet, int packet_size)
|
||||
{
|
||||
struct command_context *cmd_ctx = connection->cmd_ctx;
|
||||
struct gdb_connection *gdb_connection = connection->priv;
|
||||
@@ -1709,112 +1874,9 @@ int gdb_query_packet(struct connection *connection, struct target *target, char
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
else if (strstr(packet, "qXfer:memory-map:read::") && (flash_get_bank_count() > 0))
|
||||
{
|
||||
/* We get away with only specifying flash here. Regions that are not
|
||||
* specified are treated as if we provided no memory map(if not we
|
||||
* could detect the holes and mark them as RAM).
|
||||
* Normally we only execute this code once, but no big deal if we
|
||||
* have to regenerate it a couple of times. */
|
||||
|
||||
struct flash_bank *p;
|
||||
char *xml = NULL;
|
||||
int size = 0;
|
||||
int pos = 0;
|
||||
int retval = ERROR_OK;
|
||||
|
||||
int offset;
|
||||
int length;
|
||||
char *separator;
|
||||
int blocksize;
|
||||
|
||||
/* skip command character */
|
||||
packet += 23;
|
||||
|
||||
offset = strtoul(packet, &separator, 16);
|
||||
length = strtoul(separator + 1, &separator, 16);
|
||||
|
||||
xml_printf(&retval, &xml, &pos, &size, "<memory-map>\n");
|
||||
|
||||
/*
|
||||
sort banks in ascending order, we need to make non-flash memory be ram(or rather
|
||||
read/write) by default for GDB.
|
||||
GDB does not have a concept of non-cacheable read/write memory.
|
||||
*/
|
||||
struct flash_bank **banks = malloc(sizeof(struct flash_bank *)*flash_get_bank_count());
|
||||
int i;
|
||||
|
||||
for (i = 0; i < flash_get_bank_count(); i++)
|
||||
{
|
||||
p = get_flash_bank_by_num(i);
|
||||
if (p == NULL)
|
||||
{
|
||||
free(banks);
|
||||
retval = ERROR_FAIL;
|
||||
gdb_send_error(connection, retval);
|
||||
return retval;
|
||||
}
|
||||
banks[i]=p;
|
||||
}
|
||||
|
||||
qsort(banks, flash_get_bank_count(), sizeof(struct flash_bank *), compare_bank);
|
||||
|
||||
uint32_t ram_start = 0;
|
||||
for (i = 0; i < flash_get_bank_count(); i++)
|
||||
{
|
||||
p = banks[i];
|
||||
|
||||
if (ram_start < p->base)
|
||||
{
|
||||
xml_printf(&retval, &xml, &pos, &size, "<memory type=\"ram\" start=\"0x%x\" length=\"0x%x\"/>\n",
|
||||
ram_start, p->base-ram_start);
|
||||
}
|
||||
|
||||
/* if device has uneven sector sizes, eg. str7, lpc
|
||||
* we pass the smallest sector size to gdb memory map */
|
||||
blocksize = gdb_calc_blocksize(p);
|
||||
|
||||
xml_printf(&retval, &xml, &pos, &size, "<memory type=\"flash\" start=\"0x%x\" length=\"0x%x\">\n" \
|
||||
"<property name=\"blocksize\">0x%x</property>\n" \
|
||||
"</memory>\n", \
|
||||
p->base, p->size, blocksize);
|
||||
ram_start = p->base + p->size;
|
||||
}
|
||||
if (ram_start != 0)
|
||||
{
|
||||
xml_printf(&retval, &xml, &pos, &size, "<memory type=\"ram\" start=\"0x%x\" length=\"0x%x\"/>\n",
|
||||
ram_start, 0-ram_start);
|
||||
} else
|
||||
{
|
||||
/* a flash chip could be at the very end of the 32 bit address space, in which case
|
||||
ram_start will be precisely 0 */
|
||||
}
|
||||
|
||||
free(banks);
|
||||
banks = NULL;
|
||||
|
||||
xml_printf(&retval, &xml, &pos, &size, "</memory-map>\n");
|
||||
|
||||
if (retval != ERROR_OK)
|
||||
{
|
||||
gdb_send_error(connection, retval);
|
||||
return retval;
|
||||
}
|
||||
|
||||
if (offset + length > pos)
|
||||
{
|
||||
length = pos - offset;
|
||||
}
|
||||
|
||||
char *t = malloc(length + 1);
|
||||
t[0] = 'l';
|
||||
memcpy(t + 1, xml + offset, length);
|
||||
gdb_put_packet(connection, t, length + 1);
|
||||
|
||||
free(t);
|
||||
free(xml);
|
||||
return ERROR_OK;
|
||||
}
|
||||
else if (strstr(packet, "qXfer:memory-map:read::")
|
||||
&& (flash_get_bank_count() > 0))
|
||||
return gdb_memory_map(connection, target, packet, packet_size);
|
||||
else if (strstr(packet, "qXfer:features:read:"))
|
||||
{
|
||||
char *xml = NULL;
|
||||
@@ -1866,7 +1928,8 @@ int gdb_query_packet(struct connection *connection, struct target *target, char
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
int gdb_v_packet(struct connection *connection, struct target *target, char *packet, int packet_size)
|
||||
static int gdb_v_packet(struct connection *connection,
|
||||
struct target *target, char *packet, int packet_size)
|
||||
{
|
||||
struct gdb_connection *gdb_connection = connection->priv;
|
||||
struct gdb_service *gdb_service = connection->service->priv;
|
||||
@@ -1913,9 +1976,19 @@ int gdb_v_packet(struct connection *connection, struct target *target, char *pac
|
||||
flash_set_dirty();
|
||||
|
||||
/* perform any target specific operations before the erase */
|
||||
target_call_event_callbacks(gdb_service->target, TARGET_EVENT_GDB_FLASH_ERASE_START);
|
||||
result = flash_erase_address_range(gdb_service->target, addr, length);
|
||||
target_call_event_callbacks(gdb_service->target, TARGET_EVENT_GDB_FLASH_ERASE_END);
|
||||
target_call_event_callbacks(gdb_service->target,
|
||||
TARGET_EVENT_GDB_FLASH_ERASE_START);
|
||||
|
||||
/* vFlashErase:addr,length messages require region start and
|
||||
* end to be "block" aligned ... if padding is ever needed,
|
||||
* GDB will have become dangerously confused.
|
||||
*/
|
||||
result = flash_erase_address_range(gdb_service->target,
|
||||
false, addr, length);
|
||||
|
||||
/* perform any target specific operations after the erase */
|
||||
target_call_event_callbacks(gdb_service->target,
|
||||
TARGET_EVENT_GDB_FLASH_ERASE_END);
|
||||
|
||||
/* perform erase */
|
||||
if (result != ERROR_OK)
|
||||
@@ -2003,11 +2076,12 @@ int gdb_v_packet(struct connection *connection, struct target *target, char *pac
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
int gdb_detach(struct connection *connection, struct target *target)
|
||||
static int gdb_detach(struct connection *connection, struct target *target)
|
||||
{
|
||||
struct gdb_service *gdb_service = connection->service->priv;
|
||||
|
||||
target_call_event_callbacks(gdb_service->target, TARGET_EVENT_GDB_DETACH);
|
||||
target_call_event_callbacks(gdb_service->target,
|
||||
TARGET_EVENT_GDB_DETACH);
|
||||
|
||||
return gdb_put_packet(connection, "OK", 2);
|
||||
}
|
||||
@@ -2027,9 +2101,6 @@ static void gdb_log_callback(void *priv, const char *file, unsigned line,
|
||||
gdb_output_con(connection, string);
|
||||
}
|
||||
|
||||
/* Do not allocate this on the stack */
|
||||
char gdb_packet_buffer[GDB_BUFFER_SIZE];
|
||||
|
||||
static void gdb_sig_halted(struct connection *connection)
|
||||
{
|
||||
char sig_reply[4];
|
||||
@@ -2038,8 +2109,11 @@ static void gdb_sig_halted(struct connection *connection)
|
||||
|
||||
}
|
||||
|
||||
int gdb_input_inner(struct connection *connection)
|
||||
static int gdb_input_inner(struct connection *connection)
|
||||
{
|
||||
/* Do not allocate this on the stack */
|
||||
static char gdb_packet_buffer[GDB_BUFFER_SIZE];
|
||||
|
||||
struct gdb_service *gdb_service = connection->service->priv;
|
||||
struct target *target = gdb_service->target;
|
||||
char *packet = gdb_packet_buffer;
|
||||
@@ -2052,10 +2126,9 @@ int gdb_input_inner(struct connection *connection)
|
||||
do
|
||||
{
|
||||
packet_size = GDB_BUFFER_SIZE-1;
|
||||
if ((retval = gdb_get_packet(connection, packet, &packet_size)) != ERROR_OK)
|
||||
{
|
||||
retval = gdb_get_packet(connection, packet, &packet_size);
|
||||
if (retval != ERROR_OK)
|
||||
return retval;
|
||||
}
|
||||
|
||||
/* terminate with zero */
|
||||
packet[packet_size] = 0;
|
||||
@@ -2087,32 +2160,48 @@ int gdb_input_inner(struct connection *connection)
|
||||
break;
|
||||
case 'q':
|
||||
case 'Q':
|
||||
retval = gdb_query_packet(connection, target, packet, packet_size);
|
||||
retval = gdb_query_packet(connection,
|
||||
target, packet,
|
||||
packet_size);
|
||||
break;
|
||||
case 'g':
|
||||
retval = gdb_get_registers_packet(connection, target, packet, packet_size);
|
||||
retval = gdb_get_registers_packet(
|
||||
connection, target,
|
||||
packet, packet_size);
|
||||
break;
|
||||
case 'G':
|
||||
retval = gdb_set_registers_packet(connection, target, packet, packet_size);
|
||||
retval = gdb_set_registers_packet(
|
||||
connection, target,
|
||||
packet, packet_size);
|
||||
break;
|
||||
case 'p':
|
||||
retval = gdb_get_register_packet(connection, target, packet, packet_size);
|
||||
retval = gdb_get_register_packet(
|
||||
connection, target,
|
||||
packet, packet_size);
|
||||
break;
|
||||
case 'P':
|
||||
retval = gdb_set_register_packet(connection, target, packet, packet_size);
|
||||
retval = gdb_set_register_packet(
|
||||
connection, target,
|
||||
packet, packet_size);
|
||||
break;
|
||||
case 'm':
|
||||
retval = gdb_read_memory_packet(connection, target, packet, packet_size);
|
||||
retval = gdb_read_memory_packet(
|
||||
connection, target,
|
||||
packet, packet_size);
|
||||
break;
|
||||
case 'M':
|
||||
retval = gdb_write_memory_packet(connection, target, packet, packet_size);
|
||||
retval = gdb_write_memory_packet(
|
||||
connection, target,
|
||||
packet, packet_size);
|
||||
break;
|
||||
case 'z':
|
||||
case 'Z':
|
||||
retval = gdb_breakpoint_watchpoint_packet(connection, target, packet, packet_size);
|
||||
break;
|
||||
case '?':
|
||||
gdb_last_signal_packet(connection, target, packet, packet_size);
|
||||
gdb_last_signal_packet(
|
||||
connection, target,
|
||||
packet, packet_size);
|
||||
break;
|
||||
case 'c':
|
||||
case 's':
|
||||
@@ -2123,12 +2212,13 @@ int gdb_input_inner(struct connection *connection)
|
||||
log_add_callback(gdb_log_callback, connection);
|
||||
|
||||
bool nostep = false;
|
||||
bool already_running = false;
|
||||
if (target->state == TARGET_RUNNING)
|
||||
{
|
||||
LOG_WARNING("The target is already running. Halt target before stepi/continue.");
|
||||
retval = target_halt(target);
|
||||
if (retval == ERROR_OK)
|
||||
retval = target_wait_state(target, TARGET_HALTED, 100);
|
||||
LOG_WARNING("WARNING! The target is already running. "
|
||||
"All changes GDB did to registers will be discarded! "
|
||||
"Waiting for target to halt.");
|
||||
already_running = true;
|
||||
} else if (target->state != TARGET_HALTED)
|
||||
{
|
||||
LOG_WARNING("The target is not in the halted nor running stated, stepi/continue ignored.");
|
||||
@@ -2144,7 +2234,7 @@ int gdb_input_inner(struct connection *connection)
|
||||
}
|
||||
gdb_con->sync = false;
|
||||
|
||||
if ((retval!=ERROR_OK) || nostep)
|
||||
if ((retval!=ERROR_OK) || (!already_running && nostep))
|
||||
{
|
||||
/* Either the target isn't in the halted state, then we can't
|
||||
* step/continue. This might be early setup, etc.
|
||||
@@ -2164,24 +2254,33 @@ int gdb_input_inner(struct connection *connection)
|
||||
*/
|
||||
gdb_con->frontend_state = TARGET_RUNNING;
|
||||
target_call_event_callbacks(target, TARGET_EVENT_GDB_START);
|
||||
int retval = gdb_step_continue_packet(connection, target, packet, packet_size);
|
||||
if (retval != ERROR_OK)
|
||||
|
||||
if (!already_running)
|
||||
{
|
||||
/* we'll never receive a halted condition... issue a false one.. */
|
||||
gdb_frontend_halted(target, connection);
|
||||
int retval = gdb_step_continue_packet(connection, target, packet, packet_size);
|
||||
if (retval != ERROR_OK)
|
||||
{
|
||||
/* we'll never receive a halted condition... issue a false one.. */
|
||||
gdb_frontend_halted(target, connection);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'v':
|
||||
retval = gdb_v_packet(connection, target, packet, packet_size);
|
||||
retval = gdb_v_packet(
|
||||
connection, target,
|
||||
packet, packet_size);
|
||||
break;
|
||||
case 'D':
|
||||
retval = gdb_detach(connection, target);
|
||||
extended_protocol = 0;
|
||||
break;
|
||||
case 'X':
|
||||
if ((retval = gdb_write_memory_binary_packet(connection, target, packet, packet_size)) != ERROR_OK)
|
||||
retval = gdb_write_memory_binary_packet(
|
||||
connection, target,
|
||||
packet, packet_size);
|
||||
if (retval != ERROR_OK)
|
||||
return retval;
|
||||
break;
|
||||
case 'k':
|
||||
@@ -2236,7 +2335,7 @@ int gdb_input_inner(struct connection *connection)
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
int gdb_input(struct connection *connection)
|
||||
static int gdb_input(struct connection *connection)
|
||||
{
|
||||
int retval = gdb_input_inner(connection);
|
||||
struct gdb_connection *gdb_con = connection->priv;
|
||||
@@ -2272,7 +2371,7 @@ static int gdb_target_start(struct target *target, uint16_t port)
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
int gdb_target_add_one(struct target *target)
|
||||
static int gdb_target_add_one(struct target *target)
|
||||
{
|
||||
if (gdb_port == 0 && server_use_pipes == 0)
|
||||
{
|
||||
@@ -2411,7 +2510,7 @@ COMMAND_HANDLER(handle_gdb_breakpoint_override_command)
|
||||
static const struct command_registration gdb_command_handlers[] = {
|
||||
{
|
||||
.name = "gdb_sync",
|
||||
.handler = &handle_gdb_sync_command,
|
||||
.handler = handle_gdb_sync_command,
|
||||
.mode = COMMAND_ANY,
|
||||
.help = "next stepi will return immediately allowing "
|
||||
"GDB to fetch register state without affecting "
|
||||
@@ -2419,39 +2518,41 @@ static const struct command_registration gdb_command_handlers[] = {
|
||||
},
|
||||
{
|
||||
.name = "gdb_port",
|
||||
.handler = &handle_gdb_port_command,
|
||||
.handler = handle_gdb_port_command,
|
||||
.mode = COMMAND_ANY,
|
||||
.help = "daemon configuration command gdb_port",
|
||||
.usage = "<port>",
|
||||
.help = "Display or specify base port on which to listen "
|
||||
"for incoming GDB connections. "
|
||||
"No arguments reports GDB port; zero disables.",
|
||||
.usage = "[port_num]",
|
||||
},
|
||||
{
|
||||
.name = "gdb_memory_map",
|
||||
.handler = &handle_gdb_memory_map_command,
|
||||
.handler = handle_gdb_memory_map_command,
|
||||
.mode = COMMAND_CONFIG,
|
||||
.help = "enable or disable memory map",
|
||||
.usage = "enable|disable"
|
||||
.usage = "('enable'|'disable')"
|
||||
},
|
||||
{
|
||||
.name = "gdb_flash_program",
|
||||
.handler = &handle_gdb_flash_program_command,
|
||||
.handler = handle_gdb_flash_program_command,
|
||||
.mode = COMMAND_CONFIG,
|
||||
.help = "enable or disable flash program",
|
||||
.usage = "enable|disable"
|
||||
.usage = "('enable'|'disable')"
|
||||
},
|
||||
{
|
||||
.name = "gdb_report_data_abort",
|
||||
.handler = &handle_gdb_report_data_abort_command,
|
||||
.handler = handle_gdb_report_data_abort_command,
|
||||
.mode = COMMAND_CONFIG,
|
||||
.help = "enable or disable reporting data aborts",
|
||||
.usage = "enable|disable"
|
||||
.usage = "('enable'|'disable')"
|
||||
},
|
||||
{
|
||||
.name = "gdb_breakpoint_override",
|
||||
.handler = &handle_gdb_breakpoint_override_command,
|
||||
.mode = COMMAND_EXEC,
|
||||
.help = "force type of breakpoint "
|
||||
"used by gdb 'break' commands.",
|
||||
.usage = "hard|soft|disable",
|
||||
.handler = handle_gdb_breakpoint_override_command,
|
||||
.mode = COMMAND_ANY,
|
||||
.help = "Display or specify type of breakpoint "
|
||||
"to be used by gdb 'break' commands.",
|
||||
.usage = "('hard'|'soft'|'disable')"
|
||||
},
|
||||
COMMAND_REGISTRATION_DONE
|
||||
};
|
||||
|
||||
@@ -36,7 +36,6 @@ struct gdb_service
|
||||
struct target *target;
|
||||
};
|
||||
|
||||
int gdb_target_add_one(struct target *target);
|
||||
int gdb_target_add_all(struct target *target);
|
||||
int gdb_register_commands(struct command_context *command_context);
|
||||
|
||||
|
||||
@@ -118,11 +118,11 @@ static int httpd_Jim_Command_writeform(Jim_Interp *interp, int argc,
|
||||
// Find length
|
||||
const char *data;
|
||||
int actual;
|
||||
|
||||
int retcode;
|
||||
|
||||
const char *script = alloc_printf("set dummy_val $httppostdata(%s); set dummy_val",
|
||||
const char *script = alloc_printf(
|
||||
"set dummy_val $httppostdata(%s); set dummy_val",
|
||||
name);
|
||||
|
||||
retcode = Jim_Eval_Named(interp, script, __FILE__, __LINE__);
|
||||
free((void *) script);
|
||||
if (retcode != JIM_OK)
|
||||
@@ -154,27 +154,25 @@ httpd_Jim_Command_formfetch(Jim_Interp *interp,
|
||||
int argc,
|
||||
Jim_Obj *const *argv)
|
||||
{
|
||||
if (argc != 2)
|
||||
{
|
||||
Jim_WrongNumArgs(interp, 1, argv, "method ?CMD_ARGV ...?");
|
||||
return JIM_ERR;
|
||||
}
|
||||
char *name = (char*)Jim_GetString(argv[1], NULL);
|
||||
if (argc != 2)
|
||||
{
|
||||
Jim_WrongNumArgs(interp, 1, argv, "method ?CMD_ARGV ...?");
|
||||
return JIM_ERR;
|
||||
}
|
||||
|
||||
char *name = (char*)Jim_GetString(argv[1], NULL);
|
||||
const char *script = alloc_printf(
|
||||
"set dummy_val $httppostdata(%s); set dummy_val",
|
||||
name);
|
||||
int retcode = Jim_Eval_Named(interp, script, __FILE__, __LINE__);
|
||||
|
||||
const char *script = alloc_printf("set dummy_val $httppostdata(%s); set dummy_val",
|
||||
name);
|
||||
int retcode = Jim_Eval_Named(interp, script, __FILE__, __LINE__);
|
||||
free((void *) script);
|
||||
if (retcode != JIM_OK)
|
||||
{
|
||||
Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));
|
||||
} else
|
||||
{
|
||||
Jim_SetResult(interp, Jim_GetResult(interp));
|
||||
}
|
||||
free((void *) script);
|
||||
if (retcode != JIM_OK)
|
||||
Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));
|
||||
else
|
||||
Jim_SetResult(interp, Jim_GetResult(interp));
|
||||
|
||||
return JIM_OK;
|
||||
return JIM_OK;
|
||||
}
|
||||
|
||||
struct httpd_request
|
||||
@@ -467,16 +465,16 @@ static struct MHD_Daemon * d;
|
||||
static const struct command_registration httpd_command_handlers[] = {
|
||||
{
|
||||
.name = "formfetch",
|
||||
.jim_handler = &httpd_Jim_Command_formfetch,
|
||||
.jim_handler = httpd_Jim_Command_formfetch,
|
||||
.mode = COMMAND_EXEC,
|
||||
.usage = "<parameter_name>",
|
||||
.usage = "parameter_name",
|
||||
.help = "Reads a posted form value.",
|
||||
},
|
||||
{
|
||||
.name = "writeform",
|
||||
.jim_handler = &httpd_Jim_Command_writeform,
|
||||
.jim_handler = httpd_Jim_Command_writeform,
|
||||
.mode = COMMAND_EXEC,
|
||||
.usage = "<parameter_name> <file>",
|
||||
.usage = "parameter_name filename",
|
||||
.help = "Writes a form value to a file.",
|
||||
},
|
||||
COMMAND_REGISTRATION_DONE
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -2,7 +2,7 @@
|
||||
<!DOCTYPE xsl:stylesheet [<!ENTITY nbsp " ">]>
|
||||
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns="http://www.w3.org/TR/REC-html40" version="1.0">
|
||||
<xsl:output method="html" version="4.0" indent="yes" encoding="UTF-8"
|
||||
|
||||
|
||||
media-type="text/plain; charset=UTF-8"/>
|
||||
|
||||
<xsl:param name="pagetogenerate" select="UNDEFINED"/>
|
||||
@@ -16,17 +16,17 @@
|
||||
<html>
|
||||
<head>
|
||||
<title>OpenOCD debugger</title>
|
||||
<meta http-equiv="Content-Type" content="text/html" charset="utf-8"/>
|
||||
<link href="menuweb.css" rel="stylesheet" type="text/css"/>
|
||||
|
||||
<meta http-equiv="Content-Type" content="text/html" charset="utf-8"/>
|
||||
<link href="menuweb.css" rel="stylesheet" type="text/css"/>
|
||||
|
||||
</head>
|
||||
|
||||
|
||||
|
||||
|
||||
<tcl>
|
||||
set console ""
|
||||
set upload_filename /ram/upload
|
||||
</tcl>
|
||||
|
||||
|
||||
<body style="margin:0px;">
|
||||
<div style="width:974px;height:85px;">
|
||||
<div style="float:left;position:relative;left:32px;width:478px;">
|
||||
@@ -92,17 +92,17 @@
|
||||
</xsl:for-each>
|
||||
<tr>
|
||||
<td style="width:140px;height:35px;background-image:url('menu_cuts/v_1.png')">
|
||||
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="width:140px;background-image:url('menu_cuts/v_2_tile.png')">
|
||||
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="width:140px;height:140px;background-image:url('menu_cuts/v_3.png')">
|
||||
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
@@ -142,96 +142,96 @@
|
||||
</xsl:for-each>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="6" style="height:30px;width:535px;background-image:url('menu_cuts/center_top.png');background-repeat: no-repeat;background-position:top right;">
|
||||
<div style="width:500px;background-color:#ffffff;height:100%;">
|
||||
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="6" style="background-color:#ffffff;text-indent:30px;height:40px;">
|
||||
<H1><xsl:value-of select="pageheading"/></H1>
|
||||
</td>
|
||||
</tr>
|
||||
<tr style="height:100%;">
|
||||
<td colspan="6" style="background-color:#ffffff;padding-left:30px;padding-right:30px;width=535px;height:100%;">
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="6" style="height:30px;width:535px;background-image:url('menu_cuts/center_top.png');background-repeat: no-repeat;background-position:top right;">
|
||||
<div style="width:500px;background-color:#ffffff;height:100%;">
|
||||
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="6" style="background-color:#ffffff;text-indent:30px;height:40px;">
|
||||
<H1><xsl:value-of select="pageheading"/></H1>
|
||||
</td>
|
||||
</tr>
|
||||
<tr style="height:100%;">
|
||||
<td colspan="6" style="background-color:#ffffff;padding-left:30px;padding-right:30px;width=535px;height:100%;">
|
||||
<xsl:value-of disable-output-escaping="yes" select="pagetext/markup_code"/>
|
||||
</td>
|
||||
</tr>
|
||||
<tcl>
|
||||
<!-- This is the output from any OpenOCD commands -->
|
||||
set toggle_details [formfetch toggle_details]
|
||||
if {[string length $toggle_details]==0} {
|
||||
set toggle_details 0
|
||||
}
|
||||
set show_details [load_var show_details]
|
||||
if {[string length $show_details]==0} {
|
||||
set show_details 0
|
||||
}
|
||||
if {$toggle_details==1} {
|
||||
set show_details [expr 1-$show_details]
|
||||
save_var show_details $show_details
|
||||
}
|
||||
|
||||
if {[string length $console]!=0} {
|
||||
</tcl>
|
||||
<tr style="height:100%;">
|
||||
<td colspan="6" style="height:100%;background-color:red;">
|
||||
</td>
|
||||
</tr>
|
||||
<tcl>
|
||||
<!-- This is the output from any OpenOCD commands -->
|
||||
set toggle_details [formfetch toggle_details]
|
||||
if {[string length $toggle_details]==0} {
|
||||
set toggle_details 0
|
||||
}
|
||||
set show_details [load_var show_details]
|
||||
if {[string length $show_details]==0} {
|
||||
set show_details 0
|
||||
}
|
||||
if {$toggle_details==1} {
|
||||
set show_details [expr 1-$show_details]
|
||||
save_var show_details $show_details
|
||||
}
|
||||
|
||||
if {[string length $console]!=0} {
|
||||
</tcl>
|
||||
<tr style="height:100%;">
|
||||
<td colspan="6" style="height:100%;background-color:red;">
|
||||
<table class="textgray" style="padding:0px;border-collapse:collapse;background-color:#ffffff;width:100%">
|
||||
<td style="width:25px;"> </td>
|
||||
<tcl>
|
||||
if {$show_details==1} {
|
||||
append buffer <xsl:text disable-output-escaping="yes"><![CDATA[<]]></xsl:text>
|
||||
append buffer {td style="background-color:#dddddd;padding-left:5px;padding-right:5px;padding-top:3px;padding-bottom:3px;"}
|
||||
append buffer <xsl:text disable-output-escaping="yes"><![CDATA[>]]></xsl:text>
|
||||
} else {
|
||||
append buffer <xsl:text disable-output-escaping="yes"><![CDATA[<]]></xsl:text>
|
||||
append buffer {td style="background-image:url('menu_cuts/h_tab_free.png');width:110px;height:29px;background-repeat: no-repeat;background-position:top left;"}
|
||||
append buffer <xsl:text disable-output-escaping="yes"><![CDATA[>]]></xsl:text>
|
||||
}
|
||||
</tcl>
|
||||
<a class="openocd">
|
||||
<td style="width:25px;"> </td>
|
||||
<tcl>
|
||||
if {$show_details==1} {
|
||||
append buffer <xsl:text disable-output-escaping="yes"><![CDATA[<]]></xsl:text>
|
||||
append buffer {td style="background-color:#dddddd;padding-left:5px;padding-right:5px;padding-top:3px;padding-bottom:3px;"}
|
||||
append buffer <xsl:text disable-output-escaping="yes"><![CDATA[>]]></xsl:text>
|
||||
} else {
|
||||
append buffer <xsl:text disable-output-escaping="yes"><![CDATA[<]]></xsl:text>
|
||||
append buffer {td style="background-image:url('menu_cuts/h_tab_free.png');width:110px;height:29px;background-repeat: no-repeat;background-position:top left;"}
|
||||
append buffer <xsl:text disable-output-escaping="yes"><![CDATA[>]]></xsl:text>
|
||||
}
|
||||
</tcl>
|
||||
<a class="openocd">
|
||||
<xsl:attribute name="href"><xsl:value-of select="$pagetogenerate"/>?toggle_details=1</xsl:attribute>
|
||||
<tcl>
|
||||
if {$show_details==1} {
|
||||
append buffer "Hide details"
|
||||
append buffer <br/>
|
||||
append buffer <br/>
|
||||
} else {
|
||||
append buffer {<div style="position:relative;top:7px;text-align:center;">}
|
||||
append buffer "Show details"
|
||||
append buffer {</div>}
|
||||
}
|
||||
</tcl>
|
||||
</a>
|
||||
<tcl>
|
||||
if {$show_details==1} {
|
||||
append buffer $console
|
||||
}
|
||||
</tcl>
|
||||
</a>
|
||||
<tcl>
|
||||
if {$show_details==1} {
|
||||
append buffer $console
|
||||
}
|
||||
</tcl>
|
||||
<xsl:text disable-output-escaping="yes"><![CDATA[<]]></xsl:text>/td<xsl:text disable-output-escaping="yes"><![CDATA[>]]></xsl:text>
|
||||
<tcl>
|
||||
if {$show_details!=1} {
|
||||
append buffer {<td> </td>}
|
||||
}
|
||||
if {$show_details!=1} {
|
||||
append buffer {<td> </td>}
|
||||
}
|
||||
</tcl>
|
||||
<td style="width:25px;"> </td>
|
||||
</table>
|
||||
</td>
|
||||
<td style="width:25px;"> </td>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
<tcl>
|
||||
<tcl>
|
||||
}
|
||||
</tcl>
|
||||
<tr>
|
||||
<td colspan="6" style="height:30px;background-image:url('menu_cuts/center_bottom.png');background-repeat: no-repeat;background-position:top right;">
|
||||
<div style="width:500px;background-color:#ffffff;height:100%;">
|
||||
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<tr>
|
||||
<td colspan="6" style="height:30px;background-image:url('menu_cuts/center_bottom.png');background-repeat: no-repeat;background-position:top right;">
|
||||
<div style="width:500px;background-color:#ffffff;height:100%;">
|
||||
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
<td style="width:6px;">
|
||||
</td>
|
||||
@@ -240,56 +240,56 @@
|
||||
<tr>
|
||||
<td style="width:103px;height:29px;background-image:url('menu_cuts/h_tab2_selected.png');background-repeat: no-repeat;">
|
||||
<div class="textgray" style="position:relative;top:7px;;font-weight:bold;text-align:center;width:100px;">
|
||||
Documentation
|
||||
Documentation
|
||||
</div>
|
||||
</td>
|
||||
<td width="40px">
|
||||
|
||||
</td>
|
||||
<td>
|
||||
</td>
|
||||
</td>
|
||||
<td width="40px">
|
||||
|
||||
</td>
|
||||
<td>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="3" style="height:10px;width:245px;background-image:url('menu_cuts/right_top_small.png');"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="3" style="background-color:#d8d7d7;width:245px;padding-left:10px;padding-buttom:10px;line-height:17px;">
|
||||
<a href="http://openocd.berlios.de/doc/openocd.pdf" target="_blank">OpenOCD Manual</a><br/>
|
||||
</td>
|
||||
</tr>
|
||||
<tr><td colspan="3" style="background-color:#d8d7d7;height:15px;"></td></tr>
|
||||
<tr>
|
||||
<td colspan="3">
|
||||
<table style="padding:0px;border-collapse:collapse;">
|
||||
<td style="background-color:#d8d7d7;width:10px;height:1px"></td>
|
||||
<td style="background-color:#999999;width:225px; height:1px;"></td>
|
||||
<td style="background-color:#d8d7d7;width:10px;height:1px"></td>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
<tr><td colspan="3" style="background-color:#d8d7d7;height:15px;"></td></tr>
|
||||
<tr style="height:100%;">
|
||||
<td class="textgray" colspan="3" style="height:100%;background-color:#d8d7d7;padding-left:10px;padding-right:10px;">
|
||||
<tr>
|
||||
<td colspan="3" style="height:10px;width:245px;background-image:url('menu_cuts/right_top_small.png');"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="3" style="background-color:#d8d7d7;width:245px;padding-left:10px;padding-buttom:10px;line-height:17px;">
|
||||
<a href="http://openocd.berlios.de/doc/openocd.pdf" target="_blank">OpenOCD Manual</a><br/>
|
||||
</td>
|
||||
</tr>
|
||||
<tr><td colspan="3" style="background-color:#d8d7d7;height:15px;"></td></tr>
|
||||
<tr>
|
||||
<td colspan="3">
|
||||
<table style="padding:0px;border-collapse:collapse;">
|
||||
<td style="background-color:#d8d7d7;width:10px;height:1px"></td>
|
||||
<td style="background-color:#999999;width:225px; height:1px;"></td>
|
||||
<td style="background-color:#d8d7d7;width:10px;height:1px"></td>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
<tr><td colspan="3" style="background-color:#d8d7d7;height:15px;"></td></tr>
|
||||
<tr style="height:100%;">
|
||||
<td class="textgray" colspan="3" style="height:100%;background-color:#d8d7d7;padding-left:10px;padding-right:10px;">
|
||||
<xsl:choose>
|
||||
<xsl:when test="(pagetext/right_column)">
|
||||
<xsl:value-of disable-output-escaping="yes" select="pagetext/right_column"/>
|
||||
</xsl:when>
|
||||
<xsl:otherwise>
|
||||
|
||||
|
||||
</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="3" style="height:30px;background-image:url('menu_cuts/right_bottom.png');">
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="3" style="height:30px;background-image:url('menu_cuts/right_bottom.png');">
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
|
||||
</table>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -70,7 +70,7 @@ body
|
||||
font-size: 12px;
|
||||
line-height: 15px;
|
||||
color : #024d67;
|
||||
|
||||
|
||||
}
|
||||
|
||||
h1
|
||||
@@ -86,7 +86,7 @@ td
|
||||
{
|
||||
padding: 0px;
|
||||
font-size: 12px;
|
||||
vertical-align:top;
|
||||
vertical-align:top;
|
||||
|
||||
}
|
||||
|
||||
@@ -95,7 +95,7 @@ td
|
||||
color: #cccccc;
|
||||
padding: 0px;
|
||||
font-size: 12px;
|
||||
vertical-align:top;
|
||||
vertical-align:top;
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ tcl with embedded html.
|
||||
|
||||
sh build.sh
|
||||
|
||||
xalan.jar can be gotten from apache.org.
|
||||
xalan.jar can be gotten from apache.org.
|
||||
|
||||
|
||||
2. libmicrohttpd is a bit tricky to build under Cygwin:
|
||||
|
||||
@@ -563,9 +563,11 @@ int server_quit(void)
|
||||
/* tell the server we want to shut down */
|
||||
COMMAND_HANDLER(handle_shutdown_command)
|
||||
{
|
||||
LOG_USER("shutdown command invoked");
|
||||
|
||||
shutdown_openocd = 1;
|
||||
|
||||
return ERROR_COMMAND_CLOSE_CONNECTION;
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
static const struct command_registration server_command_handlers[] = {
|
||||
|
||||
@@ -88,7 +88,7 @@ static int tcl_input(struct connection *connection)
|
||||
const char *result;
|
||||
int reslen;
|
||||
struct tcl_connection *tclc;
|
||||
char in[256];
|
||||
unsigned char in[256];
|
||||
|
||||
rlen = read_socket(connection->fd, &in, sizeof(in));
|
||||
if (rlen <= 0) {
|
||||
@@ -181,11 +181,12 @@ COMMAND_HANDLER(handle_tcl_port_command)
|
||||
static const struct command_registration tcl_command_handlers[] = {
|
||||
{
|
||||
.name = "tcl_port",
|
||||
.handler = &handle_tcl_port_command,
|
||||
.handler = handle_tcl_port_command,
|
||||
.mode = COMMAND_CONFIG,
|
||||
.help = "port on which to listen "
|
||||
"for incoming TCL syntax",
|
||||
.usage = "<port>",
|
||||
.help = "Specify port on which to listen "
|
||||
"for incoming Tcl syntax. "
|
||||
"No arguments reports Tcl port; zero disables.",
|
||||
.usage = "[port_num]",
|
||||
},
|
||||
COMMAND_REGISTRATION_DONE
|
||||
};
|
||||
|
||||
@@ -62,7 +62,6 @@ int telnet_prompt(struct connection *connection)
|
||||
{
|
||||
struct telnet_connection *t_con = connection->priv;
|
||||
|
||||
telnet_write(connection, "\r", 1); /* the prompt is always placed at the line beginning */
|
||||
return telnet_write(connection, t_con->prompt, strlen(t_con->prompt));
|
||||
}
|
||||
|
||||
@@ -116,10 +115,12 @@ void telnet_log_callback(void *priv, const char *file, unsigned line,
|
||||
}
|
||||
|
||||
/* clear the command line */
|
||||
telnet_write(connection, "\r", 1);
|
||||
for (i = strlen(t_con->prompt) + t_con->line_size; i > 0; i -= 16)
|
||||
telnet_write(connection, "\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b", i > 16 ? 16 : i);
|
||||
for (i = strlen(t_con->prompt) + t_con->line_size; i > 0; i -= 16)
|
||||
telnet_write(connection, " ", i > 16 ? 16 : i);
|
||||
telnet_write(connection, "\r", 1);
|
||||
for (i = strlen(t_con->prompt) + t_con->line_size; i > 0; i -= 16)
|
||||
telnet_write(connection, "\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b", i > 16 ? 16 : i);
|
||||
|
||||
/* output the message */
|
||||
telnet_outputline(connection, string);
|
||||
@@ -160,6 +161,7 @@ int telnet_new_connection(struct connection *connection)
|
||||
telnet_write(connection, "\r\n", 2);
|
||||
}
|
||||
|
||||
telnet_write(connection, "\r", 1); /* the prompt is always placed at the line beginning */
|
||||
telnet_prompt(connection);
|
||||
|
||||
/* initialize history */
|
||||
@@ -195,8 +197,8 @@ void telnet_clear_line(struct connection *connection, struct telnet_connection *
|
||||
int telnet_input(struct connection *connection)
|
||||
{
|
||||
int bytes_read;
|
||||
char buffer[TELNET_BUFFER_SIZE];
|
||||
char *buf_p;
|
||||
unsigned char buffer[TELNET_BUFFER_SIZE];
|
||||
unsigned char *buf_p;
|
||||
struct telnet_connection *t_con = connection->priv;
|
||||
struct command_context *command_context = connection->cmd_ctx;
|
||||
|
||||
@@ -216,7 +218,7 @@ int telnet_input(struct connection *connection)
|
||||
switch (t_con->state)
|
||||
{
|
||||
case TELNET_STATE_DATA:
|
||||
if (*buf_p == '\xff')
|
||||
if (*buf_p == 0xff)
|
||||
{
|
||||
t_con->state = TELNET_STATE_IAC;
|
||||
}
|
||||
@@ -331,6 +333,7 @@ int telnet_input(struct connection *connection)
|
||||
if (retval == ERROR_COMMAND_CLOSE_CONNECTION)
|
||||
return ERROR_SERVER_REMOTE_CLOSED;
|
||||
|
||||
telnet_write(connection, "\r", 1); /* the prompt is always placed at the line beginning */
|
||||
retval = telnet_prompt(connection);
|
||||
if (retval == ERROR_SERVER_REMOTE_CLOSED)
|
||||
return ERROR_SERVER_REMOTE_CLOSED;
|
||||
@@ -395,16 +398,16 @@ int telnet_input(struct connection *connection)
|
||||
case TELNET_STATE_IAC:
|
||||
switch (*buf_p)
|
||||
{
|
||||
case '\xfe':
|
||||
case 0xfe:
|
||||
t_con->state = TELNET_STATE_DONT;
|
||||
break;
|
||||
case '\xfd':
|
||||
case 0xfd:
|
||||
t_con->state = TELNET_STATE_DO;
|
||||
break;
|
||||
case '\xfc':
|
||||
case 0xfc:
|
||||
t_con->state = TELNET_STATE_WONT;
|
||||
break;
|
||||
case '\xfb':
|
||||
case 0xfb:
|
||||
t_con->state = TELNET_STATE_WILL;
|
||||
break;
|
||||
}
|
||||
@@ -619,17 +622,18 @@ COMMAND_HANDLER(handle_exit_command)
|
||||
static const struct command_registration telnet_command_handlers[] = {
|
||||
{
|
||||
.name = "exit",
|
||||
.handler = &handle_exit_command,
|
||||
.handler = handle_exit_command,
|
||||
.mode = COMMAND_EXEC,
|
||||
.help = "exit telnet session",
|
||||
},
|
||||
{
|
||||
.name = "telnet_port",
|
||||
.handler = &handle_telnet_port_command,
|
||||
.handler = handle_telnet_port_command,
|
||||
.mode = COMMAND_ANY,
|
||||
.help = "port on which to listen "
|
||||
"for incoming telnet connections",
|
||||
.usage = "<port>",
|
||||
.help = "Specify port on which to listen "
|
||||
"for incoming telnet connections. "
|
||||
"No arguments reports telnet port; zero disables.",
|
||||
.usage = "[port_num]",
|
||||
},
|
||||
COMMAND_REGISTRATION_DONE
|
||||
};
|
||||
|
||||
@@ -470,7 +470,8 @@ free_all:
|
||||
#define SVFP_CMD_INC_CNT 1024
|
||||
static int svf_read_command_from_file(int fd)
|
||||
{
|
||||
char ch, *tmp_buffer = NULL;
|
||||
unsigned char ch;
|
||||
char *tmp_buffer = NULL;
|
||||
int cmd_pos = 0, cmd_ok = 0, slash = 0, comment = 0;
|
||||
|
||||
while (!cmd_ok && (read(fd, &ch, 1) > 0))
|
||||
@@ -499,31 +500,55 @@ static int svf_read_command_from_file(int fd)
|
||||
case '\r':
|
||||
slash = 0;
|
||||
comment = 0;
|
||||
break;
|
||||
/* Don't save '\r' and '\n' if no data is parsed */
|
||||
if (!cmd_pos)
|
||||
break;
|
||||
default:
|
||||
if (!comment)
|
||||
{
|
||||
if (cmd_pos >= svf_command_buffer_size - 1)
|
||||
/* The parsing code currently expects a space
|
||||
* before parentheses -- "TDI (123)". Also a
|
||||
* space afterwards -- "TDI (123) TDO(456)".
|
||||
* But such spaces are optional... instead of
|
||||
* parser updates, cope with that by adding the
|
||||
* spaces as needed.
|
||||
*
|
||||
* Ensure there are 3 bytes available, for:
|
||||
* - current character
|
||||
* - added space.
|
||||
* - terminating NUL ('\0')
|
||||
*/
|
||||
if ((cmd_pos + 2) >= svf_command_buffer_size)
|
||||
{
|
||||
tmp_buffer = (char*)malloc(svf_command_buffer_size + SVFP_CMD_INC_CNT); // 1 more byte for '\0'
|
||||
/* REVISIT use realloc(); simpler */
|
||||
tmp_buffer = malloc(
|
||||
svf_command_buffer_size
|
||||
+ SVFP_CMD_INC_CNT);
|
||||
if (NULL == tmp_buffer)
|
||||
{
|
||||
LOG_ERROR("not enough memory");
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
if (svf_command_buffer_size > 0)
|
||||
{
|
||||
memcpy(tmp_buffer, svf_command_buffer, svf_command_buffer_size);
|
||||
}
|
||||
memcpy(tmp_buffer,
|
||||
svf_command_buffer,
|
||||
svf_command_buffer_size);
|
||||
if (svf_command_buffer != NULL)
|
||||
{
|
||||
free(svf_command_buffer);
|
||||
}
|
||||
svf_command_buffer = tmp_buffer;
|
||||
svf_command_buffer_size += SVFP_CMD_INC_CNT;
|
||||
tmp_buffer = NULL;
|
||||
}
|
||||
|
||||
/* insert a space before '(' */
|
||||
if ('(' == ch)
|
||||
svf_command_buffer[cmd_pos++] = ' ';
|
||||
|
||||
svf_command_buffer[cmd_pos++] = (char)toupper(ch);
|
||||
|
||||
/* insert a space after ')' */
|
||||
if (')' == ch)
|
||||
svf_command_buffer[cmd_pos++] = ' ';
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -542,25 +567,30 @@ static int svf_read_command_from_file(int fd)
|
||||
|
||||
static int svf_parse_cmd_string(char *str, int len, char **argus, int *num_of_argu)
|
||||
{
|
||||
int pos = 0, num = 0, space_found = 1;
|
||||
int pos = 0, num = 0, space_found = 1, in_bracket = 0;
|
||||
|
||||
while (pos < len)
|
||||
{
|
||||
switch (str[pos])
|
||||
{
|
||||
case '\n':
|
||||
case '\r':
|
||||
case '!':
|
||||
case '/':
|
||||
LOG_ERROR("fail to parse svf command");
|
||||
return ERROR_FAIL;
|
||||
break;
|
||||
case ' ':
|
||||
space_found = 1;
|
||||
str[pos] = '\0';
|
||||
break;
|
||||
case '(':
|
||||
in_bracket = 1;
|
||||
goto parse_char;
|
||||
case ')':
|
||||
in_bracket = 0;
|
||||
goto parse_char;
|
||||
default:
|
||||
if (space_found)
|
||||
parse_char:
|
||||
if (!in_bracket && isspace((int) str[pos]))
|
||||
{
|
||||
space_found = 1;
|
||||
str[pos] = '\0';
|
||||
}
|
||||
else if (space_found)
|
||||
{
|
||||
argus[num++] = &str[pos];
|
||||
space_found = 0;
|
||||
@@ -628,6 +658,7 @@ static int svf_copy_hexstring_to_binary(char *str, uint8_t **bin, int orig_bit_l
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
|
||||
/* fill from LSB (end of str) to MSB (beginning of str) */
|
||||
for (i = 0; i < str_hbyte_len; i++)
|
||||
{
|
||||
ch = 0;
|
||||
@@ -635,7 +666,13 @@ static int svf_copy_hexstring_to_binary(char *str, uint8_t **bin, int orig_bit_l
|
||||
{
|
||||
ch = str[--str_len];
|
||||
|
||||
if (!isblank(ch))
|
||||
/* Skip whitespace. The SVF specification (rev E) is
|
||||
* deficient in terms of basic lexical issues like
|
||||
* where whitespace is allowed. Long bitstrings may
|
||||
* require line ends for correctness, since there is
|
||||
* a hard limit on line length.
|
||||
*/
|
||||
if (!isspace(ch))
|
||||
{
|
||||
if ((ch >= '0') && (ch <= '9'))
|
||||
{
|
||||
@@ -671,11 +708,12 @@ static int svf_copy_hexstring_to_binary(char *str, uint8_t **bin, int orig_bit_l
|
||||
}
|
||||
}
|
||||
|
||||
// consume optional leading '0' characters
|
||||
while (str_len > 0 && str[str_len - 1] == '0')
|
||||
/* consume optional leading '0' MSBs or whitespace */
|
||||
while (str_len > 0 && ((str[str_len - 1] == '0')
|
||||
|| isspace((int) str[str_len - 1])))
|
||||
str_len--;
|
||||
|
||||
// check valid
|
||||
/* check validity: we must have consumed everything */
|
||||
if (str_len > 0 || (ch & ~((2 << ((bit_len - 1) % 4)) - 1)) != 0)
|
||||
{
|
||||
LOG_ERROR("value execeeds length");
|
||||
@@ -1460,10 +1498,10 @@ static int svf_run_command(struct command_context *cmd_ctx, char *cmd_str)
|
||||
static const struct command_registration svf_command_handlers[] = {
|
||||
{
|
||||
.name = "svf",
|
||||
.handler = &handle_svf_command,
|
||||
.handler = handle_svf_command,
|
||||
.mode = COMMAND_EXEC,
|
||||
.help = "Runs a SVF file.",
|
||||
.usage = "<file>",
|
||||
.usage = "filename ['quiet']",
|
||||
},
|
||||
COMMAND_REGISTRATION_DONE
|
||||
};
|
||||
|
||||
@@ -64,10 +64,10 @@ static int arm11_step(struct target *target, int current,
|
||||
static int arm11_check_init(struct arm11_common *arm11)
|
||||
{
|
||||
CHECK_RETVAL(arm11_read_DSCR(arm11));
|
||||
LOG_DEBUG("DSCR %08x", (unsigned) arm11->dscr);
|
||||
|
||||
if (!(arm11->dscr & DSCR_HALT_DBG_MODE))
|
||||
{
|
||||
LOG_DEBUG("DSCR %08x", (unsigned) arm11->dscr);
|
||||
LOG_DEBUG("Bringing target into debug mode");
|
||||
|
||||
arm11->dscr |= DSCR_HALT_DBG_MODE;
|
||||
@@ -498,12 +498,9 @@ static int arm11_resume(struct target *target, int current,
|
||||
if (!debug_execution)
|
||||
target_free_all_working_areas(target);
|
||||
|
||||
/* Set up breakpoints */
|
||||
if (handle_breakpoints)
|
||||
{
|
||||
/* check if one matches PC and step over it if necessary */
|
||||
|
||||
struct breakpoint * bp;
|
||||
/* Should we skip over breakpoints matching the PC? */
|
||||
if (handle_breakpoints) {
|
||||
struct breakpoint *bp;
|
||||
|
||||
for (bp = target->breakpoints; bp; bp = bp->next)
|
||||
{
|
||||
@@ -514,9 +511,11 @@ static int arm11_resume(struct target *target, int current,
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* set all breakpoints */
|
||||
|
||||
/* activate all breakpoints */
|
||||
if (true) {
|
||||
struct breakpoint *bp;
|
||||
unsigned brp_num = 0;
|
||||
|
||||
for (bp = target->breakpoints; bp; bp = bp->next)
|
||||
@@ -542,7 +541,8 @@ static int arm11_resume(struct target *target, int current,
|
||||
arm11_sc7_set_vcr(arm11, arm11_vcr);
|
||||
}
|
||||
|
||||
arm11_leave_debug_state(arm11, handle_breakpoints);
|
||||
/* activate all watchpoints and breakpoints */
|
||||
arm11_leave_debug_state(arm11, true);
|
||||
|
||||
arm11_add_IR(arm11, ARM11_RESTART, TAP_IDLE);
|
||||
|
||||
@@ -953,6 +953,7 @@ static int arm11_write_memory_inner(struct target *target,
|
||||
if (retval != ERROR_OK)
|
||||
return retval;
|
||||
|
||||
/* load r0 with buffer address */
|
||||
/* MRC p14,0,r0,c0,c5,0 */
|
||||
retval = arm11_run_instr_data_to_core1(arm11, 0xee100e15, address);
|
||||
if (retval != ERROR_OK)
|
||||
@@ -975,11 +976,13 @@ static int arm11_write_memory_inner(struct target *target,
|
||||
|
||||
for (size_t i = 0; i < count; i++)
|
||||
{
|
||||
/* load r1 from DCC with byte data */
|
||||
/* MRC p14,0,r1,c0,c5,0 */
|
||||
retval = arm11_run_instr_data_to_core1(arm11, 0xee101e15, *buffer++);
|
||||
if (retval != ERROR_OK)
|
||||
return retval;
|
||||
|
||||
/* write r1 to memory */
|
||||
/* strb r1, [r0], #1 */
|
||||
/* strb r1, [r0] */
|
||||
retval = arm11_run_instr_no_data1(arm11,
|
||||
@@ -1002,11 +1005,13 @@ static int arm11_write_memory_inner(struct target *target,
|
||||
uint16_t value;
|
||||
memcpy(&value, buffer + i * sizeof(uint16_t), sizeof(uint16_t));
|
||||
|
||||
/* load r1 from DCC with halfword data */
|
||||
/* MRC p14,0,r1,c0,c5,0 */
|
||||
retval = arm11_run_instr_data_to_core1(arm11, 0xee101e15, value);
|
||||
if (retval != ERROR_OK)
|
||||
return retval;
|
||||
|
||||
/* write r1 to memory */
|
||||
/* strh r1, [r0], #2 */
|
||||
/* strh r1, [r0] */
|
||||
retval = arm11_run_instr_no_data1(arm11,
|
||||
@@ -1021,6 +1026,7 @@ static int arm11_write_memory_inner(struct target *target,
|
||||
}
|
||||
|
||||
case 4: {
|
||||
/* stream word data through DCC directly to memory */
|
||||
/* increment: STC p14,c5,[R0],#4 */
|
||||
/* no increment: STC p14,c5,[R0]*/
|
||||
uint32_t instr = !no_increment ? 0xeca05e01 : 0xed805e00;
|
||||
@@ -1318,17 +1324,20 @@ COMMAND_HANDLER(arm11_handle_vcr)
|
||||
static const struct command_registration arm11_mw_command_handlers[] = {
|
||||
{
|
||||
.name = "burst",
|
||||
.handler = &arm11_handle_bool_memwrite_burst,
|
||||
.handler = arm11_handle_bool_memwrite_burst,
|
||||
.mode = COMMAND_ANY,
|
||||
.help = "Enable/Disable potentially risky fast burst mode"
|
||||
" (default: enabled)",
|
||||
.help = "Display or modify flag controlling potentially "
|
||||
"risky fast burst mode (default: enabled)",
|
||||
.usage = "['enable'|'disable']",
|
||||
},
|
||||
{
|
||||
.name = "error_fatal",
|
||||
.handler = &arm11_handle_bool_memwrite_error_fatal,
|
||||
.handler = arm11_handle_bool_memwrite_error_fatal,
|
||||
.mode = COMMAND_ANY,
|
||||
.help = "Terminate program if transfer error was found"
|
||||
.help = "Display or modify flag controlling transfer "
|
||||
"termination on transfer errors"
|
||||
" (default: enabled)",
|
||||
.usage = "['enable'|'disable']",
|
||||
},
|
||||
COMMAND_REGISTRATION_DONE
|
||||
};
|
||||
@@ -1338,11 +1347,11 @@ static const struct command_registration arm11_any_command_handlers[] = {
|
||||
* simulate + breakpoint implementation is broken.
|
||||
* TEMPORARY! NOT DOCUMENTED! */
|
||||
.name = "hardware_step",
|
||||
.handler = &arm11_handle_bool_hardware_step,
|
||||
.handler = arm11_handle_bool_hardware_step,
|
||||
.mode = COMMAND_ANY,
|
||||
.help = "DEBUG ONLY - Hardware single stepping"
|
||||
" (default: disabled)",
|
||||
.usage = "(enable|disable)",
|
||||
.usage = "['enable'|'disable']",
|
||||
},
|
||||
{
|
||||
.name = "memwrite",
|
||||
@@ -1352,16 +1361,18 @@ static const struct command_registration arm11_any_command_handlers[] = {
|
||||
},
|
||||
{
|
||||
.name = "step_irq_enable",
|
||||
.handler = &arm11_handle_bool_step_irq_enable,
|
||||
.handler = arm11_handle_bool_step_irq_enable,
|
||||
.mode = COMMAND_ANY,
|
||||
.help = "Enable interrupts while stepping"
|
||||
" (default: disabled)",
|
||||
.help = "Display or modify flag controlling interrupt "
|
||||
"enable while stepping (default: disabled)",
|
||||
.usage = "['enable'|'disable']",
|
||||
},
|
||||
{
|
||||
.name = "vcr",
|
||||
.handler = &arm11_handle_vcr,
|
||||
.handler = arm11_handle_vcr,
|
||||
.mode = COMMAND_ANY,
|
||||
.help = "Control (Interrupt) Vector Catch Register",
|
||||
.help = "Display or modify Vector Catch Register",
|
||||
.usage = "[value]",
|
||||
},
|
||||
COMMAND_REGISTRATION_DONE
|
||||
};
|
||||
|
||||
@@ -854,7 +854,9 @@ int arm11_sc7_run(struct arm11_common * arm11, struct arm11_sc7_action * actions
|
||||
AddressOut = 0;
|
||||
}
|
||||
|
||||
do
|
||||
/* Timeout here so we don't get stuck. */
|
||||
int i = 0;
|
||||
while (1)
|
||||
{
|
||||
JTAG_DEBUG("SC7 <= c%-3d Data %08x %s",
|
||||
(unsigned) AddressOut,
|
||||
@@ -866,10 +868,27 @@ int arm11_sc7_run(struct arm11_common * arm11, struct arm11_sc7_action * actions
|
||||
|
||||
CHECK_RETVAL(jtag_execute_queue());
|
||||
|
||||
if (!Ready)
|
||||
JTAG_DEBUG("SC7 => !ready");
|
||||
/* 'nRW' is 'Ready' on read out */
|
||||
if (Ready)
|
||||
break;
|
||||
|
||||
long long then = 0;
|
||||
|
||||
if (i == 1000)
|
||||
{
|
||||
then = timeval_ms();
|
||||
}
|
||||
if (i >= 1000)
|
||||
{
|
||||
if ((timeval_ms()-then) > 1000)
|
||||
{
|
||||
LOG_WARNING("Timeout (1000ms) waiting for instructions to complete");
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
}
|
||||
|
||||
i++;
|
||||
}
|
||||
while (!Ready); /* 'nRW' is 'Ready' on read out */
|
||||
|
||||
if (!nRW)
|
||||
JTAG_DEBUG("SC7 => Data %08x", (unsigned) DataIn);
|
||||
|
||||
@@ -255,11 +255,21 @@ static int arm720_mmu(struct target *target, int *enabled)
|
||||
}
|
||||
|
||||
static int arm720_virt2phys(struct target *target,
|
||||
uint32_t virt, uint32_t *phys)
|
||||
uint32_t virtual, uint32_t *physical)
|
||||
{
|
||||
/** @todo Implement this! */
|
||||
LOG_ERROR("%s: not implemented", __func__);
|
||||
return ERROR_FAIL;
|
||||
int type;
|
||||
uint32_t cb;
|
||||
int domain;
|
||||
uint32_t ap;
|
||||
struct arm720t_common *arm720t = target_to_arm720(target);
|
||||
|
||||
uint32_t ret = armv4_5_mmu_translate_va(target, &arm720t->armv4_5_mmu, virtual, &type, &cb, &domain, &ap);
|
||||
if (type == -1)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
*physical = ret;
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
static int arm720t_read_memory(struct target *target,
|
||||
@@ -516,8 +526,10 @@ static const struct command_registration arm720t_exec_command_handlers[] = {
|
||||
.name = "cp15",
|
||||
.handler = arm720t_handle_cp15_command,
|
||||
.mode = COMMAND_EXEC,
|
||||
.usage = "<opcode> [value]",
|
||||
.help = "display/modify cp15 register",
|
||||
/* prefer using less error-prone "arm mcr" or "arm mrc" */
|
||||
.help = "display/modify cp15 register using ARM opcode"
|
||||
" (DEPRECATED)",
|
||||
.usage = "instruction [value]",
|
||||
},
|
||||
COMMAND_REGISTRATION_DONE
|
||||
};
|
||||
@@ -576,4 +588,5 @@ struct target_type arm720t_target =
|
||||
.target_create = arm720t_target_create,
|
||||
.init_target = arm720t_init_target,
|
||||
.examine = arm7_9_examine,
|
||||
.check_reset = arm7_9_check_reset,
|
||||
};
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* Copyright (C) 2005 by Dominic Rath *
|
||||
* Dominic.Rath@gmx.de *
|
||||
* *
|
||||
* Copyright (C) 2007,2008 Øyvind Harboe *
|
||||
* Copyright (C) 2007-2009 Øyvind Harboe *
|
||||
* oyvind.harboe@zylin.com *
|
||||
* *
|
||||
* Copyright (C) 2008 by Spencer Oliver *
|
||||
@@ -11,6 +11,8 @@
|
||||
* Copyright (C) 2008 by Hongtao Zheng *
|
||||
* hontor@126.com *
|
||||
* *
|
||||
* Copyright (C) 2009 by David Brownell *
|
||||
* *
|
||||
* 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 *
|
||||
@@ -941,14 +943,16 @@ int arm7_9_poll(struct target *target)
|
||||
int arm7_9_assert_reset(struct target *target)
|
||||
{
|
||||
struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
|
||||
enum reset_types jtag_reset_config = jtag_get_reset_config();
|
||||
bool use_event = false;
|
||||
|
||||
LOG_DEBUG("target->state: %s",
|
||||
target_state_name(target));
|
||||
|
||||
enum reset_types jtag_reset_config = jtag_get_reset_config();
|
||||
if (!(jtag_reset_config & RESET_HAS_SRST))
|
||||
{
|
||||
LOG_ERROR("Can't assert SRST");
|
||||
if (target_has_event_action(target, TARGET_EVENT_RESET_ASSERT))
|
||||
use_event = true;
|
||||
else if (!(jtag_reset_config & RESET_HAS_SRST)) {
|
||||
LOG_ERROR("%s: how to reset?", target_name(target));
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
|
||||
@@ -963,7 +967,8 @@ int arm7_9_assert_reset(struct target *target)
|
||||
*/
|
||||
bool srst_asserted = false;
|
||||
|
||||
if (((jtag_reset_config & RESET_SRST_PULLS_TRST) == 0)
|
||||
if (!use_event
|
||||
&& !(jtag_reset_config & RESET_SRST_PULLS_TRST)
|
||||
&& (jtag_reset_config & RESET_SRST_NO_GATING))
|
||||
{
|
||||
jtag_add_reset(0, 1);
|
||||
@@ -973,48 +978,70 @@ int arm7_9_assert_reset(struct target *target)
|
||||
if (target->reset_halt)
|
||||
{
|
||||
/*
|
||||
* Some targets do not support communication while SRST is asserted. We need to
|
||||
* set up the reset vector catch here.
|
||||
* For targets that don't support communication while SRST is
|
||||
* asserted, we need to set up the reset vector catch first.
|
||||
*
|
||||
* If TRST is asserted, then these settings will be reset anyway, so setting them
|
||||
* here is harmless.
|
||||
* When we use TRST+SRST and that's equivalent to a power-up
|
||||
* reset, these settings may well be reset anyway; so setting
|
||||
* them here won't matter.
|
||||
*/
|
||||
if (arm7_9->has_vector_catch)
|
||||
{
|
||||
/* program vector catch register to catch reset vector */
|
||||
embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_VEC_CATCH], 0x1);
|
||||
/* program vector catch register to catch reset */
|
||||
embeddedice_write_reg(&arm7_9->eice_cache
|
||||
->reg_list[EICE_VEC_CATCH], 0x1);
|
||||
|
||||
/* extra runtest added as issues were found with certain ARM9 cores (maybe more) - AT91SAM9260 and STR9 */
|
||||
/* extra runtest added as issues were found with
|
||||
* certain ARM9 cores (maybe more) - AT91SAM9260
|
||||
* and STR9
|
||||
*/
|
||||
jtag_add_runtest(1, jtag_get_end_state());
|
||||
}
|
||||
else
|
||||
{
|
||||
/* program watchpoint unit to match on reset vector address */
|
||||
embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_W0_ADDR_VALUE], 0x0);
|
||||
embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_W0_ADDR_MASK], 0x3);
|
||||
embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_W0_DATA_MASK], 0xffffffff);
|
||||
embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_W0_CONTROL_VALUE], EICE_W_CTRL_ENABLE);
|
||||
embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_W0_CONTROL_MASK], ~EICE_W_CTRL_nOPC & 0xff);
|
||||
/* program watchpoint unit to match on reset vector
|
||||
* address
|
||||
*/
|
||||
embeddedice_write_reg(&arm7_9->eice_cache
|
||||
->reg_list[EICE_W0_ADDR_VALUE], 0x0);
|
||||
embeddedice_write_reg(&arm7_9->eice_cache
|
||||
->reg_list[EICE_W0_ADDR_MASK], 0x3);
|
||||
embeddedice_write_reg(&arm7_9->eice_cache
|
||||
->reg_list[EICE_W0_DATA_MASK],
|
||||
0xffffffff);
|
||||
embeddedice_write_reg(&arm7_9->eice_cache
|
||||
->reg_list[EICE_W0_CONTROL_VALUE],
|
||||
EICE_W_CTRL_ENABLE);
|
||||
embeddedice_write_reg(&arm7_9->eice_cache
|
||||
->reg_list[EICE_W0_CONTROL_MASK],
|
||||
~EICE_W_CTRL_nOPC & 0xff);
|
||||
}
|
||||
}
|
||||
|
||||
/* here we should issue an SRST only, but we may have to assert TRST as well */
|
||||
if (jtag_reset_config & RESET_SRST_PULLS_TRST)
|
||||
{
|
||||
jtag_add_reset(1, 1);
|
||||
} else if (!srst_asserted)
|
||||
{
|
||||
jtag_add_reset(0, 1);
|
||||
if (use_event) {
|
||||
target_handle_event(target, TARGET_EVENT_RESET_ASSERT);
|
||||
} else {
|
||||
/* If we use SRST ... we'd like to issue just SRST, but the
|
||||
* board or chip may be set up so we have to assert TRST as
|
||||
* well. On some chips that combination is equivalent to a
|
||||
* power-up reset, and generally clobbers EICE state.
|
||||
*/
|
||||
if (jtag_reset_config & RESET_SRST_PULLS_TRST)
|
||||
jtag_add_reset(1, 1);
|
||||
else if (!srst_asserted)
|
||||
jtag_add_reset(0, 1);
|
||||
jtag_add_sleep(50000);
|
||||
}
|
||||
|
||||
target->state = TARGET_RESET;
|
||||
jtag_add_sleep(50000);
|
||||
|
||||
register_cache_invalidate(arm7_9->armv4_5_common.core_cache);
|
||||
|
||||
if ((target->reset_halt) && ((jtag_reset_config & RESET_SRST_PULLS_TRST) == 0))
|
||||
/* REVISIT why isn't standard debug entry logic sufficient?? */
|
||||
if (target->reset_halt
|
||||
&& (!(jtag_reset_config & RESET_SRST_PULLS_TRST)
|
||||
|| use_event))
|
||||
{
|
||||
/* debug entry was already prepared in arm7_9_assert_reset() */
|
||||
/* debug entry was prepared above */
|
||||
target->debug_reason = DBG_REASON_DBGRQ;
|
||||
}
|
||||
|
||||
@@ -2723,6 +2750,29 @@ int arm7_9_examine(struct target *target)
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
||||
int arm7_9_check_reset(struct target *target)
|
||||
{
|
||||
struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
|
||||
|
||||
if (get_target_reset_nag() && !arm7_9->dcc_downloads)
|
||||
{
|
||||
LOG_WARNING("NOTE! DCC downloads have not been enabled, defaulting to slow memory writes. Type 'help dcc'.");
|
||||
}
|
||||
|
||||
if (get_target_reset_nag() && (target->working_area_size == 0))
|
||||
{
|
||||
LOG_WARNING("NOTE! Severe performance degradation without working memory enabled.");
|
||||
}
|
||||
|
||||
if (get_target_reset_nag() && !arm7_9->fast_memory_access)
|
||||
{
|
||||
LOG_WARNING("NOTE! Severe performance degradation without fast memory access enabled. Type 'help fast'.");
|
||||
}
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
COMMAND_HANDLER(handle_arm7_9_dbgrq_command)
|
||||
{
|
||||
struct target *target = get_current_target(CMD_CTX);
|
||||
@@ -2797,6 +2847,12 @@ COMMAND_HANDLER(handle_arm7_9_semihosting_command)
|
||||
|
||||
COMMAND_PARSE_ENABLE(CMD_ARGV[0], semihosting);
|
||||
|
||||
if (!target_was_examined(target))
|
||||
{
|
||||
LOG_ERROR("Target not examined yet");
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
|
||||
if (arm7_9->has_vector_catch) {
|
||||
struct reg *vector_catch = &arm7_9->eice_cache
|
||||
->reg_list[EICE_VEC_CATCH];
|
||||
@@ -2858,32 +2914,32 @@ int arm7_9_init_arch_info(struct target *target, struct arm7_9_common *arm7_9)
|
||||
static const struct command_registration arm7_9_any_command_handlers[] = {
|
||||
{
|
||||
"dbgrq",
|
||||
.handler = &handle_arm7_9_dbgrq_command,
|
||||
.handler = handle_arm7_9_dbgrq_command,
|
||||
.mode = COMMAND_ANY,
|
||||
.usage = "<enable|disable>",
|
||||
.usage = "['enable'|'disable']",
|
||||
.help = "use EmbeddedICE dbgrq instead of breakpoint "
|
||||
"for target halt requests",
|
||||
},
|
||||
{
|
||||
"fast_memory_access",
|
||||
.handler = &handle_arm7_9_fast_memory_access_command,
|
||||
.handler = handle_arm7_9_fast_memory_access_command,
|
||||
.mode = COMMAND_ANY,
|
||||
.usage = "<enable|disable>",
|
||||
.usage = "['enable'|'disable']",
|
||||
.help = "use fast memory accesses instead of slower "
|
||||
"but potentially safer accesses",
|
||||
},
|
||||
{
|
||||
"dcc_downloads",
|
||||
.handler = &handle_arm7_9_dcc_downloads_command,
|
||||
.handler = handle_arm7_9_dcc_downloads_command,
|
||||
.mode = COMMAND_ANY,
|
||||
.usage = "<enable | disable>",
|
||||
.usage = "['enable'|'disable']",
|
||||
.help = "use DCC downloads for larger memory writes",
|
||||
},
|
||||
{
|
||||
"semihosting",
|
||||
.handler = &handle_arm7_9_semihosting_command,
|
||||
.handler = handle_arm7_9_semihosting_command,
|
||||
.mode = COMMAND_EXEC,
|
||||
.usage = "<enable | disable>",
|
||||
.usage = "['enable'|'disable']",
|
||||
.help = "activate support for semihosting operations",
|
||||
},
|
||||
COMMAND_REGISTRATION_DONE
|
||||
|
||||
@@ -157,5 +157,6 @@ int arm7_9_execute_sys_speed(struct target *target);
|
||||
|
||||
int arm7_9_init_arch_info(struct target *target, struct arm7_9_common *arm7_9);
|
||||
int arm7_9_examine(struct target *target);
|
||||
int arm7_9_check_reset(struct target *target);
|
||||
|
||||
#endif /* ARM7_9_COMMON_H */
|
||||
|
||||
@@ -752,4 +752,5 @@ struct target_type arm7tdmi_target =
|
||||
.target_create = arm7tdmi_target_create,
|
||||
.init_target = arm7tdmi_init_target,
|
||||
.examine = arm7_9_examine,
|
||||
.check_reset = arm7_9_check_reset,
|
||||
};
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user