Compare commits
453 Commits
v0.2.0
...
v0.3.0-rc0
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
70f735007d | ||
|
|
ce88e8adf7 | ||
|
|
4d17541a2c | ||
|
|
053a763aa6 | ||
|
|
0b882951b7 | ||
|
|
e8dc384be9 | ||
|
|
07c85e41a4 | ||
|
|
c970d03ddb | ||
|
|
eb9790dc91 | ||
|
|
89c1bea931 | ||
|
|
76afa936ba | ||
|
|
39dd68bca6 | ||
|
|
993fe4ab63 | ||
|
|
ad5192a2b9 | ||
|
|
68937cadfb | ||
|
|
068a6c7895 | ||
|
|
ee8e93cb83 | ||
|
|
1020569b9f | ||
|
|
0b476c9f4c | ||
|
|
4a26390eec | ||
|
|
4a91b070ff | ||
|
|
ddade10d4a | ||
|
|
8f3b28ff41 | ||
|
|
d87ee640c7 | ||
|
|
eaebc6cd69 | ||
|
|
592e021543 | ||
|
|
8b30f22dec | ||
|
|
6cb1d10cda | ||
|
|
0cac8b67be | ||
|
|
a07422c26c | ||
|
|
d785f552ee | ||
|
|
19b84dafb0 | ||
|
|
e98817c463 | ||
|
|
2a8aa3b7ef | ||
|
|
0b436497e0 | ||
|
|
75cdc8a260 | ||
|
|
bfefe85645 | ||
|
|
cb854323c9 | ||
|
|
0a1356c9cc | ||
|
|
18aad44f71 | ||
|
|
79f71fad58 | ||
|
|
814183a5c4 | ||
|
|
517e812de3 | ||
|
|
f593ff0a3d | ||
|
|
344bed2f7e | ||
|
|
3537c368fe | ||
|
|
fcf1301e52 | ||
|
|
e996452089 | ||
|
|
1e5daf5886 | ||
|
|
2d45a10dfd | ||
|
|
85bf1627cd | ||
|
|
2783cba810 | ||
|
|
818cedaff3 | ||
|
|
69a6037ce6 | ||
|
|
e895246966 | ||
|
|
a4a1de4dd1 | ||
|
|
62525792e0 | ||
|
|
a02411a15f | ||
|
|
7556a93aed | ||
|
|
a1609e5ad1 | ||
|
|
79e257a209 | ||
|
|
ad75639611 | ||
|
|
e4dba30b63 | ||
|
|
6907ef9d50 | ||
|
|
c70073ef67 | ||
|
|
d243e641d3 | ||
|
|
3cc147efd9 | ||
|
|
53979244b1 | ||
|
|
fb61f52731 | ||
|
|
0388a9c0e5 | ||
|
|
6ec1026bbb | ||
|
|
6726b78707 | ||
|
|
97166327db | ||
|
|
113679ff59 | ||
|
|
557d1b6490 | ||
|
|
89a8a37998 | ||
|
|
76b4ee8935 | ||
|
|
990f50a73b | ||
|
|
5cf0af002c | ||
|
|
73349dc5ac | ||
|
|
c9fbfbd95c | ||
|
|
05d6716936 | ||
|
|
cb7965da15 | ||
|
|
a61b57a87f | ||
|
|
510db585fd | ||
|
|
bc792857a5 | ||
|
|
dd54981702 | ||
|
|
a894c2d8b2 | ||
|
|
4490a42a09 | ||
|
|
44e9200d0a | ||
|
|
1ee8ef4210 | ||
|
|
7afc181e42 | ||
|
|
9b9bc78ef1 | ||
|
|
ed1e45b388 | ||
|
|
5535399a46 | ||
|
|
6a2fd7cad5 | ||
|
|
bc0cc62afd | ||
|
|
79bf27da71 | ||
|
|
4d32b6eee9 | ||
|
|
20c8f64f0a | ||
|
|
1f917bdc0c | ||
|
|
f8cd850c4d | ||
|
|
86cbbe8a4a | ||
|
|
b6c4d1006f | ||
|
|
85398ccdcf | ||
|
|
23c629a85e | ||
|
|
407061eaa6 | ||
|
|
35affce085 | ||
|
|
0ca473468c | ||
|
|
165e3a1468 | ||
|
|
bbd7e22f0b | ||
|
|
b5b4fee811 | ||
|
|
5e837387aa | ||
|
|
9f6c23f479 | ||
|
|
026559068d | ||
|
|
c8d935ab7c | ||
|
|
b23b096c8e | ||
|
|
2d924a59db | ||
|
|
688003cb23 | ||
|
|
8b3bfcfc5b | ||
|
|
5aba621b55 | ||
|
|
a0b1e05b53 | ||
|
|
456ec36795 | ||
|
|
dbf7440148 | ||
|
|
bc13c12be9 | ||
|
|
c3428f5b7a | ||
|
|
8f09c5df85 | ||
|
|
20a3b14828 | ||
|
|
bffe824df6 | ||
|
|
60e24aa597 | ||
|
|
6160a946ec | ||
|
|
5b352c9e79 | ||
|
|
7b650a6abe | ||
|
|
41c1af7c67 | ||
|
|
a8234af06c | ||
|
|
40c9668b70 | ||
|
|
22aff82cae | ||
|
|
4aacf01e19 | ||
|
|
cf7eae176e | ||
|
|
f525f2ef0d | ||
|
|
d75b9ec697 | ||
|
|
6efaa95c44 | ||
|
|
37e9f65f5a | ||
|
|
7252a72465 | ||
|
|
8a162e5e06 | ||
|
|
03c9e48f88 | ||
|
|
cdc33b3808 | ||
|
|
246ff4f601 | ||
|
|
7035b37e71 | ||
|
|
4c450b5c6b | ||
|
|
55f4e430e8 | ||
|
|
f8c8d8bc72 | ||
|
|
f2dc1eeef1 | ||
|
|
b83d79a42f | ||
|
|
dc871f422d | ||
|
|
71bca7640a | ||
|
|
616c154866 | ||
|
|
b4e4532dd2 | ||
|
|
40ac8d7753 | ||
|
|
53dea2f952 | ||
|
|
e4cc19521b | ||
|
|
b1f7b35983 | ||
|
|
a343b18bfb | ||
|
|
0da2f750a1 | ||
|
|
60f8770502 | ||
|
|
7d78021efa | ||
|
|
4119cd6db2 | ||
|
|
39b57471bf | ||
|
|
a2886fe3c6 | ||
|
|
00f2c9e062 | ||
|
|
0d3632adff | ||
|
|
64ec7f66a8 | ||
|
|
7280a52e69 | ||
|
|
7a57c31619 | ||
|
|
7c7467b34f | ||
|
|
16a7ad5799 | ||
|
|
3aa9fabfe9 | ||
|
|
c6b24fb4f0 | ||
|
|
f87985b614 | ||
|
|
16742b529b | ||
|
|
49f3497bfa | ||
|
|
1b90a9f5eb | ||
|
|
84dabdcc72 | ||
|
|
c74ede4248 | ||
|
|
1033633321 | ||
|
|
d340906476 | ||
|
|
e3d82fe24d | ||
|
|
1beb24a61c | ||
|
|
eccd9059d3 | ||
|
|
740fd107f2 | ||
|
|
14be119906 | ||
|
|
7b9f01e0ae | ||
|
|
8624535b80 | ||
|
|
32599fab1a | ||
|
|
aaf1daa056 | ||
|
|
54c16fc56e | ||
|
|
642519649e | ||
|
|
e4de4251fe | ||
|
|
6d4cdddbe2 | ||
|
|
4297209ac9 | ||
|
|
bde4a40422 | ||
|
|
d96e3eae23 | ||
|
|
afc3a5cc6f | ||
|
|
f4fce92f28 | ||
|
|
035b6ba84b | ||
|
|
9bdbffb8cc | ||
|
|
c5949a03a7 | ||
|
|
e3a0647558 | ||
|
|
62b7e1ce64 | ||
|
|
cbe34d0819 | ||
|
|
9a4e650083 | ||
|
|
817ea3f4e4 | ||
|
|
fbbd3066ff | ||
|
|
5c3c4af88f | ||
|
|
2329ae9306 | ||
|
|
f64e924ba9 | ||
|
|
2e210ee48f | ||
|
|
ad43374c7f | ||
|
|
43b3807878 | ||
|
|
1c262c8826 | ||
|
|
37755ffdb6 | ||
|
|
23e22b6ec4 | ||
|
|
22045fa6f2 | ||
|
|
d9ce8a2f60 | ||
|
|
a6d858ebcd | ||
|
|
7393fcfc90 | ||
|
|
6521b75ec2 | ||
|
|
a2a3620d35 | ||
|
|
50b94628ae | ||
|
|
6cba486356 | ||
|
|
b11d79110e | ||
|
|
71af49ca7f | ||
|
|
86a7d813a1 | ||
|
|
0bcf5a6b76 | ||
|
|
108028112f | ||
|
|
d20103cd93 | ||
|
|
48e96a18ed | ||
|
|
24df719b09 | ||
|
|
0c4b119d3f | ||
|
|
75581ffea6 | ||
|
|
965b331d0b | ||
|
|
781997f556 | ||
|
|
01735c515f | ||
|
|
3e87fc20ab | ||
|
|
2d3bcddf04 | ||
|
|
74ae645623 | ||
|
|
7b3be0e21e | ||
|
|
631b2ab244 | ||
|
|
358263f484 | ||
|
|
e961bd14d9 | ||
|
|
9536577c02 | ||
|
|
9655c5b093 | ||
|
|
84f51bf50c | ||
|
|
1dd302883d | ||
|
|
016e7ebbfa | ||
|
|
cb7ad25c04 | ||
|
|
e18bd3b55e | ||
|
|
9b11eebf33 | ||
|
|
45f03dd9b5 | ||
|
|
9542318312 | ||
|
|
6d2473b65b | ||
|
|
f0ddb40ced | ||
|
|
7e4f9ac697 | ||
|
|
388e94d5c1 | ||
|
|
379386743a | ||
|
|
45674af63a | ||
|
|
d4e4d65d28 | ||
|
|
14dc22612b | ||
|
|
5a6980869b | ||
|
|
8e39f86ef4 | ||
|
|
9816f2ecda | ||
|
|
772d8d06ea | ||
|
|
d4607c1f7c | ||
|
|
c4ee12ea77 | ||
|
|
a17eb667a3 | ||
|
|
40f361dd94 | ||
|
|
c993d75d1f | ||
|
|
f6a29d438e | ||
|
|
4f7761828c | ||
|
|
ec3015db1a | ||
|
|
25f9a466ca | ||
|
|
00e900f8a1 | ||
|
|
f89d1cbfd6 | ||
|
|
0dcfbec7fb | ||
|
|
58b78818e0 | ||
|
|
6dd8f37e6d | ||
|
|
9b1a938a22 | ||
|
|
c5f54c5333 | ||
|
|
49d0ea2126 | ||
|
|
9262e0dbdf | ||
|
|
3bade442b1 | ||
|
|
b4acbee47f | ||
|
|
7b5ddb4a58 | ||
|
|
983f5a1ae9 | ||
|
|
aa46b15377 | ||
|
|
8b2b0071a9 | ||
|
|
857c06ca8b | ||
|
|
f6a5749c1b | ||
|
|
5dae4753ff | ||
|
|
57e12b7e45 | ||
|
|
2c76cd7171 | ||
|
|
a690ee3c0c | ||
|
|
0b11e4dbb4 | ||
|
|
b13dbc80e0 | ||
|
|
982ac083f0 | ||
|
|
2e29131f2b | ||
|
|
81b57a3fb6 | ||
|
|
ee329275d3 | ||
|
|
51be978b43 | ||
|
|
ce89c7bf65 | ||
|
|
76b78feef1 | ||
|
|
a89dd2ca65 | ||
|
|
3878b12793 | ||
|
|
cde17a42e9 | ||
|
|
f7f38fa70d | ||
|
|
fbf775c0b7 | ||
|
|
a41725c788 | ||
|
|
bb5f713e44 | ||
|
|
0dd669f2a7 | ||
|
|
2a86a53c3f | ||
|
|
072d6d3db6 | ||
|
|
fbe1c23c12 | ||
|
|
98ae6c24f0 | ||
|
|
ab30d5203c | ||
|
|
d879faa3cb | ||
|
|
4b9bdd664a | ||
|
|
69b8b5e0aa | ||
|
|
ed8fd94d7c | ||
|
|
efef05870d | ||
|
|
a5d02116a6 | ||
|
|
997d5284cb | ||
|
|
ae17ce23eb | ||
|
|
c5145ceb19 | ||
|
|
bb000a6f77 | ||
|
|
32a2c70d3e | ||
|
|
641c574425 | ||
|
|
327ba6cb0a | ||
|
|
e921fead94 | ||
|
|
01000e988a | ||
|
|
fc7cd1d85e | ||
|
|
56a04a3413 | ||
|
|
f36d0083de | ||
|
|
56b346447b | ||
|
|
dce1cdc9fb | ||
|
|
0de530067f | ||
|
|
c87357a33f | ||
|
|
9a9ebfb924 | ||
|
|
11856bcffc | ||
|
|
a5354ff5cb | ||
|
|
34e8c67b1f | ||
|
|
bc075606b7 | ||
|
|
24f011ebb4 | ||
|
|
86b49612a6 | ||
|
|
6f359fba68 | ||
|
|
bd7cbd01e8 | ||
|
|
0c41395fc3 | ||
|
|
7a1ac49ac9 | ||
|
|
8e1d516927 | ||
|
|
696ed5fdc4 | ||
|
|
d11c8e3c8e | ||
|
|
14f2189e1a | ||
|
|
fd4c0f33b1 | ||
|
|
ae4c224459 | ||
|
|
41bb41bb93 | ||
|
|
9df861b0c0 | ||
|
|
1d0b276c9f | ||
|
|
6f7491c1c1 | ||
|
|
0ed5f5afd9 | ||
|
|
bf5f21e39a | ||
|
|
332c8d78d8 | ||
|
|
6336ebb05c | ||
|
|
5c50cf802c | ||
|
|
0a7158140a | ||
|
|
8b73ec8d64 | ||
|
|
afae28fb2c | ||
|
|
ef30f22fd3 | ||
|
|
028e535604 | ||
|
|
c2f593bdc1 | ||
|
|
18d8ac5267 | ||
|
|
57578b4ea3 | ||
|
|
69dd81dcf8 | ||
|
|
1b092a27f0 | ||
|
|
a6f9c5a796 | ||
|
|
a634b5d52e | ||
|
|
bb5086b83e | ||
|
|
7b4428df97 | ||
|
|
ed22097a55 | ||
|
|
a4c7e2dd96 | ||
|
|
5badd9b29a | ||
|
|
35e5e07127 | ||
|
|
1d96a84f06 | ||
|
|
ad23cb97b2 | ||
|
|
2a0e491d9a | ||
|
|
a33e272abd | ||
|
|
b747da2663 | ||
|
|
59b295dbbe | ||
|
|
720c39ba2f | ||
|
|
732df6fea0 | ||
|
|
ad800b1c02 | ||
|
|
84903467ec | ||
|
|
d40fd9e0f4 | ||
|
|
1ee32a8fa1 | ||
|
|
398f60af56 | ||
|
|
9b29b729f3 | ||
|
|
5a824c934f | ||
|
|
e9b919fbc6 | ||
|
|
e31e6a10de | ||
|
|
49e2267f1f | ||
|
|
3bcf8a8a25 | ||
|
|
fc318c0298 | ||
|
|
67dbf35896 | ||
|
|
ad3a24f944 | ||
|
|
431925a452 | ||
|
|
50aa561796 | ||
|
|
31b520c379 | ||
|
|
c7565cc381 | ||
|
|
30b1bbceea | ||
|
|
7986ed5ac2 | ||
|
|
a7a1ae032b | ||
|
|
d460a7cd6c | ||
|
|
4da019edeb | ||
|
|
eea0486263 | ||
|
|
cd0ca916b3 | ||
|
|
55b1ea1d8e | ||
|
|
f703322b3f | ||
|
|
8b994145b8 | ||
|
|
14cbd545bf | ||
|
|
bd4377194e | ||
|
|
4deb8530c6 | ||
|
|
4ebd353ae1 | ||
|
|
1af6b72fc1 | ||
|
|
16e17ab1b3 | ||
|
|
0c2ff267aa | ||
|
|
fdfd434c24 | ||
|
|
00adcc773a | ||
|
|
930269b483 | ||
|
|
421b8e133a | ||
|
|
889bd3e716 | ||
|
|
84e86e9aee | ||
|
|
d2088f0d29 | ||
|
|
f163d0009d | ||
|
|
0165ae4405 | ||
|
|
8b89224c6e | ||
|
|
b71e3aff6d | ||
|
|
309870e414 | ||
|
|
2ff59c9aaf | ||
|
|
e76fe13a95 | ||
|
|
d78d79aff6 | ||
|
|
8b82de60c7 | ||
|
|
1df358855a | ||
|
|
197a195191 | ||
|
|
4eb2e50e4d | ||
|
|
f9c65b5cd5 |
65
.gitignore
vendored
Normal file
65
.gitignore
vendored
Normal file
@@ -0,0 +1,65 @@
|
||||
# stuff "git status" should ignore
|
||||
|
||||
# build output
|
||||
.libs
|
||||
.deps
|
||||
*.o
|
||||
*.a
|
||||
*.lo
|
||||
*.la
|
||||
*.in
|
||||
|
||||
# editor files
|
||||
*.swp
|
||||
|
||||
startup_tcl.c
|
||||
xscale_debug.h
|
||||
|
||||
bin2char
|
||||
bin2char.exe
|
||||
|
||||
doc/openocd.aux
|
||||
doc/openocd.cp
|
||||
doc/openocd.cps
|
||||
doc/openocd.fn
|
||||
doc/openocd.fns
|
||||
doc/openocd.html
|
||||
doc/openocd.info
|
||||
doc/openocd.info-1
|
||||
doc/openocd.info-2
|
||||
doc/openocd.ky
|
||||
doc/openocd.log
|
||||
doc/openocd.pdf
|
||||
doc/openocd.pg
|
||||
doc/openocd.toc
|
||||
doc/openocd.tp
|
||||
doc/openocd.vr
|
||||
doc/texinfo.tex
|
||||
doc/version.texi
|
||||
src/openocd
|
||||
src/openocd.exe
|
||||
|
||||
# configure/autotools output
|
||||
aclocal.m4
|
||||
autom4te.cache
|
||||
compile
|
||||
config.*
|
||||
configure
|
||||
depcomp
|
||||
doxygen
|
||||
doxygen.log
|
||||
Doxyfile
|
||||
install-sh
|
||||
libtool
|
||||
ltmain.sh
|
||||
Makefile
|
||||
mdate-sh
|
||||
missing
|
||||
stamp-h1
|
||||
stamp-vti
|
||||
INSTALL
|
||||
NOTES
|
||||
|
||||
# Eclipse stuff
|
||||
.project
|
||||
|
||||
3
.gitmodules
vendored
Normal file
3
.gitmodules
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
[submodule "tools/git2cl"]
|
||||
path = tools/git2cl
|
||||
url = git://repo.or.cz/git2cl.git
|
||||
11
BUGS
11
BUGS
@@ -22,7 +22,7 @@ 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.
|
||||
For example: if testing version 550 works but 600 fail, then try 575, etc.
|
||||
You can use "git bisect" to expedite this binary search.
|
||||
|
||||
If possible, please develop and attach a patch that helps to expose or
|
||||
solve the reported problem. See the PATCHES file for more information
|
||||
@@ -34,8 +34,15 @@ in total.
|
||||
|
||||
@section bugscrashdump Obtaining Crash Backtraces
|
||||
|
||||
If OpenOCD is crashing, you can use GDB to get a trace:@par
|
||||
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.
|
||||
|
||||
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
|
||||
@code
|
||||
% OPENOCDSRC/configure --enable-dummy ...
|
||||
% openocd -f interface/dummy.cfg -f target/xxx.cfg
|
||||
=> SEGFAULT
|
||||
% gdb --args openocd ....
|
||||
(gdb) run
|
||||
(gdb) bt
|
||||
|
||||
106
NEWS
106
NEWS
@@ -1,79 +1,57 @@
|
||||
The OpenOCD 0.2.0 source archive release includes numerous improvements
|
||||
that were made since the initial 0.1.0 source archive release. Many
|
||||
contributors helped make this release a great success, and the community
|
||||
of developers and maintainers look forward to any response.
|
||||
|
||||
In addition to the list of changes below, countless bug fixing and
|
||||
cleaning was performed across the tree. Various TCL command parameters
|
||||
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
|
||||
commands that will be removed in the future.
|
||||
|
||||
The following areas of OpenOCD functionality changed in this release:
|
||||
This file should include highlights of the changes made in the
|
||||
OpenOCD openocd-0.3.0 source archive release. See the repository
|
||||
history for details about what changed, including bugfixes and
|
||||
other issues not mentioned here.
|
||||
|
||||
JTAG Layer:
|
||||
- Improves modularity: core, TCL, driver commands, and interface have
|
||||
been separated, encapsulated, and documented for developers. Mostly.
|
||||
- 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.
|
||||
- New drivers:
|
||||
* Adds stub minidriver for developing new embedded JTAG interfaces.
|
||||
- Improves drivers:
|
||||
* ft2232+ftd2xx:
|
||||
+ Adds initial high-speed device support: --enable-ftd2xx-highspeed
|
||||
+ Supports more types of FTDI-based devices.
|
||||
* jlink:
|
||||
+ Works with more versions of the firmware (v3 and newer)
|
||||
+ Supports dynamically detects device capabilities and limits
|
||||
* vsllink:
|
||||
+ Supports very long scan chains
|
||||
* amtjtagaccel:
|
||||
+ Fixes broken ID code detection problems.
|
||||
FT2232H (high speed USB) support doesn't need separate configuration
|
||||
New reset_config options for SRST gating the JTAG clock (or not)
|
||||
TAP declaration no longer requires ircapture and mask attributes
|
||||
New "post-reset" event handler for TAP-invariant setup code
|
||||
Overridable Tcl "init_reset" and "jtag_init" procedures
|
||||
|
||||
Target Layer:
|
||||
- New devices: AVR, FA526
|
||||
- Improved support: ARM ADI, ARM11, MIPS
|
||||
- Numerous other bug fixes and improvements
|
||||
New commands for use with Cortex-M3 processors:
|
||||
"cortex_m3 disassemble" ... Thumb2 disassembly (UAL format)
|
||||
"cortex_m3 vector_catch" ... traps certain hardware faults
|
||||
without tying up breakpoint resources
|
||||
If you're willing to help debug it
|
||||
VERY EARLY Cortex-A8 and ARMv7A support
|
||||
Updated BeagleBoard.org hardware support
|
||||
New commands for use with XScale processors: "xscale vector_table"
|
||||
ARM9
|
||||
name change: "arm9 vector_catch" not "arm9tdmi vector_catch"
|
||||
ARM11
|
||||
single stepping support for i.MX31
|
||||
bugfix for missing "arm11" prefix on "arm11 memwrite ..."
|
||||
ETM support
|
||||
Unavailable registers are not listed
|
||||
|
||||
Flash Layer:
|
||||
- Improved drivers: mflash
|
||||
- New drivers: AT91SAM3, AVR, Davinci NAND
|
||||
The lpc2000 driver handles the new NXP LPC1700 (Cortex-M3) chips
|
||||
New lpc2900 driver for NXP LPC2900 chips (ARM968 based)
|
||||
New "last" flag for NOR "flash erase_sector" and "flash protect"
|
||||
The "nand erase N" command now erases all of bank N
|
||||
|
||||
Board, Interface, and Target Configuration Scripts:
|
||||
- Many new and improved targets and boards are now available.
|
||||
- Better separation of "board" and "target" configuration
|
||||
- Moved all TCL files to top-level "tcl" directory in the source tree
|
||||
- Installation moved from '$pkglibdir/' to '$pkgdatadir/scripts/'.
|
||||
- Site-specific files should be installed under '$pkgdatadir/site/';
|
||||
files that exist this tree will be used in preference to default
|
||||
distribution configurations in '$pkgdatadir/scripts/'.
|
||||
Board, Target, and Interface Configuration Scripts:
|
||||
Amontec JTAGkey2 support
|
||||
Cleanup and additions for the TI/Luminary Stellaris scripts
|
||||
LPC1768 target (and flash) support
|
||||
Keil MCB1700 eval board
|
||||
Samsung s3c2450
|
||||
Mini2440 board
|
||||
Numeric TAP and Target identifiers now trigger warnings
|
||||
PXA255 partially enumerates
|
||||
|
||||
Documentation:
|
||||
- Updated User Guide: http://openocd.berlios.de/doc/html/index.html
|
||||
* Partially re-written and re-organized.
|
||||
* Standardized presentation for all commands.
|
||||
* Covers many drivers and commands that were previously omitted.
|
||||
* New index for commands and drivers.
|
||||
- Added Developer Manual: http://openocd.berlios.de/doc/doxygen/index.html
|
||||
* Now includes architecture, technical primers, style guides, and more.
|
||||
* Available in-tree and on-line.
|
||||
Capture more debugging and setup advice
|
||||
Notes on target source code changes that may help debugging
|
||||
|
||||
Build and Release:
|
||||
- Increased configuration and compilation warning coverage.
|
||||
* Use --disable-werror to work around build errors caused by warnings.
|
||||
- Use libtool to produce helper libraries as a step toward "libopenocd".
|
||||
- New processes and scripting to facilitate future source releases.
|
||||
|
||||
For more details about what has changed since 0.1.0, see the ChangeLog
|
||||
associated with this release.
|
||||
For more details about what has changed since the last release,
|
||||
see the ChangeLog associated with this source archive. For older NEWS,
|
||||
see the NEWS files associated with each release (i.e. NEWS-<version>).
|
||||
|
||||
For more information about contributing test reports, bug fixes, or new
|
||||
features and device support, please read the new Developer Manual (or
|
||||
|
||||
80
NEWS-0.2.0
Normal file
80
NEWS-0.2.0
Normal file
@@ -0,0 +1,80 @@
|
||||
The OpenOCD 0.2.0 source archive release includes numerous improvements
|
||||
that were made since the initial 0.1.0 source archive release. Many
|
||||
contributors helped make this release a great success, and the community
|
||||
of developers and maintainers look forward to any response.
|
||||
|
||||
In addition to the list of changes below, countless bug fixing and
|
||||
cleaning was performed across the tree. Various TCL command parameters
|
||||
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
|
||||
commands that will be removed in the future.
|
||||
|
||||
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:
|
||||
* 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.
|
||||
- New drivers:
|
||||
* Adds stub minidriver for developing new embedded JTAG interfaces.
|
||||
- Improves drivers:
|
||||
* ft2232+ftd2xx:
|
||||
+ Adds initial high-speed device support: --enable-ftd2xx-highspeed
|
||||
+ Supports more types of FTDI-based devices.
|
||||
* jlink:
|
||||
+ Works with more versions of the firmware (v3 and newer)
|
||||
+ Supports dynamically detects device capabilities and limits
|
||||
* vsllink:
|
||||
+ Supports very long scan chains
|
||||
* amtjtagaccel:
|
||||
+ Fixes broken ID code detection problems.
|
||||
|
||||
Target Layer:
|
||||
- New devices: AVR, FA526
|
||||
- Improved support: ARM ADI, ARM11, MIPS
|
||||
- Numerous other bug fixes and improvements
|
||||
|
||||
Flash Layer:
|
||||
- Improved drivers: mflash
|
||||
- New drivers: AT91SAM3, AVR, Davinci NAND
|
||||
|
||||
Board, Interface, and Target Configuration Scripts:
|
||||
- Many new and improved targets and boards are now available.
|
||||
- Better separation of "board" and "target" configuration
|
||||
- Moved all TCL files to top-level "tcl" directory in the source tree
|
||||
- Installation moved from '$pkglibdir/' to '$pkgdatadir/scripts/'.
|
||||
- Site-specific files should be installed under '$pkgdatadir/site/';
|
||||
files that exist this tree will be used in preference to default
|
||||
distribution configurations in '$pkgdatadir/scripts/'.
|
||||
|
||||
Documentation:
|
||||
- Updated User Guide: http://openocd.berlios.de/doc/html/index.html
|
||||
* Partially re-written and re-organized.
|
||||
* Standardized presentation for all commands.
|
||||
* Covers many drivers and commands that were previously omitted.
|
||||
* New index for commands and drivers.
|
||||
- Added Developer Manual: http://openocd.berlios.de/doc/doxygen/index.html
|
||||
* Now includes architecture, technical primers, style guides, and more.
|
||||
* Available in-tree and on-line.
|
||||
|
||||
Build and Release:
|
||||
- Increased configuration and compilation warning coverage.
|
||||
* Use --disable-werror to work around build errors caused by warnings.
|
||||
- Use libtool to produce helper libraries as a step toward "libopenocd".
|
||||
- New processes and scripting to facilitate future source releases.
|
||||
|
||||
For more details about what has changed since 0.1.0, see the ChangeLog
|
||||
associated with this 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).
|
||||
16
PATCHES
16
PATCHES
@@ -9,9 +9,8 @@ you're a member, despite what the list info page says.
|
||||
|
||||
@section Patch Guidelines in a Nutshell
|
||||
|
||||
The patch should be against svn trunk using an SVN
|
||||
diff. If you use git-svn, a git diff or patch is OK
|
||||
too; likewise a quilt patch, if you use quilt.
|
||||
Your patches should be against git mainline. Submit output
|
||||
of "git diff"; equivalently, quilt patches are OK.
|
||||
|
||||
It should be a "good patch": focus it on a single
|
||||
issue, and make it be easily reviewable. Don't make
|
||||
@@ -34,18 +33,9 @@ Add yourself to the GPL copyright for non-trivial changes.
|
||||
|
||||
To create a patch from the command line:
|
||||
@code
|
||||
svn diff >mypatch.txt
|
||||
git diff >mypatch.txt
|
||||
@endcode
|
||||
|
||||
See: @par
|
||||
http://svnbook.red-bean.com/en/1.0/re09.html
|
||||
|
||||
Remember to use "svn add" on new files first: @par
|
||||
http://svnbook.red-bean.com/en/1.0/re01.html
|
||||
|
||||
If you have a decent SVN GUI, then that should be
|
||||
able to create and apply patches as well...
|
||||
|
||||
@section More Information on Patching
|
||||
|
||||
The @ref primerpatches provides a more complete guide to creating,
|
||||
|
||||
71
README
71
README
@@ -64,17 +64,23 @@ you can build the in-tree documentation.
|
||||
Installing OpenOCD
|
||||
==================
|
||||
|
||||
On Linux, you may have permissions problems to address. The best
|
||||
way to do this is to use the contrib/udev.rules file. It probably
|
||||
belongs somewhere in /etc/udev/rules.d, but consult your operating
|
||||
system documentation to be sure. In particular, make sure that it
|
||||
matches the syntax used by your operating system's version of udev.
|
||||
|
||||
A Note to OpenOCD Users
|
||||
-----------------------
|
||||
|
||||
If you would rather be working "with" OpenOCD rather than "on" it, your
|
||||
operating system or interface supplier may provide binaries for you in a
|
||||
convenient package.
|
||||
operating system or JTAG interface supplier may provide binaries for
|
||||
you in a convenient-enough package.
|
||||
|
||||
Such packages should be more stable than SVN trunk, where bleeding-edge
|
||||
Such packages may be more stable than git mainline, where bleeding-edge
|
||||
development takes place. These "Packagers" produce binary releases of
|
||||
OpenOCD after the developers produces new "stable" versions of the
|
||||
source code. Previous versions of OpenOCD cannot be used to diagnosed
|
||||
OpenOCD after the developers produces new "release" versions of the
|
||||
source code. Previous versions of OpenOCD cannot be used to diagnose
|
||||
problems with the current release, so users are encouraged to keep in
|
||||
contact with their distribution package maintainers or interface vendors
|
||||
to ensure suitable upgrades appear regularly.
|
||||
@@ -199,7 +205,7 @@ options may be available there:
|
||||
|
||||
--enable-maintainer-mode enable make rules and dependencies not useful
|
||||
(and sometimes confusing) to the casual installer
|
||||
NOTE: This option is *required* for SVN builds!
|
||||
NOTE: This option is *required* for GIT builds!
|
||||
It should *not* be used to build a release.
|
||||
|
||||
--enable-dummy Enable building the dummy JTAG port driver
|
||||
@@ -209,9 +215,6 @@ options may be available there:
|
||||
FTD2XX
|
||||
--enable-ft2232_ftd2xx Enable building support for FT2232 based devices
|
||||
using the FTD2XX driver from ftdichip.com
|
||||
--enable-ftd2xx-highspeed
|
||||
Enable building support for FT2232H and
|
||||
FT4232H-based devices (requires >=libftd2xx-0.4.16)
|
||||
|
||||
--enable-gw16012 Enable building support for the Gateworks GW16012
|
||||
JTAG Programmer
|
||||
@@ -325,7 +328,7 @@ Then type ``make'', and perhaps ``make install''.
|
||||
Using FTDI's FTD2XX
|
||||
-------------------
|
||||
|
||||
Some claim the (closed) FTDICHIP.COM solution is faster, which
|
||||
The (closed source) FTDICHIP.COM solution is faster on MS-Windows. That
|
||||
is the motivation for supporting it even though its licensing restricts
|
||||
it to non-redistributable OpenOCD binaries, and it is not available for
|
||||
all operating systems used with OpenOCD. You may, however, build such
|
||||
@@ -370,29 +373,45 @@ the following:
|
||||
--with-ft2xx-linux-tardir=../libftd2xx0.4.16 \
|
||||
... other options ...
|
||||
|
||||
=================================
|
||||
Obtaining OpenOCD From Subversion
|
||||
---------------------------------
|
||||
Note that on Linux there is no good reason to use these FTDI binaries;
|
||||
they are no faster (on Linux) than libftdi, and cause licensing issues.
|
||||
|
||||
You can download the current SVN version with an SVN client of your
|
||||
choice from the following repositories:
|
||||
==========================
|
||||
Obtaining OpenOCD From GIT
|
||||
==========================
|
||||
|
||||
svn://svn.berlios.de/openocd/trunk
|
||||
or
|
||||
http://svn.berlios.de/svnroot/repos/openocd/trunk
|
||||
You can download the current GIT version with a GIT client of your
|
||||
choice from the main repository:
|
||||
|
||||
Using the SVN command line client, you can use the following command to
|
||||
fetch the latest version (make sure there is no (non-svn) directory
|
||||
called "openocd" in the current directory):
|
||||
git://openocd.git.sourceforge.net/gitroot/openocd/openocd
|
||||
|
||||
svn checkout svn://svn.berlios.de/openocd/trunk openocd
|
||||
You may prefer to use a mirror:
|
||||
|
||||
If you prefer GIT based tools, the git-svn package works too:
|
||||
http://repo.or.cz/r/openocd.git
|
||||
git://repo.or.cz/openocd.git
|
||||
|
||||
git svn clone -s svn://svn.berlios.de/openocd
|
||||
Using the GIT command line client, you might use the following command
|
||||
to set up a local copy of the current repository (make sure there is no
|
||||
directory called "openocd" in the current directory):
|
||||
|
||||
Tips For Building From The Subversion Repository
|
||||
************************************************
|
||||
git clone git://openocd.git.sourceforge.net/gitroot/openocd/openocd
|
||||
|
||||
Then you can update that at your convenience using
|
||||
|
||||
git pull
|
||||
|
||||
There is also a gitweb interface, which you can use either to browse
|
||||
the repository or to downlad arbitrary snapshots using HTTP:
|
||||
|
||||
http://openocd.git.sourceforge.net/git/gitweb.cgi?p=openocd/openocd
|
||||
http://repo.or.cz/w/openocd.git
|
||||
|
||||
Snapshots are compressed tarballs of the source tree, about 1.3 MBytes
|
||||
each at this writing.
|
||||
|
||||
|
||||
Tips For Building From a GIT Repository
|
||||
---------------------------------------
|
||||
|
||||
Building OpenOCD from a repository requires a recent version of the GNU
|
||||
autotools (autoconf >= 2.59 and automake >= 1.9).
|
||||
|
||||
@@ -40,7 +40,8 @@ Take note that different Linux distributions often have different MinGW
|
||||
installation directory. Some of them also put the library and include
|
||||
into a separate sys-root directory.
|
||||
|
||||
If there is a new svn version of libusb-win32, you can build it as well.
|
||||
When the libusb-win32 repository is more current than its release code,
|
||||
you could build that instead.
|
||||
|
||||
These are the instruction from the libusb-win32 Makefile:
|
||||
|
||||
@@ -93,5 +94,5 @@ To use ftd2xx:
|
||||
--with-ftd2xx-win32-zipdir=/path/to/libftd2xx-win32 \
|
||||
... other options ...
|
||||
|
||||
If you are using the SVN repository, see the README file for additional
|
||||
If you are using the GIT repository, see the README file for additional
|
||||
instructions about configuring and building OpenOCD.
|
||||
|
||||
99
TODO
99
TODO
@@ -23,6 +23,10 @@ This section provides possible things to improve with OpenOCD's TCL support.
|
||||
- provide more directory structure for boards/targets?
|
||||
- factor configurations into layers (encapsulation and re-use)
|
||||
|
||||
- Fix handling of variables between multiple command line "-c" and "-f"
|
||||
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.
|
||||
- Allow developers to build new dongles using OpenOCD's JTAG core.
|
||||
@@ -39,22 +43,48 @@ This section list issues that need to be resolved in the JTAG layer.
|
||||
|
||||
@subsection thelistjtagcore JTAG Core
|
||||
|
||||
The following tasks have been suggeted for cleaning up the JTAG layer:
|
||||
The following tasks have been suggested for cleaning up the JTAG layer:
|
||||
|
||||
- use tap_set_state everywhere to allow logging TAP state transitions
|
||||
- rename other tap_states to use standard JTAG names (suggested by ML)
|
||||
- Encapsulate cmd_queue_cur_state and related varaible handling.
|
||||
- add slick 32 bit versions of jtag_add_xxx_scan() that avoids
|
||||
buf_set_u32() calls and other evidence of poor impedance match between
|
||||
API and calling code. New API should cut down # of lines in calling
|
||||
code by 100's and make things clearer. Also potentially be supported
|
||||
directly in minidriver API for better embedded host performance.
|
||||
|
||||
The following tasks have been suggested for adding new core JTAG support:
|
||||
|
||||
- autodetect devices present on the scan chain
|
||||
- implement 'discover_taps' command
|
||||
- Improve autodetection of TAPs by supporting tcl escape procedures that
|
||||
can configure discovered TAPs based on IDCODE value ... they could:
|
||||
- Remove guessing for irlen
|
||||
- Allow non-default irmask/ircapture values
|
||||
- SPI/UART emulation:
|
||||
- (ab)use bit-banging JTAG interfaces to emulate SPI/UART
|
||||
- allow SPI to program flash, MCUs, etc.
|
||||
|
||||
@subsection thelistjtaginterfaces JTAG Interfaces
|
||||
|
||||
There are some known bugs to fix in JTAG adapter drivers:
|
||||
|
||||
- For JTAG_STATEMOVE to TAP_RESET, all drivers must ignore the current
|
||||
recorded state. The tap_get_state() call won't necessarily return
|
||||
the correct value, especially at server startup. Fix is easy: in
|
||||
that case, always issue five clocks with TMS high.
|
||||
- amt_jtagaccel.c
|
||||
- arm-jtag-ew.c
|
||||
- bitbang.c
|
||||
- bitq.c
|
||||
- gw16012.c
|
||||
- jlink.c
|
||||
- usbprog.c
|
||||
- vsllink.c
|
||||
- rlink/rlink.c
|
||||
- bug: USBprog is broken with new tms sequence; it needs 7-clock cycles.
|
||||
Fix promised from Peter Denison openwrt at marshadder.org
|
||||
Workaround: use "tms_sequence long" @par
|
||||
https://lists.berlios.de/pipermail/openocd-development/2009-July/009426.html
|
||||
|
||||
The following tasks have been suggeted for improving OpenOCD's JTAG
|
||||
interface support:
|
||||
|
||||
@@ -64,12 +94,21 @@ interface support:
|
||||
- J-Link driver:
|
||||
- fix to work with long scan chains, such as R.Doss's svf test.
|
||||
- FT2232 (libftdi):
|
||||
- make performance comparable to alternatives
|
||||
- make performance comparable to alternatives (on Win32, D2XX is faster)
|
||||
- make usability comparable to alternatives
|
||||
- Autodetect USB based adapters; this should be easy on Linux. If there's
|
||||
more than one, list the options; otherwise, just select that one.
|
||||
|
||||
The following tasks have been suggested for adding new JTAG interfaces:
|
||||
|
||||
- TCP driver: allow client/server for remote JTAG interface control.
|
||||
This requires a client and a server. The server is built into the
|
||||
normal OpenOCD and takes commands from the client and executes
|
||||
them on the interface returning the result of TCP/IP. The client
|
||||
is an OpenOCD which is built with a TCP/IP minidriver. The use
|
||||
of a minidriver is required to capture all the jtag_add_xxx()
|
||||
fn's at a high enough level and repackage these cmd's as
|
||||
TCP/IP packets handled by the server.
|
||||
|
||||
@section thelistswd Serial Wire Debug
|
||||
|
||||
@@ -98,24 +137,38 @@ Once the above are completed:
|
||||
|
||||
@section thelisttargets Target Support
|
||||
|
||||
- Many common ARM cores could be autodetected using IDCODE
|
||||
- general layer cleanup: @par
|
||||
https://lists.berlios.de/pipermail/openocd-development/2009-May/006590.html
|
||||
- regression: xscale does not place debug_handler.bin into the right spot. workaround:
|
||||
use -s option on command line to place xscale/debug_handler.bin in search path @par
|
||||
https://lists.berlios.de/pipermail/openocd-development/2009-July/009338.html
|
||||
- bug: either USBprog is broken with new tms sequence or there is a general
|
||||
problem with XScale and the new tms sequence. Workaround: use "tms_sequence long"
|
||||
@par
|
||||
https://lists.berlios.de/pipermail/openocd-development/2009-July/009426.html
|
||||
- regression: "reset halt" between 729(works) and 788(fails): @par
|
||||
https://lists.berlios.de/pipermail/openocd-development/2009-July/009206.html
|
||||
- ARM923EJS:
|
||||
- ARM7/9:
|
||||
- clean up "arm9tdmi vector_catch". Available for some arm7 cores? @par
|
||||
https://lists.berlios.de/pipermail/openocd-development/2009-October/011488.html
|
||||
https://lists.berlios.de/pipermail/openocd-development/2009-October/011506.html
|
||||
- add reset option to allow programming embedded ice while srst is asserted.
|
||||
Some CPUs will gate the JTAG clock when srst is asserted and in this case,
|
||||
it is necessary to program embedded ice and then assert srst afterwards.
|
||||
- ARM926EJS:
|
||||
- reset run/halt/step is not robust; needs testing to map out problems.
|
||||
- ARM11 improvements (MB?)
|
||||
- fix single stepping (reported by <20>H)
|
||||
- add support for asserting srst to reset the core.
|
||||
- Single stepping works, but should automatically
|
||||
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:
|
||||
mdw 0xb80005f0 0x8, mdh 0xb80005f0 0x10, mdb 0xb80005f0 0x20. mdb returns
|
||||
garabage.
|
||||
- implement missing functionality (grep FNC_INFO_NOTIMPLEMENTED ...)
|
||||
- thumb support is missing: ISTR ARMv6 requires Thumb.
|
||||
ARM1156 has Thumb2; ARM1136 doesn't.
|
||||
- Cortex A8 support (ML)
|
||||
- add target implementation (ML)
|
||||
- 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
|
||||
- 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)
|
||||
@@ -144,14 +197,6 @@ https://lists.berlios.de/pipermail/openocd-development/2009-July/009206.html
|
||||
|
||||
@section thelistflash Flash Support
|
||||
|
||||
- aduc702x segfault reported by Thomas A Moulton
|
||||
|
||||
https://lists.berlios.de/pipermail/openocd-development/2009-July/009186.html
|
||||
|
||||
- aduc7024 programming w/working area does not work:
|
||||
|
||||
https://lists.berlios.de/pipermail/openocd-development/2009-July/009337.html
|
||||
|
||||
- finish documentation for the following flash drivers:
|
||||
- avr
|
||||
- ecosflash
|
||||
@@ -164,12 +209,19 @@ https://lists.berlios.de/pipermail/openocd-development/2009-July/009337.html
|
||||
- finish implementing bus width/chip width handling (suggested by NC)
|
||||
- factor vendor-specific code into separate source files
|
||||
- add new callback interface for vendor-specific code
|
||||
- investigate/implement "thin wrapper" to use eCos CFI drivers (<EFBFBD>H)
|
||||
- investigate/implement "thin wrapper" to use eCos CFI drivers (ØH)
|
||||
|
||||
@section thelistdebug Debugger Support
|
||||
|
||||
- add support for masks in watchpoints? @par
|
||||
https://lists.berlios.de/pipermail/openocd-development/2009-October/011507.html
|
||||
- breakpoints can get lost in some circumstances: @par
|
||||
https://lists.berlios.de/pipermail/openocd-development/2009-June/008853.html
|
||||
- add support for masks in watchpoints. The trick is that GDB does not
|
||||
support a breakpoint mask in the remote protocol. One way to work around
|
||||
this is to add a separate command "watchpoint_mask add/rem <addr> <mask>", that
|
||||
is run to register a list of masks that the gdb_server knows to use with
|
||||
a particular watchpoint address.
|
||||
- integrate Keil AGDI interface to OpenOCD? (submitted by Dario Vecchio)
|
||||
|
||||
@section thelisttesting Testing Suite
|
||||
@@ -282,3 +334,4 @@ to complete:
|
||||
/** @file
|
||||
This file contains the @ref thelist page.
|
||||
*/
|
||||
|
||||
|
||||
@@ -20,6 +20,7 @@ autoheader
|
||||
automake --gnu --add-missing --copy
|
||||
)
|
||||
|
||||
# AM_MAINTAINER_MODE requires SVN users provide --enable-maintainer-mode
|
||||
# AM_MAINTAINER_MODE requires --enable-maintainer-mode from everyone using
|
||||
# current source snapshots (working from GIT, or some source snapshot, etc)
|
||||
# otherwise the documentation will fail to build due to missing version.texi
|
||||
echo "Bootstrap complete; you can './configure --enable-maintainer-mode ....'"
|
||||
|
||||
57
configure.in
57
configure.in
@@ -1,5 +1,5 @@
|
||||
AC_PREREQ(2.60)
|
||||
AC_INIT([openocd], [0.2.0],
|
||||
AC_INIT([openocd], [0.3.0-rc0],
|
||||
[OpenOCD Mailing List <openocd-development@lists.berlios.de>])
|
||||
AC_CONFIG_SRCDIR([src/openocd.c])
|
||||
|
||||
@@ -323,10 +323,6 @@ 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(ftd2xx_highspeed,
|
||||
AS_HELP_STRING([--enable-ftd2xx-highspeed], [Enable building support for FT2232H and FT4232H-based devices (requires >=libftd2xx-0.4.16)]),
|
||||
[want_ftd2xx_highspeed=$enableval], [want_ftd2xx_highspeed=no])
|
||||
|
||||
AC_ARG_ENABLE(amtjtagaccel,
|
||||
AS_HELP_STRING([--enable-amtjtagaccel], [Enable building the Amontec JTAG-Accelerator driver]),
|
||||
[build_amtjtagaccel=$enableval], [build_amtjtagaccel=no])
|
||||
@@ -381,7 +377,8 @@ AC_ARG_ENABLE(usbprog,
|
||||
[build_usbprog=$enableval], [build_usbprog=no])
|
||||
|
||||
AC_ARG_ENABLE(oocd_trace,
|
||||
AS_HELP_STRING([--enable-oocd_trace], [Enable building support for the OpenOCD+trace ETM capture device]),
|
||||
AS_HELP_STRING([--enable-oocd_trace],
|
||||
[Enable building support for some prototype OpenOCD+trace ETM capture hardware]),
|
||||
[build_oocd_trace=$enableval], [build_oocd_trace=no])
|
||||
|
||||
AC_ARG_ENABLE(jlink,
|
||||
@@ -453,6 +450,7 @@ esac
|
||||
case $host in
|
||||
*-cygwin*)
|
||||
is_win32=yes
|
||||
parport_use_ppdev=no
|
||||
|
||||
AC_COMPILE_IFELSE(AC_LANG_PROGRAM([],[return __MINGW32__;]),
|
||||
[is_mingw=yes],[is_mingw=no])
|
||||
@@ -466,6 +464,10 @@ case $host in
|
||||
else
|
||||
is_cygwin=yes
|
||||
AC_DEFINE(IS_CYGWIN, 1, [1 if building for Cygwin.])
|
||||
# sys/io.h needed under cygwin for parport access
|
||||
if test $build_parport = yes; then
|
||||
AC_CHECK_HEADERS(sys/io.h,[],AC_MSG_ERROR([Please install the cygwin ioperm package]))
|
||||
fi
|
||||
fi
|
||||
|
||||
AC_DEFINE(IS_WIN32, 1, [1 if building for Win32.])
|
||||
@@ -474,12 +476,15 @@ case $host in
|
||||
*-mingw*)
|
||||
is_mingw=yes
|
||||
is_win32=yes
|
||||
parport_use_ppdev=no
|
||||
|
||||
if test x$parport_use_giveio = xno; then
|
||||
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.])
|
||||
AC_DEFINE(IS_WIN32, 1, [1 if building for Win32.])
|
||||
AC_DEFINE(IS_DARWIN, 0, [0 if not building for Darwin.])
|
||||
@@ -828,11 +833,8 @@ main( int argc, char **argv )
|
||||
AC_MSG_RESULT([Skipping as we are cross-compiling])
|
||||
])
|
||||
|
||||
AC_MSG_CHECKING([whether to build ftd2xx highspeed device support])
|
||||
AC_MSG_RESULT([$want_ftd2xx_highspeed])
|
||||
if test $want_ftd2xx_highspeed != no; then
|
||||
AC_MSG_CHECKING([for ftd2xx highspeed device support])
|
||||
AC_COMPILE_IFELSE([
|
||||
AC_MSG_CHECKING([for ftd2xx highspeed device support])
|
||||
AC_COMPILE_IFELSE([
|
||||
#include "confdefs.h"
|
||||
#if IS_WIN32
|
||||
#include "windows.h"
|
||||
@@ -841,18 +843,17 @@ if test $want_ftd2xx_highspeed != no; then
|
||||
#include <ftd2xx.h>
|
||||
DWORD x = FT_DEVICE_4232H;
|
||||
], [
|
||||
AC_DEFINE(BUILD_FTD2XX_HIGHSPEED, [1],
|
||||
[Support FT2232H/FT4232HS with FTD2XX.])
|
||||
build_ftd2xx_highspeed=yes
|
||||
AC_DEFINE(BUILD_FT2232_HIGHSPEED, [1],
|
||||
[Support FT2232H/FT4232HS with FTD2XX or libftdi.])
|
||||
build_ft2232_highspeed=yes
|
||||
], [
|
||||
build_ftd2xx_highspeed=no
|
||||
build_ft2232_highspeed=no
|
||||
])
|
||||
AC_MSG_RESULT([$build_ftd2xx_highspeed])
|
||||
AC_MSG_RESULT([$build_ft2232_highspeed])
|
||||
|
||||
if test $want_ftd2xx_highspeed = yes -a $build_ftd2xx_highspeed = no; then
|
||||
AC_MSG_ERROR([You need a newer FTD2XX driver (version 0.4.16 or later).])
|
||||
if test $build_ft2232_highspeed = no; then
|
||||
AC_MSG_WARN([You need a newer FTD2XX driver (version 2.04.16 or later).])
|
||||
fi
|
||||
fi
|
||||
|
||||
LDFLAGS=$LDFLAGS_SAVE
|
||||
CFLAGS=$CFLAGS_SAVE
|
||||
@@ -897,6 +898,24 @@ main( int argc, char **argv )
|
||||
AC_MSG_RESULT([Skipping as we are cross-compiling])
|
||||
])
|
||||
|
||||
AC_MSG_CHECKING([for libftdi highspeed device support])
|
||||
AC_COMPILE_IFELSE([
|
||||
#include <stdio.h>
|
||||
#include <ftdi.h>
|
||||
enum ftdi_chip_type x = TYPE_2232H;
|
||||
], [
|
||||
AC_DEFINE(BUILD_FT2232_HIGHSPEED, [1],
|
||||
[Support FT2232H/FT4232HS with FTD2XX or libftdi.])
|
||||
build_ft2232_highspeed=yes
|
||||
], [
|
||||
build_ft2232_highspeed=no
|
||||
])
|
||||
AC_MSG_RESULT([$build_ft2232_highspeed])
|
||||
|
||||
if test $build_ft2232_highspeed = no; then
|
||||
AC_MSG_WARN([You need a newer libftdi version (0.16 or later).])
|
||||
fi
|
||||
|
||||
# Restore the 'unexpanded ldflags'
|
||||
LDFLAGS=$LDFLAGS_SAVE
|
||||
CFLAGS=$CFLAGS_SAVE
|
||||
|
||||
@@ -22,14 +22,14 @@ cases, a fresh bootstrap may be still required.
|
||||
@subsection primerbootstrapcures Problems Solved By Bootstrap
|
||||
|
||||
For example, the build system can fail in unexpected ways after running
|
||||
<code>svn update</code>. Here, the <code>make maintainer-clean</code>
|
||||
<code>git pull</code>. Here, the <code>make maintainer-clean</code>
|
||||
should be used to remove all of the files generated by the @c bootstrap
|
||||
script and subsequent build processes.
|
||||
|
||||
In this particular case, one may also need to remove stray files by hand
|
||||
after running this command to ensure everything is rebuilt properly.
|
||||
This step should be necessary only if the @c maintainer-clean was run
|
||||
@b after altering the build system files with Subversion. If it is run
|
||||
@b after altering the build system files with git. If it is run
|
||||
@b before any updates, the build system should never leave artifacts
|
||||
in the tree.
|
||||
|
||||
@@ -61,7 +61,7 @@ experience errors when running @c make that some files cannot be found
|
||||
the problems. The isssue is well-known and expected, if unfortunate.
|
||||
|
||||
The OpenOCD project requires that all developers building from the
|
||||
Subversion repository use the @c --enable-maintainer-mode option when
|
||||
git repository use the @c --enable-maintainer-mode option when
|
||||
running the @c configure script. This option ensures that certain files
|
||||
are created during the build process that would normally be packaged in
|
||||
the distribution tarball. The @c bootstrap script will remind you of
|
||||
|
||||
@@ -6,10 +6,10 @@ for OpenOCD contributors who are unfamiliar with the process.
|
||||
@section primerpatchintro Introduction to Patching
|
||||
|
||||
The standard method for creating patches requires developers to:
|
||||
- checkout the Subversion repository (or bring a copy up-to-date),
|
||||
- checkout the git repository (or bring a copy up-to-date),
|
||||
- make the necessary modifications to a working copy,
|
||||
- check with 'svn status' to see which files will be modified/added, and
|
||||
- use 'svn diff' to review the changes and produce a patch.
|
||||
- check with 'git status' to see which files will be modified/added, and
|
||||
- use 'git diff' to review the changes and produce a patch.
|
||||
|
||||
It is important to minimize the changes to only those lines that contain
|
||||
important differences; do not allow stray whitespace changes into your
|
||||
@@ -20,7 +20,7 @@ patches, and keep the focus to a single logical change.
|
||||
You can create a patch (from the root of your working copy) with a
|
||||
command like the following example: @par
|
||||
@verbatim
|
||||
svn diff > patch-name.patch
|
||||
git diff > patch-name.patch
|
||||
@endverbatim
|
||||
|
||||
where @a patch-name should be something that is descriptive and unique.
|
||||
@@ -29,8 +29,8 @@ The above command will create a patch containing all of the changes in
|
||||
the working copy; if you want to obtain a subset, simply provide the
|
||||
list of files to the command: @par
|
||||
@verbatim
|
||||
svn diff doc > <patch-name>-doc.patch
|
||||
svn diff src > <patch-name>-src.patch
|
||||
git diff doc > <patch-name>-doc.patch
|
||||
git diff src > <patch-name>-src.patch
|
||||
@endverbatim
|
||||
|
||||
This will create two patches, each containing only those changes present
|
||||
@@ -56,65 +56,20 @@ submission, sending your patch to the bit bucket on accident.
|
||||
@section primerpatchpreflight Developer Review
|
||||
|
||||
Before sending in patches, please make sure you have updated to the
|
||||
latest version of the trunk (using <code>svn up</code>) before creating
|
||||
latest version of the trunk (using <code>git pull</code>) before creating
|
||||
your patch. This helps to increase the chances that it will apply
|
||||
cleanly to the trunk. However, the content matters most.
|
||||
|
||||
When creating a patch using "<code>svn diff</code>", Subversion will
|
||||
When creating a patch using "<code>git diff</code>", git will
|
||||
produce a patch that contains all of the changes in your working copy.
|
||||
To manage multiple changes at once, you either need one working copy per
|
||||
patch, or you can specified specific files and directories when using
|
||||
<code>svn diff</code>. Overlapping patches will be discussed in the
|
||||
<code>git diff</code>. Overlapping patches will be discussed in the
|
||||
next section.
|
||||
|
||||
The remainder of this section provides
|
||||
|
||||
@subsection primerpatchprops Subversion Properties
|
||||
|
||||
The Subversion attributes of files can be examined with commands like the
|
||||
following: @par
|
||||
@verbatim
|
||||
$ svn pl README
|
||||
Properties on 'README':
|
||||
svn:eol-style
|
||||
$ svn pl tools/rlink_make_speed_table/rlink_make_speed_table.pl
|
||||
Properties on 'tools/rlink_make_speed_table/rlink_make_speed_table.pl':
|
||||
svn:executable
|
||||
svn:eol-style
|
||||
$
|
||||
@endverbatim
|
||||
|
||||
@subsection primerpatchpropcrlf Native Line-endings
|
||||
|
||||
Subversion checks out files marked with the attribute @c svn:eol-style
|
||||
set to @c native such that these files contain the default line ending
|
||||
style of the current host ('\\n' or '\\r\\n'). By using the proper line
|
||||
endings for different platforms, two different byte streams for the same
|
||||
file will be produced.
|
||||
|
||||
@subsection primerpatchwincrlf Windows Patching Problems
|
||||
|
||||
Because of the line-ending functionality, it may be correct when a fresh
|
||||
patch does not apply cleanly on the Windows platform. This is because
|
||||
patches are created by SVN with UNIX line endings, so the context and
|
||||
changes will not appear to match the files with Windows line endings.
|
||||
|
||||
In other words, the following command may @b not succeed because @c foo
|
||||
has its @c svn:eol-style property set to @c native: @par
|
||||
@code
|
||||
svn diff foo | patch -R
|
||||
@endcode
|
||||
|
||||
The following series of commands will work: @par
|
||||
@code
|
||||
svn diff foo | unix2dos | patch -R
|
||||
@endcode
|
||||
|
||||
This is not a bug.
|
||||
|
||||
@todo Does Subversion's treatment of line-endings for files marked with
|
||||
svn:eol-style=native continue to pose the problems described here, or
|
||||
has this been magically solved?
|
||||
@todo Does git's treatment of line-endings behave sanely?
|
||||
Basically, the repository should use newlines internally,
|
||||
and convert to/from CRLF on Windows etc.
|
||||
|
||||
@section primerpatchseries Patch Series
|
||||
|
||||
@@ -132,9 +87,8 @@ simply a matter of taste or familiarity; your mileage may vary.
|
||||
|
||||
Packages such as @c patchutils, @c diffutils, and @c quilt are among
|
||||
those that have proved themselves invaluable for these type of tasks.
|
||||
Others take their patch management a step further, tracking the
|
||||
Subversion repository with git-svn and employing GIT conventions and
|
||||
methodologies for development.
|
||||
Others take their patch management a step further, using stkgit or
|
||||
some other framework on top of git.
|
||||
|
||||
@subsection primerpatchseriesinterdiff Using @c interdiff
|
||||
|
||||
@@ -144,22 +98,22 @@ patches. This command can be used to manage the creation of trivial
|
||||
patch series. For example, the following sequence of commands will
|
||||
produce three patches: @par
|
||||
@verbatim
|
||||
$ cd openocd-head/
|
||||
$ svn up && svn st
|
||||
At revision NNNN.
|
||||
$ cd openocd/
|
||||
$ git pull
|
||||
...
|
||||
$ <<<start changes for patch #1>>>
|
||||
...
|
||||
$ <<<finish changes for patch #1>>>
|
||||
$ svn diff > series-1.patch # patch #1 is easy
|
||||
$ git diff > series-1.patch # patch #1 is easy
|
||||
$ <<<start changes for patch #2>>>
|
||||
...
|
||||
$ <<<finish changes for patch #2>>>
|
||||
$ svn diff > series-1+2.patch # create patch 1+2
|
||||
$ git diff > series-1+2.patch # create patch 1+2
|
||||
$ interdiff series-1{,+2}.patch > series-2.patch # 1 ~ 1+2 => #2
|
||||
$ <<<start changes for patch #3>>>
|
||||
...
|
||||
$ <<<finish changes for patch #3>>>
|
||||
$ svn diff > series-1+2+3.patch # create patch 1+2+3
|
||||
$ git diff > series-1+2+3.patch # create patch 1+2+3
|
||||
$ interdiff series-1+2{,+3}.patch > series-3.patch # 1+2 ~ 1+2+3 => 3
|
||||
@endverbatim
|
||||
|
||||
@@ -173,19 +127,14 @@ efficiently than can be managed by hand. For out-of-tree work projects
|
||||
that require such patch management, @c quilt provides an indispensable
|
||||
tool for solving the problem.
|
||||
|
||||
@subsection primerpatchseriesgit Using @c git
|
||||
|
||||
The @c git revision control system provides a tool for tracking
|
||||
Subversion repositories.
|
||||
|
||||
@section primerpatchsubmit Submitting Patches
|
||||
|
||||
Write access to the OpenOCD Subversion repository is limited to
|
||||
Write access to the OpenOCD git repository is limited to
|
||||
contributors that have demonstrated the ability to produce clear,
|
||||
consistent, and frequent patches. These individuals are responsible
|
||||
for maintaining the integrity of the repository for the community.
|
||||
|
||||
Thus, commits to the Subversion repository must be handled by one of
|
||||
Thus, commits to the git repository must be handled by one of
|
||||
these maintainers.
|
||||
|
||||
Patches must be sent to the OpenOCD developer mailing list:
|
||||
|
||||
@@ -14,35 +14,35 @@ This page provides an introduction to the OpenOCD Release Processes:
|
||||
|
||||
@section releasewhy Why Produce Releases?
|
||||
|
||||
The OpenOCD maintainers should produce <i>releases</i> periodically. This
|
||||
section gives several reasons to explain the reasons for making releases
|
||||
on a regular basis. These reasons lead to motivation for developing and
|
||||
following a set of <i>release processes</i>. The actual processes are
|
||||
described in the remainder of the @ref releases sections.
|
||||
The OpenOCD maintainers produce <i>releases</i> periodically for many
|
||||
reasons. This section provides the key reasons for making releases on a
|
||||
regular basis and why a set of <i>release processes</i> should be used
|
||||
to produce them.
|
||||
|
||||
At any time, a "source archives" can be produced by running 'make dist'
|
||||
in the OpenOCD project tree. With the 0.2.0 release, this command will
|
||||
produce openocd-\<version\>.{tar.gz,tar.bz2,zip} archives. These files
|
||||
will be suitable for being released when produced properly.
|
||||
At any time, <i>source archives</i> can be produced by running
|
||||
<code>make dist</code> in the OpenOCD project tree. With the 0.2.0
|
||||
release, this command will package the tree into several popular archive
|
||||
formats: <code>openocd-\<version\>.{tar.gz,tar.bz2,zip}</code>. If
|
||||
produced properly, these files are suitable for release to the public.
|
||||
|
||||
When released for users, these archives present several important
|
||||
advantages when contrasted to using the Subversion repository:
|
||||
advantages when contrasted to using the git repository:
|
||||
|
||||
-# They allow others to package and distribute the code to users.
|
||||
-# They allow others to package and distribute the code.
|
||||
-# They build easier for developers, because they contain
|
||||
a working configure script that was produced by the Release Manager.
|
||||
-# They prevent users from trying a random HEAD revision of the trunk.
|
||||
-# They free developers from answering questions about trunk breakage.
|
||||
-# They prevent users from trying a random work-in-process revision.
|
||||
-# They free developers from answering questions about mainline breakage.
|
||||
|
||||
Hopefully, this shows several good reasons to produce regular releases,
|
||||
but these release processes were developed with some additional design
|
||||
but the release processes were developed with some additional design
|
||||
goals in mind. Specifically, the releases processes should have the
|
||||
following properties:
|
||||
|
||||
-# Produce successive sets of release archives cleanly and consistently.
|
||||
-# Implementable as a script that automates the critical release steps.
|
||||
-# Prevent human operators from producing bad releases, when possible.
|
||||
-# Allow scheduling and automation of release process milestones.
|
||||
-# Produce successive sets of archives cleanly and consistently.
|
||||
-# Implementable as a script that automates the critical steps.
|
||||
-# Prevent human operators from producing broken packages, when possible.
|
||||
-# Allow scheduling and automation of building and publishing milestones.
|
||||
|
||||
The current release processes are documented in the following sections.
|
||||
They attempt to meet these design goals, but there may improvements
|
||||
@@ -59,27 +59,50 @@ For a <i>bug-fix</i> release, the micro version number will be non-zero
|
||||
number will be zero (<code>z = 0</code>). For a <i>major releases</i>,
|
||||
the minor version will @a also be zero (<code>y = 0, z = 0</code>).
|
||||
|
||||
The trunk and all branches should have the tag '-in-development' in
|
||||
@subsection releaseversiontags Version Tags
|
||||
|
||||
After these required numeric components, the version string may contain
|
||||
one or more <i>version tags</i>, such as '-rc1' or '-dev'.
|
||||
|
||||
Mainline and all branches should have the tag '-dev' in
|
||||
their version number. This tag helps developers identify reports
|
||||
created from the Subversion repository, and it can be detected and
|
||||
created from the git repository, and it can be detected and
|
||||
manipulated by the release script. Specifically, this tag will be
|
||||
removed and re-added during the release process; it should never be
|
||||
manipulated by developers in submitted patches.
|
||||
|
||||
@subsection releaseversionsdist Patched Versions
|
||||
The 'rc' tags indicate a "release candidate" version of the package.
|
||||
This tag will also be manipulated by the automated release process.
|
||||
|
||||
Distributors of patched versions of OpenOCD are encouraged to extend
|
||||
the version string when producing external releases, as this helps to
|
||||
identify your particular distribution series.
|
||||
Additional tags may be used as necessary.
|
||||
|
||||
@subsection releaseversionsdist Version Processes
|
||||
@subsection releaseversionsdist Packager Versions
|
||||
|
||||
Distributors of patched versions of OpenOCD are encouraged to extend the
|
||||
version string with a unique version tag when producing external
|
||||
releases, as this helps to identify your particular distribution series.
|
||||
|
||||
For example, the following command will add a 'foo1' tag to the
|
||||
configure.in script of a local copy of the source tree:
|
||||
|
||||
@code
|
||||
tools/release.sh version bump tag foo
|
||||
@endcode
|
||||
|
||||
This command will modify the configure.in script in your working copy
|
||||
only. After running the @c bootstrap sequence, the tree can be patched
|
||||
and used to produce your own derived versions. The same command can be
|
||||
used each time the derived package is released, incrementing the tag's
|
||||
version to facilitate tracking the changes you have distributed.
|
||||
|
||||
@subsection releaseversionhow Version Processes
|
||||
|
||||
The release process includes version number manipulations to the tree
|
||||
being released, ensuring that all numbers are incremented at the right
|
||||
time and in the proper locations of the repository.
|
||||
|
||||
The version numbers for any branch should monotonically
|
||||
increase to the next successive integer, except when reset to zero
|
||||
The version numbers for any branch should increase monotonically
|
||||
to the next successive integer, except when reset to zero
|
||||
during major or minor releases. The community should decide when
|
||||
major and minor milestones will be released.
|
||||
|
||||
@@ -136,8 +159,8 @@ If T is the time of the next release, then the following schedule
|
||||
might describe some of the key milestones of the new release cycle:
|
||||
|
||||
- T minus one month: start of new development cycle
|
||||
- T minus two weeks: announce pending trunk closure to new work
|
||||
- T minus one week: close trunk to new work, begin testing phase
|
||||
- T minus two weeks: announce pending mainline closure to new work
|
||||
- T minus one week: close mainline to new work, begin testing phase
|
||||
- T minus two days: call for final bug fixes
|
||||
- T minus one day: produce -rc packages and distribute to testers
|
||||
- T minus one hour: produce final packages and post on-line
|
||||
@@ -169,7 +192,7 @@ than allowing the release cycle to be delayed while waiting for them.
|
||||
|
||||
Despite any assurances this schedule may appear to give, the Release
|
||||
Manager cannot schedule the work that will be done on the project,
|
||||
when it will be submitted, review, and deemed suitable to be committed.
|
||||
when it will be submitted, reviewed, and deemed suitable to be committed.
|
||||
In this way, the RM cannot act as a priest in a cathedral; OpenOCD uses
|
||||
the bazaar development model. The release schedule must adapt
|
||||
continuously in response to changes in the rate of churn.
|
||||
@@ -179,7 +202,7 @@ expectation of a fairly high rate of development. Fewer releases may be
|
||||
required if developers contribute less patches, and more releases may be
|
||||
desirable if the project continues to grow and experience high rates of
|
||||
community contribution. During each cycle, the RM should be tracking
|
||||
the situation and gathering feedback from the community .
|
||||
the situation and gathering feedback from the community.
|
||||
|
||||
@section releasehow Release Process: Step-by-Step
|
||||
|
||||
@@ -189,45 +212,47 @@ Even with the release script, some steps require clear user intervention
|
||||
|
||||
The following steps should be followed to produce each release:
|
||||
|
||||
-# Produce final patches to the trunk (or release branch):
|
||||
-# Produce final manual patches to mainline (or release branch):
|
||||
-# Finalize @c NEWS file to describe the changes in the release
|
||||
- This file is Used to automatically post "blurbs" about the project.
|
||||
- This material should be produced during the development cycle.
|
||||
- Add a new item for each @c NEWS-worthy contribution, when committed.
|
||||
-# bump library version if our API changed (not yet required)
|
||||
-# Remove -in-development tag from package version:
|
||||
- For major/minor releases, remove version tag from trunk, @a or
|
||||
- For bug-fix releases, remove version tag from release branch.
|
||||
-# Branch or tag the required tree in the Subversion repository:
|
||||
- Tags and branches for releases must be named consistently: @par
|
||||
"${PACKAGE_TARNAME}-${PACKAGE_VERSION}"
|
||||
- For a major/minor release from the main trunk, the code should be
|
||||
branched and tagged in the repository:
|
||||
-# Bump library version if our API changed (not yet required)
|
||||
-# Produce and tag the final revision in the git repository:
|
||||
- Update and commit the final package version in @c configure.in :
|
||||
-# Remove @c -dev tag.
|
||||
-# Remove @c -rc tag, if producing the final release from an -rc series.
|
||||
- Tags must be named consistently:
|
||||
@verbatim
|
||||
svn cp .../trunk .../branches/${RELEASE_BRANCH}
|
||||
svn cp .../branches/${RELEASE_BRANCH} .../tags/${RELEASE_TAG}
|
||||
@endverbatim
|
||||
- For bug-fix releases produced in their respective branch, a tag
|
||||
should be created in the repository:
|
||||
- Tag the final commit with a consistent GIT tag name and message:
|
||||
@verbatim
|
||||
svn cp .../branches/${RELEASE_BRANCH} .../tags/${RELEASE_TAG}
|
||||
PACKAGE_VERSION="x.y.z"
|
||||
PACKAGE_TAG="v${PACKAGE_VERSION}"
|
||||
git tag -m "The openocd-${PACKAGE_VERSION} release." "${PACKAGE_TAG}"
|
||||
@endverbatim
|
||||
-# Prepare to resume normal development activities:
|
||||
- Archive @c NEWS file as <code>doc/news/NEWS-${PACKAGE_VERSION}</code>.
|
||||
- Create a new @c NEWS file for the next release
|
||||
- For major/minor release from the trunk:
|
||||
-# Bump major or minor package version in trunk.
|
||||
-# Restore version tag to trunk and release branch.
|
||||
- For bug-fix releases from a release branch:
|
||||
-# Bump bug-fix version in release branch.
|
||||
-# Restore version tag to release branch.
|
||||
-# Prepare to resume normal development on the branch:
|
||||
- Restore @c -dev and -@c -rc0 version tags.
|
||||
- To start a new major (or minor) release cycle on the @c master branch:
|
||||
- Bump major (or minor) package version, zeroing sub-components.
|
||||
- Add -rc0 version tag:
|
||||
- This insures casual releases from GIT always increase monotonically.
|
||||
- For example, a major increment after releasing 1.2.3 starts 2.0.0-rc0-dev.
|
||||
- Archive @c NEWS file as "<code>doc/news/NEWS-${PACKAGE_VERSION}</code>".
|
||||
- Create a new @c NEWS file for the next release
|
||||
- To start a bug-fix release on a non-master branch:
|
||||
-# Bump bug-fix version.
|
||||
- To start another release candidate on a major or minor branch:
|
||||
-# Bump rc tag.
|
||||
-# Produce the package source archives:
|
||||
-# Start with a clean working copy, used for producing releases only.
|
||||
-# Switch to release tag branch: svn switch .../${RELEASE_TAG}
|
||||
-# produce a ChangeLog for the release (using svn2cl).
|
||||
-# Checkout the appropriate tag:
|
||||
<code>git checkout $(git tag ) "${PACKAGE_VERSION}"</code>
|
||||
-# Produce a ChangeLog for the release (using @c git2cl).
|
||||
-# @c bootstrap, @c configure, and @c make the package.
|
||||
-# Run <code>make distcheck</code> to produce the distribution archives.
|
||||
-# Run <code>make maintainer-clean</code> verify the repository is empty.
|
||||
-# Create signature files using @c md5sum, @c sha1sum, etc.
|
||||
-# Publish documentation for the release:
|
||||
- Allow users to access the documentation for each of our releases.
|
||||
- Place static copies of the following files on the project website:
|
||||
@@ -235,12 +260,21 @@ svn cp .../branches/${RELEASE_BRANCH} .../tags/${RELEASE_TAG}
|
||||
- @c ChangeLog: to show exactly what has been changed
|
||||
- User Guide, Developer Manual: to allow easy on-line viewing
|
||||
-# Upload packages and post announcements of their availability:
|
||||
-# Release packages into files section of berliOS project site:
|
||||
-# Release packages into files section of project sites:
|
||||
- SF.net:
|
||||
-# Create a new folder named "${PACKAGE_VERSION}"
|
||||
-# Select new folder as the target for uploads.
|
||||
-# Upload files via Web interface into new
|
||||
-# Set platform types for each archive:
|
||||
- .tar.bz2: Linux, Mac
|
||||
- .tar.gz: BSD, Solaris, Others
|
||||
- .zip: Windows
|
||||
- Berlios:
|
||||
-# Create the new release for the new version.
|
||||
-# Provide @c NEWS and ChangeLog files, as requested.
|
||||
-# Upload files via FTP to ftp://ftp.berlios.de/incoming/
|
||||
-# Edit descriptions for each file.
|
||||
-# Send E-mail Release Notice
|
||||
-# Click button to send E-mail Release Notice.
|
||||
-# Post announcement e-mail to the openocd-development list.
|
||||
-# Announce updates on freshmeat.net and other trackers.
|
||||
-# Submit big updates to news feeds (e.g. Digg, Reddit, etc.).
|
||||
@@ -251,7 +285,7 @@ Many of the processes described in the last section are no longer
|
||||
entrusted to humans. Instead, the @c release.sh script provides
|
||||
automation of the mechanical steps.
|
||||
|
||||
Presently, the @c release.sh script automates steps 1(c) through 4,
|
||||
Presently, the @c release.sh script automates steps 2 through 4,
|
||||
allowing the Release Manager from perform these tasks in easy steps.
|
||||
|
||||
The following task still need to be automated:
|
||||
@@ -261,61 +295,34 @@ The following task still need to be automated:
|
||||
- Step 6(b): package announcement e-mail process.
|
||||
- Step 6(c): post files and announce them using releaseforge.
|
||||
|
||||
In addition, support for '-rc' releases needs to be added.
|
||||
|
||||
@subsection releasescriptcmds Release Script Commands
|
||||
|
||||
The following output was taken from the release script:
|
||||
@verbatim
|
||||
usage: tools/release.sh [options] <command>
|
||||
The release script can be used for two tasks:
|
||||
- Creating releases and starting a new release cycle:
|
||||
@code
|
||||
git checkout master
|
||||
tools/release.sh --type=minor --final --start-rc release
|
||||
@endcode
|
||||
- Creating a development branch from a tagged release:
|
||||
@code
|
||||
git checkout 'v0.2.0'
|
||||
tools/release.sh --type=micro branch
|
||||
@endcode
|
||||
|
||||
Main Commands:
|
||||
info Show a summary of the next pending release.
|
||||
release Release the current tree as an archive.
|
||||
upload Upload archives to berliOS project site
|
||||
Both of these variations make automatic commits and tags in your
|
||||
repository, so you should be sure to run it on a cloned copy before
|
||||
proceding with a live release.
|
||||
|
||||
Build Commands:
|
||||
bootstrap Prepare the working copy for configuration and building.
|
||||
configure Configures the package; runs bootstrap, if needed.
|
||||
build Compiles the project; runs configure, if needed.
|
||||
|
||||
Packaging Commands:
|
||||
changelog Generate a new ChangeLog using svn2cl.
|
||||
package Produce new distributable source archives.
|
||||
stage Move archives to staging area for upload.
|
||||
|
||||
Repository Commands:
|
||||
commit Perform branch and tag, as appropriate for the version.
|
||||
branch Create a release branch from the project trunk.
|
||||
tag Create a tag for the current release branch.
|
||||
|
||||
Other Commands:
|
||||
version ... Perform version number and tag manipulations.
|
||||
clean Forces regeneration of results.
|
||||
clean_all Removes all traces of the release process.
|
||||
help Provides this list of commands.
|
||||
|
||||
For more information about this script, see the Release Processes page
|
||||
in the OpenOCD Developer's Manual (doc/manual/release.txt).
|
||||
|
||||
WARNING: This script should be used by the Release Manager ONLY.
|
||||
@endverbatim
|
||||
|
||||
Run <code>tools/release.sh help</code> for current command support.
|
||||
|
||||
@subsection releasescriptenv Release Script Options
|
||||
@subsection releasescriptopts Release Script Options
|
||||
|
||||
The @c release.sh script recognizes some command-line options that
|
||||
affect its behavior:
|
||||
|
||||
- @c --live : Use this option to perform a live release.
|
||||
When this option has been given, the release commands will affect
|
||||
the repository; otherwise, the script reports the actions to take,
|
||||
and it produces archives that are unsuitable for public release.
|
||||
|
||||
@note Only the Release Manager should use the @c --live option, as
|
||||
it will make permanent changes to the Subversion repository that
|
||||
cannot be undone.
|
||||
- The @c --start-rc indicates that the new development release cycle
|
||||
should start with @c -rc0. Without this, the @c -rc tag will be omitted,
|
||||
leading to non-monotonic versioning of the in-tree version numbers.
|
||||
- The @c --final indicates that the release should drop the @c -rc tag,
|
||||
to going from @c x.y.z-rcN-dev to x.y.z.
|
||||
|
||||
@subsection releasescriptenv Release Script Environment
|
||||
|
||||
@@ -327,66 +334,9 @@ affect its behavior:
|
||||
|
||||
@section releasetutorial Release Tutorials
|
||||
|
||||
This section provides tutorials for using the Release Script to perform
|
||||
common release tasks.
|
||||
|
||||
@subsection releasetutorialsetup Release Tutorial Setup
|
||||
|
||||
The tutorials in this section assume the following environment
|
||||
variables have been set properly:
|
||||
@verbatim
|
||||
SVN_USER="maintainer"
|
||||
SVN_URL="https://${SVN_USER}@svn.berlios.de/svnroot/repos/openocd"
|
||||
@endverbatim
|
||||
|
||||
@subsection releasetutorialminor Minor Release Tutorial
|
||||
|
||||
This section provides a step-by-step tutorial for a Release Manager to
|
||||
use to run the @c release.sh script to produce a minor release.
|
||||
|
||||
If the proper environment has been set, the following steps will produce
|
||||
a new minor release:
|
||||
|
||||
-# Check out (or update) the project trunk from the berliOS repository:
|
||||
@code
|
||||
svn checkout "${SVN_URL}/trunk" openocd-trunk
|
||||
@endcode
|
||||
-# Change to the new working copy directory:
|
||||
@code
|
||||
cd openocd-trunk
|
||||
@endcode
|
||||
-# Run @c release.sh to produce the minor release:
|
||||
@code
|
||||
tools/release.sh all
|
||||
@endcode
|
||||
|
||||
@subsection releasetutorialmicro Bug-Fix Release Tutorial
|
||||
|
||||
This section provides a step-by-step tutorial for a Release Manager to
|
||||
use to run the @c release.sh script to produce a bug-fix release.
|
||||
|
||||
In addition to the environment variables described in the introduction
|
||||
to these tutorials, the following variables are also used in the
|
||||
instructions for this section:
|
||||
@verbatim
|
||||
PACKAGE_BRANCH_VERSION="x.y.z"
|
||||
PACKAGE_BRANCH="openocd-${PACKAGE_BRANCH_VERSION}"
|
||||
@endverbatim
|
||||
|
||||
If the proper environment has been set, the following steps will produce
|
||||
a new bug-fix release:
|
||||
|
||||
-# Check out (or update) the release branch from the project repository:
|
||||
@code
|
||||
svn checkout "${SVN_URL}/branches/${PACKAGE_BRANCH}" "${PACKAGE_BRANCH}"
|
||||
@endcode
|
||||
@code
|
||||
cd "${PACKAGE_BRANCH}"
|
||||
@endcode
|
||||
-# Run @c release.sh to produce the bug-fix release:
|
||||
@code
|
||||
tools/release.sh all
|
||||
@endcode
|
||||
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.
|
||||
|
||||
@section releasetodo Release Script Shortcomings
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@ language, the choice of language is not terribly important
|
||||
to those same end users.
|
||||
|
||||
Jim Tcl was chosen as it was easy to integrate, works
|
||||
great in an embedded environment and Øyvind Harboe
|
||||
great in an embedded environment and Øyvind Harboe
|
||||
had experience with it.
|
||||
|
||||
@section scriptinguses Uses of scripting
|
||||
|
||||
@@ -111,7 +111,7 @@ Long before OpenOCD had a TCL command line, Zylin AS built their ZY1000
|
||||
devince with a built-in HTTP server. Later, they were willing to both
|
||||
contribute and integrate most of that work into the main tree.
|
||||
|
||||
@subsection serverdocsother Other Options Concidered
|
||||
@subsection serverdocsother Other Options Considered
|
||||
|
||||
What if a web browser is not acceptable ie: You want to write your own
|
||||
front gadget in Eclipse, or KDevelop, or PerlTK, Ruby, or what ever
|
||||
@@ -311,6 +311,15 @@ This section needs to be expanded.
|
||||
|
||||
/** @page serverhttp OpenOCD HTTP Server API
|
||||
|
||||
This section needs to be expanded.
|
||||
|
||||
Smoketest:
|
||||
|
||||
configure --enable-httpd --enable-dummy --enable-ioutil
|
||||
|
||||
openocd -s /usr/local/share/openocd -f httpd/httpd.tcl -f interface/dummy.cfg -f target/lpc2148.cfg
|
||||
|
||||
Navigate to: http://localhost:8888/
|
||||
|
||||
|
||||
|
||||
*/
|
||||
|
||||
@@ -49,7 +49,7 @@ OpenOCD project.
|
||||
- limit adjacent empty lines to at most two (2).
|
||||
- remove any trailing empty lines at the end of source files
|
||||
- do not "comment out" code from the tree; instead, one should either:
|
||||
-# remove it entirely (Subversion can retrieve the old version), or
|
||||
-# remove it entirely (git can retrieve the old version), or
|
||||
-# use an @c \#if/\#endif block.
|
||||
|
||||
Finally, try to avoid lines of code that are longer than than 72-80 columns:
|
||||
@@ -358,10 +358,8 @@ perl script.pl
|
||||
|
||||
Maintainers must also be sure to follow additional guidelines:
|
||||
-# Ensure that Perl scripts are committed as executables:
|
||||
- Use "<code>chmod +x script.pl</code>"
|
||||
@a before using "<code>svn add script.pl</code>", or
|
||||
- Use "<code>svn ps svn:executable '*' script.pl</code>"
|
||||
@a after using "<code>svn add script.pl</code>".
|
||||
Use "<code>chmod +x script.pl</code>"
|
||||
@a before using "<code>git add script.pl</code>"
|
||||
|
||||
*/
|
||||
/** @page styleautotools Autotools Style Guide
|
||||
|
||||
1412
doc/openocd.texi
1412
doc/openocd.texi
File diff suppressed because it is too large
Load Diff
@@ -1,7 +1,7 @@
|
||||
#####ECOSGPLCOPYRIGHTBEGIN####
|
||||
## -------------------------------------------
|
||||
## This file is part of eCos, the Embedded Configurable Operating System.
|
||||
## Copyright (C) 2008 Øyvind Harboe
|
||||
## Copyright (C) 2008 Øyvind Harboe
|
||||
##
|
||||
## eCos 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
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
#####ECOSGPLCOPYRIGHTBEGIN####
|
||||
## -------------------------------------------
|
||||
## This file is part of eCos, the Embedded Configurable Operating System.
|
||||
## Copyright (C) 2008 Øyvind Harboe
|
||||
## Copyright (C) 2008 Øyvind Harboe
|
||||
##
|
||||
## eCos 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
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
#####ECOSGPLCOPYRIGHTBEGIN####
|
||||
## -------------------------------------------
|
||||
## This file is part of eCos, the Embedded Configurable Operating System.
|
||||
## Copyright (C) 2008 Øyvind Harboe
|
||||
## Copyright (C) 2008 Øyvind Harboe
|
||||
##
|
||||
## eCos 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
|
||||
|
||||
83
guess-rev.sh
83
guess-rev.sh
@@ -1,8 +1,83 @@
|
||||
#!/bin/bash
|
||||
#!/bin/sh
|
||||
#
|
||||
# This scripts adds local version information from the version
|
||||
# control systems git, mercurial (hg) and subversion (svn).
|
||||
#
|
||||
# Copied from Linux 2.6.32 scripts/setlocalversion and modified
|
||||
# slightly to work better for OpenOCD.
|
||||
#
|
||||
|
||||
REV=unknown
|
||||
usage() {
|
||||
echo "Usage: $0 [srctree]" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
which svnversion > /dev/null 2>&1 && REV=`svnversion -n "$1"`
|
||||
cd "${1:-.}" || usage
|
||||
|
||||
echo -n $REV
|
||||
# Check for git and a git repo.
|
||||
if head=`git rev-parse --verify --short HEAD 2>/dev/null`; then
|
||||
|
||||
# If we are at a tagged commit (like "v2.6.30-rc6"), we ignore it,
|
||||
# because this version is defined in the top level Makefile.
|
||||
if [ -z "`git describe --exact-match 2>/dev/null`" ]; then
|
||||
|
||||
# If we are past a tagged commit (like "v2.6.30-rc5-302-g72357d5"),
|
||||
# we pretty print it.
|
||||
if atag="`git describe 2>/dev/null`"; then
|
||||
echo "$atag" | awk -F- '{printf("-%05d-%s", $(NF-1),$(NF))}'
|
||||
|
||||
# If we don't have a tag at all we print -g{commitish}.
|
||||
else
|
||||
printf '%s%s' -g $head
|
||||
fi
|
||||
fi
|
||||
|
||||
# Is this git on svn?
|
||||
if git config --get svn-remote.svn.url >/dev/null; then
|
||||
printf -- '-svn%s' "`git svn find-rev $head`"
|
||||
fi
|
||||
|
||||
# Update index only on r/w media
|
||||
[ -w . ] && git update-index --refresh --unmerged > /dev/null
|
||||
|
||||
# Check for uncommitted changes
|
||||
if git diff-index --name-only HEAD | grep -v "^scripts/package" \
|
||||
| read dummy; then
|
||||
printf '%s' -dirty
|
||||
fi
|
||||
|
||||
# All done with git
|
||||
exit
|
||||
fi
|
||||
|
||||
# Check for mercurial and a mercurial repo.
|
||||
if hgid=`hg id 2>/dev/null`; then
|
||||
tag=`printf '%s' "$hgid" | cut -d' ' -f2`
|
||||
|
||||
# Do we have an untagged version?
|
||||
if [ -z "$tag" -o "$tag" = tip ]; then
|
||||
id=`printf '%s' "$hgid" | sed 's/[+ ].*//'`
|
||||
printf '%s%s' -hg "$id"
|
||||
fi
|
||||
|
||||
# Are there uncommitted changes?
|
||||
# These are represented by + after the changeset id.
|
||||
case "$hgid" in
|
||||
*+|*+\ *) printf '%s' -dirty ;;
|
||||
esac
|
||||
|
||||
# All done with mercurial
|
||||
exit
|
||||
fi
|
||||
|
||||
# Check for svn and a svn repo.
|
||||
if rev=`svn info 2>/dev/null | grep '^Last Changed Rev'`; then
|
||||
rev=`echo $rev | awk '{print $NF}'`
|
||||
printf -- '-svn%s' "$rev"
|
||||
|
||||
# All done with svn
|
||||
exit
|
||||
fi
|
||||
|
||||
# There's no reecognized repository; we must be a snapshot.
|
||||
printf -- '-snapshot'
|
||||
|
||||
@@ -28,10 +28,12 @@ AM_CPPFLAGS = \
|
||||
|
||||
libopenocd_la_CPPFLAGS = -DPKGBLDDATE=\"`date +%F-%R`\"
|
||||
|
||||
# banner output includes RELSTR appended to $VERSION from the configure script
|
||||
# guess-rev.sh returns either a repository version ID or "-snapshot"
|
||||
if RELEASE
|
||||
libopenocd_la_CPPFLAGS += -DRELSTR=\"Release\" -DPKGBLDREV=\"\"
|
||||
libopenocd_la_CPPFLAGS += -DRELSTR=\"\"
|
||||
else
|
||||
libopenocd_la_CPPFLAGS += -DRELSTR=\"svn:\" -DPKGBLDREV=\"`$(top_srcdir)/guess-rev.sh $(top_srcdir)`\"
|
||||
libopenocd_la_CPPFLAGS += -DRELSTR=\"`$(top_srcdir)/guess-rev.sh $(top_srcdir)`\"
|
||||
endif
|
||||
|
||||
# add default CPPFLAGS
|
||||
@@ -41,7 +43,7 @@ libopenocd_la_CPPFLAGS += $(AM_CPPFLAGS) $(CPPFLAGS)
|
||||
libopenocd_la_LDFLAGS = $(all_libraries)
|
||||
|
||||
if IS_MINGW
|
||||
MINGWLDADD = -lwsock32
|
||||
MINGWLDADD = -lws2_32
|
||||
else
|
||||
MINGWLDADD =
|
||||
endif
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2007-2008 by <EFBFBD>yvind Harboe *
|
||||
* Copyright (C) 2007-2008 by Øyvind Harboe *
|
||||
* *
|
||||
* 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 *
|
||||
@@ -155,8 +155,8 @@ static char reboot_stack[2048];
|
||||
static void zylinjtag_reboot(cyg_addrword_t data)
|
||||
{
|
||||
serialLog = true;
|
||||
diag_printf("Rebooting in 100 ticks..\n");
|
||||
cyg_thread_delay(100);
|
||||
diag_printf("Rebooting in 500 ticks..\n");
|
||||
cyg_thread_delay(500);
|
||||
diag_printf("Unmounting /config..\n");
|
||||
umount("/config");
|
||||
diag_printf("Rebooting..\n");
|
||||
@@ -328,6 +328,7 @@ void openocd_sleep_postlude(void)
|
||||
|
||||
void format(void)
|
||||
{
|
||||
#ifdef CYGDAT_IO_FLASH_BLOCK_DEVICE_NAME_1
|
||||
diag_printf("Formatting JFFS2...\n");
|
||||
|
||||
cyg_io_handle_t handle;
|
||||
@@ -365,6 +366,7 @@ void format(void)
|
||||
}
|
||||
|
||||
diag_printf("Flash formatted successfully\n");
|
||||
#endif
|
||||
|
||||
reboot();
|
||||
}
|
||||
@@ -503,7 +505,7 @@ static void zylinjtag_startNetwork(void)
|
||||
|
||||
Jim_CreateCommand(httpstate.jim_interp, "log", zylinjtag_Jim_Command_log,
|
||||
NULL, NULL);
|
||||
Jim_CreateCommand(httpstate.jim_interp, "reboot",
|
||||
Jim_CreateCommand(httpstate.jim_interp, "zy1000_reboot",
|
||||
zylinjtag_Jim_Command_reboot, NULL, NULL);
|
||||
Jim_CreateCommand(httpstate.jim_interp, "threads",
|
||||
zylinjtag_Jim_Command_threads, NULL, NULL);
|
||||
@@ -623,6 +625,9 @@ void setNoDelay(int session, int flag)
|
||||
#endif
|
||||
}
|
||||
|
||||
#define TEST_TCPIP() 0
|
||||
|
||||
#if TEST_TCPIP
|
||||
struct
|
||||
{
|
||||
int req;
|
||||
@@ -631,6 +636,7 @@ struct
|
||||
int actual2;
|
||||
} tcpipSent[512 * 1024];
|
||||
int cur;
|
||||
#endif
|
||||
|
||||
static void zylinjtag_uart(cyg_addrword_t data)
|
||||
{
|
||||
@@ -695,7 +701,9 @@ static void zylinjtag_uart(cyg_addrword_t data)
|
||||
size_t pos, pos2;
|
||||
pos = 0;
|
||||
pos2 = 0;
|
||||
#if TEST_TCPIP
|
||||
cur = 0;
|
||||
#endif
|
||||
for (;;)
|
||||
{
|
||||
fd_set write_fds;
|
||||
@@ -796,6 +804,7 @@ static void zylinjtag_uart(cyg_addrword_t data)
|
||||
}
|
||||
y2 = written;
|
||||
}
|
||||
#if TEST_TCPIP
|
||||
if (cur < 1024)
|
||||
{
|
||||
tcpipSent[cur].req = x;
|
||||
@@ -804,11 +813,12 @@ static void zylinjtag_uart(cyg_addrword_t data)
|
||||
tcpipSent[cur].actual2 = y2;
|
||||
cur++;
|
||||
}
|
||||
|
||||
#endif
|
||||
}
|
||||
closeSession: close(session);
|
||||
close(serHandle);
|
||||
|
||||
#if TEST_TCPIP
|
||||
int i;
|
||||
for (i = 0; i < 1024; i++)
|
||||
{
|
||||
@@ -816,6 +826,7 @@ static void zylinjtag_uart(cyg_addrword_t data)
|
||||
tcpipSent[i].req2, tcpipSent[i].actual2);
|
||||
|
||||
}
|
||||
#endif
|
||||
}
|
||||
close(fd);
|
||||
|
||||
@@ -918,7 +929,7 @@ command_context_t *setup_command_handler(void);
|
||||
|
||||
static const char *zylin_config_dir="/config/settings";
|
||||
|
||||
int add_default_dirs(void)
|
||||
static int add_default_dirs(void)
|
||||
{
|
||||
add_script_search_dir(zylin_config_dir);
|
||||
add_script_search_dir("/rom/lib/openocd");
|
||||
|
||||
@@ -6,8 +6,11 @@ AM_CPPFLAGS = \
|
||||
METASOURCES = AUTO
|
||||
noinst_LTLIBRARIES = libflash.la
|
||||
libflash_la_SOURCES = \
|
||||
arm_nandio.c \
|
||||
flash.c \
|
||||
lpc2000.c \
|
||||
lpc288x.c \
|
||||
lpc2900.c \
|
||||
cfi.c \
|
||||
non_cfi.c \
|
||||
at91sam7.c \
|
||||
@@ -31,15 +34,19 @@ libflash_la_SOURCES = \
|
||||
s3c2412_nand.c \
|
||||
s3c2440_nand.c \
|
||||
s3c2443_nand.c \
|
||||
lpc288x.c \
|
||||
ocl.c \
|
||||
mflash.c \
|
||||
pic32mx.c \
|
||||
avrf.c
|
||||
avrf.c \
|
||||
faux.c \
|
||||
mx3_nand.c
|
||||
|
||||
noinst_HEADERS = \
|
||||
arm_nandio.h \
|
||||
flash.h \
|
||||
lpc2000.h \
|
||||
lpc288x.h \
|
||||
lpc2900.h \
|
||||
cfi.h \
|
||||
non_cfi.h \
|
||||
at91sam7.h \
|
||||
@@ -54,10 +61,10 @@ noinst_HEADERS = \
|
||||
tms470.h \
|
||||
s3c24xx_nand.h \
|
||||
s3c24xx_regs_nand.h \
|
||||
lpc288x.h \
|
||||
mflash.h \
|
||||
ocl.h \
|
||||
pic32mx.h \
|
||||
avrf.h
|
||||
avrf.h \
|
||||
mx3_nand.h
|
||||
|
||||
MAINTAINERCLEANFILES = $(srcdir)/Makefile.in
|
||||
|
||||
134
src/flash/arm_nandio.c
Normal file
134
src/flash/arm_nandio.c
Normal file
@@ -0,0 +1,134 @@
|
||||
/*
|
||||
* Copyright (C) 2009 by Marvell Semiconductors, Inc.
|
||||
* Written by Nicolas Pitre <nico at marvell.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
|
||||
* (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 "arm_nandio.h"
|
||||
#include "armv4_5.h"
|
||||
|
||||
|
||||
/*
|
||||
* ARM-specific bulk write from buffer to address of 8-bit wide NAND.
|
||||
* For now this only supports ARMv4 and ARMv5 cores.
|
||||
*
|
||||
* Enhancements to target_run_algorithm() could enable:
|
||||
* - ARMv6 and ARMv7 cores in ARM mode
|
||||
*
|
||||
* Different code fragments could handle:
|
||||
* - Thumb2 cores like Cortex-M (needs different byteswapping)
|
||||
* - 16-bit wide data (needs different setup too)
|
||||
*/
|
||||
int arm_nandwrite(struct arm_nand_data *nand, uint8_t *data, int size)
|
||||
{
|
||||
target_t *target = nand->target;
|
||||
armv4_5_algorithm_t algo;
|
||||
armv4_5_common_t *armv4_5 = target->arch_info;
|
||||
reg_param_t reg_params[3];
|
||||
uint32_t target_buf;
|
||||
uint32_t exit = 0;
|
||||
int retval;
|
||||
|
||||
/* Inputs:
|
||||
* r0 NAND data address (byte wide)
|
||||
* r1 buffer address
|
||||
* r2 buffer length
|
||||
*/
|
||||
static const uint32_t code[] = {
|
||||
0xe4d13001, /* s: ldrb r3, [r1], #1 */
|
||||
0xe5c03000, /* strb r3, [r0] */
|
||||
0xe2522001, /* subs r2, r2, #1 */
|
||||
0x1afffffb, /* bne s */
|
||||
|
||||
/* exit: ARMv4 needs hardware breakpoint */
|
||||
0xe1200070, /* e: bkpt #0 */
|
||||
};
|
||||
|
||||
if (!nand->copy_area) {
|
||||
uint8_t code_buf[sizeof(code)];
|
||||
unsigned i;
|
||||
|
||||
/* make sure we have a working area */
|
||||
if (target_alloc_working_area(target,
|
||||
sizeof(code) + nand->chunk_size,
|
||||
&nand->copy_area) != ERROR_OK) {
|
||||
LOG_DEBUG("%s: no %d byte buffer",
|
||||
__FUNCTION__,
|
||||
(int) sizeof(code) + nand->chunk_size);
|
||||
return ERROR_NAND_NO_BUFFER;
|
||||
}
|
||||
|
||||
/* buffer code in target endianness */
|
||||
for (i = 0; i < sizeof(code) / 4; i++)
|
||||
target_buffer_set_u32(target, code_buf + i * 4, code[i]);
|
||||
|
||||
/* copy code to work area */
|
||||
retval = target_write_memory(target,
|
||||
nand->copy_area->address,
|
||||
4, sizeof(code) / 4, code_buf);
|
||||
if (retval != ERROR_OK)
|
||||
return retval;
|
||||
}
|
||||
|
||||
/* copy data to work area */
|
||||
target_buf = nand->copy_area->address + sizeof(code);
|
||||
retval = target_bulk_write_memory(target, target_buf, size / 4, data);
|
||||
if (retval == ERROR_OK && (size & 3) != 0)
|
||||
retval = target_write_memory(target,
|
||||
target_buf + (size & ~3),
|
||||
1, size & 3, data + (size & ~3));
|
||||
if (retval != ERROR_OK)
|
||||
return retval;
|
||||
|
||||
/* set up algorithm and parameters */
|
||||
algo.common_magic = ARMV4_5_COMMON_MAGIC;
|
||||
algo.core_mode = ARMV4_5_MODE_SVC;
|
||||
algo.core_state = ARMV4_5_STATE_ARM;
|
||||
|
||||
init_reg_param(®_params[0], "r0", 32, PARAM_IN);
|
||||
init_reg_param(®_params[1], "r1", 32, PARAM_IN);
|
||||
init_reg_param(®_params[2], "r2", 32, PARAM_IN);
|
||||
|
||||
buf_set_u32(reg_params[0].value, 0, 32, nand->data);
|
||||
buf_set_u32(reg_params[1].value, 0, 32, target_buf);
|
||||
buf_set_u32(reg_params[2].value, 0, 32, size);
|
||||
|
||||
/* armv4 must exit using a hardware breakpoint */
|
||||
if (armv4_5->is_armv4)
|
||||
exit = nand->copy_area->address + sizeof(code) - 4;
|
||||
|
||||
/* use alg to write data from work area to NAND chip */
|
||||
retval = target_run_algorithm(target, 0, NULL, 3, reg_params,
|
||||
nand->copy_area->address, exit, 1000, &algo);
|
||||
if (retval != ERROR_OK)
|
||||
LOG_ERROR("error executing hosted NAND write");
|
||||
|
||||
destroy_reg_param(®_params[0]);
|
||||
destroy_reg_param(®_params[1]);
|
||||
destroy_reg_param(®_params[2]);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
/* REVISIT do the same for bulk *read* too ... */
|
||||
|
||||
25
src/flash/arm_nandio.h
Normal file
25
src/flash/arm_nandio.h
Normal file
@@ -0,0 +1,25 @@
|
||||
#ifndef __ARM_NANDIO_H
|
||||
#define __ARM_NANDIO_H
|
||||
|
||||
#include "nand.h"
|
||||
#include "binarybuffer.h"
|
||||
|
||||
struct arm_nand_data {
|
||||
/* target is proxy for some ARM core */
|
||||
struct target_s *target;
|
||||
|
||||
/* copy_area holds write-to-NAND loop and data to write */
|
||||
struct working_area_s *copy_area;
|
||||
|
||||
/* chunk_size == page or ECC unit */
|
||||
unsigned chunk_size;
|
||||
|
||||
/* data == where to write the data */
|
||||
uint32_t data;
|
||||
|
||||
/* currently implicit: data width == 8 bits (not 16) */
|
||||
};
|
||||
|
||||
int arm_nandwrite(struct arm_nand_data *nand, uint8_t *data, int size);
|
||||
|
||||
#endif /* __ARM_NANDIO_H */
|
||||
@@ -1609,7 +1609,7 @@ static int
|
||||
sam3_protect_check(struct flash_bank_s *bank)
|
||||
{
|
||||
int r;
|
||||
uint32_t v;
|
||||
uint32_t v=0;
|
||||
unsigned x;
|
||||
struct sam3_bank_private *pPrivate;
|
||||
|
||||
|
||||
@@ -20,20 +20,30 @@
|
||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||
****************************************************************************/
|
||||
|
||||
/***************************************************************************************************************************************************************************************
|
||||
/***************************************************************************
|
||||
*
|
||||
* New flash setup command:
|
||||
*
|
||||
* flash bank <driver> <base_addr> <size> <chip_width> <bus_width> <target_number> [<target_name> <banks> <sectors_per_bank> <pages_per_sector> <page_size> <num_nvmbits> <ext_freq_khz>]
|
||||
* flash bank <driver> <base_addr> <size> <chip_width> <bus_width> <target_id>
|
||||
* [<chip_type> <banks>
|
||||
* <sectors_per_bank> <pages_per_sector>
|
||||
* <page_size> <num_nvmbits>
|
||||
* <ext_freq_khz>]
|
||||
*
|
||||
* <ext_freq_khz> - MUST be used if clock is from external source,
|
||||
* CAN be used if main oscillator frequency is known (recomended)
|
||||
* CAN be used if main oscillator frequency is known (recommended)
|
||||
* Examples:
|
||||
* flash bank at91sam7 0x00100000 0 0 4 0 0 AT91SAM7XC256 1 16 64 256 3 25000 ==== RECOMENDED ============
|
||||
* flash bank at91sam7 0 0 0 0 0 0 0 0 0 0 0 0 25000 (auto-detection, except for clock) ==== RECOMENDED ============
|
||||
* flash bank at91sam7 0x00100000 0 0 4 0 0 AT91SAM7XC256 1 16 64 256 3 0 ==== NOT RECOMENDED !!! ====
|
||||
* flash bank at91sam7 0 0 0 0 0 (old style, full auto-detection) ==== NOT RECOMENDED !!! ====
|
||||
****************************************************************************************************************************************************************************************/
|
||||
* ==== RECOMMENDED (covers clock speed) ============
|
||||
* flash bank at91sam7 0x00100000 0 0 4 $_TARGETNAME AT91SAM7XC256 1 16 64 256 3 25000
|
||||
* (if auto-detect fails; provides clock spec)
|
||||
* flash bank at91sam7 0 0 0 0 $_TARGETNAME 0 0 0 0 0 0 25000
|
||||
* (auto-detect everything except the clock)
|
||||
* ==== NOT RECOMMENDED !!! (clock speed is not configured) ====
|
||||
* flash bank at91sam7 0x00100000 0 0 4 $_TARGETNAME AT91SAM7XC256 1 16 64 256 3 0
|
||||
* (if auto-detect fails)
|
||||
* flash bank at91sam7 0 0 0 0 $_TARGETNAME
|
||||
* (old style, auto-detect everything)
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
@@ -734,16 +744,6 @@ static int at91sam7_protect_check(struct flash_bank_s *bank)
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
/***************************************************************************************************************************************************************************************
|
||||
# flash bank <driver> <base_addr> <size> <chip_width> <bus_width> <target_number> [<target_name> <banks> <sectors_per_bank> <pages_per_sector> <page_size> <num_nvmbits> <ext_freq_khz>]
|
||||
# <ext_freq_khz> - MUST be used if clock is from external source
|
||||
# CAN be used if main oscillator frequency is known
|
||||
# Examples:
|
||||
# flash bank at91sam7 0x00100000 0 0 4 0 0 AT91SAM7XC256 1 16 64 256 3 25000 ==== RECOMENDED ============
|
||||
# flash bank at91sam7 0 0 0 0 0 0 0 0 0 0 0 0 25000 (auto-detection, except for clock) ==== RECOMENDED ============
|
||||
# flash bank at91sam7 0x00100000 0 0 4 0 0 AT91SAM7XC256 1 16 64 256 3 0 ==== NOT RECOMENDED !!! ====
|
||||
# flash bank at91sam7 0 0 0 0 0 (old style, full auto-detection) ==== NOT RECOMENDED !!! ====
|
||||
****************************************************************************************************************************************************************************************/
|
||||
static int at91sam7_flash_bank_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct flash_bank_s *bank)
|
||||
{
|
||||
flash_bank_t *t_bank = bank;
|
||||
|
||||
187
src/flash/cfi.c
187
src/flash/cfi.c
@@ -74,7 +74,7 @@ static void cfi_fixup_0002_unlock_addresses(flash_bank_t *flash, void *param);
|
||||
static void cfi_fixup_atmel_reversed_erase_regions(flash_bank_t *flash, void *param);
|
||||
|
||||
/* fixup after reading cmdset 0002 primary query table */
|
||||
static cfi_fixup_t cfi_0002_fixups[] = {
|
||||
static const cfi_fixup_t cfi_0002_fixups[] = {
|
||||
{CFI_MFR_SST, 0x00D4, cfi_fixup_0002_unlock_addresses, &cfi_unlock_addresses[CFI_UNLOCK_5555_2AAA]},
|
||||
{CFI_MFR_SST, 0x00D5, cfi_fixup_0002_unlock_addresses, &cfi_unlock_addresses[CFI_UNLOCK_5555_2AAA]},
|
||||
{CFI_MFR_SST, 0x00D6, cfi_fixup_0002_unlock_addresses, &cfi_unlock_addresses[CFI_UNLOCK_5555_2AAA]},
|
||||
@@ -90,14 +90,14 @@ static cfi_fixup_t cfi_0002_fixups[] = {
|
||||
};
|
||||
|
||||
/* fixup after reading cmdset 0001 primary query table */
|
||||
static cfi_fixup_t cfi_0001_fixups[] = {
|
||||
static const cfi_fixup_t cfi_0001_fixups[] = {
|
||||
{0, 0, NULL, NULL}
|
||||
};
|
||||
|
||||
static void cfi_fixup(flash_bank_t *bank, cfi_fixup_t *fixups)
|
||||
static void cfi_fixup(flash_bank_t *bank, const cfi_fixup_t *fixups)
|
||||
{
|
||||
cfi_flash_bank_t *cfi_info = bank->driver_priv;
|
||||
cfi_fixup_t *f;
|
||||
const cfi_fixup_t *f;
|
||||
|
||||
for (f = fixups; f->fixup; f++)
|
||||
{
|
||||
@@ -1125,11 +1125,11 @@ static int cfi_intel_write_block(struct flash_bank_s *bank, uint8_t *buffer, uin
|
||||
armv4_5_info.core_state = ARMV4_5_STATE_ARM;
|
||||
|
||||
/* If we are setting up the write_algorith, we need target_code_src */
|
||||
/* if not we only need target_code_size. */
|
||||
/* */
|
||||
/* However, we don't want to create multiple code paths, so we */
|
||||
/* do the unecessary evaluation of target_code_src, which the */
|
||||
/* compiler will probably nicely optimize away if not needed */
|
||||
/* if not we only need target_code_size. */
|
||||
|
||||
/* However, we don't want to create multiple code paths, so we */
|
||||
/* do the unecessary evaluation of target_code_src, which the */
|
||||
/* compiler will probably nicely optimize away if not needed */
|
||||
|
||||
/* prepare algorithm code for target endian */
|
||||
switch (bank->bus_width)
|
||||
@@ -1384,6 +1384,31 @@ static int cfi_spansion_write_block(struct flash_bank_s *bank, uint8_t *buffer,
|
||||
0xeafffffe /* b 81ac <sp_16_done> */
|
||||
};
|
||||
|
||||
static const uint32_t word_16_code_dq7only[] = {
|
||||
/* <sp_16_code>: */
|
||||
0xe0d050b2, /* ldrh r5, [r0], #2 */
|
||||
0xe1c890b0, /* strh r9, [r8] */
|
||||
0xe1cab0b0, /* strh r11, [r10] */
|
||||
0xe1c830b0, /* strh r3, [r8] */
|
||||
0xe1c150b0, /* strh r5, [r1] */
|
||||
0xe1a00000, /* nop (mov r0,r0) */
|
||||
/* */
|
||||
/* <sp_16_busy>: */
|
||||
0xe1d160b0, /* ldrh r6, [r1] */
|
||||
0xe0257006, /* eor r7, r5, r6 */
|
||||
0xe2177080, /* ands r7, #0x80 */
|
||||
0x1afffffb, /* bne 8168 <sp_16_busy> */
|
||||
/* */
|
||||
0xe2522001, /* subs r2, r2, #1 ; 0x1 */
|
||||
0x03a05080, /* moveq r5, #128 ; 0x80 */
|
||||
0x0a000001, /* beq 81ac <sp_16_done> */
|
||||
0xe2811002, /* add r1, r1, #2 ; 0x2 */
|
||||
0xeafffff0, /* b 8158 <sp_16_code> */
|
||||
/* */
|
||||
/* 000081ac <sp_16_done>: */
|
||||
0xeafffffe /* b 81ac <sp_16_done> */
|
||||
};
|
||||
|
||||
static const uint32_t word_8_code[] = {
|
||||
/* 000081b0 <sp_16_code_end>: */
|
||||
0xe4d05001, /* ldrb r5, [r0], #1 */
|
||||
@@ -1422,34 +1447,46 @@ static int cfi_spansion_write_block(struct flash_bank_s *bank, uint8_t *buffer,
|
||||
armv4_5_info.core_mode = ARMV4_5_MODE_SVC;
|
||||
armv4_5_info.core_state = ARMV4_5_STATE_ARM;
|
||||
|
||||
int target_code_size;
|
||||
const uint32_t *target_code_src;
|
||||
|
||||
switch (bank->bus_width)
|
||||
{
|
||||
case 1 :
|
||||
target_code_src = word_8_code;
|
||||
target_code_size = sizeof(word_8_code);
|
||||
break;
|
||||
case 2 :
|
||||
/* Check for DQ5 support */
|
||||
if( cfi_info->status_poll_mask & (1 << 5) )
|
||||
{
|
||||
target_code_src = word_16_code;
|
||||
target_code_size = sizeof(word_16_code);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* No DQ5 support. Use DQ7 DATA# polling only. */
|
||||
target_code_src = word_16_code_dq7only;
|
||||
target_code_size = sizeof(word_16_code_dq7only);
|
||||
}
|
||||
break;
|
||||
case 4 :
|
||||
target_code_src = word_32_code;
|
||||
target_code_size = sizeof(word_32_code);
|
||||
break;
|
||||
default:
|
||||
LOG_ERROR("Unsupported bank buswidth %d, can't do block memory writes", bank->bus_width);
|
||||
return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
|
||||
}
|
||||
|
||||
/* flash write code */
|
||||
if (!cfi_info->write_algorithm)
|
||||
{
|
||||
uint8_t *target_code;
|
||||
int target_code_size;
|
||||
const uint32_t *src;
|
||||
|
||||
/* convert bus-width dependent algorithm code to correct endiannes */
|
||||
switch (bank->bus_width)
|
||||
{
|
||||
case 1:
|
||||
src = word_8_code;
|
||||
target_code_size = sizeof(word_8_code);
|
||||
break;
|
||||
case 2:
|
||||
src = word_16_code;
|
||||
target_code_size = sizeof(word_16_code);
|
||||
break;
|
||||
case 4:
|
||||
src = word_32_code;
|
||||
target_code_size = sizeof(word_32_code);
|
||||
break;
|
||||
default:
|
||||
LOG_ERROR("Unsupported bank buswidth %d, can't do block memory writes", bank->bus_width);
|
||||
return ERROR_FLASH_OPERATION_FAILED;
|
||||
}
|
||||
target_code = malloc(target_code_size);
|
||||
cfi_fix_code_endian(target, target_code, src, target_code_size / 4);
|
||||
cfi_fix_code_endian(target, target_code, target_code_src, target_code_size / 4);
|
||||
|
||||
/* allocate working area */
|
||||
retval = target_alloc_working_area(target, target_code_size,
|
||||
@@ -1515,7 +1552,7 @@ static int cfi_spansion_write_block(struct flash_bank_s *bank, uint8_t *buffer,
|
||||
|
||||
retval = target_run_algorithm(target, 0, NULL, 10, reg_params,
|
||||
cfi_info->write_algorithm->address,
|
||||
cfi_info->write_algorithm->address + ((24 * 4) - 4),
|
||||
cfi_info->write_algorithm->address + ((target_code_size) - 4),
|
||||
10000, &armv4_5_info);
|
||||
|
||||
status = buf_get_u32(reg_params[5].value, 0, 32);
|
||||
@@ -1532,7 +1569,7 @@ static int cfi_spansion_write_block(struct flash_bank_s *bank, uint8_t *buffer,
|
||||
count -= thisrun_count;
|
||||
}
|
||||
|
||||
target_free_working_area(target, source);
|
||||
target_free_all_working_areas(target);
|
||||
|
||||
destroy_reg_param(®_params[0]);
|
||||
destroy_reg_param(®_params[1]);
|
||||
@@ -2106,6 +2143,45 @@ static void cfi_fixup_0002_unlock_addresses(flash_bank_t *bank, void *param)
|
||||
pri_ext->_unlock2 = unlock_addresses->unlock2;
|
||||
}
|
||||
|
||||
|
||||
static int cfi_query_string(struct flash_bank_s *bank, int address)
|
||||
{
|
||||
cfi_flash_bank_t *cfi_info = bank->driver_priv;
|
||||
target_t *target = bank->target;
|
||||
int retval;
|
||||
uint8_t command[8];
|
||||
|
||||
cfi_command(bank, 0x98, command);
|
||||
if ((retval = target_write_memory(target, flash_address(bank, 0, address), bank->bus_width, 1, command)) != ERROR_OK)
|
||||
{
|
||||
return retval;
|
||||
}
|
||||
|
||||
cfi_info->qry[0] = cfi_query_u8(bank, 0, 0x10);
|
||||
cfi_info->qry[1] = cfi_query_u8(bank, 0, 0x11);
|
||||
cfi_info->qry[2] = cfi_query_u8(bank, 0, 0x12);
|
||||
|
||||
LOG_DEBUG("CFI qry returned: 0x%2.2x 0x%2.2x 0x%2.2x", cfi_info->qry[0], cfi_info->qry[1], cfi_info->qry[2]);
|
||||
|
||||
if ((cfi_info->qry[0] != 'Q') || (cfi_info->qry[1] != 'R') || (cfi_info->qry[2] != 'Y'))
|
||||
{
|
||||
cfi_command(bank, 0xf0, command);
|
||||
if ((retval = target_write_memory(target, flash_address(bank, 0, 0x0), bank->bus_width, 1, command)) != ERROR_OK)
|
||||
{
|
||||
return retval;
|
||||
}
|
||||
cfi_command(bank, 0xff, command);
|
||||
if ((retval = target_write_memory(target, flash_address(bank, 0, 0x0), bank->bus_width, 1, command)) != ERROR_OK)
|
||||
{
|
||||
return retval;
|
||||
}
|
||||
LOG_ERROR("Could not probe bank: no QRY");
|
||||
return ERROR_FLASH_BANK_INVALID;
|
||||
}
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
static int cfi_probe(struct flash_bank_s *bank)
|
||||
{
|
||||
cfi_flash_bank_t *cfi_info = bank->driver_priv;
|
||||
@@ -2172,7 +2248,7 @@ static int cfi_probe(struct flash_bank_s *bank)
|
||||
{
|
||||
return retval;
|
||||
}
|
||||
if ((retval = target_read_u16(target, flash_address(bank, 0, 0x02), &cfi_info->device_id)) != ERROR_OK)
|
||||
if ((retval = target_read_u16(target, flash_address(bank, 0, 0x01), &cfi_info->device_id)) != ERROR_OK)
|
||||
{
|
||||
return retval;
|
||||
}
|
||||
@@ -2199,6 +2275,8 @@ static int cfi_probe(struct flash_bank_s *bank)
|
||||
*/
|
||||
if (cfi_info->not_cfi == 0)
|
||||
{
|
||||
int retval;
|
||||
|
||||
/* enter CFI query mode
|
||||
* according to JEDEC Standard No. 68.01,
|
||||
* a single bus sequence with address = 0x55, data = 0x98 should put
|
||||
@@ -2206,33 +2284,21 @@ static int cfi_probe(struct flash_bank_s *bank)
|
||||
*
|
||||
* SST flashes clearly violate this, and we will consider them incompatbile for now
|
||||
*/
|
||||
cfi_command(bank, 0x98, command);
|
||||
if ((retval = target_write_memory(target, flash_address(bank, 0, 0x55), bank->bus_width, 1, command)) != ERROR_OK)
|
||||
|
||||
retval = cfi_query_string(bank, 0x55);
|
||||
if (retval != ERROR_OK)
|
||||
{
|
||||
/*
|
||||
* Spansion S29WS-N CFI query fix is to try 0x555 if 0x55 fails. Should
|
||||
* be harmless enough:
|
||||
*
|
||||
* http://www.infradead.org/pipermail/linux-mtd/2005-September/013618.html
|
||||
*/
|
||||
LOG_USER("Try workaround w/0x555 instead of 0x55 to get QRY.");
|
||||
retval = cfi_query_string(bank, 0x555);
|
||||
}
|
||||
if (retval != ERROR_OK)
|
||||
return retval;
|
||||
}
|
||||
|
||||
cfi_info->qry[0] = cfi_query_u8(bank, 0, 0x10);
|
||||
cfi_info->qry[1] = cfi_query_u8(bank, 0, 0x11);
|
||||
cfi_info->qry[2] = cfi_query_u8(bank, 0, 0x12);
|
||||
|
||||
LOG_DEBUG("CFI qry returned: 0x%2.2x 0x%2.2x 0x%2.2x", cfi_info->qry[0], cfi_info->qry[1], cfi_info->qry[2]);
|
||||
|
||||
if ((cfi_info->qry[0] != 'Q') || (cfi_info->qry[1] != 'R') || (cfi_info->qry[2] != 'Y'))
|
||||
{
|
||||
cfi_command(bank, 0xf0, command);
|
||||
if ((retval = target_write_memory(target, flash_address(bank, 0, 0x0), bank->bus_width, 1, command)) != ERROR_OK)
|
||||
{
|
||||
return retval;
|
||||
}
|
||||
cfi_command(bank, 0xff, command);
|
||||
if ((retval = target_write_memory(target, flash_address(bank, 0, 0x0), bank->bus_width, 1, command)) != ERROR_OK)
|
||||
{
|
||||
return retval;
|
||||
}
|
||||
LOG_ERROR("Could not probe bank: no QRY");
|
||||
return ERROR_FLASH_BANK_INVALID;
|
||||
}
|
||||
|
||||
cfi_info->pri_id = cfi_query_u16(bank, 0, 0x13);
|
||||
cfi_info->pri_addr = cfi_query_u16(bank, 0, 0x15);
|
||||
@@ -2383,9 +2449,10 @@ static int cfi_probe(struct flash_bank_s *bank)
|
||||
sector++;
|
||||
}
|
||||
}
|
||||
if (offset != cfi_info->dev_size)
|
||||
if (offset != (cfi_info->dev_size * bank->bus_width / bank->chip_width))
|
||||
{
|
||||
LOG_WARNING("CFI size is 0x%" PRIx32 ", but total sector size is 0x%" PRIx32 "", cfi_info->dev_size, offset);
|
||||
LOG_WARNING("CFI size is 0x%" PRIx32 ", but total sector size is 0x%" PRIx32 "", \
|
||||
(cfi_info->dev_size * bank->bus_width / bank->chip_width), offset);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "nand.h"
|
||||
#include "arm_nandio.h"
|
||||
|
||||
|
||||
enum ecc {
|
||||
@@ -51,6 +51,9 @@ struct davinci_nand {
|
||||
uint32_t cmd; /* with CLE */
|
||||
uint32_t addr; /* with ALE */
|
||||
|
||||
/* write acceleration */
|
||||
struct arm_nand_data io;
|
||||
|
||||
/* page i/o for the relevant flavor of hardware ECC */
|
||||
int (*read_page)(struct nand_device_s *nand, uint32_t page,
|
||||
uint8_t *data, uint32_t data_size, uint8_t *oob, uint32_t oob_size);
|
||||
@@ -181,7 +184,7 @@ static int davinci_read_data(struct nand_device_s *nand, void *data)
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
/* REVISIT a bit of native code should let block I/O be MUCH faster */
|
||||
/* REVISIT a bit of native code should let block reads be MUCH faster */
|
||||
|
||||
static int davinci_read_block_data(struct nand_device_s *nand,
|
||||
uint8_t *data, int data_size)
|
||||
@@ -223,10 +226,17 @@ static int davinci_write_block_data(struct nand_device_s *nand,
|
||||
target_t *target = info->target;
|
||||
uint32_t nfdata = info->data;
|
||||
uint32_t tmp;
|
||||
int status;
|
||||
|
||||
if (!halted(target, "write_block"))
|
||||
return ERROR_NAND_OPERATION_FAILED;
|
||||
|
||||
/* try the fast way first */
|
||||
status = arm_nandwrite(&info->io, data, data_size);
|
||||
if (status != ERROR_NAND_NO_BUFFER)
|
||||
return status;
|
||||
|
||||
/* else do it slowly */
|
||||
while (data_size >= 4) {
|
||||
tmp = le_to_h_u32(data);
|
||||
target_write_u32(target, nfdata, tmp);
|
||||
@@ -285,6 +295,12 @@ static int davinci_write_page(struct nand_device_s *nand, uint32_t page,
|
||||
memset(oob, 0x0ff, oob_size);
|
||||
}
|
||||
|
||||
/* REVISIT avoid wasting SRAM: unless nand->use_raw is set,
|
||||
* use 512 byte chunks. Read side support will often want
|
||||
* to include oob_size ...
|
||||
*/
|
||||
info->io.chunk_size = nand->page_size;
|
||||
|
||||
status = info->write_page(nand, page, data, data_size, oob, oob_size);
|
||||
free(ooballoc);
|
||||
return status;
|
||||
@@ -365,7 +381,7 @@ static int davinci_write_page_ecc1(struct nand_device_s *nand, uint32_t page,
|
||||
struct davinci_nand *info = nand->controller_priv;
|
||||
target_t *target = info->target;
|
||||
const uint32_t fcr_addr = info->aemif + NANDFCR;
|
||||
const uint32_t ecc1_addr = info->aemif + NANDFECC + info->chipsel;
|
||||
const uint32_t ecc1_addr = info->aemif + NANDFECC + (4 * info->chipsel);
|
||||
uint32_t fcr, ecc1;
|
||||
|
||||
/* Write contiguous ECC bytes starting at specified offset.
|
||||
@@ -663,7 +679,7 @@ static int davinci_nand_device_command(struct command_context_s *cmd_ctx,
|
||||
}
|
||||
|
||||
aemif = strtoul(argv[4], &ep, 0);
|
||||
if (*ep || chip == 0 || chip == ULONG_MAX) {
|
||||
if (*ep || aemif == 0 || aemif == ULONG_MAX) {
|
||||
LOG_ERROR("Invalid AEMIF controller address %s", argv[4]);
|
||||
goto fail;
|
||||
}
|
||||
@@ -676,11 +692,11 @@ static int davinci_nand_device_command(struct command_context_s *cmd_ctx,
|
||||
|| aemif == 0x01e10000 /* dm335, dm355 */
|
||||
|| aemif == 0x01d10000 /* dm365 */
|
||||
) {
|
||||
if (chip < 0x0200000 || chip >= 0x0a000000) {
|
||||
if (chip < 0x02000000 || chip >= 0x0a000000) {
|
||||
LOG_ERROR("NAND address %08lx out of range?", chip);
|
||||
goto fail;
|
||||
}
|
||||
chipsel = (chip - 0x02000000) >> 21;
|
||||
chipsel = (chip - 0x02000000) >> 25;
|
||||
} else {
|
||||
LOG_ERROR("unrecognized AEMIF controller address %08lx", aemif);
|
||||
goto fail;
|
||||
@@ -700,6 +716,9 @@ static int davinci_nand_device_command(struct command_context_s *cmd_ctx,
|
||||
|
||||
nand->controller_priv = info;
|
||||
|
||||
info->io.target = target;
|
||||
info->io.data = info->data;
|
||||
|
||||
/* NOTE: for now we don't do any error correction on read.
|
||||
* Nothing else in OpenOCD currently corrects read errors,
|
||||
* and in any case it's *writing* that we care most about.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2007,2008 Øyvind Harboe *
|
||||
* Copyright (C) 2007,2008 Øyvind Harboe *
|
||||
* oyvind.harboe@zylin.com *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
@@ -148,7 +148,7 @@ static int ecosflash_flash_bank_command(struct command_context_s *cmd_ctx, char
|
||||
info->driverPath = strdup(args[6]);
|
||||
|
||||
/* eCos flash sector sizes are not exposed to OpenOCD, use 0x10000 as
|
||||
* a way to improve impeadance matach between OpenOCD and eCos flash
|
||||
* a way to improve impedance match between OpenOCD and eCos flash
|
||||
* driver.
|
||||
*/
|
||||
int i = 0;
|
||||
|
||||
153
src/flash/faux.c
Normal file
153
src/flash/faux.c
Normal file
@@ -0,0 +1,153 @@
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2009 Øyvind Harboe *
|
||||
* oyvind.harboe@zylin.com *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation; either version 2 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
* This program is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License *
|
||||
* along with this program; if not, write to the *
|
||||
* Free Software Foundation, Inc., *
|
||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||
***************************************************************************/
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "flash.h"
|
||||
#include "image.h"
|
||||
|
||||
|
||||
static int faux_register_commands(struct command_context_s *cmd_ctx);
|
||||
static int faux_flash_bank_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct flash_bank_s *bank);
|
||||
static int faux_erase(struct flash_bank_s *bank, int first, int last);
|
||||
static int faux_protect(struct flash_bank_s *bank, int set, int first, int last);
|
||||
static int faux_write(struct flash_bank_s *bank, uint8_t *buffer, uint32_t offset, uint32_t count);
|
||||
static int faux_probe(struct flash_bank_s *bank);
|
||||
static int faux_protect_check(struct flash_bank_s *bank);
|
||||
static int faux_info(struct flash_bank_s *bank, char *buf, int buf_size);
|
||||
|
||||
flash_driver_t faux_flash =
|
||||
{
|
||||
.name = "faux",
|
||||
.register_commands = faux_register_commands,
|
||||
.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
|
||||
};
|
||||
|
||||
typedef struct faux_flash_bank_s
|
||||
{
|
||||
struct target_s *target;
|
||||
uint8_t *memory;
|
||||
uint32_t start_address;
|
||||
} faux_flash_bank_t;
|
||||
|
||||
static const int sectorSize = 0x10000;
|
||||
|
||||
|
||||
/* flash bank faux <base> <size> <chip_width> <bus_width> <target#> <driverPath>
|
||||
*/
|
||||
static int faux_flash_bank_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct flash_bank_s *bank)
|
||||
{
|
||||
faux_flash_bank_t *info;
|
||||
|
||||
if (argc < 6)
|
||||
{
|
||||
LOG_WARNING("incomplete flash_bank faux configuration");
|
||||
return ERROR_FLASH_BANK_INVALID;
|
||||
}
|
||||
|
||||
info = malloc(sizeof(faux_flash_bank_t));
|
||||
if (info == NULL)
|
||||
{
|
||||
LOG_ERROR("no memory for flash bank info");
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
info->memory = malloc(bank->size);
|
||||
if (info == NULL)
|
||||
{
|
||||
free(info);
|
||||
LOG_ERROR("no memory for flash bank info");
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
bank->driver_priv = info;
|
||||
|
||||
/* Use 0x10000 as a fixed sector size. */
|
||||
int i = 0;
|
||||
uint32_t offset = 0;
|
||||
bank->num_sectors = bank->size/sectorSize;
|
||||
bank->sectors = malloc(sizeof(flash_sector_t) * bank->num_sectors);
|
||||
for (i = 0; i < bank->num_sectors; i++)
|
||||
{
|
||||
bank->sectors[i].offset = offset;
|
||||
bank->sectors[i].size = sectorSize;
|
||||
offset += bank->sectors[i].size;
|
||||
bank->sectors[i].is_erased = -1;
|
||||
bank->sectors[i].is_protected = 0;
|
||||
}
|
||||
|
||||
info->target = get_target(args[5]);
|
||||
if (info->target == NULL)
|
||||
{
|
||||
LOG_ERROR("target '%s' not defined", args[5]);
|
||||
free(info->memory);
|
||||
free(info);
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
static int faux_register_commands(struct command_context_s *cmd_ctx)
|
||||
{
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
static int faux_erase(struct flash_bank_s *bank, int first, int last)
|
||||
{
|
||||
faux_flash_bank_t *info = bank->driver_priv;
|
||||
memset(info->memory + first*sectorSize, 0xff, sectorSize*(last-first + 1));
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
static int faux_protect(struct flash_bank_s *bank, int set, int first, int last)
|
||||
{
|
||||
LOG_USER("set protection sector %d to %d to %s", first, last, set?"on":"off");
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
static int faux_write(struct flash_bank_s *bank, uint8_t *buffer, uint32_t offset, uint32_t count)
|
||||
{
|
||||
faux_flash_bank_t *info = bank->driver_priv;
|
||||
memcpy(info->memory + offset, buffer, count);
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
static int faux_protect_check(struct flash_bank_s *bank)
|
||||
{
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
static int faux_info(struct flash_bank_s *bank, char *buf, int buf_size)
|
||||
{
|
||||
snprintf(buf, buf_size, "faux flash driver");
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
static int faux_probe(struct flash_bank_s *bank)
|
||||
{
|
||||
return ERROR_OK;
|
||||
}
|
||||
@@ -2,7 +2,7 @@
|
||||
* Copyright (C) 2005 by Dominic Rath *
|
||||
* Dominic.Rath@gmx.de *
|
||||
* *
|
||||
* Copyright (C) 2007,2008 Øyvind Harboe *
|
||||
* Copyright (C) 2007,2008 Øyvind Harboe *
|
||||
* oyvind.harboe@zylin.com *
|
||||
* *
|
||||
* Copyright (C) 2008 by Spencer Oliver *
|
||||
@@ -43,10 +43,13 @@ static int handle_flash_write_bank_command(struct command_context_s *cmd_ctx, ch
|
||||
static int handle_flash_write_image_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
|
||||
static int handle_flash_fill_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
|
||||
static int handle_flash_protect_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
|
||||
static int flash_write_unlock(target_t *target, image_t *image, uint32_t *written, int erase, bool unlock);
|
||||
|
||||
/* flash drivers
|
||||
*/
|
||||
extern flash_driver_t lpc2000_flash;
|
||||
extern flash_driver_t lpc288x_flash;
|
||||
extern flash_driver_t lpc2900_flash;
|
||||
extern flash_driver_t cfi_flash;
|
||||
extern flash_driver_t at91sam3_flash;
|
||||
extern flash_driver_t at91sam7_flash;
|
||||
@@ -58,13 +61,15 @@ extern flash_driver_t str9xpec_flash;
|
||||
extern flash_driver_t stm32x_flash;
|
||||
extern flash_driver_t tms470_flash;
|
||||
extern flash_driver_t ecosflash_flash;
|
||||
extern flash_driver_t lpc288x_flash;
|
||||
extern flash_driver_t ocl_flash;
|
||||
extern flash_driver_t pic32mx_flash;
|
||||
extern flash_driver_t avr_flash;
|
||||
extern flash_driver_t faux_flash;
|
||||
|
||||
flash_driver_t *flash_drivers[] = {
|
||||
&lpc2000_flash,
|
||||
&lpc288x_flash,
|
||||
&lpc2900_flash,
|
||||
&cfi_flash,
|
||||
&at91sam7_flash,
|
||||
&at91sam3_flash,
|
||||
@@ -76,10 +81,10 @@ flash_driver_t *flash_drivers[] = {
|
||||
&stm32x_flash,
|
||||
&tms470_flash,
|
||||
&ecosflash_flash,
|
||||
&lpc288x_flash,
|
||||
&ocl_flash,
|
||||
&pic32mx_flash,
|
||||
&avr_flash,
|
||||
&faux_flash,
|
||||
NULL,
|
||||
};
|
||||
|
||||
@@ -197,7 +202,7 @@ int flash_init_drivers(struct command_context_s *cmd_ctx)
|
||||
register_command(cmd_ctx, flash_cmd, "write_bank", handle_flash_write_bank_command, COMMAND_EXEC,
|
||||
"write binary data to <bank> <file> <offset>");
|
||||
register_command(cmd_ctx, flash_cmd, "write_image", handle_flash_write_image_command, COMMAND_EXEC,
|
||||
"write_image [erase] <file> [offset] [type]");
|
||||
"write_image [erase] [unlock] <file> [offset] [type]");
|
||||
register_command(cmd_ctx, flash_cmd, "protect", handle_flash_protect_command, COMMAND_EXEC,
|
||||
"set protection of sectors at <bank> <first> <last> <on | off>");
|
||||
}
|
||||
@@ -557,82 +562,122 @@ static int handle_flash_protect_check_command(struct command_context_s *cmd_ctx,
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
static int handle_flash_erase_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
|
||||
static int flash_check_sector_parameters(struct command_context_s *cmd_ctx,
|
||||
uint32_t first, uint32_t last, uint32_t num_sectors)
|
||||
{
|
||||
if (argc > 2)
|
||||
{
|
||||
int first = strtoul(args[1], NULL, 0);
|
||||
int last = strtoul(args[2], NULL, 0);
|
||||
int retval;
|
||||
flash_bank_t *p = get_flash_bank_by_num(strtoul(args[0], NULL, 0));
|
||||
duration_t duration;
|
||||
char *duration_text;
|
||||
|
||||
duration_start_measure(&duration);
|
||||
|
||||
if (!p)
|
||||
{
|
||||
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||
}
|
||||
|
||||
if ((retval = flash_driver_erase(p, first, last)) == ERROR_OK)
|
||||
{
|
||||
if ((retval = duration_stop_measure(&duration, &duration_text)) != ERROR_OK)
|
||||
{
|
||||
return retval;
|
||||
}
|
||||
|
||||
command_print(cmd_ctx, "erased sectors %i through %i on flash bank %li in %s",
|
||||
first, last, strtoul(args[0], 0, 0), duration_text);
|
||||
free(duration_text);
|
||||
}
|
||||
if (!(first <= last)) {
|
||||
command_print(cmd_ctx, "ERROR: "
|
||||
"first sector must be <= last sector");
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
else
|
||||
{
|
||||
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||
|
||||
if (!(last <= (num_sectors - 1))) {
|
||||
command_print(cmd_ctx, "ERROR: last sector must be <= %d",
|
||||
(int) num_sectors - 1);
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
static int handle_flash_protect_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
|
||||
static int handle_flash_erase_command(struct command_context_s *cmd_ctx,
|
||||
char *cmd, char **args, int argc)
|
||||
{
|
||||
if (argc > 2)
|
||||
{
|
||||
uint32_t bank_nr;
|
||||
uint32_t first;
|
||||
uint32_t last;
|
||||
int retval;
|
||||
|
||||
if ((retval = parse_u32(args[0], &bank_nr)) != ERROR_OK)
|
||||
return retval;
|
||||
|
||||
flash_bank_t *p = get_flash_bank_by_num(bank_nr);
|
||||
if (!p)
|
||||
return ERROR_OK;
|
||||
|
||||
if ((retval = parse_u32(args[1], &first)) != ERROR_OK)
|
||||
return retval;
|
||||
if (strcmp(args[2], "last") == 0)
|
||||
last = p->num_sectors - 1;
|
||||
else
|
||||
if ((retval = parse_u32(args[2], &last)) != ERROR_OK)
|
||||
return retval;
|
||||
|
||||
if ((retval = flash_check_sector_parameters(cmd_ctx,
|
||||
first, last, p->num_sectors)) != ERROR_OK)
|
||||
return retval;
|
||||
|
||||
duration_t duration;
|
||||
char *duration_text;
|
||||
duration_start_measure(&duration);
|
||||
|
||||
if ((retval = flash_driver_erase(p, first, last)) == ERROR_OK) {
|
||||
if ((retval = duration_stop_measure(&duration,
|
||||
&duration_text)) != ERROR_OK)
|
||||
return retval;
|
||||
command_print(cmd_ctx, "erased sectors %i through %i "
|
||||
"on flash bank %i in %s",
|
||||
(int) first, (int) last, (int) bank_nr,
|
||||
duration_text);
|
||||
free(duration_text);
|
||||
}
|
||||
}
|
||||
else
|
||||
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
static int handle_flash_protect_command(struct command_context_s *cmd_ctx,
|
||||
char *cmd, char **args, int argc)
|
||||
{
|
||||
if (argc > 3)
|
||||
{
|
||||
int first = strtoul(args[1], NULL, 0);
|
||||
int last = strtoul(args[2], NULL, 0);
|
||||
int set;
|
||||
uint32_t bank_nr;
|
||||
uint32_t first;
|
||||
uint32_t last;
|
||||
int retval;
|
||||
flash_bank_t *p = get_flash_bank_by_num(strtoul(args[0], NULL, 0));
|
||||
int set;
|
||||
|
||||
if ((retval = parse_u32(args[0], &bank_nr)) != ERROR_OK)
|
||||
return retval;
|
||||
|
||||
flash_bank_t *p = get_flash_bank_by_num(bank_nr);
|
||||
if (!p)
|
||||
{
|
||||
command_print(cmd_ctx, "flash bank '#%s' is out of bounds", args[0]);
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
if ((retval = parse_u32(args[1], &first)) != ERROR_OK)
|
||||
return retval;
|
||||
if (strcmp(args[2], "last") == 0)
|
||||
last = p->num_sectors - 1;
|
||||
else
|
||||
if ((retval = parse_u32(args[2], &last)) != ERROR_OK)
|
||||
return retval;
|
||||
|
||||
if (strcmp(args[3], "on") == 0)
|
||||
set = 1;
|
||||
else if (strcmp(args[3], "off") == 0)
|
||||
set = 0;
|
||||
else
|
||||
{
|
||||
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||
}
|
||||
|
||||
if ((retval = flash_check_sector_parameters(cmd_ctx,
|
||||
first, last, p->num_sectors)) != ERROR_OK)
|
||||
return retval;
|
||||
|
||||
retval = flash_driver_protect(p, set, first, last);
|
||||
if (retval == ERROR_OK)
|
||||
{
|
||||
command_print(cmd_ctx, "%s protection for sectors %i through %i on flash bank %li",
|
||||
(set) ? "set" : "cleared", first,
|
||||
last, strtoul(args[0], 0, 0));
|
||||
if (retval == ERROR_OK) {
|
||||
command_print(cmd_ctx, "%s protection for sectors %i "
|
||||
"through %i on flash bank %i",
|
||||
(set) ? "set" : "cleared", (int) first,
|
||||
(int) last, (int) bank_nr);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||
|
||||
}
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
@@ -655,13 +700,26 @@ static int handle_flash_write_image_command(struct command_context_s *cmd_ctx, c
|
||||
|
||||
/* flash auto-erase is disabled by default*/
|
||||
int auto_erase = 0;
|
||||
bool auto_unlock = false;
|
||||
|
||||
if (strcmp(args[0], "erase") == 0)
|
||||
for (;;)
|
||||
{
|
||||
auto_erase = 1;
|
||||
args++;
|
||||
argc--;
|
||||
command_print(cmd_ctx, "auto erase enabled");
|
||||
if (strcmp(args[0], "erase") == 0)
|
||||
{
|
||||
auto_erase = 1;
|
||||
args++;
|
||||
argc--;
|
||||
command_print(cmd_ctx, "auto erase enabled");
|
||||
} else if (strcmp(args[0], "unlock") == 0)
|
||||
{
|
||||
auto_unlock = true;
|
||||
args++;
|
||||
argc--;
|
||||
command_print(cmd_ctx, "auto unlock enabled");
|
||||
} else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (argc < 1)
|
||||
@@ -696,7 +754,7 @@ static int handle_flash_write_image_command(struct command_context_s *cmd_ctx, c
|
||||
return retval;
|
||||
}
|
||||
|
||||
retval = flash_write(target, &image, &written, auto_erase);
|
||||
retval = flash_write_unlock(target, &image, &written, auto_erase, auto_unlock);
|
||||
if (retval != ERROR_OK)
|
||||
{
|
||||
image_close(&image);
|
||||
@@ -708,15 +766,16 @@ static int handle_flash_write_image_command(struct command_context_s *cmd_ctx, c
|
||||
image_close(&image);
|
||||
return retvaltemp;
|
||||
}
|
||||
if (retval == ERROR_OK)
|
||||
{
|
||||
command_print(cmd_ctx,
|
||||
"wrote %" PRIu32 " byte from file %s in %s (%f kb/s)",
|
||||
written,
|
||||
args[0],
|
||||
duration_text,
|
||||
(float)written / 1024.0 / ((float)duration.duration.tv_sec + ((float)duration.duration.tv_usec / 1000000.0)));
|
||||
}
|
||||
|
||||
float speed;
|
||||
|
||||
speed = written / 1024.0;
|
||||
speed /= ((float)duration.duration.tv_sec
|
||||
+ ((float)duration.duration.tv_usec / 1000000.0));
|
||||
command_print(cmd_ctx,
|
||||
"wrote %" PRIu32 " byte from file %s in %s (%f kb/s)",
|
||||
written, args[0], duration_text, speed);
|
||||
|
||||
free(duration_text);
|
||||
|
||||
image_close(&image);
|
||||
@@ -828,18 +887,15 @@ static int handle_flash_fill_command(struct command_context_s *cmd_ctx, char *cm
|
||||
return retval;
|
||||
}
|
||||
|
||||
if (err == ERROR_OK)
|
||||
{
|
||||
float speed;
|
||||
speed = wrote / 1024.0;
|
||||
speed/=((float)duration.duration.tv_sec + ((float)duration.duration.tv_usec / 1000000.0));
|
||||
command_print(cmd_ctx,
|
||||
"wrote %" PRId32 " bytes to 0x%8.8" PRIx32 " in %s (%f kb/s)",
|
||||
count*wordsize,
|
||||
address,
|
||||
duration_text,
|
||||
speed);
|
||||
}
|
||||
float speed;
|
||||
|
||||
speed = wrote / 1024.0;
|
||||
speed /= ((float)duration.duration.tv_sec
|
||||
+ ((float)duration.duration.tv_usec / 1000000.0));
|
||||
command_print(cmd_ctx,
|
||||
"wrote %" PRIu32 " bytes to 0x%8.8" PRIx32 " in %s (%f kb/s)",
|
||||
wrote, address, duration_text, speed);
|
||||
|
||||
free(duration_text);
|
||||
return ERROR_OK;
|
||||
}
|
||||
@@ -954,7 +1010,8 @@ flash_bank_t *get_flash_bank_by_addr(target_t *target, uint32_t addr)
|
||||
}
|
||||
|
||||
/* erase given flash region, selects proper bank according to target and address */
|
||||
int flash_erase_address_range(target_t *target, uint32_t addr, uint32_t length)
|
||||
static int flash_iterate_address_range(target_t *target, uint32_t addr, uint32_t length,
|
||||
int (*callback)(struct flash_bank_s *bank, int first, int last))
|
||||
{
|
||||
flash_bank_t *c;
|
||||
int first = -1;
|
||||
@@ -976,7 +1033,7 @@ int flash_erase_address_range(target_t *target, uint32_t addr, uint32_t length)
|
||||
if (addr != c->base)
|
||||
return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
|
||||
|
||||
return flash_driver_erase(c, 0, c->num_sectors - 1);
|
||||
return callback(c, 0, c->num_sectors - 1);
|
||||
}
|
||||
|
||||
/* check whether it fits */
|
||||
@@ -999,11 +1056,29 @@ int flash_erase_address_range(target_t *target, uint32_t addr, uint32_t length)
|
||||
if (first == -1 || last == -1)
|
||||
return ERROR_OK;
|
||||
|
||||
return flash_driver_erase(c, first, last);
|
||||
return callback(c, first, last);
|
||||
}
|
||||
|
||||
|
||||
|
||||
int flash_erase_address_range(target_t *target, uint32_t addr, uint32_t length)
|
||||
{
|
||||
return flash_iterate_address_range(target, addr, length, &flash_driver_erase);
|
||||
}
|
||||
|
||||
static int flash_driver_unprotect(struct flash_bank_s *bank, int first, int last)
|
||||
{
|
||||
return flash_driver_protect(bank, 0, first, last);
|
||||
}
|
||||
|
||||
static int flash_unlock_address_range(target_t *target, uint32_t addr, uint32_t length)
|
||||
{
|
||||
return flash_iterate_address_range(target, addr, length, &flash_driver_unprotect);
|
||||
}
|
||||
|
||||
|
||||
/* write (optional verify) an image to flash memory of the given target */
|
||||
int flash_write(target_t *target, image_t *image, uint32_t *written, int erase)
|
||||
static int flash_write_unlock(target_t *target, image_t *image, uint32_t *written, int erase, bool unlock)
|
||||
{
|
||||
int retval = ERROR_OK;
|
||||
|
||||
@@ -1126,10 +1201,17 @@ int flash_write(target_t *target, image_t *image, uint32_t *written, int erase)
|
||||
|
||||
retval = ERROR_OK;
|
||||
|
||||
if (erase)
|
||||
if (unlock)
|
||||
{
|
||||
/* calculate and erase sectors */
|
||||
retval = flash_erase_address_range(target, run_address, run_size);
|
||||
retval = flash_unlock_address_range(target, run_address, run_size);
|
||||
}
|
||||
if (retval == ERROR_OK)
|
||||
{
|
||||
if (erase)
|
||||
{
|
||||
/* calculate and erase sectors */
|
||||
retval = flash_erase_address_range(target, run_address, run_size);
|
||||
}
|
||||
}
|
||||
|
||||
if (retval == ERROR_OK)
|
||||
@@ -1155,6 +1237,11 @@ int flash_write(target_t *target, image_t *image, uint32_t *written, int erase)
|
||||
return retval;
|
||||
}
|
||||
|
||||
int flash_write(target_t *target, image_t *image, uint32_t *written, int erase)
|
||||
{
|
||||
return flash_write_unlock(target, image, written, erase, false);
|
||||
}
|
||||
|
||||
int default_flash_mem_blank_check(struct flash_bank_s *bank)
|
||||
{
|
||||
target_t *target = bank->target;
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* Copyright (C) 2005 by Dominic Rath *
|
||||
* Dominic.Rath@gmx.de *
|
||||
* *
|
||||
* Copyright (C) 2007,2008 Øyvind Harboe *
|
||||
* Copyright (C) 2007,2008 Øyvind Harboe *
|
||||
* oyvind.harboe@zylin.com *
|
||||
* *
|
||||
* Copyright (C) 2008 by Spencer Oliver *
|
||||
|
||||
@@ -2,6 +2,9 @@
|
||||
* Copyright (C) 2005 by Dominic Rath *
|
||||
* Dominic.Rath@gmx.de *
|
||||
* *
|
||||
* LPC1700 support Copyright (C) 2009 by Audrius Urmanavicius *
|
||||
* didele.deze@gmail.com *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation; either version 2 of the License, or *
|
||||
@@ -24,13 +27,14 @@
|
||||
|
||||
#include "lpc2000.h"
|
||||
#include "armv4_5.h"
|
||||
#include "armv7m.h"
|
||||
#include "binarybuffer.h"
|
||||
|
||||
|
||||
/* flash programming support for Philips LPC2xxx devices
|
||||
/* flash programming support for NXP LPC17xx and LPC2xxx devices
|
||||
* currently supported devices:
|
||||
* variant 1 (lpc2000_v1):
|
||||
* - 2104 | 5|6
|
||||
* - 2104 | 5 | 6
|
||||
* - 2114 | 9
|
||||
* - 2124 | 9
|
||||
* - 2194
|
||||
@@ -40,9 +44,13 @@
|
||||
* variant 2 (lpc2000_v2):
|
||||
* - 213x
|
||||
* - 214x
|
||||
* - 2101 | 2|3
|
||||
* - 2364 | 6|8
|
||||
* - 2101 | 2 | 3
|
||||
* - 2364 | 6 | 8
|
||||
* - 2378
|
||||
*
|
||||
* lpc1700:
|
||||
* - 175x
|
||||
* - 176x (tested with LPC1768)
|
||||
*/
|
||||
|
||||
static int lpc2000_register_commands(struct command_context_s *cmd_ctx);
|
||||
@@ -85,15 +93,14 @@ static int lpc2000_register_commands(struct command_context_s *cmd_ctx)
|
||||
static int lpc2000_build_sector_list(struct flash_bank_s *bank)
|
||||
{
|
||||
lpc2000_flash_bank_t *lpc2000_info = bank->driver_priv;
|
||||
int i;
|
||||
uint32_t offset = 0;
|
||||
|
||||
/* default to a 4096 write buffer */
|
||||
lpc2000_info->cmd51_max_buffer = 4096;
|
||||
|
||||
if (lpc2000_info->variant == 1)
|
||||
if (lpc2000_info->variant == lpc2000_v1)
|
||||
{
|
||||
int i = 0;
|
||||
uint32_t offset = 0;
|
||||
|
||||
/* variant 1 has different layout for 128kb and 256kb flashes */
|
||||
if (bank->size == 128 * 1024)
|
||||
{
|
||||
@@ -144,41 +151,37 @@ static int lpc2000_build_sector_list(struct flash_bank_s *bank)
|
||||
exit(-1);
|
||||
}
|
||||
}
|
||||
else if (lpc2000_info->variant == 2)
|
||||
else if (lpc2000_info->variant == lpc2000_v2)
|
||||
{
|
||||
int num_sectors;
|
||||
int i;
|
||||
uint32_t offset = 0;
|
||||
|
||||
/* variant 2 has a uniform layout, only number of sectors differs */
|
||||
switch (bank->size)
|
||||
{
|
||||
case 4 * 1024:
|
||||
lpc2000_info->cmd51_max_buffer = 1024;
|
||||
num_sectors = 1;
|
||||
bank->num_sectors = 1;
|
||||
break;
|
||||
case 8 * 1024:
|
||||
lpc2000_info->cmd51_max_buffer = 1024;
|
||||
num_sectors = 2;
|
||||
bank->num_sectors = 2;
|
||||
break;
|
||||
case 16 * 1024:
|
||||
num_sectors = 4;
|
||||
bank->num_sectors = 4;
|
||||
break;
|
||||
case 32 * 1024:
|
||||
num_sectors = 8;
|
||||
bank->num_sectors = 8;
|
||||
break;
|
||||
case 64 * 1024:
|
||||
num_sectors = 9;
|
||||
bank->num_sectors = 9;
|
||||
break;
|
||||
case 128 * 1024:
|
||||
num_sectors = 11;
|
||||
bank->num_sectors = 11;
|
||||
break;
|
||||
case 256 * 1024:
|
||||
num_sectors = 15;
|
||||
bank->num_sectors = 15;
|
||||
break;
|
||||
case 512 * 1024:
|
||||
case 500 * 1024:
|
||||
num_sectors = 27;
|
||||
bank->num_sectors = 27;
|
||||
break;
|
||||
default:
|
||||
LOG_ERROR("BUG: unknown bank->size encountered");
|
||||
@@ -186,10 +189,9 @@ static int lpc2000_build_sector_list(struct flash_bank_s *bank)
|
||||
break;
|
||||
}
|
||||
|
||||
bank->num_sectors = num_sectors;
|
||||
bank->sectors = malloc(sizeof(flash_sector_t) * num_sectors);
|
||||
bank->sectors = malloc(sizeof(flash_sector_t) * bank->num_sectors);
|
||||
|
||||
for (i = 0; i < num_sectors; i++)
|
||||
for (i = 0; i < bank->num_sectors; i++)
|
||||
{
|
||||
if ((i >= 0) && (i < 8))
|
||||
{
|
||||
@@ -217,6 +219,42 @@ static int lpc2000_build_sector_list(struct flash_bank_s *bank)
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (lpc2000_info->variant == lpc1700)
|
||||
{
|
||||
switch(bank->size)
|
||||
{
|
||||
case 32 * 1024:
|
||||
bank->num_sectors = 8;
|
||||
break;
|
||||
case 64 * 1024:
|
||||
bank->num_sectors = 16;
|
||||
break;
|
||||
case 128 * 1024:
|
||||
bank->num_sectors = 18;
|
||||
break;
|
||||
case 256 * 1024:
|
||||
bank->num_sectors = 22;
|
||||
break;
|
||||
case 512 * 1024:
|
||||
bank->num_sectors = 30;
|
||||
break;
|
||||
default:
|
||||
LOG_ERROR("BUG: unknown bank->size encountered");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
bank->sectors = malloc(sizeof(flash_sector_t) * bank->num_sectors);
|
||||
|
||||
for(i = 0; i < bank->num_sectors; i++)
|
||||
{
|
||||
bank->sectors[i].offset = offset;
|
||||
/* sectors 0-15 are 4kB-sized, 16 and above are 32kB-sized for LPC17xx devices */
|
||||
bank->sectors[i].size = (i < 16)? 4 * 1024 : 32 * 1024;
|
||||
offset += bank->sectors[i].size;
|
||||
bank->sectors[i].is_erased = -1;
|
||||
bank->sectors[i].is_protected = 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG_ERROR("BUG: unknown lpc2000_info->variant encountered");
|
||||
@@ -226,22 +264,24 @@ static int lpc2000_build_sector_list(struct flash_bank_s *bank)
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
/* call LPC2000 IAP function
|
||||
* uses 172 bytes working area
|
||||
/* call LPC1700/LPC2000 IAP function
|
||||
* uses 180 bytes working area
|
||||
* 0x0 to 0x7: jump gate (BX to thumb state, b -2 to wait)
|
||||
* 0x8 to 0x1f: command parameter table
|
||||
* 0x20 to 0x2b: command result table
|
||||
* 0x2c to 0xac: stack (only 128b needed)
|
||||
* 0x8 to 0x1f: command parameter table (1+5 words)
|
||||
* 0x20 to 0x33: command result table (1+4 words)
|
||||
* 0x34 to 0xb3: stack (only 128b needed)
|
||||
*/
|
||||
static int lpc2000_iap_call(flash_bank_t *bank, int code, uint32_t param_table[5], uint32_t result_table[2])
|
||||
static int lpc2000_iap_call(flash_bank_t *bank, int code, uint32_t param_table[5], uint32_t result_table[4])
|
||||
{
|
||||
int retval;
|
||||
lpc2000_flash_bank_t *lpc2000_info = bank->driver_priv;
|
||||
target_t *target = bank->target;
|
||||
mem_param_t mem_params[2];
|
||||
reg_param_t reg_params[5];
|
||||
armv4_5_algorithm_t armv4_5_info;
|
||||
uint32_t status_code;
|
||||
armv4_5_algorithm_t armv4_5_info; /* for LPC2000 */
|
||||
armv7m_algorithm_t armv7m_info; /* for LPC1700 */
|
||||
uint32_t status_code;
|
||||
uint32_t iap_entry_point = 0; /* to make compiler happier */
|
||||
|
||||
/* regrab previously allocated working_area, or allocate a new one */
|
||||
if (!lpc2000_info->iap_working_area)
|
||||
@@ -249,60 +289,116 @@ static int lpc2000_iap_call(flash_bank_t *bank, int code, uint32_t param_table[5
|
||||
uint8_t jump_gate[8];
|
||||
|
||||
/* make sure we have a working area */
|
||||
if (target_alloc_working_area(target, 172, &lpc2000_info->iap_working_area) != ERROR_OK)
|
||||
if (target_alloc_working_area(target, 180, &lpc2000_info->iap_working_area) != ERROR_OK)
|
||||
{
|
||||
LOG_ERROR("no working area specified, can't write LPC2000 internal flash");
|
||||
return ERROR_FLASH_OPERATION_FAILED;
|
||||
}
|
||||
|
||||
/* write IAP code to working area */
|
||||
target_buffer_set_u32(target, jump_gate, ARMV4_5_BX(12));
|
||||
target_buffer_set_u32(target, jump_gate + 4, ARMV4_5_B(0xfffffe, 0));
|
||||
switch(lpc2000_info->variant)
|
||||
{
|
||||
case lpc1700:
|
||||
target_buffer_set_u32(target, jump_gate, ARMV7M_T_BX(12));
|
||||
target_buffer_set_u32(target, jump_gate + 4, ARMV7M_T_B(0xfffffe));
|
||||
break;
|
||||
case lpc2000_v1:
|
||||
case lpc2000_v2:
|
||||
target_buffer_set_u32(target, jump_gate, ARMV4_5_BX(12));
|
||||
target_buffer_set_u32(target, jump_gate + 4, ARMV4_5_B(0xfffffe, 0));
|
||||
break;
|
||||
default:
|
||||
LOG_ERROR("BUG: unknown bank->size encountered");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
if ((retval = target_write_memory(target, lpc2000_info->iap_working_area->address, 4, 2, jump_gate)) != ERROR_OK)
|
||||
{
|
||||
LOG_ERROR("Write memory at address 0x%8.8" PRIx32 " failed (check work_area definition)", lpc2000_info->iap_working_area->address);
|
||||
return retval;
|
||||
}
|
||||
}
|
||||
|
||||
armv4_5_info.common_magic = ARMV4_5_COMMON_MAGIC;
|
||||
armv4_5_info.core_mode = ARMV4_5_MODE_SVC;
|
||||
armv4_5_info.core_state = ARMV4_5_STATE_ARM;
|
||||
switch(lpc2000_info->variant)
|
||||
{
|
||||
case lpc1700:
|
||||
armv7m_info.common_magic = ARMV7M_COMMON_MAGIC;
|
||||
armv7m_info.core_mode = ARMV7M_MODE_ANY;
|
||||
iap_entry_point = 0x1fff1ff1;
|
||||
break;
|
||||
case lpc2000_v1:
|
||||
case lpc2000_v2:
|
||||
armv4_5_info.common_magic = ARMV4_5_COMMON_MAGIC;
|
||||
armv4_5_info.core_mode = ARMV4_5_MODE_SVC;
|
||||
armv4_5_info.core_state = ARMV4_5_STATE_ARM;
|
||||
iap_entry_point = 0x7ffffff1;
|
||||
break;
|
||||
default:
|
||||
LOG_ERROR("BUG: unknown lpc2000->variant encountered");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
/* command parameter table */
|
||||
init_mem_param(&mem_params[0], lpc2000_info->iap_working_area->address + 8, 4 * 6, PARAM_OUT);
|
||||
init_mem_param(&mem_params[0], lpc2000_info->iap_working_area->address + 8, 6 * 4, PARAM_OUT);
|
||||
target_buffer_set_u32(target, mem_params[0].value, code);
|
||||
target_buffer_set_u32(target, mem_params[0].value + 0x4, param_table[0]);
|
||||
target_buffer_set_u32(target, mem_params[0].value + 0x8, param_table[1]);
|
||||
target_buffer_set_u32(target, mem_params[0].value + 0xc, param_table[2]);
|
||||
target_buffer_set_u32(target, mem_params[0].value + 0x04, param_table[0]);
|
||||
target_buffer_set_u32(target, mem_params[0].value + 0x08, param_table[1]);
|
||||
target_buffer_set_u32(target, mem_params[0].value + 0x0c, param_table[2]);
|
||||
target_buffer_set_u32(target, mem_params[0].value + 0x10, param_table[3]);
|
||||
target_buffer_set_u32(target, mem_params[0].value + 0x14, param_table[4]);
|
||||
|
||||
init_reg_param(®_params[0], "r0", 32, PARAM_OUT);
|
||||
buf_set_u32(reg_params[0].value, 0, 32, lpc2000_info->iap_working_area->address + 0x8);
|
||||
buf_set_u32(reg_params[0].value, 0, 32, lpc2000_info->iap_working_area->address + 0x08);
|
||||
|
||||
/* command result table */
|
||||
init_mem_param(&mem_params[1], lpc2000_info->iap_working_area->address + 0x20, 4 * 3, PARAM_IN);
|
||||
init_mem_param(&mem_params[1], lpc2000_info->iap_working_area->address + 0x20, 5 * 4, PARAM_IN);
|
||||
|
||||
init_reg_param(®_params[1], "r1", 32, PARAM_OUT);
|
||||
buf_set_u32(reg_params[1].value, 0, 32, lpc2000_info->iap_working_area->address + 0x20);
|
||||
|
||||
/* IAP entry point */
|
||||
init_reg_param(®_params[2], "r12", 32, PARAM_OUT);
|
||||
buf_set_u32(reg_params[2].value, 0, 32, 0x7ffffff1);
|
||||
buf_set_u32(reg_params[2].value, 0, 32, iap_entry_point);
|
||||
|
||||
/* IAP stack */
|
||||
init_reg_param(®_params[3], "r13_svc", 32, PARAM_OUT);
|
||||
buf_set_u32(reg_params[3].value, 0, 32, lpc2000_info->iap_working_area->address + 0xac);
|
||||
switch(lpc2000_info->variant)
|
||||
{
|
||||
case lpc1700:
|
||||
/* IAP stack */
|
||||
init_reg_param(®_params[3], "sp", 32, PARAM_OUT);
|
||||
buf_set_u32(reg_params[3].value, 0, 32, lpc2000_info->iap_working_area->address + 0xb4);
|
||||
|
||||
/* return address */
|
||||
init_reg_param(®_params[4], "lr_svc", 32, PARAM_OUT);
|
||||
buf_set_u32(reg_params[4].value, 0, 32, lpc2000_info->iap_working_area->address + 0x4);
|
||||
/* return address */
|
||||
init_reg_param(®_params[4], "lr", 32, PARAM_OUT);
|
||||
buf_set_u32(reg_params[4].value, 0, 32, (lpc2000_info->iap_working_area->address + 0x04) | 1); /* bit0 of LR = 1 to return in Thumb mode */
|
||||
|
||||
target_run_algorithm(target, 2, mem_params, 5, reg_params, lpc2000_info->iap_working_area->address, lpc2000_info->iap_working_area->address + 0x4, 10000, &armv4_5_info);
|
||||
target_run_algorithm(target, 2, mem_params, 5, reg_params, lpc2000_info->iap_working_area->address, lpc2000_info->iap_working_area->address + 0x4, 10000, &armv7m_info);
|
||||
break;
|
||||
case lpc2000_v1:
|
||||
case lpc2000_v2:
|
||||
/* IAP stack */
|
||||
init_reg_param(®_params[3], "r13_svc", 32, PARAM_OUT);
|
||||
buf_set_u32(reg_params[3].value, 0, 32, lpc2000_info->iap_working_area->address + 0xb4);
|
||||
|
||||
status_code = buf_get_u32(mem_params[1].value, 0, 32);
|
||||
result_table[0] = target_buffer_get_u32(target, mem_params[1].value);
|
||||
result_table[1] = target_buffer_get_u32(target, mem_params[1].value + 4);
|
||||
/* return address */
|
||||
init_reg_param(®_params[4], "lr_svc", 32, PARAM_OUT);
|
||||
buf_set_u32(reg_params[4].value, 0, 32, lpc2000_info->iap_working_area->address + 0x04);
|
||||
|
||||
target_run_algorithm(target, 2, mem_params, 5, reg_params, lpc2000_info->iap_working_area->address, lpc2000_info->iap_working_area->address + 0x4, 10000, &armv4_5_info);
|
||||
break;
|
||||
default:
|
||||
LOG_ERROR("BUG: unknown lpc2000->variant encountered");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
|
||||
status_code = target_buffer_get_u32(target, mem_params[1].value);
|
||||
result_table[0] = target_buffer_get_u32(target, mem_params[1].value + 0x04);
|
||||
result_table[1] = target_buffer_get_u32(target, mem_params[1].value + 0x08);
|
||||
result_table[2] = target_buffer_get_u32(target, mem_params[1].value + 0x0c);
|
||||
result_table[3] = target_buffer_get_u32(target, mem_params[1].value + 0x10);
|
||||
|
||||
LOG_DEBUG("IAP command = %i (0x%8.8" PRIx32", 0x%8.8" PRIx32", 0x%8.8" PRIx32", 0x%8.8" PRIx32", 0x%8.8" PRIx32") completed with result = %8.8" PRIx32,
|
||||
code, param_table[0], param_table[1], param_table[2], param_table[3], param_table[4], status_code);
|
||||
|
||||
destroy_mem_param(&mem_params[0]);
|
||||
destroy_mem_param(&mem_params[1]);
|
||||
@@ -319,7 +415,7 @@ static int lpc2000_iap_call(flash_bank_t *bank, int code, uint32_t param_table[5
|
||||
static int lpc2000_iap_blank_check(struct flash_bank_s *bank, int first, int last)
|
||||
{
|
||||
uint32_t param_table[5];
|
||||
uint32_t result_table[2];
|
||||
uint32_t result_table[4];
|
||||
int status_code;
|
||||
int i;
|
||||
|
||||
@@ -349,7 +445,7 @@ static int lpc2000_iap_blank_check(struct flash_bank_s *bank, int first, int las
|
||||
return ERROR_FLASH_BUSY;
|
||||
break;
|
||||
default:
|
||||
LOG_ERROR("BUG: unknown LPC2000 status code");
|
||||
LOG_ERROR("BUG: unknown LPC2000 status code %i", status_code);
|
||||
exit(-1);
|
||||
}
|
||||
}
|
||||
@@ -357,7 +453,8 @@ static int lpc2000_iap_blank_check(struct flash_bank_s *bank, int first, int las
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
/* flash bank lpc2000 <base> <size> 0 0 <target#> <lpc_variant> <cclk> [calc_checksum]
|
||||
/*
|
||||
* flash bank lpc2000 <base> <size> 0 0 <target#> <lpc_variant> <cclk> [calc_checksum]
|
||||
*/
|
||||
static int lpc2000_flash_bank_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct flash_bank_s *bank)
|
||||
{
|
||||
@@ -374,21 +471,31 @@ static int lpc2000_flash_bank_command(struct command_context_s *cmd_ctx, char *c
|
||||
|
||||
if (strcmp(args[6], "lpc2000_v1") == 0)
|
||||
{
|
||||
lpc2000_info->variant = 1;
|
||||
lpc2000_info->variant = lpc2000_v1;
|
||||
lpc2000_info->cmd51_dst_boundary = 512;
|
||||
lpc2000_info->cmd51_can_256b = 0;
|
||||
lpc2000_info->cmd51_can_8192b = 1;
|
||||
lpc2000_info->checksum_vector = 5;
|
||||
}
|
||||
else if (strcmp(args[6], "lpc2000_v2") == 0)
|
||||
{
|
||||
lpc2000_info->variant = 2;
|
||||
lpc2000_info->variant = lpc2000_v2;
|
||||
lpc2000_info->cmd51_dst_boundary = 256;
|
||||
lpc2000_info->cmd51_can_256b = 1;
|
||||
lpc2000_info->cmd51_can_8192b = 0;
|
||||
lpc2000_info->checksum_vector = 5;
|
||||
}
|
||||
else if (strcmp(args[6], "lpc1700") == 0)
|
||||
{
|
||||
lpc2000_info->variant = lpc1700;
|
||||
lpc2000_info->cmd51_dst_boundary = 256;
|
||||
lpc2000_info->cmd51_can_256b = 1;
|
||||
lpc2000_info->cmd51_can_8192b = 0;
|
||||
lpc2000_info->checksum_vector = 7;
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG_ERROR("unknown LPC2000 variant");
|
||||
LOG_ERROR("unknown LPC2000 variant: %s", args[6]);
|
||||
free(lpc2000_info);
|
||||
return ERROR_FLASH_BANK_INVALID;
|
||||
}
|
||||
@@ -411,7 +518,7 @@ static int lpc2000_erase(struct flash_bank_s *bank, int first, int last)
|
||||
{
|
||||
lpc2000_flash_bank_t *lpc2000_info = bank->driver_priv;
|
||||
uint32_t param_table[5];
|
||||
uint32_t result_table[2];
|
||||
uint32_t result_table[4];
|
||||
int status_code;
|
||||
|
||||
if (bank->target->state != TARGET_HALTED)
|
||||
@@ -475,7 +582,7 @@ static int lpc2000_write(struct flash_bank_s *bank, uint8_t *buffer, uint32_t of
|
||||
int first_sector = 0;
|
||||
int last_sector = 0;
|
||||
uint32_t param_table[5];
|
||||
uint32_t result_table[2];
|
||||
uint32_t result_table[4];
|
||||
int status_code;
|
||||
int i;
|
||||
working_area_t *download_area;
|
||||
@@ -490,10 +597,7 @@ static int lpc2000_write(struct flash_bank_s *bank, uint8_t *buffer, uint32_t of
|
||||
if (offset + count > bank->size)
|
||||
return ERROR_FLASH_DST_OUT_OF_BANK;
|
||||
|
||||
if (lpc2000_info->cmd51_can_256b)
|
||||
dst_min_alignment = 256;
|
||||
else
|
||||
dst_min_alignment = 512;
|
||||
dst_min_alignment = lpc2000_info->cmd51_dst_boundary;
|
||||
|
||||
if (offset % dst_min_alignment)
|
||||
{
|
||||
@@ -515,25 +619,25 @@ static int lpc2000_write(struct flash_bank_s *bank, uint8_t *buffer, uint32_t of
|
||||
if ((offset == 0) && (count >= 0x20) && lpc2000_info->calc_checksum)
|
||||
{
|
||||
uint32_t checksum = 0;
|
||||
int i = 0;
|
||||
int i;
|
||||
for (i = 0; i < 8; i++)
|
||||
{
|
||||
LOG_DEBUG("0x%2.2x: 0x%8.8" PRIx32, i * 4, buf_get_u32(buffer + (i * 4), 0, 32));
|
||||
if (i != 5)
|
||||
LOG_DEBUG("Vector 0x%2.2x: 0x%8.8" PRIx32, i * 4, buf_get_u32(buffer + (i * 4), 0, 32));
|
||||
if (i != lpc2000_info->checksum_vector)
|
||||
checksum += buf_get_u32(buffer + (i * 4), 0, 32);
|
||||
}
|
||||
checksum = 0 - checksum;
|
||||
LOG_DEBUG("checksum: 0x%8.8" PRIx32, checksum);
|
||||
|
||||
uint32_t original_value = buf_get_u32(buffer + (5 * 4), 0, 32);
|
||||
uint32_t original_value = buf_get_u32(buffer + (lpc2000_info->checksum_vector * 4), 0, 32);
|
||||
if (original_value != checksum)
|
||||
{
|
||||
LOG_WARNING("Verification will fail since checksum in image(0x%8.8" PRIx32 ") written to flash was different from calculated vector checksum(0x%8.8" PRIx32 ").",
|
||||
LOG_WARNING("Verification will fail since checksum in image (0x%8.8" PRIx32 ") to be written to flash is different from calculated vector checksum (0x%8.8" PRIx32 ").",
|
||||
original_value, checksum);
|
||||
LOG_WARNING("To remove this warning modify build tools on developer PC to inject correct LPC vector checksum.");
|
||||
}
|
||||
|
||||
buf_set_u32(buffer + 0x14, 0, 32, checksum);
|
||||
buf_set_u32(buffer + (lpc2000_info->checksum_vector * 4), 0, 32, checksum);
|
||||
}
|
||||
|
||||
/* allocate a working area */
|
||||
@@ -590,10 +694,8 @@ static int lpc2000_write(struct flash_bank_s *bank, uint8_t *buffer, uint32_t of
|
||||
else
|
||||
{
|
||||
uint8_t *last_buffer = malloc(thisrun_bytes);
|
||||
uint32_t i;
|
||||
memcpy(last_buffer, buffer + bytes_written, bytes_remaining);
|
||||
for (i = bytes_remaining; i < thisrun_bytes; i++)
|
||||
last_buffer[i] = 0xff;
|
||||
memset(last_buffer + bytes_remaining, 0xff, thisrun_bytes - bytes_remaining);
|
||||
target_write_buffer(bank->target, download_area->address, thisrun_bytes, last_buffer);
|
||||
free(last_buffer);
|
||||
}
|
||||
@@ -667,7 +769,7 @@ static int lpc2000_info(struct flash_bank_s *bank, char *buf, int buf_size)
|
||||
{
|
||||
lpc2000_flash_bank_t *lpc2000_info = bank->driver_priv;
|
||||
|
||||
snprintf(buf, buf_size, "lpc2000 flash driver variant: %i, clk: %" PRIi32 , lpc2000_info->variant, lpc2000_info->cclk);
|
||||
snprintf(buf, buf_size, "lpc2000 flash driver variant: %i, clk: %" PRIi32 "kHz" , lpc2000_info->variant, lpc2000_info->cclk);
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
@@ -676,7 +778,7 @@ static int lpc2000_handle_part_id_command(struct command_context_s *cmd_ctx, cha
|
||||
{
|
||||
flash_bank_t *bank;
|
||||
uint32_t param_table[5];
|
||||
uint32_t result_table[2];
|
||||
uint32_t result_table[4];
|
||||
int status_code;
|
||||
|
||||
if (argc < 1)
|
||||
|
||||
@@ -2,6 +2,9 @@
|
||||
* Copyright (C) 2005 by Dominic Rath *
|
||||
* Dominic.Rath@gmx.de *
|
||||
* *
|
||||
* LPC1700 support Copyright (C) 2009 by Audrius Urmanavicius *
|
||||
* didele.deze@gmail.com *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation; either version 2 of the License, or *
|
||||
@@ -22,9 +25,16 @@
|
||||
|
||||
#include "flash.h"
|
||||
|
||||
typedef enum
|
||||
{
|
||||
lpc2000_v1,
|
||||
lpc2000_v2,
|
||||
lpc1700
|
||||
} lpc2000_variant;
|
||||
|
||||
typedef struct lpc2000_flash_bank_s
|
||||
{
|
||||
int variant;
|
||||
lpc2000_variant variant;
|
||||
struct working_area_s *iap_working_area;
|
||||
uint32_t cclk;
|
||||
int cmd51_dst_boundary;
|
||||
@@ -32,6 +42,7 @@ typedef struct lpc2000_flash_bank_s
|
||||
int cmd51_can_8192b;
|
||||
int calc_checksum;
|
||||
uint32_t cmd51_max_buffer;
|
||||
int checksum_vector;
|
||||
} lpc2000_flash_bank_t;
|
||||
|
||||
enum lpc2000_status_codes
|
||||
@@ -47,7 +58,16 @@ enum lpc2000_status_codes
|
||||
LPC2000_SECTOR_NOT_BLANK = 8,
|
||||
LPC2000_SECTOR_NOT_PREPARED = 9,
|
||||
LPC2000_COMPARE_ERROR = 10,
|
||||
LPC2000_BUSY = 11
|
||||
LPC2000_BUSY = 11,
|
||||
LPC2000_PARAM_ERROR = 12,
|
||||
LPC2000_ADDR_ERROR = 13,
|
||||
LPC2000_ADDR_NOT_MAPPED = 14,
|
||||
LPC2000_CMD_NOT_LOCKED = 15,
|
||||
LPC2000_INVALID_CODE = 16,
|
||||
LPC2000_INVALID_BAUD_RATE = 17,
|
||||
LPC2000_INVALID_STOP_BIT = 18,
|
||||
LPC2000_CRP_ENABLED = 19
|
||||
|
||||
};
|
||||
|
||||
#endif /* LPC2000_H */
|
||||
|
||||
@@ -214,8 +214,8 @@ static int lpc288x_flash_bank_command(struct command_context_s *cmd_ctx, char *c
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
/* The frequency is the AHB clock frequency divided by (CLK_DIV ×3) + 1.
|
||||
* This must be programmed such that the Flash Programming clock frequency is 66 kHz ± 20%.
|
||||
/* The frequency is the AHB clock frequency divided by (CLK_DIV ×3) + 1.
|
||||
* This must be programmed such that the Flash Programming clock frequency is 66 kHz ± 20%.
|
||||
* AHB = 12 MHz ?
|
||||
* 12000000/66000 = 182
|
||||
* CLK_DIV = 60 ? */
|
||||
|
||||
1928
src/flash/lpc2900.c
Normal file
1928
src/flash/lpc2900.c
Normal file
File diff suppressed because it is too large
Load Diff
27
src/flash/lpc2900.h
Normal file
27
src/flash/lpc2900.h
Normal file
@@ -0,0 +1,27 @@
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2009 by *
|
||||
* Rolf Meeser <rolfm_9dq@yahoo.de> *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation; either version 2 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
* This program is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License *
|
||||
* along with this program; if not, write to the *
|
||||
* Free Software Foundation, Inc., *
|
||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef lpc2900_H
|
||||
#define lpc2900_H
|
||||
|
||||
#include "flash.h"
|
||||
|
||||
|
||||
#endif /* lpc2900_H */
|
||||
@@ -474,8 +474,8 @@ static int mg_mflash_read_sects(void *buff, uint32_t sect_num, uint32_t sect_cnt
|
||||
residue = sect_cnt % 256;
|
||||
|
||||
for (i = 0; i < quotient; i++) {
|
||||
LOG_DEBUG("mflash: sect num : %" PRIu32 " buff : 0x%0lx", sect_num,
|
||||
(unsigned long)buff_ptr);
|
||||
LOG_DEBUG("mflash: sect num : %" PRIu32 " buff : %p",
|
||||
sect_num, buff_ptr);
|
||||
ret = mg_mflash_do_read_sects(buff_ptr, sect_num, 256);
|
||||
if (ret != ERROR_OK)
|
||||
return ret;
|
||||
@@ -485,8 +485,8 @@ static int mg_mflash_read_sects(void *buff, uint32_t sect_num, uint32_t sect_cnt
|
||||
}
|
||||
|
||||
if (residue) {
|
||||
LOG_DEBUG("mflash: sect num : %" PRIx32 " buff : %0lx", sect_num,
|
||||
(unsigned long)buff_ptr);
|
||||
LOG_DEBUG("mflash: sect num : %" PRIx32 " buff : %p",
|
||||
sect_num, buff_ptr);
|
||||
return mg_mflash_do_read_sects(buff_ptr, sect_num, residue);
|
||||
}
|
||||
|
||||
|
||||
902
src/flash/mx3_nand.c
Normal file
902
src/flash/mx3_nand.c
Normal file
@@ -0,0 +1,902 @@
|
||||
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2009 by Alexei Babich *
|
||||
* Rezonans plc., Chelyabinsk, Russia *
|
||||
* impatt@mail.ru *
|
||||
* *
|
||||
* 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. *
|
||||
***************************************************************************/
|
||||
|
||||
/*
|
||||
* Freescale iMX3* OpenOCD NAND Flash controller support.
|
||||
*
|
||||
* Many thanks to Ben Dooks for writing s3c24xx driver.
|
||||
*/
|
||||
|
||||
/*
|
||||
driver tested with STMicro NAND512W3A @imx31
|
||||
tested "nand probe #", "nand erase # 0 #", "nand dump # file 0 #", "nand write # file 0"
|
||||
get_next_halfword_from_sram_buffer() not tested
|
||||
*/
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "mx3_nand.h"
|
||||
|
||||
static const char target_not_halted_err_msg[] =
|
||||
"target must be halted to use mx3 NAND flash controller";
|
||||
static const char data_block_size_err_msg[] =
|
||||
"minimal granularity is one half-word, %" PRId32 " is incorrect";
|
||||
static const char sram_buffer_bounds_err_msg[] =
|
||||
"trying to access out of SRAM buffer bound (addr=0x%" PRIx32 ")";
|
||||
static const char get_status_register_err_msg[] = "can't get NAND status";
|
||||
static uint32_t in_sram_address;
|
||||
unsigned char sign_of_sequental_byte_read;
|
||||
|
||||
static int test_iomux_settings (target_t * target, uint32_t value,
|
||||
uint32_t mask, const char *text);
|
||||
static int initialize_nf_controller (struct nand_device_s *device);
|
||||
static int get_next_byte_from_sram_buffer (target_t * target, uint8_t * value);
|
||||
static int get_next_halfword_from_sram_buffer (target_t * target,
|
||||
uint16_t * value);
|
||||
static int poll_for_complete_op (target_t * target, const char *text);
|
||||
static int validate_target_state (struct nand_device_s *device);
|
||||
static int do_data_output (struct nand_device_s *device);
|
||||
|
||||
static int imx31_nand_device_command (struct command_context_s *cmd_ctx,
|
||||
char *cmd, char **args, int argc,
|
||||
struct nand_device_s *device);
|
||||
static int imx31_init (struct nand_device_s *device);
|
||||
static int imx31_read_data (struct nand_device_s *device, void *data);
|
||||
static int imx31_write_data (struct nand_device_s *device, uint16_t data);
|
||||
static int imx31_nand_ready (struct nand_device_s *device, int timeout);
|
||||
static int imx31_register_commands (struct command_context_s *cmd_ctx);
|
||||
static int imx31_reset (struct nand_device_s *device);
|
||||
static int imx31_command (struct nand_device_s *device, uint8_t command);
|
||||
static int imx31_address (struct nand_device_s *device, uint8_t address);
|
||||
static int imx31_controller_ready (struct nand_device_s *device, int tout);
|
||||
static int imx31_write_page (struct nand_device_s *device, uint32_t page,
|
||||
uint8_t * data, uint32_t data_size, uint8_t * oob,
|
||||
uint32_t oob_size);
|
||||
static int imx31_read_page (struct nand_device_s *device, uint32_t page,
|
||||
uint8_t * data, uint32_t data_size, uint8_t * oob,
|
||||
uint32_t oob_size);
|
||||
|
||||
nand_flash_controller_t imx31_nand_flash_controller = {
|
||||
.name = "imx31",
|
||||
.nand_device_command = imx31_nand_device_command,
|
||||
.register_commands = imx31_register_commands,
|
||||
.init = imx31_init,
|
||||
.reset = imx31_reset,
|
||||
.command = imx31_command,
|
||||
.address = imx31_address,
|
||||
.write_data = imx31_write_data,
|
||||
.read_data = imx31_read_data,
|
||||
.write_page = imx31_write_page,
|
||||
.read_page = imx31_read_page,
|
||||
.controller_ready = imx31_controller_ready,
|
||||
.nand_ready = imx31_nand_ready,
|
||||
};
|
||||
|
||||
static int imx31_nand_device_command (struct command_context_s *cmd_ctx,
|
||||
char *cmd, char **args, int argc,
|
||||
struct nand_device_s *device)
|
||||
{
|
||||
mx3_nf_controller_t *mx3_nf_info;
|
||||
mx3_nf_info = malloc (sizeof (mx3_nf_controller_t));
|
||||
if (mx3_nf_info == NULL)
|
||||
{
|
||||
LOG_ERROR ("no memory for nand controller");
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
|
||||
device->controller_priv = mx3_nf_info;
|
||||
|
||||
mx3_nf_info->target = get_target (args[1]);
|
||||
if (mx3_nf_info->target == NULL)
|
||||
{
|
||||
LOG_ERROR ("target '%s' not defined", args[1]);
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
if (argc < 3)
|
||||
{
|
||||
LOG_ERROR ("use \"nand device imx31 target noecc|hwecc\"");
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
/*
|
||||
* check hwecc requirements
|
||||
*/
|
||||
{
|
||||
int hwecc_needed;
|
||||
hwecc_needed = strcmp (args[2], "hwecc");
|
||||
if (hwecc_needed == 0)
|
||||
{
|
||||
mx3_nf_info->flags.hw_ecc_enabled = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
mx3_nf_info->flags.hw_ecc_enabled = 0;
|
||||
}
|
||||
}
|
||||
|
||||
mx3_nf_info->optype = MX3_NF_DATAOUT_PAGE;
|
||||
mx3_nf_info->fin = MX3_NF_FIN_NONE;
|
||||
mx3_nf_info->flags.target_little_endian =
|
||||
(mx3_nf_info->target->endianness == TARGET_LITTLE_ENDIAN);
|
||||
/*
|
||||
* testing host endianess
|
||||
*/
|
||||
{
|
||||
int x = 1;
|
||||
if (*(char *) &x == 1)
|
||||
{
|
||||
mx3_nf_info->flags.host_little_endian = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
mx3_nf_info->flags.host_little_endian = 0;
|
||||
}
|
||||
}
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
static int imx31_init (struct nand_device_s *device)
|
||||
{
|
||||
mx3_nf_controller_t *mx3_nf_info = device->controller_priv;
|
||||
target_t *target = mx3_nf_info->target;
|
||||
|
||||
{
|
||||
/*
|
||||
* validate target state
|
||||
*/
|
||||
int validate_target_result;
|
||||
validate_target_result = validate_target_state (device);
|
||||
if (validate_target_result != ERROR_OK)
|
||||
{
|
||||
return validate_target_result;
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
uint16_t buffsize_register_content;
|
||||
target_read_u16 (target, MX3_NF_BUFSIZ, &buffsize_register_content);
|
||||
mx3_nf_info->flags.one_kb_sram = !(buffsize_register_content & 0x000f);
|
||||
}
|
||||
|
||||
{
|
||||
uint32_t pcsr_register_content;
|
||||
target_read_u32 (target, MX3_PCSR, &pcsr_register_content);
|
||||
if (!device->bus_width)
|
||||
{
|
||||
device->bus_width =
|
||||
(pcsr_register_content & 0x80000000) ? 16 : 8;
|
||||
}
|
||||
else
|
||||
{
|
||||
pcsr_register_content |=
|
||||
((device->bus_width == 16) ? 0x80000000 : 0x00000000);
|
||||
target_write_u32 (target, MX3_PCSR, pcsr_register_content);
|
||||
}
|
||||
|
||||
if (!device->page_size)
|
||||
{
|
||||
device->page_size =
|
||||
(pcsr_register_content & 0x40000000) ? 2048 : 512;
|
||||
}
|
||||
else
|
||||
{
|
||||
pcsr_register_content |=
|
||||
((device->page_size == 2048) ? 0x40000000 : 0x00000000);
|
||||
target_write_u32 (target, MX3_PCSR, pcsr_register_content);
|
||||
}
|
||||
if (mx3_nf_info->flags.one_kb_sram && (device->page_size == 2048))
|
||||
{
|
||||
LOG_ERROR
|
||||
("NAND controller have only 1 kb SRAM, so pagesize 2048 is incompatible with it");
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
uint32_t cgr_register_content;
|
||||
target_read_u32 (target, MX3_CCM_CGR2, &cgr_register_content);
|
||||
if (!(cgr_register_content & 0x00000300))
|
||||
{
|
||||
LOG_ERROR ("clock gating to EMI disabled");
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
uint32_t gpr_register_content;
|
||||
target_read_u32 (target, MX3_GPR, &gpr_register_content);
|
||||
if (gpr_register_content & 0x00000060)
|
||||
{
|
||||
LOG_ERROR ("pins mode overrided by GPR");
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
/*
|
||||
* testing IOMUX settings; must be in "functional-mode output and
|
||||
* functional-mode input" mode
|
||||
*/
|
||||
int test_iomux;
|
||||
test_iomux = ERROR_OK;
|
||||
test_iomux |=
|
||||
test_iomux_settings (target, 0x43fac0c0, 0x7f7f7f00, "d0,d1,d2");
|
||||
test_iomux |=
|
||||
test_iomux_settings (target, 0x43fac0c4, 0x7f7f7f7f, "d3,d4,d5,d6");
|
||||
test_iomux |=
|
||||
test_iomux_settings (target, 0x43fac0c8, 0x0000007f, "d7");
|
||||
if (device->bus_width == 16)
|
||||
{
|
||||
test_iomux |=
|
||||
test_iomux_settings (target, 0x43fac0c8, 0x7f7f7f00,
|
||||
"d8,d9,d10");
|
||||
test_iomux |=
|
||||
test_iomux_settings (target, 0x43fac0cc, 0x7f7f7f7f,
|
||||
"d11,d12,d13,d14");
|
||||
test_iomux |=
|
||||
test_iomux_settings (target, 0x43fac0d0, 0x0000007f, "d15");
|
||||
}
|
||||
test_iomux |=
|
||||
test_iomux_settings (target, 0x43fac0d0, 0x7f7f7f00,
|
||||
"nfwp,nfce,nfrb");
|
||||
test_iomux |=
|
||||
test_iomux_settings (target, 0x43fac0d4, 0x7f7f7f7f,
|
||||
"nfwe,nfre,nfale,nfcle");
|
||||
if (test_iomux != ERROR_OK)
|
||||
{
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
}
|
||||
|
||||
initialize_nf_controller (device);
|
||||
|
||||
{
|
||||
int retval;
|
||||
uint16_t nand_status_content;
|
||||
retval = ERROR_OK;
|
||||
retval |= imx31_command (device, NAND_CMD_STATUS);
|
||||
retval |= imx31_address (device, 0x00);
|
||||
retval |= do_data_output (device);
|
||||
if (retval != ERROR_OK)
|
||||
{
|
||||
LOG_ERROR (get_status_register_err_msg);
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
target_read_u16 (target, MX3_NF_MAIN_BUFFER0, &nand_status_content);
|
||||
if (!(nand_status_content & 0x0080))
|
||||
{
|
||||
/*
|
||||
* is host-big-endian correctly ??
|
||||
*/
|
||||
LOG_INFO ("NAND read-only");
|
||||
mx3_nf_info->flags.nand_readonly = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
mx3_nf_info->flags.nand_readonly = 0;
|
||||
}
|
||||
}
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
static int imx31_read_data (struct nand_device_s *device, void *data)
|
||||
{
|
||||
mx3_nf_controller_t *mx3_nf_info = device->controller_priv;
|
||||
target_t *target = mx3_nf_info->target;
|
||||
{
|
||||
/*
|
||||
* validate target state
|
||||
*/
|
||||
int validate_target_result;
|
||||
validate_target_result = validate_target_state (device);
|
||||
if (validate_target_result != ERROR_OK)
|
||||
{
|
||||
return validate_target_result;
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
/*
|
||||
* get data from nand chip
|
||||
*/
|
||||
int try_data_output_from_nand_chip;
|
||||
try_data_output_from_nand_chip = do_data_output (device);
|
||||
if (try_data_output_from_nand_chip != ERROR_OK)
|
||||
{
|
||||
return try_data_output_from_nand_chip;
|
||||
}
|
||||
}
|
||||
|
||||
if (device->bus_width == 16)
|
||||
{
|
||||
get_next_halfword_from_sram_buffer (target, data);
|
||||
}
|
||||
else
|
||||
{
|
||||
get_next_byte_from_sram_buffer (target, data);
|
||||
}
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
static int imx31_write_data (struct nand_device_s *device, uint16_t data)
|
||||
{
|
||||
LOG_ERROR ("write_data() not implemented");
|
||||
return ERROR_NAND_OPERATION_FAILED;
|
||||
}
|
||||
|
||||
static int imx31_nand_ready (struct nand_device_s *device, int timeout)
|
||||
{
|
||||
return imx31_controller_ready (device, timeout);
|
||||
}
|
||||
|
||||
static int imx31_register_commands (struct command_context_s *cmd_ctx)
|
||||
{
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
static int imx31_reset (struct nand_device_s *device)
|
||||
{
|
||||
/*
|
||||
* validate target state
|
||||
*/
|
||||
int validate_target_result;
|
||||
validate_target_result = validate_target_state (device);
|
||||
if (validate_target_result != ERROR_OK)
|
||||
{
|
||||
return validate_target_result;
|
||||
}
|
||||
initialize_nf_controller (device);
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
static int imx31_command (struct nand_device_s *device, uint8_t command)
|
||||
{
|
||||
mx3_nf_controller_t *mx3_nf_info = device->controller_priv;
|
||||
target_t *target = mx3_nf_info->target;
|
||||
{
|
||||
/*
|
||||
* validate target state
|
||||
*/
|
||||
int validate_target_result;
|
||||
validate_target_result = validate_target_state (device);
|
||||
if (validate_target_result != ERROR_OK)
|
||||
{
|
||||
return validate_target_result;
|
||||
}
|
||||
}
|
||||
|
||||
switch (command)
|
||||
{
|
||||
case NAND_CMD_READOOB:
|
||||
command = NAND_CMD_READ0;
|
||||
in_sram_address = MX3_NF_SPARE_BUFFER0; /* set read point for
|
||||
* data_read() and
|
||||
* read_block_data() to
|
||||
* spare area in SRAM
|
||||
* buffer */
|
||||
break;
|
||||
case NAND_CMD_READ1:
|
||||
command = NAND_CMD_READ0;
|
||||
/*
|
||||
* offset == one half of page size
|
||||
*/
|
||||
in_sram_address =
|
||||
MX3_NF_MAIN_BUFFER0 + (device->page_size >> 1);
|
||||
default:
|
||||
in_sram_address = MX3_NF_MAIN_BUFFER0;
|
||||
}
|
||||
|
||||
target_write_u16 (target, MX3_NF_FCMD, command);
|
||||
/*
|
||||
* start command input operation (set MX3_NF_BIT_OP_DONE==0)
|
||||
*/
|
||||
target_write_u16 (target, MX3_NF_CFG2, MX3_NF_BIT_OP_FCI);
|
||||
{
|
||||
int poll_result;
|
||||
poll_result = poll_for_complete_op (target, "command");
|
||||
if (poll_result != ERROR_OK)
|
||||
{
|
||||
return poll_result;
|
||||
}
|
||||
}
|
||||
/*
|
||||
* reset cursor to begin of the buffer
|
||||
*/
|
||||
sign_of_sequental_byte_read = 0;
|
||||
switch (command)
|
||||
{
|
||||
case NAND_CMD_READID:
|
||||
mx3_nf_info->optype = MX3_NF_DATAOUT_NANDID;
|
||||
mx3_nf_info->fin = MX3_NF_FIN_DATAOUT;
|
||||
break;
|
||||
case NAND_CMD_STATUS:
|
||||
mx3_nf_info->optype = MX3_NF_DATAOUT_NANDSTATUS;
|
||||
mx3_nf_info->fin = MX3_NF_FIN_DATAOUT;
|
||||
break;
|
||||
case NAND_CMD_READ0:
|
||||
mx3_nf_info->fin = MX3_NF_FIN_DATAOUT;
|
||||
mx3_nf_info->optype = MX3_NF_DATAOUT_PAGE;
|
||||
break;
|
||||
default:
|
||||
mx3_nf_info->optype = MX3_NF_DATAOUT_PAGE;
|
||||
}
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
static int imx31_address (struct nand_device_s *device, uint8_t address)
|
||||
{
|
||||
mx3_nf_controller_t *mx3_nf_info = device->controller_priv;
|
||||
target_t *target = mx3_nf_info->target;
|
||||
{
|
||||
/*
|
||||
* validate target state
|
||||
*/
|
||||
int validate_target_result;
|
||||
validate_target_result = validate_target_state (device);
|
||||
if (validate_target_result != ERROR_OK)
|
||||
{
|
||||
return validate_target_result;
|
||||
}
|
||||
}
|
||||
|
||||
target_write_u16 (target, MX3_NF_FADDR, address);
|
||||
/*
|
||||
* start address input operation (set MX3_NF_BIT_OP_DONE==0)
|
||||
*/
|
||||
target_write_u16 (target, MX3_NF_CFG2, MX3_NF_BIT_OP_FAI);
|
||||
{
|
||||
int poll_result;
|
||||
poll_result = poll_for_complete_op (target, "address");
|
||||
if (poll_result != ERROR_OK)
|
||||
{
|
||||
return poll_result;
|
||||
}
|
||||
}
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
static int imx31_controller_ready (struct nand_device_s *device, int tout)
|
||||
{
|
||||
uint16_t poll_complete_status;
|
||||
mx3_nf_controller_t *mx3_nf_info = device->controller_priv;
|
||||
target_t *target = mx3_nf_info->target;
|
||||
|
||||
{
|
||||
/*
|
||||
* validate target state
|
||||
*/
|
||||
int validate_target_result;
|
||||
validate_target_result = validate_target_state (device);
|
||||
if (validate_target_result != ERROR_OK)
|
||||
{
|
||||
return validate_target_result;
|
||||
}
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
target_read_u16 (target, MX3_NF_CFG2, &poll_complete_status);
|
||||
if (poll_complete_status & MX3_NF_BIT_OP_DONE)
|
||||
{
|
||||
return tout;
|
||||
}
|
||||
alive_sleep (1);
|
||||
}
|
||||
while (tout-- > 0);
|
||||
return tout;
|
||||
}
|
||||
|
||||
static int imx31_write_page (struct nand_device_s *device, uint32_t page,
|
||||
uint8_t * data, uint32_t data_size, uint8_t * oob,
|
||||
uint32_t oob_size)
|
||||
{
|
||||
mx3_nf_controller_t *mx3_nf_info = device->controller_priv;
|
||||
target_t *target = mx3_nf_info->target;
|
||||
|
||||
if (data_size % 2)
|
||||
{
|
||||
LOG_ERROR (data_block_size_err_msg, data_size);
|
||||
return ERROR_NAND_OPERATION_FAILED;
|
||||
}
|
||||
if (oob_size % 2)
|
||||
{
|
||||
LOG_ERROR (data_block_size_err_msg, oob_size);
|
||||
return ERROR_NAND_OPERATION_FAILED;
|
||||
}
|
||||
if (!data)
|
||||
{
|
||||
LOG_ERROR ("nothing to program");
|
||||
return ERROR_NAND_OPERATION_FAILED;
|
||||
}
|
||||
{
|
||||
/*
|
||||
* validate target state
|
||||
*/
|
||||
int retval;
|
||||
retval = validate_target_state (device);
|
||||
if (retval != ERROR_OK)
|
||||
{
|
||||
return retval;
|
||||
}
|
||||
}
|
||||
{
|
||||
int retval = ERROR_OK;
|
||||
retval |= imx31_command (device, NAND_CMD_SEQIN);
|
||||
retval |= imx31_address (device, 0x00);
|
||||
retval |= imx31_address (device, page & 0xff);
|
||||
retval |= imx31_address (device, (page >> 8) & 0xff);
|
||||
if (device->address_cycles >= 4)
|
||||
{
|
||||
retval |= imx31_address (device, (page >> 16) & 0xff);
|
||||
if (device->address_cycles >= 5)
|
||||
{
|
||||
retval |= imx31_address (device, (page >> 24) & 0xff);
|
||||
}
|
||||
}
|
||||
target_write_buffer (target, MX3_NF_MAIN_BUFFER0, data_size, data);
|
||||
if (oob)
|
||||
{
|
||||
if (mx3_nf_info->flags.hw_ecc_enabled)
|
||||
{
|
||||
/*
|
||||
* part of spare block will be overrided by hardware
|
||||
* ECC generator
|
||||
*/
|
||||
LOG_DEBUG
|
||||
("part of spare block will be overrided by hardware ECC generator");
|
||||
}
|
||||
target_write_buffer (target, MX3_NF_SPARE_BUFFER0, oob_size,
|
||||
oob);
|
||||
}
|
||||
/*
|
||||
* start data input operation (set MX3_NF_BIT_OP_DONE==0)
|
||||
*/
|
||||
target_write_u16 (target, MX3_NF_CFG2, MX3_NF_BIT_OP_FDI);
|
||||
{
|
||||
int poll_result;
|
||||
poll_result = poll_for_complete_op (target, "data input");
|
||||
if (poll_result != ERROR_OK)
|
||||
{
|
||||
return poll_result;
|
||||
}
|
||||
}
|
||||
retval |= imx31_command (device, NAND_CMD_PAGEPROG);
|
||||
if (retval != ERROR_OK)
|
||||
{
|
||||
return retval;
|
||||
}
|
||||
|
||||
/*
|
||||
* check status register
|
||||
*/
|
||||
{
|
||||
uint16_t nand_status_content;
|
||||
retval = ERROR_OK;
|
||||
retval |= imx31_command (device, NAND_CMD_STATUS);
|
||||
retval |= imx31_address (device, 0x00);
|
||||
retval |= do_data_output (device);
|
||||
if (retval != ERROR_OK)
|
||||
{
|
||||
LOG_ERROR (get_status_register_err_msg);
|
||||
return retval;
|
||||
}
|
||||
target_read_u16 (target, MX3_NF_MAIN_BUFFER0, &nand_status_content);
|
||||
if (nand_status_content & 0x0001)
|
||||
{
|
||||
/*
|
||||
* is host-big-endian correctly ??
|
||||
*/
|
||||
return ERROR_NAND_OPERATION_FAILED;
|
||||
}
|
||||
}
|
||||
}
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
static int imx31_read_page (struct nand_device_s *device, uint32_t page,
|
||||
uint8_t * data, uint32_t data_size, uint8_t * oob,
|
||||
uint32_t oob_size)
|
||||
{
|
||||
mx3_nf_controller_t *mx3_nf_info = device->controller_priv;
|
||||
target_t *target = mx3_nf_info->target;
|
||||
|
||||
if (data_size % 2)
|
||||
{
|
||||
LOG_ERROR (data_block_size_err_msg, data_size);
|
||||
return ERROR_NAND_OPERATION_FAILED;
|
||||
}
|
||||
if (oob_size % 2)
|
||||
{
|
||||
LOG_ERROR (data_block_size_err_msg, oob_size);
|
||||
return ERROR_NAND_OPERATION_FAILED;
|
||||
}
|
||||
|
||||
{
|
||||
/*
|
||||
* validate target state
|
||||
*/
|
||||
int retval;
|
||||
retval = validate_target_state (device);
|
||||
if (retval != ERROR_OK)
|
||||
{
|
||||
return retval;
|
||||
}
|
||||
}
|
||||
{
|
||||
int retval = ERROR_OK;
|
||||
retval |= imx31_command (device, NAND_CMD_READ0);
|
||||
retval |= imx31_address (device, 0x00);
|
||||
retval |= imx31_address (device, page & 0xff);
|
||||
retval |= imx31_address (device, (page >> 8) & 0xff);
|
||||
if (device->address_cycles >= 4)
|
||||
{
|
||||
retval |= imx31_address (device, (page >> 16) & 0xff);
|
||||
if (device->address_cycles >= 5)
|
||||
{
|
||||
retval |= imx31_address (device, (page >> 24) & 0xff);
|
||||
retval |= imx31_command (device, NAND_CMD_READSTART);
|
||||
}
|
||||
}
|
||||
retval |= do_data_output (device);
|
||||
if (retval != ERROR_OK)
|
||||
{
|
||||
return retval;
|
||||
}
|
||||
|
||||
if (data)
|
||||
{
|
||||
target_read_buffer (target, MX3_NF_MAIN_BUFFER0, data_size,
|
||||
data);
|
||||
}
|
||||
if (oob)
|
||||
{
|
||||
target_read_buffer (target, MX3_NF_SPARE_BUFFER0, oob_size,
|
||||
oob);
|
||||
}
|
||||
}
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
static int test_iomux_settings (target_t * target, uint32_t address,
|
||||
uint32_t mask, const char *text)
|
||||
{
|
||||
uint32_t register_content;
|
||||
target_read_u32 (target, address, ®ister_content);
|
||||
if ((register_content & mask) != (0x12121212 & mask))
|
||||
{
|
||||
LOG_ERROR ("IOMUX for {%s} is bad", text);
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
static int initialize_nf_controller (struct nand_device_s *device)
|
||||
{
|
||||
mx3_nf_controller_t *mx3_nf_info = device->controller_priv;
|
||||
target_t *target = mx3_nf_info->target;
|
||||
/*
|
||||
* resets NAND flash controller in zero time ? I dont know.
|
||||
*/
|
||||
target_write_u16 (target, MX3_NF_CFG1, MX3_NF_BIT_RESET_EN);
|
||||
{
|
||||
uint16_t work_mode;
|
||||
work_mode = MX3_NF_BIT_INT_DIS; /* disable interrupt */
|
||||
if (target->endianness == TARGET_BIG_ENDIAN)
|
||||
{
|
||||
work_mode |= MX3_NF_BIT_BE_EN;
|
||||
}
|
||||
if (mx3_nf_info->flags.hw_ecc_enabled)
|
||||
{
|
||||
work_mode |= MX3_NF_BIT_ECC_EN;
|
||||
}
|
||||
target_write_u16 (target, MX3_NF_CFG1, work_mode);
|
||||
}
|
||||
/*
|
||||
* unlock SRAM buffer for write; 2 mean "Unlock", other values means "Lock"
|
||||
*/
|
||||
target_write_u16 (target, MX3_NF_BUFCFG, 2);
|
||||
{
|
||||
uint16_t temp;
|
||||
target_read_u16 (target, MX3_NF_FWP, &temp);
|
||||
if ((temp & 0x0007) == 1)
|
||||
{
|
||||
LOG_ERROR ("NAND flash is tight-locked, reset needed");
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
|
||||
}
|
||||
/*
|
||||
* unlock NAND flash for write
|
||||
*/
|
||||
target_write_u16 (target, MX3_NF_FWP, 4);
|
||||
target_write_u16 (target, MX3_NF_LOCKSTART, 0x0000);
|
||||
target_write_u16 (target, MX3_NF_LOCKEND, 0xFFFF);
|
||||
/*
|
||||
* 0x0000 means that first SRAM buffer @0xB800_0000 will be used
|
||||
*/
|
||||
target_write_u16 (target, MX3_NF_BUFADDR, 0x0000);
|
||||
/*
|
||||
* address of SRAM buffer
|
||||
*/
|
||||
in_sram_address = MX3_NF_MAIN_BUFFER0;
|
||||
sign_of_sequental_byte_read = 0;
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
static int get_next_byte_from_sram_buffer (target_t * target, uint8_t * value)
|
||||
{
|
||||
static uint8_t even_byte = 0;
|
||||
/*
|
||||
* host-big_endian ??
|
||||
*/
|
||||
if (sign_of_sequental_byte_read == 0)
|
||||
{
|
||||
even_byte = 0;
|
||||
}
|
||||
if (in_sram_address > MX3_NF_LAST_BUFFER_ADDR)
|
||||
{
|
||||
LOG_ERROR (sram_buffer_bounds_err_msg, in_sram_address);
|
||||
*value = 0;
|
||||
sign_of_sequental_byte_read = 0;
|
||||
even_byte = 0;
|
||||
return ERROR_NAND_OPERATION_FAILED;
|
||||
}
|
||||
else
|
||||
{
|
||||
uint16_t temp;
|
||||
target_read_u16 (target, in_sram_address, &temp);
|
||||
if (even_byte)
|
||||
{
|
||||
*value = temp >> 8;
|
||||
even_byte = 0;
|
||||
in_sram_address += 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
*value = temp & 0xff;
|
||||
even_byte = 1;
|
||||
}
|
||||
}
|
||||
sign_of_sequental_byte_read = 1;
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
static int get_next_halfword_from_sram_buffer (target_t * target,
|
||||
uint16_t * value)
|
||||
{
|
||||
if (in_sram_address > MX3_NF_LAST_BUFFER_ADDR)
|
||||
{
|
||||
LOG_ERROR (sram_buffer_bounds_err_msg, in_sram_address);
|
||||
*value = 0;
|
||||
return ERROR_NAND_OPERATION_FAILED;
|
||||
}
|
||||
else
|
||||
{
|
||||
target_read_u16 (target, in_sram_address, value);
|
||||
in_sram_address += 2;
|
||||
}
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
static int poll_for_complete_op (target_t * target, const char *text)
|
||||
{
|
||||
uint16_t poll_complete_status;
|
||||
for (int poll_cycle_count = 0; poll_cycle_count < 100; poll_cycle_count++)
|
||||
{
|
||||
usleep (25);
|
||||
target_read_u16 (target, MX3_NF_CFG2, &poll_complete_status);
|
||||
if (poll_complete_status & MX3_NF_BIT_OP_DONE)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!(poll_complete_status & MX3_NF_BIT_OP_DONE))
|
||||
{
|
||||
LOG_ERROR ("%s sending timeout", text);
|
||||
return ERROR_NAND_OPERATION_FAILED;
|
||||
}
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
static int validate_target_state (struct nand_device_s *device)
|
||||
{
|
||||
mx3_nf_controller_t *mx3_nf_info = device->controller_priv;
|
||||
target_t *target = mx3_nf_info->target;
|
||||
|
||||
if (target->state != TARGET_HALTED)
|
||||
{
|
||||
LOG_ERROR (target_not_halted_err_msg);
|
||||
return ERROR_NAND_OPERATION_FAILED;
|
||||
}
|
||||
|
||||
if (mx3_nf_info->flags.target_little_endian !=
|
||||
(target->endianness == TARGET_LITTLE_ENDIAN))
|
||||
{
|
||||
/*
|
||||
* endianness changed after NAND controller probed
|
||||
*/
|
||||
return ERROR_NAND_OPERATION_FAILED;
|
||||
}
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
static int do_data_output (struct nand_device_s *device)
|
||||
{
|
||||
mx3_nf_controller_t *mx3_nf_info = device->controller_priv;
|
||||
target_t *target = mx3_nf_info->target;
|
||||
switch (mx3_nf_info->fin)
|
||||
{
|
||||
case MX3_NF_FIN_DATAOUT:
|
||||
/*
|
||||
* start data output operation (set MX3_NF_BIT_OP_DONE==0)
|
||||
*/
|
||||
target_write_u16 (target, MX3_NF_CFG2,
|
||||
MX3_NF_BIT_DATAOUT_TYPE (mx3_nf_info->
|
||||
optype));
|
||||
{
|
||||
int poll_result;
|
||||
poll_result = poll_for_complete_op (target, "data output");
|
||||
if (poll_result != ERROR_OK)
|
||||
{
|
||||
return poll_result;
|
||||
}
|
||||
}
|
||||
mx3_nf_info->fin = MX3_NF_FIN_NONE;
|
||||
/*
|
||||
* ECC stuff
|
||||
*/
|
||||
if ((mx3_nf_info->optype == MX3_NF_DATAOUT_PAGE)
|
||||
&& mx3_nf_info->flags.hw_ecc_enabled)
|
||||
{
|
||||
uint16_t ecc_status;
|
||||
target_read_u16 (target, MX3_NF_ECCSTATUS, &ecc_status);
|
||||
switch (ecc_status & 0x000c)
|
||||
{
|
||||
case 1 << 2:
|
||||
LOG_DEBUG
|
||||
("main area readed with 1 (correctable) error");
|
||||
break;
|
||||
case 2 << 2:
|
||||
LOG_DEBUG
|
||||
("main area readed with more than 1 (incorrectable) error");
|
||||
return ERROR_NAND_OPERATION_FAILED;
|
||||
break;
|
||||
}
|
||||
switch (ecc_status & 0x0003)
|
||||
{
|
||||
case 1:
|
||||
LOG_DEBUG
|
||||
("spare area readed with 1 (correctable) error");
|
||||
break;
|
||||
case 2:
|
||||
LOG_DEBUG
|
||||
("main area readed with more than 1 (incorrectable) error");
|
||||
return ERROR_NAND_OPERATION_FAILED;
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case MX3_NF_FIN_NONE:
|
||||
break;
|
||||
}
|
||||
return ERROR_OK;
|
||||
}
|
||||
117
src/flash/mx3_nand.h
Normal file
117
src/flash/mx3_nand.h
Normal file
@@ -0,0 +1,117 @@
|
||||
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2009 by Alexei Babich *
|
||||
* Rezonans plc., Chelyabinsk, Russia *
|
||||
* impatt@mail.ru *
|
||||
* *
|
||||
* 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. *
|
||||
***************************************************************************/
|
||||
|
||||
/*
|
||||
* Freescale iMX3* OpenOCD NAND Flash controller support.
|
||||
*
|
||||
* Many thanks to Ben Dooks for writing s3c24xx driver.
|
||||
*/
|
||||
#include <nand.h>
|
||||
|
||||
#define MX3_NF_BASE_ADDR 0xb8000000
|
||||
#define MX3_NF_BUFSIZ (MX3_NF_BASE_ADDR + 0xe00)
|
||||
#define MX3_NF_BUFADDR (MX3_NF_BASE_ADDR + 0xe04)
|
||||
#define MX3_NF_FADDR (MX3_NF_BASE_ADDR + 0xe06)
|
||||
#define MX3_NF_FCMD (MX3_NF_BASE_ADDR + 0xe08)
|
||||
#define MX3_NF_BUFCFG (MX3_NF_BASE_ADDR + 0xe0a)
|
||||
#define MX3_NF_ECCSTATUS (MX3_NF_BASE_ADDR + 0xe0c)
|
||||
#define MX3_NF_ECCMAINPOS (MX3_NF_BASE_ADDR + 0xe0e)
|
||||
#define MX3_NF_ECCSPAREPOS (MX3_NF_BASE_ADDR + 0xe10)
|
||||
#define MX3_NF_FWP (MX3_NF_BASE_ADDR + 0xe12)
|
||||
#define MX3_NF_LOCKSTART (MX3_NF_BASE_ADDR + 0xe14)
|
||||
#define MX3_NF_LOCKEND (MX3_NF_BASE_ADDR + 0xe16)
|
||||
#define MX3_NF_FWPSTATUS (MX3_NF_BASE_ADDR + 0xe18)
|
||||
/*
|
||||
* all bits not marked as self-clearing bit
|
||||
*/
|
||||
#define MX3_NF_CFG1 (MX3_NF_BASE_ADDR + 0xe1a)
|
||||
#define MX3_NF_CFG2 (MX3_NF_BASE_ADDR + 0xe1c)
|
||||
|
||||
#define MX3_NF_MAIN_BUFFER0 (MX3_NF_BASE_ADDR + 0x0000)
|
||||
#define MX3_NF_MAIN_BUFFER1 (MX3_NF_BASE_ADDR + 0x0200)
|
||||
#define MX3_NF_MAIN_BUFFER2 (MX3_NF_BASE_ADDR + 0x0400)
|
||||
#define MX3_NF_MAIN_BUFFER3 (MX3_NF_BASE_ADDR + 0x0600)
|
||||
#define MX3_NF_SPARE_BUFFER0 (MX3_NF_BASE_ADDR + 0x0800)
|
||||
#define MX3_NF_SPARE_BUFFER1 (MX3_NF_BASE_ADDR + 0x0810)
|
||||
#define MX3_NF_SPARE_BUFFER2 (MX3_NF_BASE_ADDR + 0x0820)
|
||||
#define MX3_NF_SPARE_BUFFER3 (MX3_NF_BASE_ADDR + 0x0830)
|
||||
#define MX3_NF_MAIN_BUFFER_LEN 512
|
||||
#define MX3_NF_SPARE_BUFFER_LEN 16
|
||||
#define MX3_NF_LAST_BUFFER_ADDR ((MX3_NF_SPARE_BUFFER3) + MX3_NF_SPARE_BUFFER_LEN - 2)
|
||||
|
||||
/* bits in MX3_NF_CFG1 register */
|
||||
#define MX3_NF_BIT_SPARE_ONLY_EN (1<<2)
|
||||
#define MX3_NF_BIT_ECC_EN (1<<3)
|
||||
#define MX3_NF_BIT_INT_DIS (1<<4)
|
||||
#define MX3_NF_BIT_BE_EN (1<<5)
|
||||
#define MX3_NF_BIT_RESET_EN (1<<6)
|
||||
#define MX3_NF_BIT_FORCE_CE (1<<7)
|
||||
|
||||
/* bits in MX3_NF_CFG2 register */
|
||||
|
||||
/*Flash Command Input*/
|
||||
#define MX3_NF_BIT_OP_FCI (1<<0)
|
||||
/*
|
||||
* Flash Address Input
|
||||
*/
|
||||
#define MX3_NF_BIT_OP_FAI (1<<1)
|
||||
/*
|
||||
* Flash Data Input
|
||||
*/
|
||||
#define MX3_NF_BIT_OP_FDI (1<<2)
|
||||
|
||||
/* see "enum mx_dataout_type" below */
|
||||
#define MX3_NF_BIT_DATAOUT_TYPE(x) ((x)<<3)
|
||||
#define MX3_NF_BIT_OP_DONE (1<<15)
|
||||
|
||||
#define MX3_CCM_CGR2 0x53f80028
|
||||
#define MX3_GPR 0x43fac008
|
||||
#define MX3_PCSR 0x53f8000c
|
||||
|
||||
enum mx_dataout_type
|
||||
{
|
||||
MX3_NF_DATAOUT_PAGE = 1,
|
||||
MX3_NF_DATAOUT_NANDID = 2,
|
||||
MX3_NF_DATAOUT_NANDSTATUS = 4,
|
||||
};
|
||||
enum mx_nf_finalize_action
|
||||
{
|
||||
MX3_NF_FIN_NONE,
|
||||
MX3_NF_FIN_DATAOUT,
|
||||
};
|
||||
|
||||
struct mx3_nf_flags
|
||||
{
|
||||
unsigned host_little_endian:1;
|
||||
unsigned target_little_endian:1;
|
||||
unsigned nand_readonly:1;
|
||||
unsigned one_kb_sram:1;
|
||||
unsigned hw_ecc_enabled:1;
|
||||
};
|
||||
|
||||
typedef struct mx3_nf_controller_s
|
||||
{
|
||||
struct target_s *target;
|
||||
enum mx_dataout_type optype;
|
||||
enum mx_nf_finalize_action fin;
|
||||
struct mx3_nf_flags flags;
|
||||
} mx3_nf_controller_t;
|
||||
@@ -52,6 +52,7 @@ extern nand_flash_controller_t s3c2410_nand_controller;
|
||||
extern nand_flash_controller_t s3c2412_nand_controller;
|
||||
extern nand_flash_controller_t s3c2440_nand_controller;
|
||||
extern nand_flash_controller_t s3c2443_nand_controller;
|
||||
extern nand_flash_controller_t imx31_nand_flash_controller;
|
||||
|
||||
/* extern nand_flash_controller_t boundary_scan_nand_controller; */
|
||||
|
||||
@@ -64,6 +65,7 @@ static nand_flash_controller_t *nand_flash_controllers[] =
|
||||
&s3c2412_nand_controller,
|
||||
&s3c2440_nand_controller,
|
||||
&s3c2443_nand_controller,
|
||||
&imx31_nand_flash_controller,
|
||||
/* &boundary_scan_nand_controller, */
|
||||
NULL
|
||||
};
|
||||
@@ -307,8 +309,9 @@ int nand_init(struct command_context_s *cmd_ctx)
|
||||
"identify NAND flash device <num>");
|
||||
register_command(cmd_ctx, nand_cmd, "check_bad_blocks", handle_nand_check_bad_blocks_command, COMMAND_EXEC,
|
||||
"check NAND flash device <num> for bad blocks [<offset> <length>]");
|
||||
register_command(cmd_ctx, nand_cmd, "erase", handle_nand_erase_command, COMMAND_EXEC,
|
||||
"erase blocks on NAND flash device <num> <offset> <length>");
|
||||
register_command(cmd_ctx, nand_cmd, "erase",
|
||||
handle_nand_erase_command, COMMAND_EXEC,
|
||||
"erase blocks on NAND flash device <num> [<offset> <length>]");
|
||||
register_command(cmd_ctx, nand_cmd, "dump", handle_nand_dump_command, COMMAND_EXEC,
|
||||
"dump from NAND flash device <num> <filename> "
|
||||
"<offset> <length> [oob_raw | oob_only]");
|
||||
@@ -635,7 +638,7 @@ int nand_probe(struct nand_device_s *device)
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
int nand_erase(struct nand_device_s *device, int first_block, int last_block)
|
||||
static int nand_erase(struct nand_device_s *device, int first_block, int last_block)
|
||||
{
|
||||
int i;
|
||||
uint32_t page;
|
||||
@@ -710,8 +713,11 @@ int nand_erase(struct nand_device_s *device, int first_block, int last_block)
|
||||
|
||||
if (status & 0x1)
|
||||
{
|
||||
LOG_ERROR("erase operation didn't pass, status: 0x%2.2x", status);
|
||||
return ERROR_NAND_OPERATION_FAILED;
|
||||
LOG_ERROR("didn't erase %sblock %d; status: 0x%2.2x",
|
||||
(device->blocks[i].is_bad == 1)
|
||||
? "bad " : "",
|
||||
i, status);
|
||||
/* continue; other blocks might still be erasable */
|
||||
}
|
||||
|
||||
device->blocks[i].is_erased = 1;
|
||||
@@ -1073,8 +1079,12 @@ int handle_nand_list_command(struct command_context_s *cmd_ctx, char *cmd, char
|
||||
for (p = nand_devices, i = 0; p; p = p->next, i++)
|
||||
{
|
||||
if (p->device)
|
||||
command_print(cmd_ctx, "#%i: %s (%s) pagesize: %i, buswidth: %i, erasesize: %i",
|
||||
i, p->device->name, p->manufacturer->name, p->page_size, p->bus_width, p->erase_size);
|
||||
command_print(cmd_ctx, "#%i: %s (%s) "
|
||||
"pagesize: %i, buswidth: %i,\n\t"
|
||||
"blocksize: %i, blocks: %i",
|
||||
i, p->device->name, p->manufacturer->name,
|
||||
p->page_size, p->bus_width,
|
||||
p->erase_size, p->num_blocks);
|
||||
else
|
||||
command_print(cmd_ctx, "#%i: not probed", i);
|
||||
}
|
||||
@@ -1195,7 +1205,7 @@ static int handle_nand_erase_command(struct command_context_s *cmd_ctx, char *cm
|
||||
nand_device_t *p;
|
||||
int retval;
|
||||
|
||||
if (argc != 3)
|
||||
if (argc != 1 && argc != 3)
|
||||
{
|
||||
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||
|
||||
@@ -1208,27 +1218,37 @@ static int handle_nand_erase_command(struct command_context_s *cmd_ctx, char *cm
|
||||
unsigned long offset;
|
||||
unsigned long length;
|
||||
|
||||
offset = strtoul(args[1], &cp, 0);
|
||||
if (*cp || offset == ULONG_MAX || offset % p->erase_size)
|
||||
{
|
||||
return ERROR_INVALID_ARGUMENTS;
|
||||
}
|
||||
offset /= p->erase_size;
|
||||
/* erase specified part of the chip; or else everything */
|
||||
if (argc == 3) {
|
||||
unsigned long size = p->erase_size * p->num_blocks;
|
||||
|
||||
length = strtoul(args[2], &cp, 0);
|
||||
if (*cp || length == ULONG_MAX || length % p->erase_size)
|
||||
{
|
||||
return ERROR_INVALID_ARGUMENTS;
|
||||
}
|
||||
length -= 1;
|
||||
length /= p->erase_size;
|
||||
offset = strtoul(args[1], &cp, 0);
|
||||
if (*cp || (offset == ULONG_MAX)
|
||||
|| (offset % p->erase_size) != 0
|
||||
|| offset >= size)
|
||||
return ERROR_INVALID_ARGUMENTS;
|
||||
|
||||
retval = nand_erase(p, offset, offset + length);
|
||||
length = strtoul(args[2], &cp, 0);
|
||||
if (*cp || (length == ULONG_MAX)
|
||||
|| (length == 0)
|
||||
|| (length % p->erase_size) != 0
|
||||
|| (length + offset) > size)
|
||||
return ERROR_INVALID_ARGUMENTS;
|
||||
|
||||
offset /= p->erase_size;
|
||||
length /= p->erase_size;
|
||||
} else {
|
||||
offset = 0;
|
||||
length = p->num_blocks;
|
||||
}
|
||||
|
||||
retval = nand_erase(p, offset, offset + length - 1);
|
||||
if (retval == ERROR_OK)
|
||||
{
|
||||
command_print(cmd_ctx, "successfully erased blocks "
|
||||
"%lu to %lu on NAND flash device '%s'",
|
||||
offset, offset + length, p->device->name);
|
||||
command_print(cmd_ctx, "erased blocks %lu to %lu "
|
||||
"on NAND flash device #%s '%s'",
|
||||
offset, offset + length,
|
||||
args[0], p->device->name);
|
||||
}
|
||||
else if (retval == ERROR_NAND_OPERATION_FAILED)
|
||||
{
|
||||
|
||||
@@ -223,5 +223,6 @@ extern int nand_init(struct command_context_s *cmd_ctx);
|
||||
#define ERROR_NAND_OPERATION_NOT_SUPPORTED (-1103)
|
||||
#define ERROR_NAND_DEVICE_NOT_PROBED (-1104)
|
||||
#define ERROR_NAND_ERROR_CORRECTION_FAILED (-1105)
|
||||
#define ERROR_NAND_NO_BUFFER (-1106)
|
||||
|
||||
#endif /* NAND_H */
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
* Copyright (C) 2009 Marvell Semiconductor, Inc.
|
||||
*
|
||||
* Authors: Lennert Buytenhek <buytenh@wantstofly.org>
|
||||
* Nicolas Pitre <nico@cam.org>
|
||||
* Nicolas Pitre <nico@fluxnic.net>
|
||||
*
|
||||
* This file is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
|
||||
@@ -32,7 +32,7 @@
|
||||
#define ERASE_REGION(num, size) (((size/256) << 16) | (num-1))
|
||||
|
||||
/* non-CFI compatible flashes */
|
||||
non_cfi_t non_cfi_flashes[] = {
|
||||
static non_cfi_t non_cfi_flashes[] = {
|
||||
{
|
||||
.mfr = CFI_MFR_SST,
|
||||
.id = 0xd4,
|
||||
@@ -140,7 +140,10 @@ non_cfi_t non_cfi_flashes[] = {
|
||||
|
||||
/* SST 39VF* do not support DQ5 status polling - this currently is
|
||||
only supported by the host algorithm, not by the target code using
|
||||
the work area. */
|
||||
the work area.
|
||||
Only true for 8-bit and 32-bit wide memories. 16-bit wide memories
|
||||
without DQ5 status polling are supported by the target code.
|
||||
*/
|
||||
{
|
||||
.mfr = CFI_MFR_SST,
|
||||
.id = 0x2782, /* SST39xF160 */
|
||||
|
||||
@@ -35,7 +35,6 @@ typedef struct non_cfi_s
|
||||
uint8_t status_poll_mask;
|
||||
} non_cfi_t;
|
||||
|
||||
extern non_cfi_t non_cfi_flashes[];
|
||||
extern void cfi_fixup_non_cfi(flash_bank_t *bank);
|
||||
|
||||
#endif /* NON_CFI_H */
|
||||
|
||||
@@ -26,15 +26,15 @@
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "nand.h"
|
||||
#include "arm_nandio.h"
|
||||
#include "armv4_5.h"
|
||||
#include "binarybuffer.h"
|
||||
|
||||
|
||||
typedef struct orion_nand_controller_s
|
||||
{
|
||||
struct target_s *target;
|
||||
working_area_t *copy_area;
|
||||
|
||||
struct arm_nand_data io;
|
||||
|
||||
uint32_t cmd;
|
||||
uint32_t addr;
|
||||
@@ -99,78 +99,14 @@ static int orion_nand_slow_block_write(struct nand_device_s *device, uint8_t *da
|
||||
static int orion_nand_fast_block_write(struct nand_device_s *device, uint8_t *data, int size)
|
||||
{
|
||||
orion_nand_controller_t *hw = device->controller_priv;
|
||||
target_t *target = hw->target;
|
||||
armv4_5_algorithm_t algo;
|
||||
reg_param_t reg_params[3];
|
||||
uint32_t target_buf;
|
||||
int retval;
|
||||
|
||||
static const uint32_t code[] = {
|
||||
0xe4d13001, /* ldrb r3, [r1], #1 */
|
||||
0xe5c03000, /* strb r3, [r0] */
|
||||
0xe2522001, /* subs r2, r2, #1 */
|
||||
0x1afffffb, /* bne 0 */
|
||||
0xeafffffe, /* b . */
|
||||
};
|
||||
int code_size = sizeof(code);
|
||||
hw->io.chunk_size = device->page_size;
|
||||
|
||||
if (!hw->copy_area) {
|
||||
uint8_t code_buf[code_size];
|
||||
int i;
|
||||
retval = arm_nandwrite(&hw->io, data, size);
|
||||
if (retval == ERROR_NAND_NO_BUFFER)
|
||||
retval = orion_nand_slow_block_write(device, data, size);
|
||||
|
||||
/* make sure we have a working area */
|
||||
if (target_alloc_working_area(target,
|
||||
code_size + device->page_size,
|
||||
&hw->copy_area) != ERROR_OK)
|
||||
{
|
||||
return orion_nand_slow_block_write(device, data, size);
|
||||
}
|
||||
|
||||
/* copy target instructions to target endianness */
|
||||
for (i = 0; i < code_size/4; i++)
|
||||
target_buffer_set_u32(target, code_buf + i*4, code[i]);
|
||||
|
||||
/* write code to working area */
|
||||
retval = target_write_memory(target,
|
||||
hw->copy_area->address,
|
||||
4, code_size/4, code_buf);
|
||||
if (retval != ERROR_OK)
|
||||
return retval;
|
||||
}
|
||||
|
||||
/* copy data to target's memory */
|
||||
target_buf = hw->copy_area->address + code_size;
|
||||
retval = target_bulk_write_memory(target, target_buf, size/4, data);
|
||||
if (retval == ERROR_OK && size & 3) {
|
||||
retval = target_write_memory(target,
|
||||
target_buf + (size & ~3),
|
||||
1, size & 3, data + (size & ~3));
|
||||
}
|
||||
if (retval != ERROR_OK)
|
||||
return retval;
|
||||
|
||||
algo.common_magic = ARMV4_5_COMMON_MAGIC;
|
||||
algo.core_mode = ARMV4_5_MODE_SVC;
|
||||
algo.core_state = ARMV4_5_STATE_ARM;
|
||||
|
||||
init_reg_param(®_params[0], "r0", 32, PARAM_IN);
|
||||
init_reg_param(®_params[1], "r1", 32, PARAM_IN);
|
||||
init_reg_param(®_params[2], "r2", 32, PARAM_IN);
|
||||
|
||||
buf_set_u32(reg_params[0].value, 0, 32, hw->data);
|
||||
buf_set_u32(reg_params[1].value, 0, 32, target_buf);
|
||||
buf_set_u32(reg_params[2].value, 0, 32, size);
|
||||
|
||||
retval = target_run_algorithm(target, 0, NULL, 3, reg_params,
|
||||
hw->copy_area->address,
|
||||
hw->copy_area->address + code_size - 4,
|
||||
1000, &algo);
|
||||
if (retval != ERROR_OK)
|
||||
LOG_ERROR("error executing hosted NAND write");
|
||||
|
||||
destroy_reg_param(®_params[0]);
|
||||
destroy_reg_param(®_params[1]);
|
||||
destroy_reg_param(®_params[2]);
|
||||
return retval;
|
||||
}
|
||||
|
||||
@@ -198,7 +134,7 @@ int orion_nand_device_command(struct command_context_s *cmd_ctx, char *cmd,
|
||||
uint8_t ale, cle;
|
||||
|
||||
if (argc != 3) {
|
||||
LOG_ERROR("arguments must be: <target_number> <NAND_address>\n");
|
||||
LOG_ERROR("arguments must be: <target_id> <NAND_address>\n");
|
||||
return ERROR_NAND_DEVICE_INVALID;
|
||||
}
|
||||
|
||||
@@ -224,6 +160,9 @@ int orion_nand_device_command(struct command_context_s *cmd_ctx, char *cmd,
|
||||
hw->cmd = base + (1 << cle);
|
||||
hw->addr = base + (1 << ale);
|
||||
|
||||
hw->io.target = hw->target;
|
||||
hw->io.data = hw->data;
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
|
||||
@@ -257,7 +257,10 @@ static int stellaris_flash_bank_command(struct command_context_s *cmd_ctx, char
|
||||
/* part wasn't probed for info yet */
|
||||
stellaris_info->did1 = 0;
|
||||
|
||||
/* TODO Use an optional main oscillator clock rate in kHz from arg[6] */
|
||||
/* TODO Specify the main crystal speed in kHz using an optional
|
||||
* argument; ditto, the speed of an external oscillator used
|
||||
* instead of a crystal. Avoid programming flash using IOSC.
|
||||
*/
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
@@ -294,7 +297,8 @@ static int stellaris_info(struct flash_bank_s *bank, char *buf, int buf_size)
|
||||
}
|
||||
printed = snprintf(buf,
|
||||
buf_size,
|
||||
"\nLMI Stellaris information: Chip is class %i(%s) %s v%c.%i\n",
|
||||
"\nTI/LMI Stellaris information: Chip is "
|
||||
"class %i (%s) %s rev %c%i\n",
|
||||
device_class,
|
||||
StellarisClassname[device_class],
|
||||
stellaris_info->target_name,
|
||||
@@ -305,10 +309,11 @@ static int stellaris_info(struct flash_bank_s *bank, char *buf, int buf_size)
|
||||
|
||||
printed = snprintf(buf,
|
||||
buf_size,
|
||||
"did1: 0x%8.8" PRIx32 ", arch: 0x%4.4" PRIx32 ", eproc: %s, ramsize:%ik, flashsize: %ik\n",
|
||||
"did1: 0x%8.8" PRIx32 ", arch: 0x%4.4" PRIx32
|
||||
", eproc: %s, ramsize: %ik, flashsize: %ik\n",
|
||||
stellaris_info->did1,
|
||||
stellaris_info->did1,
|
||||
"ARMV7M",
|
||||
"ARMv7M",
|
||||
(int)((1 + ((stellaris_info->dc0 >> 16) & 0xFFFF))/4),
|
||||
(int)((1 + (stellaris_info->dc0 & 0xFFFF))*2));
|
||||
buf += printed;
|
||||
@@ -316,9 +321,12 @@ static int stellaris_info(struct flash_bank_s *bank, char *buf, int buf_size)
|
||||
|
||||
printed = snprintf(buf,
|
||||
buf_size,
|
||||
"master clock(estimated): %ikHz, rcc is 0x%" PRIx32 " \n",
|
||||
"master clock: %ikHz%s, "
|
||||
"rcc is 0x%" PRIx32 ", rcc2 is 0x%" PRIx32 "\n",
|
||||
(int)(stellaris_info->mck_freq / 1000),
|
||||
stellaris_info->rcc);
|
||||
stellaris_info->mck_desc,
|
||||
stellaris_info->rcc,
|
||||
stellaris_info->rcc2);
|
||||
buf += printed;
|
||||
buf_size -= printed;
|
||||
|
||||
@@ -353,38 +361,103 @@ static uint32_t stellaris_get_flash_status(flash_bank_t *bank)
|
||||
|
||||
/** Read clock configuration and set stellaris_info->usec_clocks*/
|
||||
|
||||
static const unsigned rcc_xtal[32] = {
|
||||
[0x00] = 1000000, /* no pll */
|
||||
[0x01] = 1843200, /* no pll */
|
||||
[0x02] = 2000000, /* no pll */
|
||||
[0x03] = 2457600, /* no pll */
|
||||
|
||||
[0x04] = 3579545,
|
||||
[0x05] = 3686400,
|
||||
[0x06] = 4000000, /* usb */
|
||||
[0x07] = 4096000,
|
||||
|
||||
[0x08] = 4915200,
|
||||
[0x09] = 5000000, /* usb */
|
||||
[0x0a] = 5120000,
|
||||
[0x0b] = 6000000, /* (reset) usb */
|
||||
|
||||
[0x0c] = 6144000,
|
||||
[0x0d] = 7372800,
|
||||
[0x0e] = 8000000, /* usb */
|
||||
[0x0f] = 8192000,
|
||||
|
||||
/* parts before DustDevil use just 4 bits for xtal spec */
|
||||
|
||||
[0x10] = 10000000, /* usb */
|
||||
[0x11] = 12000000, /* usb */
|
||||
[0x12] = 12288000,
|
||||
[0x13] = 13560000,
|
||||
|
||||
[0x14] = 14318180,
|
||||
[0x15] = 16000000, /* usb */
|
||||
[0x16] = 16384000,
|
||||
};
|
||||
|
||||
static void stellaris_read_clock_info(flash_bank_t *bank)
|
||||
{
|
||||
stellaris_flash_bank_t *stellaris_info = bank->driver_priv;
|
||||
target_t *target = bank->target;
|
||||
uint32_t rcc, pllcfg, sysdiv, usesysdiv, bypass, oscsrc;
|
||||
uint32_t rcc, rcc2, pllcfg, sysdiv, usesysdiv, bypass, oscsrc;
|
||||
unsigned xtal;
|
||||
unsigned long mainfreq;
|
||||
|
||||
target_read_u32(target, SCB_BASE | RCC, &rcc);
|
||||
LOG_DEBUG("Stellaris RCC %" PRIx32 "", rcc);
|
||||
|
||||
target_read_u32(target, SCB_BASE | RCC2, &rcc2);
|
||||
LOG_DEBUG("Stellaris RCC2 %" PRIx32 "", rcc);
|
||||
|
||||
target_read_u32(target, SCB_BASE | PLLCFG, &pllcfg);
|
||||
LOG_DEBUG("Stellaris PLLCFG %" PRIx32 "", pllcfg);
|
||||
|
||||
stellaris_info->rcc = rcc;
|
||||
stellaris_info->rcc = rcc2;
|
||||
|
||||
sysdiv = (rcc >> 23) & 0xF;
|
||||
usesysdiv = (rcc >> 22) & 0x1;
|
||||
bypass = (rcc >> 11) & 0x1;
|
||||
oscsrc = (rcc >> 4) & 0x3;
|
||||
/* xtal = (rcc >> 6)&0xF; */
|
||||
xtal = (rcc >> 6) & stellaris_info->xtal_mask;
|
||||
|
||||
/* NOTE: post-Sandstorm parts have RCC2 which may override
|
||||
* parts of RCC ... with more sysdiv options, option for
|
||||
* 32768 Hz mainfreq, PLL controls. On Sandstorm it reads
|
||||
* as zero, so the "use RCC2" flag is always clear.
|
||||
*/
|
||||
if (rcc2 & (1 << 31)) {
|
||||
sysdiv = (rcc2 >> 23) & 0x3F;
|
||||
bypass = (rcc2 >> 11) & 0x1;
|
||||
oscsrc = (rcc2 >> 4) & 0x7;
|
||||
|
||||
/* FIXME Tempest parts have an additional lsb for
|
||||
* fractional sysdiv (200 MHz / 2.5 == 80 MHz)
|
||||
*/
|
||||
}
|
||||
|
||||
stellaris_info->mck_desc = "";
|
||||
|
||||
switch (oscsrc)
|
||||
{
|
||||
case 0:
|
||||
mainfreq = 6000000; /* Default xtal */
|
||||
case 0: /* MOSC */
|
||||
mainfreq = rcc_xtal[xtal];
|
||||
break;
|
||||
case 1:
|
||||
mainfreq = 22500000; /* Internal osc. 15 MHz +- 50% */
|
||||
case 1: /* IOSC */
|
||||
mainfreq = stellaris_info->iosc_freq;
|
||||
stellaris_info->mck_desc = stellaris_info->iosc_desc;
|
||||
break;
|
||||
case 2:
|
||||
mainfreq = 5625000; /* Internal osc. / 4 */
|
||||
case 2: /* IOSC/4 */
|
||||
mainfreq = stellaris_info->iosc_freq / 4;
|
||||
stellaris_info->mck_desc = stellaris_info->iosc_desc;
|
||||
break;
|
||||
case 3:
|
||||
LOG_WARNING("Invalid oscsrc (3) in rcc register");
|
||||
mainfreq = 6000000;
|
||||
case 3: /* lowspeed */
|
||||
/* Sandstorm doesn't have this 30K +/- 30% osc */
|
||||
mainfreq = 30000;
|
||||
stellaris_info->mck_desc = " (±30%)";
|
||||
break;
|
||||
case 8: /* hibernation osc */
|
||||
/* not all parts support hibernation */
|
||||
mainfreq = 32768;
|
||||
break;
|
||||
|
||||
default: /* NOTREACHED */
|
||||
@@ -392,8 +465,11 @@ static void stellaris_read_clock_info(flash_bank_t *bank)
|
||||
break;
|
||||
}
|
||||
|
||||
/* PLL is used if it's not bypassed; its output is 200 MHz
|
||||
* even when it runs at 400 MHz (adds divide-by-two stage).
|
||||
*/
|
||||
if (!bypass)
|
||||
mainfreq = 200000000; /* PLL out frec */
|
||||
mainfreq = 200000000;
|
||||
|
||||
if (usesysdiv)
|
||||
stellaris_info->mck_freq = mainfreq/(1 + sysdiv);
|
||||
@@ -487,6 +563,48 @@ static int stellaris_read_part_info(struct flash_bank_s *bank)
|
||||
LOG_WARNING("Unknown did1 version/family, cannot positively identify target as a Stellaris");
|
||||
}
|
||||
|
||||
/* For Sandstorm, Fury, DustDevil: current data sheets say IOSC
|
||||
* is 12 MHz, but some older parts have 15 MHz. A few data sheets
|
||||
* even give _both_ numbers! We'll use current numbers; IOSC is
|
||||
* always approximate.
|
||||
*
|
||||
* For Tempest: IOSC is calibrated, 16 MHz
|
||||
*/
|
||||
stellaris_info->iosc_freq = 12000000;
|
||||
stellaris_info->iosc_desc = " (±30%)";
|
||||
stellaris_info->xtal_mask = 0x0f;
|
||||
|
||||
switch ((did0 >> 28) & 0x7) {
|
||||
case 0: /* Sandstorm */
|
||||
/*
|
||||
* Current (2009-August) parts seem to be rev C2 and use 12 MHz.
|
||||
* Parts before rev C0 used 15 MHz; some C0 parts use 15 MHz
|
||||
* (LM3S618), but some other C0 parts are 12 MHz (LM3S811).
|
||||
*/
|
||||
if (((did0 >> 8) & 0xff) < 2) {
|
||||
stellaris_info->iosc_freq = 15000000;
|
||||
stellaris_info->iosc_desc = " (±50%)";
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
switch ((did0 >> 16) & 0xff) {
|
||||
case 1: /* Fury */
|
||||
break;
|
||||
case 4: /* Tempest */
|
||||
stellaris_info->iosc_freq = 16000000; /* +/- 1% */
|
||||
stellaris_info->iosc_desc = " (±1%)";
|
||||
/* FALL THROUGH */
|
||||
case 3: /* DustDevil */
|
||||
stellaris_info->xtal_mask = 0x1f;
|
||||
break;
|
||||
default:
|
||||
LOG_WARNING("Unknown did0 class");
|
||||
}
|
||||
default:
|
||||
break;
|
||||
LOG_WARNING("Unknown did0 version");
|
||||
}
|
||||
|
||||
for (i = 0; StellarisParts[i].partno; i++)
|
||||
{
|
||||
if (StellarisParts[i].partno == ((did1 >> 16) & 0xFF))
|
||||
@@ -547,7 +665,7 @@ static int stellaris_protect_check(struct flash_bank_s *bank)
|
||||
|
||||
if (stellaris_info->did1 == 0)
|
||||
{
|
||||
LOG_WARNING("Cannot identify target as an AT91SAM");
|
||||
LOG_WARNING("Cannot identify target as Stellaris");
|
||||
return ERROR_FLASH_OPERATION_FAILED;
|
||||
}
|
||||
|
||||
@@ -799,8 +917,8 @@ static int stellaris_write_block(struct flash_bank_s *bank, uint8_t *buffer, uin
|
||||
buf_set_u32(reg_params[0].value, 0, 32, source->address);
|
||||
buf_set_u32(reg_params[1].value, 0, 32, address);
|
||||
buf_set_u32(reg_params[2].value, 0, 32, 4*thisrun_count);
|
||||
LOG_INFO("Algorithm flash write %" PRIi32 " words to 0x%" PRIx32 ", %" PRIi32 " remaining", thisrun_count, address, wcount);
|
||||
LOG_DEBUG("Algorithm flash write %" PRIi32 " words to 0x%" PRIx32 ", %" PRIi32 " remaining", thisrun_count, address, wcount);
|
||||
LOG_INFO("Algorithm flash write %" PRIi32 " words to 0x%" PRIx32 ", %" PRIi32 " remaining", thisrun_count, address, (wcount - thisrun_count));
|
||||
LOG_DEBUG("Algorithm flash write %" PRIi32 " words to 0x%" PRIx32 ", %" PRIi32 " remaining", thisrun_count, address, (wcount - thisrun_count));
|
||||
if ((retval = target_run_algorithm(target, 0, NULL, 3, reg_params, write_algorithm->address, write_algorithm->address + sizeof(stellaris_write_code)-10, 10000, &armv7m_info)) != ERROR_OK)
|
||||
{
|
||||
LOG_ERROR("error executing stellaris flash write algorithm");
|
||||
|
||||
@@ -45,8 +45,13 @@ typedef struct stellaris_flash_bank_s
|
||||
|
||||
/* main clock status */
|
||||
uint32_t rcc;
|
||||
uint32_t rcc2;
|
||||
uint8_t mck_valid;
|
||||
uint8_t xtal_mask;
|
||||
uint32_t iosc_freq;
|
||||
uint32_t mck_freq;
|
||||
const char *iosc_desc;
|
||||
const char *mck_desc;
|
||||
} stellaris_flash_bank_t;
|
||||
|
||||
/* STELLARIS control registers */
|
||||
@@ -62,6 +67,7 @@ typedef struct stellaris_flash_bank_s
|
||||
#define RIS 0x050
|
||||
#define RCC 0x060
|
||||
#define PLLCFG 0x064
|
||||
#define RCC2 0x070
|
||||
|
||||
#define FMPRE 0x130
|
||||
#define FMPPE 0x134
|
||||
|
||||
@@ -410,7 +410,7 @@ static int stm32x_protect(struct flash_bank_s *bank, int set, int first, int las
|
||||
|
||||
if ((first && (first % stm32x_info->ppage_size)) || ((last + 1) && (last + 1) % stm32x_info->ppage_size))
|
||||
{
|
||||
LOG_WARNING("sector start/end incorrect - stm32 has %dK sector protection", stm32x_info->ppage_size);
|
||||
LOG_WARNING("Error: start and end sectors must be on a %d sector boundary", stm32x_info->ppage_size);
|
||||
return ERROR_FLASH_SECTOR_INVALID;
|
||||
}
|
||||
|
||||
|
||||
@@ -1254,7 +1254,8 @@ static int str9xpec_handle_flash_disable_turbo_command(struct command_context_s
|
||||
return ERROR_FAIL;
|
||||
|
||||
/* exit turbo mode via RESET */
|
||||
str9xpec_set_instr(tap, ISC_NOOP, TAP_RESET);
|
||||
str9xpec_set_instr(tap, ISC_NOOP, TAP_IDLE);
|
||||
jtag_add_tlr();
|
||||
jtag_execute_queue();
|
||||
|
||||
/* restore previous scan chain */
|
||||
|
||||
@@ -52,12 +52,16 @@ noinst_HEADERS = \
|
||||
startup.tcl \
|
||||
bin2char.c
|
||||
|
||||
bin2char$(EXEEXT_FOR_BUILD): bin2char.c
|
||||
BIN2C = bin2char$(EXEEXT_FOR_BUILD)
|
||||
|
||||
BUILT_SOURCES = $(BIN2C)
|
||||
|
||||
$(BIN2C): bin2char.c
|
||||
${CC_FOR_BUILD} ${CFLAGS_FOR_BUILD} $(srcdir)/bin2char.c -o $@
|
||||
|
||||
# Convert .tcl to cfile
|
||||
startup_tcl.c: startup.tcl bin2char$(EXEEXT_FOR_BUILD)
|
||||
./bin2char$(EXEEXT_FOR_BUILD) startup_tcl < $(srcdir)/startup.tcl > $@
|
||||
startup_tcl.c: startup.tcl $(BIN2C)
|
||||
./$(BIN2C) startup_tcl < $(srcdir)/startup.tcl > $@
|
||||
|
||||
# add startup_tcl.c to make clean list
|
||||
CLEANFILES = startup_tcl.c bin2char$(EXEEXT_FOR_BUILD)
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* Copyright (C) 2004, 2005 by Dominic Rath *
|
||||
* Dominic.Rath@gmx.de *
|
||||
* *
|
||||
* Copyright (C) 2007,2008 Øyvind Harboe *
|
||||
* Copyright (C) 2007,2008 Øyvind Harboe *
|
||||
* oyvind.harboe@zylin.com *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* Copyright (C) 2004, 2005 by Dominic Rath *
|
||||
* Dominic.Rath@gmx.de *
|
||||
* *
|
||||
* Copyright (C) 2007,2008 Øyvind Harboe *
|
||||
* Copyright (C) 2007,2008 Øyvind Harboe *
|
||||
* oyvind.harboe@zylin.com *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
@@ -86,7 +86,7 @@ extern char* buf_to_str(const uint8_t *buf, int size, int radix);
|
||||
struct scan_field_s;
|
||||
extern int buf_to_u32_handler(uint8_t *in_buf, void *priv, struct scan_field_s *field);
|
||||
|
||||
#define CEIL(m, n) ((m + n - 1) / n)
|
||||
#define CEIL(m, n) (((m) + (n) - 1) / (n))
|
||||
|
||||
/* read a uint32_t from a buffer in target memory endianness */
|
||||
static inline uint32_t fast_target_buffer_get_u32(const uint8_t *buffer, int little)
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* Copyright (C) 2005 by Dominic Rath *
|
||||
* Dominic.Rath@gmx.de *
|
||||
* *
|
||||
* Copyright (C) 2007,2008 <EFBFBD>yvind Harboe *
|
||||
* Copyright (C) 2007,2008 Øyvind Harboe *
|
||||
* oyvind.harboe@zylin.com *
|
||||
* *
|
||||
* Copyright (C) 2008, Duane Ellis *
|
||||
@@ -117,6 +117,10 @@ static int script_command(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
|
||||
words[i] = strdup(w);
|
||||
if (words[i] == NULL)
|
||||
{
|
||||
int j;
|
||||
for (j = 0; j < i; j++)
|
||||
free(words[j]);
|
||||
free(words);
|
||||
return JIM_ERR;
|
||||
}
|
||||
}
|
||||
@@ -740,8 +744,6 @@ command_context_t* command_init()
|
||||
interp->cb_fflush = openocd_jim_fflush;
|
||||
interp->cb_fgets = openocd_jim_fgets;
|
||||
|
||||
add_default_dirs();
|
||||
|
||||
#if !BUILD_ECOSBOARD
|
||||
Jim_EventLoopOnLoad(interp);
|
||||
#endif
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* Copyright (C) 2005 by Dominic Rath *
|
||||
* Dominic.Rath@gmx.de *
|
||||
* *
|
||||
* Copyright (C) 2007,2008 Øyvind Harboe *
|
||||
* Copyright (C) 2007,2008 Øyvind Harboe *
|
||||
* oyvind.harboe@zylin.com *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
@@ -35,6 +35,15 @@
|
||||
#include "jim.h"
|
||||
#endif
|
||||
|
||||
/* To achieve C99 printf compatibility in MinGW, gnu_printf should be
|
||||
* used for __attribute__((format( ... ))), with GCC v4.4 or later
|
||||
*/
|
||||
#if (defined(IS_MINGW) && (((__GNUC__ << 16) + __GNUC_MINOR__) >= 0x00040004))
|
||||
#define PRINTF_ATTRIBUTE_FORMAT gnu_printf
|
||||
#else
|
||||
#define PRINTF_ATTRIBUTE_FORMAT printf
|
||||
#endif
|
||||
|
||||
enum command_mode
|
||||
{
|
||||
COMMAND_EXEC,
|
||||
@@ -85,12 +94,12 @@ extern command_context_t* command_init(void);
|
||||
extern int command_done(command_context_t *context);
|
||||
|
||||
extern void command_print(command_context_t *context, const char *format, ...)
|
||||
__attribute__ ((format (printf, 2, 3)));
|
||||
__attribute__ ((format (PRINTF_ATTRIBUTE_FORMAT, 2, 3)));
|
||||
extern void command_print_sameline(command_context_t *context, const char *format, ...)
|
||||
__attribute__ ((format (printf, 2, 3)));
|
||||
__attribute__ ((format (PRINTF_ATTRIBUTE_FORMAT, 2, 3)));
|
||||
extern int command_run_line(command_context_t *context, char *line);
|
||||
extern int command_run_linef(command_context_t *context, const char *format, ...)
|
||||
__attribute__ ((format (printf, 2, 3)));
|
||||
__attribute__ ((format (PRINTF_ATTRIBUTE_FORMAT, 2, 3)));
|
||||
extern void command_output_text(command_context_t *context, const char *data);
|
||||
|
||||
extern void process_jim_events(void);
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* Copyright (C) 2004, 2005 by Dominic Rath *
|
||||
* Dominic.Rath@gmx.de *
|
||||
* *
|
||||
* Copyright (C) 2007,2008 Øyvind Harboe *
|
||||
* Copyright (C) 2007,2008 Øyvind Harboe *
|
||||
* oyvind.harboe@zylin.com *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* Copyright (C) 2004, 2005 by Dominic Rath *
|
||||
* Dominic.Rath@gmx.de *
|
||||
* *
|
||||
* Copyright (C) 2007,2008 Øyvind Harboe *
|
||||
* Copyright (C) 2007,2008 Øyvind Harboe *
|
||||
* oyvind.harboe@zylin.com *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
@@ -32,6 +32,5 @@ extern void add_script_search_dir (const char *dir);
|
||||
extern int configuration_output_handler(struct command_context_s *context, const char* line);
|
||||
extern FILE *open_file_from_path (char *file, char *mode);
|
||||
extern char *find_file(const char *name);
|
||||
int add_default_dirs(void);
|
||||
|
||||
#endif /* CONFIGURATION_H */
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* Copyright (C) 2007 by Dominic Rath *
|
||||
* Dominic.Rath@gmx.de *
|
||||
* *
|
||||
* Copyright (C) 2007,2008 Øyvind Harboe *
|
||||
* Copyright (C) 2007,2008 Øyvind Harboe *
|
||||
* oyvind.harboe@zylin.com *
|
||||
* *
|
||||
* Copyright (C) 2008 by Spencer Oliver *
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* Copyright (C) 2007 by Dominic Rath *
|
||||
* Dominic.Rath@gmx.de *
|
||||
* *
|
||||
* Copyright (C) 2007,2008 Øyvind Harboe *
|
||||
* Copyright (C) 2007,2008 Øyvind Harboe *
|
||||
* oyvind.harboe@zylin.com *
|
||||
* *
|
||||
* Copyright (C) 2008 by Spencer Oliver *
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2007-2008 by Øyvind Harboe *
|
||||
* Copyright (C) 2007-2008 by Øyvind Harboe *
|
||||
* *
|
||||
* 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 *
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
* Copyright 2005 Salvatore Sanfilippo <antirez@invece.org>
|
||||
* Copyright 2005 Clemens Hintze <c.hintze@gmx.net>
|
||||
* Copyright 2005 patthoyts - Pat Thoyts <patthoyts@users.sf.net>
|
||||
* Copyright 2008 oharboe - Øyvind Harboe - oyvind.harboe@zylin.com
|
||||
* Copyright 2008 oharboe - Øyvind Harboe - oyvind.harboe@zylin.com
|
||||
* Copyright 2008 Andrew Lunn <andrew@lunn.ch>
|
||||
* Copyright 2008 Duane Ellis <openocd@duaneellis.com>
|
||||
* Copyright 2008 Uwe Klein <uklein@klein-messgeraete.de>
|
||||
@@ -52,8 +52,7 @@
|
||||
#define __JIM_EVENTLOOP_CORE__
|
||||
#ifdef __ECOS
|
||||
#include <pkgconf/jimtcl.h>
|
||||
#endif
|
||||
#ifdef __ECOS
|
||||
#include <sys/time.h>
|
||||
#include <cyg/jimtcl/jim.h>
|
||||
#include <cyg/jimtcl/jim-eventloop.h>
|
||||
#else
|
||||
@@ -498,7 +497,7 @@ static int JimELAfterCommand(Jim_Interp *interp, int argc,
|
||||
int tlen ;
|
||||
jim_wide remain = 0;
|
||||
const char *tok = Jim_GetString(argv[2], &tlen);
|
||||
if (sscanf(tok,"after#%lld",&id) == 1) {
|
||||
if (sscanf(tok,"after#%" JIM_WIDE_MODIFIER, &id) == 1) {
|
||||
remain = Jim_DeleteTimeHandler(interp, id);
|
||||
if (remain > -2) {
|
||||
Jim_SetResult(interp, Jim_NewIntObj(interp, remain));
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
* Copyright 2005 Salvatore Sanfilippo <antirez@invece.org>
|
||||
* Copyright 2005 Clemens Hintze <c.hintze@gmx.net>
|
||||
* Copyright 2005 patthoyts - Pat Thoyts <patthoyts@users.sf.net>
|
||||
* Copyright 2008 oharboe - Øyvind Harboe - oyvind.harboe@zylin.com
|
||||
* Copyright 2008 oharboe - Øyvind Harboe - oyvind.harboe@zylin.com
|
||||
* Copyright 2008 Andrew Lunn <andrew@lunn.ch>
|
||||
* Copyright 2008 Duane Ellis <openocd@duaneellis.com>
|
||||
* Copyright 2008 Uwe Klein <uklein@klein-messgeraete.de>
|
||||
|
||||
@@ -3,11 +3,14 @@
|
||||
* Copyright 2005 Salvatore Sanfilippo <antirez@invece.org>
|
||||
* Copyright 2005 Clemens Hintze <c.hintze@gmx.net>
|
||||
* Copyright 2005 patthoyts - Pat Thoyts <patthoyts@users.sf.net>
|
||||
* Copyright 2008 oharboe - Øyvind Harboe - oyvind.harboe@zylin.com
|
||||
* Copyright 2008,2009 oharboe - Øyvind Harboe - oyvind.harboe@zylin.com
|
||||
* Copyright 2008 Andrew Lunn <andrew@lunn.ch>
|
||||
* Copyright 2008 Duane Ellis <openocd@duaneellis.com>
|
||||
* Copyright 2008 Uwe Klein <uklein@klein-messgeraete.de>
|
||||
* Copyright 2008 Steve Bennett <steveb@workware.net.au>
|
||||
* Copyright 2009 Nico Coesel <ncoesel@dealogic.nl>
|
||||
* Copyright 2009 Zachary T Welch zw@superlucidity.net
|
||||
* Copyright 2009 David Brownell
|
||||
*
|
||||
* The FreeBSD license
|
||||
*
|
||||
@@ -50,6 +53,9 @@
|
||||
#include <pkgconf/jimtcl.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
typedef CYG_ADDRWORD intptr_t;
|
||||
|
||||
#include <string.h>
|
||||
#include <stdarg.h>
|
||||
#include <ctype.h>
|
||||
@@ -2828,6 +2834,9 @@ void FreeScriptInternalRep(Jim_Interp *interp, Jim_Obj *objPtr)
|
||||
int i;
|
||||
struct ScriptObj *script = (void*) objPtr->internalRep.ptr;
|
||||
|
||||
if (!script)
|
||||
return;
|
||||
|
||||
script->inUse--;
|
||||
if (script->inUse != 0) return;
|
||||
for (i = 0; i < script->len; i++) {
|
||||
@@ -3232,7 +3241,7 @@ int Jim_CreateProcedure(Jim_Interp *interp, const char *cmdName,
|
||||
Jim_InitHashTable(cmdPtr->staticVars, getJimVariablesHashTableType(),
|
||||
interp);
|
||||
for (i = 0; i < len; i++) {
|
||||
Jim_Obj *objPtr, *initObjPtr, *nameObjPtr;
|
||||
Jim_Obj *objPtr=NULL, *initObjPtr=NULL, *nameObjPtr=NULL;
|
||||
Jim_Var *varPtr;
|
||||
int subLen;
|
||||
|
||||
@@ -4748,7 +4757,7 @@ const char *Jim_GetSharedString(Jim_Interp *interp, const char *str)
|
||||
Jim_AddHashEntry(&interp->sharedStrings, strCopy, (void*)1);
|
||||
return strCopy;
|
||||
} else {
|
||||
long refCount = (long) he->val;
|
||||
intptr_t refCount = (intptr_t) he->val;
|
||||
|
||||
refCount++;
|
||||
he->val = (void*) refCount;
|
||||
@@ -4758,13 +4767,13 @@ const char *Jim_GetSharedString(Jim_Interp *interp, const char *str)
|
||||
|
||||
void Jim_ReleaseSharedString(Jim_Interp *interp, const char *str)
|
||||
{
|
||||
long refCount;
|
||||
intptr_t refCount;
|
||||
Jim_HashEntry *he = Jim_FindHashEntry(&interp->sharedStrings, str);
|
||||
|
||||
if (he == NULL)
|
||||
Jim_Panic(interp,"Jim_ReleaseSharedString called with "
|
||||
"unknown shared string '%s'", str);
|
||||
refCount = (long) he->val;
|
||||
refCount = (intptr_t) he->val;
|
||||
refCount--;
|
||||
if (refCount == 0) {
|
||||
Jim_DeleteHashEntry(&interp->sharedStrings, str);
|
||||
@@ -7736,7 +7745,7 @@ Jim_Obj *Jim_ScanString(Jim_Interp *interp, Jim_Obj *strObjPtr,
|
||||
int scanned = 1;
|
||||
const char *str = Jim_GetString(strObjPtr, 0);
|
||||
Jim_Obj *resultList = 0;
|
||||
Jim_Obj **resultVec;
|
||||
Jim_Obj **resultVec =NULL;
|
||||
int resultc;
|
||||
Jim_Obj *emptyStr = 0;
|
||||
ScanFmtStringObj *fmtObj;
|
||||
@@ -8820,9 +8829,9 @@ int JimCallProcedure(Jim_Interp *interp, Jim_Cmd *cmd, int argc,
|
||||
}
|
||||
|
||||
for (i = 0; i < num_args; i++) {
|
||||
Jim_Obj *argObjPtr;
|
||||
Jim_Obj *nameObjPtr;
|
||||
Jim_Obj *valueObjPtr;
|
||||
Jim_Obj *argObjPtr=NULL;
|
||||
Jim_Obj *nameObjPtr=NULL;
|
||||
Jim_Obj *valueObjPtr=NULL;
|
||||
|
||||
Jim_ListIndex(interp, cmd->argListObjPtr, i, &argObjPtr, JIM_NONE);
|
||||
if (i + 1 >= cmd->arityMin) {
|
||||
@@ -8846,7 +8855,7 @@ int JimCallProcedure(Jim_Interp *interp, Jim_Cmd *cmd, int argc,
|
||||
}
|
||||
/* Set optional arguments */
|
||||
if (cmd->arityMax == -1) {
|
||||
Jim_Obj *listObjPtr, *objPtr;
|
||||
Jim_Obj *listObjPtr=NULL, *objPtr=NULL;
|
||||
|
||||
i++;
|
||||
listObjPtr = Jim_NewListObj(interp, argv + i, argc-i);
|
||||
@@ -9418,7 +9427,7 @@ static Jim_Obj *JimCommandsList(Jim_Interp *interp, Jim_Obj *patternObjPtr)
|
||||
Jim_HashEntry *he;
|
||||
Jim_Obj *listObjPtr = Jim_NewListObj(interp, NULL, 0);
|
||||
const char *pattern;
|
||||
int patternLen;
|
||||
int patternLen=0;
|
||||
|
||||
pattern = patternObjPtr ? Jim_GetString(patternObjPtr, &patternLen) : NULL;
|
||||
htiter = Jim_GetHashTableIterator(&interp->commands);
|
||||
@@ -9444,7 +9453,7 @@ static Jim_Obj *JimVariablesList(Jim_Interp *interp, Jim_Obj *patternObjPtr,
|
||||
Jim_HashEntry *he;
|
||||
Jim_Obj *listObjPtr = Jim_NewListObj(interp, NULL, 0);
|
||||
const char *pattern;
|
||||
int patternLen;
|
||||
int patternLen=0;
|
||||
|
||||
pattern = patternObjPtr ? Jim_GetString(patternObjPtr, &patternLen) : NULL;
|
||||
if (mode == JIM_VARLIST_GLOBALS) {
|
||||
@@ -9813,7 +9822,7 @@ static int Jim_WhileCoreCommand(Jim_Interp *interp, int argc,
|
||||
exprLen = expr->len;
|
||||
|
||||
if (exprLen == 1) {
|
||||
jim_wide wideValue;
|
||||
jim_wide wideValue=0;
|
||||
|
||||
if (expr->opcode[0] == JIM_EXPROP_VARIABLE) {
|
||||
varAObjPtr = expr->obj[0];
|
||||
@@ -9853,7 +9862,7 @@ static int Jim_WhileCoreCommand(Jim_Interp *interp, int argc,
|
||||
if (varAObjPtr)
|
||||
Jim_DecrRefCount(interp, varAObjPtr);
|
||||
} else if (exprLen == 3) {
|
||||
jim_wide wideValueA, wideValueB, cmpRes = 0;
|
||||
jim_wide wideValueA, wideValueB=0, cmpRes = 0;
|
||||
int cmpType = expr->opcode[2];
|
||||
|
||||
varAObjPtr = expr->obj[0];
|
||||
@@ -9980,7 +9989,7 @@ static int Jim_ForCoreCommand(Jim_Interp *interp, int argc,
|
||||
{
|
||||
ScriptObj *initScript, *incrScript;
|
||||
ExprByteCode *expr;
|
||||
jim_wide start, stop, currentVal;
|
||||
jim_wide start, stop=0, currentVal;
|
||||
unsigned jim_wide procEpoch = interp->procEpoch;
|
||||
Jim_Obj *varNamePtr, *stopVarNamePtr = NULL, *objPtr;
|
||||
int cmpType;
|
||||
@@ -11010,7 +11019,7 @@ static int Jim_ProcCoreCommand(Jim_Interp *interp, int argc,
|
||||
if (argListLen) {
|
||||
const char *str;
|
||||
int len;
|
||||
Jim_Obj *argPtr;
|
||||
Jim_Obj *argPtr=NULL;
|
||||
|
||||
/* Check for 'args' and adjust arityMin and arityMax if necessary */
|
||||
Jim_ListIndex(interp, argv[2], argListLen-1, &argPtr, JIM_NONE);
|
||||
@@ -11129,7 +11138,7 @@ static Jim_Obj *JimStringMap(Jim_Interp *interp, Jim_Obj *mapListObjPtr,
|
||||
value = Jim_Alloc(sizeof(Jim_Obj*)*numMaps);
|
||||
resultObjPtr = Jim_NewStringObj(interp, "", 0);
|
||||
for (i = 0; i < numMaps; i++) {
|
||||
Jim_Obj *eleObjPtr;
|
||||
Jim_Obj *eleObjPtr=NULL;
|
||||
|
||||
Jim_ListIndex(interp, mapListObjPtr, i*2, &eleObjPtr, JIM_NONE);
|
||||
key[i] = Jim_GetString(eleObjPtr, &keyLen[i]);
|
||||
@@ -11852,7 +11861,7 @@ static int Jim_JoinCoreCommand(Jim_Interp *interp, int argc,
|
||||
resObjPtr = Jim_NewStringObj(interp, NULL, 0);
|
||||
/* Split */
|
||||
for (i = 0; i < listLen; i++) {
|
||||
Jim_Obj *objPtr;
|
||||
Jim_Obj *objPtr=NULL;
|
||||
|
||||
Jim_ListIndex(interp, argv[1], i, &objPtr, JIM_NONE);
|
||||
Jim_AppendObj(interp, resObjPtr, objPtr);
|
||||
@@ -12116,7 +12125,7 @@ static int Jim_RangeCoreCommand(Jim_Interp *interp, int argc,
|
||||
static int Jim_RandCoreCommand(Jim_Interp *interp, int argc,
|
||||
Jim_Obj *const *argv)
|
||||
{
|
||||
jim_wide min = 0, max, len, maxMul;
|
||||
jim_wide min = 0, max =0, len, maxMul;
|
||||
|
||||
if (argc < 1 || argc > 3) {
|
||||
Jim_WrongNumArgs(interp, 1, argv, "?min? max");
|
||||
@@ -12308,7 +12317,7 @@ void Jim_PrintErrorMessage(Jim_Interp *interp)
|
||||
Jim_GetString(interp->result, NULL));
|
||||
Jim_ListLength(interp, interp->stackTrace, &len);
|
||||
for (i = len-3; i >= 0; i-= 3) {
|
||||
Jim_Obj *objPtr;
|
||||
Jim_Obj *objPtr=NULL;
|
||||
const char *proc, *file, *line;
|
||||
|
||||
Jim_ListIndex(interp, interp->stackTrace, i, &objPtr, JIM_NONE);
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
* Copyright 2005 Salvatore Sanfilippo <antirez@invece.org>
|
||||
* Copyright 2005 Clemens Hintze <c.hintze@gmx.net>
|
||||
* Copyright 2005 patthoyts - Pat Thoyts <patthoyts@users.sf.net>
|
||||
* Copyright 2008 oharboe - Øyvind Harboe - oyvind.harboe@zylin.com
|
||||
* Copyright 2008 oharboe - Øyvind Harboe - oyvind.harboe@zylin.com
|
||||
* Copyright 2008 Andrew Lunn <andrew@lunn.ch>
|
||||
* Copyright 2008 Duane Ellis <openocd@duaneellis.com>
|
||||
* Copyright 2008 Uwe Klein <uklein@klein-messgeraete.de>
|
||||
@@ -87,7 +87,7 @@ extern "C" {
|
||||
#endif /* _MSC_VER */
|
||||
|
||||
/* Long Long type and related issues */
|
||||
#ifdef HAVE_LONG_LONG_INT
|
||||
#if !defined(__ECOS) && defined(HAVE_LONG_LONG_INT)
|
||||
# ifdef _MSC_VER /* MSC compiler */
|
||||
# define jim_wide _int64
|
||||
# ifndef LLONG_MAX
|
||||
@@ -119,8 +119,8 @@ extern "C" {
|
||||
* LIBC specific fixes
|
||||
* ---------------------------------------------------------------------------*/
|
||||
|
||||
#ifdef HAVE_LONG_LONG_INT
|
||||
# if defined(_MSC_VER) || defined(__MSVCRT__)
|
||||
#if !defined(__ECOS) && defined(HAVE_LONG_LONG_INT)
|
||||
# if defined(_MSC_VER) || defined(__MSVCRT__) || defined(__MINGW32__)
|
||||
# define JIM_WIDE_MODIFIER "I64d"
|
||||
# else
|
||||
# define JIM_WIDE_MODIFIER "lld"
|
||||
|
||||
102
src/helper/log.c
102
src/helper/log.c
@@ -2,7 +2,7 @@
|
||||
* Copyright (C) 2005 by Dominic Rath *
|
||||
* Dominic.Rath@gmx.de *
|
||||
* *
|
||||
* Copyright (C) 2007,2008 Øyvind Harboe *
|
||||
* Copyright (C) 2007,2008 Øyvind Harboe *
|
||||
* oyvind.harboe@zylin.com *
|
||||
* *
|
||||
* Copyright (C) 2008 by Spencer Oliver *
|
||||
@@ -64,6 +64,95 @@ static char *log_strings[5] =
|
||||
|
||||
static int count = 0;
|
||||
|
||||
|
||||
static struct store_log_forward * log_head = NULL;
|
||||
static int log_forward_count = 0;
|
||||
|
||||
struct store_log_forward
|
||||
{
|
||||
struct store_log_forward * next;
|
||||
const char * file;
|
||||
int line;
|
||||
const char * function;
|
||||
const char * string;
|
||||
};
|
||||
|
||||
/* either forward the log to the listeners or store it for possible forwarding later */
|
||||
static void log_forward(const char *file, int line, const char *function, const char *string)
|
||||
{
|
||||
if (log_forward_count==0)
|
||||
{
|
||||
log_callback_t *cb, *next;
|
||||
cb = log_callbacks;
|
||||
/* DANGER!!!! the log callback can remove itself!!!! */
|
||||
while (cb)
|
||||
{
|
||||
next = cb->next;
|
||||
cb->fn(cb->priv, file, line, function, string);
|
||||
cb = next;
|
||||
}
|
||||
} else
|
||||
{
|
||||
struct store_log_forward *log = malloc(sizeof (struct store_log_forward));
|
||||
log->file = strdup(file);
|
||||
log->line = line;
|
||||
log->function = strdup(function);
|
||||
log->string = strdup(string);
|
||||
log->next = NULL;
|
||||
if (log_head==NULL)
|
||||
log_head = log;
|
||||
else
|
||||
{
|
||||
/* append to tail */
|
||||
struct store_log_forward * t;
|
||||
t = log_head;
|
||||
while (t->next!=NULL)
|
||||
{
|
||||
t = t->next;
|
||||
}
|
||||
t->next = log;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void log_try(void)
|
||||
{
|
||||
log_forward_count++;
|
||||
}
|
||||
|
||||
void log_catch(void)
|
||||
{
|
||||
assert(log_forward_count>0);
|
||||
log_forward_count--;
|
||||
}
|
||||
|
||||
void log_rethrow(void)
|
||||
{
|
||||
log_catch();
|
||||
if (log_forward_count==0)
|
||||
{
|
||||
struct store_log_forward *log;
|
||||
|
||||
log = log_head;
|
||||
while (log != NULL)
|
||||
{
|
||||
log_forward(log->file, log->line, log->function, log->string);
|
||||
|
||||
struct store_log_forward *t=log;
|
||||
log = log->next;
|
||||
|
||||
free((void *)t->file);
|
||||
free((void *)t->function);
|
||||
free((void *)t->string);
|
||||
free(t);
|
||||
|
||||
}
|
||||
|
||||
log_head = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* The log_puts() serves to somewhat different goals:
|
||||
*
|
||||
* - logging
|
||||
@@ -131,18 +220,11 @@ static void log_puts(enum log_levels level, const char *file, int line, const ch
|
||||
/* Never forward LOG_LVL_DEBUG, too verbose and they can be found in the log if need be */
|
||||
if (level <= LOG_LVL_INFO)
|
||||
{
|
||||
log_callback_t *cb, *next;
|
||||
cb = log_callbacks;
|
||||
/* DANGER!!!! the log callback can remove itself!!!! */
|
||||
while (cb)
|
||||
{
|
||||
next = cb->next;
|
||||
cb->fn(cb->priv, file, line, function, string);
|
||||
cb = next;
|
||||
}
|
||||
log_forward(file, line, function, string);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void log_printf(enum log_levels level, const char *file, int line, const char *function, const char *format, ...)
|
||||
{
|
||||
char *string;
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* Copyright (C) 2005 by Dominic Rath *
|
||||
* Dominic.Rath@gmx.de *
|
||||
* *
|
||||
* Copyright (C) 2007,2008 Øyvind Harboe *
|
||||
* Copyright (C) 2007,2008 Øyvind Harboe *
|
||||
* oyvind.harboe@zylin.com *
|
||||
* *
|
||||
* Copyright (C) 2008 by Spencer Oliver *
|
||||
@@ -28,6 +28,15 @@
|
||||
|
||||
#include "command.h"
|
||||
|
||||
/* To achieve C99 printf compatibility in MinGW, gnu_printf should be
|
||||
* used for __attribute__((format( ... ))), with GCC v4.4 or later
|
||||
*/
|
||||
#if (defined(IS_MINGW) && (((__GNUC__ << 16) + __GNUC_MINOR__) >= 0x00040004))
|
||||
#define PRINTF_ATTRIBUTE_FORMAT gnu_printf
|
||||
#else
|
||||
#define PRINTF_ATTRIBUTE_FORMAT printf
|
||||
#endif
|
||||
|
||||
/* logging priorities
|
||||
* LOG_LVL_SILENT - turn off all output. In lieu of try + catch this can be used as a
|
||||
* feeble ersatz.
|
||||
@@ -52,10 +61,10 @@ enum log_levels
|
||||
|
||||
extern void log_printf(enum log_levels level, const char *file, int line,
|
||||
const char *function, const char *format, ...)
|
||||
__attribute__ ((format (printf, 5, 6)));
|
||||
__attribute__ ((format (PRINTF_ATTRIBUTE_FORMAT, 5, 6)));
|
||||
extern void log_printf_lf(enum log_levels level, const char *file, int line,
|
||||
const char *function, const char *format, ...)
|
||||
__attribute__ ((format (printf, 5, 6)));
|
||||
__attribute__ ((format (PRINTF_ATTRIBUTE_FORMAT, 5, 6)));
|
||||
extern int log_register_commands(struct command_context_s *cmd_ctx);
|
||||
extern int log_init(struct command_context_s *cmd_ctx);
|
||||
extern int set_log_output(struct command_context_s *cmd_ctx, FILE *output);
|
||||
@@ -64,6 +73,15 @@ extern void kept_alive(void);
|
||||
extern void alive_sleep(int ms);
|
||||
extern void busy_sleep(int ms);
|
||||
|
||||
|
||||
/* log entries can be paused and replayed roughly according to the try/catch/rethrow
|
||||
* concepts in C++
|
||||
*/
|
||||
void log_try(void);
|
||||
void log_catch(void);
|
||||
void log_rethrow(void);
|
||||
|
||||
|
||||
typedef void (*log_callback_fn)(void *priv, const char *file, int line,
|
||||
const char *function, const char *string);
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* Copyright (C) 2004, 2005 by Dominic Rath *
|
||||
* Dominic.Rath@gmx.de *
|
||||
* *
|
||||
* Copyright (C) 2007,2008 Øyvind Harboe *
|
||||
* Copyright (C) 2007,2008 Øyvind Harboe *
|
||||
* oyvind.harboe@zylin.com *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
@@ -38,7 +38,7 @@ static struct option long_options[] =
|
||||
{"help", no_argument, &help_flag, 1},
|
||||
{"version", no_argument, &version_flag, 1},
|
||||
{"debug", optional_argument, 0, 'd'},
|
||||
{"file", required_argument, 0, 'f'},
|
||||
{"file", required_argument, 0, 'f'},
|
||||
{"search", required_argument, 0, 's'},
|
||||
{"log_output", required_argument, 0, 'l'},
|
||||
{"command", required_argument, 0, 'c'},
|
||||
@@ -53,7 +53,7 @@ int configuration_output_handler(struct command_context_s *context, const char*
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
int add_default_dirs(void)
|
||||
static void add_default_dirs(void)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
/* Add the parent of the directory where openocd.exe resides to the
|
||||
@@ -106,7 +106,6 @@ int add_default_dirs(void)
|
||||
add_script_search_dir(PKGDATADIR "/site");
|
||||
add_script_search_dir(PKGDATADIR "/scripts");
|
||||
#endif
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
int parse_cmdline_args(struct command_context_s *cmd_ctx, int argc, char *argv[])
|
||||
@@ -196,5 +195,10 @@ int parse_cmdline_args(struct command_context_s *cmd_ctx, int argc, char *argv[]
|
||||
exit(0);
|
||||
}
|
||||
|
||||
/* paths specified on the command line take precedence over these
|
||||
* built-in paths
|
||||
*/
|
||||
add_default_dirs();
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* Copyright (C) 2006 by Dominic Rath *
|
||||
* Dominic.Rath@gmx.de *
|
||||
* *
|
||||
* Copyright (C) 2007,2008 Øyvind Harboe *
|
||||
* Copyright (C) 2007,2008 Øyvind Harboe *
|
||||
* oyvind.harboe@zylin.com *
|
||||
* *
|
||||
* Copyright (C) 2008 by Spencer Oliver *
|
||||
@@ -169,7 +169,7 @@ int win_select(int max_fd, fd_set *rfds, fd_set *wfds, fd_set *efds, struct time
|
||||
/* build an array of handles for non-sockets */
|
||||
for (i = 0; i < max_fd; i++) {
|
||||
if (SAFE_FD_ISSET(i, rfds) || SAFE_FD_ISSET(i, wfds) || SAFE_FD_ISSET(i, efds)) {
|
||||
long handle = _get_osfhandle(i);
|
||||
intptr_t handle = (intptr_t) _get_osfhandle(i);
|
||||
handles[n_handles] = (HANDLE)handle;
|
||||
if (handles[n_handles] == INVALID_HANDLE_VALUE) {
|
||||
/* socket */
|
||||
@@ -244,7 +244,7 @@ int win_select(int max_fd, fd_set *rfds, fd_set *wfds, fd_set *efds, struct time
|
||||
if (WAIT_OBJECT_0 == WaitForSingleObject(handles[i], 0)) {
|
||||
if (SAFE_FD_ISSET(handle_slot_to_fd[i], rfds)) {
|
||||
DWORD dwBytes;
|
||||
long handle = _get_osfhandle(handle_slot_to_fd[i]);
|
||||
intptr_t handle = (intptr_t) _get_osfhandle(handle_slot_to_fd[i]);
|
||||
|
||||
if (PeekNamedPipe((HANDLE)handle, NULL, 0, NULL, &dwBytes, NULL))
|
||||
{
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* Copyright (C) 2006 by Dominic Rath *
|
||||
* Dominic.Rath@gmx.de *
|
||||
* *
|
||||
* Copyright (C) 2007,2008 Øyvind Harboe *
|
||||
* Copyright (C) 2007,2008 Øyvind Harboe *
|
||||
* oyvind.harboe@zylin.com *
|
||||
* *
|
||||
* Copyright (C) 2008 by Spencer Oliver *
|
||||
|
||||
@@ -128,22 +128,53 @@ add_help_text script "<filename> - filename of OpenOCD script (tcl) to run"
|
||||
# Handle GDB 'R' packet. Can be overriden by configuration script,
|
||||
# but it's not something one would expect target scripts to do
|
||||
# normally
|
||||
proc ocd_gdb_restart {target_num} {
|
||||
proc ocd_gdb_restart {target_id} {
|
||||
# Fix!!! we're resetting all targets here! Really we should reset only
|
||||
# one target
|
||||
reset halt
|
||||
}
|
||||
|
||||
# If RCLK is not supported, use fallback_speed_khz
|
||||
proc jtag_rclk {fallback_speed_khz} {
|
||||
if {[catch {jtag_khz 0}]!=0} {
|
||||
jtag_khz $fallback_speed_khz
|
||||
|
||||
# This reset logic may be overridden by board/target/... scripts as needed
|
||||
# to provide a reset that, if possible, is close to a power-up reset.
|
||||
#
|
||||
# Exit requirements include: (a) JTAG must be working, (b) the scan
|
||||
# chain was validated with "jtag arp_init" (or equivalent), (c) nothing
|
||||
# stays in reset. No TAP-specific scans were performed. It's OK if
|
||||
# some targets haven't been reset yet; they may need TAP-specific scans.
|
||||
#
|
||||
# The "mode" values include: halt, init, run (from "reset" command);
|
||||
# startup (at OpenOCD server startup, when JTAG may not yet work); and
|
||||
# potentially more (for reset types like cold, warm, etc)
|
||||
proc init_reset { mode } {
|
||||
jtag arp_init-reset
|
||||
}
|
||||
|
||||
|
||||
global in_process_reset
|
||||
set in_process_reset 0
|
||||
|
||||
# Catch reset recursion
|
||||
proc ocd_process_reset { MODE } {
|
||||
global in_process_reset
|
||||
if {$in_process_reset} {
|
||||
set in_process_reset 0
|
||||
return -code error "'reset' can not be invoked recursively"
|
||||
}
|
||||
|
||||
set in_process_reset 1
|
||||
set success [expr [catch {ocd_process_reset_inner $MODE} result]==0]
|
||||
set in_process_reset 0
|
||||
|
||||
if {$success} {
|
||||
return $result
|
||||
} else {
|
||||
return -code error $result
|
||||
}
|
||||
}
|
||||
|
||||
add_help_text jtag_rclk "fallback_speed_khz - set JTAG speed to RCLK or use fallback speed"
|
||||
|
||||
proc ocd_process_reset { MODE } {
|
||||
proc ocd_process_reset_inner { MODE } {
|
||||
set targets [target names]
|
||||
|
||||
# If this target must be halted...
|
||||
set halt -1
|
||||
@@ -162,47 +193,63 @@ proc ocd_process_reset { MODE } {
|
||||
|
||||
# Target event handlers *might* change which TAPs are enabled
|
||||
# or disabled, so we fire all of them. But don't issue any
|
||||
# of the "arp_*" commands, which may issue JTAG transactions,
|
||||
# target "arp_*" commands, which may issue JTAG transactions,
|
||||
# unless we know the underlying TAP is active.
|
||||
#
|
||||
# NOTE: ARP == "Advanced Reset Process" ... "advanced" is
|
||||
# relative to a previous restrictive scheme
|
||||
|
||||
foreach t [ target names ] {
|
||||
foreach t $targets {
|
||||
# New event script.
|
||||
$t invoke-event reset-start
|
||||
}
|
||||
|
||||
# Init the tap controller.
|
||||
jtag arp_init-reset
|
||||
# Use TRST or TMS/TCK operations to reset all the tap controllers.
|
||||
# TAP reset events get reported; they might enable some taps.
|
||||
init_reset $MODE
|
||||
|
||||
# Examine all targets on enabled taps.
|
||||
foreach t [ target names ] {
|
||||
foreach t $targets {
|
||||
if {[jtag tapisenabled [$t cget -chain-position]]} {
|
||||
$t arp_examine
|
||||
}
|
||||
}
|
||||
|
||||
# Let the C code know we are asserting reset.
|
||||
foreach t [ target names ] {
|
||||
# Assert SRST, and report the pre/post events.
|
||||
# Note: no target sees SRST before "pre" or after "post".
|
||||
foreach t $targets {
|
||||
$t invoke-event reset-assert-pre
|
||||
}
|
||||
foreach t $targets {
|
||||
# C code needs to know if we expect to 'halt'
|
||||
if {[jtag tapisenabled [$t cget -chain-position]]} {
|
||||
$t arp_reset assert $halt
|
||||
}
|
||||
}
|
||||
foreach t $targets {
|
||||
$t invoke-event reset-assert-post
|
||||
}
|
||||
|
||||
# Now de-assert reset.
|
||||
foreach t [ target names ] {
|
||||
# Now de-assert SRST, and report the pre/post events.
|
||||
# Note: no target sees !SRST before "pre" or after "post".
|
||||
foreach t $targets {
|
||||
$t invoke-event reset-deassert-pre
|
||||
# Again, de-assert code needs to know..
|
||||
}
|
||||
foreach t $targets {
|
||||
# Again, de-assert code needs to know if we 'halt'
|
||||
if {[jtag tapisenabled [$t cget -chain-position]]} {
|
||||
$t arp_reset deassert $halt
|
||||
}
|
||||
}
|
||||
foreach t $targets {
|
||||
$t invoke-event reset-deassert-post
|
||||
}
|
||||
|
||||
# Pass 1 - Now try to halt.
|
||||
# Pass 1 - Now wait for any halt (requested as part of reset
|
||||
# assert/deassert) to happen. Ideally it takes effect without
|
||||
# first executing any instructions.
|
||||
if { $halt } {
|
||||
foreach t [target names] {
|
||||
foreach t $targets {
|
||||
if {[jtag tapisenabled [$t cget -chain-position]] == 0} {
|
||||
continue
|
||||
}
|
||||
@@ -226,7 +273,7 @@ proc ocd_process_reset { MODE } {
|
||||
|
||||
#Pass 2 - if needed "init"
|
||||
if { 0 == [string compare init $MODE] } {
|
||||
foreach t [target names] {
|
||||
foreach t $targets {
|
||||
if {[jtag tapisenabled [$t cget -chain-position]] == 0} {
|
||||
continue
|
||||
}
|
||||
@@ -239,64 +286,15 @@ proc ocd_process_reset { MODE } {
|
||||
}
|
||||
}
|
||||
|
||||
foreach t [ target names ] {
|
||||
foreach t $targets {
|
||||
$t invoke-event reset-end
|
||||
}
|
||||
}
|
||||
|
||||
# stubs for targets scripts that do not have production procedure
|
||||
proc production_info {} {
|
||||
return "Imagine an explanation here..."
|
||||
}
|
||||
add_help_text production_info "Displays information on production procedure for target script. Implement this procedure in target script."
|
||||
#########
|
||||
|
||||
proc production {firmwarefile serialnumber} {
|
||||
puts "Imagine production procedure running successfully. Programmed $firmwarefile with serial number $serialnumber"
|
||||
}
|
||||
|
||||
add_help_text production "<serialnumber> - Runs production procedure. Throws exception if procedure failed. Prints progress messages. Implement this procedure in the target script."
|
||||
|
||||
proc production_test {} {
|
||||
puts "Imagine nifty test procedure having run to completion here."
|
||||
}
|
||||
add_help_text production "Runs test procedure. Throws exception if procedure failed. Prints progress messages. Implement in target script."
|
||||
|
||||
add_help_text cpu "<name> - prints out target options and a comment on CPU which matches name"
|
||||
|
||||
# A list of names of CPU and options required
|
||||
set ocd_cpu_list {
|
||||
{
|
||||
name IXP42x
|
||||
options {xscale -variant IXP42x}
|
||||
comment {IXP42x cpu}
|
||||
}
|
||||
{
|
||||
name arm7
|
||||
options {arm7tdmi -variant arm7tdmi}
|
||||
comment {vanilla ARM7}
|
||||
}
|
||||
}
|
||||
|
||||
# Invoked from Tcl code
|
||||
proc ocd_cpu {args} {
|
||||
set name $args
|
||||
set result ""
|
||||
global ocd_cpu_list
|
||||
foreach a [lsort $ocd_cpu_list] {
|
||||
if {[string length $args]==0||[string first [string toupper $name] [string toupper "$a(name)$a(options)$a(comment)"]]!=-1} {
|
||||
lappend result $a
|
||||
}
|
||||
}
|
||||
return $result
|
||||
}
|
||||
|
||||
proc cpu {args} {
|
||||
# 0123456789012345678901234567890123456789012345678901234567890123456789
|
||||
puts "CPU Options Comment"
|
||||
foreach a [lsort [ocd_cpu $args]] {
|
||||
puts [format "%-20s%-40s%s" $a(name) $a(options) $a(comment)]
|
||||
}
|
||||
}
|
||||
# REVISIT power_restore, power_dropout, srst_deasserted, srst_asserted
|
||||
# are currently neither documented nor supported except on ZY1000.
|
||||
|
||||
proc power_restore {} {
|
||||
puts "Sensed power restore."
|
||||
@@ -319,6 +317,8 @@ proc srst_asserted {} {
|
||||
puts "Sensed nSRST asserted."
|
||||
}
|
||||
|
||||
#########
|
||||
|
||||
# catch any exceptions, capture output and return output
|
||||
proc capture_catch {a} {
|
||||
catch {
|
||||
@@ -326,3 +326,13 @@ proc capture_catch {a} {
|
||||
} result
|
||||
return $result
|
||||
}
|
||||
|
||||
|
||||
# Executed during "init". Can be overridden
|
||||
# by board/target/... scripts
|
||||
proc jtag_init {} {
|
||||
if {[catch {jtag arp_init} err]!=0} {
|
||||
# try resetting additionally
|
||||
init_reset startup
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* Copyright (C) 2006 by Dominic Rath *
|
||||
* Dominic.Rath@gmx.de *
|
||||
* *
|
||||
* Copyright (C) 2007,2008 Øyvind Harboe *
|
||||
* Copyright (C) 2007,2008 Øyvind Harboe *
|
||||
* oyvind.harboe@zylin.com *
|
||||
* *
|
||||
* Copyright (C) 2008 by Spencer Oliver *
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* Copyright (C) 2006 by Dominic Rath *
|
||||
* Dominic.Rath@gmx.de *
|
||||
* *
|
||||
* Copyright (C) 2007,2008 Øyvind Harboe *
|
||||
* Copyright (C) 2007,2008 Øyvind Harboe *
|
||||
* oyvind.harboe@zylin.com *
|
||||
* *
|
||||
* Copyright (C) 2008 by Spencer Oliver *
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* Copyright (C) 2004, 2005 by Dominic Rath *
|
||||
* Dominic.Rath@gmx.de *
|
||||
* *
|
||||
* Copyright (C) 2007,2008 Øyvind Harboe *
|
||||
* Copyright (C) 2007,2008 Øyvind Harboe *
|
||||
* oyvind.harboe@zylin.com *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
@@ -123,13 +123,14 @@ static inline void h_u16_to_be(uint8_t* buf, int val)
|
||||
buf[1] = (uint8_t) (val >> 0);
|
||||
}
|
||||
|
||||
#ifdef __ECOS
|
||||
#if defined(__ECOS)
|
||||
|
||||
/* eCos plain lacks these definition... A series of upstream patches
|
||||
* could probably repair it, but it seems like too much work to be
|
||||
* worth it.
|
||||
*/
|
||||
|
||||
|
||||
#if !defined(_STDINT_H)
|
||||
#define PRIx32 "x"
|
||||
#define PRId32 "d"
|
||||
#define SCNx32 "x"
|
||||
@@ -151,8 +152,19 @@ typedef uint64_t uintmax_t;
|
||||
#define INT64_MAX 0x7fffffffffffffffLL
|
||||
#define INT64_MIN (-INT64_MAX - 1LL)
|
||||
#define UINT64_MAX (__CONCAT(INT64_MAX, U) * 2ULL + 1ULL)
|
||||
#endif
|
||||
|
||||
#ifndef LLONG_MAX
|
||||
#define ULLONG_MAX UINT64_C(0xFFFFFFFFFFFFFFFF)
|
||||
#define LLONG_MAX INT64_C(0x7FFFFFFFFFFFFFFF)
|
||||
#define LLONG_MIN ULLONG_MAX
|
||||
#endif
|
||||
|
||||
|
||||
#define ULLONG_MAX 18446744073709551615
|
||||
|
||||
/* C99, eCos is C90 compliant (with bits of C99) */
|
||||
#define isblank(c) ((c) == ' ' || (c) == '\t')
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
@@ -374,7 +374,7 @@ static int amt_jtagaccel_execute_queue(void)
|
||||
break;
|
||||
case JTAG_SLEEP:
|
||||
#ifdef _DEBUG_JTAG_IO_
|
||||
LOG_DEBUG("sleep %i", cmd->cmd.sleep->us);
|
||||
LOG_DEBUG("sleep %" PRIi32, cmd->cmd.sleep->us);
|
||||
#endif
|
||||
jtag_sleep(cmd->cmd.sleep->us);
|
||||
break;
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* Copyright (C) 2005 by Dominic Rath *
|
||||
* Dominic.Rath@gmx.de *
|
||||
* *
|
||||
* Copyright (C) 2007,2008 Øyvind Harboe *
|
||||
* Copyright (C) 2007,2008 Øyvind Harboe *
|
||||
* oyvind.harboe@zylin.com *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
@@ -46,12 +46,12 @@ bitbang_interface_t *bitbang_interface;
|
||||
* Set this to 1 and str912 reset halt will fail.
|
||||
*
|
||||
* If someone can submit a patch with an explanation it will be greatly
|
||||
* appreciated, but as far as I can tell (ØH) DCLK is generated upon
|
||||
* appreciated, but as far as I can tell (ØH) DCLK is generated upon
|
||||
* clk = 0 in TAP_IDLE. Good luck deducing that from the ARM documentation!
|
||||
* The ARM documentation uses the term "DCLK is asserted while in the TAP_IDLE
|
||||
* state". With hardware there is no such thing as *while* in a state. There
|
||||
* are only edges. So clk => 0 is in fact a very subtle state transition that
|
||||
* happens *while* in the TAP_IDLE state. "#&¤"#¤&"#&"#&
|
||||
* happens *while* in the TAP_IDLE state. "#&¤"#¤&"#&"#&
|
||||
*
|
||||
* For "reset halt" the last thing that happens before srst is asserted
|
||||
* is that the breakpoint is set up. If DCLK is not wiggled one last
|
||||
@@ -308,7 +308,7 @@ int bitbang_execute_queue(void)
|
||||
break;
|
||||
case JTAG_SLEEP:
|
||||
#ifdef _DEBUG_JTAG_IO_
|
||||
LOG_DEBUG("sleep %i", cmd->cmd.sleep->us);
|
||||
LOG_DEBUG("sleep %" PRIi32, cmd->cmd.sleep->us);
|
||||
#endif
|
||||
jtag_sleep(cmd->cmd.sleep->us);
|
||||
break;
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* Copyright (C) 2005 by Dominic Rath *
|
||||
* Dominic.Rath@gmx.de *
|
||||
* *
|
||||
* Copyright (C) 2007,2008 Øyvind Harboe *
|
||||
* Copyright (C) 2007,2008 Øyvind Harboe *
|
||||
* oyvind.harboe@zylin.com *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
|
||||
@@ -184,36 +184,37 @@ int jtag_build_buffer(const scan_command_t *cmd, uint8_t **buffer)
|
||||
|
||||
bit_count = 0;
|
||||
|
||||
#ifdef _DEBUG_JTAG_IO_
|
||||
LOG_DEBUG("%s num_fields: %i", cmd->ir_scan ? "IRSCAN" : "DRSCAN", cmd->num_fields);
|
||||
#endif
|
||||
DEBUG_JTAG_IO("%s num_fields: %i",
|
||||
cmd->ir_scan ? "IRSCAN" : "DRSCAN",
|
||||
cmd->num_fields);
|
||||
|
||||
for (i = 0; i < cmd->num_fields; i++)
|
||||
{
|
||||
if (cmd->fields[i].out_value)
|
||||
{
|
||||
#ifdef _DEBUG_JTAG_IO_
|
||||
char* char_buf = buf_to_str(cmd->fields[i].out_value, (cmd->fields[i].num_bits > DEBUG_JTAG_IOZ) ? DEBUG_JTAG_IOZ : cmd->fields[i].num_bits, 16);
|
||||
#endif
|
||||
buf_set_buf(cmd->fields[i].out_value, 0, *buffer, bit_count, cmd->fields[i].num_bits);
|
||||
#ifdef _DEBUG_JTAG_IO_
|
||||
LOG_DEBUG("fields[%i].out_value[%i]: 0x%s", i, cmd->fields[i].num_bits, char_buf);
|
||||
char *char_buf = buf_to_str(cmd->fields[i].out_value,
|
||||
(cmd->fields[i].num_bits > DEBUG_JTAG_IOZ)
|
||||
? DEBUG_JTAG_IOZ
|
||||
: cmd->fields[i].num_bits, 16);
|
||||
|
||||
LOG_DEBUG("fields[%i].out_value[%i]: 0x%s", i,
|
||||
cmd->fields[i].num_bits, char_buf);
|
||||
free(char_buf);
|
||||
#endif
|
||||
buf_set_buf(cmd->fields[i].out_value, 0, *buffer,
|
||||
bit_count, cmd->fields[i].num_bits);
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef _DEBUG_JTAG_IO_
|
||||
LOG_DEBUG("fields[%i].out_value[%i]: NULL", i, cmd->fields[i].num_bits);
|
||||
#endif
|
||||
DEBUG_JTAG_IO("fields[%i].out_value[%i]: NULL",
|
||||
i, cmd->fields[i].num_bits);
|
||||
}
|
||||
|
||||
bit_count += cmd->fields[i].num_bits;
|
||||
}
|
||||
|
||||
#ifdef _DEBUG_JTAG_IO_
|
||||
//LOG_DEBUG("bit_count totalling: %i", bit_count);
|
||||
#endif
|
||||
//DEBUG_JTAG_IO("bit_count totalling: %i", bit_count);
|
||||
|
||||
return bit_count;
|
||||
}
|
||||
@@ -238,8 +239,13 @@ int jtag_read_buffer(uint8_t *buffer, const scan_command_t *cmd)
|
||||
uint8_t *captured = buf_set_buf(buffer, bit_count, malloc(CEIL(num_bits, 8)), 0, num_bits);
|
||||
|
||||
#ifdef _DEBUG_JTAG_IO_
|
||||
char *char_buf = buf_to_str(captured, (num_bits > DEBUG_JTAG_IOZ) ? DEBUG_JTAG_IOZ : num_bits, 16);
|
||||
LOG_DEBUG("fields[%i].in_value[%i]: 0x%s", i, num_bits, char_buf);
|
||||
char *char_buf = buf_to_str(captured,
|
||||
(num_bits > DEBUG_JTAG_IOZ)
|
||||
? DEBUG_JTAG_IOZ
|
||||
: num_bits, 16);
|
||||
|
||||
LOG_DEBUG("fields[%i].in_value[%i]: 0x%s",
|
||||
i, num_bits, char_buf);
|
||||
free(char_buf);
|
||||
#endif
|
||||
|
||||
|
||||
922
src/jtag/core.c
922
src/jtag/core.c
File diff suppressed because it is too large
Load Diff
@@ -489,6 +489,11 @@ void interface_jtag_add_callback4(jtag_callback_t callback, jtag_callback_data_t
|
||||
|
||||
int interface_jtag_execute_queue(void)
|
||||
{
|
||||
static int reentry = 0;
|
||||
|
||||
assert(reentry==0);
|
||||
reentry++;
|
||||
|
||||
int retval = default_interface_jtag_execute_queue();
|
||||
if (retval == ERROR_OK)
|
||||
{
|
||||
@@ -504,6 +509,8 @@ int interface_jtag_execute_queue(void)
|
||||
jtag_command_queue_reset();
|
||||
jtag_callback_queue_reset();
|
||||
|
||||
reentry--;
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2008 by Øyvind Harboe *
|
||||
* Copyright (C) 2008 by Øyvind Harboe *
|
||||
* oyvind.harboe@zylin.com *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
|
||||
1248
src/jtag/ft2232.c
1248
src/jtag/ft2232.c
File diff suppressed because it is too large
Load Diff
@@ -2,7 +2,7 @@
|
||||
* Copyright (C) 2005 by Dominic Rath *
|
||||
* Dominic.Rath@gmx.de *
|
||||
* *
|
||||
* Copyright (C) 2007,2008 Øyvind Harboe *
|
||||
* Copyright (C) 2007,2008 Øyvind Harboe *
|
||||
* oyvind.harboe@zylin.com *
|
||||
* *
|
||||
* Copyright (C) 2009 SoftPLC Corporation *
|
||||
@@ -73,20 +73,23 @@ tap_state_t tap_get_end_state()
|
||||
|
||||
int tap_move_ndx(tap_state_t astate)
|
||||
{
|
||||
/* given a stable state, return the index into the tms_seqs[] array within tap_get_tms_path() */
|
||||
/* given a stable state, return the index into the tms_seqs[]
|
||||
* array within tap_get_tms_path()
|
||||
*/
|
||||
|
||||
int ndx;
|
||||
|
||||
switch (astate)
|
||||
{
|
||||
case TAP_RESET: ndx = 0; break;
|
||||
case TAP_IDLE: ndx = 1; break;
|
||||
case TAP_DRSHIFT: ndx = 2; break;
|
||||
case TAP_DRPAUSE: ndx = 3; break;
|
||||
case TAP_IDLE: ndx = 1; break;
|
||||
case TAP_IRSHIFT: ndx = 4; break;
|
||||
case TAP_IRPAUSE: ndx = 5; break;
|
||||
default:
|
||||
LOG_ERROR("fatal: unstable state \"%s\" used in tap_move_ndx()", tap_state_name(astate));
|
||||
LOG_ERROR("FATAL: unstable state \"%s\" in tap_move_ndx()",
|
||||
tap_state_name(astate));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
@@ -95,12 +98,7 @@ int tap_move_ndx(tap_state_t astate)
|
||||
|
||||
|
||||
/* tap_move[i][j]: tap movement command to go from state i to state j
|
||||
* 0: Test-Logic-Reset
|
||||
* 1: Run-Test/Idle
|
||||
* 2: Shift-DR
|
||||
* 3: Pause-DR
|
||||
* 4: Shift-IR
|
||||
* 5: Pause-IR
|
||||
* encodings of i and j are what tap_move_ndx() reports.
|
||||
*
|
||||
* DRSHIFT->DRSHIFT and IRSHIFT->IRSHIFT have to be caught in interface specific code
|
||||
*/
|
||||
@@ -108,7 +106,6 @@ struct tms_sequences
|
||||
{
|
||||
uint8_t bits;
|
||||
uint8_t bit_count;
|
||||
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -133,13 +130,10 @@ static const struct tms_sequences old_tms_seqs[6][6] = /* [from_state_ndx][to_
|
||||
{
|
||||
/* value clocked to TMS to move from one of six stable states to another.
|
||||
* N.B. OOCD clocks TMS from LSB first, so read these right-to-left.
|
||||
* N.B. These values are tightly bound to the table in tap_get_tms_path_len().
|
||||
* N.B. Reset only needs to be 0b11111, but in JLink an even byte of 1's is more stable.
|
||||
* These extra ones cause no TAP state problem, because we go into reset and stay in reset.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/* to state: */
|
||||
/* RESET IDLE DRSHIFT DRPAUSE IRSHIFT IRPAUSE */ /* from state: */
|
||||
{ B8(1111111,7), B8(0000000,7), B8(0010111,7), B8(0001010,7), B8(0011011,7), B8(0010110,7) }, /* RESET */
|
||||
@@ -168,24 +162,33 @@ static const struct tms_sequences short_tms_seqs[6][6] = /* [from_state_ndx][t
|
||||
|
||||
state specific comments:
|
||||
------------------------
|
||||
*->RESET tried the 5 bit reset and it gave me problems, 7 bits seems to
|
||||
*->RESET tried the 5 bit reset and it gave me problems, 7 bits seems to
|
||||
work better on ARM9 with ft2232 driver. (Dick)
|
||||
|
||||
RESET->DRSHIFT add 1 extra clock cycles in the RESET state before advancing.
|
||||
needed on ARM9 with ft2232 driver. (Dick)
|
||||
(For a total of *THREE* extra clocks in RESET; NOP.)
|
||||
|
||||
RESET->IRSHIFT add 1 extra clock cycles in the RESET state before advancing.
|
||||
needed on ARM9 with ft2232 driver. (Dick)
|
||||
(For a total of *TWO* extra clocks in RESET; NOP.)
|
||||
|
||||
RESET->* always adds one or more clocks in the target state,
|
||||
which should be NOPS; except shift states which (as
|
||||
noted above) add those clocks in RESET.
|
||||
|
||||
The X-to-X transitions always add clocks; from *SHIFT, they go
|
||||
via IDLE and thus *DO HAVE SIDE EFFECTS* (capture and update).
|
||||
*/
|
||||
|
||||
/* to state: */
|
||||
/* RESET IDLE DRSHIFT DRPAUSE IRSHIFT IRPAUSE */ /* from state: */
|
||||
{ B8(1111111,7), B8(0000000,7), B8(0010111,7), B8(0001010,7), B8(0011011,7), B8(0010110,7) }, /* RESET */
|
||||
{ B8(1111111,7), B8(0000000,7), B8(001,3), B8(0101,4), B8(0011,4), B8(01011,5) }, /* IDLE */
|
||||
{ B8(1111111,7), B8(011,3), B8(00111,5), B8(01,2), B8(001111,6), B8(0101111,7) }, /* DRSHIFT */
|
||||
{ B8(1111111,7), B8(011,3), B8(01,2), B8(0,1), B8(001111,6), B8(0101111,7) }, /* DRPAUSE */
|
||||
{ B8(1111111,7), B8(011,3), B8(00111,5), B8(010111,6), B8(001111,6), B8(01,2) }, /* IRSHIFT */
|
||||
{ B8(1111111,7), B8(011,3), B8(00111,5), B8(010111,6), B8(01,2), B8(0,1) } /* IRPAUSE */
|
||||
/* RESET IDLE DRSHIFT DRPAUSE IRSHIFT IRPAUSE */ /* from state: */
|
||||
{ B8(1111111,7), B8(0000000,7), B8(0010111,7), B8(0001010,7), B8(0011011,7), B8(0010110,7) }, /* RESET */
|
||||
{ B8(1111111,7), B8(0000000,7), B8(001,3), B8(0101,4), B8(0011,4), B8(01011,5) }, /* IDLE */
|
||||
{ B8(1111111,7), B8(011,3), B8(00111,5), B8(01,2), B8(001111,6), B8(0101111,7) }, /* DRSHIFT */
|
||||
{ B8(1111111,7), B8(011,3), B8(01,2), B8(0,1), B8(001111,6), B8(0101111,7) }, /* DRPAUSE */
|
||||
{ B8(1111111,7), B8(011,3), B8(00111,5), B8(010111,6), B8(001111,6), B8(01,2) }, /* IRSHIFT */
|
||||
{ B8(1111111,7), B8(011,3), B8(00111,5), B8(010111,6), B8(01,2), B8(0,1)} /* IRPAUSE */
|
||||
|
||||
};
|
||||
|
||||
@@ -327,43 +330,54 @@ tap_state_t tap_state_transition(tap_state_t cur_state, bool tms)
|
||||
return new_state;
|
||||
}
|
||||
|
||||
const char* tap_state_name(tap_state_t state)
|
||||
|
||||
/* NOTE: do not change these state names. They're documented,
|
||||
* and we rely on them to match SVF input (except for "RUN/IDLE").
|
||||
*/
|
||||
static const struct name_mapping {
|
||||
enum tap_state symbol;
|
||||
const char *name;
|
||||
} tap_name_mapping[] = {
|
||||
{ TAP_RESET, "RESET", },
|
||||
{ TAP_IDLE, "RUN/IDLE", },
|
||||
{ TAP_DRSELECT, "DRSELECT", },
|
||||
{ TAP_DRCAPTURE,"DRCAPTURE", },
|
||||
{ TAP_DRSHIFT, "DRSHIFT", },
|
||||
{ TAP_DREXIT1, "DREXIT1", },
|
||||
{ TAP_DRPAUSE, "DRPAUSE", },
|
||||
{ TAP_DREXIT2, "DREXIT2", },
|
||||
{ TAP_DRUPDATE, "DRUPDATE", },
|
||||
{ TAP_IRSELECT, "IRSELECT", },
|
||||
{ TAP_IRCAPTURE,"IRCAPTURE", },
|
||||
{ TAP_IRSHIFT, "IRSHIFT", },
|
||||
{ TAP_IREXIT1, "IREXIT1", },
|
||||
{ TAP_IRPAUSE, "IRPAUSE", },
|
||||
{ TAP_IREXIT2, "IREXIT2", },
|
||||
{ TAP_IRUPDATE, "IRUPDATE", },
|
||||
|
||||
/* only for input: accept standard SVF name */
|
||||
{ TAP_IDLE, "IDLE", },
|
||||
};
|
||||
|
||||
const char *tap_state_name(tap_state_t state)
|
||||
{
|
||||
const char* ret;
|
||||
unsigned i;
|
||||
|
||||
switch (state)
|
||||
{
|
||||
case TAP_RESET: ret = "RESET"; break;
|
||||
case TAP_IDLE: ret = "RUN/IDLE"; break;
|
||||
case TAP_DRSELECT: ret = "DRSELECT"; break;
|
||||
case TAP_DRCAPTURE: ret = "DRCAPTURE"; break;
|
||||
case TAP_DRSHIFT: ret = "DRSHIFT"; break;
|
||||
case TAP_DREXIT1: ret = "DREXIT1"; break;
|
||||
case TAP_DRPAUSE: ret = "DRPAUSE"; break;
|
||||
case TAP_DREXIT2: ret = "DREXIT2"; break;
|
||||
case TAP_DRUPDATE: ret = "DRUPDATE"; break;
|
||||
case TAP_IRSELECT: ret = "IRSELECT"; break;
|
||||
case TAP_IRCAPTURE: ret = "IRCAPTURE"; break;
|
||||
case TAP_IRSHIFT: ret = "IRSHIFT"; break;
|
||||
case TAP_IREXIT1: ret = "IREXIT1"; break;
|
||||
case TAP_IRPAUSE: ret = "IRPAUSE"; break;
|
||||
case TAP_IREXIT2: ret = "IREXIT2"; break;
|
||||
case TAP_IRUPDATE: ret = "IRUPDATE"; break;
|
||||
default: ret = "???";
|
||||
for (i = 0; i < DIM(tap_name_mapping); i++) {
|
||||
if (tap_name_mapping[i].symbol == state)
|
||||
return tap_name_mapping[i].name;
|
||||
}
|
||||
|
||||
return ret;
|
||||
return "???";
|
||||
}
|
||||
|
||||
tap_state_t tap_state_by_name(const char *name)
|
||||
{
|
||||
tap_state_t x;
|
||||
unsigned i;
|
||||
|
||||
for (x = 0 ; x < TAP_NUM_STATES ; x++) {
|
||||
for (i = 0; i < DIM(tap_name_mapping); i++) {
|
||||
/* be nice to the human */
|
||||
if (0 == strcasecmp(name, tap_state_name(x))) {
|
||||
return x;
|
||||
}
|
||||
if (strcasecmp(name, tap_name_mapping[i].name) == 0)
|
||||
return tap_name_mapping[i].symbol;
|
||||
}
|
||||
/* not found */
|
||||
return TAP_INVALID;
|
||||
|
||||
@@ -160,9 +160,6 @@ bool tap_is_state_stable(tap_state_t astate);
|
||||
*/
|
||||
tap_state_t tap_state_transition(tap_state_t current_state, bool tms);
|
||||
|
||||
/// Provides user-friendly name lookup of TAP states.
|
||||
tap_state_t tap_state_by_name(const char *name);
|
||||
|
||||
/// Allow switching between old and new TMS tables. @see tap_get_tms_path
|
||||
void tap_use_new_tms_table(bool use_new);
|
||||
/// @returns True if new TMS table is active; false otherwise.
|
||||
|
||||
@@ -499,12 +499,10 @@ static void jlink_reset(int trst, int srst)
|
||||
{
|
||||
jlink_simple_command(EMU_CMD_HW_TRST0);
|
||||
}
|
||||
|
||||
if (trst == 0)
|
||||
{
|
||||
jlink_simple_command(EMU_CMD_HW_TRST1);
|
||||
jtag_sleep(5000);
|
||||
jlink_end_state(TAP_RESET);
|
||||
jlink_state_move();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
126
src/jtag/jtag.h
126
src/jtag/jtag.h
@@ -2,7 +2,7 @@
|
||||
* Copyright (C) 2005 by Dominic Rath *
|
||||
* Dominic.Rath@gmx.de *
|
||||
* *
|
||||
* Copyright (C) 2007,2008 Øyvind Harboe *
|
||||
* Copyright (C) 2007,2008 Øyvind Harboe *
|
||||
* oyvind.harboe@zylin.com *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
@@ -28,9 +28,11 @@
|
||||
|
||||
|
||||
#ifdef _DEBUG_JTAG_IO_
|
||||
#define DEBUG_JTAG_IO(expr ...) LOG_DEBUG(expr)
|
||||
#define DEBUG_JTAG_IO(expr ...) \
|
||||
do { if (1) LOG_DEBUG(expr); } while (0)
|
||||
#else
|
||||
#define DEBUG_JTAG_IO(expr ...)
|
||||
#define DEBUG_JTAG_IO(expr ...) \
|
||||
do { if (0) LOG_DEBUG(expr); } while (0)
|
||||
#endif
|
||||
|
||||
#ifndef DEBUG_JTAG_IOZ
|
||||
@@ -55,13 +57,17 @@
|
||||
*
|
||||
* These definitions were gleaned from the ARM7TDMI-S Technical
|
||||
* Reference Manual and validated against several other ARM core
|
||||
* technical manuals. tap_get_tms_path() is sensitive to this numbering
|
||||
* and ordering of the TAP states; furthermore, some interfaces require
|
||||
* specific numbers be used, as they are handed-off directly to their
|
||||
* hardware implementations.
|
||||
* technical manuals.
|
||||
*
|
||||
* FIXME some interfaces require specific numbers be used, as they
|
||||
* are handed-off directly to their hardware implementations.
|
||||
* Fix those drivers to map as appropriate ... then pick some
|
||||
* sane set of numbers here (where 0/uninitialized == INVALID).
|
||||
*/
|
||||
typedef enum tap_state
|
||||
{
|
||||
TAP_INVALID = -1,
|
||||
|
||||
#if BUILD_ZY1000
|
||||
/* These are the old numbers. Leave as-is for now... */
|
||||
TAP_RESET = 0, TAP_IDLE = 8,
|
||||
@@ -70,7 +76,6 @@ typedef enum tap_state
|
||||
TAP_IRSELECT = 9, TAP_IRCAPTURE = 10, TAP_IRSHIFT = 11, TAP_IREXIT1 = 12,
|
||||
TAP_IRPAUSE = 13, TAP_IREXIT2 = 14, TAP_IRUPDATE = 15,
|
||||
|
||||
TAP_NUM_STATES = 16, TAP_INVALID = -1,
|
||||
#else
|
||||
/* Proper ARM recommended numbers */
|
||||
TAP_DREXIT2 = 0x0,
|
||||
@@ -90,9 +95,6 @@ typedef enum tap_state
|
||||
TAP_IRCAPTURE = 0xe,
|
||||
TAP_RESET = 0x0f,
|
||||
|
||||
TAP_NUM_STATES = 0x10,
|
||||
|
||||
TAP_INVALID = -1,
|
||||
#endif
|
||||
} tap_state_t;
|
||||
|
||||
@@ -100,7 +102,10 @@ typedef enum tap_state
|
||||
* Function tap_state_name
|
||||
* Returns a string suitable for display representing the JTAG tap_state
|
||||
*/
|
||||
const char* tap_state_name(tap_state_t state);
|
||||
const char *tap_state_name(tap_state_t state);
|
||||
|
||||
/// Provides user-friendly name lookup of TAP states.
|
||||
tap_state_t tap_state_by_name(const char *name);
|
||||
|
||||
/// The current TAP state of the pending JTAG command queue.
|
||||
extern tap_state_t cmd_queue_cur_state;
|
||||
@@ -144,7 +149,7 @@ typedef struct jtag_tap_event_action_s jtag_tap_event_action_t;
|
||||
|
||||
/* this is really: typedef jtag_tap_t */
|
||||
/* But - the typedef is done in "types.h" */
|
||||
/* due to "forward decloration reasons" */
|
||||
/* due to "forward declaration reasons" */
|
||||
struct jtag_tap_s
|
||||
{
|
||||
const char* chip;
|
||||
@@ -161,6 +166,7 @@ struct jtag_tap_s
|
||||
uint32_t ir_capture_mask;
|
||||
uint8_t* expected_mask; /**< Capture-IR expected mask */
|
||||
uint32_t idcode;
|
||||
bool hasidcode; /* not all devices have idcode, we'll discover this during chain examination */
|
||||
/**< device identification code */
|
||||
|
||||
/// Array of expected identification codes */
|
||||
@@ -191,20 +197,30 @@ extern unsigned jtag_tap_count(void);
|
||||
|
||||
|
||||
/*
|
||||
* There are three cases when JTAG_TRST_ASSERTED callback is invoked. The
|
||||
* event is invoked *after* TRST is asserted(or queued rather). It is illegal
|
||||
* to communicate with the JTAG interface during the callback(as there is
|
||||
* currently a queue being built).
|
||||
* - TRST_ASSERTED triggers two sets of callbacks, after operations to
|
||||
* reset the scan chain -- via TMS+TCK signaling, or deasserting the
|
||||
* nTRST signal -- are queued:
|
||||
*
|
||||
* - TMS reset
|
||||
* - SRST pulls TRST
|
||||
* - TRST asserted
|
||||
* + Callbacks in C code fire first, patching internal state
|
||||
* + Then post-reset event scripts fire ... activating JTAG circuits
|
||||
* via TCK cycles, exiting SWD mode via TMS sequences, etc
|
||||
*
|
||||
* TAP activation/deactivation is currently implemented outside the core
|
||||
* using scripted code that understands the specific router type.
|
||||
* During those callbacks, scan chain contents have not been validated.
|
||||
* JTAG operations that address a specific TAP (primarily DR/IR scans)
|
||||
* must *not* be queued.
|
||||
*
|
||||
* - TAP_EVENT_SETUP is reported after TRST_ASSERTED, and after the scan
|
||||
* chain has been validated. JTAG operations including scans that
|
||||
* target specific TAPs may be performed.
|
||||
*
|
||||
* - TAP_EVENT_ENABLE and TAP_EVENT_DISABLE implement TAP activation and
|
||||
* deactivation outside the core using scripted code that understands
|
||||
* the specific JTAG router type. They might be triggered indirectly
|
||||
* from EVENT_SETUP operations.
|
||||
*/
|
||||
enum jtag_event {
|
||||
JTAG_TRST_ASSERTED,
|
||||
JTAG_TAP_EVENT_SETUP,
|
||||
JTAG_TAP_EVENT_ENABLE,
|
||||
JTAG_TAP_EVENT_DISABLE,
|
||||
};
|
||||
@@ -252,13 +268,16 @@ int jtag_get_speed_readable(int *speed);
|
||||
* @returns ERROR_OK during configuration or on success, or an error
|
||||
* code returned from the interface @c speed callback.
|
||||
*/
|
||||
int jtag_set_speed(int speed);
|
||||
int jtag_config_speed(int speed);
|
||||
|
||||
|
||||
/// Attempt to configure the interface for the specified KHz.
|
||||
int jtag_config_khz(unsigned khz);
|
||||
/// Set the clock speed of the JTAG interface in KHz.
|
||||
void jtag_set_speed_khz(unsigned speed);
|
||||
/**
|
||||
* Attempt to enable RTCK/RCLK. If that fails, fallback to the
|
||||
* specified frequency.
|
||||
*/
|
||||
int jtag_config_rclk(unsigned fallback_speed_khz);
|
||||
/// Retreives the clock speed of the JTAG interface in KHz.
|
||||
unsigned jtag_get_speed_khz(void);
|
||||
|
||||
@@ -272,6 +291,7 @@ enum reset_types {
|
||||
RESET_TRST_PULLS_SRST = 0x8,
|
||||
RESET_TRST_OPEN_DRAIN = 0x10,
|
||||
RESET_SRST_PUSH_PULL = 0x20,
|
||||
RESET_SRST_NO_GATING = 0x40,
|
||||
};
|
||||
|
||||
enum reset_types jtag_get_reset_config(void);
|
||||
@@ -283,6 +303,12 @@ unsigned jtag_get_nsrst_delay(void);
|
||||
void jtag_set_ntrst_delay(unsigned delay);
|
||||
unsigned jtag_get_ntrst_delay(void);
|
||||
|
||||
void jtag_set_nsrst_assert_width(unsigned delay);
|
||||
unsigned jtag_get_nsrst_assert_width(void);
|
||||
|
||||
void jtag_set_ntrst_assert_width(unsigned delay);
|
||||
unsigned jtag_get_ntrst_assert_width(void);
|
||||
|
||||
/// @returns The current state of TRST.
|
||||
int jtag_get_trst(void);
|
||||
/// @returns The current state of SRST.
|
||||
@@ -314,8 +340,9 @@ extern int jtag_interface_quit(void);
|
||||
extern int jtag_init(struct command_context_s* cmd_ctx);
|
||||
|
||||
/// reset, then initialize JTAG chain
|
||||
extern int jtag_init_reset(struct command_context_s* cmd_ctx);
|
||||
extern int jtag_register_commands(struct command_context_s* cmd_ctx);
|
||||
extern int jtag_init_reset(struct command_context_s* cmd_ctx);
|
||||
extern int jtag_register_commands(struct command_context_s* cmd_ctx);
|
||||
extern int jtag_init_inner(struct command_context_s *cmd_ctx);
|
||||
|
||||
/**
|
||||
* @file
|
||||
@@ -512,29 +539,7 @@ extern void jtag_add_pathmove(int num_states, const tap_state_t* path);
|
||||
* @return ERROR_OK on success, or an error code on failure.
|
||||
*
|
||||
* Moves from the current state to the goal \a state.
|
||||
*
|
||||
* This needs to be handled according to the xsvf spec, see the XSTATE
|
||||
* command description. From the XSVF spec, pertaining to XSTATE:
|
||||
*
|
||||
* For special states known as stable states (Test-Logic-Reset,
|
||||
* Run-Test/Idle, Pause-DR, Pause- IR), an XSVF interpreter follows
|
||||
* predefined TAP state paths when the starting state is a stable state
|
||||
* and when the XSTATE specifies a new stable state. See the STATE
|
||||
* command in the [Ref 5] for the TAP state paths between stable
|
||||
* states.
|
||||
*
|
||||
* For non-stable states, XSTATE should specify a state that is only one
|
||||
* TAP state transition distance from the current TAP state to avoid
|
||||
* undefined TAP state paths. A sequence of multiple XSTATE commands can
|
||||
* be issued to transition the TAP through a specific state path.
|
||||
*
|
||||
* @note Unless @c tms_bits holds a path that agrees with [Ref 5] in the
|
||||
* above spec, then this code is not fully conformant to the xsvf spec.
|
||||
* This puts a burden on tap_get_tms_path() function from the xsvf spec.
|
||||
* If in doubt, you should confirm that that burden is being met.
|
||||
*
|
||||
* Otherwise, @a goal_state must be immediately reachable in one clock
|
||||
* cycle, and does not need to be a stable state.
|
||||
* Both states must be stable.
|
||||
*/
|
||||
extern int jtag_add_statemove(tap_state_t goal_state);
|
||||
|
||||
@@ -631,6 +636,9 @@ extern void jtag_execute_queue_noclear(void);
|
||||
/// @returns the number of times the scan queue has been flushed
|
||||
int jtag_get_flush_queue_count(void);
|
||||
|
||||
/// Report Tcl event to all TAPs
|
||||
void jtag_notify_event(enum jtag_event);
|
||||
|
||||
|
||||
/* can be implemented by hw + sw */
|
||||
extern int jtag_power_dropout(int* dropout);
|
||||
@@ -662,6 +670,7 @@ extern void jtag_sleep(uint32_t us);
|
||||
#define ERROR_JTAG_DEVICE_ERROR (-107)
|
||||
#define ERROR_JTAG_STATE_INVALID (-108)
|
||||
#define ERROR_JTAG_TRANSITION_INVALID (-109)
|
||||
#define ERROR_JTAG_INIT_SOFT_FAIL (-110)
|
||||
|
||||
/**
|
||||
* jtag_add_dr_out() is a version of jtag_add_dr_scan() which
|
||||
@@ -709,4 +718,21 @@ int jtag_get_error(void);
|
||||
*/
|
||||
int jtag_error_clear(void);
|
||||
|
||||
/**
|
||||
* Return true if it's safe for a background polling task to access the
|
||||
* JTAG scan chain. Polling may be explicitly disallowed, and is also
|
||||
* unsafe while nTRST is active or the JTAG clock is gated off.,
|
||||
*/
|
||||
bool is_jtag_poll_safe(void);
|
||||
|
||||
/**
|
||||
* Return flag reporting whether JTAG polling is disallowed.
|
||||
*/
|
||||
bool jtag_poll_get_enabled(void);
|
||||
|
||||
/**
|
||||
* Assign flag reporting whether JTAG polling is disallowed.
|
||||
*/
|
||||
void jtag_poll_set_enabled(bool value);
|
||||
|
||||
#endif /* JTAG_H */
|
||||
|
||||
@@ -120,7 +120,6 @@ extern int interface_jtag_add_runtest(int num_cycles, tap_state_t endstate);
|
||||
* approperiate
|
||||
*/
|
||||
extern int interface_jtag_add_reset(int trst, int srst);
|
||||
extern int interface_jtag_set_end_state(tap_state_t endstate);
|
||||
extern int interface_jtag_add_sleep(uint32_t us);
|
||||
extern int interface_jtag_add_clocks(int num_cycles);
|
||||
extern int interface_jtag_execute_queue(void);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2007-2008 by Øyvind Harboe *
|
||||
* Copyright (C) 2007-2008 by Øyvind Harboe *
|
||||
* *
|
||||
* 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 *
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2007-2008 by Øyvind Harboe *
|
||||
* Copyright (C) 2007-2008 by Øyvind Harboe *
|
||||
* *
|
||||
* 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 *
|
||||
@@ -59,12 +59,6 @@ int interface_jtag_execute_queue(void)
|
||||
|
||||
extern int jtag_check_value(uint8_t *captured, void *priv);
|
||||
|
||||
int interface_jtag_set_end_state(tap_state_t state)
|
||||
{
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
|
||||
int interface_jtag_add_ir_scan(int num_fields, const scan_field_t *fields, tap_state_t state)
|
||||
{
|
||||
/* synchronously do the operation here */
|
||||
|
||||
@@ -247,7 +247,7 @@ static int parport_speed(int speed)
|
||||
static int parport_register_commands(struct command_context_s *cmd_ctx)
|
||||
{
|
||||
register_command(cmd_ctx, NULL, "parport_port", parport_handle_parport_port_command,
|
||||
COMMAND_CONFIG, "either the address of the I/O port or the number of the ‘/dev/parport’ device");
|
||||
COMMAND_CONFIG, "either the address of the I/O port or the number of the '/dev/parport' device");
|
||||
register_command(cmd_ctx, NULL, "parport_cable", parport_handle_parport_cable_command,
|
||||
COMMAND_CONFIG, "the layout of the parallel port cable used to connect to the target");
|
||||
register_command(cmd_ctx, NULL, "parport_write_on_exit", parport_handle_write_on_exit_command,
|
||||
@@ -337,7 +337,8 @@ static int parport_init(void)
|
||||
|
||||
if (device_handle < 0)
|
||||
{
|
||||
LOG_ERROR("cannot open device. check it exists and that user read and write rights are set");
|
||||
int err = errno;
|
||||
LOG_ERROR("cannot open device. check it exists and that user read and write rights are set. errno=%d", err);
|
||||
return ERROR_JTAG_INIT_FAILED;
|
||||
}
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* Copyright (C) 2005 by Dominic Rath *
|
||||
* Dominic.Rath@gmx.de *
|
||||
* *
|
||||
* Copyright (C) 2007,2008 Øyvind Harboe *
|
||||
* Copyright (C) 2007,2008 Øyvind Harboe *
|
||||
* oyvind.harboe@zylin.com *
|
||||
* *
|
||||
* Copyright (C) 2008 Rob Brown, Lou Deluxe *
|
||||
|
||||
335
src/jtag/tcl.c
335
src/jtag/tcl.c
@@ -2,7 +2,7 @@
|
||||
* Copyright (C) 2005 by Dominic Rath *
|
||||
* Dominic.Rath@gmx.de *
|
||||
* *
|
||||
* Copyright (C) 2007,2008 <EFBFBD>yvind Harboe *
|
||||
* Copyright (C) 2007,2008 Øyvind Harboe *
|
||||
* oyvind.harboe@zylin.com *
|
||||
* *
|
||||
* Copyright (C) 2009 SoftPLC Corporation *
|
||||
@@ -41,6 +41,8 @@
|
||||
#endif
|
||||
|
||||
static const Jim_Nvp nvp_jtag_tap_event[] = {
|
||||
{ .value = JTAG_TRST_ASSERTED, .name = "post-reset" },
|
||||
{ .value = JTAG_TAP_EVENT_SETUP, .name = "setup" },
|
||||
{ .value = JTAG_TAP_EVENT_ENABLE, .name = "tap-enable" },
|
||||
{ .value = JTAG_TAP_EVENT_DISABLE, .name = "tap-disable" },
|
||||
|
||||
@@ -55,10 +57,13 @@ static int handle_interface_list_command(struct command_context_s *cmd_ctx,
|
||||
static int handle_interface_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
|
||||
static int handle_jtag_speed_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
|
||||
static int handle_jtag_khz_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
|
||||
static int handle_jtag_rclk_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
|
||||
static int handle_jtag_device_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
|
||||
static int handle_reset_config_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
|
||||
static int handle_jtag_nsrst_delay_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
|
||||
static int handle_jtag_ntrst_delay_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
|
||||
static int handle_jtag_nsrst_assert_width_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
|
||||
static int handle_jtag_ntrst_assert_width_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
|
||||
|
||||
static int handle_scan_chain_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
|
||||
|
||||
@@ -73,8 +78,6 @@ static int handle_verify_ircapture_command(struct command_context_s *cmd_ctx, ch
|
||||
static int handle_verify_jtag_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
|
||||
static int handle_tms_sequence_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
|
||||
|
||||
extern int jtag_examine_chain(void);
|
||||
extern int jtag_validate_chain(void);
|
||||
|
||||
enum jtag_tap_cfg_param {
|
||||
JCFG_EVENT
|
||||
@@ -140,9 +143,11 @@ static int jtag_tap_configure_cmd(Jim_GetOptInfo *goi, jtag_tap_t * tap)
|
||||
}
|
||||
|
||||
if (goi->isconfigure) {
|
||||
bool replace = true;
|
||||
if (jteap == NULL) {
|
||||
/* create new */
|
||||
jteap = calloc(1, sizeof (*jteap));
|
||||
replace = false;
|
||||
}
|
||||
jteap->event = n->value;
|
||||
Jim_GetOpt_Obj(goi, &o);
|
||||
@@ -152,9 +157,12 @@ static int jtag_tap_configure_cmd(Jim_GetOptInfo *goi, jtag_tap_t * tap)
|
||||
jteap->body = Jim_DuplicateObj(goi->interp, o);
|
||||
Jim_IncrRefCount(jteap->body);
|
||||
|
||||
/* add to head of event list */
|
||||
jteap->next = tap->event_action;
|
||||
tap->event_action = jteap;
|
||||
if (!replace)
|
||||
{
|
||||
/* add to head of event list */
|
||||
jteap->next = tap->event_action;
|
||||
tap->event_action = jteap;
|
||||
}
|
||||
Jim_SetEmptyResult(goi->interp);
|
||||
} else {
|
||||
/* get */
|
||||
@@ -189,7 +197,6 @@ static int jim_newtap_cmd(Jim_GetOptInfo *goi)
|
||||
jim_wide w;
|
||||
int x;
|
||||
int e;
|
||||
int reqbits;
|
||||
Jim_Nvp *n;
|
||||
char *cp;
|
||||
const Jim_Nvp opts[] = {
|
||||
@@ -219,6 +226,7 @@ static int jim_newtap_cmd(Jim_GetOptInfo *goi)
|
||||
* */
|
||||
if (goi->argc < 3) {
|
||||
Jim_SetResult_sprintf(goi->interp, "Missing CHIP TAP OPTIONS ....");
|
||||
free(pTap);
|
||||
return JIM_ERR;
|
||||
}
|
||||
Jim_GetOpt_String(goi, &cp, NULL);
|
||||
@@ -236,18 +244,19 @@ static int jim_newtap_cmd(Jim_GetOptInfo *goi)
|
||||
LOG_DEBUG("Creating New Tap, Chip: %s, Tap: %s, Dotted: %s, %d params",
|
||||
pTap->chip, pTap->tapname, pTap->dotted_name, goi->argc);
|
||||
|
||||
/* deal with options */
|
||||
#define NTREQ_IRLEN 1
|
||||
#define NTREQ_IRCAPTURE 2
|
||||
#define NTREQ_IRMASK 4
|
||||
|
||||
/* clear them as we find them */
|
||||
reqbits = (NTREQ_IRLEN | NTREQ_IRCAPTURE | NTREQ_IRMASK);
|
||||
/* IEEE specifies that the two LSBs of an IR scan are 01, so make
|
||||
* that the default. The "-irlen" and "-irmask" options are only
|
||||
* needed to cope with nonstandard TAPs, or to specify more bits.
|
||||
*/
|
||||
pTap->ir_capture_mask = 0x03;
|
||||
pTap->ir_capture_value = 0x01;
|
||||
|
||||
while (goi->argc) {
|
||||
e = Jim_GetOpt_Nvp(goi, opts, &n);
|
||||
if (e != JIM_OK) {
|
||||
Jim_GetOpt_NvpUnknown(goi, opts, 0);
|
||||
free((void *)pTap->dotted_name);
|
||||
free(pTap);
|
||||
return e;
|
||||
}
|
||||
LOG_DEBUG("Processing option: %s", n->name);
|
||||
@@ -265,12 +274,16 @@ static int jim_newtap_cmd(Jim_GetOptInfo *goi)
|
||||
e = Jim_GetOpt_Wide(goi, &w);
|
||||
if (e != JIM_OK) {
|
||||
Jim_SetResult_sprintf(goi->interp, "option: %s bad parameter", n->name);
|
||||
free((void *)pTap->dotted_name);
|
||||
free(pTap);
|
||||
return e;
|
||||
}
|
||||
|
||||
new_expected_ids = malloc(sizeof(uint32_t) * (pTap->expected_ids_cnt + 1));
|
||||
if (new_expected_ids == NULL) {
|
||||
Jim_SetResult_sprintf(goi->interp, "no memory");
|
||||
free((void *)pTap->dotted_name);
|
||||
free(pTap);
|
||||
return JIM_ERR;
|
||||
}
|
||||
|
||||
@@ -289,32 +302,45 @@ static int jim_newtap_cmd(Jim_GetOptInfo *goi)
|
||||
e = Jim_GetOpt_Wide(goi, &w);
|
||||
if (e != JIM_OK) {
|
||||
Jim_SetResult_sprintf(goi->interp, "option: %s bad parameter", n->name);
|
||||
free((void *)pTap->dotted_name);
|
||||
free(pTap);
|
||||
return e;
|
||||
}
|
||||
switch (n->value) {
|
||||
case NTAP_OPT_IRLEN:
|
||||
if (w > (jim_wide) (8 * sizeof(pTap->ir_capture_value)))
|
||||
LOG_WARNING("huge IR length %d", (int) w);
|
||||
LOG_WARNING("%s: huge IR length %d",
|
||||
pTap->dotted_name,
|
||||
(int) w);
|
||||
pTap->ir_length = w;
|
||||
reqbits &= (~(NTREQ_IRLEN));
|
||||
break;
|
||||
case NTAP_OPT_IRMASK:
|
||||
if (is_bad_irval(pTap->ir_length, w)) {
|
||||
LOG_ERROR("IR mask %x too big",
|
||||
LOG_ERROR("%s: IR mask %x too big",
|
||||
pTap->dotted_name,
|
||||
(int) w);
|
||||
free((void *)pTap->dotted_name);
|
||||
free(pTap);
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
if ((w & 3) != 3)
|
||||
LOG_WARNING("%s: nonstandard IR mask",
|
||||
pTap->dotted_name);
|
||||
pTap->ir_capture_mask = w;
|
||||
reqbits &= (~(NTREQ_IRMASK));
|
||||
break;
|
||||
case NTAP_OPT_IRCAPTURE:
|
||||
if (is_bad_irval(pTap->ir_length, w)) {
|
||||
LOG_ERROR("IR capture %x too big",
|
||||
LOG_ERROR("%s: IR capture %x too big",
|
||||
pTap->dotted_name,
|
||||
(int) w);
|
||||
free((void *)pTap->dotted_name);
|
||||
free(pTap);
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
if ((w & 3) != 1)
|
||||
LOG_WARNING("%s: nonstandard IR value",
|
||||
pTap->dotted_name);
|
||||
pTap->ir_capture_value = w;
|
||||
reqbits &= (~(NTREQ_IRCAPTURE));
|
||||
break;
|
||||
}
|
||||
} /* switch (n->value) */
|
||||
@@ -324,14 +350,14 @@ static int jim_newtap_cmd(Jim_GetOptInfo *goi)
|
||||
pTap->enabled = !pTap->disabled_after_reset;
|
||||
|
||||
/* Did all the required option bits get cleared? */
|
||||
if (0 == reqbits)
|
||||
if (pTap->ir_length != 0)
|
||||
{
|
||||
jtag_tap_init(pTap);
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
Jim_SetResult_sprintf(goi->interp,
|
||||
"newtap: %s missing required parameters",
|
||||
"newtap: %s missing IR length",
|
||||
pTap->dotted_name);
|
||||
jtag_tap_free(pTap);
|
||||
return JIM_ERR;
|
||||
@@ -340,37 +366,31 @@ static int jim_newtap_cmd(Jim_GetOptInfo *goi)
|
||||
static void jtag_tap_handle_event(jtag_tap_t *tap, enum jtag_event e)
|
||||
{
|
||||
jtag_tap_event_action_t * jteap;
|
||||
int done;
|
||||
|
||||
jteap = tap->event_action;
|
||||
|
||||
done = 0;
|
||||
while (jteap) {
|
||||
for (jteap = tap->event_action; jteap != NULL; jteap = jteap->next) {
|
||||
if (jteap->event == e) {
|
||||
done = 1;
|
||||
LOG_DEBUG("JTAG tap: %s event: %d (%s) action: %s\n",
|
||||
LOG_DEBUG("JTAG tap: %s event: %d (%s)\n\taction: %s",
|
||||
tap->dotted_name,
|
||||
e,
|
||||
Jim_Nvp_value2name_simple(nvp_jtag_tap_event, e)->name,
|
||||
Jim_GetString(jteap->body, NULL));
|
||||
if (Jim_EvalObj(interp, jteap->body) != JIM_OK) {
|
||||
Jim_PrintErrorMessage(interp);
|
||||
} else {
|
||||
} else switch (e) {
|
||||
case JTAG_TAP_EVENT_ENABLE:
|
||||
case JTAG_TAP_EVENT_DISABLE:
|
||||
/* NOTE: we currently assume the handlers
|
||||
* can't fail. That presumes later code
|
||||
* will be verifying the scan chains ...
|
||||
* can't fail. Right here is where we should
|
||||
* really be verifying the scan chains ...
|
||||
*/
|
||||
tap->enabled = (e == JTAG_TAP_EVENT_ENABLE);
|
||||
LOG_INFO("JTAG tap: %s %s", tap->dotted_name,
|
||||
tap->enabled ? "enabled" : "disabled");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
jteap = jteap->next;
|
||||
}
|
||||
|
||||
if (!done) {
|
||||
LOG_DEBUG("event %d %s - no action",
|
||||
e,
|
||||
Jim_Nvp_value2name_simple(nvp_jtag_tap_event, e)->name);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -385,6 +405,7 @@ static int jim_jtag_command(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
|
||||
|
||||
enum {
|
||||
JTAG_CMD_INTERFACE,
|
||||
JTAG_CMD_INIT,
|
||||
JTAG_CMD_INIT_RESET,
|
||||
JTAG_CMD_NEWTAP,
|
||||
JTAG_CMD_TAPENABLE,
|
||||
@@ -397,6 +418,7 @@ static int jim_jtag_command(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
|
||||
|
||||
const Jim_Nvp jtag_cmds[] = {
|
||||
{ .name = "interface" , .value = JTAG_CMD_INTERFACE },
|
||||
{ .name = "arp_init" , .value = JTAG_CMD_INIT },
|
||||
{ .name = "arp_init-reset", .value = JTAG_CMD_INIT_RESET },
|
||||
{ .name = "newtap" , .value = JTAG_CMD_NEWTAP },
|
||||
{ .name = "tapisenabled" , .value = JTAG_CMD_TAPISENABLED },
|
||||
@@ -430,6 +452,17 @@ static int jim_jtag_command(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
|
||||
}
|
||||
Jim_SetResultString(goi.interp, jtag_interface->name, -1);
|
||||
return JIM_OK;
|
||||
case JTAG_CMD_INIT:
|
||||
if (goi.argc != 0) {
|
||||
Jim_WrongNumArgs(goi.interp, 1, goi.argv-1, "(no params)");
|
||||
return JIM_ERR;
|
||||
}
|
||||
e = jtag_init_inner(context);
|
||||
if (e != ERROR_OK) {
|
||||
Jim_SetResult_sprintf(goi.interp, "error: %d", e);
|
||||
return JIM_ERR;
|
||||
}
|
||||
return JIM_OK;
|
||||
case JTAG_CMD_INIT_RESET:
|
||||
if (goi.argc != 0) {
|
||||
Jim_WrongNumArgs(goi.interp, 1, goi.argv-1, "(no params)");
|
||||
@@ -563,6 +596,16 @@ static int jim_jtag_command(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
|
||||
return JIM_ERR;
|
||||
}
|
||||
|
||||
|
||||
void jtag_notify_event(enum jtag_event event)
|
||||
{
|
||||
jtag_tap_t *tap;
|
||||
|
||||
for (tap = jtag_all_taps(); tap; tap = tap->next_tap)
|
||||
jtag_tap_handle_event(tap, event);
|
||||
}
|
||||
|
||||
|
||||
int jtag_register_commands(struct command_context_s *cmd_ctx)
|
||||
{
|
||||
register_jim(cmd_ctx, "jtag", jim_jtag_command, "perform jtag tap actions");
|
||||
@@ -577,15 +620,26 @@ int jtag_register_commands(struct command_context_s *cmd_ctx)
|
||||
register_command(cmd_ctx, NULL, "jtag_khz", handle_jtag_khz_command,
|
||||
COMMAND_ANY, "set maximum jtag speed (if supported); "
|
||||
"parameter is maximum khz, or 0 for adaptive clocking (RTCK).");
|
||||
register_command(cmd_ctx, NULL, "jtag_rclk", handle_jtag_rclk_command,
|
||||
COMMAND_ANY, "fallback_speed_khz - set JTAG speed to RCLK or use fallback speed");
|
||||
register_command(cmd_ctx, NULL, "jtag_device", handle_jtag_device_command,
|
||||
COMMAND_CONFIG, "(DEPRECATED) jtag_device <ir_length> <ir_expected> <ir_mask>");
|
||||
register_command(cmd_ctx, NULL, "reset_config", handle_reset_config_command,
|
||||
COMMAND_ANY,
|
||||
"[none/trst_only/srst_only/trst_and_srst] [srst_pulls_trst/trst_pulls_srst] [combined/separate] [trst_push_pull/trst_open_drain] [srst_push_pull/srst_open_drain]");
|
||||
"reset_config "
|
||||
"[none|trst_only|srst_only|trst_and_srst] "
|
||||
"[srst_pulls_trst|trst_pulls_srst|combined|separate] "
|
||||
"[srst_gates_jtag|srst_nogate] "
|
||||
"[trst_push_pull|trst_open_drain] "
|
||||
"[srst_push_pull|srst_open_drain]");
|
||||
register_command(cmd_ctx, NULL, "jtag_nsrst_delay", handle_jtag_nsrst_delay_command,
|
||||
COMMAND_ANY, "jtag_nsrst_delay <ms> - delay after deasserting srst in ms");
|
||||
register_command(cmd_ctx, NULL, "jtag_ntrst_delay", handle_jtag_ntrst_delay_command,
|
||||
COMMAND_ANY, "jtag_ntrst_delay <ms> - delay after deasserting trst in ms");
|
||||
register_command(cmd_ctx, NULL, "jtag_nsrst_assert_width", handle_jtag_nsrst_assert_width_command,
|
||||
COMMAND_ANY, "jtag_nsrst_assert_width <ms> - delay after asserting srst in ms");
|
||||
register_command(cmd_ctx, NULL, "jtag_ntrst_assert_width", handle_jtag_ntrst_assert_width_command,
|
||||
COMMAND_ANY, "jtag_ntrst_assert_width <ms> - delay after asserting trst in ms");
|
||||
|
||||
register_command(cmd_ctx, NULL, "scan_chain", handle_scan_chain_command,
|
||||
COMMAND_EXEC, "print current scan chain configuration");
|
||||
@@ -797,9 +851,6 @@ static int handle_reset_config_command(struct command_context_s *cmd_ctx, char *
|
||||
int new_cfg = 0;
|
||||
int mask = 0;
|
||||
|
||||
if (argc < 1)
|
||||
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||
|
||||
/* Original versions cared about the order of these tokens:
|
||||
* reset_config signals [combination [trst_type [srst_type]]]
|
||||
* They also clobbered the previous configuration even on error.
|
||||
@@ -811,6 +862,22 @@ static int handle_reset_config_command(struct command_context_s *cmd_ctx, char *
|
||||
int tmp = 0;
|
||||
int m;
|
||||
|
||||
/* gating */
|
||||
m = RESET_SRST_NO_GATING;
|
||||
if (strcmp(*args, "srst_gates_jtag") == 0)
|
||||
/* default: don't use JTAG while SRST asserted */;
|
||||
else if (strcmp(*args, "srst_nogate") == 0)
|
||||
tmp = RESET_SRST_NO_GATING;
|
||||
else
|
||||
m = 0;
|
||||
if (mask & m) {
|
||||
LOG_ERROR("extra reset_config %s spec (%s)",
|
||||
"gating", *args);
|
||||
return ERROR_INVALID_ARGUMENTS;
|
||||
}
|
||||
if (m)
|
||||
goto next;
|
||||
|
||||
/* signals */
|
||||
m = RESET_HAS_TRST | RESET_HAS_SRST;
|
||||
if (strcmp(*args, "none") == 0)
|
||||
@@ -896,10 +963,81 @@ next:
|
||||
}
|
||||
|
||||
/* clear previous values of those bits, save new values */
|
||||
enum reset_types old_cfg = jtag_get_reset_config();
|
||||
old_cfg &= ~mask;
|
||||
new_cfg |= old_cfg;
|
||||
jtag_set_reset_config(new_cfg);
|
||||
if (mask) {
|
||||
int old_cfg = jtag_get_reset_config();
|
||||
|
||||
old_cfg &= ~mask;
|
||||
new_cfg |= old_cfg;
|
||||
jtag_set_reset_config(new_cfg);
|
||||
} else
|
||||
new_cfg = jtag_get_reset_config();
|
||||
|
||||
|
||||
/*
|
||||
* Display the (now-)current reset mode
|
||||
*/
|
||||
char *modes[5];
|
||||
|
||||
/* minimal JTAG has neither SRST nor TRST (so that's the default) */
|
||||
switch (new_cfg & (RESET_HAS_TRST | RESET_HAS_SRST)) {
|
||||
case RESET_HAS_SRST:
|
||||
modes[0] = "srst_only";
|
||||
break;
|
||||
case RESET_HAS_TRST:
|
||||
modes[0] = "trst_only";
|
||||
break;
|
||||
case RESET_TRST_AND_SRST:
|
||||
modes[0] = "trst_and_srst";
|
||||
break;
|
||||
default:
|
||||
modes[0] = "none";
|
||||
break;
|
||||
}
|
||||
|
||||
/* normally SRST and TRST are decoupled; but bugs happen ... */
|
||||
switch (new_cfg & (RESET_SRST_PULLS_TRST | RESET_TRST_PULLS_SRST)) {
|
||||
case RESET_SRST_PULLS_TRST:
|
||||
modes[1] = "srst_pulls_trst";
|
||||
break;
|
||||
case RESET_TRST_PULLS_SRST:
|
||||
modes[1] = "trst_pulls_srst";
|
||||
break;
|
||||
case RESET_SRST_PULLS_TRST | RESET_TRST_PULLS_SRST:
|
||||
modes[1] = "combined";
|
||||
break;
|
||||
default:
|
||||
modes[1] = "separate";
|
||||
break;
|
||||
}
|
||||
|
||||
/* TRST-less connectors include Altera, Xilinx, and minimal JTAG */
|
||||
if (new_cfg & RESET_HAS_TRST) {
|
||||
if (new_cfg & RESET_TRST_OPEN_DRAIN)
|
||||
modes[3] = " trst_open_drain";
|
||||
else
|
||||
modes[3] = " trst_push_pull";
|
||||
} else
|
||||
modes[3] = "";
|
||||
|
||||
/* SRST-less connectors include TI-14, Xilinx, and minimal JTAG */
|
||||
if (new_cfg & RESET_HAS_SRST) {
|
||||
if (new_cfg & RESET_SRST_NO_GATING)
|
||||
modes[2] = " srst_nogate";
|
||||
else
|
||||
modes[2] = " srst_gates_jtag";
|
||||
|
||||
if (new_cfg & RESET_SRST_PUSH_PULL)
|
||||
modes[4] = " srst_push_pull";
|
||||
else
|
||||
modes[4] = " srst_open_drain";
|
||||
} else {
|
||||
modes[2] = "";
|
||||
modes[4] = "";
|
||||
}
|
||||
|
||||
command_print(cmd_ctx, "%s %s%s%s%s",
|
||||
modes[0], modes[1],
|
||||
modes[2], modes[3], modes[4]);
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
@@ -938,10 +1076,47 @@ static int handle_jtag_ntrst_delay_command(struct command_context_s *cmd_ctx,
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
static int handle_jtag_nsrst_assert_width_command(struct command_context_s *cmd_ctx,
|
||||
char *cmd, char **args, int argc)
|
||||
{
|
||||
if (argc > 1)
|
||||
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||
if (argc == 1)
|
||||
{
|
||||
unsigned delay;
|
||||
int retval = parse_uint(args[0], &delay);
|
||||
if (ERROR_OK != retval)
|
||||
return retval;
|
||||
jtag_set_nsrst_assert_width(delay);
|
||||
}
|
||||
command_print(cmd_ctx, "jtag_nsrst_assert_width: %u", jtag_get_nsrst_assert_width());
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
static int handle_jtag_ntrst_assert_width_command(struct command_context_s *cmd_ctx,
|
||||
char *cmd, char **args, int argc)
|
||||
{
|
||||
if (argc > 1)
|
||||
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||
if (argc == 1)
|
||||
{
|
||||
unsigned delay;
|
||||
int retval = parse_uint(args[0], &delay);
|
||||
if (ERROR_OK != retval)
|
||||
return retval;
|
||||
jtag_set_ntrst_assert_width(delay);
|
||||
}
|
||||
command_print(cmd_ctx, "jtag_ntrst_assert_width: %u", jtag_get_ntrst_assert_width());
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
static int handle_jtag_speed_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
|
||||
{
|
||||
int retval = ERROR_OK;
|
||||
|
||||
command_print(cmd_ctx, "OLD SYNTAX: DEPRECATED - "
|
||||
"use jtag_khz, not jtag_speed");
|
||||
|
||||
if (argc > 1)
|
||||
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||
if (argc == 1)
|
||||
@@ -952,7 +1127,7 @@ static int handle_jtag_speed_command(struct command_context_s *cmd_ctx, char *cm
|
||||
int retval = parse_uint(args[0], &cur_speed);
|
||||
if (ERROR_OK != retval)
|
||||
return retval;
|
||||
retval = jtag_set_speed(cur_speed);
|
||||
retval = jtag_config_speed(cur_speed);
|
||||
|
||||
}
|
||||
command_print(cmd_ctx, "jtag_speed: %d", jtag_get_speed());
|
||||
@@ -990,6 +1165,36 @@ static int handle_jtag_khz_command(struct command_context_s *cmd_ctx, char *cmd,
|
||||
return retval;
|
||||
}
|
||||
|
||||
static int handle_jtag_rclk_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
|
||||
{
|
||||
if (argc > 1)
|
||||
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||
|
||||
int retval = ERROR_OK;
|
||||
if (argc == 1)
|
||||
{
|
||||
unsigned khz = 0;
|
||||
int retval = parse_uint(args[0], &khz);
|
||||
if (ERROR_OK != retval)
|
||||
return retval;
|
||||
retval = jtag_config_rclk(khz);
|
||||
if (ERROR_OK != retval)
|
||||
return retval;
|
||||
}
|
||||
|
||||
int cur_khz = jtag_get_speed_khz();
|
||||
retval = jtag_get_speed_readable(&cur_khz);
|
||||
if (ERROR_OK != retval)
|
||||
return retval;
|
||||
|
||||
if (cur_khz)
|
||||
command_print(cmd_ctx, "RCLK not supported - fallback to %d kHz", cur_khz);
|
||||
else
|
||||
command_print(cmd_ctx, "RCLK - adaptive");
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
static int handle_jtag_reset_command(struct command_context_s *cmd_ctx,
|
||||
char *cmd, char **args, int argc)
|
||||
{
|
||||
@@ -1038,6 +1243,8 @@ static int handle_runtest_command(struct command_context_s *cmd_ctx,
|
||||
* For "irscan" or "drscan" commands, the "end" (really, "next") state
|
||||
* should be stable ... and *NOT* a shift state, otherwise free-running
|
||||
* jtag clocks could change the values latched by the update state.
|
||||
* Not surprisingly, this is the same constraint as SVF; the "irscan"
|
||||
* and "drscan" commands are a write-only subset of what SVF provides.
|
||||
*/
|
||||
static bool scan_is_safe(tap_state_t state)
|
||||
{
|
||||
@@ -1075,25 +1282,14 @@ static int handle_irscan_command(struct command_context_s *cmd_ctx, char *cmd, c
|
||||
if (argc >= 4) {
|
||||
/* have at least one pair of numbers. */
|
||||
/* is last pair the magic text? */
|
||||
if (0 == strcmp("-endstate", args[ argc - 2 ])) {
|
||||
const char *cpA;
|
||||
const char *cpS;
|
||||
cpA = args[ argc-1 ];
|
||||
for (endstate = 0 ; endstate < TAP_NUM_STATES ; endstate++) {
|
||||
cpS = tap_state_name(endstate);
|
||||
if (0 == strcmp(cpA, cpS)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (endstate >= TAP_NUM_STATES) {
|
||||
if (strcmp("-endstate", args[argc - 2]) == 0) {
|
||||
endstate = tap_state_by_name(args[argc - 1]);
|
||||
if (endstate == TAP_INVALID)
|
||||
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||
} else {
|
||||
if (!scan_is_safe(endstate))
|
||||
LOG_WARNING("irscan with unsafe "
|
||||
"endstate \"%s\"", cpA);
|
||||
/* found - remove the last 2 args */
|
||||
argc -= 2;
|
||||
}
|
||||
if (!scan_is_safe(endstate))
|
||||
LOG_WARNING("unstable irscan endstate \"%s\"",
|
||||
args[argc - 1]);
|
||||
argc -= 2;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1108,7 +1304,12 @@ static int handle_irscan_command(struct command_context_s *cmd_ctx, char *cmd, c
|
||||
tap = jtag_tap_by_string(args[i*2]);
|
||||
if (tap == NULL)
|
||||
{
|
||||
int j;
|
||||
for (j = 0; j < i; j++)
|
||||
free(fields[j].out_value);
|
||||
free(fields);
|
||||
command_print(cmd_ctx, "Tap: %s unknown", args[i*2]);
|
||||
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
int field_size = tap->ir_length;
|
||||
|
||||
@@ -435,6 +435,7 @@ struct usbprog_jtag* usbprog_jtag_open(void)
|
||||
}
|
||||
}
|
||||
}
|
||||
free(tmp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2007-2008 by Øyvind Harboe *
|
||||
* Copyright (C) 2007-2008 by Øyvind Harboe *
|
||||
* *
|
||||
* 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 *
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2007-2008 by <EFBFBD>yvind Harboe *
|
||||
* Copyright (C) 2007-2008 by Øyvind Harboe *
|
||||
* *
|
||||
* 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 *
|
||||
@@ -23,16 +23,16 @@
|
||||
#include "embeddedice.h"
|
||||
#include "minidriver.h"
|
||||
#include "interface.h"
|
||||
#include "zy1000_version.h"
|
||||
|
||||
#include <cyg/hal/hal_io.h> // low level i/o
|
||||
#include <cyg/hal/hal_diag.h>
|
||||
|
||||
|
||||
#define ZYLIN_VERSION "1.53"
|
||||
#define ZYLIN_VERSION GIT_ZY1000_VERSION
|
||||
#define ZYLIN_DATE __DATE__
|
||||
#define ZYLIN_TIME __TIME__
|
||||
#define ZYLIN_OPENOCD "$Revision$"
|
||||
#define ZYLIN_OPENOCD_VERSION "Zylin JTAG ZY1000 " ZYLIN_VERSION " " ZYLIN_DATE " " ZYLIN_TIME
|
||||
#define ZYLIN_OPENOCD GIT_OPENOCD_VERSION
|
||||
#define ZYLIN_OPENOCD_VERSION "ZY1000 " ZYLIN_VERSION " " ZYLIN_DATE
|
||||
|
||||
/* low level command set
|
||||
*/
|
||||
@@ -270,10 +270,7 @@ static int jim_zy1000_version(Jim_Interp *interp, int argc, Jim_Obj *const *argv
|
||||
const char *str = Jim_GetString(argv[1], NULL);
|
||||
if (strcmp("openocd", str) == 0)
|
||||
{
|
||||
int revision;
|
||||
revision = atol(ZYLIN_OPENOCD + strlen("XRevision: "));
|
||||
sprintf(buff, "%d", revision);
|
||||
version_str = buff;
|
||||
version_str = ZYLIN_OPENOCD;
|
||||
}
|
||||
else if (strcmp("zy1000", str) == 0)
|
||||
{
|
||||
@@ -283,6 +280,10 @@ static int jim_zy1000_version(Jim_Interp *interp, int argc, Jim_Obj *const *argv
|
||||
{
|
||||
version_str = ZYLIN_DATE;
|
||||
}
|
||||
else if (strcmp("time", str) == 0)
|
||||
{
|
||||
version_str = ZYLIN_TIME;
|
||||
}
|
||||
else if (strcmp("pcb", str) == 0)
|
||||
{
|
||||
#ifdef CYGPKG_HAL_NIOS2
|
||||
@@ -531,12 +532,6 @@ static __inline void scanFields(int num_fields, const scan_field_t *fields, tap_
|
||||
}
|
||||
}
|
||||
|
||||
int interface_jtag_set_end_state(tap_state_t state)
|
||||
{
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
|
||||
int interface_jtag_add_ir_scan(int num_fields, const scan_field_t *fields, tap_state_t state)
|
||||
{
|
||||
|
||||
@@ -657,9 +652,6 @@ int interface_jtag_add_tlr()
|
||||
|
||||
|
||||
|
||||
extern int jtag_nsrst_delay;
|
||||
extern int jtag_ntrst_delay;
|
||||
|
||||
int interface_jtag_add_reset(int req_trst, int req_srst)
|
||||
{
|
||||
zy1000_reset(req_trst, req_srst);
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* Copyright (C) 2005 by Dominic Rath *
|
||||
* Dominic.Rath@gmx.de *
|
||||
* *
|
||||
* Copyright (C) 2007,2008 Øyvind Harboe *
|
||||
* Copyright (C) 2007,2008 Øyvind Harboe *
|
||||
* oyvind.harboe@zylin.com *
|
||||
* *
|
||||
* Copyright (C) 2008 Richard Missenden *
|
||||
@@ -49,7 +49,7 @@
|
||||
|
||||
|
||||
#define OPENOCD_VERSION \
|
||||
"Open On-Chip Debugger " VERSION " (" PKGBLDDATE ") " RELSTR PKGBLDREV
|
||||
"Open On-Chip Debugger " VERSION RELSTR " (" PKGBLDDATE ")"
|
||||
|
||||
static void print_version(void)
|
||||
{
|
||||
@@ -255,7 +255,9 @@ int openocd_main(int argc, char *argv[])
|
||||
|
||||
print_version();
|
||||
|
||||
LOG_OUTPUT("For bug reports, read http://svn.berlios.de/svnroot/repos/openocd/trunk/BUGS\n");
|
||||
LOG_OUTPUT("For bug reports, read\n\t"
|
||||
"http://openocd.berlios.de/doc/doxygen/bugs.html"
|
||||
"\n");
|
||||
|
||||
|
||||
command_context_mode(cmd_ctx, COMMAND_CONFIG);
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* Copyright (C) 2005 by Dominic Rath *
|
||||
* Dominic.Rath@gmx.de *
|
||||
* *
|
||||
* Copyright (C) 2007,2008 <EFBFBD>yvind Harboe *
|
||||
* Copyright (C) 2007,2008 Øyvind Harboe *
|
||||
* oyvind.harboe@zylin.com *
|
||||
* *
|
||||
* Copyright (C) 2008 by Spencer Oliver *
|
||||
@@ -40,6 +40,8 @@
|
||||
#define _DEBUG_GDB_IO_
|
||||
#endif
|
||||
|
||||
static gdb_connection_t *current_gdb_connection;
|
||||
|
||||
static int gdb_breakpoint_override;
|
||||
static enum breakpoint_type gdb_breakpoint_override_type;
|
||||
|
||||
@@ -50,17 +52,6 @@ static const char *DIGITS = "0123456789abcdef";
|
||||
static void gdb_log_callback(void *priv, const char *file, int line,
|
||||
const char *function, const char *string);
|
||||
|
||||
enum gdb_detach_mode
|
||||
{
|
||||
GDB_DETACH_RESUME,
|
||||
GDB_DETACH_RESET,
|
||||
GDB_DETACH_HALT,
|
||||
GDB_DETACH_NOTHING
|
||||
};
|
||||
|
||||
/* target behaviour on gdb detach */
|
||||
enum gdb_detach_mode detach_mode = GDB_DETACH_RESUME;
|
||||
|
||||
/* number of gdb connections, mainly to supress gdb related debugging spam
|
||||
* in helper/log.c when no gdb connections are actually active */
|
||||
int gdb_actual_connections;
|
||||
@@ -712,7 +703,7 @@ int gdb_target_callback_event_handler(struct target_s *target, enum target_event
|
||||
target_handle_event(target, event);
|
||||
switch (event)
|
||||
{
|
||||
case TARGET_EVENT_EARLY_HALTED:
|
||||
case TARGET_EVENT_GDB_HALT:
|
||||
gdb_frontend_halted(target, connection);
|
||||
break;
|
||||
case TARGET_EVENT_HALTED:
|
||||
@@ -750,6 +741,7 @@ int gdb_new_connection(connection_t *connection)
|
||||
gdb_connection->closed = 0;
|
||||
gdb_connection->busy = 0;
|
||||
gdb_connection->noack_mode = 0;
|
||||
gdb_connection->sync = true;
|
||||
|
||||
/* send ACK to GDB for debug request */
|
||||
gdb_write(connection, "+", 1);
|
||||
@@ -767,30 +759,6 @@ int gdb_new_connection(connection_t *connection)
|
||||
/* register callback to be informed about target events */
|
||||
target_register_event_callback(gdb_target_callback_event_handler, connection);
|
||||
|
||||
/* a gdb session just attached, try to put the target in halt mode.
|
||||
*
|
||||
* DANGER!!!!
|
||||
*
|
||||
* If the halt fails(e.g. target needs a reset, JTAG communication not
|
||||
* working, etc.), then the GDB connect will succeed as
|
||||
* the get_gdb_reg_list() will lie and return a register list with
|
||||
* dummy values.
|
||||
*
|
||||
* This allows GDB monitor commands to be run from a GDB init script to
|
||||
* initialize the target
|
||||
*
|
||||
* Also, since the halt() is asynchronous target connect will be
|
||||
* instantaneous and thus avoiding annoying timeout problems during
|
||||
* connect.
|
||||
*/
|
||||
target_halt(gdb_service->target);
|
||||
/* FIX!!!! could extended-remote work better here?
|
||||
*
|
||||
* wait a tiny bit for halted state or we just continue. The
|
||||
* GDB register packet will then contain garbage
|
||||
*/
|
||||
target_wait_state(gdb_service->target, TARGET_HALTED, 500);
|
||||
|
||||
/* remove the initial ACK from the incoming buffer */
|
||||
if ((retval = gdb_get_char(connection, &initial_ack)) != ERROR_OK)
|
||||
return retval;
|
||||
@@ -816,6 +784,11 @@ int gdb_connection_closed(connection_t *connection)
|
||||
gdb_service_t *gdb_service = connection->service->priv;
|
||||
gdb_connection_t *gdb_connection = connection->priv;
|
||||
|
||||
/* we're done forwarding messages. Tear down callback before
|
||||
* cleaning up connection.
|
||||
*/
|
||||
log_remove_callback(gdb_log_callback, connection);
|
||||
|
||||
gdb_actual_connections--;
|
||||
LOG_DEBUG("GDB Close, Target: %s, state: %s, gdb_actual_connections=%d",
|
||||
gdb_service->target->cmd_name,
|
||||
@@ -843,9 +816,10 @@ int gdb_connection_closed(connection_t *connection)
|
||||
LOG_ERROR("BUG: connection->priv == NULL");
|
||||
}
|
||||
|
||||
|
||||
target_unregister_event_callback(gdb_target_callback_event_handler, connection);
|
||||
|
||||
target_call_event_callbacks(gdb_service->target, TARGET_EVENT_GDB_END);
|
||||
log_remove_callback(gdb_log_callback, connection);
|
||||
|
||||
target_call_event_callbacks(gdb_service->target, TARGET_EVENT_GDB_DETACH);
|
||||
|
||||
@@ -1603,7 +1577,11 @@ int gdb_query_packet(connection_t *connection, target_t *target, char *packet, i
|
||||
/* We want to print all debug output to GDB connection */
|
||||
log_add_callback(gdb_log_callback, connection);
|
||||
target_call_timer_callbacks_now();
|
||||
/* some commands need to know the GDB connection, make note of current
|
||||
* GDB connection. */
|
||||
current_gdb_connection = gdb_connection;
|
||||
command_run_line(cmd_ctx, cmd);
|
||||
current_gdb_connection = NULL;
|
||||
target_call_timer_callbacks_now();
|
||||
log_remove_callback(gdb_log_callback, connection);
|
||||
free(cmd);
|
||||
@@ -1971,29 +1949,11 @@ int gdb_v_packet(connection_t *connection, target_t *target, char *packet, int p
|
||||
|
||||
int gdb_detach(connection_t *connection, target_t *target)
|
||||
{
|
||||
gdb_service_t *gdb_service = connection->service->priv;
|
||||
|
||||
switch (detach_mode)
|
||||
{
|
||||
case GDB_DETACH_RESUME:
|
||||
target_handle_event(target, TARGET_EVENT_OLD_pre_resume);
|
||||
target_resume(target, 1, 0, 1, 0);
|
||||
break;
|
||||
target_call_event_callbacks(gdb_service->target, TARGET_EVENT_GDB_DETACH);
|
||||
|
||||
case GDB_DETACH_RESET:
|
||||
/* FIX?? make this configurable?? */
|
||||
target_process_reset(connection->cmd_ctx, RESET_HALT);
|
||||
break;
|
||||
|
||||
case GDB_DETACH_HALT:
|
||||
target_halt(target);
|
||||
break;
|
||||
|
||||
case GDB_DETACH_NOTHING:
|
||||
break;
|
||||
}
|
||||
|
||||
gdb_put_packet(connection, "OK", 2);
|
||||
return ERROR_OK;
|
||||
return gdb_put_packet(connection, "OK", 2);
|
||||
}
|
||||
|
||||
static void gdb_log_callback(void *priv, const char *file, int line,
|
||||
@@ -2101,20 +2061,52 @@ int gdb_input_inner(connection_t *connection)
|
||||
case 'c':
|
||||
case 's':
|
||||
{
|
||||
if (target->state != TARGET_HALTED)
|
||||
int retval = ERROR_OK;
|
||||
|
||||
gdb_connection_t *gdb_con = connection->priv;
|
||||
log_add_callback(gdb_log_callback, connection);
|
||||
|
||||
bool nostep = false;
|
||||
if (target->state == TARGET_RUNNING)
|
||||
{
|
||||
/* If the target isn't in the halted state, then we can't
|
||||
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);
|
||||
} else if (target->state != TARGET_HALTED)
|
||||
{
|
||||
LOG_WARNING("The target is not in the halted nor running stated, stepi/continue ignored.");
|
||||
nostep = true;
|
||||
} else if ((packet[0] == 's') && gdb_con->sync)
|
||||
{
|
||||
/* Hmm..... when you issue a continue in GDB, then a "stepi" is
|
||||
* sent by GDB first to OpenOCD, thus defeating the check to
|
||||
* make only the single stepping have the sync feature...
|
||||
*/
|
||||
nostep = true;
|
||||
LOG_WARNING("stepi ignored. GDB will now fetch the register state from the target.");
|
||||
}
|
||||
gdb_con->sync = false;
|
||||
|
||||
if ((retval!=ERROR_OK) || nostep)
|
||||
{
|
||||
/* Either the target isn't in the halted state, then we can't
|
||||
* step/continue. This might be early setup, etc.
|
||||
*
|
||||
* Or we want to allow GDB to pick up a fresh set of
|
||||
* register values without modifying the target state.
|
||||
*
|
||||
*/
|
||||
gdb_sig_halted(connection);
|
||||
|
||||
/* stop forwarding log packets! */
|
||||
log_remove_callback(gdb_log_callback, connection);
|
||||
} else
|
||||
{
|
||||
/* We're running/stepping, in which case we can
|
||||
* forward log output until the target is halted
|
||||
*/
|
||||
gdb_connection_t *gdb_con = connection->priv;
|
||||
gdb_con->frontend_state = TARGET_RUNNING;
|
||||
log_add_callback(gdb_log_callback, connection);
|
||||
target_call_event_callbacks(target, TARGET_EVENT_GDB_START);
|
||||
int retval = gdb_step_continue_packet(connection, target, packet, packet_size);
|
||||
if (retval != ERROR_OK)
|
||||
@@ -2150,7 +2142,9 @@ int gdb_input_inner(connection_t *connection)
|
||||
/* handle extended restart packet */
|
||||
breakpoint_clear_target(gdb_service->target);
|
||||
watchpoint_clear_target(gdb_service->target);
|
||||
command_run_linef(connection->cmd_ctx, "ocd_gdb_restart %d", get_num_by_target(target));
|
||||
command_run_linef(connection->cmd_ctx,
|
||||
"ocd_gdb_restart %s",
|
||||
target->cmd_name);
|
||||
break;
|
||||
default:
|
||||
/* ignore unkown packets */
|
||||
@@ -2168,8 +2162,16 @@ int gdb_input_inner(connection_t *connection)
|
||||
{
|
||||
if (target->state == TARGET_RUNNING)
|
||||
{
|
||||
target_halt(target);
|
||||
retval = target_halt(target);
|
||||
if (retval != ERROR_OK)
|
||||
{
|
||||
target_call_event_callbacks(target, TARGET_EVENT_GDB_HALT);
|
||||
}
|
||||
gdb_con->ctrl_c = 0;
|
||||
} else
|
||||
{
|
||||
LOG_INFO("The target is not running when halt was requested, stopping GDB.");
|
||||
target_call_event_callbacks(target, TARGET_EVENT_GDB_HALT);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2224,23 +2226,48 @@ int gdb_init(void)
|
||||
}
|
||||
else
|
||||
{
|
||||
unsigned short port = gdb_port;
|
||||
|
||||
while (target)
|
||||
{
|
||||
gdb_service = malloc(sizeof(gdb_service_t));
|
||||
gdb_service->target = target;
|
||||
|
||||
add_service("gdb", CONNECTION_TCP, gdb_port + target->target_number, 1, gdb_new_connection, gdb_input, gdb_connection_closed, gdb_service);
|
||||
add_service("gdb", CONNECTION_TCP,
|
||||
port, 1,
|
||||
gdb_new_connection, gdb_input,
|
||||
gdb_connection_closed, gdb_service);
|
||||
|
||||
LOG_DEBUG("gdb service for target %s at port %i",
|
||||
LOG_DEBUG("gdb service for target %s at TCP port %i",
|
||||
target_get_name(target),
|
||||
gdb_port + target->target_number);
|
||||
port);
|
||||
target = target->next;
|
||||
port++;
|
||||
}
|
||||
}
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
int handle_gdb_sync_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
|
||||
{
|
||||
if (argc != 0)
|
||||
{
|
||||
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||
}
|
||||
|
||||
if (current_gdb_connection == NULL)
|
||||
{
|
||||
command_print(cmd_ctx,
|
||||
"gdb_sync command can only be run from within gdb using \"monitor gdb_sync\"");
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
|
||||
current_gdb_connection->sync = true;
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
/* daemon configuration command gdb_port */
|
||||
int handle_gdb_port_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
|
||||
{
|
||||
@@ -2255,37 +2282,6 @@ int handle_gdb_port_command(struct command_context_s *cmd_ctx, char *cmd, char *
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
int handle_gdb_detach_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
|
||||
{
|
||||
if (argc == 1)
|
||||
{
|
||||
if (strcmp(args[0], "resume") == 0)
|
||||
{
|
||||
detach_mode = GDB_DETACH_RESUME;
|
||||
return ERROR_OK;
|
||||
}
|
||||
else if (strcmp(args[0], "reset") == 0)
|
||||
{
|
||||
detach_mode = GDB_DETACH_RESET;
|
||||
return ERROR_OK;
|
||||
}
|
||||
else if (strcmp(args[0], "halt") == 0)
|
||||
{
|
||||
detach_mode = GDB_DETACH_HALT;
|
||||
return ERROR_OK;
|
||||
}
|
||||
else if (strcmp(args[0], "nothing") == 0)
|
||||
{
|
||||
detach_mode = GDB_DETACH_NOTHING;
|
||||
return ERROR_OK;
|
||||
}
|
||||
else
|
||||
LOG_WARNING("invalid gdb_detach configuration directive: %s", args[0]);
|
||||
}
|
||||
|
||||
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||
}
|
||||
|
||||
int handle_gdb_memory_map_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
|
||||
{
|
||||
if (argc == 1)
|
||||
@@ -2385,11 +2381,10 @@ int handle_gdb_breakpoint_override_command(struct command_context_s *cmd_ctx, ch
|
||||
|
||||
int gdb_register_commands(command_context_t *command_context)
|
||||
{
|
||||
register_command(command_context, NULL, "gdb_sync", handle_gdb_sync_command,
|
||||
COMMAND_ANY, "next stepi will return immediately allowing GDB fetch register state without affecting target state");
|
||||
register_command(command_context, NULL, "gdb_port", handle_gdb_port_command,
|
||||
COMMAND_ANY, "daemon configuration command gdb_port");
|
||||
register_command(command_context, NULL, "gdb_detach", handle_gdb_detach_command,
|
||||
COMMAND_CONFIG, "resume/reset/halt/nothing - "
|
||||
"specify behavior when GDB detaches from the target");
|
||||
register_command(command_context, NULL, "gdb_memory_map", handle_gdb_memory_map_command,
|
||||
COMMAND_CONFIG, "enable or disable memory map");
|
||||
register_command(command_context, NULL, "gdb_flash_program", handle_gdb_flash_program_command,
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* Copyright (C) 2005 by Dominic Rath *
|
||||
* Dominic.Rath@gmx.de *
|
||||
* *
|
||||
* Copyright (C) 2007,2008 Øyvind Harboe *
|
||||
* Copyright (C) 2007,2008 Øyvind Harboe *
|
||||
* oyvind.harboe@zylin.com *
|
||||
* *
|
||||
* Copyright (C) 2008 by Spencer Oliver *
|
||||
@@ -43,6 +43,10 @@ typedef struct gdb_connection_s
|
||||
int closed;
|
||||
int busy;
|
||||
int noack_mode;
|
||||
bool sync; /* set flag to true if you want the next stepi to return immediately.
|
||||
allowing GDB to pick up a fresh set of register values from the target
|
||||
without modifying the target state. */
|
||||
|
||||
} gdb_connection_t;
|
||||
|
||||
typedef struct gdb_service_s
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user