Merge commit '05ee88915520d1dd82da94a016a9374a1f3a8129' into from_upstream
Conflicts: src/jtag/drivers/xds110.c src/target/riscv/riscv.c src/target/riscv/riscv_semihosting.c tcl/target/esp_common.cfg Change-Id: If0c02817df03b7fd700cc84b4da2c02d36737d28
This commit is contained in:
commit
b5bd88441c
|
@ -0,0 +1,503 @@
|
|||
Valid-License-Identifier: LGPL-2.1-only
|
||||
Valid-License-Identifier: LGPL-2.1-or-later
|
||||
SPDX-URL: https://spdx.org/licenses/LGPL-2.1.html
|
||||
Usage-Guide:
|
||||
To use this license in source code, put one of the following SPDX
|
||||
tag/value pairs into a comment according to the placement
|
||||
guidelines in the licensing rules documentation.
|
||||
For 'GNU Lesser General Public License (LGPL) version 2.1 only' use:
|
||||
SPDX-License-Identifier: LGPL-2.1-only
|
||||
For 'GNU Lesser General Public License (LGPL) version 2.1 or any later
|
||||
version' use:
|
||||
SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
License-Text:
|
||||
|
||||
GNU LESSER GENERAL PUBLIC LICENSE
|
||||
Version 2.1, February 1999
|
||||
|
||||
Copyright (C) 1991, 1999 Free Software Foundation, Inc.
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
Everyone is permitted to copy and distribute verbatim copies of this
|
||||
license document, but changing it is not allowed.
|
||||
|
||||
[This is the first released version of the Lesser GPL. It also counts as
|
||||
the successor of the GNU Library Public License, version 2, hence the
|
||||
version number 2.1.]
|
||||
|
||||
Preamble
|
||||
|
||||
The licenses for most software are designed to take away your freedom to
|
||||
share and change it. By contrast, the GNU General Public Licenses are
|
||||
intended to guarantee your freedom to share and change free software--to
|
||||
make sure the software is free for all its users.
|
||||
|
||||
This license, the Lesser General Public License, applies to some specially
|
||||
designated software packages--typically libraries--of the Free Software
|
||||
Foundation and other authors who decide to use it. You can use it too, but
|
||||
we suggest you first think carefully about whether this license or the
|
||||
ordinary General Public License is the better strategy to use in any
|
||||
particular case, based on the explanations below.
|
||||
|
||||
When we speak of free software, we are referring to freedom of use, not
|
||||
price. Our General Public Licenses are designed to make sure that you have
|
||||
the freedom to distribute copies of free software (and charge for this
|
||||
service if you wish); that you receive source code or can get it if you
|
||||
want it; that you can change the software and use pieces of it in new free
|
||||
programs; and that you are informed that you can do these things.
|
||||
|
||||
To protect your rights, we need to make restrictions that forbid
|
||||
distributors to deny you these rights or to ask you to surrender these
|
||||
rights. These restrictions translate to certain responsibilities for you if
|
||||
you distribute copies of the library or if you modify it.
|
||||
|
||||
For example, if you distribute copies of the library, whether gratis or for
|
||||
a fee, you must give the recipients all the rights that we gave you. You
|
||||
must make sure that they, too, receive or can get the source code. If you
|
||||
link other code with the library, you must provide complete object files to
|
||||
the recipients, so that they can relink them with the library after making
|
||||
changes to the library and recompiling it. And you must show them these
|
||||
terms so they know their rights.
|
||||
|
||||
We protect your rights with a two-step method: (1) we copyright the
|
||||
library, and (2) we offer you this license, which gives you legal
|
||||
permission to copy, distribute and/or modify the library.
|
||||
|
||||
To protect each distributor, we want to make it very clear that there is no
|
||||
warranty for the free library. Also, if the library is modified by someone
|
||||
else and passed on, the recipients should know that what they have is not
|
||||
the original version, so that the original author's reputation will not be
|
||||
affected by problems that might be introduced by others.
|
||||
|
||||
Finally, software patents pose a constant threat to the existence of any
|
||||
free program. We wish to make sure that a company cannot effectively
|
||||
restrict the users of a free program by obtaining a restrictive license
|
||||
from a patent holder. Therefore, we insist that any patent license obtained
|
||||
for a version of the library must be consistent with the full freedom of
|
||||
use specified in this license.
|
||||
|
||||
Most GNU software, including some libraries, is covered by the ordinary GNU
|
||||
General Public License. This license, the GNU Lesser General Public
|
||||
License, applies to certain designated libraries, and is quite different
|
||||
from the ordinary General Public License. We use this license for certain
|
||||
libraries in order to permit linking those libraries into non-free
|
||||
programs.
|
||||
|
||||
When a program is linked with a library, whether statically or using a
|
||||
shared library, the combination of the two is legally speaking a combined
|
||||
work, a derivative of the original library. The ordinary General Public
|
||||
License therefore permits such linking only if the entire combination fits
|
||||
its criteria of freedom. The Lesser General Public License permits more lax
|
||||
criteria for linking other code with the library.
|
||||
|
||||
We call this license the "Lesser" General Public License because it does
|
||||
Less to protect the user's freedom than the ordinary General Public
|
||||
License. It also provides other free software developers Less of an
|
||||
advantage over competing non-free programs. These disadvantages are the
|
||||
reason we use the ordinary General Public License for many
|
||||
libraries. However, the Lesser license provides advantages in certain
|
||||
special circumstances.
|
||||
|
||||
For example, on rare occasions, there may be a special need to encourage
|
||||
the widest possible use of a certain library, so that it becomes a de-facto
|
||||
standard. To achieve this, non-free programs must be allowed to use the
|
||||
library. A more frequent case is that a free library does the same job as
|
||||
widely used non-free libraries. In this case, there is little to gain by
|
||||
limiting the free library to free software only, so we use the Lesser
|
||||
General Public License.
|
||||
|
||||
In other cases, permission to use a particular library in non-free programs
|
||||
enables a greater number of people to use a large body of free
|
||||
software. For example, permission to use the GNU C Library in non-free
|
||||
programs enables many more people to use the whole GNU operating system, as
|
||||
well as its variant, the GNU/Linux operating system.
|
||||
|
||||
Although the Lesser General Public License is Less protective of the users'
|
||||
freedom, it does ensure that the user of a program that is linked with the
|
||||
Library has the freedom and the wherewithal to run that program using a
|
||||
modified version of the Library.
|
||||
|
||||
The precise terms and conditions for copying, distribution and modification
|
||||
follow. Pay close attention to the difference between a "work based on the
|
||||
library" and a "work that uses the library". The former contains code
|
||||
derived from the library, whereas the latter must be combined with the
|
||||
library in order to run.
|
||||
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. This License Agreement applies to any software library or other program
|
||||
which contains a notice placed by the copyright holder or other
|
||||
authorized party saying it may be distributed under the terms of this
|
||||
Lesser General Public License (also called "this License"). Each
|
||||
licensee is addressed as "you".
|
||||
|
||||
A "library" means a collection of software functions and/or data
|
||||
prepared so as to be conveniently linked with application programs
|
||||
(which use some of those functions and data) to form executables.
|
||||
|
||||
The "Library", below, refers to any such software library or work which
|
||||
has been distributed under these terms. A "work based on the Library"
|
||||
means either the Library or any derivative work under copyright law:
|
||||
that is to say, a work containing the Library or a portion of it, either
|
||||
verbatim or with modifications and/or translated straightforwardly into
|
||||
another language. (Hereinafter, translation is included without
|
||||
limitation in the term "modification".)
|
||||
|
||||
"Source code" for a work means the preferred form of the work for making
|
||||
modifications to it. For a library, complete source code means all the
|
||||
source code for all modules it contains, plus any associated interface
|
||||
definition files, plus the scripts used to control compilation and
|
||||
installation of the library.
|
||||
|
||||
Activities other than copying, distribution and modification are not
|
||||
covered by this License; they are outside its scope. The act of running
|
||||
a program using the Library is not restricted, and output from such a
|
||||
program is covered only if its contents constitute a work based on the
|
||||
Library (independent of the use of the Library in a tool for writing
|
||||
it). Whether that is true depends on what the Library does and what the
|
||||
program that uses the Library does.
|
||||
|
||||
1. You may copy and distribute verbatim copies of the Library's complete
|
||||
source code as you receive it, in any medium, provided that you
|
||||
conspicuously and appropriately publish on each copy an appropriate
|
||||
copyright notice and disclaimer of warranty; keep intact all the notices
|
||||
that refer to this License and to the absence of any warranty; and
|
||||
distribute a copy of this License along with the Library.
|
||||
|
||||
You may charge a fee for the physical act of transferring a copy, and
|
||||
you may at your option offer warranty protection in exchange for a fee.
|
||||
|
||||
2. You may modify your copy or copies of the Library or any portion of it,
|
||||
thus forming a work based on the Library, and copy and distribute such
|
||||
modifications or work under the terms of Section 1 above, provided that
|
||||
you also meet all of these conditions:
|
||||
|
||||
a) The modified work must itself be a software library.
|
||||
|
||||
b) You must cause the files modified to carry prominent notices stating
|
||||
that you changed the files and the date of any change.
|
||||
|
||||
c) You must cause the whole of the work to be licensed at no charge to
|
||||
all third parties under the terms of this License.
|
||||
|
||||
d) If a facility in the modified Library refers to a function or a table
|
||||
of data to be supplied by an application program that uses the
|
||||
facility, other than as an argument passed when the facility is
|
||||
invoked, then you must make a good faith effort to ensure that, in
|
||||
the event an application does not supply such function or table, the
|
||||
facility still operates, and performs whatever part of its purpose
|
||||
remains meaningful.
|
||||
|
||||
(For example, a function in a library to compute square roots has a
|
||||
purpose that is entirely well-defined independent of the
|
||||
application. Therefore, Subsection 2d requires that any
|
||||
application-supplied function or table used by this function must be
|
||||
optional: if the application does not supply it, the square root
|
||||
function must still compute square roots.)
|
||||
|
||||
These requirements apply to the modified work as a whole. If
|
||||
identifiable sections of that work are not derived from the Library, and
|
||||
can be reasonably considered independent and separate works in
|
||||
themselves, then this License, and its terms, do not apply to those
|
||||
sections when you distribute them as separate works. But when you
|
||||
distribute the same sections as part of a whole which is a work based on
|
||||
the Library, the distribution of the whole must be on the terms of this
|
||||
License, whose permissions for other licensees extend to the entire
|
||||
whole, and thus to each and every part regardless of who wrote it.
|
||||
|
||||
Thus, it is not the intent of this section to claim rights or contest
|
||||
your rights to work written entirely by you; rather, the intent is to
|
||||
exercise the right to control the distribution of derivative or
|
||||
collective works based on the Library.
|
||||
|
||||
In addition, mere aggregation of another work not based on the Library
|
||||
with the Library (or with a work based on the Library) on a volume of a
|
||||
storage or distribution medium does not bring the other work under the
|
||||
scope of this License.
|
||||
|
||||
3. You may opt to apply the terms of the ordinary GNU General Public
|
||||
License instead of this License to a given copy of the Library. To do
|
||||
this, you must alter all the notices that refer to this License, so that
|
||||
they refer to the ordinary GNU General Public License, version 2,
|
||||
instead of to this License. (If a newer version than version 2 of the
|
||||
ordinary GNU General Public License has appeared, then you can specify
|
||||
that version instead if you wish.) Do not make any other change in these
|
||||
notices.
|
||||
|
||||
Once this change is made in a given copy, it is irreversible for that
|
||||
copy, so the ordinary GNU General Public License applies to all
|
||||
subsequent copies and derivative works made from that copy.
|
||||
|
||||
This option is useful when you wish to copy part of the code of the
|
||||
Library into a program that is not a library.
|
||||
|
||||
4. You may copy and distribute the Library (or a portion or derivative of
|
||||
it, under Section 2) in object code or executable form under the terms
|
||||
of Sections 1 and 2 above provided that you accompany it with the
|
||||
complete corresponding machine-readable source code, which must be
|
||||
distributed under the terms of Sections 1 and 2 above on a medium
|
||||
customarily used for software interchange.
|
||||
|
||||
If distribution of object code is made by offering access to copy from a
|
||||
designated place, then offering equivalent access to copy the source
|
||||
code from the same place satisfies the requirement to distribute the
|
||||
source code, even though third parties are not compelled to copy the
|
||||
source along with the object code.
|
||||
|
||||
5. A program that contains no derivative of any portion of the Library, but
|
||||
is designed to work with the Library by being compiled or linked with
|
||||
it, is called a "work that uses the Library". Such a work, in isolation,
|
||||
is not a derivative work of the Library, and therefore falls outside the
|
||||
scope of this License.
|
||||
|
||||
However, linking a "work that uses the Library" with the Library creates
|
||||
an executable that is a derivative of the Library (because it contains
|
||||
portions of the Library), rather than a "work that uses the
|
||||
library". The executable is therefore covered by this License. Section 6
|
||||
states terms for distribution of such executables.
|
||||
|
||||
When a "work that uses the Library" uses material from a header file
|
||||
that is part of the Library, the object code for the work may be a
|
||||
derivative work of the Library even though the source code is
|
||||
not. Whether this is true is especially significant if the work can be
|
||||
linked without the Library, or if the work is itself a library. The
|
||||
threshold for this to be true is not precisely defined by law.
|
||||
|
||||
If such an object file uses only numerical parameters, data structure
|
||||
layouts and accessors, and small macros and small inline functions (ten
|
||||
lines or less in length), then the use of the object file is
|
||||
unrestricted, regardless of whether it is legally a derivative
|
||||
work. (Executables containing this object code plus portions of the
|
||||
Library will still fall under Section 6.)
|
||||
|
||||
Otherwise, if the work is a derivative of the Library, you may
|
||||
distribute the object code for the work under the terms of Section
|
||||
6. Any executables containing that work also fall under Section 6,
|
||||
whether or not they are linked directly with the Library itself.
|
||||
|
||||
6. As an exception to the Sections above, you may also combine or link a
|
||||
"work that uses the Library" with the Library to produce a work
|
||||
containing portions of the Library, and distribute that work under terms
|
||||
of your choice, provided that the terms permit modification of the work
|
||||
for the customer's own use and reverse engineering for debugging such
|
||||
modifications.
|
||||
|
||||
You must give prominent notice with each copy of the work that the
|
||||
Library is used in it and that the Library and its use are covered by
|
||||
this License. You must supply a copy of this License. If the work during
|
||||
execution displays copyright notices, you must include the copyright
|
||||
notice for the Library among them, as well as a reference directing the
|
||||
user to the copy of this License. Also, you must do one of these things:
|
||||
|
||||
a) Accompany the work with the complete corresponding machine-readable
|
||||
source code for the Library including whatever changes were used in
|
||||
the work (which must be distributed under Sections 1 and 2 above);
|
||||
and, if the work is an executable linked with the Library, with the
|
||||
complete machine-readable "work that uses the Library", as object
|
||||
code and/or source code, so that the user can modify the Library and
|
||||
then relink to produce a modified executable containing the modified
|
||||
Library. (It is understood that the user who changes the contents of
|
||||
definitions files in the Library will not necessarily be able to
|
||||
recompile the application to use the modified definitions.)
|
||||
|
||||
b) Use a suitable shared library mechanism for linking with the
|
||||
Library. A suitable mechanism is one that (1) uses at run time a copy
|
||||
of the library already present on the user's computer system, rather
|
||||
than copying library functions into the executable, and (2) will
|
||||
operate properly with a modified version of the library, if the user
|
||||
installs one, as long as the modified version is interface-compatible
|
||||
with the version that the work was made with.
|
||||
|
||||
c) Accompany the work with a written offer, valid for at least three
|
||||
years, to give the same user the materials specified in Subsection
|
||||
6a, above, for a charge no more than the cost of performing this
|
||||
distribution.
|
||||
|
||||
d) If distribution of the work is made by offering access to copy from a
|
||||
designated place, offer equivalent access to copy the above specified
|
||||
materials from the same place.
|
||||
|
||||
e) Verify that the user has already received a copy of these materials
|
||||
or that you have already sent this user a copy.
|
||||
|
||||
For an executable, the required form of the "work that uses the Library"
|
||||
must include any data and utility programs needed for reproducing the
|
||||
executable from it. However, as a special exception, the materials to be
|
||||
distributed need not include anything that is normally distributed (in
|
||||
either source or binary form) with the major components (compiler,
|
||||
kernel, and so on) of the operating system on which the executable runs,
|
||||
unless that component itself accompanies the executable.
|
||||
|
||||
It may happen that this requirement contradicts the license restrictions
|
||||
of other proprietary libraries that do not normally accompany the
|
||||
operating system. Such a contradiction means you cannot use both them
|
||||
and the Library together in an executable that you distribute.
|
||||
|
||||
7. You may place library facilities that are a work based on the Library
|
||||
side-by-side in a single library together with other library facilities
|
||||
not covered by this License, and distribute such a combined library,
|
||||
provided that the separate distribution of the work based on the Library
|
||||
and of the other library facilities is otherwise permitted, and provided
|
||||
that you do these two things:
|
||||
|
||||
a) Accompany the combined library with a copy of the same work based on
|
||||
the Library, uncombined with any other library facilities. This must
|
||||
be distributed under the terms of the Sections above.
|
||||
|
||||
b) Give prominent notice with the combined library of the fact that part
|
||||
of it is a work based on the Library, and explaining where to find
|
||||
the accompanying uncombined form of the same work.
|
||||
|
||||
8. You may not copy, modify, sublicense, link with, or distribute the
|
||||
Library except as expressly provided under this License. Any attempt
|
||||
otherwise to copy, modify, sublicense, link with, or distribute the
|
||||
Library is void, and will automatically terminate your rights under this
|
||||
License. However, parties who have received copies, or rights, from you
|
||||
under this License will not have their licenses terminated so long as
|
||||
such parties remain in full compliance.
|
||||
|
||||
9. You are not required to accept this License, since you have not signed
|
||||
it. However, nothing else grants you permission to modify or distribute
|
||||
the Library or its derivative works. These actions are prohibited by law
|
||||
if you do not accept this License. Therefore, by modifying or
|
||||
distributing the Library (or any work based on the Library), you
|
||||
indicate your acceptance of this License to do so, and all its terms and
|
||||
conditions for copying, distributing or modifying the Library or works
|
||||
based on it.
|
||||
|
||||
10. Each time you redistribute the Library (or any work based on the
|
||||
Library), the recipient automatically receives a license from the
|
||||
original licensor to copy, distribute, link with or modify the Library
|
||||
subject to these terms and conditions. You may not impose any further
|
||||
restrictions on the recipients' exercise of the rights granted
|
||||
herein. You are not responsible for enforcing compliance by third
|
||||
parties with this License.
|
||||
|
||||
11. If, as a consequence of a court judgment or allegation of patent
|
||||
infringement or for any other reason (not limited to patent issues),
|
||||
conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot
|
||||
distribute so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you
|
||||
may not distribute the Library at all. For example, if a patent license
|
||||
would not permit royalty-free redistribution of the Library by all
|
||||
those who receive copies directly or indirectly through you, then the
|
||||
only way you could satisfy both it and this License would be to refrain
|
||||
entirely from distribution of the Library.
|
||||
|
||||
If any portion of this section is held invalid or unenforceable under
|
||||
any particular circumstance, the balance of the section is intended to
|
||||
apply, and the section as a whole is intended to apply in other
|
||||
circumstances.
|
||||
|
||||
It is not the purpose of this section to induce you to infringe any
|
||||
patents or other property right claims or to contest validity of any
|
||||
such claims; this section has the sole purpose of protecting the
|
||||
integrity of the free software distribution system which is implemented
|
||||
by public license practices. Many people have made generous
|
||||
contributions to the wide range of software distributed through that
|
||||
system in reliance on consistent application of that system; it is up
|
||||
to the author/donor to decide if he or she is willing to distribute
|
||||
software through any other system and a licensee cannot impose that
|
||||
choice.
|
||||
|
||||
This section is intended to make thoroughly clear what is believed to
|
||||
be a consequence of the rest of this License.
|
||||
|
||||
12. If the distribution and/or use of the Library is restricted in certain
|
||||
countries either by patents or by copyrighted interfaces, the original
|
||||
copyright holder who places the Library under this License may add an
|
||||
explicit geographical distribution limitation excluding those
|
||||
countries, so that distribution is permitted only in or among countries
|
||||
not thus excluded. In such case, this License incorporates the
|
||||
limitation as if written in the body of this License.
|
||||
|
||||
13. The Free Software Foundation may publish revised and/or new versions of
|
||||
the Lesser General Public License from time to time. Such new versions
|
||||
will be similar in spirit to the present version, but may differ in
|
||||
detail to address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the Library
|
||||
specifies a version number of this License which applies to it and "any
|
||||
later version", you have the option of following the terms and
|
||||
conditions either of that version or of any later version published by
|
||||
the Free Software Foundation. If the Library does not specify a license
|
||||
version number, you may choose any version ever published by the Free
|
||||
Software Foundation.
|
||||
|
||||
14. If you wish to incorporate parts of the Library into other free
|
||||
programs whose distribution conditions are incompatible with these,
|
||||
write to the author to ask for permission. For software which is
|
||||
copyrighted by the Free Software Foundation, write to the Free Software
|
||||
Foundation; we sometimes make exceptions for this. Our decision will be
|
||||
guided by the two goals of preserving the free status of all
|
||||
derivatives of our free software and of promoting the sharing and reuse
|
||||
of software generally.
|
||||
|
||||
NO WARRANTY
|
||||
|
||||
15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
|
||||
FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
|
||||
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
|
||||
PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
|
||||
EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE
|
||||
ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE LIBRARY IS WITH
|
||||
YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL
|
||||
NECESSARY SERVICING, REPAIR OR CORRECTION.
|
||||
|
||||
16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
|
||||
REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU FOR
|
||||
DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL
|
||||
DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE LIBRARY
|
||||
(INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED
|
||||
INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF
|
||||
THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR
|
||||
OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Libraries
|
||||
|
||||
If you develop a new library, and you want it to be of the greatest
|
||||
possible use to the public, we recommend making it free software that
|
||||
everyone can redistribute and change. You can do so by permitting
|
||||
redistribution under these terms (or, alternatively, under the terms of the
|
||||
ordinary General Public License).
|
||||
|
||||
To apply these terms, attach the following notices to the library. It is
|
||||
safest to attach them to the start of each source file to most effectively
|
||||
convey the exclusion of warranty; and each file should have at least the
|
||||
"copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
one line to give the library's name and an idea of what it does.
|
||||
Copyright (C) year name of author
|
||||
|
||||
This library is free software; you can redistribute it and/or modify it
|
||||
under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or (at
|
||||
your option) any later version.
|
||||
|
||||
This library 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 Lesser General Public License
|
||||
for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this library; if not, write to the Free Software Foundation,
|
||||
Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Also add
|
||||
information on how to contact you by electronic and paper mail.
|
||||
|
||||
You should also get your employer (if you work as a programmer) or your
|
||||
school, if any, to sign a "copyright disclaimer" for the library, if
|
||||
necessary. Here is a sample; alter the names:
|
||||
|
||||
Yoyodyne, Inc., hereby disclaims all copyright interest in
|
||||
the library `Frob' (a library for tweaking knobs) written
|
||||
by James Random Hacker.
|
||||
|
||||
signature of Ty Coon, 1 April 1990
|
||||
Ty Coon, President of Vice
|
||||
That's all there is to it!
|
|
@ -69,6 +69,7 @@ EXTRA_DIST += \
|
|||
LICENSES/preferred/GFDL-1.2 \
|
||||
LICENSES/preferred/gfdl-1.2.texi.readme \
|
||||
LICENSES/preferred/GPL-2.0 \
|
||||
LICENSES/preferred/LGPL-2.1 \
|
||||
LICENSES/preferred/MIT \
|
||||
LICENSES/stand-alone/GPL-3.0 \
|
||||
tools/logger.pl \
|
||||
|
|
|
@ -119,6 +119,7 @@ m4_define([USB1_ADAPTERS],
|
|||
[[stlink], [ST-Link Programmer], [HLADAPTER_STLINK]],
|
||||
[[ti_icdi], [TI ICDI JTAG Programmer], [HLADAPTER_ICDI]],
|
||||
[[ulink], [Keil ULINK JTAG Programmer], [ULINK]],
|
||||
[[angie], [ANGIE Adapter], [ANGIE]],
|
||||
[[usb_blaster_2], [Altera USB-Blaster II Compatible], [USB_BLASTER_2]],
|
||||
[[ft232r], [Bitbang mode of FT232R based devices], [FT232R]],
|
||||
[[vsllink], [Versaloon-Link JTAG Programmer], [VSLLINK]],
|
||||
|
|
|
@ -99,6 +99,8 @@ ATTRS{idVendor}=="0483", ATTRS{idProduct}=="374e", MODE="660", GROUP="plugdev",
|
|||
ATTRS{idVendor}=="0483", ATTRS{idProduct}=="374f", MODE="660", GROUP="plugdev", TAG+="uaccess"
|
||||
ATTRS{idVendor}=="0483", ATTRS{idProduct}=="3753", MODE="660", GROUP="plugdev", TAG+="uaccess"
|
||||
ATTRS{idVendor}=="0483", ATTRS{idProduct}=="3754", MODE="660", GROUP="plugdev", TAG+="uaccess"
|
||||
ATTRS{idVendor}=="0483", ATTRS{idProduct}=="3755", MODE="660", GROUP="plugdev", TAG+="uaccess"
|
||||
ATTRS{idVendor}=="0483", ATTRS{idProduct}=="3757", MODE="660", GROUP="plugdev", TAG+="uaccess"
|
||||
|
||||
# Cypress SuperSpeed Explorer Kit
|
||||
ATTRS{idVendor}=="04b4", ATTRS{idProduct}=="0007", MODE="660", GROUP="plugdev", TAG+="uaccess"
|
||||
|
@ -222,6 +224,10 @@ ATTRS{idVendor}=="2aec", ATTRS{idProduct}=="1106", MODE="660", GROUP="plugdev",
|
|||
ATTRS{idVendor}=="303a", ATTRS{idProduct}=="1001", MODE="660", GROUP="plugdev", TAG+="uaccess"
|
||||
ATTRS{idVendor}=="303a", ATTRS{idProduct}=="1002", MODE="660", GROUP="plugdev", TAG+="uaccess"
|
||||
|
||||
# ANGIE USB-JTAG Adapter
|
||||
ATTRS{idVendor}=="584e", ATTRS{idProduct}=="424e", MODE="660", GROUP="plugdev", TAG+="uaccess"
|
||||
ATTRS{idVendor}=="584e", ATTRS{idProduct}=="4a55", MODE="660", GROUP="plugdev", TAG+="uaccess"
|
||||
|
||||
# Marvell Sheevaplug
|
||||
ATTRS{idVendor}=="9e88", ATTRS{idProduct}=="9e8f", MODE="660", GROUP="plugdev", TAG+="uaccess"
|
||||
|
||||
|
|
|
@ -0,0 +1,75 @@
|
|||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
#****************************************************************************
|
||||
# File : Makefile *
|
||||
# Contents : Code for NanoXplore USB-JTAG ANGIE adapter hardware. *
|
||||
# Based on openULINK project by: Martin Schmoelzer. *
|
||||
# Copyright 2023, Ahmed Errached BOUDJELIDA, NanoXplore SAS. *
|
||||
# <aboudjelida@nanoxplore.com> *
|
||||
# <ahmederrachedbjld@gmail.com> *
|
||||
# ***************************************************************************/
|
||||
|
||||
# Define the name of tools.
|
||||
PREFIX =
|
||||
|
||||
# Small Device C Compiler: http://sdcc.sourceforge.net/
|
||||
CC = $(PREFIX)sdcc
|
||||
|
||||
# 8051 assembler, part of the SDCC software package.
|
||||
AS = $(PREFIX)sdas8051
|
||||
|
||||
# SDCC produces quite messy Intel HEX files. This tool is be used to re-format
|
||||
# those files. It is not required for the firmware download functionality in
|
||||
# the OpenOCD driver, but the resulting file is smaller.
|
||||
PACKIHX = $(PREFIX)packihx
|
||||
|
||||
# GNU binutils size. Used to print the size of the IHX file generated by SDCC.
|
||||
SIZE = size
|
||||
|
||||
# Source and header directories.
|
||||
SRC_DIR = src
|
||||
INCLUDE_DIR = include
|
||||
|
||||
CODE_SIZE = 0x3C00
|
||||
XRAM_LOC = 0x3C00
|
||||
XRAM_SIZE = 0x0400
|
||||
|
||||
CFLAGS = --std-sdcc99 --opt-code-size --model-small
|
||||
LDFLAGS = --code-loc 0x0000 --code-size $(CODE_SIZE) --xram-loc $(XRAM_LOC) \
|
||||
--xram-size $(XRAM_SIZE) --iram-size 256 --model-small
|
||||
|
||||
# list of base object files
|
||||
OBJECTS = main.rel usb.rel protocol.rel jtag.rel delay.rel USBJmpTb.rel serial.rel gpif.rel
|
||||
HEADERS = $(INCLUDE_DIR)/usb.h \
|
||||
$(INCLUDE_DIR)/protocol.h \
|
||||
$(INCLUDE_DIR)/jtag.h \
|
||||
$(INCLUDE_DIR)/delay.h \
|
||||
$(INCLUDE_DIR)/reg_ezusb.h \
|
||||
$(INCLUDE_DIR)/io.h \
|
||||
$(INCLUDE_DIR)/serial.h \
|
||||
$(INCLUDE_DIR)/fx2macros.h \
|
||||
$(INCLUDE_DIR)/msgtypes.h
|
||||
|
||||
# Disable all built-in rules.
|
||||
.SUFFIXES:
|
||||
|
||||
# Targets which are executed even when identically named file is present.
|
||||
.PHONY: all, clean
|
||||
|
||||
all: angie_firmware.ihx
|
||||
$(SIZE) angie_firmware.ihx
|
||||
|
||||
angie_firmware.ihx: $(OBJECTS)
|
||||
$(CC) -mmcs51 $(LDFLAGS) -o $@ $^
|
||||
|
||||
# Rebuild every C module (there are only 5 of them) if any header changes.
|
||||
%.rel: $(SRC_DIR)/%.c $(HEADERS)
|
||||
$(CC) -c $(CFLAGS) -mmcs51 -I$(INCLUDE_DIR) -o $@ $<
|
||||
|
||||
%.rel: $(SRC_DIR)/%.a51
|
||||
$(AS) -lsgo $@ $<
|
||||
|
||||
clean:
|
||||
rm -f *.asm *.lst *.rel *.rst *.sym *.ihx *.lk *.map *.mem
|
||||
|
||||
bin: angie_firmware.ihx
|
||||
makebin -p angie_firmware.ihx angie_firmware.bin
|
|
@ -0,0 +1,37 @@
|
|||
#SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
This is the ANGIE firmware for ANGIE USB-JTAG adapter.
|
||||
|
||||
The main components of ANGIE adapter are:
|
||||
- Cypress EZ-USB FX2 microcontroller
|
||||
- Spartan-6 FPGA
|
||||
- SRAM memory chip
|
||||
- Pin headers for various JTAG pin assignments
|
||||
|
||||
To compile the firmware, the SDCC compiler package is required. Most Linux
|
||||
distributions include SDCC in their official package repositories. The SDCC
|
||||
source code can be found at http://sdcc.sourceforge.net/
|
||||
|
||||
Simply type "make hex" in the ANGIE directory to compile the firmware.
|
||||
"make clean" will remove all generated files except the Intel HEX file
|
||||
required for downloading the firmware to ANGIE.
|
||||
|
||||
Note that the EZ-USB FX2 microcontroller does not have on-chip flash,
|
||||
ANGIE include on-board EEPROM memory to store the firmware program of
|
||||
the FX2, but we are not going to use this method.
|
||||
|
||||
Instead, upon initial connection of the ANGIE adapter to the host PC
|
||||
via USB, the EZ-USB FX2 core has enough intelligence to act as a
|
||||
stand-alone USB device, responding to USB control requests and allowing
|
||||
firmware download via a special VENDOR-type control request. Then, the
|
||||
EZ-USB microcontroller simulates a disconnect and re-connect to the USB bus.
|
||||
It may take up to two seconds for the host to recognize the newly connected
|
||||
device before OpenOCD can proceed to execute JTAG commands. This delay is
|
||||
only visible when OpenOCD first uses a blank (unconfigured) ANGIE device.
|
||||
|
||||
Once the firmware downloaded, the FX2 microcontroller activate its GPIF mode,
|
||||
download the Spartan-6 FPGA's bitstream, program the FPGA rapidly, and switch
|
||||
back to default io mode.
|
||||
|
||||
Once the user disconnects the ANGIE adapter, all its memory contents are lost
|
||||
and the firmware & bitstream download process has to be executed again.
|
|
@ -0,0 +1,50 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
/****************************************************************
|
||||
File : delay.h *
|
||||
Contents : Delays handling header file for NanoXplore *
|
||||
USB-JTAG ANGIE adapter hardware. *
|
||||
Based on openULINK project code by: Martin Schmoelzer. *
|
||||
Copyright 2023, Ahmed Errached BOUDJELIDA, NanoXplore SAS. *
|
||||
<aboudjelida@nanoxplore.com> *
|
||||
<ahmederrachedbjld@gmail.com> *
|
||||
*****************************************************************/
|
||||
|
||||
#ifndef __DELAY_H
|
||||
#define __DELAY_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
void syncdelay(uint8_t count);
|
||||
void delay_5us(void);
|
||||
void delay_1ms(void);
|
||||
void delay_us(uint16_t delay);
|
||||
void delay_ms(uint16_t delay);
|
||||
|
||||
#ifndef _IFREQ
|
||||
#define _IFREQ 48000 /* IFCLK frequency in kHz */
|
||||
#endif
|
||||
|
||||
/* CFREQ can be any one of: 48000, 24000, or 12000 */
|
||||
#ifndef _CFREQ
|
||||
#define _CFREQ 48000 /* CLKOUT frequency in kHz */
|
||||
#endif
|
||||
|
||||
#if (_IFREQ < 5000)
|
||||
#error "_IFREQ too small! Valid Range: 5000 to 48000..."
|
||||
#endif
|
||||
|
||||
#if (_IFREQ > 48000)
|
||||
#error "_IFREQ too large! Valid Range: 5000 to 48000..."
|
||||
#endif
|
||||
|
||||
#if (_CFREQ != 48000)
|
||||
#if (_CFREQ != 24000)
|
||||
#if (_CFREQ != 12000)
|
||||
#error "_CFREQ invalid! Valid values: 48000, 24000, 12000..."
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Synchronization Delay formula: see TRM section 15-14 */
|
||||
#define _SCYCL (3 * (_CFREQ) + 5 * (_IFREQ) - 1) / (2 * (_IFREQ))
|
||||
#endif
|
|
@ -0,0 +1,31 @@
|
|||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
|
||||
/*
|
||||
* This code was taken from the fx2lib project from this link:
|
||||
* https://github.com/djmuhlestein/fx2lib
|
||||
*
|
||||
* Copyright (C) 2009 Ubixum, Inc.
|
||||
*/
|
||||
|
||||
/*! \file
|
||||
* Macros for simple common tasks in fx2 firmware.
|
||||
* */
|
||||
|
||||
#ifndef FX2MACROS_H
|
||||
#define FX2MACROS_H
|
||||
|
||||
#include "reg_ezusb.h"
|
||||
|
||||
typedef enum {FALSE = 0, TRUE} BOOL_VALS;
|
||||
|
||||
/**
|
||||
* \brief Used for getting and setting the CPU clock speed.
|
||||
**/
|
||||
typedef enum {CLK_12M = 0, CLK_24M, CLK_48M} CLK_SPD;
|
||||
|
||||
/**
|
||||
* \brief Evaluates to a CLK_SPD enum.
|
||||
**/
|
||||
#define CPUFREQ (CLK_SPD)((CPUCS & bmclkspd) >> 3)
|
||||
|
||||
#endif
|
|
@ -0,0 +1,65 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
/****************************************************************************
|
||||
File : io.h *
|
||||
Contents : input/output declaration header file for NanoXplore *
|
||||
USB-JTAG ANGIE adapter hardware. *
|
||||
Based on openULINK project code by: Martin Schmoelzer. *
|
||||
Copyright 2023, Ahmed Errached BOUDJELIDA, NanoXplore SAS. *
|
||||
<aboudjelida@nanoxplore.com> *
|
||||
<ahmederrachedbjld@gmail.com> *
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef __IO_H
|
||||
#define __IO_H
|
||||
|
||||
#include "reg_ezusb.h"
|
||||
|
||||
/***************************************************************************
|
||||
* JTAG Signals: *
|
||||
***************************************************************************
|
||||
* TMS ....... Test Mode Select *
|
||||
* TCK ....... Test Clock *
|
||||
* TDI ....... Test Data Input (from device point of view, not JTAG *
|
||||
* adapter point of view!) *
|
||||
* TDO ....... Test Data Output (from device point of view, not JTAG *
|
||||
* adapter point of view!) *
|
||||
* TRST ...... Test Reset: Used to reset the TAP Finite State Machine *
|
||||
* into the Test Logic Reset state *
|
||||
* SRST ..... Chip Reset *
|
||||
***************************************************************************/
|
||||
|
||||
/* PORT A */
|
||||
/* PA0 Not Connected */
|
||||
/* PA1 Not Connected */
|
||||
#define PIN_RDWR_B IOA2
|
||||
#define PIN_CSI_B IOA3
|
||||
#define PIN_INIT_B IOA4
|
||||
#define PIN_PROGRAM_B IOA5
|
||||
/* PA6 Not Connected */
|
||||
/* PA7 Not Connected */
|
||||
|
||||
/* PORT B */
|
||||
#define PIN_TRST IOB0
|
||||
#define PIN_TMS IOB1
|
||||
#define PIN_TCK IOB2
|
||||
#define PIN_TDI IOB3
|
||||
#define PIN_TDO IOB4
|
||||
#define PIN_SRST IOB5
|
||||
/* PA6 Not Connected */
|
||||
/* PA7 Not Connected */
|
||||
|
||||
/* JTAG Signals with direction 'OUT' on port B */
|
||||
/* PIN_TDI - PIN_TCK - PIN_TMS - PIN_TRST - PIN_SRST */
|
||||
#define MASK_PORTB_DIRECTION_OUT (bmbit0 | bmbit1 | bmbit2 | bmbit3 | bmbit5)
|
||||
|
||||
/* PORT C */ // Debug:
|
||||
#define PIN_T0 IOC0
|
||||
#define PIN_T1 IOC1
|
||||
#define PIN_T2 IOC2
|
||||
#define PIN_T3 IOC3
|
||||
#define PIN_T4 IOC4
|
||||
/* PC5 Not Connected */
|
||||
/* PC6 Not Connected */
|
||||
/* PC7 Not Connected */
|
||||
|
||||
#endif
|
|
@ -0,0 +1,31 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
/****************************************************************************
|
||||
File : jtag.h *
|
||||
Contents : Jtag handling functions header file for NanoXplore *
|
||||
USB-JTAG ANGIE adapter hardware. *
|
||||
Based on openULINK project code by: Martin Schmoelzer. *
|
||||
Copyright 2023, Ahmed Errached BOUDJELIDA, NanoXplore SAS. *
|
||||
<aboudjelida@nanoxplore.com> *
|
||||
<ahmederrachedbjld@gmail.com> *
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef __JTAG_H
|
||||
#define __JTAG_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
uint16_t jtag_get_signals(void);
|
||||
void jtag_configure_tck_delay(uint8_t scan_in, uint8_t scan_out,
|
||||
uint8_t scan_io, uint8_t tck, uint8_t tms);
|
||||
void jtag_clock_tms(uint8_t count, uint8_t sequence);
|
||||
void jtag_slow_clock_tms(uint8_t count, uint8_t sequence);
|
||||
void jtag_set_signals(uint8_t low, uint8_t high);
|
||||
void jtag_clock_tck(uint16_t count);
|
||||
void jtag_slow_clock_tck(uint16_t count);
|
||||
void jtag_scan_in(uint8_t out_offset, uint8_t in_offset);
|
||||
void jtag_scan_out(uint8_t out_offset);
|
||||
void jtag_scan_io(uint8_t out_offset, uint8_t in_offset);
|
||||
void jtag_slow_scan_in(uint8_t out_offset, uint8_t in_offset);
|
||||
void jtag_slow_scan_out(uint8_t out_offset);
|
||||
void jtag_slow_scan_io(uint8_t out_offset, uint8_t in_offset);
|
||||
#endif
|
|
@ -0,0 +1,171 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
/****************************************************************************
|
||||
File : msgtypes.h *
|
||||
Contents : Definition of the commands supported by NanoXplore *
|
||||
USB-JTAG ANGIE adapter hardware. *
|
||||
Based on openULINK project code by: Martin Schmoelzer. *
|
||||
Copyright 2023, Ahmed Errached BOUDJELIDA, NanoXplore SAS. *
|
||||
<aboudjelida@nanoxplore.com> *
|
||||
<ahmederrachedbjld@gmail.com> *
|
||||
*****************************************************************************/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Definition of the commands supported by the ANGIE firmware.
|
||||
*
|
||||
* Basically, two types of commands can be distinguished:
|
||||
* - Commands with fixed payload size
|
||||
* - Commands with variable payload size
|
||||
*
|
||||
* SCAN commands (in all variations) carry payloads of variable size, all
|
||||
* other commands carry payloads of fixed size.
|
||||
*
|
||||
* In the case of SCAN commands, the payload size (n) is calculated by
|
||||
* dividing the scan_size_bits variable by 8, rounding up the result.
|
||||
*
|
||||
* Offset zero always contains the command ID.
|
||||
*
|
||||
****************************************************************************
|
||||
* CMD_SCAN_IN, CMD_SLOW_SCAN_IN: *
|
||||
* *
|
||||
* OUT: *
|
||||
* offset 1: scan_size_bytes *
|
||||
* offset 2: bits_last_byte *
|
||||
* offset 3: tms_count_start + tms_count_end *
|
||||
* offset 4: tms_sequence_start *
|
||||
* offset 5: tms_sequence_end *
|
||||
* *
|
||||
* IN: *
|
||||
* offset 0..n: TDO data *
|
||||
****************************************************************************
|
||||
* CMD_SCAN_OUT, CMD_SLOW_SCAN_OUT: *
|
||||
* *
|
||||
* OUT: *
|
||||
* offset 1: scan_size_bytes *
|
||||
* offset 2: bits_last_byte *
|
||||
* offset 3: tms_count_start + tms_count_end *
|
||||
* offset 4: tms_sequence_start *
|
||||
* offset 5: tms_sequence_end *
|
||||
* offset 6..x: TDI data *
|
||||
****************************************************************************
|
||||
* CMD_SCAN_IO, CMD_SLOW_SCAN_IO: *
|
||||
* *
|
||||
* OUT: *
|
||||
* offset 1: scan_size_bytes *
|
||||
* offset 2: bits_last_byte *
|
||||
* offset 3: tms_count_start + tms_count_end *
|
||||
* offset 4: tms_sequence_start *
|
||||
* offset 5: tms_sequence_end *
|
||||
* offset 6..x: TDI data *
|
||||
* *
|
||||
* IN: *
|
||||
* offset 0..n: TDO data *
|
||||
****************************************************************************
|
||||
* CMD_CLOCK_TMS, CMD_SLOW_CLOCK_TMS: *
|
||||
* *
|
||||
* OUT: *
|
||||
* offset 1: tms_count *
|
||||
* offset 2: tms_sequence *
|
||||
****************************************************************************
|
||||
* CMD_CLOCK_TCK, CMD_SLOW_CLOCK_TCK: *
|
||||
* *
|
||||
* OUT: *
|
||||
* offset 1: low byte of tck_count *
|
||||
* offset 2: high byte of tck_count *
|
||||
****************************************************************************
|
||||
* CMD_CLOCK_SLEEP_US: *
|
||||
* *
|
||||
* OUT: *
|
||||
* offset 1: low byte of sleep_us *
|
||||
* offset 2: high byte of sleep_us *
|
||||
****************************************************************************
|
||||
* CMD_CLOCK_SLEEP_MS: *
|
||||
* *
|
||||
* OUT: *
|
||||
* offset 1: low byte of sleep_ms *
|
||||
* offset 2: high byte of sleep_ms *
|
||||
****************************************************************************
|
||||
* CMD_GET_SIGNALS: *
|
||||
* *
|
||||
* IN: *
|
||||
* offset 0: current state of input signals *
|
||||
* offset 1: current state of output signals *
|
||||
****************************************************************************
|
||||
* CMD_SET_SIGNALS: *
|
||||
* *
|
||||
* OUT: *
|
||||
* offset 1: signals that should be de-asserted *
|
||||
* offset 2: signals that should be asserted *
|
||||
****************************************************************************
|
||||
* CMD_CONFIGURE_TCK_FREQ: *
|
||||
* *
|
||||
* OUT: *
|
||||
* offset 1: delay value for scan_in function *
|
||||
* offset 2: delay value for scan_out function *
|
||||
* offset 3: delay value for scan_io function *
|
||||
* offset 4: delay value for clock_tck function *
|
||||
* offset 5: delay value for clock_tms function *
|
||||
****************************************************************************
|
||||
* CMD_SET_LEDS: *
|
||||
* *
|
||||
* OUT: *
|
||||
* offset 1: LED states: *
|
||||
* Bit 0: turn COM LED on *
|
||||
* Bit 1: turn RUN LED on *
|
||||
* Bit 2: turn COM LED off *
|
||||
* Bit 3: turn RUN LED off *
|
||||
* Bits 7..4: Reserved *
|
||||
****************************************************************************
|
||||
* CMD_TEST: *
|
||||
* *
|
||||
* OUT: *
|
||||
* offset 1: unused dummy value *
|
||||
****************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef __MSGTYPES_H
|
||||
#define __MSGTYPES_H
|
||||
|
||||
/*
|
||||
* Command IDs:
|
||||
*
|
||||
* Bits 7..6: Reserved, should always be zero
|
||||
* Bits 5..0: Command ID. There are 62 usable IDs. Of this 63 available IDs,
|
||||
* the IDs 0x00..0x1F are commands with variable payload size,
|
||||
* the IDs 0x20..0x3F are commands with fixed payload size.
|
||||
*/
|
||||
|
||||
#define CMD_ID_MASK 0x3F
|
||||
|
||||
/* Commands with variable payload size */
|
||||
#define CMD_SCAN_IN 0x00
|
||||
#define CMD_SLOW_SCAN_IN 0x01
|
||||
#define CMD_SCAN_OUT 0x02
|
||||
#define CMD_SLOW_SCAN_OUT 0x03
|
||||
#define CMD_SCAN_IO 0x04
|
||||
#define CMD_SLOW_SCAN_IO 0x05
|
||||
|
||||
/* Commands with fixed payload size */
|
||||
#define CMD_CLOCK_TMS 0x20
|
||||
#define CMD_SLOW_CLOCK_TMS 0x21
|
||||
#define CMD_CLOCK_TCK 0x22
|
||||
#define CMD_SLOW_CLOCK_TCK 0x23
|
||||
#define CMD_SLEEP_US 0x24
|
||||
#define CMD_SLEEP_MS 0x25
|
||||
#define CMD_GET_SIGNALS 0x26
|
||||
#define CMD_SET_SIGNALS 0x27
|
||||
#define CMD_CONFIGURE_TCK_FREQ 0x28
|
||||
#define CMD_SET_LEDS 0x29
|
||||
#define CMD_TEST 0x2A
|
||||
|
||||
/* JTAG signal definition for jtag_get_signals() -- Input signals! */
|
||||
#define SIGNAL_TDO 1
|
||||
|
||||
/* JTAG signal definition for jtag_get_signals() -- Output signals! */
|
||||
#define SIGNAL_TDI 8
|
||||
#define SIGNAL_TMS 2
|
||||
#define SIGNAL_TCK 4
|
||||
#define SIGNAL_TRST 1
|
||||
#define SIGNAL_SRST 32
|
||||
|
||||
#endif
|
|
@ -0,0 +1,20 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
/****************************************************************************
|
||||
File : protocol.h *
|
||||
Contents : Jtag commands handling protocol header file for NanoXplore *
|
||||
USB-JTAG ANGIE adapter hardware. *
|
||||
Based on openULINK project code by: Martin Schmoelzer. *
|
||||
Copyright 2023, Ahmed Errached BOUDJELIDA, NanoXplore SAS. *
|
||||
<aboudjelida@nanoxplore.com> *
|
||||
<ahmederrachedbjld@gmail.com> *
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef __PROTOCOL_H
|
||||
#define __PROTOCOL_H
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
bool execute_command(void);
|
||||
void command_loop(void);
|
||||
|
||||
#endif
|
|
@ -0,0 +1,656 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
/****************************************************************************
|
||||
File : reg_ezusb.h *
|
||||
Contents : FX2 microcontroller registers file for NanoXplore *
|
||||
USB-JTAG ANGIE adapter hardware. *
|
||||
Based on openULINK project code by: Martin Schmoelzer. *
|
||||
Copyright 2023, Ahmed Errached BOUDJELIDA, NanoXplore SAS. *
|
||||
<aboudjelida@nanoxplore.com> *
|
||||
<ahmederrachedbjld@gmail.com> *
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef REG_EZUSB_H
|
||||
#define REG_EZUSB_H
|
||||
|
||||
/**
|
||||
* @file
|
||||
* All information in this file was taken from the EZ-USB FX2 Technical
|
||||
* Reference Manual, Cypress Semiconductor, 3901 North First Street
|
||||
* San Jose, CA 95134 (www.cypress.com).
|
||||
*
|
||||
* The EZ-USB Technical Reference Manual is called "EZ-USB FX2 TRM" hereafter.
|
||||
*/
|
||||
|
||||
/* Compiler-specific definitions of SBIT, SFR, SFRX, ... macros */
|
||||
#include <mcs51/compiler.h>
|
||||
|
||||
/* Bit vectors */
|
||||
#define bmbit0 0x01
|
||||
#define bmbit1 0x02
|
||||
#define bmbit2 0x04
|
||||
#define bmbit3 0x08
|
||||
#define bmbit4 0x10
|
||||
#define bmbit5 0x20
|
||||
#define bmbit6 0x40
|
||||
#define bmbit7 0x80
|
||||
|
||||
/**************************************************************************
|
||||
************************ Special Function Registers **********************
|
||||
***************************************************************************/
|
||||
SFR(IOA, 0x80);
|
||||
SBIT(IOA0, 0x80, 0);
|
||||
SBIT(IOA1, 0x80, 1);
|
||||
SBIT(IOA2, 0x80, 2);
|
||||
SBIT(IOA3, 0x80, 3);
|
||||
SBIT(IOA4, 0x80, 4);
|
||||
SBIT(IOA5, 0x80, 5);
|
||||
SBIT(IOA6, 0x80, 6);
|
||||
SBIT(IOA7, 0x80, 7);
|
||||
|
||||
SFR(SP, 0x81);
|
||||
SFR(DPL0, 0x82);
|
||||
SFR(DPH0, 0x83);
|
||||
SFR(DPL1, 0x84);
|
||||
SFR(DPL2, 0x85);
|
||||
|
||||
SFR(DPS, 0x86);
|
||||
#define SEL bmbit0
|
||||
/* Bit 1 read-only, always reads '0' */
|
||||
/* Bit 2 read-only, always reads '0' */
|
||||
/* Bit 3 read-only, always reads '0' */
|
||||
/* Bit 4 read-only, always reads '0' */
|
||||
/* Bit 5 read-only, always reads '0' */
|
||||
/* Bit 6 read-only, always reads '0' */
|
||||
/* Bit 7 read-only, always reads '0' */
|
||||
|
||||
SFR(PCON, 0x87);
|
||||
#define IDLE bmbit0
|
||||
#define STOP bmbit1
|
||||
#define GF0 bmbit2
|
||||
#define GF1 bmbit3
|
||||
/* Bit 4 read-only, always reads '1' */
|
||||
/* Bit 5 read-only, always reads '1' */
|
||||
/* Bit 6 unused */
|
||||
#define SMOD0 bmbit7
|
||||
|
||||
SFR(TCON, 0x88);
|
||||
SBIT(IT0, 0x88, 0);
|
||||
SBIT(IE0, 0x88, 1);
|
||||
SBIT(IT1, 0x88, 2);
|
||||
SBIT(IE1, 0x88, 3);
|
||||
SBIT(TR0, 0x88, 4);
|
||||
SBIT(TF0, 0x88, 5);
|
||||
SBIT(TR1, 0x88, 6);
|
||||
SBIT(TF1, 0x88, 7);
|
||||
|
||||
SFR(TMOD, 0x89);
|
||||
SFR(TL0, 0x8A);
|
||||
SFR(TL1, 0x8B);
|
||||
SFR(TH0, 0x8C);
|
||||
SFR(TH1, 0x8D);
|
||||
|
||||
SFR(CKCON, 0x8E);
|
||||
#define MD0 bmbit0
|
||||
#define MD1 bmbit1
|
||||
#define MD2 bmbit2
|
||||
#define T0M bmbit3
|
||||
#define T1M bmbit4
|
||||
#define T2M bmbit5
|
||||
/* Bit 6 unused */
|
||||
/* Bit 7 unused */
|
||||
|
||||
SFR(SPC_FNC, 0x8F);
|
||||
#define BMWRS bmbit0
|
||||
/* Bit 1 read-only, always reads '0' */
|
||||
/* Bit 2 read-only, always reads '0' */
|
||||
/* Bit 3 read-only, always reads '0' */
|
||||
/* Bit 4 read-only, always reads '0' */
|
||||
/* Bit 5 read-only, always reads '0' */
|
||||
/* Bit 6 read-only, always reads '0' */
|
||||
/* Bit 7 read-only, always reads '0' */
|
||||
|
||||
SFR(IOB, 0x90);
|
||||
SBIT(IOB0, 0x90, 0);
|
||||
SBIT(IOB1, 0x90, 1);
|
||||
SBIT(IOB2, 0x90, 2);
|
||||
SBIT(IOB3, 0x90, 3);
|
||||
SBIT(IOB4, 0x90, 4);
|
||||
SBIT(IOB5, 0x90, 5);
|
||||
SBIT(IOB6, 0x90, 6);
|
||||
SBIT(IOB7, 0x90, 7);
|
||||
|
||||
SFR(EXIF, 0x91);
|
||||
SBIT(USBINT, 0x91, 4);
|
||||
SBIT(I2CINT, 0x91, 5);
|
||||
SBIT(IE4, 0x91, 6);
|
||||
SBIT(IE5, 0x91, 7);
|
||||
|
||||
SFR(MPAGE, 0x92);
|
||||
SFR(SCON0, 0x98);
|
||||
SBIT(RI, 0x98, 0);
|
||||
SBIT(TI, 0x98, 1);
|
||||
SBIT(RB8, 0x98, 2);
|
||||
SBIT(TB8, 0x98, 3);
|
||||
SBIT(REN, 0x98, 4);
|
||||
SBIT(SM2, 0x98, 5);
|
||||
SBIT(SM1, 0x98, 6);
|
||||
SBIT(SM0, 0x98, 7);
|
||||
|
||||
SFR(SBUF0, 0x99);
|
||||
SFR(AUTOPTRH1, 0x9A);
|
||||
SFR(AUTOPTRL1, 0x9B);
|
||||
SFR(AUTOPTRH2, 0x9D);
|
||||
SFR(AUTOPTRL2, 0x9E);
|
||||
|
||||
#define AUTOPTR1H AUTOPTRH1 /* for backwards compatibility with examples */
|
||||
#define AUTOPTR1L AUTOPTRL1 /* for backwards compatibility with examples */
|
||||
#define APTR1H AUTOPTRH1 /* for backwards compatibility with examples */
|
||||
#define APTR1L AUTOPTRL1 /* for backwards compatibility with examples */
|
||||
|
||||
SFR(IOC, 0xA0);
|
||||
SBIT(IOC0, 0xA0, 0);
|
||||
SBIT(IOC1, 0xA0, 1);
|
||||
SBIT(IOC2, 0xA0, 2);
|
||||
SBIT(IOC3, 0xA0, 3);
|
||||
SBIT(IOC4, 0xA0, 4);
|
||||
SBIT(IOC5, 0xA0, 5);
|
||||
SBIT(IOC6, 0xA0, 6);
|
||||
SBIT(IOC7, 0xA0, 7);
|
||||
|
||||
SFR(INT2CLR, 0xA1);
|
||||
SFR(INT4CLR, 0xA2);
|
||||
SFR(IE, 0xA8);
|
||||
SBIT(EX0, 0xA8, 0);
|
||||
SBIT(ET0, 0xA8, 1);
|
||||
SBIT(EX1, 0xA8, 2);
|
||||
SBIT(ET1, 0xA8, 3);
|
||||
SBIT(ES0, 0xA8, 4);
|
||||
SBIT(ET2, 0xA8, 5);
|
||||
SBIT(ES1, 0xA8, 6);
|
||||
SBIT(EA, 0xA8, 7);
|
||||
|
||||
SFR(EP2468STAT, 0xAA);
|
||||
#define EP8F bmbit7
|
||||
#define EP8E bmbit6
|
||||
#define EP6F bmbit5
|
||||
#define EP6E bmbit4
|
||||
#define EP4F bmbit3
|
||||
#define EP4E bmbit2
|
||||
#define EP2F bmbit1
|
||||
#define EP2E bmbit0
|
||||
|
||||
SFR(EP24FIFOFLGS, 0xAB);
|
||||
SFR(EP68FIFOFLGS, 0xAC);
|
||||
SFR(AUTOPTRSETUP, 0xAF);
|
||||
SFR(IOD, 0xB0);
|
||||
SBIT(IOD0, 0xB0, 0);
|
||||
SBIT(IOD1, 0xB0, 1);
|
||||
SBIT(IOD2, 0xB0, 2);
|
||||
SBIT(IOD3, 0xB0, 3);
|
||||
SBIT(IOD4, 0xB0, 4);
|
||||
SBIT(IOD5, 0xB0, 5);
|
||||
SBIT(IOD6, 0xB0, 6);
|
||||
SBIT(IOD7, 0xB0, 7);
|
||||
|
||||
SFR(IOE, 0xB1);
|
||||
SFR(OEA, 0xB2);
|
||||
SFR(OEB, 0xB3);
|
||||
SFR(OEC, 0xB4);
|
||||
SFR(OED, 0xB5);
|
||||
SFR(OEE, 0xB6);
|
||||
|
||||
SFR(IP, 0xB8);
|
||||
SBIT(PX0, 0xB8, 0);
|
||||
SBIT(PT0, 0xB8, 1);
|
||||
SBIT(PX1, 0xB8, 2);
|
||||
SBIT(PT1, 0xB8, 3);
|
||||
SBIT(PS0, 0xB8, 4);
|
||||
SBIT(PT2, 0xB8, 5);
|
||||
SBIT(PS1, 0xB8, 6);
|
||||
/* Bit 7 read-only, always reads '1' */
|
||||
|
||||
SFR(EP01STAT, 0xBA);
|
||||
SFR(GPIFTRIG, 0xBB);
|
||||
#define BMGPIFDONE bmbit7
|
||||
#define BMGPIFREAD bmbit2
|
||||
#define GPIF_EP2 0
|
||||
#define GPIF_EP4 1
|
||||
#define GPIF_EP6 2
|
||||
#define GPIF_EP8 3
|
||||
|
||||
SFR(GPIFSGLDATH, 0xBD);
|
||||
SFR(GPIFSGLDATLX, 0xBE);
|
||||
SFR(GPIFSGLDATLNOX, 0xBF);
|
||||
|
||||
SFR(SCON1, 0xC0);
|
||||
SBIT(RI_1, 0xC0, 0);
|
||||
SBIT(TI_1, 0xC0, 1);
|
||||
SBIT(RB8_1, 0xC0, 2);
|
||||
SBIT(TB8_1, 0xC0, 3);
|
||||
SBIT(REN_1, 0xC0, 4);
|
||||
SBIT(SM2_1, 0xC0, 5);
|
||||
SBIT(SM1_1, 0xC0, 6);
|
||||
SBIT(SM0_1, 0xC0, 7);
|
||||
|
||||
SFR(SBUF1, 0xC1);
|
||||
SFR(T2CON, 0xC8);
|
||||
SBIT(CPRL2, 0xC8, 0);
|
||||
SBIT(C_T2, 0xC8, 1);
|
||||
SBIT(TR2, 0xC8, 2);
|
||||
SBIT(EXEN2, 0xC8, 3);
|
||||
SBIT(TCLK, 0xC8, 4);
|
||||
SBIT(RCLK, 0xC8, 5);
|
||||
SBIT(EXF2, 0xC8, 6);
|
||||
SBIT(TF2, 0xC8, 7);
|
||||
|
||||
SFR(RCAP2L, 0xCA);
|
||||
SFR(RCAP2H, 0xCB);
|
||||
SFR(TL2, 0xCC);
|
||||
SFR(TH2, 0xCD);
|
||||
SFR(PSW, 0xD0);
|
||||
SBIT(P, 0xD0, 0);
|
||||
SBIT(F1, 0xD0, 1);
|
||||
SBIT(OV, 0xD0, 2);
|
||||
SBIT(RS0, 0xD0, 3);
|
||||
SBIT(RS1, 0xD0, 4);
|
||||
SBIT(F0, 0xD0, 5);
|
||||
SBIT(AC, 0xD0, 6);
|
||||
SBIT(CY, 0xD0, 7);
|
||||
|
||||
SFR(EICON, 0xD8);
|
||||
/* Bit 0 read-only, always reads '0' */
|
||||
/* Bit 1 read-only, always reads '0' */
|
||||
/* Bit 2 read-only, always reads '0' */
|
||||
SBIT(INT6, 0xD8, 3);
|
||||
SBIT(RESI, 0xD8, 4);
|
||||
SBIT(ERESI, 0xD8, 5);
|
||||
/* Bit 6 read-only, always reads '1' */
|
||||
SBIT(SMOD1, 0xD8, 7);
|
||||
|
||||
SFR(ACC, 0xE0);
|
||||
SFR(EIE, 0xE8);
|
||||
SBIT(EUSB, 0xE8, 0);
|
||||
SBIT(EI2C, 0xE8, 1);
|
||||
SBIT(EX4, 0xE8, 2);
|
||||
SBIT(EX5, 0xE8, 3);
|
||||
SBIT(EWDI, 0xE8, 4);
|
||||
/* Bit 5 read-only, always reads '1' */
|
||||
/* Bit 6 read-only, always reads '1' */
|
||||
/* Bit 7 read-only, always reads '1' */
|
||||
|
||||
SFR(B, 0xF0);
|
||||
SFR(EIP, 0xF8);
|
||||
SBIT(PUSB, 0xF8, 0);
|
||||
SBIT(PI2C, 0xF8, 1);
|
||||
SBIT(PX4, 0xF8, 2);
|
||||
SBIT(PX5, 0xF8, 3);
|
||||
SBIT(PX6, 0xF8, 4);
|
||||
/* Bit 5 read-only, always reads '1' */
|
||||
/* Bit 6 read-only, always reads '1' */
|
||||
/* Bit 7 read-only, always reads '1' */
|
||||
|
||||
/**************************************************************************
|
||||
***************************** XDATA Registers ****************************
|
||||
***************************************************************************/
|
||||
|
||||
SFRX(GPIF_WAVE_DATA, 0xE400);
|
||||
SFRX(RES_WAVEDATA_END, 0xE480);
|
||||
|
||||
/* General Configuration */
|
||||
SFRX(CPUCS, 0xE600);
|
||||
#define RES8051 bmbit0
|
||||
#define CLKOE bmbit1
|
||||
#define BMCLKINV bmbit2
|
||||
#define bmclkspd0 bmbit3
|
||||
#define bmclkspd1 bmbit4
|
||||
#define bmclkspd (bmbit4 | bmbit3)
|
||||
#define BMPRTCSTB bmbit5
|
||||
|
||||
/* PCON register */
|
||||
#define BMSMOD0 bmbit7
|
||||
|
||||
SFRX(IFCONFIG, 0xE601);
|
||||
#define BMIFCLKSRC bmbit7
|
||||
#define BM3048MHZ bmbit6
|
||||
#define BMIFCLKOE bmbit5
|
||||
#define BMIFCLKPOL bmbit4
|
||||
#define BMASYNC bmbit3
|
||||
#define BMGSTATE bmbit2
|
||||
#define BMIFCFG1 bmbit1
|
||||
#define BMIFCFG0 bmbit0
|
||||
#define BMIFCFGMASK (BMIFCFG0 | BMIFCFG1)
|
||||
#define BMIFGPIF BMIFCFG1
|
||||
|
||||
SFRX(PINFLAGSAB, 0xE602);
|
||||
SFRX(PINFLAGSCD, 0xE603);
|
||||
SFRX(FIFORESET, 0xE604);
|
||||
#define BMNAKALL bmbit7
|
||||
|
||||
SFRX(BREAKPT, 0xE605);
|
||||
#define BMBREAK bmbit3
|
||||
#define BMBPPULSE bmbit2
|
||||
#define BMBPEN bmbit1
|
||||
|
||||
SFRX(BPADDRH, 0xE606);
|
||||
SFRX(BPADDRL, 0xE607);
|
||||
SFRX(UART230, 0xE608);
|
||||
SFRX(FIFOPINPOLAR, 0xE609);
|
||||
SFRX(REVID, 0xE60A);
|
||||
SFRX(REVCTL, 0xE60B);
|
||||
#define BMNOAUTOARM bmbit1
|
||||
#define BMSKIPCOMMIT bmbit0
|
||||
|
||||
/* Endpoint Configuration */
|
||||
SFRX(EP1OUTCFG, 0xE610);
|
||||
SFRX(EP1INCFG, 0xE611);
|
||||
SFRX(EP2CFG, 0xE612);
|
||||
SFRX(EP4CFG, 0xE613);
|
||||
SFRX(EP6CFG, 0xE614);
|
||||
SFRX(EP8CFG, 0xE615);
|
||||
SFRX(EP2FIFOCFG, 0xE618);
|
||||
SFRX(EP4FIFOCFG, 0xE619);
|
||||
SFRX(EP6FIFOCFG, 0xE61A);
|
||||
SFRX(EP8FIFOCFG, 0xE61B);
|
||||
#define BMINFM bmbit6
|
||||
#define BMOEP bmbit5
|
||||
#define BMAUTOOUT bmbit4
|
||||
#define BMAUTOIN bmbit3
|
||||
#define BMZEROLENIN bmbit2
|
||||
#define BMWORDWIDE bmbit0
|
||||
|
||||
SFRX(EP2AUTOINLENH, 0xE620);
|
||||
SFRX(EP2AUTOINLENL, 0xE621);
|
||||
SFRX(EP4AUTOINLENH, 0xE622);
|
||||
SFRX(EP4AUTOINLENL, 0xE623);
|
||||
SFRX(EP6AUTOINLENH, 0xE612);
|
||||
SFRX(EP6AUTOINLENL, 0xE613);
|
||||
SFRX(EP8AUTOINLENH, 0xE614);
|
||||
SFRX(EP8AUTOINLENL, 0xE615);
|
||||
SFRX(EP2FIFOPFH, 0xE630);
|
||||
SFRX(EP2FIFOPFL, 0xE631);
|
||||
SFRX(EP4FIFOPFH, 0xE632);
|
||||
SFRX(EP4FIFOPFL, 0xE633);
|
||||
SFRX(EP6FIFOPFH, 0xE634);
|
||||
SFRX(EP6FIFOPFL, 0xE635);
|
||||
SFRX(EP8FIFOPFH, 0xE636);
|
||||
SFRX(EP8FIFOPFL, 0xE637);
|
||||
SFRX(EP2ISOINPKTS, 0xE640);
|
||||
SFRX(EP4ISOINPKTS, 0xE641);
|
||||
SFRX(EP6ISOINPKTS, 0xE642);
|
||||
SFRX(EP8ISOINPKTS, 0xE643);
|
||||
SFRX(INPKTEND, 0xE648);
|
||||
SFRX(OUTPKTEND, 0xE649);
|
||||
|
||||
/* Interrupts */
|
||||
SFRX(EP2FIFOIE, 0xE650);
|
||||
SFRX(EP2FIFOIRQ, 0xE651);
|
||||
SFRX(EP4FIFOIE, 0xE652);
|
||||
SFRX(EP4FIFOIRQ, 0xE653);
|
||||
SFRX(EP6FIFOIE, 0xE654);
|
||||
SFRX(EP6FIFOIRQ, 0xE655);
|
||||
SFRX(EP8FIFOIE, 0xE656);
|
||||
SFRX(EP8FIFOIRQ, 0xE657);
|
||||
SFRX(IBNIE, 0xE658);
|
||||
SFRX(IBNIRQ, 0xE659);
|
||||
#define EP0IBN bmbit0
|
||||
#define EP1IBN bmbit1
|
||||
#define EP2IBN bmbit2
|
||||
#define EP4IBN bmbit3
|
||||
#define EP6IBN bmbit4
|
||||
#define EP8IBN bmbit5
|
||||
|
||||
SFRX(NAKIE, 0xE65A);
|
||||
SFRX(NAKIRQ, 0xE65B);
|
||||
#define EP8PING bmbit7
|
||||
#define EP6PING bmbit6
|
||||
#define EP4PING bmbit5
|
||||
#define EP2PING bmbit4
|
||||
#define EP1PING bmbit3
|
||||
#define EP0PING bmbit2
|
||||
#define IBN bmbit0
|
||||
|
||||
SFRX(USBIEN, 0xE65C);
|
||||
SFRX(USBIRQ, 0xE65D);
|
||||
#define SUDAVI bmbit0
|
||||
#define SOFI bmbit1
|
||||
#define SUTOKI bmbit2
|
||||
#define SUSPI bmbit3
|
||||
#define URESI bmbit4
|
||||
#define HSGRANT bmbit5
|
||||
#define EP0ACK bmbit6
|
||||
|
||||
SFRX(EPIE, 0xE65E);
|
||||
SFRX(EPIRQ, 0xE65F);
|
||||
SFRX(GPIFIE, 0xE660);
|
||||
SFRX(GPIFIRQ, 0xE661);
|
||||
SFRX(USBERRIE, 0xE662);
|
||||
SFRX(USBERRIRQ, 0xE663);
|
||||
SFRX(ERRCNTLIM, 0xE664);
|
||||
SFRX(CLRERRCNT, 0xE665);
|
||||
SFRX(INT2IVEC, 0xE666);
|
||||
#define I2V0 bmbit2
|
||||
#define I2V1 bmbit3
|
||||
#define I2V2 bmbit4
|
||||
#define I2V3 bmbit5
|
||||
#define I2V4 bmbit6
|
||||
|
||||
SFRX(INT4IVEC, 0xE667);
|
||||
SFRX(INTSETUP, 0xE668);
|
||||
#define AV4EN bmbit0
|
||||
#define INT4IN bmbit1
|
||||
#define AV2EN bmbit3
|
||||
|
||||
/* Input/Output */
|
||||
SFRX(PORTACFG, 0xE670);
|
||||
#define BMINT0 bmbit0
|
||||
#define BMINT1 bmbit1
|
||||
#define BMFLAGD bmbit7
|
||||
|
||||
SFRX(PORTCCFG, 0xE671);
|
||||
#define BMGPIFA0 bmbit0
|
||||
#define BMGPIFA1 bmbit1
|
||||
#define BMGPIFA2 bmbit2
|
||||
#define BMGPIFA3 bmbit3
|
||||
#define BMGPIFA4 bmbit4
|
||||
#define BMGPIFA5 bmbit5
|
||||
#define BMGPIFA6 bmbit6
|
||||
#define BMGPIFA7 bmbit7
|
||||
|
||||
SFRX(PORTECFG, 0xE672);
|
||||
#define BMT0OUT bmbit0
|
||||
#define BMT1OUT bmbit1
|
||||
#define BMT2OUT bmbit2
|
||||
#define BMRXD0OUT bmbit3
|
||||
#define BMRXD1OUT bmbit4
|
||||
#define BMINT6 bmbit5
|
||||
#define BMT2EX bmbit6
|
||||
#define BMGPIFA8 bmbit7
|
||||
|
||||
SFRX(I2CS, 0xE678);
|
||||
#define BMDONE bmbit0
|
||||
#define BMACK bmbit1
|
||||
#define BMBERR bmbit2
|
||||
#define BMID (bmbit4 | bmbit3)
|
||||
#define BMLASTRD bmbit5
|
||||
#define BMSTOP bmbit6
|
||||
#define BMSTART bmbit7
|
||||
|
||||
SFRX(I2DAT, 0xE679);
|
||||
SFRX(I2CTL, 0xE67A);
|
||||
#define BMSTOPIE bmbit1
|
||||
#define BM400KHZ bmbit0
|
||||
|
||||
SFRX(XAUTODAT1, 0xE67B);
|
||||
SFRX(XAUTODAT2, 0xE67C);
|
||||
#define EXTAUTODAT1 XAUTODAT1
|
||||
#define EXTAUTODAT2 XAUTODAT2
|
||||
|
||||
/* USB Control */
|
||||
SFRX(USBCS, 0xE680);
|
||||
#define SIGRSUME bmbit0
|
||||
#define RENUM bmbit1
|
||||
#define NOSYNSOF bmbit2
|
||||
#define DISCON bmbit3
|
||||
#define HSM bmbit7
|
||||
|
||||
SFRX(SUSPEND, 0xE681);
|
||||
SFRX(WAKEUPCS, 0xE682);
|
||||
#define BMWU2 bmbit7
|
||||
#define BMWU bmbit6
|
||||
#define BMWU2POL bmbit5
|
||||
#define BMWUPOL bmbit4
|
||||
#define BMDPEN bmbit2
|
||||
#define BMWU2EN bmbit1
|
||||
#define BMWUEN bmbit0
|
||||
|
||||
SFRX(TOGCTL, 0xE683);
|
||||
#define BMTOGCTLEPMASK bmbit3 | bmbit2 | bmbit1 | bmbit0
|
||||
#define BMRESETTOGGLE bmbit5
|
||||
#define BMSETTOGGLE bmbit6
|
||||
#define BMQUERYTOGGLE bmbit7
|
||||
|
||||
SFRX(USBFRAMEH, 0xE684);
|
||||
SFRX(USBFRAMEL, 0xE685);
|
||||
SFRX(MICROFRAME, 0xE686);
|
||||
SFRX(FNADDR, 0xE687);
|
||||
|
||||
/* Endpoints */
|
||||
SFRX(EP0BCH, 0xE68A);
|
||||
SFRX(EP0BCL, 0xE68B);
|
||||
SFRX(EP1OUTBC, 0xE68D);
|
||||
SFRX(EP1INBC, 0xE68F);
|
||||
SFRX(EP2BCH, 0xE690);
|
||||
SFRX(EP2BCL, 0xE691);
|
||||
SFRX(EP4BCH, 0xE694);
|
||||
SFRX(EP4BCL, 0xE695);
|
||||
SFRX(EP6BCH, 0xE698);
|
||||
SFRX(EP6BCL, 0xE699);
|
||||
SFRX(EP8BCH, 0xE69C);
|
||||
SFRX(EP8BCL, 0xE69D);
|
||||
SFRX(EP0CS, 0xE6A0);
|
||||
#define HSNAK bmbit7
|
||||
|
||||
SFRX(EP1INCS, 0xE6A2);
|
||||
SFRX(EP1OUTCS, 0xE6A1);
|
||||
#define EPSTALL bmbit0
|
||||
#define EPBSY bmbit1
|
||||
|
||||
SFRX(EP2CS, 0xE6A3);
|
||||
SFRX(EP4CS, 0xE6A4);
|
||||
SFRX(EP6CS, 0xE6A5);
|
||||
SFRX(EP8CS, 0xE6A6);
|
||||
#define BMEPEMPTY bmbit2
|
||||
#define BMEPFULL bmbit3
|
||||
#define BMNPAK (bmbit6 | bmbit5 | bmbit4)
|
||||
|
||||
SFRX(EP2FIFOFLGS, 0xE6A7);
|
||||
SFRX(EP4FIFOFLGS, 0xE6A8);
|
||||
SFRX(EP6FIFOFLGS, 0xE6A9);
|
||||
SFRX(EP8FIFOFLGS, 0xE6AA);
|
||||
SFRX(EP2FIFOBCH, 0xE6AB);
|
||||
SFRX(EP2FIFOBCL, 0xE6AC);
|
||||
SFRX(EP4FIFOBCH, 0xE6AD);
|
||||
SFRX(EP4FIFOBCL, 0xE6AE);
|
||||
SFRX(EP6FIFOBCH, 0xE6AF);
|
||||
SFRX(EP6FIFOBCL, 0xE6B0);
|
||||
SFRX(EP8FIFOBCH, 0xE6B1);
|
||||
SFRX(EP8FIFOBCL, 0xE6B2);
|
||||
SFRX(SUDPTRH, 0xE6B3);
|
||||
SFRX(SUDPTRL, 0xE6B4);
|
||||
|
||||
SFRX(SUDPTRCTL, 0xE6B5);
|
||||
#define BMSDPAUTO bmbit0
|
||||
|
||||
SFRX(SETUPDAT[8], 0xE6B8);
|
||||
|
||||
/* GPIF */
|
||||
SFRX(GPIFWFSELECT, 0xE6C0);
|
||||
SFRX(GPIFIDLECS, 0xE6C1);
|
||||
SFRX(GPIFIDLECTL, 0xE6C2);
|
||||
SFRX(GPIFCTLCFG, 0xE6C3);
|
||||
SFRX(GPIFADRH, 0xE6C4);
|
||||
SFRX(GPIFADRL, 0xE6C5);
|
||||
SFRX(GPIFTCB3, 0xE6CE);
|
||||
SFRX(GPIFTCB2, 0xE6CF);
|
||||
SFRX(GPIFTCB1, 0xE6D0);
|
||||
SFRX(GPIFTCB0, 0xE6D1);
|
||||
|
||||
#define EP2GPIFTCH GPIFTCB1 /* these are here for backwards compatibility */
|
||||
#define EP2GPIFTCL GPIFTCB0
|
||||
#define EP4GPIFTCH GPIFTCB1 /* these are here for backwards compatibility */
|
||||
#define EP4GPIFTCL GPIFTCB0
|
||||
#define EP6GPIFTCH GPIFTCB1 /* these are here for backwards compatibility */
|
||||
#define EP6GPIFTCL GPIFTCB0
|
||||
#define EP8GPIFTCH GPIFTCB1 /* these are here for backwards compatibility */
|
||||
#define EP8GPIFTCL GPIFTCB0
|
||||
|
||||
SFRX(EP2GPIFFLGSEL, 0xE6D2);
|
||||
SFRX(EP2GPIFPFSTOP, 0xE6D3);
|
||||
SFRX(EP2GPIFTRIG, 0xE6D4);
|
||||
SFRX(EP4GPIFFLGSEL, 0xE6DA);
|
||||
SFRX(EP4GPIFPFSTOP, 0xE6DB);
|
||||
SFRX(EP4GPIFTRIG, 0xE6DC);
|
||||
SFRX(EP6GPIFFLGSEL, 0xE6E2);
|
||||
SFRX(EP6GPIFPFSTOP, 0xE6E3);
|
||||
SFRX(EP6GPIFTRIG, 0xE6E4);
|
||||
SFRX(EP8GPIFFLGSEL, 0xE6EA);
|
||||
SFRX(EP8GPIFPFSTOP, 0xE6EB);
|
||||
SFRX(EP8GPIFTRIG, 0xE6EC);
|
||||
SFRX(XGPIFSGLDATH, 0xE6F0);
|
||||
SFRX(XGPIFSGLDATLX, 0xE6F1);
|
||||
SFRX(XGPIFSGLDATLNOX, 0xE6F2);
|
||||
SFRX(GPIFREADYCFG, 0xE6F3);
|
||||
SFRX(GPIFREADYSTAT, 0xE6F4);
|
||||
SFRX(GPIFABORT, 0xE6F5);
|
||||
|
||||
// UDMA
|
||||
SFRX(FLOWSTATE, 0xE6C6);
|
||||
SFRX(FLOWLOGIC, 0xE6C7);
|
||||
SFRX(FLOWEQ0CTL, 0xE6C8);
|
||||
SFRX(FLOWEQ1CTL, 0xE6C9);
|
||||
SFRX(FLOWHOLDOFF, 0xE6CA);
|
||||
SFRX(FLOWSTB, 0xE6CB);
|
||||
SFRX(FLOWSTBEDGE, 0xE6CC);
|
||||
SFRX(FLOWSTBHPERIOD, 0xE6CD);
|
||||
SFRX(GPIFHOLDAMOUNT, 0xE60C);
|
||||
SFRX(UDMACRCH, 0xE67D);
|
||||
SFRX(UDMACRCL, 0xE67E);
|
||||
SFRX(UDMACRCQUAL, 0xE67F);
|
||||
|
||||
/* Debug/Test
|
||||
* The following registers are for Cypress's internal testing purposes only.
|
||||
* These registers are not documented in the datasheet or the Technical Reference
|
||||
* Manual as they were not designed for end user application usage
|
||||
*/
|
||||
SFRX(DBUG, 0xE6F8);
|
||||
SFRX(TESTCFG, 0xE6F9);
|
||||
SFRX(USBTEST, 0xE6FA);
|
||||
SFRX(CT1, 0xE6FB);
|
||||
SFRX(CT2, 0xE6FC);
|
||||
SFRX(CT3, 0xE6FD);
|
||||
SFRX(CT4, 0xE6FE);
|
||||
|
||||
/* Endpoint Buffers */
|
||||
SFRX(EP0BUF[64], 0xE740);
|
||||
SFRX(EP1INBUF[64], 0xE7C0);
|
||||
SFRX(EP1OUTBUF[64], 0xE780);
|
||||
SFRX(EP2FIFOBUF[512], 0xF000);
|
||||
SFRX(EP4FIFOBUF[512], 0xF400);
|
||||
SFRX(EP6FIFOBUF[512], 0xF800);
|
||||
SFRX(EP8FIFOBUF[512], 0xFC00);
|
||||
|
||||
/* Error Correction Code (ECC) Registers (FX2LP/FX1 only) */
|
||||
SFRX(ECCCFG, 0xE628);
|
||||
SFRX(ECCRESET, 0xE629);
|
||||
SFRX(ECC1B0, 0xE62A);
|
||||
SFRX(ECC1B1, 0xE62B);
|
||||
SFRX(ECC1B2, 0xE62C);
|
||||
SFRX(ECC2B0, 0xE62D);
|
||||
SFRX(ECC2B1, 0xE62E);
|
||||
SFRX(ECC2B2, 0xE62F);
|
||||
|
||||
/* Feature Registers (FX2LP/FX1 only) */
|
||||
SFRX(GPCR2, 0xE50D);
|
||||
#define BMFULLSPEEDONLY bmbit4
|
||||
|
||||
#endif
|
|
@ -0,0 +1,47 @@
|
|||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
|
||||
/**
|
||||
* This code was taken from the fx2lib project from this link:
|
||||
* https://github.com/djmuhlestein/fx2lib
|
||||
*
|
||||
* Copyright (C) 2009 Ubixum, Inc.
|
||||
**/
|
||||
|
||||
/** \file serial.h
|
||||
* defines functions to print to a serial console with SIO0
|
||||
**/
|
||||
|
||||
#include "fx2macros.h"
|
||||
#include <stdint.h>
|
||||
/**
|
||||
* This function inits sio0 to use T2CON (timer 2)
|
||||
* See TRM 14.3.4.1 (Table 14-16)
|
||||
* Certain baud rates have too high an error rate to work. All baud rates are .16%
|
||||
* except:
|
||||
*
|
||||
* 12MHZ 24MHZ
|
||||
* \li 57600 -6.99%
|
||||
* \li 38400 -2.34% -2.34%
|
||||
* \li 19200 -2.34%
|
||||
*
|
||||
* Possible Baud rates:
|
||||
* \li 2400
|
||||
* \li 4800
|
||||
* \li 9600
|
||||
* \li 19200
|
||||
* \li 28800
|
||||
* \li 38400
|
||||
* \li 57600
|
||||
*
|
||||
* Any of these rates should work except 57600 at 12mhz. -2.34% is pushing
|
||||
* most hardware specs for working. All rates at 48mhz work at .16%
|
||||
**/
|
||||
|
||||
void sio0_init(uint32_t baud_rate) __critical; /* baud_rate max should be 57600 since int=2 bytes */
|
||||
|
||||
/**
|
||||
* putchar('\\n') or putchar('\\r') both transmit \\r\\n
|
||||
* Just use one or the other. (This makes terminal echo easy)
|
||||
**/
|
||||
int putchar(char c);
|
||||
int getchar(void);
|
|
@ -0,0 +1,273 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
/****************************************************************************
|
||||
File : usb.h *
|
||||
Contents : usb communication handling header file for NanoXplore *
|
||||
USB-JTAG ANGIE adapter hardware. *
|
||||
Based on openULINK project code by: Martin Schmoelzer. *
|
||||
Copyright 2023, Ahmed Errached BOUDJELIDA, NanoXplore SAS. *
|
||||
<aboudjelida@nanoxplore.com> *
|
||||
<ahmederrachedbjld@gmail.com> *
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef __USB_H
|
||||
#define __USB_H
|
||||
|
||||
#include "reg_ezusb.h"
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
/* High and Low byte of a word (uint16_t) */
|
||||
#define HI8(word) (uint8_t)(((uint16_t)(word) >> 8) & 0xff)
|
||||
#define LO8(word) (uint8_t)((uint16_t)(word) & 0xff)
|
||||
|
||||
/* Convenience functions */
|
||||
#define STALL_EP0() (EP0CS |= EPSTALL)
|
||||
#define CLEAR_IRQ() (USBINT = 0)
|
||||
|
||||
/*********** USB descriptors. See section 9.5 of the USB 1.1 spec **********/
|
||||
|
||||
/* USB Descriptor Types. See USB 1.1 spec, page 187, table 9-5 */
|
||||
#define DESCRIPTOR_TYPE_DEVICE 0x01
|
||||
#define DESCRIPTOR_TYPE_CONFIGURATION 0x02
|
||||
#define DESCRIPTOR_TYPE_STRING 0x03
|
||||
#define DESCRIPTOR_TYPE_INTERFACE 0x04
|
||||
#define DESCRIPTOR_TYPE_ENDPOINT 0x05
|
||||
|
||||
#define STR_DESCR(len, ...) { (len) * 2 + 2, DESCRIPTOR_TYPE_STRING, { __VA_ARGS__ } }
|
||||
|
||||
/** USB Device Descriptor. See USB 1.1 spec, pp. 196 - 198 */
|
||||
struct usb_device_descriptor {
|
||||
uint8_t blength; /**< Size of this descriptor in bytes. */
|
||||
uint8_t bdescriptortype; /**< DEVICE Descriptor Type. */
|
||||
uint16_t bcdusb; /**< USB specification release number (BCD). */
|
||||
uint8_t bdeviceclass; /**< Class code. */
|
||||
uint8_t bdevicesubclass; /**< Subclass code. */
|
||||
uint8_t bdeviceprotocol; /**< Protocol code. */
|
||||
uint8_t bmaxpacketsize0; /**< Maximum packet size for EP0 (8, 16, 32, 64). */
|
||||
uint16_t idvendor; /**< USB Vendor ID. */
|
||||
uint16_t idproduct; /**< USB Product ID. */
|
||||
uint16_t bcddevice; /**< Device Release Number (BCD). */
|
||||
uint8_t imanufacturer; /**< Index of manufacturer string descriptor. */
|
||||
uint8_t iproduct; /**< Index of product string descriptor. */
|
||||
uint8_t iserialnumber; /**< Index of string descriptor containing serial #. */
|
||||
uint8_t bnumconfigurations; /**< Number of possible configurations. */
|
||||
};
|
||||
|
||||
/** USB Configuration Descriptor. See USB 1.1 spec, pp. 199 - 200 */
|
||||
struct usb_config_descriptor {
|
||||
uint8_t blength; /**< Size of this descriptor in bytes. */
|
||||
uint8_t bdescriptortype; /**< CONFIGURATION descriptor type. */
|
||||
uint16_t wtotallength; /**< Combined total length of all descriptors. */
|
||||
uint8_t bnuminterfaces; /**< Number of interfaces in this configuration. */
|
||||
uint8_t bconfigurationvalue; /**< Value used to select this configuration. */
|
||||
uint8_t iconfiguration; /**< Index of configuration string descriptor. */
|
||||
uint8_t bmattributes; /**< Configuration characteristics. */
|
||||
uint8_t maxpower; /**< Maximum power consumption in 2 mA units. */
|
||||
};
|
||||
|
||||
/** USB Interface Descriptor. See USB 1.1 spec, pp. 201 - 203 */
|
||||
struct usb_interface_descriptor {
|
||||
uint8_t blength; /**< Size of this descriptor in bytes. */
|
||||
uint8_t bdescriptortype; /**< INTERFACE descriptor type. */
|
||||
uint8_t binterfacenumber; /**< Interface number. */
|
||||
uint8_t balternatesetting; /**< Value used to select alternate setting. */
|
||||
uint8_t bnumendpoints; /**< Number of endpoints used by this interface. */
|
||||
uint8_t binterfaceclass; /**< Class code. */
|
||||
uint8_t binterfacesubclass; /**< Subclass code. */
|
||||
uint8_t binterfaceprotocol; /**< Protocol code. */
|
||||
uint8_t iinterface; /**< Index of interface string descriptor. */
|
||||
};
|
||||
|
||||
/** USB Endpoint Descriptor. See USB 1.1 spec, pp. 203 - 204 */
|
||||
struct usb_endpoint_descriptor {
|
||||
uint8_t blength; /**< Size of this descriptor in bytes. */
|
||||
uint8_t bdescriptortype; /**< ENDPOINT descriptor type. */
|
||||
uint8_t bendpointaddress; /**< Endpoint Address: IN/OUT + EP number. */
|
||||
uint8_t bmattributes; /**< Endpoint Attributes: BULK/INTR/ISO/CTRL. */
|
||||
uint16_t wmaxpacketsize; /**< Maximum packet size for this endpoint. */
|
||||
uint8_t binterval; /**< Polling interval (in ms) for this endpoint. */
|
||||
};
|
||||
|
||||
/** USB Language Descriptor. See USB 1.1 spec, pp. 204 - 205 */
|
||||
struct usb_language_descriptor {
|
||||
uint8_t blength; /**< Size of this descriptor in bytes. */
|
||||
uint8_t bdescriptortype; /**< STRING descriptor type. */
|
||||
uint16_t wlangid[]; /**< LANGID codes. */
|
||||
};
|
||||
|
||||
/** USB String Descriptor. See USB 1.1 spec, pp. 204 - 205 */
|
||||
struct usb_string_descriptor {
|
||||
uint8_t blength; /**< Size of this descriptor in bytes. */
|
||||
uint8_t bdescriptortype; /**< STRING descriptor type. */
|
||||
uint16_t bstring[]; /**< UNICODE encoded string. */
|
||||
};
|
||||
|
||||
/********************** USB Control Endpoint 0 related *********************/
|
||||
|
||||
/** USB Control Setup Data. See USB 1.1 spec, pp. 183 - 185 */
|
||||
struct setup_data {
|
||||
uint8_t bmrequesttype; /**< Characteristics of a request. */
|
||||
uint8_t brequest; /**< Specific request. */
|
||||
uint16_t wvalue; /**< Field that varies according to request. */
|
||||
uint16_t windex; /**< Field that varies according to request. */
|
||||
uint16_t wlength; /**< Number of bytes to transfer in data stage. */
|
||||
};
|
||||
|
||||
/* External declarations for variables that need to be accessed outside of
|
||||
* the USB module */
|
||||
extern volatile bool ep1_out;
|
||||
extern volatile bool ep1_in;
|
||||
|
||||
extern volatile __xdata __at 0xE6B8 struct setup_data setup_data;
|
||||
|
||||
/*
|
||||
* USB Request Types (bmRequestType): See USB 1.1 spec, page 183, table 9-2
|
||||
*
|
||||
* Bit 7: Data transfer direction
|
||||
* 0 = Host-to-device
|
||||
* 1 = Device-to-host
|
||||
* Bit 6...5: Type
|
||||
* 0 = Standard
|
||||
* 1 = Class
|
||||
* 2 = Vendor
|
||||
* 3 = Reserved
|
||||
* Bit 4...0: Recipient
|
||||
* 0 = Device
|
||||
* 1 = Interface
|
||||
* 2 = Endpoint
|
||||
* 3 = Other
|
||||
* 4...31 = Reserved
|
||||
*/
|
||||
|
||||
#define USB_DIR_OUT 0x00
|
||||
#define USB_DIR_IN 0x80
|
||||
|
||||
#define USB_REQ_TYPE_STANDARD (0x00 << 5)
|
||||
#define USB_REQ_TYPE_CLASS (0x01 << 5)
|
||||
#define USB_REQ_TYPE_VENDOR (0x02 << 5)
|
||||
#define USB_REQ_TYPE_RESERVED (0x03 << 5)
|
||||
|
||||
#define USB_RECIP_DEVICE 0x00
|
||||
#define USB_RECIP_INTERFACE 0x01
|
||||
#define USB_RECIP_ENDPOINT 0x02
|
||||
#define USB_RECIP_OTHER 0x03
|
||||
|
||||
/* Clear Interface Request */
|
||||
#define CF_DEVICE (USB_DIR_OUT | USB_REQ_TYPE_STANDARD | USB_RECIP_DEVICE)
|
||||
#define CF_INTERFACE (USB_DIR_OUT | USB_REQ_TYPE_STANDARD | USB_RECIP_INTERFACE)
|
||||
#define CF_ENDPOINT (USB_DIR_OUT | USB_REQ_TYPE_STANDARD | USB_RECIP_ENDPOINT)
|
||||
|
||||
/* Get Configuration Request */
|
||||
#define GC_DEVICE (USB_DIR_IN | USB_REQ_TYPE_STANDARD | USB_RECIP_DEVICE)
|
||||
|
||||
/* Get Descriptor Request */
|
||||
#define GD_DEVICE (USB_DIR_IN | USB_REQ_TYPE_STANDARD | USB_RECIP_DEVICE)
|
||||
|
||||
/* Get Interface Request */
|
||||
#define GI_INTERFACE (USB_DIR_IN | USB_REQ_TYPE_STANDARD | USB_RECIP_INTERFACE)
|
||||
|
||||
/* Get Status Request: See USB 1.1 spec, page 190 */
|
||||
#define GS_DEVICE (USB_DIR_IN | USB_REQ_TYPE_STANDARD | USB_RECIP_DEVICE)
|
||||
#define GS_INTERFACE (USB_DIR_IN | USB_REQ_TYPE_STANDARD | USB_RECIP_INTERFACE)
|
||||
#define GS_ENDPOINT (USB_DIR_IN | USB_REQ_TYPE_STANDARD | USB_RECIP_ENDPOINT)
|
||||
|
||||
/* Set Address Request is handled by EZ-USB core */
|
||||
|
||||
/* Set Configuration Request */
|
||||
#define SC_DEVICE (USB_DIR_OUT | USB_REQ_TYPE_STANDARD | USB_RECIP_DEVICE)
|
||||
|
||||
/* Set Descriptor Request */
|
||||
#define SD_DEVICE (USB_DIR_OUT | USB_REQ_TYPE_STANDARD | USB_RECIP_DEVICE)
|
||||
|
||||
/* Set Feature Request */
|
||||
#define SF_DEVICE (USB_DIR_OUT | USB_REQ_TYPE_STANDARD | USB_RECIP_DEVICE)
|
||||
#define SF_INTERFACE (USB_DIR_OUT | USB_REQ_TYPE_STANDARD | USB_RECIP_INTERFACE)
|
||||
#define SF_ENDPOINT (USB_DIR_OUT | USB_REQ_TYPE_STANDARD | USB_RECIP_ENDPOINT)
|
||||
|
||||
/* Set Interface Request */
|
||||
#define SI_INTERFACE (USB_DIR_OUT | USB_REQ_TYPE_STANDARD | USB_RECIP_INTERFACE)
|
||||
|
||||
/* Synch Frame Request */
|
||||
#define SY_ENDPOINT (USB_DIR_IN | USB_REQ_TYPE_STANDARD | USB_RECIP_ENDPOINT)
|
||||
|
||||
/* USB Requests (bRequest): See USB 1.1 spec, table 9-4 on page 187 */
|
||||
#define GET_STATUS 0
|
||||
#define CLEAR_FEATURE 1
|
||||
/* Value '2' is reserved for future use */
|
||||
#define SET_FEATURE 3
|
||||
/* Value '4' is reserved for future use */
|
||||
#define SET_ADDRESS 5
|
||||
#define GET_DESCRIPTOR 6
|
||||
#define SET_DESCRIPTOR 7
|
||||
#define GET_CONFIGURATION 8
|
||||
#define SET_CONFIGURATION 9
|
||||
#define GET_INTERFACE 10
|
||||
#define SET_INTERFACE 11
|
||||
#define SYNCH_FRAME 12
|
||||
|
||||
/* Standard Feature Selectors: See USB 1.1 spec, table 9-6 on page 188 */
|
||||
#define DEVICE_REMOTE_WAKEUP 1
|
||||
#define ENDPOINT_HALT 0
|
||||
|
||||
/************************** EZ-USB specific stuff **************************/
|
||||
/** USB Interrupts. See AN2131-TRM, page 9-4 for details */
|
||||
enum usb_isr {
|
||||
SUDAV_ISR = 13,
|
||||
SOF_ISR,
|
||||
SUTOK_ISR,
|
||||
SUSPEND_ISR,
|
||||
USBRESET_ISR,
|
||||
HIGHSPEED_ISR,
|
||||
EP0ACK_ISR,
|
||||
STUB_ISR,
|
||||
EP0IN_ISR,
|
||||
EP0OUT_ISR,
|
||||
EP1IN_ISR,
|
||||
EP1OUT_ISR,
|
||||
EP2_ISR,
|
||||
EP4_ISR,
|
||||
EP6_ISR,
|
||||
EP8_ISR,
|
||||
IBN_ISR,
|
||||
EP0PINGNAK_ISR,
|
||||
EP1PINGNAK_ISR,
|
||||
EP2PINGNAK_ISR,
|
||||
EP4PINGNAK_ISR,
|
||||
EP6PINGNAK_ISR,
|
||||
EP8PINGNAK_ISR,
|
||||
ERRORLIMIT_ISR,
|
||||
EP2PIDERROR_ISR,
|
||||
EP4PIDERROR_ISR,
|
||||
EP6PIDERROR_ISR,
|
||||
EP8PIDERROR_ISR,
|
||||
EP2PFLAG_ISR,
|
||||
EP4PFLAG_ISR,
|
||||
EP6PFLAG_ISR,
|
||||
EP8PFLAG_ISR,
|
||||
EP2EFLAG_ISR,
|
||||
EP4EFLAG_ISR,
|
||||
EP6EFLAG_ISR,
|
||||
EP8EFLAG_ISR,
|
||||
EP2FFLAG_ISR,
|
||||
EP4FFLAG_ISR,
|
||||
EP6FFLAG_ISR,
|
||||
EP8FFLAG_ISR,
|
||||
GPIFCOMPLETE_ISR,
|
||||
GPIFWAVEFORM_ISR
|
||||
};
|
||||
|
||||
/*************************** Function Prototypes ***************************/
|
||||
__xdata uint8_t *usb_get_endpoint_cs_reg(uint8_t ep);
|
||||
void usb_reset_data_toggle(uint8_t ep);
|
||||
bool usb_handle_get_status(void);
|
||||
bool usb_handle_clear_feature(void);
|
||||
bool usb_handle_set_feature(void);
|
||||
bool usb_handle_get_descriptor(void);
|
||||
void usb_handle_set_interface(void);
|
||||
void usb_handle_setup_data(void);
|
||||
|
||||
void ep_init(void);
|
||||
void interrupt_init(void);
|
||||
void io_init(void);
|
||||
|
||||
#endif
|
|
@ -0,0 +1,125 @@
|
|||
; SPDX-License-Identifier: GPL-2.0-or-later
|
||||
;****************************************************************************
|
||||
; File : USBJmpTb.a51 *
|
||||
; Contents : Interruptions vector configuration. *
|
||||
; Based on openULINK project code by: Martin Schmoelzer. *
|
||||
; Copyright 2023, Ahmed Errached BOUDJELIDA, NanoXplore SAS. *
|
||||
; <aboudjelida@nanoxplore.com> *
|
||||
; <ahmederrachedbjld@gmail.com> *
|
||||
;****************************************************************************
|
||||
.module JUMPTABLE
|
||||
|
||||
.globl USB_AutoVector
|
||||
.globl USB_Jump_Table
|
||||
|
||||
.globl _sudav_isr, _sof_isr, _sutok_isr, _suspend_isr, _usbreset_isr, _highspeed_isr, _ep0ack_isr, _stub_isr, _ep0in_isr, _ep0out_isr, _ep1in_isr, _ep1out_isr, _ep2_isr, _ep4_isr, _ep6_isr, _ep8_isr, _ibn_isr
|
||||
.globl _ep0pingnak_isr, _ep1pingnak_isr, _ep2pingnak_isr, _ep4pingnak_isr, _ep6pingnak_isr, _ep8pingnak_isr, _errorlimit_isr, _stub_isr, _stub_isr, _stub_isr, _ep2piderror_isr, _ep4piderror_isr, _ep6piderror_isr, _ep8piderror_isr
|
||||
.globl _ep2pflag_isr, _ep4pflag_isr, _ep6pflag_isr, _ep8pflag_isr, _ep2eflag_isr, _ep4eflag_isr, _ep6eflag_isr, _ep8eflag_isr, _ep2fflag_isr, _ep4fflag_isr, _ep6fflag_isr, _ep8fflag_isr, _gpifcomplete_isr, _gpifwaveform_isr
|
||||
|
||||
;--------------------------------------------------------------------------;
|
||||
; Interrupt Vectors ;
|
||||
;--------------------------------------------------------------------------;
|
||||
.area USB_JV (ABS,OVR) ; Absolute, Overlay
|
||||
.org 0x43 ; USB interrupt (INT2) jumps here
|
||||
USB_AutoVector = #. + 2
|
||||
ljmp USB_Jump_Table ; Autovector will replace byte 45
|
||||
|
||||
;--------------------------------------------------------------------------;
|
||||
; USB Jump Table ;
|
||||
;--------------------------------------------------------------------------;
|
||||
.area USB_JT (ABS) ; Absolute placement
|
||||
.org 0x0200 ; Place jump table at 0x0200
|
||||
|
||||
USB_Jump_Table: ; autovector jump table
|
||||
ljmp _sudav_isr ; (00) Setup Data Available
|
||||
.db 0
|
||||
ljmp _sof_isr ; (04) Start of Frame
|
||||
.db 0
|
||||
ljmp _sutok_isr ; (08) Setup Data Loading
|
||||
.db 0
|
||||
ljmp _suspend_isr ; (0C) Global Suspend
|
||||
.db 0
|
||||
ljmp _usbreset_isr ; (10) USB Reset
|
||||
.db 0
|
||||
ljmp _highspeed_isr ; (14) Entered High Speed
|
||||
.db 0
|
||||
ljmp _ep0ack_isr ; (18) EP0ACK
|
||||
.db 0
|
||||
ljmp _stub_isr ; (1C) Reserved
|
||||
.db 0
|
||||
ljmp _ep0in_isr ; (20) EP0 In
|
||||
.db 0
|
||||
ljmp _ep0out_isr ; (24) EP0 Out
|
||||
.db 0
|
||||
ljmp _ep1in_isr ; (28) EP1 In
|
||||
.db 0
|
||||
ljmp _ep1out_isr ; (2C) EP1 Out
|
||||
.db 0
|
||||
ljmp _ep2_isr ; (30) EP2 In/Out
|
||||
.db 0
|
||||
ljmp _ep4_isr ; (34) EP4 In/Out
|
||||
.db 0
|
||||
ljmp _ep6_isr ; (38) EP6 In/Out
|
||||
.db 0
|
||||
ljmp _ep8_isr ; (3C) EP8 In/Out
|
||||
.db 0
|
||||
ljmp _ibn_isr ; (40) IBN
|
||||
.db 0
|
||||
ljmp _stub_isr ; (44) Reserved
|
||||
.db 0
|
||||
ljmp _ep0pingnak_isr ; (48) EP0 PING NAK
|
||||
.db 0
|
||||
ljmp _ep1pingnak_isr ; (4C) EP1 PING NAK
|
||||
.db 0
|
||||
ljmp _ep2pingnak_isr ; (50) EP2 PING NAK
|
||||
.db 0
|
||||
ljmp _ep4pingnak_isr ; (54) EP4 PING NAK
|
||||
.db 0
|
||||
ljmp _ep6pingnak_isr ; (58) EP6 PING NAK
|
||||
.db 0
|
||||
ljmp _ep8pingnak_isr ; (5C) EP8 PING NAK
|
||||
.db 0
|
||||
ljmp _errorlimit_isr ; (60) Error Limit
|
||||
.db 0
|
||||
ljmp _stub_isr ; (64) Reserved
|
||||
.db 0
|
||||
ljmp _stub_isr ; (68) Reserved
|
||||
.db 0
|
||||
ljmp _stub_isr ; (6C) Reserved
|
||||
.db 0
|
||||
ljmp _ep2piderror_isr ; (70) EP2 ISO Pid Sequence Error
|
||||
.db 0
|
||||
ljmp _ep4piderror_isr ; (74) EP4 ISO Pid Sequence Error
|
||||
.db 0
|
||||
ljmp _ep6piderror_isr ; (78) EP6 ISO Pid Sequence Error
|
||||
.db 0
|
||||
ljmp _ep8piderror_isr ; (7C) EP8 ISO Pid Sequence Error
|
||||
.db 0
|
||||
ljmp _ep2pflag_isr ; (80) EP2 Programmable Flag
|
||||
.db 0
|
||||
ljmp _ep4pflag_isr ; (84) EP4 Programmable Flag
|
||||
.db 0
|
||||
ljmp _ep6pflag_isr ; (88) EP6 Programmable Flag
|
||||
.db 0
|
||||
ljmp _ep8pflag_isr ; (8C) EP8 Programmable Flag
|
||||
.db 0
|
||||
ljmp _ep2eflag_isr ; (90) EP2 Empty Flag
|
||||
.db 0
|
||||
ljmp _ep4eflag_isr ; (94) EP4 Empty Flag
|
||||
.db 0
|
||||
ljmp _ep6eflag_isr ; (98) EP6 Empty Flag
|
||||
.db 0
|
||||
ljmp _ep8eflag_isr ; (9C) EP8 Empty Flag
|
||||
.db 0
|
||||
ljmp _ep2fflag_isr ; (A0) EP2 Full Flag
|
||||
.db 0
|
||||
ljmp _ep4fflag_isr ; (A4) EP4 Full Flag
|
||||
.db 0
|
||||
ljmp _ep6fflag_isr ; (A8) EP6 Full Flag
|
||||
.db 0
|
||||
ljmp _ep8fflag_isr ; (AC) EP8 Full Flag
|
||||
.db 0
|
||||
ljmp _gpifcomplete_isr ; (B0) GPIF Operation Complete
|
||||
.db 0
|
||||
ljmp _gpifwaveform_isr ; (B4) GPIF Waveform
|
||||
.db 0
|
|
@ -0,0 +1,49 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
/****************************************************************************
|
||||
File : delay.c *
|
||||
Contents : Delays handling fucntions code for NanoXplore *
|
||||
USB-JTAG ANGIE adapter hardware. *
|
||||
Based on openULINK project code by: Martin Schmoelzer. *
|
||||
Copyright 2023, Ahmed Errached BOUDJELIDA, NanoXplore SAS. *
|
||||
<aboudjelida@nanoxplore.com> *
|
||||
<ahmederrachedbjld@gmail.com> *
|
||||
*****************************************************************************/
|
||||
|
||||
#include "delay.h"
|
||||
#include <mcs51/compiler.h>
|
||||
|
||||
void syncdelay(uint8_t count)
|
||||
{
|
||||
for (uint8_t i = 0; i < count; i++)
|
||||
NOP();
|
||||
}
|
||||
|
||||
void delay_5us(void)
|
||||
{
|
||||
NOP();
|
||||
}
|
||||
|
||||
void delay_1ms(void)
|
||||
{
|
||||
uint16_t i;
|
||||
|
||||
for (i = 0; i < 598; i++)
|
||||
;
|
||||
}
|
||||
|
||||
void delay_us(uint16_t delay)
|
||||
{
|
||||
uint16_t i;
|
||||
uint16_t maxcount = (delay / 5);
|
||||
|
||||
for (i = 0; i < maxcount; i++)
|
||||
delay_5us();
|
||||
}
|
||||
|
||||
void delay_ms(uint16_t delay)
|
||||
{
|
||||
uint16_t i;
|
||||
|
||||
for (i = 0; i < delay; i++)
|
||||
delay_1ms();
|
||||
}
|
|
@ -0,0 +1,98 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
/*
|
||||
This program configures the General Programmable Interface (GPIF) for FX2.
|
||||
Please do not modify sections of text which are marked as "DO NOT EDIT ...".
|
||||
*/
|
||||
|
||||
/* GPIF Program Code */
|
||||
|
||||
#include "reg_ezusb.h"
|
||||
#include "delay.h"
|
||||
|
||||
/****************************** GPIF PROGRAM CODE ********************************/
|
||||
/* DO NOT EDIT ... */
|
||||
const char wavedata[128] = {
|
||||
/* Wave 0 */
|
||||
/* LenBr */ 0x01, 0x3F, 0x01, 0x01, 0x01, 0x01, 0x01, 0x07,
|
||||
/* Opcode*/ 0x02, 0x07, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00,
|
||||
/* Output*/ 0x04, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
|
||||
/* LFun */ 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F,
|
||||
/* Wave 1 */
|
||||
/* LenBr */ 0x88, 0x01, 0x3F, 0x01, 0x01, 0x01, 0x01, 0x07,
|
||||
/* Opcode*/ 0x01, 0x02, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
/* Output*/ 0x07, 0x05, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
|
||||
/* LFun */ 0x09, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x3F,
|
||||
/* Wave 2 */
|
||||
/* LenBr */ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x07,
|
||||
/* Opcode*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
/* Output*/ 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
|
||||
/* LFun */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F,
|
||||
/* Wave 3 */
|
||||
/* LenBr */ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x07,
|
||||
/* Opcode*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
/* Output*/ 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
|
||||
/* LFun */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F,
|
||||
};
|
||||
/* END DO NOT EDIT */
|
||||
|
||||
/* DO NOT EDIT ... */
|
||||
const char flowstates[36] = {
|
||||
/* Wave 0 flowstates */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
/* Wave 1 flowstates */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
/* Wave 2 flowstates */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
/* Wave 3 flowstates */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
};
|
||||
/* END DO NOT EDIT */
|
||||
|
||||
/* DO NOT EDIT ... */
|
||||
const char initdata[7] = {
|
||||
/* Regs */ 0xE0, 0x00, 0x00, 0x07, 0xEE, 0xF2, 0x00
|
||||
};
|
||||
/* END DO NOT EDIT */
|
||||
|
||||
void gpif_init(void)
|
||||
{
|
||||
uint8_t i;
|
||||
|
||||
IFCONFIG = 0xEE;
|
||||
|
||||
GPIFABORT = 0xFF; /* abort any waveforms pending */
|
||||
GPIFREADYCFG = initdata[0];
|
||||
GPIFCTLCFG = initdata[1];
|
||||
GPIFIDLECS = initdata[2];
|
||||
GPIFIDLECTL = initdata[3];
|
||||
GPIFWFSELECT = initdata[5];
|
||||
GPIFREADYSTAT = initdata[6];
|
||||
|
||||
/* use dual autopointer feature... */
|
||||
AUTOPTRSETUP = 0x07;
|
||||
|
||||
/* source */
|
||||
AUTOPTRH1 = (uint8_t)(((uint16_t)(&wavedata) >> 8) & 0xff);
|
||||
AUTOPTRL1 = (uint8_t)((uint16_t)(&wavedata) & 0xff);
|
||||
|
||||
/* destination */
|
||||
AUTOPTRH2 = 0xE4;
|
||||
AUTOPTRL2 = 0x00;
|
||||
|
||||
/* transfer */
|
||||
for (i = 0x00; i < 128; i++)
|
||||
EXTAUTODAT2 = EXTAUTODAT1;
|
||||
|
||||
/* GPIF address pins update when GPIFADRH/L written */
|
||||
syncdelay(3);
|
||||
GPIFADRH = 0x00; /* bits[7:1] always 0 */
|
||||
syncdelay(3);
|
||||
GPIFADRL = 0x00; /* point to PERIPHERAL address 0x0000 */
|
||||
|
||||
/* Configure GPIF flowstates registers for Wave 0 of wavedata */
|
||||
FLOWSTATE = flowstates[0];
|
||||
FLOWLOGIC = flowstates[1];
|
||||
FLOWEQ0CTL = flowstates[2];
|
||||
FLOWEQ1CTL = flowstates[3];
|
||||
FLOWHOLDOFF = flowstates[4];
|
||||
FLOWSTB = flowstates[5];
|
||||
FLOWSTBEDGE = flowstates[6];
|
||||
FLOWSTBHPERIOD = flowstates[7];
|
||||
}
|
|
@ -0,0 +1,674 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
/****************************************************************************
|
||||
File : jtag.c *
|
||||
Contents : Jtag handling functions code for NanoXplore *
|
||||
USB-JTAG ANGIE adapter hardware. *
|
||||
Based on openULINK project code by: Martin Schmoelzer. *
|
||||
Copyright 2023, Ahmed Errached BOUDJELIDA, NanoXplore SAS. *
|
||||
<aboudjelida@nanoxplore.com> *
|
||||
<ahmederrachedbjld@gmail.com> *
|
||||
*****************************************************************************/
|
||||
|
||||
#include "jtag.h"
|
||||
#include "io.h"
|
||||
#include "msgtypes.h"
|
||||
#include "reg_ezusb.h"
|
||||
#include <stdbool.h>
|
||||
#include <serial.h>
|
||||
#include <stdio.h>
|
||||
|
||||
/** Delay value for SCAN_IN operations with less than maximum TCK frequency */
|
||||
uint8_t delay_scan_in;
|
||||
|
||||
/** Delay value for SCAN_OUT operations with less than maximum TCK frequency */
|
||||
uint8_t delay_scan_out;
|
||||
|
||||
/** Delay value for SCAN_IO operations with less than maximum TCK frequency */
|
||||
uint8_t delay_scan_io;
|
||||
|
||||
/** Delay value for CLOCK_TCK operations with less than maximum frequency */
|
||||
uint8_t delay_tck;
|
||||
|
||||
/** Delay value for CLOCK_TMS operations with less than maximum frequency */
|
||||
uint8_t delay_tms;
|
||||
|
||||
/**
|
||||
* Perform JTAG SCAN-IN operation at maximum TCK frequency.
|
||||
*
|
||||
* Dummy data is shifted into the JTAG chain via TDI, TDO data is sampled and
|
||||
* stored in the EP2 IN buffer.
|
||||
*
|
||||
* Maximum achievable TCK frequency is 182 kHz for ANGIE clocked at 24 MHz.
|
||||
*
|
||||
* @param out_offset offset in EP1OUTBUF where payload data starts
|
||||
* @param in_offset
|
||||
*/
|
||||
void jtag_scan_in(uint8_t out_offset, uint8_t in_offset)
|
||||
{
|
||||
uint8_t scan_size_bytes, bits_last_byte;
|
||||
uint8_t tms_count_start, tms_count_end;
|
||||
uint8_t tms_sequence_start, tms_sequence_end;
|
||||
uint8_t tdo_data, i, j;
|
||||
|
||||
uint8_t outb_buffer;
|
||||
|
||||
/* Get parameters from EP1OUTBUF */
|
||||
scan_size_bytes = EP1OUTBUF[out_offset];
|
||||
bits_last_byte = EP1OUTBUF[out_offset + 1];
|
||||
tms_count_start = (EP1OUTBUF[out_offset + 2] >> 4) & 0x0F;
|
||||
tms_count_end = EP1OUTBUF[out_offset + 2] & 0x0F;
|
||||
tms_sequence_start = EP1OUTBUF[out_offset + 3];
|
||||
tms_sequence_end = EP1OUTBUF[out_offset + 4];
|
||||
|
||||
if (tms_count_start > 0)
|
||||
jtag_clock_tms(tms_count_start, tms_sequence_start);
|
||||
|
||||
outb_buffer = IOB & ~(bmbit1 | bmbit2 | bmbit3);
|
||||
|
||||
/* Shift all bytes except the last byte */
|
||||
for (i = 0; i < scan_size_bytes - 1; i++) {
|
||||
tdo_data = 0;
|
||||
|
||||
for (j = 0; j < 8; j++) {
|
||||
IOB = outb_buffer; /* TCK changes here */
|
||||
tdo_data = tdo_data >> 1;
|
||||
IOB = (outb_buffer | bmbit2);
|
||||
|
||||
if (PIN_TDO)
|
||||
tdo_data |= 0x80;
|
||||
}
|
||||
|
||||
/* Copy TDO data to EP1INBUF */
|
||||
EP1INBUF[i + in_offset] = tdo_data;
|
||||
}
|
||||
tdo_data = 0;
|
||||
|
||||
/* Shift the last byte */
|
||||
for (j = 0; j < bits_last_byte; j++) {
|
||||
/* Assert TMS signal if requested and this is the last bit */
|
||||
if (j == (bits_last_byte - 1) && tms_count_end > 0) {
|
||||
outb_buffer |= bmbit1;
|
||||
tms_count_end--;
|
||||
tms_sequence_end = tms_sequence_end >> 1;
|
||||
}
|
||||
|
||||
IOB = outb_buffer; /* TCK changes here */
|
||||
tdo_data = tdo_data >> 1;
|
||||
IOB = (outb_buffer | bmbit2);
|
||||
|
||||
if (PIN_TDO)
|
||||
tdo_data |= 0x80;
|
||||
}
|
||||
tdo_data = tdo_data >> (8 - bits_last_byte);
|
||||
|
||||
/* Copy TDO data to EP1INBUF */
|
||||
EP1INBUF[i + in_offset] = tdo_data;
|
||||
|
||||
/* Move to correct end state */
|
||||
if (tms_count_end > 0)
|
||||
jtag_clock_tms(tms_count_end, tms_sequence_end);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Perform JTAG SCAN-IN operation at variable TCK frequency.
|
||||
*
|
||||
* Dummy data is shifted into the JTAG chain via TDI, TDO data is sampled and
|
||||
* stored in the EP2 IN buffer.
|
||||
*
|
||||
* Maximum achievable TCK frequency is 113 kHz for ANGIE clocked at 24 MHz.
|
||||
*
|
||||
* @param out_offset offset in EP1OUTBUF where payload data starts
|
||||
* @param in_offset
|
||||
*/
|
||||
void jtag_slow_scan_in(uint8_t out_offset, uint8_t in_offset)
|
||||
{
|
||||
uint8_t scan_size_bytes, bits_last_byte;
|
||||
uint8_t tms_count_start, tms_count_end;
|
||||
uint8_t tms_sequence_start, tms_sequence_end;
|
||||
uint8_t tdo_data, i, j, k;
|
||||
uint8_t outb_buffer;
|
||||
|
||||
/* Get parameters from EP1OUTBUF */
|
||||
scan_size_bytes = EP1OUTBUF[out_offset];
|
||||
bits_last_byte = EP1OUTBUF[out_offset + 1];
|
||||
tms_count_start = (EP1OUTBUF[out_offset + 2] >> 4) & 0x0F;
|
||||
tms_count_end = EP1OUTBUF[out_offset + 2] & 0x0F;
|
||||
tms_sequence_start = EP1OUTBUF[out_offset + 3];
|
||||
tms_sequence_end = EP1OUTBUF[out_offset + 4];
|
||||
|
||||
if (tms_count_start > 0)
|
||||
jtag_slow_clock_tms(tms_count_start, tms_sequence_start);
|
||||
|
||||
outb_buffer = IOB & ~(bmbit3 | bmbit2 | bmbit1);
|
||||
|
||||
/* Shift all bytes except the last byte */
|
||||
for (i = 0; i < scan_size_bytes - 1; i++) {
|
||||
tdo_data = 0;
|
||||
|
||||
for (j = 0; j < 8; j++) {
|
||||
IOB = outb_buffer; /* TCK changes here */
|
||||
for (k = 0; k < delay_scan_in; k++)
|
||||
;
|
||||
tdo_data = tdo_data >> 1;
|
||||
|
||||
IOB = (outb_buffer | bmbit2);
|
||||
for (k = 0; k < delay_scan_in; k++)
|
||||
;
|
||||
|
||||
if (PIN_TDO)
|
||||
tdo_data |= 0x80;
|
||||
}
|
||||
|
||||
/* Copy TDO data to EP1INBUF */
|
||||
EP1INBUF[i + in_offset] = tdo_data;
|
||||
}
|
||||
|
||||
tdo_data = 0;
|
||||
|
||||
/* Shift the last byte */
|
||||
for (j = 0; j < bits_last_byte; j++) {
|
||||
/* Assert TMS signal if requested and this is the last bit */
|
||||
if (j == (bits_last_byte - 1) && tms_count_end > 0) {
|
||||
outb_buffer |= bmbit1;
|
||||
tms_count_end--;
|
||||
tms_sequence_end = tms_sequence_end >> 1;
|
||||
}
|
||||
|
||||
IOB = outb_buffer; /* TCK changes here */
|
||||
for (k = 0; k < delay_scan_in; k++)
|
||||
;
|
||||
tdo_data = tdo_data >> 1;
|
||||
|
||||
IOB = (outb_buffer | bmbit2);
|
||||
for (k = 0; k < delay_scan_in; k++)
|
||||
;
|
||||
|
||||
if (PIN_TDO)
|
||||
tdo_data |= 0x80;
|
||||
}
|
||||
tdo_data = tdo_data >> (8 - bits_last_byte);
|
||||
|
||||
/* Copy TDO data to EP1INBUF */
|
||||
EP1INBUF[i + in_offset] = tdo_data;
|
||||
|
||||
/* Move to correct end state */
|
||||
if (tms_count_end > 0)
|
||||
jtag_slow_clock_tms(tms_count_end, tms_sequence_end);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Perform JTAG SCAN-OUT operation at maximum TCK frequency.
|
||||
*
|
||||
* Data stored in EP2 OUT buffer is shifted into the JTAG chain via TDI, TDO
|
||||
* data is not sampled.
|
||||
* The TAP-FSM state is always left in the PAUSE-DR/PAUSE-IR state.
|
||||
*
|
||||
* Maximum achievable TCK frequency is 142 kHz for ANGIE clocked at 24 MHz.
|
||||
*
|
||||
* @param out_offset offset in EP1OUTBUF where payload data starts
|
||||
*/
|
||||
void jtag_scan_out(uint8_t out_offset)
|
||||
{
|
||||
uint8_t scan_size_bytes, bits_last_byte;
|
||||
uint8_t tms_count_start, tms_count_end;
|
||||
uint8_t tms_sequence_start, tms_sequence_end;
|
||||
uint8_t tdi_data, i, j;
|
||||
uint8_t outb_buffer;
|
||||
|
||||
/* Get parameters from EP1OUTBUF */
|
||||
scan_size_bytes = EP1OUTBUF[out_offset];
|
||||
bits_last_byte = EP1OUTBUF[out_offset + 1];
|
||||
tms_count_start = (EP1OUTBUF[out_offset + 2] >> 4) & 0x0F;
|
||||
tms_count_end = EP1OUTBUF[out_offset + 2] & 0x0F;
|
||||
tms_sequence_start = EP1OUTBUF[out_offset + 3];
|
||||
tms_sequence_end = EP1OUTBUF[out_offset + 4];
|
||||
|
||||
if (tms_count_start > 0)
|
||||
jtag_clock_tms(tms_count_start, tms_sequence_start);
|
||||
outb_buffer = IOB & ~(bmbit2 | bmbit1);
|
||||
|
||||
/* Shift all bytes except the last byte */
|
||||
for (i = 0; i < scan_size_bytes - 1; i++) {
|
||||
tdi_data = EP1OUTBUF[i + out_offset + 5];
|
||||
|
||||
for (j = 0; j < 8; j++) {
|
||||
if (tdi_data & 0x01)
|
||||
outb_buffer |= bmbit3;
|
||||
else
|
||||
outb_buffer &= ~bmbit3;
|
||||
|
||||
IOB = outb_buffer; /* TDI and TCK change here */
|
||||
tdi_data = tdi_data >> 1;
|
||||
IOB = (outb_buffer | bmbit2);
|
||||
}
|
||||
}
|
||||
tdi_data = EP1OUTBUF[i + out_offset + 5];
|
||||
|
||||
/* Shift the last byte */
|
||||
for (j = 0; j < bits_last_byte; j++) {
|
||||
if (tdi_data & 0x01)
|
||||
outb_buffer |= bmbit3;
|
||||
else
|
||||
outb_buffer &= ~bmbit3;
|
||||
|
||||
/* Assert TMS signal if requested and this is the last bit */
|
||||
if (j == (bits_last_byte - 1) && tms_count_end > 0) {
|
||||
outb_buffer |= bmbit1;
|
||||
tms_count_end--;
|
||||
tms_sequence_end = tms_sequence_end >> 1;
|
||||
}
|
||||
IOB = outb_buffer; /* TDI and TCK change here */
|
||||
tdi_data = tdi_data >> 1;
|
||||
IOB = (outb_buffer | bmbit2);
|
||||
}
|
||||
|
||||
/* Move to correct end state */
|
||||
if (tms_count_end > 0)
|
||||
jtag_clock_tms(tms_count_end, tms_sequence_end);
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform JTAG SCAN-OUT operation at maximum TCK frequency.
|
||||
*
|
||||
* Data stored in EP2 OUT buffer is shifted into the JTAG chain via TDI, TDO
|
||||
* data is not sampled.
|
||||
* The TAP-FSM state is always left in the PAUSE-DR/PAUSE-IR state.
|
||||
*
|
||||
* Maximum achievable TCK frequency is 97 kHz for ANGIE clocked at 24 MHz.
|
||||
*
|
||||
* @param out_offset offset in EP1OUTBUF where payload data starts
|
||||
*/
|
||||
void jtag_slow_scan_out(uint8_t out_offset)
|
||||
{
|
||||
uint8_t scan_size_bytes, bits_last_byte;
|
||||
uint8_t tms_count_start, tms_count_end;
|
||||
uint8_t tms_sequence_start, tms_sequence_end;
|
||||
uint8_t tdi_data, i, j, k;
|
||||
uint8_t outb_buffer;
|
||||
|
||||
/* Get parameters from EP1OUTBUF */
|
||||
scan_size_bytes = EP1OUTBUF[out_offset];
|
||||
bits_last_byte = EP1OUTBUF[out_offset + 1];
|
||||
tms_count_start = (EP1OUTBUF[out_offset + 2] >> 4) & 0x0F;
|
||||
tms_count_end = EP1OUTBUF[out_offset + 2] & 0x0F;
|
||||
tms_sequence_start = EP1OUTBUF[out_offset + 3];
|
||||
tms_sequence_end = EP1OUTBUF[out_offset + 4];
|
||||
|
||||
if (tms_count_start > 0)
|
||||
jtag_slow_clock_tms(tms_count_start, tms_sequence_start);
|
||||
outb_buffer = IOB & ~(bmbit2 | bmbit1);
|
||||
|
||||
/* Shift all bytes except the last byte */
|
||||
for (i = 0; i < scan_size_bytes - 1; i++) {
|
||||
tdi_data = EP1OUTBUF[i + out_offset + 5];
|
||||
|
||||
for (j = 0; j < 8; j++) {
|
||||
if (tdi_data & 0x01)
|
||||
outb_buffer |= bmbit3;
|
||||
else
|
||||
outb_buffer &= ~bmbit3;
|
||||
IOB = outb_buffer; /* TDI and TCK change here */
|
||||
for (k = 0; k < delay_scan_out; k++)
|
||||
;
|
||||
tdi_data = tdi_data >> 1;
|
||||
IOB = (outb_buffer | bmbit2);
|
||||
for (k = 0; k < delay_scan_out; k++)
|
||||
;
|
||||
}
|
||||
}
|
||||
tdi_data = EP1OUTBUF[i + out_offset + 5];
|
||||
|
||||
/* Shift the last byte */
|
||||
for (j = 0; j < bits_last_byte; j++) {
|
||||
if (tdi_data & 0x01)
|
||||
outb_buffer |= bmbit3;
|
||||
else
|
||||
outb_buffer &= ~bmbit3;
|
||||
|
||||
/* Assert TMS signal if requested and this is the last bit */
|
||||
if (j == (bits_last_byte - 1) && tms_count_end > 0) {
|
||||
outb_buffer |= bmbit1;
|
||||
tms_count_end--;
|
||||
tms_sequence_end = tms_sequence_end >> 1;
|
||||
}
|
||||
IOB = outb_buffer; /* TDI and TCK change here */
|
||||
for (k = 0; k < delay_scan_out; k++)
|
||||
;
|
||||
tdi_data = tdi_data >> 1;
|
||||
IOB = (outb_buffer | bmbit2);
|
||||
for (k = 0; k < delay_scan_out; k++)
|
||||
;
|
||||
}
|
||||
|
||||
/* Move to correct end state */
|
||||
if (tms_count_end > 0)
|
||||
jtag_slow_clock_tms(tms_count_end, tms_sequence_end);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Perform bidirectional JTAG SCAN operation at maximum TCK frequency.
|
||||
*
|
||||
* Data stored in EP2 OUT buffer is shifted into the JTAG chain via TDI, TDO
|
||||
* data is sampled and stored in the EP2 IN buffer.
|
||||
* The TAP-FSM state is always left in the PAUSE-DR/PAUSE-IR state.
|
||||
*
|
||||
* Maximum achievable TCK frequency is 100 kHz for ANGIE clocked at 24 MHz.
|
||||
*
|
||||
* @param out_offset offset in EP1OUTBUF where payload data starts
|
||||
* @param in_offset
|
||||
*/
|
||||
int it;
|
||||
void jtag_scan_io(uint8_t out_offset, uint8_t in_offset)
|
||||
{
|
||||
uint8_t scan_size_bytes, bits_last_byte;
|
||||
uint8_t tms_count_start, tms_count_end;
|
||||
uint8_t tms_sequence_start, tms_sequence_end;
|
||||
uint8_t tdi_data, tdo_data, i, j;
|
||||
uint8_t outb_buffer;
|
||||
|
||||
it++;
|
||||
/* Get parameters from EP1OUTBUF */
|
||||
scan_size_bytes = EP1OUTBUF[out_offset];
|
||||
bits_last_byte = EP1OUTBUF[out_offset + 1];
|
||||
tms_count_start = (EP1OUTBUF[out_offset + 2] >> 4) & 0x0F;
|
||||
tms_count_end = EP1OUTBUF[out_offset + 2] & 0x0F;
|
||||
tms_sequence_start = EP1OUTBUF[out_offset + 3];
|
||||
tms_sequence_end = EP1OUTBUF[out_offset + 4];
|
||||
|
||||
if (tms_count_start > 0)
|
||||
jtag_clock_tms(tms_count_start, tms_sequence_start);
|
||||
outb_buffer = IOB & ~(bmbit2 | bmbit1);
|
||||
|
||||
/* Shift all bytes except the last byte */
|
||||
for (i = 0; i < scan_size_bytes - 1; i++) {
|
||||
tdi_data = EP1OUTBUF[i + out_offset + 5];
|
||||
tdo_data = 0;
|
||||
for (j = 0; j < 8; j++) {
|
||||
if (tdi_data & 0x01)
|
||||
outb_buffer |= bmbit3;
|
||||
else
|
||||
outb_buffer &= ~bmbit3;
|
||||
IOB = outb_buffer; /* TDI and TCK change here */
|
||||
tdi_data = tdi_data >> 1;
|
||||
IOB = (outb_buffer | bmbit2);
|
||||
tdo_data = tdo_data >> 1;
|
||||
if (PIN_TDO)
|
||||
tdo_data |= 0x80;
|
||||
}
|
||||
|
||||
/* Copy TDO data to EP1INBUF */
|
||||
EP1INBUF[i + in_offset] = tdo_data;
|
||||
}
|
||||
tdi_data = EP1OUTBUF[i + out_offset + 5];
|
||||
tdo_data = 0;
|
||||
|
||||
/* Shift the last byte */
|
||||
for (j = 0; j < bits_last_byte; j++) {
|
||||
if (tdi_data & 0x01)
|
||||
outb_buffer |= bmbit3;
|
||||
else
|
||||
outb_buffer &= ~bmbit3;
|
||||
|
||||
/* Assert TMS signal if requested and this is the last bit */
|
||||
if (j == (bits_last_byte - 1) && tms_count_end > 0) {
|
||||
outb_buffer |= bmbit1;
|
||||
tms_count_end--;
|
||||
tms_sequence_end = tms_sequence_end >> 1;
|
||||
}
|
||||
IOB = outb_buffer; /* TDI and TCK change here */
|
||||
tdi_data = tdi_data >> 1;
|
||||
IOB = (outb_buffer | bmbit2);
|
||||
tdo_data = tdo_data >> 1;
|
||||
if (PIN_TDO)
|
||||
tdo_data |= 0x80;
|
||||
}
|
||||
tdo_data = tdo_data >> (8 - bits_last_byte);
|
||||
|
||||
/* Copy TDO data to EP1INBUF */
|
||||
EP1INBUF[i + in_offset] = tdo_data;
|
||||
|
||||
/* Move to correct end state */
|
||||
if (tms_count_end > 0)
|
||||
jtag_clock_tms(tms_count_end, tms_sequence_end);
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform bidirectional JTAG SCAN operation at maximum TCK frequency.
|
||||
*
|
||||
* Data stored in EP2 OUT buffer is shifted into the JTAG chain via TDI, TDO
|
||||
* data is sampled and stored in the EP2 IN buffer.
|
||||
* The TAP-FSM state is always left in the PAUSE-DR/PAUSE-IR state.
|
||||
*
|
||||
* Maximum achievable TCK frequency is 78 kHz for ANGIE clocked at 24 MHz.
|
||||
*
|
||||
* @param out_offset offset in EP1OUTBUF where payload data starts
|
||||
* @param in_offset
|
||||
*/
|
||||
void jtag_slow_scan_io(uint8_t out_offset, uint8_t in_offset)
|
||||
{
|
||||
uint8_t scan_size_bytes, bits_last_byte;
|
||||
uint8_t tms_count_start, tms_count_end;
|
||||
uint8_t tms_sequence_start, tms_sequence_end;
|
||||
uint8_t tdi_data, tdo_data, i, j, k;
|
||||
uint8_t outb_buffer;
|
||||
|
||||
/* Get parameters from EP1OUTBUF */
|
||||
scan_size_bytes = EP1OUTBUF[out_offset];
|
||||
bits_last_byte = EP1OUTBUF[out_offset + 1];
|
||||
tms_count_start = (EP1OUTBUF[out_offset + 2] >> 4) & 0x0F;
|
||||
tms_count_end = EP1OUTBUF[out_offset + 2] & 0x0F;
|
||||
tms_sequence_start = EP1OUTBUF[out_offset + 3];
|
||||
tms_sequence_end = EP1OUTBUF[out_offset + 4];
|
||||
|
||||
if (tms_count_start > 0)
|
||||
jtag_slow_clock_tms(tms_count_start, tms_sequence_start);
|
||||
outb_buffer = IOB & ~(bmbit2 | bmbit1);
|
||||
|
||||
/* Shift all bytes except the last byte */
|
||||
for (i = 0; i < scan_size_bytes - 1; i++) {
|
||||
tdi_data = EP1OUTBUF[i + out_offset + 5];
|
||||
tdo_data = 0;
|
||||
for (j = 0; j < 8; j++) {
|
||||
if (tdi_data & 0x01)
|
||||
outb_buffer |= bmbit3;
|
||||
else
|
||||
outb_buffer &= ~bmbit3;
|
||||
IOB = outb_buffer; /* TDI and TCK change here */
|
||||
for (k = 0; k < delay_scan_io; k++)
|
||||
;
|
||||
tdi_data = tdi_data >> 1;
|
||||
IOB = (outb_buffer | bmbit2);
|
||||
for (k = 0; k < delay_scan_io; k++)
|
||||
;
|
||||
tdo_data = tdo_data >> 1;
|
||||
if (PIN_TDO)
|
||||
tdo_data |= 0x80;
|
||||
}
|
||||
|
||||
/* Copy TDO data to EP1INBUF */
|
||||
EP1INBUF[i + in_offset] = tdo_data;
|
||||
}
|
||||
tdi_data = EP1OUTBUF[i + out_offset + 5];
|
||||
tdo_data = 0;
|
||||
|
||||
/* Shift the last byte */
|
||||
for (j = 0; j < bits_last_byte; j++) {
|
||||
if (tdi_data & 0x01)
|
||||
outb_buffer |= bmbit3;
|
||||
else
|
||||
outb_buffer &= ~bmbit3;
|
||||
|
||||
/* Assert TMS signal if requested and this is the last bit */
|
||||
if (j == (bits_last_byte - 1) && tms_count_end > 0) {
|
||||
outb_buffer |= bmbit1;
|
||||
tms_count_end--;
|
||||
tms_sequence_end = tms_sequence_end >> 1;
|
||||
}
|
||||
IOB = outb_buffer; /* TDI and TCK change here */
|
||||
for (k = 0; k < delay_scan_io; k++)
|
||||
;
|
||||
tdi_data = tdi_data >> 1;
|
||||
IOB = (outb_buffer | bmbit2);
|
||||
for (k = 0; k < delay_scan_io; k++)
|
||||
;
|
||||
tdo_data = tdo_data >> 1;
|
||||
if (PIN_TDO)
|
||||
tdo_data |= 0x80;
|
||||
}
|
||||
tdo_data = tdo_data >> (8 - bits_last_byte);
|
||||
|
||||
/* Copy TDO data to EP1INBUF */
|
||||
EP1INBUF[i + in_offset] = tdo_data;
|
||||
|
||||
/* Move to correct end state */
|
||||
if (tms_count_end > 0)
|
||||
jtag_slow_clock_tms(tms_count_end, tms_sequence_end);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate TCK clock cycles.
|
||||
*
|
||||
* Maximum achievable TCK frequency is 375 kHz for ANGIE clocked at 24 MHz.
|
||||
*
|
||||
* @param count number of TCK clock cycles to generate.
|
||||
*/
|
||||
void jtag_clock_tck(uint16_t count)
|
||||
{
|
||||
uint16_t i;
|
||||
uint8_t outb_buffer = IOB & ~(bmbit2);
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
IOB = outb_buffer;
|
||||
IOB = outb_buffer | bmbit2;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate TCK clock cycles at variable frequency.
|
||||
*
|
||||
* Maximum achievable TCK frequency is 166.6 kHz for ANGIE clocked at 24 MHz.
|
||||
*
|
||||
* @param count number of TCK clock cycles to generate.
|
||||
*/
|
||||
void jtag_slow_clock_tck(uint16_t count)
|
||||
{
|
||||
uint16_t i;
|
||||
uint8_t j;
|
||||
uint8_t outb_buffer = IOB & ~(bmbit2);
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
IOB = outb_buffer;
|
||||
for (j = 0; j < delay_tck; j++)
|
||||
;
|
||||
IOB = outb_buffer | bmbit2;
|
||||
for (j = 0; j < delay_tck; j++)
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform TAP FSM state transitions at maximum TCK frequency.
|
||||
*
|
||||
* Maximum achievable TCK frequency is 176 kHz for ANGIE clocked at 24 MHz.
|
||||
*
|
||||
* @param count the number of state transitions to perform.
|
||||
* @param sequence the TMS pin levels for each state transition, starting with
|
||||
* the least-significant bit.
|
||||
*/
|
||||
void jtag_clock_tms(uint8_t count, uint8_t sequence)
|
||||
{
|
||||
uint8_t outb_buffer = IOB & ~(bmbit2);
|
||||
uint8_t i;
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
/* Set TMS pin according to sequence parameter */
|
||||
if (sequence & 0x1)
|
||||
outb_buffer |= bmbit1;
|
||||
else
|
||||
outb_buffer &= ~bmbit1;
|
||||
IOB = outb_buffer;
|
||||
sequence = sequence >> 1;
|
||||
IOB = outb_buffer | bmbit2;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform TAP-FSM state transitions at less than maximum TCK frequency.
|
||||
*
|
||||
* Maximum achievable TCK frequency is 117 kHz for ANGIE clocked at 24 MHz.
|
||||
*
|
||||
* @param count the number of state transitions to perform.
|
||||
* @param sequence the TMS pin levels for each state transition, starting with
|
||||
* the least-significant bit.
|
||||
*/
|
||||
void jtag_slow_clock_tms(uint8_t count, uint8_t sequence)
|
||||
{
|
||||
uint8_t outb_buffer = IOB & ~(bmbit2);
|
||||
uint8_t i, j;
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
/* Set TMS pin according to sequence parameter */
|
||||
if (sequence & 0x1)
|
||||
outb_buffer |= bmbit1;
|
||||
else
|
||||
outb_buffer &= ~bmbit1;
|
||||
IOB = outb_buffer;
|
||||
for (j = 0; j < delay_tms; j++)
|
||||
;
|
||||
sequence = sequence >> 1;
|
||||
IOB = outb_buffer | bmbit2;
|
||||
for (j = 0; j < delay_tms; j++)
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
uint16_t jtag_get_signals(void)
|
||||
{
|
||||
uint8_t input_signal_state, output_signal_state;
|
||||
input_signal_state = 0;
|
||||
output_signal_state = 0;
|
||||
|
||||
/* Get states of input pins */
|
||||
if (PIN_TDO)
|
||||
input_signal_state |= SIGNAL_TDO;
|
||||
|
||||
/* Get states of output pins */
|
||||
output_signal_state = IOB & MASK_PORTB_DIRECTION_OUT;
|
||||
|
||||
return ((uint16_t)input_signal_state << 8) | ((uint16_t)output_signal_state);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set state of JTAG output signals.
|
||||
*
|
||||
* @param low signals which should be de-asserted.
|
||||
* @param high signals which should be asserted.
|
||||
*/
|
||||
void jtag_set_signals(uint8_t low, uint8_t high)
|
||||
{
|
||||
IOB &= ~(low & MASK_PORTB_DIRECTION_OUT);
|
||||
IOB |= (high & MASK_PORTB_DIRECTION_OUT);
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure TCK delay parameters.
|
||||
*
|
||||
* @param scan_in number of delay cycles in scan_in operations.
|
||||
* @param scan_out number of delay cycles in scan_out operations.
|
||||
* @param scan_io number of delay cycles in scan_io operations.
|
||||
* @param tck number of delay cycles in clock_tck operations.
|
||||
* @param tms number of delay cycles in clock_tms operations.
|
||||
*/
|
||||
void jtag_configure_tck_delay(uint8_t scan_in, uint8_t scan_out,
|
||||
uint8_t scan_io, uint8_t tck, uint8_t tms)
|
||||
{
|
||||
delay_scan_in = scan_in;
|
||||
delay_scan_out = scan_out;
|
||||
delay_scan_io = scan_io;
|
||||
delay_tck = tck;
|
||||
delay_tms = tms;
|
||||
}
|
|
@ -0,0 +1,85 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
/****************************************************************************
|
||||
File : main.c *
|
||||
Contents : main code for NanoXplore USB-JTAG ANGIE adapter *
|
||||
hardware. *
|
||||
Based on openULINK project code by: Martin Schmoelzer. *
|
||||
Copyright 2023, Ahmed Errached BOUDJELIDA, NanoXplore SAS. *
|
||||
<aboudjelida@nanoxplore.com> *
|
||||
<ahmederrachedbjld@gmail.com> *
|
||||
*****************************************************************************/
|
||||
|
||||
#include "usb.h"
|
||||
#include "delay.h"
|
||||
#include "protocol.h"
|
||||
#include "reg_ezusb.h"
|
||||
#include <serial.h>
|
||||
#include <stdio.h>
|
||||
|
||||
extern void sudav_isr(void)__interrupt SUDAV_ISR;
|
||||
extern void sof_isr(void)__interrupt;
|
||||
extern void sutok_isr(void)__interrupt;
|
||||
extern void suspend_isr(void)__interrupt;
|
||||
extern void usbreset_isr(void)__interrupt;
|
||||
extern void highspeed_isr(void)__interrupt;
|
||||
extern void ep0ack_isr(void)__interrupt;
|
||||
extern void stub_isr(void)__interrupt;
|
||||
extern void ep0in_isr(void)__interrupt;
|
||||
extern void ep0out_isr(void)__interrupt;
|
||||
extern void ep1in_isr(void)__interrupt;
|
||||
extern void ep1out_isr(void)__interrupt;
|
||||
extern void ep2_isr(void)__interrupt;
|
||||
extern void ep4_isr(void)__interrupt;
|
||||
extern void ep6_isr(void)__interrupt;
|
||||
extern void ep8_isr(void)__interrupt;
|
||||
extern void ibn_isr(void)__interrupt;
|
||||
extern void ep0pingnak_isr(void)__interrupt;
|
||||
extern void ep1pingnak_isr(void)__interrupt;
|
||||
extern void ep2pingnak_isr(void)__interrupt;
|
||||
extern void ep4pingnak_isr(void)__interrupt;
|
||||
extern void ep6pingnak_isr(void)__interrupt;
|
||||
extern void ep8pingnak_isr(void)__interrupt;
|
||||
extern void errorlimit_isr(void)__interrupt;
|
||||
extern void ep2piderror_isr(void)__interrupt;
|
||||
extern void ep4piderror_isr(void)__interrupt;
|
||||
extern void ep6piderror_isr(void)__interrupt;
|
||||
extern void ep8piderror_isr(void)__interrupt;
|
||||
extern void ep2pflag_isr(void)__interrupt;
|
||||
extern void ep4pflag_isr(void)__interrupt;
|
||||
extern void ep6pflag_isr(void)__interrupt;
|
||||
extern void ep8pflag_isr(void)__interrupt;
|
||||
extern void ep2eflag_isr(void)__interrupt;
|
||||
extern void ep4eflag_isr(void)__interrupt;
|
||||
extern void ep6eflag_isr(void)__interrupt;
|
||||
extern void ep8eflag_isr(void)__interrupt;
|
||||
extern void ep2fflag_isr(void)__interrupt;
|
||||
extern void ep4fflag_isr(void)__interrupt;
|
||||
extern void ep6fflag_isr(void)__interrupt;
|
||||
extern void ep8fflag_isr(void)__interrupt;
|
||||
extern void gpifcomplete_isr(void)__interrupt;
|
||||
extern void gpifwaveform_isr(void)__interrupt;
|
||||
|
||||
void gpif_init(void);
|
||||
|
||||
int main(void)
|
||||
{
|
||||
CPUCS = ((CPUCS & ~bmclkspd) | (CLK_48M << 3) | CLKOE); /* required for sio0_init */
|
||||
sio0_init(57600); /* needed for printf */
|
||||
|
||||
ep_init();
|
||||
gpif_init();
|
||||
interrupt_init();
|
||||
io_init();
|
||||
|
||||
/* Perform ReNumeration */
|
||||
USBCS |= (DISCON | RENUM);
|
||||
delay_ms(250);
|
||||
USBCS &= ~DISCON;
|
||||
|
||||
/* Begin executing command(s). This function never returns. */
|
||||
command_loop();
|
||||
|
||||
/* Never reached, but SDCC complains about missing return statement */
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,189 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
/****************************************************************************
|
||||
File : protocol.c *
|
||||
Contents : Jtag commands handling protocol code for NanoXplore *
|
||||
USB-JTAG ANGIE adapter hardware. *
|
||||
Based on openULINK project code by: Martin Schmoelzer. *
|
||||
Copyright 2023, Ahmed Errached BOUDJELIDA, NanoXplore SAS. *
|
||||
<aboudjelida@nanoxplore.com> *
|
||||
<ahmederrachedbjld@gmail.com> *
|
||||
*****************************************************************************/
|
||||
|
||||
#include "usb.h"
|
||||
#include "protocol.h"
|
||||
#include "jtag.h"
|
||||
#include "delay.h"
|
||||
#include "io.h"
|
||||
#include "msgtypes.h"
|
||||
#include "reg_ezusb.h"
|
||||
#include <serial.h>
|
||||
#include <stdio.h>
|
||||
|
||||
/** Index in EP1 Bulk-OUT data buffer that contains the current command ID */
|
||||
volatile uint8_t cmd_id_index;
|
||||
|
||||
/** Number of data bytes already in EP1 Bulk-IN buffer */
|
||||
volatile uint8_t payload_index_in;
|
||||
|
||||
/**
|
||||
* Executes one command and updates global command indexes.
|
||||
*
|
||||
* @return true if this command was the last command.
|
||||
* @return false if there are more commands within the current contents of the
|
||||
* Bulk EP1-OUT data buffer.
|
||||
*/
|
||||
bool execute_command(void)
|
||||
{
|
||||
uint8_t usb_out_bytecount, usb_in_bytecount;
|
||||
uint16_t signal_state = 0;
|
||||
uint16_t count;
|
||||
|
||||
/* Most commands do not transfer IN data. To save code space, we write 0 to
|
||||
* usb_in_bytecount here, then modify it in the switch statement below where
|
||||
* necessary */
|
||||
usb_in_bytecount = 0;
|
||||
|
||||
switch (EP1OUTBUF[cmd_id_index] /* Command ID */) {
|
||||
case CMD_SCAN_IN:
|
||||
usb_out_bytecount = 5;
|
||||
usb_in_bytecount = EP1OUTBUF[cmd_id_index + 1];
|
||||
jtag_scan_in((cmd_id_index + 1), payload_index_in);
|
||||
break;
|
||||
case CMD_SCAN_OUT:
|
||||
usb_out_bytecount = EP1OUTBUF[cmd_id_index + 1] + 5;
|
||||
jtag_scan_out(cmd_id_index + 1);
|
||||
break;
|
||||
case CMD_SCAN_IO:
|
||||
usb_in_bytecount = EP1OUTBUF[cmd_id_index + 1];
|
||||
usb_out_bytecount = usb_in_bytecount + 5;
|
||||
jtag_scan_io((cmd_id_index + 1), payload_index_in);
|
||||
break;
|
||||
case CMD_CLOCK_TMS:
|
||||
usb_out_bytecount = 2;
|
||||
jtag_clock_tms(EP1OUTBUF[cmd_id_index + 1], EP1OUTBUF[cmd_id_index + 2]);
|
||||
break;
|
||||
case CMD_CLOCK_TCK:
|
||||
usb_out_bytecount = 2;
|
||||
count = (uint16_t)EP1OUTBUF[cmd_id_index + 1];
|
||||
count |= ((uint16_t)EP1OUTBUF[cmd_id_index + 2]) << 8;
|
||||
jtag_clock_tck(count);
|
||||
break;
|
||||
case CMD_SLOW_SCAN_IN:
|
||||
usb_out_bytecount = 5;
|
||||
usb_in_bytecount = EP1OUTBUF[cmd_id_index + 1];
|
||||
jtag_slow_scan_in(cmd_id_index + 1, payload_index_in);
|
||||
break;
|
||||
case CMD_SLOW_SCAN_OUT:
|
||||
usb_out_bytecount = EP1OUTBUF[cmd_id_index + 1] + 5;
|
||||
jtag_slow_scan_out(cmd_id_index + 1);
|
||||
break;
|
||||
case CMD_SLOW_SCAN_IO:
|
||||
usb_in_bytecount = EP1OUTBUF[cmd_id_index + 1];
|
||||
usb_out_bytecount = usb_in_bytecount + 5;
|
||||
jtag_slow_scan_io(cmd_id_index + 1, payload_index_in);
|
||||
break;
|
||||
case CMD_SLOW_CLOCK_TMS:
|
||||
usb_out_bytecount = 2;
|
||||
jtag_slow_clock_tms(EP1OUTBUF[cmd_id_index + 1], EP1OUTBUF[cmd_id_index + 2]);
|
||||
break;
|
||||
case CMD_SLOW_CLOCK_TCK:
|
||||
usb_out_bytecount = 2;
|
||||
count = (uint16_t)EP1OUTBUF[cmd_id_index + 1];
|
||||
count |= ((uint16_t)EP1OUTBUF[cmd_id_index + 2]) << 8;
|
||||
jtag_slow_clock_tck(count);
|
||||
break;
|
||||
case CMD_SLEEP_US:
|
||||
usb_out_bytecount = 2;
|
||||
count = (uint16_t)EP1OUTBUF[cmd_id_index + 1];
|
||||
count |= ((uint16_t)EP1OUTBUF[cmd_id_index + 2]) << 8;
|
||||
delay_us(count);
|
||||
break;
|
||||
case CMD_SLEEP_MS:
|
||||
usb_out_bytecount = 2;
|
||||
count = (uint16_t)EP1OUTBUF[cmd_id_index + 1];
|
||||
count |= ((uint16_t)EP1OUTBUF[cmd_id_index + 2]) << 8;
|
||||
delay_ms(count);
|
||||
break;
|
||||
case CMD_GET_SIGNALS:
|
||||
usb_out_bytecount = 0;
|
||||
usb_in_bytecount = 2;
|
||||
signal_state = jtag_get_signals();
|
||||
EP1INBUF[payload_index_in] = (signal_state >> 8);
|
||||
EP1INBUF[payload_index_in + 1] = (signal_state & 0xFF);
|
||||
break;
|
||||
case CMD_SET_SIGNALS:
|
||||
usb_out_bytecount = 2;
|
||||
jtag_set_signals(EP1OUTBUF[cmd_id_index + 1], EP1OUTBUF[cmd_id_index + 2]);
|
||||
break;
|
||||
case CMD_CONFIGURE_TCK_FREQ:
|
||||
usb_out_bytecount = 5;
|
||||
jtag_configure_tck_delay(EP1OUTBUF[cmd_id_index + 1], /* scan_in */
|
||||
EP1OUTBUF[cmd_id_index + 2], /* scan_out */
|
||||
EP1OUTBUF[cmd_id_index + 3], /* scan_io */
|
||||
EP1OUTBUF[cmd_id_index + 4], /* clock_tck */
|
||||
EP1OUTBUF[cmd_id_index + 5]); /* clock_tms */
|
||||
break;
|
||||
case CMD_TEST:
|
||||
usb_out_bytecount = 1;
|
||||
/* Do nothing... This command is only used to test if the device is ready
|
||||
* to accept new commands */
|
||||
break;
|
||||
default:
|
||||
/* Should never be reached */
|
||||
usb_out_bytecount = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Update EP1 Bulk-IN data byte count */
|
||||
payload_index_in += usb_in_bytecount;
|
||||
|
||||
/* Determine if this was the last command */
|
||||
if ((cmd_id_index + usb_out_bytecount + 1) >= EP1OUTBC) {
|
||||
return true;
|
||||
/* Line between return and else required by checkpatch: */
|
||||
uint8_t a = 0;
|
||||
} else {
|
||||
/* Not the last command, update cmd_id_index */
|
||||
cmd_id_index += (usb_out_bytecount + 1);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Forever wait for commands and execute them as they arrive.
|
||||
*/
|
||||
void command_loop(void)
|
||||
{
|
||||
bool last_command;
|
||||
while (1) {
|
||||
cmd_id_index = 0;
|
||||
payload_index_in = 0;
|
||||
|
||||
/* Wait until host sends EP1 Bulk-OUT packet */
|
||||
while (!ep1_out)
|
||||
;
|
||||
ep1_out = false;
|
||||
|
||||
/* Execute the commands */
|
||||
last_command = false;
|
||||
while (!last_command)
|
||||
last_command = execute_command();
|
||||
|
||||
/* Send back EP6 Bulk-IN packet if required */
|
||||
if (payload_index_in > 0) {
|
||||
EP1INBC = payload_index_in;
|
||||
syncdelay(3);
|
||||
|
||||
while (!ep1_in)
|
||||
;
|
||||
ep1_in = false;
|
||||
}
|
||||
|
||||
/* Re-arm EP1-OUT after command execution */
|
||||
EP1OUTBC = 0;
|
||||
syncdelay(3);
|
||||
EP1OUTBC = 0;
|
||||
syncdelay(3);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,77 @@
|
|||
// SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
|
||||
/*
|
||||
* This code was taken from the fx2lib project from this link:
|
||||
* https://github.com/djmuhlestein/fx2lib
|
||||
*
|
||||
* Copyright (C) 2009 Ubixum, Inc.
|
||||
*/
|
||||
|
||||
#include <reg_ezusb.h>
|
||||
#include <fx2macros.h>
|
||||
#include <serial.h>
|
||||
#include <stdint.h>
|
||||
/**
|
||||
* using the comp port implies that timer 2 will be used as
|
||||
* a baud rate generator. (Don't use timer 2)
|
||||
**/
|
||||
void sio0_init(uint32_t baud_rate) __critical
|
||||
{
|
||||
uint16_t hl; /* hl value for reload */
|
||||
uint8_t mult; /* multiplier for clock speed */
|
||||
uint32_t tmp; /* scratch for mult/divide */
|
||||
|
||||
mult = (CPUFREQ == CLK_12M) ? 1 : ((CPUFREQ == CLK_24M) ? 2 : 4);
|
||||
|
||||
/* set the clock rate */
|
||||
/* use clock 2 */
|
||||
RCLK = 1; TCLK = 1;
|
||||
tmp = mult * 375000L * 2;
|
||||
tmp /= baud_rate;
|
||||
tmp += 1;
|
||||
tmp /= 2;
|
||||
hl = 0xFFFF - (uint16_t)tmp;
|
||||
RCAP2H = (uint8_t)(((uint16_t)(hl) >> 8) & 0xff);
|
||||
|
||||
/* seems that the 24/48mhz calculations are always one less than suggested values */
|
||||
/* trm table 14-16 */
|
||||
RCAP2L = ((uint8_t)((uint16_t)(hl) & 0xff)) + (mult > 0 ? 1 : 0);
|
||||
|
||||
/* start the timer */
|
||||
TR2 = 1;
|
||||
|
||||
/* set up the serial port */
|
||||
SM0 = 0; SM1 = 1; /* serial mode 1 (asyncronous) */
|
||||
SM2 = 0 ; /* has to do with receiving */
|
||||
REN = 1 ; /* to enable receiving */
|
||||
PCON |= 0x80; /* SET SMOD0, baud rate doubler */
|
||||
TI = 1; /* we send initial byte */
|
||||
}
|
||||
|
||||
int getchar(void)
|
||||
{
|
||||
char c;
|
||||
while (!RI)
|
||||
;
|
||||
c = SBUF0;
|
||||
RI = 0;
|
||||
return c;
|
||||
}
|
||||
|
||||
void _transchar(char c)
|
||||
{
|
||||
while (!TI)
|
||||
; /* wait for TI=1 */
|
||||
TI = 0;
|
||||
SBUF0 = c;
|
||||
}
|
||||
|
||||
int putchar (char c)
|
||||
{
|
||||
if (c == '\n')
|
||||
_transchar('\r'); /* transmit \r\n */
|
||||
_transchar(c);
|
||||
if (c == '\r')
|
||||
_transchar('\n'); /* transmit \r\n */
|
||||
return c;
|
||||
}
|
|
@ -0,0 +1,784 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
/****************************************************************************
|
||||
File : usb.c *
|
||||
Contents : usb communication handling code for NanoXplore USB-JTAG *
|
||||
ANGIE adapter hardware. *
|
||||
Based on openULINK project code by: Martin Schmoelzer. *
|
||||
Copyright 2023, Ahmed Errached BOUDJELIDA, NanoXplore SAS. *
|
||||
<aboudjelida@nanoxplore.com> *
|
||||
<ahmederrachedbjld@gmail.com> *
|
||||
*****************************************************************************/
|
||||
|
||||
#include "usb.h"
|
||||
#include "stdint.h"
|
||||
#include "delay.h"
|
||||
#include "io.h"
|
||||
#include "reg_ezusb.h"
|
||||
#include <fx2macros.h>
|
||||
#include <serial.h>
|
||||
#include <stdio.h>
|
||||
|
||||
/* Also update external declarations in "include/usb.h" if making changes to
|
||||
* these variables!
|
||||
*/
|
||||
volatile bool ep1_out;
|
||||
volatile bool ep1_in;
|
||||
|
||||
volatile __xdata __at 0xE6B8 struct setup_data setup_data;
|
||||
|
||||
/* Define number of endpoints (except Control Endpoint 0) in a central place.
|
||||
* Be sure to include the necessary endpoint descriptors!
|
||||
*/
|
||||
#define NUM_ENDPOINTS 3
|
||||
|
||||
__code struct usb_device_descriptor device_descriptor = {
|
||||
.blength = sizeof(struct usb_device_descriptor),
|
||||
.bdescriptortype = DESCRIPTOR_TYPE_DEVICE,
|
||||
.bcdusb = 0x0200, /* BCD: 02.00 (Version 2.0 USB spec) */
|
||||
.bdeviceclass = 0xFF, /* 0xFF = vendor-specific */
|
||||
.bdevicesubclass = 0xFF,
|
||||
.bdeviceprotocol = 0xFF,
|
||||
.bmaxpacketsize0 = 64,
|
||||
.idvendor = 0x584e,
|
||||
.idproduct = 0x424e,
|
||||
.bcddevice = 0x0000,
|
||||
.imanufacturer = 1,
|
||||
.iproduct = 2,
|
||||
.iserialnumber = 3,
|
||||
.bnumconfigurations = 1
|
||||
};
|
||||
|
||||
/* WARNING: ALL config, interface and endpoint descriptors MUST be adjacent! */
|
||||
|
||||
__code struct usb_config_descriptor config_descriptor = {
|
||||
.blength = sizeof(struct usb_config_descriptor),
|
||||
.bdescriptortype = DESCRIPTOR_TYPE_CONFIGURATION,
|
||||
.wtotallength = sizeof(struct usb_config_descriptor) +
|
||||
sizeof(struct usb_interface_descriptor) +
|
||||
(NUM_ENDPOINTS * sizeof(struct usb_endpoint_descriptor)),
|
||||
.bnuminterfaces = 1,
|
||||
.bconfigurationvalue = 1,
|
||||
.iconfiguration = 4, /* String describing this configuration */
|
||||
.bmattributes = 0x80, /* Only MSB set according to USB spec */
|
||||
.maxpower = 50 /* 100 mA */
|
||||
};
|
||||
|
||||
__code struct usb_interface_descriptor interface_descriptor00 = {
|
||||
.blength = sizeof(struct usb_interface_descriptor),
|
||||
.bdescriptortype = DESCRIPTOR_TYPE_INTERFACE,
|
||||
.binterfacenumber = 0,
|
||||
.balternatesetting = 0,
|
||||
.bnumendpoints = NUM_ENDPOINTS,
|
||||
.binterfaceclass = 0xFF,
|
||||
.binterfacesubclass = 0xFF,
|
||||
.binterfaceprotocol = 0xFF,
|
||||
.iinterface = 0
|
||||
};
|
||||
|
||||
__code struct usb_endpoint_descriptor bulk_ep1_out_endpoint_descriptor = {
|
||||
.blength = sizeof(struct usb_endpoint_descriptor),
|
||||
.bdescriptortype = 0x05,
|
||||
.bendpointaddress = (1 | USB_DIR_OUT),
|
||||
.bmattributes = 0x02,
|
||||
.wmaxpacketsize = 64,
|
||||
.binterval = 0
|
||||
};
|
||||
|
||||
__code struct usb_endpoint_descriptor bulk_ep1_in_endpoint_descriptor = {
|
||||
.blength = sizeof(struct usb_endpoint_descriptor),
|
||||
.bdescriptortype = 0x05,
|
||||
.bendpointaddress = (1 | USB_DIR_IN),
|
||||
.bmattributes = 0x02,
|
||||
.wmaxpacketsize = 64,
|
||||
.binterval = 0
|
||||
};
|
||||
|
||||
__code struct usb_endpoint_descriptor bulk_ep2_endpoint_descriptor = {
|
||||
.blength = sizeof(struct usb_endpoint_descriptor),
|
||||
.bdescriptortype = 0x05,
|
||||
.bendpointaddress = (2 | USB_DIR_OUT),
|
||||
.bmattributes = 0x02,
|
||||
.wmaxpacketsize = 512,
|
||||
.binterval = 0
|
||||
};
|
||||
|
||||
__code struct usb_endpoint_descriptor bulk_ep4_endpoint_descriptor = {
|
||||
.blength = sizeof(struct usb_endpoint_descriptor),
|
||||
.bdescriptortype = 0x05,
|
||||
.bendpointaddress = (4 | USB_DIR_IN),
|
||||
.bmattributes = 0x02,
|
||||
.wmaxpacketsize = 512,
|
||||
.binterval = 0
|
||||
};
|
||||
|
||||
__code struct usb_endpoint_descriptor bulk_ep6_endpoint_descriptor = {
|
||||
.blength = sizeof(struct usb_endpoint_descriptor),
|
||||
.bdescriptortype = 0x05,
|
||||
.bendpointaddress = (6 | USB_DIR_OUT),
|
||||
.bmattributes = 0x02,
|
||||
.wmaxpacketsize = 512,
|
||||
.binterval = 0
|
||||
};
|
||||
|
||||
__code struct usb_endpoint_descriptor bulk_ep8_endpoint_descriptor = {
|
||||
.blength = sizeof(struct usb_endpoint_descriptor),
|
||||
.bdescriptortype = 0x05,
|
||||
.bendpointaddress = (8 | USB_DIR_OUT),
|
||||
.bmattributes = 0x02,
|
||||
.wmaxpacketsize = 512,
|
||||
.binterval = 0
|
||||
};
|
||||
|
||||
__code struct usb_language_descriptor language_descriptor = {
|
||||
.blength = 4,
|
||||
.bdescriptortype = DESCRIPTOR_TYPE_STRING,
|
||||
.wlangid = {0x0409 /* US English */}
|
||||
};
|
||||
|
||||
__code struct usb_string_descriptor strmanufacturer =
|
||||
STR_DESCR(16, 'N', 'a', 'n', 'o', 'X', 'p', 'l', 'o', 'r', 'e', ',', ' ', 'S', 'A', 'S', '.');
|
||||
|
||||
__code struct usb_string_descriptor strproduct =
|
||||
STR_DESCR(13, 'A', 'N', 'G', 'I', 'E', ' ', 'A', 'd', 'a', 'p', 't', 'e', 'r');
|
||||
|
||||
__code struct usb_string_descriptor strserialnumber =
|
||||
STR_DESCR(6, '0', '0', '0', '0', '0', '1');
|
||||
|
||||
__code struct usb_string_descriptor strconfigdescr =
|
||||
STR_DESCR(12, 'J', 'T', 'A', 'G', ' ', 'A', 'd', 'a', 'p', 't', 'e', 'r');
|
||||
|
||||
/* Table containing pointers to string descriptors */
|
||||
__code struct usb_string_descriptor *__code en_string_descriptors[4] = {
|
||||
&strmanufacturer,
|
||||
&strproduct,
|
||||
&strserialnumber,
|
||||
&strconfigdescr
|
||||
};
|
||||
void sudav_isr(void)__interrupt SUDAV_ISR
|
||||
{
|
||||
EXIF &= ~0x10; /* Clear USBINT: Main global interrupt */
|
||||
USBIRQ = SUDAVI;
|
||||
EP0CS |= HSNAK;
|
||||
usb_handle_setup_data();
|
||||
}
|
||||
void sof_isr(void)__interrupt SOF_ISR
|
||||
{
|
||||
}
|
||||
void sutok_isr(void)__interrupt SUTOK_ISR
|
||||
{
|
||||
}
|
||||
void suspend_isr(void)__interrupt SUSPEND_ISR
|
||||
{
|
||||
}
|
||||
void usbreset_isr(void)__interrupt USBRESET_ISR
|
||||
{
|
||||
}
|
||||
void highspeed_isr(void)__interrupt HIGHSPEED_ISR
|
||||
{
|
||||
}
|
||||
void ep0ack_isr(void)__interrupt EP0ACK_ISR
|
||||
{
|
||||
}
|
||||
void stub_isr(void)__interrupt STUB_ISR
|
||||
{
|
||||
}
|
||||
void ep0in_isr(void)__interrupt EP0IN_ISR
|
||||
{
|
||||
}
|
||||
void ep0out_isr(void)__interrupt EP0OUT_ISR
|
||||
{
|
||||
}
|
||||
void ep1in_isr(void)__interrupt EP1IN_ISR
|
||||
{
|
||||
ep1_in = true;
|
||||
|
||||
EXIF &= ~0x10; /* Clear USBINT: Main global interrupt */
|
||||
EPIRQ = 0x04; /* Clear individual EP1IN IRQ */
|
||||
}
|
||||
void ep1out_isr(void)__interrupt EP1OUT_ISR
|
||||
{
|
||||
ep1_out = true;
|
||||
|
||||
EXIF &= ~0x10; /* Clear USBINT: Main global interrupt */
|
||||
EPIRQ = 0x08; /* Clear individual EP1OUT IRQ */
|
||||
}
|
||||
void ep2_isr(void)__interrupt EP2_ISR
|
||||
{
|
||||
ep1_out = false; /* Does nothing but required by the compiler */
|
||||
}
|
||||
void ep4_isr(void)__interrupt EP4_ISR
|
||||
{
|
||||
}
|
||||
void ep6_isr(void)__interrupt EP6_ISR
|
||||
{
|
||||
}
|
||||
void ep8_isr(void)__interrupt EP8_ISR
|
||||
{
|
||||
}
|
||||
void ibn_isr(void)__interrupt IBN_ISR
|
||||
{
|
||||
}
|
||||
void ep0pingnak_isr(void)__interrupt EP0PINGNAK_ISR
|
||||
{
|
||||
}
|
||||
void ep1pingnak_isr(void)__interrupt EP1PINGNAK_ISR
|
||||
{
|
||||
}
|
||||
void ep2pingnak_isr(void)__interrupt EP2PINGNAK_ISR
|
||||
{
|
||||
}
|
||||
void ep4pingnak_isr(void)__interrupt EP4PINGNAK_ISR
|
||||
{
|
||||
}
|
||||
void ep6pingnak_isr(void)__interrupt EP6PINGNAK_ISR
|
||||
{
|
||||
}
|
||||
void ep8pingnak_isr(void)__interrupt EP8PINGNAK_ISR
|
||||
{
|
||||
}
|
||||
void errorlimit_isr(void)__interrupt ERRORLIMIT_ISR
|
||||
{
|
||||
}
|
||||
void ep2piderror_isr(void)__interrupt EP2PIDERROR_ISR
|
||||
{
|
||||
}
|
||||
void ep4piderror_isr(void)__interrupt EP4PIDERROR_ISR
|
||||
{
|
||||
}
|
||||
void ep6piderror_isr(void)__interrupt EP6PIDERROR_ISR
|
||||
{
|
||||
}
|
||||
void ep8piderror_isr(void)__interrupt EP8PIDERROR_ISR
|
||||
{
|
||||
}
|
||||
void ep2pflag_isr(void)__interrupt EP2PFLAG_ISR
|
||||
{
|
||||
}
|
||||
void ep4pflag_isr(void)__interrupt EP4PFLAG_ISR
|
||||
{
|
||||
}
|
||||
void ep6pflag_isr(void)__interrupt EP6PFLAG_ISR
|
||||
{
|
||||
}
|
||||
void ep8pflag_isr(void)__interrupt EP8PFLAG_ISR
|
||||
{
|
||||
}
|
||||
void ep2eflag_isr(void)__interrupt EP2EFLAG_ISR
|
||||
{
|
||||
}
|
||||
void ep4eflag_isr(void)__interrupt EP4EFLAG_ISR
|
||||
{
|
||||
}
|
||||
void ep6eflag_isr(void)__interrupt EP6EFLAG_ISR
|
||||
{
|
||||
}
|
||||
void ep8eflag_isr(void)__interrupt EP8EFLAG_ISR
|
||||
{
|
||||
}
|
||||
void ep2fflag_isr(void)__interrupt EP2FFLAG_ISR
|
||||
{
|
||||
}
|
||||
void ep4fflag_isr(void)__interrupt EP4FFLAG_ISR
|
||||
{
|
||||
}
|
||||
void ep6fflag_isr(void)__interrupt EP6FFLAG_ISR
|
||||
{
|
||||
}
|
||||
void ep8fflag_isr(void)__interrupt EP8FFLAG_ISR
|
||||
{
|
||||
}
|
||||
void gpifcomplete_isr(void)__interrupt GPIFCOMPLETE_ISR
|
||||
{
|
||||
}
|
||||
void gpifwaveform_isr(void)__interrupt GPIFWAVEFORM_ISR
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the control/status register for an endpoint
|
||||
*
|
||||
* @param ep endpoint address
|
||||
* @return on success: pointer to Control & Status register for endpoint
|
||||
* specified in \a ep
|
||||
* @return on failure: NULL
|
||||
*/
|
||||
__xdata uint8_t *usb_get_endpoint_cs_reg(uint8_t ep)
|
||||
{
|
||||
/* Mask direction bit */
|
||||
uint8_t ep_num = ep & ~0x80;
|
||||
|
||||
switch (ep_num) {
|
||||
case 0:
|
||||
return &EP0CS;
|
||||
case 1:
|
||||
return ep & 0x80 ? &EP1INCS : &EP1OUTCS;
|
||||
case 2:
|
||||
return &EP2CS;
|
||||
case 4:
|
||||
return &EP4CS;
|
||||
case 6:
|
||||
return &EP6CS;
|
||||
case 8:
|
||||
return &EP8CS;
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void usb_reset_data_toggle(uint8_t ep)
|
||||
{
|
||||
/* TOGCTL register:
|
||||
+----+-----+-----+------+-----+-------+-------+-------+
|
||||
| Q | S | R | IO | EP3 | EP2 | EP1 | EP0 |
|
||||
+----+-----+-----+------+-----+-------+-------+-------+
|
||||
|
||||
To reset data toggle bits, we have to write the endpoint direction (IN/OUT)
|
||||
to the IO bit and the endpoint number to the EP2..EP0 bits. Then, in a
|
||||
separate write cycle, the R bit needs to be set.
|
||||
*/
|
||||
TOGCTL = (((ep & 0x80) >> 3) + (ep & 0x0F));
|
||||
TOGCTL |= BMRESETTOGGLE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle GET_STATUS request.
|
||||
*
|
||||
* @return on success: true
|
||||
* @return on failure: false
|
||||
*/
|
||||
bool usb_handle_get_status(void)
|
||||
{
|
||||
uint8_t *ep_cs;
|
||||
switch (setup_data.bmrequesttype) {
|
||||
case GS_DEVICE:
|
||||
/* Two byte response: Byte 0, Bit 0 = self-powered, Bit 1 = remote wakeup.
|
||||
* Byte 1: reserved, reset to zero */
|
||||
EP0BUF[0] = 0;
|
||||
EP0BUF[1] = 0;
|
||||
|
||||
/* Send response */
|
||||
EP0BCH = 0;
|
||||
syncdelay(3);
|
||||
EP0BCL = 2;
|
||||
syncdelay(3);
|
||||
break;
|
||||
case GS_INTERFACE:
|
||||
/* Always return two zero bytes according to USB 1.1 spec, p. 191 */
|
||||
EP0BUF[0] = 0;
|
||||
EP0BUF[1] = 0;
|
||||
|
||||
/* Send response */
|
||||
EP0BCH = 0;
|
||||
syncdelay(3);
|
||||
EP0BCL = 2;
|
||||
syncdelay(3);
|
||||
break;
|
||||
case GS_ENDPOINT:
|
||||
/* Get stall bit for endpoint specified in low byte of wIndex */
|
||||
ep_cs = usb_get_endpoint_cs_reg(setup_data.windex & 0xff);
|
||||
|
||||
if (*ep_cs & EPSTALL)
|
||||
EP0BUF[0] = 0x01;
|
||||
else
|
||||
EP0BUF[0] = 0x00;
|
||||
|
||||
/* Second byte sent has to be always zero */
|
||||
EP0BUF[1] = 0;
|
||||
|
||||
/* Send response */
|
||||
EP0BCH = 0;
|
||||
syncdelay(3);
|
||||
EP0BCL = 2;
|
||||
syncdelay(3);
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle CLEAR_FEATURE request.
|
||||
*
|
||||
* @return on success: true
|
||||
* @return on failure: false
|
||||
*/
|
||||
bool usb_handle_clear_feature(void)
|
||||
{
|
||||
__xdata uint8_t *ep_cs;
|
||||
|
||||
switch (setup_data.bmrequesttype) {
|
||||
case CF_DEVICE:
|
||||
/* Clear remote wakeup not supported: stall EP0 */
|
||||
STALL_EP0();
|
||||
break;
|
||||
case CF_ENDPOINT:
|
||||
if (setup_data.wvalue == 0) {
|
||||
/* Unstall the endpoint specified in wIndex */
|
||||
ep_cs = usb_get_endpoint_cs_reg(setup_data.windex);
|
||||
if (!ep_cs)
|
||||
return false;
|
||||
*ep_cs &= ~EPSTALL;
|
||||
} else {
|
||||
/* Unsupported feature, stall EP0 */
|
||||
STALL_EP0();
|
||||
}
|
||||
break;
|
||||
default:
|
||||
/* Vendor commands... */
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle SET_FEATURE request.
|
||||
*
|
||||
* @return on success: true
|
||||
* @return on failure: false
|
||||
*/
|
||||
bool usb_handle_set_feature(void)
|
||||
{
|
||||
__xdata uint8_t *ep_cs;
|
||||
|
||||
switch (setup_data.bmrequesttype) {
|
||||
case SF_DEVICE:
|
||||
if (setup_data.wvalue == 2)
|
||||
return true;
|
||||
break;
|
||||
case SF_ENDPOINT:
|
||||
if (setup_data.wvalue == 0) {
|
||||
/* Stall the endpoint specified in wIndex */
|
||||
ep_cs = usb_get_endpoint_cs_reg(setup_data.windex);
|
||||
if (!ep_cs)
|
||||
return false;
|
||||
*ep_cs |= EPSTALL;
|
||||
} else {
|
||||
/* Unsupported endpoint feature */
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
/* Vendor commands... */
|
||||
break;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle GET_DESCRIPTOR request.
|
||||
*
|
||||
* @return on success: true
|
||||
* @return on failure: false
|
||||
*/
|
||||
bool usb_handle_get_descriptor(void)
|
||||
{
|
||||
__xdata uint8_t descriptor_type;
|
||||
__xdata uint8_t descriptor_index;
|
||||
|
||||
descriptor_type = (setup_data.wvalue & 0xff00) >> 8;
|
||||
descriptor_index = setup_data.wvalue & 0x00ff;
|
||||
|
||||
switch (descriptor_type) {
|
||||
case DESCRIPTOR_TYPE_DEVICE:
|
||||
SUDPTRH = HI8(&device_descriptor);
|
||||
SUDPTRL = LO8(&device_descriptor);
|
||||
break;
|
||||
case DESCRIPTOR_TYPE_CONFIGURATION:
|
||||
SUDPTRH = HI8(&config_descriptor);
|
||||
SUDPTRL = LO8(&config_descriptor);
|
||||
break;
|
||||
case DESCRIPTOR_TYPE_STRING:
|
||||
if (setup_data.windex == 0) {
|
||||
/* Supply language descriptor */
|
||||
SUDPTRH = HI8(&language_descriptor);
|
||||
SUDPTRL = LO8(&language_descriptor);
|
||||
} else if (setup_data.windex == 0x0409 /* US English */) {
|
||||
/* Supply string descriptor */
|
||||
SUDPTRH = HI8(en_string_descriptors[descriptor_index - 1]);
|
||||
SUDPTRL = LO8(en_string_descriptors[descriptor_index - 1]);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
/* Unsupported descriptor type */
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle SET_INTERFACE request.
|
||||
*/
|
||||
void usb_handle_set_interface(void)
|
||||
{
|
||||
/* Reset Data Toggle */
|
||||
usb_reset_data_toggle(USB_DIR_IN | 4);
|
||||
usb_reset_data_toggle(USB_DIR_OUT | 2);
|
||||
|
||||
/* Unstall & clear busy flag of all valid IN endpoints */
|
||||
EP1INCS = 0 | EPBSY;
|
||||
|
||||
/* Unstall all valid OUT endpoints, reset bytecounts */
|
||||
EP1OUTCS = 0;
|
||||
EP1OUTBC = 0;
|
||||
syncdelay(3);
|
||||
}
|
||||
|
||||
/* Initialize GPIF interface transfer count */
|
||||
void set_gpif_cnt(uint32_t count)
|
||||
{
|
||||
GPIFTCB3 = (uint8_t)(((uint32_t)(count) >> 24) & 0x000000ff);
|
||||
syncdelay(3);
|
||||
GPIFTCB2 = (uint8_t)(((uint32_t)(count) >> 16) & 0x000000ff);
|
||||
syncdelay(3);
|
||||
GPIFTCB1 = (uint8_t)(((uint32_t)(count) >> 8) & 0x000000ff);
|
||||
syncdelay(3);
|
||||
GPIFTCB0 = (uint8_t)((uint32_t)(count) & 0x000000ff);
|
||||
}
|
||||
|
||||
/*
|
||||
* Vendor commands handling:
|
||||
*/
|
||||
#define VR_CFGOPEN 0xB0
|
||||
#define VR_CFGCLOSE 0xB1
|
||||
|
||||
uint8_t ix;
|
||||
uint8_t bcnt;
|
||||
uint8_t __xdata *eptr;
|
||||
uint16_t wcnt;
|
||||
uint32_t __xdata gcnt;
|
||||
bool usb_handle_send_bitstream(void)
|
||||
{
|
||||
eptr = EP0BUF; /* points to EP0BUF 64-byte register */
|
||||
wcnt = setup_data.wlength; /* total transfer count */
|
||||
|
||||
/* Clear EP0BUF for OUT requests */
|
||||
if (setup_data.bmrequesttype & 0x80) {
|
||||
bcnt = ((wcnt > 64) ? 64 : wcnt);
|
||||
for (ix = 0; ix < bcnt; ix++)
|
||||
eptr[ix] = 0;
|
||||
}
|
||||
|
||||
switch (setup_data.brequest) {
|
||||
case VR_CFGOPEN:
|
||||
/* Clear bytecount / to allow new data in / to stops NAKing */
|
||||
EP0BCH = 0;
|
||||
EP0BCL = 0;
|
||||
while (EP0CS & EPBSY)
|
||||
; /* wait to finish transferring in EP0BUF, until not busy */
|
||||
gcnt = ((uint32_t)(eptr[0]) << 24) | ((uint32_t)(eptr[1]) << 16)
|
||||
| ((uint32_t)(eptr[2]) << 8) | (uint32_t)(eptr[3]);
|
||||
/* Angie board FPGA bitstream download */
|
||||
switch ((setup_data.wvalue) & 0x00C0) {
|
||||
case 0x00:
|
||||
PIN_PROGRAM_B = 0; /* Apply RPGM- pulse */
|
||||
GPIFWFSELECT = 0xF2; /* Restore Config mode waveforms select */
|
||||
syncdelay(3);
|
||||
EP2FIFOCFG = BMAUTOOUT; /* and Automatic 8-bit GPIF OUT mode */
|
||||
syncdelay(3);
|
||||
PIN_PROGRAM_B = 1; /* Negate RPGM- pulse */
|
||||
delay_ms(10); /* FPGA init time < 10mS */
|
||||
set_gpif_cnt(gcnt); /* Initialize GPIF interface transfer count */
|
||||
PIN_RDWR_B = 0;
|
||||
PIN_CSI_B = 0;
|
||||
GPIFTRIG = GPIF_EP2; /* Trigger GPIF OUT transfer on EP2 */
|
||||
syncdelay(3);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case VR_CFGCLOSE:
|
||||
ix = 10;
|
||||
/* wait until GPIF transaction has been completed */
|
||||
while ((GPIFTRIG & BMGPIFDONE) == 0) {
|
||||
if (ix-- == 0) {
|
||||
printf("GPIF done time out\n");
|
||||
break;
|
||||
}
|
||||
delay_ms(1);
|
||||
}
|
||||
switch ((setup_data.wvalue) & 0x00C0) {
|
||||
case 0x00:
|
||||
PIN_CSI_B = 1;
|
||||
PIN_RDWR_B = 1;
|
||||
IFCONFIG &= 0xFC; /* Exit gpif mode */
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
EP0BCH = 0;
|
||||
EP0BCL = (uint8_t)(setup_data.wlength); /* Signal buffer is filled */
|
||||
break;
|
||||
default:
|
||||
return true; /* Error: unknown VR command */
|
||||
}
|
||||
return false; /* no error; command handled OK */
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle the arrival of a USB Control Setup Packet.
|
||||
*/
|
||||
void usb_handle_setup_data(void)
|
||||
{
|
||||
switch (setup_data.brequest) {
|
||||
case GET_STATUS:
|
||||
if (!usb_handle_get_status())
|
||||
STALL_EP0();
|
||||
break;
|
||||
case CLEAR_FEATURE:
|
||||
if (!usb_handle_clear_feature())
|
||||
STALL_EP0();
|
||||
break;
|
||||
case 2: case 4:
|
||||
/* Reserved values */
|
||||
STALL_EP0();
|
||||
break;
|
||||
case SET_FEATURE:
|
||||
if (!usb_handle_set_feature())
|
||||
STALL_EP0();
|
||||
break;
|
||||
case SET_ADDRESS:
|
||||
/* Handled by USB core */
|
||||
break;
|
||||
case SET_DESCRIPTOR:
|
||||
/* Set Descriptor not supported. */
|
||||
STALL_EP0();
|
||||
break;
|
||||
case GET_DESCRIPTOR:
|
||||
if (!usb_handle_get_descriptor())
|
||||
STALL_EP0();
|
||||
break;
|
||||
case GET_CONFIGURATION:
|
||||
/* ANGIE has only one configuration, return its index */
|
||||
EP0BUF[0] = config_descriptor.bconfigurationvalue;
|
||||
EP0BCH = 0;
|
||||
EP0BCL = 1;
|
||||
syncdelay(3);
|
||||
break;
|
||||
case SET_CONFIGURATION:
|
||||
/* ANGIE has only one configuration -> nothing to do */
|
||||
break;
|
||||
case GET_INTERFACE:
|
||||
/* ANGIE only has one interface, return its number */
|
||||
EP0BUF[0] = interface_descriptor00.binterfacenumber;
|
||||
EP0BCH = 0;
|
||||
EP0BCL = 1;
|
||||
syncdelay(3);
|
||||
break;
|
||||
case SET_INTERFACE:
|
||||
usb_handle_set_interface();
|
||||
break;
|
||||
case SYNCH_FRAME:
|
||||
/* Isochronous endpoints not used -> nothing to do */
|
||||
break;
|
||||
default:
|
||||
/* if not Vendor command, Stall EndPoint 0 */
|
||||
if (usb_handle_send_bitstream())
|
||||
STALL_EP0();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle the initialization of endpoints.
|
||||
*/
|
||||
void ep_init(void)
|
||||
{
|
||||
EP1INCFG = 0xA0;
|
||||
syncdelay(3);
|
||||
EP1OUTCFG = 0xA0;
|
||||
syncdelay(3);
|
||||
EP2CFG = 0xA0;
|
||||
syncdelay(3);
|
||||
EP4CFG = 0x00;
|
||||
syncdelay(3);
|
||||
EP6CFG = 0x00;
|
||||
syncdelay(3);
|
||||
EP8CFG = 0x00;
|
||||
syncdelay(3);
|
||||
|
||||
/* arm EP1-OUT */
|
||||
EP1OUTBC = 0;
|
||||
syncdelay(3);
|
||||
EP1OUTBC = 0;
|
||||
syncdelay(3);
|
||||
|
||||
/* arm EP1-IN */
|
||||
EP1INBC = 0;
|
||||
syncdelay(3);
|
||||
EP1INBC = 0;
|
||||
syncdelay(3);
|
||||
|
||||
/* Standard procedure to reset FIFOs */
|
||||
FIFORESET = BMNAKALL; /* NAK all transfers during the reset */
|
||||
syncdelay(3);
|
||||
FIFORESET = 0x02; /* reset EP2 FIFO */
|
||||
syncdelay(3);
|
||||
FIFORESET = 0x00; /* deactivate the NAK all */
|
||||
syncdelay(3);
|
||||
EP2FIFOCFG = 0x00;
|
||||
syncdelay(3);
|
||||
EP2FIFOCFG = BMAUTOOUT; /* Automatic 8-bit GPIF OUT mode */
|
||||
syncdelay(3);
|
||||
}
|
||||
|
||||
/**
|
||||
* Interrupt initialization. Configures USB interrupts.
|
||||
*/
|
||||
void interrupt_init(void)
|
||||
{
|
||||
/* Enable Interrupts */
|
||||
EA = 1;
|
||||
|
||||
/* Enable USB interrupt (EIE register) */
|
||||
EUSB = 1;
|
||||
EICON |= 0x20;
|
||||
|
||||
/* Enable INT 2 & 4 Autovectoring */
|
||||
INTSETUP |= (AV2EN | AV4EN);
|
||||
|
||||
/* Enable individual EP1OUT&IN interrupts */
|
||||
EPIE |= 0x0C;
|
||||
|
||||
/* Clear individual USB interrupt IRQ */
|
||||
EPIRQ = 0x0C;
|
||||
|
||||
/* Enable SUDAV interrupt */
|
||||
USBIEN |= SUDAVI;
|
||||
|
||||
/* Clear SUDAV interrupt */
|
||||
USBIRQ = SUDAVI;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle the initialization of io ports.
|
||||
*/
|
||||
void io_init(void)
|
||||
{
|
||||
/* PORT A */
|
||||
PORTACFG = 0x01; /* 0: normal ou 1: alternate function (each bit) */
|
||||
OEA = 0xEF; /* all OUT exept INIT_B IN */
|
||||
IOA = 0xFF;
|
||||
PIN_RDWR_B = 1;
|
||||
PIN_CSI_B = 1;
|
||||
PIN_PROGRAM_B = 1;
|
||||
|
||||
/* PORT B */
|
||||
OEB = 0xEF; /* all OUT exept TDO */
|
||||
IOB = 0xFF;
|
||||
PIN_TRST = 1;
|
||||
PIN_TMS = 0;
|
||||
PIN_TCK = 0;
|
||||
PIN_TDI = 0;
|
||||
PIN_SRST = 1;
|
||||
|
||||
/* PORT C */
|
||||
PORTCCFG = 0x00; /* 0: normal ou 1: alternate function (each bit) */
|
||||
OEC = 0xEF;
|
||||
IOC = 0xFF;
|
||||
}
|
|
@ -0,0 +1,109 @@
|
|||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
# Copyright (C) 2023 by NanoXplore, France - all rights reserved
|
||||
|
||||
# Needed by timing test
|
||||
export PROJECT := angie_openocd
|
||||
TARGET_PART := xc6slx9-2tqg144
|
||||
export TOPLEVEL := S609
|
||||
|
||||
# Detects the ROOT dir from the .git marker
|
||||
sp :=
|
||||
sp +=
|
||||
_walk = $(if $1,$(wildcard /$(subst $(sp),/,$1)/$2) $(call _walk,$(wordlist 2,$(words $1),x $1),$2))
|
||||
_find = $(firstword $(call _walk,$(strip $(subst /, ,$1)),$2))
|
||||
_ROOT := $(patsubst %/.git,%,$(call _find,$(CURDIR),.git))
|
||||
|
||||
SHELL := /bin/bash
|
||||
TOP_DIR := $(realpath $(_ROOT))
|
||||
HDL_DIR := $(CURDIR)
|
||||
SRC_DIR := $(HDL_DIR)/src
|
||||
TOOLS_DIR := $(TOP_DIR)/tools/build
|
||||
COMMON_DIR := $(TOP_DIR)/common/hdl
|
||||
COMMON_HDL_DIR := $(COMMON_DIR)/src
|
||||
COMMON_LIBS := $(COMMON_DIR)/libs
|
||||
HDL_BUILD_DIR := $(HDL_DIR)/build
|
||||
OUTPUT_DIR ?= $(HDL_BUILD_DIR)/output
|
||||
FINAL_OUTPUT_DIR := $(OUTPUT_DIR)/$(PROJECT)
|
||||
|
||||
# Tools
|
||||
MKDIR := mkdir -p
|
||||
CP := cp -f
|
||||
|
||||
HDL_SRC_PATH := $(addprefix $(COMMON_DIR)/ips/, $(HDL_IPS)) $(HDL_DIR)
|
||||
VHDSOURCE += $(foreach ip,$(HDL_SRC_PATH),$(wildcard $(ip)/src/*.vhd))
|
||||
VSOURCE += $(foreach ip,$(HDL_SRC_PATH),$(wildcard $(ip)/src/*.v))
|
||||
VSOURCE += $(foreach ip,$(HDL_SRC_PATH),$(wildcard $(ip)/src/*.vh))
|
||||
|
||||
CONSTRAINTS ?= $(SRC_DIR)/$(PROJECT).ucf
|
||||
|
||||
COMMON_OPTS := -intstyle xflow
|
||||
XST_OPTS :=
|
||||
NGDBUILD_OPTS :=
|
||||
MAP_OPTS := -mt 2
|
||||
PAR_OPTS := -mt 4
|
||||
BITGEN_OPTS := -g Binary:Yes
|
||||
|
||||
XILINX_PLATFORM := lin64
|
||||
PATH := $(PATH):$(XILINX_HOME)/bin/$(XILINX_PLATFORM)
|
||||
|
||||
RUN = @echo -ne "\n\n\e[1;33m======== $(1) ========\e[m\n\n"; \
|
||||
cd $(HDL_BUILD_DIR) && $(XILINX_HOME)/bin/$(XILINX_PLATFORM)/$(1)
|
||||
|
||||
compile: $(HDL_BUILD_DIR)/$(PROJECT).bin
|
||||
|
||||
install: $(HDL_BUILD_DIR)/$(PROJECT).bin
|
||||
$(MKDIR) $(FINAL_OUTPUT_DIR)
|
||||
$(CP) $(HDL_BUILD_DIR)/$(PROJECT).bin $(FINAL_OUTPUT_DIR)
|
||||
|
||||
clean:
|
||||
rm -rf $(HDL_BUILD_DIR)
|
||||
|
||||
$(HDL_BUILD_DIR)/$(PROJECT).bin: $(HDL_BUILD_DIR)/$(PROJECT).ncd
|
||||
$(call RUN,bitgen) $(COMMON_OPTS) $(BITGEN_OPTS) \
|
||||
-w $(PROJECT).ncd $(PROJECT).bit
|
||||
|
||||
$(HDL_BUILD_DIR)/$(PROJECT).ncd: $(HDL_BUILD_DIR)/$(PROJECT).map.ncd
|
||||
$(call RUN,par) $(COMMON_OPTS) $(PAR_OPTS) \
|
||||
-w $(PROJECT).map.ncd $(PROJECT).ncd $(PROJECT).pcf
|
||||
|
||||
$(HDL_BUILD_DIR)/$(PROJECT).map.ncd: $(HDL_BUILD_DIR)/$(PROJECT).ngd
|
||||
$(call RUN,map) $(COMMON_OPTS) $(MAP_OPTS) \
|
||||
-p $(TARGET_PART) \
|
||||
-w $(PROJECT).ngd -o $(PROJECT).map.ncd $(PROJECT).pcf
|
||||
|
||||
$(HDL_BUILD_DIR)/$(PROJECT).ngd: $(HDL_BUILD_DIR)/$(PROJECT).ngc
|
||||
$(call RUN,ngdbuild) $(COMMON_OPTS) $(NGDBUILD_OPTS) \
|
||||
-p $(TARGET_PART) -uc $(CONSTRAINTS) \
|
||||
$(PROJECT).ngc $(PROJECT).ngd
|
||||
|
||||
$(HDL_BUILD_DIR)/$(PROJECT).ngc: $(HDL_BUILD_DIR)/$(PROJECT).prj $(HDL_BUILD_DIR)/$(PROJECT).scr
|
||||
$(call RUN,xst) $(COMMON_OPTS) -ifn $(PROJECT).scr
|
||||
|
||||
$(HDL_BUILD_DIR)/$(PROJECT).scr: | $(HDL_BUILD_DIR)
|
||||
@echo "Updating $@"
|
||||
@mkdir -p $(HDL_BUILD_DIR)
|
||||
@rm -f $@
|
||||
@echo "run" \
|
||||
"-ifn $(PROJECT).prj" \
|
||||
"-ofn $(PROJECT).ngc" \
|
||||
"-ifmt mixed" \
|
||||
"$(XST_OPTS)" \
|
||||
"-top $(TOPLEVEL)" \
|
||||
"-ofmt NGC" \
|
||||
"-p $(TARGET_PART)" \
|
||||
> $(HDL_BUILD_DIR)/$(PROJECT).scr
|
||||
|
||||
$(HDL_BUILD_DIR)/$(PROJECT).prj: | $(HDL_BUILD_DIR)
|
||||
@echo "Updating $@"
|
||||
@rm -f $@
|
||||
@$(foreach file,$(VSOURCE),echo "verilog work \"$(file)\"" >> $@;)
|
||||
@$(foreach file,$(VHDSOURCE),echo "vhdl work \"$(file)\"" >> $@;)
|
||||
@$(foreach lib,$(HDL_LIBS),$(foreach file,$(wildcard $(COMMON_LIBS)/$(lib)/src/*.vhd),echo "vhdl $(lib) \"$(file)\"" >> $@;))
|
||||
@$(foreach lib,$(HDL_LIBS),$(foreach file,$(wildcard $(COMMON_LIBS)/$(lib)/src/*.v),echo "verilog $(lib) \"$(file)\"" >> $@;))
|
||||
@$(foreach lib,$(HDL_LIBS),$(foreach file,$(wildcard $(COMMON_LIBS)/$(lib)/src/*.vh),echo "verilog $(lib) \"$(file)\"" >> $@;))
|
||||
|
||||
$(HDL_BUILD_DIR):
|
||||
$(MKDIR) $(HDL_BUILD_DIR)
|
||||
|
||||
.PHONY: clean compile install
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
# Copyright (C) 2023 by NanoXplore, France - all rights reserved
|
||||
|
||||
This is the source code of Nanoxplore USB-JTAG Adapter Angie's bitstream.
|
||||
This bitstream is for the "xc6slx9-2tqg144" Spartan-6 Xilinx FPGA.
|
||||
|
||||
To generate this bitstream, you need to install Xilinx ISE Webpack 14.7
|
||||
You will need to give the ISE software path : export XILINX_HOME=path/to/ise/sw
|
||||
Please set the enviromnent first by executing the ". ./set_env.sh"
|
||||
|
||||
All you have to do now is to write your vhd and constrains codes.
|
||||
|
||||
One all is setup, you can use the make commands:
|
||||
make compile : to compile your (.vhd & .ucf) files in the "src" directory
|
||||
A directory named "build" will be created, which contains all the generated
|
||||
files including the bitstream file.
|
||||
|
||||
make clean : to delete the build directory.
|
|
@ -0,0 +1,14 @@
|
|||
#!/bin/bash
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
# Copyright (C) 2023 by NanoXplore, France - all rights reserved
|
||||
|
||||
[ -z "${XILINX_HOME}" ] && export XILINX_HOME=/home/software/Xilinx/ISE/14.7/ISE_DS/ISE
|
||||
export PATH="$XILINX_HOME:$PATH"
|
||||
echo "SET XILINX_HOME to ${XILINX_HOME}"
|
||||
# This is needed for isim
|
||||
XILINX_HOME_BASE=${XILINX_HOME}/..
|
||||
for part in common EDK PlanAhead ISE
|
||||
do
|
||||
el=${XILINX_HOME_BASE}/${part}
|
||||
. ${el}/.settings64.sh ${el}
|
||||
done
|
|
@ -0,0 +1,35 @@
|
|||
## SPDX-License-Identifier: BSD-3-Clause
|
||||
##--------------------------------------------------------------------------
|
||||
## Project Context: nanoXplore USB-JTAG Adapter Board, Spartan6
|
||||
## Design Name: NJTAG USB-JTAG Adapter FPGA source code
|
||||
## Module Name: _angie_openocd.ucf
|
||||
## Target Device: XC6SLX9-2 TQ144
|
||||
## Tool versions: ISE Webpack 13.2 -> 14.2
|
||||
## Author: Ahmed BOUDJELIDA nanoXplore SAS
|
||||
##--------------------------------------------------------------------------
|
||||
# WARNING: PullUps on JTAG inputs should be enabled after configuration
|
||||
# (bitgen option) since the pins are not connected.
|
||||
|
||||
net TRST LOC = 'P48' ;
|
||||
net TMS LOC = 'P43' ;
|
||||
net TCK LOC = 'P44' ;
|
||||
net TDI LOC = 'P45' ;
|
||||
net TDO LOC = 'P46' ;
|
||||
net SRST LOC = 'P61' ;
|
||||
net SI_TDO LOC = 'P16' ;
|
||||
net SO_TRST LOC = 'P32' ;
|
||||
net SO_TMS LOC = 'P27' ;
|
||||
net SO_TCK LOC = 'P30' ;
|
||||
net SO_TDI LOC = 'P26' ;
|
||||
net SO_SRST LOC = 'P12' ;
|
||||
net ST_0 LOC = 'P29' ;
|
||||
net ST_1 LOC = 'P21' ;
|
||||
net ST_2 LOC = 'P11' ;
|
||||
net FTP<0> LOC = 'P121' ;
|
||||
net FTP<1> LOC = 'P120' ;
|
||||
net FTP<2> LOC = 'P119' ;
|
||||
net FTP<3> LOC = 'P116' ;
|
||||
net FTP<4> LOC = 'P111' ;
|
||||
net FTP<5> LOC = 'P112' ;
|
||||
net FTP<6> LOC = 'P115' ;
|
||||
net FTP<7> LOC = 'P114' ;
|
|
@ -0,0 +1,66 @@
|
|||
-- SPDX-License-Identifier: BSD-3-Clause
|
||||
----------------------------------------------------------------------------
|
||||
-- Project Context: nanoXplore USB-JTAG Adapter Board, Spartan6
|
||||
-- Design Name: NJTAG USB-JTAG Adapter FPGA source code
|
||||
-- Module Name: _angie_openocd.vhd
|
||||
-- Target Device: XC6SLX9-2 TQ144
|
||||
-- Tool versions: ISE Webpack 13.2 -> 14.2
|
||||
-- Author: Ahmed BOUDJELIDA nanoXplore SAS
|
||||
----------------------------------------------------------------------------
|
||||
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
use ieee.std_logic_arith.all;
|
||||
use ieee.std_logic_unsigned.all;
|
||||
library UNISIM;
|
||||
use UNISIM.VComponents.all;
|
||||
|
||||
entity S609 is port(
|
||||
TRST : in std_logic;
|
||||
TMS : in std_logic;
|
||||
TCK : in std_logic;
|
||||
TDI : in std_logic;
|
||||
TDO : out std_logic;
|
||||
SRST : in std_logic;
|
||||
FTP : out std_logic_vector(7 downto 0); -- Test points
|
||||
SI_TDO : in std_logic;
|
||||
ST_0 : out std_logic;
|
||||
ST_1 : out std_logic;
|
||||
ST_2 : out std_logic;
|
||||
SO_TRST : out std_logic;
|
||||
SO_TMS : out std_logic;
|
||||
SO_TCK : out std_logic;
|
||||
SO_TDI : out std_logic;
|
||||
SO_SRST :out std_logic
|
||||
);
|
||||
end S609;
|
||||
|
||||
architecture A_S609 of S609 is
|
||||
begin
|
||||
|
||||
--Directions:
|
||||
ST_0 <= '0';
|
||||
ST_1 <= '1';
|
||||
|
||||
--TDO:
|
||||
TDO <= not SI_TDO;
|
||||
|
||||
--TRST - TCK - TMS - TDI:
|
||||
SO_TRST <= TRST;
|
||||
SO_TMS <= TMS;
|
||||
SO_TCK <= TCK;
|
||||
SO_TDI <= TDI;
|
||||
ST_2 <= SRST;
|
||||
SO_SRST <= '0';
|
||||
|
||||
--Points de test:
|
||||
FTP(0) <= TRST;
|
||||
FTP(1) <= TMS;
|
||||
FTP(2) <= TCK;
|
||||
FTP(3) <= TDI;
|
||||
FTP(5) <= SRST;
|
||||
FTP(4) <= SI_TDO;
|
||||
FTP(6) <= '1';
|
||||
FTP(7) <= '1';
|
||||
|
||||
end A_S609;
|
149
doc/openocd.texi
149
doc/openocd.texi
|
@ -463,6 +463,12 @@ They only work with STMicroelectronics chips, notably STM32 and STM8.
|
|||
@item @b{STLINK-V3}
|
||||
@* This is available standalone and as part of some kits.
|
||||
@* Link: @url{http://www.st.com/stlink-v3}
|
||||
@item @b{STLINK-V3PWR}
|
||||
@* This is available standalone.
|
||||
Beside the debugger functionality, the probe includes a SMU (source
|
||||
measurement unit) aimed at analyzing power consumption during code
|
||||
execution. The SMU is not supported by OpenOCD.
|
||||
@* Link: @url{http://www.st.com/stlink-v3pwr}
|
||||
@end itemize
|
||||
|
||||
For info the original ST-LINK enumerates using the mass storage usb class; however,
|
||||
|
@ -502,6 +508,9 @@ debuggers to ARM Cortex based targets @url{http://www.keil.com/support/man/docs/
|
|||
@item @b{ARM-JTAG-EW}
|
||||
@* Link: @url{http://www.olimex.com/dev/arm-jtag-ew.html}
|
||||
|
||||
@item @b{angie}
|
||||
@* Link: @url{https://nanoxplore.org/}
|
||||
|
||||
@item @b{Buspirate}
|
||||
@* Link: @url{http://dangerousprototypes.com/bus-pirate-manual/}
|
||||
|
||||
|
@ -2174,6 +2183,9 @@ In such cases, just specify the relevant port number as "disabled".
|
|||
If you disable all access through TCP/IP, you will need to
|
||||
use the command line @option{-pipe} option.
|
||||
|
||||
You can request the operating system to select one of the available
|
||||
ports for the server by specifying the relevant port number as "0".
|
||||
|
||||
@anchor{gdb_port}
|
||||
@deffn {Config Command} {gdb_port} [number]
|
||||
@cindex GDB server
|
||||
|
@ -2506,6 +2518,10 @@ Optionally sets that option first.
|
|||
@end deffn
|
||||
@end deffn
|
||||
|
||||
@deffn {Interface Driver} {angie}
|
||||
This is the NanoXplore's ANGIE USB-JTAG Adapter.
|
||||
@end deffn
|
||||
|
||||
@deffn {Interface Driver} {arm-jtag-ew}
|
||||
Olimex ARM-JTAG-EW USB adapter
|
||||
This has one driver-specific command:
|
||||
|
@ -3213,7 +3229,7 @@ passed as is to the underlying adapter layout handler.
|
|||
@anchor{st_link_dap_interface}
|
||||
@deffn {Interface Driver} {st-link}
|
||||
This is a driver that supports STMicroelectronics adapters ST-LINK/V2
|
||||
(from firmware V2J24) and STLINK-V3, thanks to a new API that provides
|
||||
(from firmware V2J24), STLINK-V3 and STLINK-V3PWR, thanks to a new API that provides
|
||||
directly access the arm ADIv5 DAP.
|
||||
|
||||
The new API provide access to multiple AP on the same DAP, but the
|
||||
|
@ -8604,22 +8620,24 @@ As it does for JTAG TAPs, debug targets, and flash chips (both NOR and NAND),
|
|||
OpenOCD maintains a list of PLDs available for use in various commands.
|
||||
Also, each such PLD requires a driver.
|
||||
|
||||
They are referenced by the number shown by the @command{pld devices} command,
|
||||
and new PLDs are defined by @command{pld device driver_name}.
|
||||
They are referenced by the name which was given when the pld was created or
|
||||
the number shown by the @command{pld devices} command.
|
||||
New PLDs are defined by @command{pld create pld_name driver_name -chain-position tap_name [driver_options]}.
|
||||
|
||||
@deffn {Config Command} {pld device} driver_name tap_name [driver_options]
|
||||
Defines a new PLD device, supported by driver @var{driver_name},
|
||||
using the TAP named @var{tap_name}.
|
||||
The driver may make use of any @var{driver_options} to configure its
|
||||
behavior.
|
||||
@deffn {Config Command} {pld create} pld_name driver_name -chain-position tap_name [driver_options]
|
||||
Creates a new PLD device, supported by driver @var{driver_name},
|
||||
assigning @var{pld_name} for further reference.
|
||||
@code{-chain-position} @var{tap_name} names the TAP
|
||||
used to access this target.
|
||||
The driver may make use of any @var{driver_options} to configure its behavior.
|
||||
@end deffn
|
||||
|
||||
@deffn {Command} {pld devices}
|
||||
Lists the PLDs and their numbers.
|
||||
List the known PLDs with their name.
|
||||
@end deffn
|
||||
|
||||
@deffn {Command} {pld load} num filename
|
||||
Loads the file @file{filename} into the PLD identified by @var{num}.
|
||||
@deffn {Command} {pld load} pld_name filename
|
||||
Loads the file @file{filename} into the PLD identified by @var{pld_name}.
|
||||
The file format must be inferred by the driver.
|
||||
@end deffn
|
||||
|
||||
|
@ -8629,12 +8647,12 @@ Drivers may support PLD-specific options to the @command{pld device}
|
|||
definition command, and may also define commands usable only with
|
||||
that particular type of PLD.
|
||||
|
||||
@deffn {FPGA Driver} {virtex2} [no_jstart]
|
||||
@deffn {FPGA Driver} {virtex2} [@option{-no_jstart}]
|
||||
Virtex-II is a family of FPGAs sold by Xilinx.
|
||||
This driver can also be used to load Series3, Series6, Series7 and Zynq 7000 devices.
|
||||
It supports the IEEE 1532 standard for In-System Configuration (ISC).
|
||||
|
||||
If @var{no_jstart} is non-zero, the JSTART instruction is not used after
|
||||
If @var{-no_jstart} is given, the JSTART instruction is not used after
|
||||
loading the bitstream. While required for Series2, Series3, and Series6, it
|
||||
breaks bitstream loading on Series7.
|
||||
|
||||
|
@ -8644,70 +8662,92 @@ openocd -f board/digilent_zedboard.cfg -c "init" \
|
|||
@end example
|
||||
|
||||
|
||||
@deffn {Command} {virtex2 read_stat} num
|
||||
@deffn {Command} {virtex2 read_stat} pld_name
|
||||
Reads and displays the Virtex-II status register (STAT)
|
||||
for FPGA @var{num}.
|
||||
for FPGA @var{pld_name}.
|
||||
@end deffn
|
||||
|
||||
@deffn {Command} {virtex2 set_instr_codes} pld_name cfg_out cfg_in jprogb jstart jshutdown [user1 [user2 [user3 [user4]]]]
|
||||
Change values for boundary scan instructions. Default are values for Virtex 2, devices Virtex 4/5/6 and
|
||||
SSI devices are using different values.
|
||||
@var{pld_name} is the name of the pld device.
|
||||
@var{cfg_out} is the value used to select CFG_OUT instruction.
|
||||
@var{cfg_in} is the value used to select CFG_IN instruction.
|
||||
@var{jprogb} is the value used to select JPROGRAM instruction.
|
||||
@var{jstart} is the value used to select JSTART instruction.
|
||||
@var{jshutdown} is the value used to select JSHUTDOWN instruction.
|
||||
@var{user1} to @var{user4} are the intruction used to select the user registers USER1 to USER4.
|
||||
@end deffn
|
||||
|
||||
@deffn {Command} {virtex2 set_user_codes} pld_name user1 [user2 [user3 [user4]]]
|
||||
Change values for boundary scan instructions selecting the registers USER1 to USER4.
|
||||
Description of the arguments can be found at command @command{virtex2 set_instr_codes}.
|
||||
@end deffn
|
||||
|
||||
@deffn {Command} {virtex2 program} pld_name
|
||||
Load the bitstream from external memory for FPGA @var{pld_name}. A.k.a. refresh.
|
||||
@end deffn
|
||||
@end deffn
|
||||
|
||||
|
||||
|
||||
@deffn {FPGA Driver} {lattice} [family]
|
||||
@deffn {FPGA Driver} {lattice} [@option{-family} <name>]
|
||||
The FGPA families ECP2, ECP3, ECP5, Certus and CertusPro by Lattice are supported.
|
||||
This driver can be used to load the bitstream into the FPGA or read the status register and read/write the usercode register.
|
||||
|
||||
The option @option{family} is one of @var{ecp2 ecp3 ecp5 certus}. This is needed when the JTAG ID of the device is not known by openocd (newer NX devices).
|
||||
For the option @option{-family} @var{name} is one of @var{ecp2 ecp3 ecp5 certus}. This is needed when the JTAG ID of the device is not known by openocd (newer NX devices).
|
||||
|
||||
@deffn {Command} {lattice read_status} num
|
||||
@deffn {Command} {lattice read_status} pld_name
|
||||
Reads and displays the status register
|
||||
for FPGA @var{num}.
|
||||
for FPGA @var{pld_name}.
|
||||
@end deffn
|
||||
|
||||
@deffn {Command} {lattice read_user} num
|
||||
@deffn {Command} {lattice read_user} pld_name
|
||||
Reads and displays the user register
|
||||
for FPGA @var{num}.
|
||||
for FPGA @var{pld_name}.
|
||||
@end deffn
|
||||
|
||||
@deffn {Command} {lattice write_user} num val
|
||||
@deffn {Command} {lattice write_user} pld_name val
|
||||
Writes the user register.
|
||||
for FPGA @var{num} with value @var{val}.
|
||||
for FPGA @var{pld_name} with value @var{val}.
|
||||
@end deffn
|
||||
|
||||
@deffn {Command} {lattice set_preload} num length
|
||||
@deffn {Command} {lattice set_preload} pld_name length
|
||||
Set the length of the register for the preload. This is needed when the JTAG ID of the device is not known by openocd (newer NX devices).
|
||||
The load command for the FPGA @var{num} will use a length for the preload of @var{length}.
|
||||
The load command for the FPGA @var{pld_name} will use a length for the preload of @var{length}.
|
||||
@end deffn
|
||||
@end deffn
|
||||
|
||||
|
||||
@deffn {FPGA Driver} {efinix}
|
||||
@deffn {FPGA Driver} {efinix} [@option{-family} <name>]
|
||||
Both families (Trion and Titanium) sold by Efinix are supported as both use the same protocol for In-System Configuration.
|
||||
This driver can be used to load the bitstream into the FPGA.
|
||||
For the option @option{-family} @var{name} is one of @var{trion|titanium}.
|
||||
@end deffn
|
||||
|
||||
|
||||
@deffn {FPGA Driver} {intel} [@option{family}]
|
||||
@deffn {FPGA Driver} {intel} [@option{-family} <name>]
|
||||
This driver can be used to load the bitstream into Intel (former Altera) FPGAs.
|
||||
The families Cyclone III, Cyclone IV, Cyclone V, Cyclone 10, Arria II are supported.
|
||||
@c Arria V and Arria 10, MAX II, MAX V, MAX10)
|
||||
|
||||
The option @option{family} is one of @var{cycloneiii cycloneiv cyclonev cyclone10 arriaii}.
|
||||
For the option @option{-family} @var{name} is one of @var{cycloneiii cycloneiv cyclonev cyclone10 arriaii}.
|
||||
This is needed when the JTAG ID of the device is ambiguous (same ID is used for chips in different families).
|
||||
|
||||
As input file format the driver supports a '.rbf' (raw bitstream file) file. The '.rbf' file can be generated
|
||||
from a '.sof' file with @verb{|quartus_cpf -c blinker.sof blinker.rbf|}
|
||||
|
||||
Defines a new PLD device, an FPGA of the Cyclone III family, using the TAP named @verb{|cycloneiii.tap|}:
|
||||
Creates a new PLD device, an FPGA of the Cyclone III family, using the TAP named @verb{|cycloneiii.tap|}:
|
||||
@example
|
||||
pld device intel cycloneiii.tap cycloneiii
|
||||
pld create cycloneiii.pld intel -chain-position cycloneiii.tap -family cycloneiii
|
||||
@end example
|
||||
|
||||
@deffn {Command} {intel set_bscan} num len
|
||||
Set boundary scan register length of FPGA @var{num} to @var{len}. This is needed because the
|
||||
@deffn {Command} {intel set_bscan} pld_name len
|
||||
Set boundary scan register length of FPGA @var{pld_name} to @var{len}. This is needed because the
|
||||
length can vary between chips with the same JTAG ID.
|
||||
@end deffn
|
||||
|
||||
@deffn {Command} {intel set_check_pos} num pos
|
||||
@deffn {Command} {intel set_check_pos} pld_name pos
|
||||
Selects the position @var{pos} in the boundary-scan register. The bit at this
|
||||
position is checked after loading the bitstream and must be '1', which is the case when no error occurred.
|
||||
With a value of -1 for @var{pos} the check will be omitted.
|
||||
|
@ -8719,6 +8759,21 @@ With a value of -1 for @var{pos} the check will be omitted.
|
|||
This driver can be used to load the bitstream into FPGAs from Gowin.
|
||||
It is possible to program the SRAM. Programming the flash is not supported.
|
||||
The files @verb{|.fs|} and @verb{|.bin|} generated by Gowin FPGA Designer are supported.
|
||||
|
||||
@deffn {Command} {gowin read_status} pld_name
|
||||
Reads and displays the status register
|
||||
for FPGA @var{pld_name}.
|
||||
@end deffn
|
||||
|
||||
@deffn {Command} {gowin read_user} pld_name
|
||||
Reads and displays the user register
|
||||
for FPGA @var{pld_name}.
|
||||
@end deffn
|
||||
|
||||
@deffn {Command} {gowin reload} pld_name
|
||||
Load the bitstream from external memory for
|
||||
FPGA @var{pld_name}. A.k.a. refresh.
|
||||
@end deffn
|
||||
@end deffn
|
||||
|
||||
|
||||
|
@ -12022,7 +12077,7 @@ In a session using JTAG for its transport protocol, OpenOCD supports the functio
|
|||
of a JTAG-Host. The JTAG-Host is needed to connect the circuit over JTAG to the
|
||||
control-software. For more details see @url{http://ipdbg.org}.
|
||||
|
||||
@deffn {Command} {ipdbg} [@option{-start|-stop}] @option{-tap @var{tapname}} @option{-hub @var{ir_value} [@var{dr_length}]} [@option{-port @var{number}}] [@option{-tool @var{number}}] [@option{-vir [@var{vir_value} [@var{length} [@var{instr_code}]]]}]
|
||||
@deffn {Command} {ipdbg} [@option{-start|-stop}] @option{-tap @var{tapname}} @option{-hub @var{ir_value} [@var{dr_length}]} [@option{-vir [@var{vir_value} [@var{length} [@var{instr_code}]]]}] [@option{-port @var{number}}] [@option{-tool @var{number}}]
|
||||
Starts or stops a IPDBG JTAG-Host server. Arguments can be specified in any order.
|
||||
|
||||
Command options:
|
||||
|
@ -12031,15 +12086,28 @@ Command options:
|
|||
@item @option{-tap @var{tapname}} targeting the TAP @var{tapname}.
|
||||
@item @option{-hub @var{ir_value}} states that the JTAG hub is
|
||||
reachable with dr-scans while the JTAG instruction register has the value @var{ir_value}.
|
||||
@item @option{-port @var{number}} tcp port number where the JTAG-Host is listening.
|
||||
@item @option{-tool @var{number}} number of the tool/feature. These corresponds to the ports "data_(up/down)_(0..6)" at the JtagHub.
|
||||
@item @option{-vir [@var{vir_value} [@var{length} [@var{instr_code}]]]} On some devices, the user data-register is only reachable if there is a
|
||||
@item @option{-port @var{number}} tcp port number where the JTAG-Host will listen. The default is 4242 which is used when the option is not given.
|
||||
@item @option{-tool @var{number}} number of the tool/feature. These corresponds to the ports "data_(up/down)_(0..6)" at the JtagHub. The default is 1 which is used when the option is not given.
|
||||
@item @option{-vir [@var{vir_value} [@var{length} [@var{instr_code}]]]} On some devices, the user data-register is reachable if there is a
|
||||
specific value in a second dr. This second dr is called vir (virtual ir). With this parameter given, the IPDBG satisfies this condition prior an
|
||||
access to the IPDBG-Hub. The value shifted into the vir is given by the first parameter @var{vir_value} (default: 0x11). The second
|
||||
parameter @var{length} is the length of the vir data register (default: 5). With the @var{instr_code} (default: 0x00e) parameter the ir value to
|
||||
shift data through vir can be configured.
|
||||
@end itemize
|
||||
@end deffn
|
||||
or
|
||||
@deffn {Command} {ipdbg} [@option{-start|-stop}] @option{-pld @var{name} [@var{user}]} [@option{-port @var{number}}] [@option{-tool @var{number}}]
|
||||
Also starts or stops a IPDBG JTAG-Host server. The pld drivers are able to provide the tap and hub/IR for the IPDBG JTAG-Host server.
|
||||
With the @option{-pld @var{name} [@var{user}]} the information from the pld-driver is used and the options @option{-tap} and @option{-hub} are not required.
|
||||
The defined driver for the pld @var{name} gets selected. (The pld devices names can be shown by the command @command{pld devices}).
|
||||
|
||||
The @verb{|USERx|} instructions are vendor specific and don't change between families of the same vendor.
|
||||
So if there's a pld driver for your vendor it should work with your FPGA even when the driver is not compatible with your device for the remaining features. If your device/vendor is not supported you have to use the previous command.
|
||||
|
||||
With [@var{user}] one can select a different @verb{|USERx|}-Instruction. If the IPDBG JTAG-Hub is used without modification the default value of 1 which selects the first @verb{|USERx|} instruction is adequate.
|
||||
|
||||
The remaining options are described in the previous command.
|
||||
@end deffn
|
||||
|
||||
Examples:
|
||||
@example
|
||||
|
@ -12054,6 +12122,13 @@ ipdbg -start -tap 10m50.tap -hub 0x00C -vir -port 60000 -tool 1
|
|||
Starts a server listening on tcp-port 60000 which connects to tool 1 (data_up_1/data_down_1).
|
||||
The connection is through the TAP of a Intel MAX10 virtual jtag component (sld_instance_index is 0; sld_ir_width is smaller than 5).
|
||||
|
||||
@example
|
||||
ipdbg -start -pld xc7.pld -port 5555 -tool 0
|
||||
@end example
|
||||
Starts a server listening on tcp-port 5555 which connects to tool 0 (data_up_0/data_down_0).
|
||||
The TAP and ir value used to reach the JTAG Hub is given by the pld driver.
|
||||
|
||||
|
||||
@node Utility Commands
|
||||
@chapter Utility Commands
|
||||
@cindex Utility Commands
|
||||
|
|
|
@ -0,0 +1,68 @@
|
|||
# SPDX-License-Identifier: GPL-2.0-or-later OR GFDL-1.2-no-invariants-or-later
|
||||
|
||||
Bus 001 Device 056: ID 584e:424e NanoXplore, SAS. ANGIE Adapter
|
||||
Device Descriptor:
|
||||
bLength 18
|
||||
bDescriptorType 1
|
||||
bcdUSB 2.00
|
||||
bDeviceClass 255 Vendor Specific Class
|
||||
bDeviceSubClass 255 Vendor Specific Subclass
|
||||
bDeviceProtocol 255 Vendor Specific Protocol
|
||||
bMaxPacketSize0 64
|
||||
idVendor 0x584e
|
||||
idProduct 0x424e
|
||||
bcdDevice 0.00
|
||||
iManufacturer 1 NanoXplore, SAS.
|
||||
iProduct 2 ANGIE Adapter
|
||||
iSerial 3 000001
|
||||
bNumConfigurations 1
|
||||
Configuration Descriptor:
|
||||
bLength 9
|
||||
bDescriptorType 2
|
||||
wTotalLength 0x0027
|
||||
bNumInterfaces 1
|
||||
bConfigurationValue 1
|
||||
iConfiguration 4 (error)
|
||||
bmAttributes 0x80
|
||||
(Bus Powered)
|
||||
MaxPower 100mA
|
||||
Interface Descriptor:
|
||||
bLength 9
|
||||
bDescriptorType 4
|
||||
bInterfaceNumber 0
|
||||
bAlternateSetting 0
|
||||
bNumEndpoints 3
|
||||
bInterfaceClass 255 Vendor Specific Class
|
||||
bInterfaceSubClass 255 Vendor Specific Subclass
|
||||
bInterfaceProtocol 255 Vendor Specific Protocol
|
||||
iInterface 0
|
||||
Endpoint Descriptor:
|
||||
bLength 7
|
||||
bDescriptorType 5
|
||||
bEndpointAddress 0x01 EP 1 OUT
|
||||
bmAttributes 2
|
||||
Transfer Type Bulk
|
||||
Synch Type None
|
||||
Usage Type Data
|
||||
wMaxPacketSize 0x0040 1x 64 bytes
|
||||
bInterval 0
|
||||
Endpoint Descriptor:
|
||||
bLength 7
|
||||
bDescriptorType 5
|
||||
bEndpointAddress 0x81 EP 1 IN
|
||||
bmAttributes 2
|
||||
Transfer Type Bulk
|
||||
Synch Type None
|
||||
Usage Type Data
|
||||
wMaxPacketSize 0x0040 1x 64 bytes
|
||||
bInterval 0
|
||||
Endpoint Descriptor:
|
||||
bLength 7
|
||||
bDescriptorType 5
|
||||
bEndpointAddress 0x02 EP 2 OUT
|
||||
bmAttributes 2
|
||||
Transfer Type Bulk
|
||||
Synch Type None
|
||||
Usage Type Data
|
||||
wMaxPacketSize 0x0200 1x 512 bytes
|
||||
bInterval 0
|
|
@ -0,0 +1,71 @@
|
|||
# SPDX-License-Identifier: GPL-2.0-or-later OR GFDL-1.2-no-invariants-or-later
|
||||
|
||||
# STLINK-V3PWR standalone in firmware update mode
|
||||
|
||||
Bus 003 Device 054: ID 0483:3755 STMicroelectronics USB2.0 Hub
|
||||
Device Descriptor:
|
||||
bLength 18
|
||||
bDescriptorType 1
|
||||
bcdUSB 2.00
|
||||
bDeviceClass 0
|
||||
bDeviceSubClass 0
|
||||
bDeviceProtocol 0
|
||||
bMaxPacketSize0 64
|
||||
idVendor 0x0483 STMicroelectronics
|
||||
idProduct 0x3755
|
||||
bcdDevice 1.00
|
||||
iManufacturer 1 STMicroelectronics
|
||||
iProduct 2 STLINK-V3PWR
|
||||
iSerial 3 123456780000
|
||||
bNumConfigurations 1
|
||||
Configuration Descriptor:
|
||||
bLength 9
|
||||
bDescriptorType 2
|
||||
wTotalLength 0x0020
|
||||
bNumInterfaces 1
|
||||
bConfigurationValue 1
|
||||
iConfiguration 4 DFU Config
|
||||
bmAttributes 0x80
|
||||
(Bus Powered)
|
||||
MaxPower 100mA
|
||||
Interface Descriptor:
|
||||
bLength 9
|
||||
bDescriptorType 4
|
||||
bInterfaceNumber 0
|
||||
bAlternateSetting 0
|
||||
bNumEndpoints 2
|
||||
bInterfaceClass 255 Vendor Specific Class
|
||||
bInterfaceSubClass 255 Vendor Specific Subclass
|
||||
bInterfaceProtocol 255 Vendor Specific Protocol
|
||||
iInterface 5 ST-Link Usbloader
|
||||
Endpoint Descriptor:
|
||||
bLength 7
|
||||
bDescriptorType 5
|
||||
bEndpointAddress 0x81 EP 1 IN
|
||||
bmAttributes 2
|
||||
Transfer Type Bulk
|
||||
Synch Type None
|
||||
Usage Type Data
|
||||
wMaxPacketSize 0x0200 1x 512 bytes
|
||||
bInterval 0
|
||||
Endpoint Descriptor:
|
||||
bLength 7
|
||||
bDescriptorType 5
|
||||
bEndpointAddress 0x01 EP 1 OUT
|
||||
bmAttributes 2
|
||||
Transfer Type Bulk
|
||||
Synch Type None
|
||||
Usage Type Data
|
||||
wMaxPacketSize 0x0200 1x 512 bytes
|
||||
bInterval 0
|
||||
Device Qualifier (for other device speed):
|
||||
bLength 10
|
||||
bDescriptorType 6
|
||||
bcdUSB 2.00
|
||||
bDeviceClass 0
|
||||
bDeviceSubClass 0
|
||||
bDeviceProtocol 0
|
||||
bMaxPacketSize0 64
|
||||
bNumConfigurations 1
|
||||
Device Status: 0x0000
|
||||
(Bus Powered)
|
|
@ -0,0 +1,253 @@
|
|||
# SPDX-License-Identifier: GPL-2.0-or-later OR GFDL-1.2-no-invariants-or-later
|
||||
|
||||
# STLINK-V3PWR standalone
|
||||
|
||||
Bus 003 Device 053: ID 0483:3757 STMicroelectronics USB2.0 Hub
|
||||
Device Descriptor:
|
||||
bLength 18
|
||||
bDescriptorType 1
|
||||
bcdUSB 2.00
|
||||
bDeviceClass 239 Miscellaneous Device
|
||||
bDeviceSubClass 2
|
||||
bDeviceProtocol 1 Interface Association
|
||||
bMaxPacketSize0 64
|
||||
idVendor 0x0483 STMicroelectronics
|
||||
idProduct 0x3757
|
||||
bcdDevice 1.00
|
||||
iManufacturer 1 STMicroelectronics
|
||||
iProduct 2 STLINK-V3PWR
|
||||
iSerial 3 123456780000
|
||||
bNumConfigurations 1
|
||||
Configuration Descriptor:
|
||||
bLength 9
|
||||
bDescriptorType 2
|
||||
wTotalLength 0x00c2
|
||||
bNumInterfaces 6
|
||||
bConfigurationValue 1
|
||||
iConfiguration 4 Default Config
|
||||
bmAttributes 0x80
|
||||
(Bus Powered)
|
||||
MaxPower 500mA
|
||||
Interface Descriptor:
|
||||
bLength 9
|
||||
bDescriptorType 4
|
||||
bInterfaceNumber 0
|
||||
bAlternateSetting 0
|
||||
bNumEndpoints 3
|
||||
bInterfaceClass 255 Vendor Specific Class
|
||||
bInterfaceSubClass 255 Vendor Specific Subclass
|
||||
bInterfaceProtocol 255 Vendor Specific Protocol
|
||||
iInterface 5 ST-Link Debug
|
||||
Endpoint Descriptor:
|
||||
bLength 7
|
||||
bDescriptorType 5
|
||||
bEndpointAddress 0x81 EP 1 IN
|
||||
bmAttributes 2
|
||||
Transfer Type Bulk
|
||||
Synch Type None
|
||||
Usage Type Data
|
||||
wMaxPacketSize 0x0200 1x 512 bytes
|
||||
bInterval 0
|
||||
Endpoint Descriptor:
|
||||
bLength 7
|
||||
bDescriptorType 5
|
||||
bEndpointAddress 0x01 EP 1 OUT
|
||||
bmAttributes 2
|
||||
Transfer Type Bulk
|
||||
Synch Type None
|
||||
Usage Type Data
|
||||
wMaxPacketSize 0x0200 1x 512 bytes
|
||||
bInterval 0
|
||||
Endpoint Descriptor:
|
||||
bLength 7
|
||||
bDescriptorType 5
|
||||
bEndpointAddress 0x82 EP 2 IN
|
||||
bmAttributes 2
|
||||
Transfer Type Bulk
|
||||
Synch Type None
|
||||
Usage Type Data
|
||||
wMaxPacketSize 0x0200 1x 512 bytes
|
||||
bInterval 0
|
||||
Interface Association:
|
||||
bLength 8
|
||||
bDescriptorType 11
|
||||
bFirstInterface 1
|
||||
bInterfaceCount 2
|
||||
bFunctionClass 2 Communications
|
||||
bFunctionSubClass 2 Abstract (modem)
|
||||
bFunctionProtocol 1 AT-commands (v.25ter)
|
||||
iFunction 6 ST-Link VCP Ctrl
|
||||
Interface Descriptor:
|
||||
bLength 9
|
||||
bDescriptorType 4
|
||||
bInterfaceNumber 1
|
||||
bAlternateSetting 0
|
||||
bNumEndpoints 1
|
||||
bInterfaceClass 2 Communications
|
||||
bInterfaceSubClass 2 Abstract (modem)
|
||||
bInterfaceProtocol 1 AT-commands (v.25ter)
|
||||
iInterface 6 ST-Link VCP Ctrl
|
||||
CDC Header:
|
||||
bcdCDC 1.10
|
||||
CDC Call Management:
|
||||
bmCapabilities 0x00
|
||||
bDataInterface 2
|
||||
CDC ACM:
|
||||
bmCapabilities 0x06
|
||||
sends break
|
||||
line coding and serial state
|
||||
CDC Union:
|
||||
bMasterInterface 1
|
||||
bSlaveInterface 2
|
||||
Endpoint Descriptor:
|
||||
bLength 7
|
||||
bDescriptorType 5
|
||||
bEndpointAddress 0x84 EP 4 IN
|
||||
bmAttributes 3
|
||||
Transfer Type Interrupt
|
||||
Synch Type None
|
||||
Usage Type Data
|
||||
wMaxPacketSize 0x000a 1x 10 bytes
|
||||
bInterval 16
|
||||
Interface Descriptor:
|
||||
bLength 9
|
||||
bDescriptorType 4
|
||||
bInterfaceNumber 2
|
||||
bAlternateSetting 0
|
||||
bNumEndpoints 2
|
||||
bInterfaceClass 10 CDC Data
|
||||
bInterfaceSubClass 0
|
||||
bInterfaceProtocol 0
|
||||
iInterface 7 ST-Link VCP Data
|
||||
Endpoint Descriptor:
|
||||
bLength 7
|
||||
bDescriptorType 5
|
||||
bEndpointAddress 0x05 EP 5 OUT
|
||||
bmAttributes 2
|
||||
Transfer Type Bulk
|
||||
Synch Type None
|
||||
Usage Type Data
|
||||
wMaxPacketSize 0x0200 1x 512 bytes
|
||||
bInterval 0
|
||||
Endpoint Descriptor:
|
||||
bLength 7
|
||||
bDescriptorType 5
|
||||
bEndpointAddress 0x85 EP 5 IN
|
||||
bmAttributes 2
|
||||
Transfer Type Bulk
|
||||
Synch Type None
|
||||
Usage Type Data
|
||||
wMaxPacketSize 0x0200 1x 512 bytes
|
||||
bInterval 0
|
||||
Interface Descriptor:
|
||||
bLength 9
|
||||
bDescriptorType 4
|
||||
bInterfaceNumber 3
|
||||
bAlternateSetting 0
|
||||
bNumEndpoints 2
|
||||
bInterfaceClass 255 Vendor Specific Class
|
||||
bInterfaceSubClass 255 Vendor Specific Subclass
|
||||
bInterfaceProtocol 255 Vendor Specific Protocol
|
||||
iInterface 8 ST-Link Bridge
|
||||
Endpoint Descriptor:
|
||||
bLength 7
|
||||
bDescriptorType 5
|
||||
bEndpointAddress 0x86 EP 6 IN
|
||||
bmAttributes 2
|
||||
Transfer Type Bulk
|
||||
Synch Type None
|
||||
Usage Type Data
|
||||
wMaxPacketSize 0x0200 1x 512 bytes
|
||||
bInterval 0
|
||||
Endpoint Descriptor:
|
||||
bLength 7
|
||||
bDescriptorType 5
|
||||
bEndpointAddress 0x06 EP 6 OUT
|
||||
bmAttributes 2
|
||||
Transfer Type Bulk
|
||||
Synch Type None
|
||||
Usage Type Data
|
||||
wMaxPacketSize 0x0200 1x 512 bytes
|
||||
bInterval 0
|
||||
Interface Association:
|
||||
bLength 8
|
||||
bDescriptorType 11
|
||||
bFirstInterface 4
|
||||
bInterfaceCount 2
|
||||
bFunctionClass 2 Communications
|
||||
bFunctionSubClass 2 Abstract (modem)
|
||||
bFunctionProtocol 1 AT-commands (v.25ter)
|
||||
iFunction 9 ST-Link VCP-PWR Ctrl
|
||||
Interface Descriptor:
|
||||
bLength 9
|
||||
bDescriptorType 4
|
||||
bInterfaceNumber 4
|
||||
bAlternateSetting 0
|
||||
bNumEndpoints 1
|
||||
bInterfaceClass 2 Communications
|
||||
bInterfaceSubClass 2 Abstract (modem)
|
||||
bInterfaceProtocol 1 AT-commands (v.25ter)
|
||||
iInterface 9 ST-Link VCP-PWR Ctrl
|
||||
CDC Header:
|
||||
bcdCDC 1.10
|
||||
CDC Call Management:
|
||||
bmCapabilities 0x00
|
||||
bDataInterface 5
|
||||
CDC ACM:
|
||||
bmCapabilities 0x06
|
||||
sends break
|
||||
line coding and serial state
|
||||
CDC Union:
|
||||
bMasterInterface 4
|
||||
bSlaveInterface 5
|
||||
Endpoint Descriptor:
|
||||
bLength 7
|
||||
bDescriptorType 5
|
||||
bEndpointAddress 0x87 EP 7 IN
|
||||
bmAttributes 3
|
||||
Transfer Type Interrupt
|
||||
Synch Type None
|
||||
Usage Type Data
|
||||
wMaxPacketSize 0x000a 1x 10 bytes
|
||||
bInterval 16
|
||||
Interface Descriptor:
|
||||
bLength 9
|
||||
bDescriptorType 4
|
||||
bInterfaceNumber 5
|
||||
bAlternateSetting 0
|
||||
bNumEndpoints 2
|
||||
bInterfaceClass 10 CDC Data
|
||||
bInterfaceSubClass 0
|
||||
bInterfaceProtocol 0
|
||||
iInterface 10 ST-Link VCP-PWR Data
|
||||
Endpoint Descriptor:
|
||||
bLength 7
|
||||
bDescriptorType 5
|
||||
bEndpointAddress 0x03 EP 3 OUT
|
||||
bmAttributes 2
|
||||
Transfer Type Bulk
|
||||
Synch Type None
|
||||
Usage Type Data
|
||||
wMaxPacketSize 0x0200 1x 512 bytes
|
||||
bInterval 0
|
||||
Endpoint Descriptor:
|
||||
bLength 7
|
||||
bDescriptorType 5
|
||||
bEndpointAddress 0x83 EP 3 IN
|
||||
bmAttributes 2
|
||||
Transfer Type Bulk
|
||||
Synch Type None
|
||||
Usage Type Data
|
||||
wMaxPacketSize 0x0200 1x 512 bytes
|
||||
bInterval 0
|
||||
Device Qualifier (for other device speed):
|
||||
bLength 10
|
||||
bDescriptorType 6
|
||||
bcdUSB 2.00
|
||||
bDeviceClass 0
|
||||
bDeviceSubClass 0
|
||||
bDeviceProtocol 0
|
||||
bMaxPacketSize0 64
|
||||
bNumConfigurations 1
|
||||
Device Status: 0x0000
|
||||
(Bus Powered)
|
|
@ -251,18 +251,6 @@ static int efm32x_read_info(struct flash_bank *bank)
|
|||
|
||||
memset(efm32_info, 0, sizeof(struct efm32_info));
|
||||
|
||||
const struct cortex_m_common *cortex_m = target_to_cm(bank->target);
|
||||
|
||||
switch (cortex_m->core_info->partno) {
|
||||
case CORTEX_M3_PARTNO:
|
||||
case CORTEX_M4_PARTNO:
|
||||
case CORTEX_M0P_PARTNO:
|
||||
break;
|
||||
default:
|
||||
LOG_ERROR("Target is not Cortex-Mx Device");
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
|
||||
ret = efm32x_get_flash_size(bank, &(efm32_info->flash_sz_kib));
|
||||
if (ret != ERROR_OK)
|
||||
return ret;
|
||||
|
|
|
@ -171,6 +171,7 @@ const struct flash_device flash_devices[] = {
|
|||
FLASH_ID("xtx xt25q32b", 0x03, 0x0b, 0x02, 0xd8, 0xc7, 0x0016600b, 0x100, 0x10000, 0x400000), /* exists ? */
|
||||
FLASH_ID("xtx xt25q64b", 0x03, 0x0b, 0x02, 0xd8, 0xc7, 0x0017600b, 0x100, 0x10000, 0x800000),
|
||||
FLASH_ID("xtx xt25q128b", 0x03, 0x0b, 0x02, 0xd8, 0xc7, 0x0018600b, 0x100, 0x10000, 0x1000000),
|
||||
FLASH_ID("zetta zd25q16", 0x03, 0x00, 0x02, 0xd8, 0xc7, 0x001560ba, 0x100, 0x10000, 0x200000),
|
||||
|
||||
/* FRAM, no erase commands, no write page or sectors */
|
||||
FRAM_ID("fu mb85rs16n", 0x03, 0, 0x02, 0x00010104, 0x800),
|
||||
|
|
|
@ -743,7 +743,7 @@ static int stm32x_get_property_addr(struct target *target, struct stm32x_propert
|
|||
return ERROR_TARGET_NOT_EXAMINED;
|
||||
}
|
||||
|
||||
switch (cortex_m_get_partno_safe(target)) {
|
||||
switch (cortex_m_get_impl_part(target)) {
|
||||
case CORTEX_M0_PARTNO: /* STM32F0x devices */
|
||||
addr->device_id = 0x40015800;
|
||||
addr->flash_size = 0x1FFFF7CC;
|
||||
|
|
|
@ -961,7 +961,7 @@ static int stm32x_get_device_id(struct flash_bank *bank, uint32_t *device_id)
|
|||
return retval;
|
||||
|
||||
if ((*device_id & 0xfff) == 0x411
|
||||
&& cortex_m_get_partno_safe(target) == CORTEX_M4_PARTNO) {
|
||||
&& cortex_m_get_impl_part(target) == CORTEX_M4_PARTNO) {
|
||||
*device_id &= ~((0xFFFF << 16) | 0xfff);
|
||||
*device_id |= (0x1000 << 16) | 0x413;
|
||||
LOG_INFO("stm32f4x errata detected - fixing incorrect MCU_IDCODE");
|
||||
|
|
|
@ -795,7 +795,7 @@ static int stm32x_probe(struct flash_bank *bank)
|
|||
/* STM32H74x/H75x, the second core (Cortex-M4) cannot read the flash size */
|
||||
retval = ERROR_FAIL;
|
||||
if (device_id == DEVID_STM32H74_H75XX
|
||||
&& cortex_m_get_partno_safe(target) == CORTEX_M4_PARTNO)
|
||||
&& cortex_m_get_impl_part(target) == CORTEX_M4_PARTNO)
|
||||
LOG_WARNING("%s cannot read the flash size register", target_name(target));
|
||||
else
|
||||
retval = target_read_u16(target, stm32x_info->part_info->fsize_addr, &flash_size_in_kb);
|
||||
|
|
|
@ -326,6 +326,7 @@ static const struct stm32l4_rev stm32g47_g48xx_revs[] = {
|
|||
|
||||
static const struct stm32l4_rev stm32l4r_l4sxx_revs[] = {
|
||||
{ 0x1000, "A" }, { 0x1001, "Z" }, { 0x1003, "Y" }, { 0x100F, "W" },
|
||||
{ 0x101F, "V" },
|
||||
};
|
||||
|
||||
static const struct stm32l4_rev stm32l4p_l4qxx_revs[] = {
|
||||
|
@ -1681,7 +1682,7 @@ static int stm32l4_read_idcode(struct flash_bank *bank, uint32_t *id)
|
|||
|
||||
/* CPU2 (Cortex-M0+) is supported only with non-hla adapters because it is on AP1.
|
||||
* Using HLA adapters armv7m.debug_ap is null, and checking ap_num triggers a segfault */
|
||||
if (cortex_m_get_partno_safe(target) == CORTEX_M0P_PARTNO &&
|
||||
if (cortex_m_get_impl_part(target) == CORTEX_M0P_PARTNO &&
|
||||
armv7m->debug_ap && armv7m->debug_ap->ap_num == 1) {
|
||||
uint32_t uid64_ids;
|
||||
|
||||
|
|
|
@ -8,7 +8,9 @@
|
|||
* identification code list, please visit the JEDEC website at www.jedec.org .
|
||||
*/
|
||||
|
||||
/* This file is aligned to revision JEP106BF.01 October 2022. */
|
||||
/* This file is aligned to revision JEP106BG May 2023. */
|
||||
|
||||
/* "NXP (Philips)" is reported below, while missing in JEP106BG */
|
||||
|
||||
[0][0x01 - 1] = "AMD",
|
||||
[0][0x02 - 1] = "AMI",
|
||||
|
@ -86,7 +88,7 @@
|
|||
[0][0x4a - 1] = "Compaq",
|
||||
[0][0x4b - 1] = "Protocol Engines",
|
||||
[0][0x4c - 1] = "SCI",
|
||||
[0][0x4d - 1] = "Seiko Instruments",
|
||||
[0][0x4d - 1] = "ABLIC",
|
||||
[0][0x4e - 1] = "Samsung",
|
||||
[0][0x4f - 1] = "I3 Design System",
|
||||
[0][0x50 - 1] = "Klic",
|
||||
|
@ -972,7 +974,7 @@
|
|||
[7][0x4e - 1] = "Mustang",
|
||||
[7][0x4f - 1] = "Orca Systems",
|
||||
[7][0x50 - 1] = "Passif Semiconductor",
|
||||
[7][0x51 - 1] = "GigaDevice Semiconductor (Beijing) Inc",
|
||||
[7][0x51 - 1] = "GigaDevice Semiconductor (Beijing)",
|
||||
[7][0x52 - 1] = "Memphis Electronic",
|
||||
[7][0x53 - 1] = "Beckhoff Automation GmbH",
|
||||
[7][0x54 - 1] = "Harmony Semiconductor Corp",
|
||||
|
@ -1786,4 +1788,57 @@
|
|||
[14][0x0a - 1] = "UltraRISC Technology (Shanghai) Co Ltd",
|
||||
[14][0x0b - 1] = "Shenzhen Jing Da Kang Technology Co Ltd",
|
||||
[14][0x0c - 1] = "Hangzhou Hongjun Microelectronics Co Ltd",
|
||||
[14][0x0d - 1] = "Pliops Ltd",
|
||||
[14][0x0e - 1] = "Cix Technology (Shanghai) Co Ltd",
|
||||
[14][0x0f - 1] = "TeraDevices Inc",
|
||||
[14][0x10 - 1] = "SpacemiT (Hangzhou)Technology Co Ltd",
|
||||
[14][0x11 - 1] = "InnoPhase loT Inc",
|
||||
[14][0x12 - 1] = "InnoPhase loT Inc",
|
||||
[14][0x13 - 1] = "Yunhight Microelectronics",
|
||||
[14][0x14 - 1] = "Samnix",
|
||||
[14][0x15 - 1] = "HKC Storage Co Ltd",
|
||||
[14][0x16 - 1] = "Chiplego Technology (Shanghai) Co Ltd",
|
||||
[14][0x17 - 1] = "StoreSkill",
|
||||
[14][0x18 - 1] = "Shenzhen Astou Technology Company",
|
||||
[14][0x19 - 1] = "Guangdong LeafFive Technology Limited",
|
||||
[14][0x1a - 1] = "Jin JuQuan",
|
||||
[14][0x1b - 1] = "Huaxuan Technology (Shenzhen) Co Ltd",
|
||||
[14][0x1c - 1] = "Gigastone Corporation",
|
||||
[14][0x1d - 1] = "Kinsotin",
|
||||
[14][0x1e - 1] = "PengYing",
|
||||
[14][0x1f - 1] = "Shenzhen Xunhi Technology Co Ltd",
|
||||
[14][0x20 - 1] = "FOXX Storage Inc",
|
||||
[14][0x21 - 1] = "Shanghai Belling Corporation Ltd",
|
||||
[14][0x22 - 1] = "Glenfy Tech Co Ltd",
|
||||
[14][0x23 - 1] = "Sahasra Semiconductors Pvt Ltd",
|
||||
[14][0x24 - 1] = "Chongqing SeekWave Technology Co Ltd",
|
||||
[14][0x25 - 1] = "Shenzhen Zhixing Intelligent Manufacturing",
|
||||
[14][0x26 - 1] = "Ethernovia",
|
||||
[14][0x27 - 1] = "Shenzhen Xinrongda Technology Co Ltd",
|
||||
[14][0x28 - 1] = "Hangzhou Clounix Technology Limited",
|
||||
[14][0x29 - 1] = "JGINYUE",
|
||||
[14][0x2a - 1] = "Shenzhen Xinwei Semiconductor Co Ltd",
|
||||
[14][0x2b - 1] = "COLORFIRE Technology Co Ltd",
|
||||
[14][0x2c - 1] = "B LKE",
|
||||
[14][0x2d - 1] = "ZHUDIAN",
|
||||
[14][0x2e - 1] = "REECHO",
|
||||
[14][0x2f - 1] = "Enphase Energy Inc",
|
||||
[14][0x30 - 1] = "Shenzhen Yingrui Storage Technology Co Ltd",
|
||||
[14][0x31 - 1] = "Shenzhen Sinomos Semiconductor Technology",
|
||||
[14][0x32 - 1] = "O2micro International Limited",
|
||||
[14][0x33 - 1] = "Axelera AI BV",
|
||||
[14][0x34 - 1] = "Silicon Legend Technology (Suzhou) Co Ltd",
|
||||
[14][0x35 - 1] = "Suzhou Novosense Microelectronics Co Ltd",
|
||||
[14][0x36 - 1] = "Pirateman",
|
||||
[14][0x37 - 1] = "Yangtze MasonSemi",
|
||||
[14][0x38 - 1] = "Shanghai Yunsilicon Technology Co Ltd",
|
||||
[14][0x39 - 1] = "Rayson",
|
||||
[14][0x3a - 1] = "Alphawave IP",
|
||||
[14][0x3b - 1] = "Shenzhen Visions Chip Electronic Technology",
|
||||
[14][0x3c - 1] = "KYO Group",
|
||||
[14][0x3d - 1] = "Shenzhen Aboison Technology Co Ltd",
|
||||
[14][0x3e - 1] = "Shenzhen JingSheng Semiconducto Co Ltd",
|
||||
[14][0x3f - 1] = "Shenzhen Dingsheng Technology Co Ltd",
|
||||
[14][0x40 - 1] = "EVAS Intelligence Co Ltd",
|
||||
[14][0x41 - 1] = "Kaibright Electronic Technologies",
|
||||
/* EOF */
|
||||
|
|
|
@ -10,8 +10,10 @@ noinst_LTLIBRARIES += %D%/libocdjtagdrivers.la
|
|||
%C%_libocdjtagdrivers_la_CPPFLAGS = $(AM_CPPFLAGS)
|
||||
|
||||
ULINK_FIRMWARE = %D%/OpenULINK
|
||||
ANGIE_FILES = %D%/angie
|
||||
|
||||
EXTRA_DIST += $(ULINK_FIRMWARE) \
|
||||
$(ANGIE_FILES) \
|
||||
%D%/usb_blaster/README.CheapClone \
|
||||
%D%/Makefile.rlink \
|
||||
%D%/rlink_call.m4 \
|
||||
|
@ -123,6 +125,12 @@ ulinkdir = $(pkgdatadir)/OpenULINK
|
|||
dist_ulink_DATA = $(ULINK_FIRMWARE)/ulink_firmware.hex
|
||||
%C%_libocdjtagdrivers_la_LIBADD += -lm
|
||||
endif
|
||||
if ANGIE
|
||||
DRIVERFILES += %D%/angie.c
|
||||
angiedir = $(pkgdatadir)/angie
|
||||
dist_angie_DATA = $(ANGIE_FILES)/angie_firmware.bin $(ANGIE_FILES)/angie_bitstream.bit
|
||||
%C%_libocdjtagdrivers_la_LIBADD += -lm
|
||||
endif
|
||||
if VSLLINK
|
||||
DRIVERFILES += %D%/versaloon/usbtoxxx/usbtogpio.c
|
||||
DRIVERFILES += %D%/versaloon/usbtoxxx/usbtojtagraw.c
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,3 @@
|
|||
This folder contain only the files needed by ANGIE's driver.
|
||||
You will find the complete ANGIE's firmware and the bitstream's code source in
|
||||
contrib/firmware.
|
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1,172 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
****************************************************************************
|
||||
File : msgtypes.h *
|
||||
Contents : Definition of the commands supported by NanoXplore *
|
||||
USB-JTAG ANGIE adapter hardware. *
|
||||
Based on openULINK project code by: Martin Schmoelzer. *
|
||||
Copyright 2023, Ahmed Errached BOUDJELIDA, NanoXplore SAS. *
|
||||
<aboudjelida@nanoxplore.com> *
|
||||
<ahmederrachedbjld@gmail.com> *
|
||||
*****************************************************************************/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Definition of the commands supported by the ANGIE firmware.
|
||||
*
|
||||
* Basically, two types of commands can be distinguished:
|
||||
* - Commands with fixed payload size
|
||||
* - Commands with variable payload size
|
||||
*
|
||||
* SCAN commands (in all variations) carry payloads of variable size, all
|
||||
* other commands carry payloads of fixed size.
|
||||
*
|
||||
* In the case of SCAN commands, the payload size (n) is calculated by
|
||||
* dividing the scan_size_bits variable by 8, rounding up the result.
|
||||
*
|
||||
* Offset zero always contains the command ID.
|
||||
*
|
||||
****************************************************************************
|
||||
* CMD_SCAN_IN, CMD_SLOW_SCAN_IN: *
|
||||
* *
|
||||
* OUT: *
|
||||
* offset 1: scan_size_bytes *
|
||||
* offset 2: bits_last_byte *
|
||||
* offset 3: tms_count_start + tms_count_end *
|
||||
* offset 4: tms_sequence_start *
|
||||
* offset 5: tms_sequence_end *
|
||||
* *
|
||||
* IN: *
|
||||
* offset 0..n: TDO data *
|
||||
****************************************************************************
|
||||
* CMD_SCAN_OUT, CMD_SLOW_SCAN_OUT: *
|
||||
* *
|
||||
* OUT: *
|
||||
* offset 1: scan_size_bytes *
|
||||
* offset 2: bits_last_byte *
|
||||
* offset 3: tms_count_start + tms_count_end *
|
||||
* offset 4: tms_sequence_start *
|
||||
* offset 5: tms_sequence_end *
|
||||
* offset 6..x: TDI data *
|
||||
****************************************************************************
|
||||
* CMD_SCAN_IO, CMD_SLOW_SCAN_IO: *
|
||||
* *
|
||||
* OUT: *
|
||||
* offset 1: scan_size_bytes *
|
||||
* offset 2: bits_last_byte *
|
||||
* offset 3: tms_count_start + tms_count_end *
|
||||
* offset 4: tms_sequence_start *
|
||||
* offset 5: tms_sequence_end *
|
||||
* offset 6..x: TDI data *
|
||||
* *
|
||||
* IN: *
|
||||
* offset 0..n: TDO data *
|
||||
****************************************************************************
|
||||
* CMD_CLOCK_TMS, CMD_SLOW_CLOCK_TMS: *
|
||||
* *
|
||||
* OUT: *
|
||||
* offset 1: tms_count *
|
||||
* offset 2: tms_sequence *
|
||||
****************************************************************************
|
||||
* CMD_CLOCK_TCK, CMD_SLOW_CLOCK_TCK: *
|
||||
* *
|
||||
* OUT: *
|
||||
* offset 1: low byte of tck_count *
|
||||
* offset 2: high byte of tck_count *
|
||||
****************************************************************************
|
||||
* CMD_CLOCK_SLEEP_US: *
|
||||
* *
|
||||
* OUT: *
|
||||
* offset 1: low byte of sleep_us *
|
||||
* offset 2: high byte of sleep_us *
|
||||
****************************************************************************
|
||||
* CMD_CLOCK_SLEEP_MS: *
|
||||
* *
|
||||
* OUT: *
|
||||
* offset 1: low byte of sleep_ms *
|
||||
* offset 2: high byte of sleep_ms *
|
||||
****************************************************************************
|
||||
* CMD_GET_SIGNALS: *
|
||||
* *
|
||||
* IN: *
|
||||
* offset 0: current state of input signals *
|
||||
* offset 1: current state of output signals *
|
||||
****************************************************************************
|
||||
* CMD_SET_SIGNALS: *
|
||||
* *
|
||||
* OUT: *
|
||||
* offset 1: signals that should be de-asserted *
|
||||
* offset 2: signals that should be asserted *
|
||||
****************************************************************************
|
||||
* CMD_CONFIGURE_TCK_FREQ: *
|
||||
* *
|
||||
* OUT: *
|
||||
* offset 1: delay value for scan_in function *
|
||||
* offset 2: delay value for scan_out function *
|
||||
* offset 3: delay value for scan_io function *
|
||||
* offset 4: delay value for clock_tck function *
|
||||
* offset 5: delay value for clock_tms function *
|
||||
****************************************************************************
|
||||
* CMD_SET_LEDS: *
|
||||
* *
|
||||
* OUT: *
|
||||
* offset 1: LED states: *
|
||||
* Bit 0: turn COM LED on *
|
||||
* Bit 1: turn RUN LED on *
|
||||
* Bit 2: turn COM LED off *
|
||||
* Bit 3: turn RUN LED off *
|
||||
* Bits 7..4: Reserved *
|
||||
****************************************************************************
|
||||
* CMD_TEST: *
|
||||
* *
|
||||
* OUT: *
|
||||
* offset 1: unused dummy value *
|
||||
****************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef __MSGTYPES_H
|
||||
#define __MSGTYPES_H
|
||||
|
||||
/*
|
||||
* Command IDs:
|
||||
*
|
||||
* Bits 7..6: Reserved, should always be zero
|
||||
* Bits 5..0: Command ID. There are 62 usable IDs. Of this 63 available IDs,
|
||||
* the IDs 0x00..0x1F are commands with variable payload size,
|
||||
* the IDs 0x20..0x3F are commands with fixed payload size.
|
||||
*/
|
||||
|
||||
#define CMD_ID_MASK 0x3F
|
||||
|
||||
/* Commands with variable payload size */
|
||||
#define CMD_SCAN_IN 0x00
|
||||
#define CMD_SLOW_SCAN_IN 0x01
|
||||
#define CMD_SCAN_OUT 0x02
|
||||
#define CMD_SLOW_SCAN_OUT 0x03
|
||||
#define CMD_SCAN_IO 0x04
|
||||
#define CMD_SLOW_SCAN_IO 0x05
|
||||
|
||||
/* Commands with fixed payload size */
|
||||
#define CMD_CLOCK_TMS 0x20
|
||||
#define CMD_SLOW_CLOCK_TMS 0x21
|
||||
#define CMD_CLOCK_TCK 0x22
|
||||
#define CMD_SLOW_CLOCK_TCK 0x23
|
||||
#define CMD_SLEEP_US 0x24
|
||||
#define CMD_SLEEP_MS 0x25
|
||||
#define CMD_GET_SIGNALS 0x26
|
||||
#define CMD_SET_SIGNALS 0x27
|
||||
#define CMD_CONFIGURE_TCK_FREQ 0x28
|
||||
#define CMD_SET_LEDS 0x29
|
||||
#define CMD_TEST 0x2A
|
||||
|
||||
/* JTAG signal definition for jtag_get_signals() -- Input signals! */
|
||||
#define SIGNAL_TDO 1
|
||||
|
||||
/* JTAG signal definition for jtag_get_signals() -- Output signals! */
|
||||
#define SIGNAL_TDI 8
|
||||
#define SIGNAL_TMS 2
|
||||
#define SIGNAL_TCK 4
|
||||
#define SIGNAL_TRST 1
|
||||
#define SIGNAL_SRST 32
|
||||
|
||||
#endif
|
|
@ -506,11 +506,13 @@ static int esp_usb_jtag_init(void)
|
|||
* 1- With the minimum size required to get to know the total length of that struct,
|
||||
* 2- Then exactly the length of that struct. */
|
||||
uint8_t jtag_caps_desc[JTAG_PROTO_CAPS_DATA_LEN];
|
||||
int jtag_caps_read_len = jtag_libusb_control_transfer(priv->usb_device,
|
||||
int jtag_caps_read_len;
|
||||
r = jtag_libusb_control_transfer(priv->usb_device,
|
||||
LIBUSB_ENDPOINT_IN | LIBUSB_REQUEST_TYPE_STANDARD | LIBUSB_RECIPIENT_DEVICE,
|
||||
LIBUSB_REQUEST_GET_DESCRIPTOR, esp_usb_jtag_caps, 0,
|
||||
(char *)jtag_caps_desc, JTAG_PROTO_CAPS_DATA_LEN, LIBUSB_TIMEOUT_MS);
|
||||
if (jtag_caps_read_len <= 0) {
|
||||
(char *)jtag_caps_desc, JTAG_PROTO_CAPS_DATA_LEN, LIBUSB_TIMEOUT_MS,
|
||||
&jtag_caps_read_len);
|
||||
if (r != ERROR_OK) {
|
||||
LOG_ERROR("esp_usb_jtag: could not retrieve jtag_caps descriptor!");
|
||||
goto out;
|
||||
}
|
||||
|
@ -580,7 +582,8 @@ static int esp_usb_jtag_init(void)
|
|||
0,
|
||||
NULL,
|
||||
0,
|
||||
LIBUSB_TIMEOUT_MS);
|
||||
LIBUSB_TIMEOUT_MS,
|
||||
NULL);
|
||||
|
||||
return ERROR_OK;
|
||||
|
||||
|
@ -637,7 +640,7 @@ static int esp_usb_jtag_speed(int divisor)
|
|||
|
||||
LOG_DEBUG("esp_usb_jtag: setting divisor %d", divisor);
|
||||
jtag_libusb_control_transfer(priv->usb_device,
|
||||
LIBUSB_REQUEST_TYPE_VENDOR, VEND_JTAG_SETDIV, divisor, 0, NULL, 0, LIBUSB_TIMEOUT_MS);
|
||||
LIBUSB_REQUEST_TYPE_VENDOR, VEND_JTAG_SETDIV, divisor, 0, NULL, 0, LIBUSB_TIMEOUT_MS, NULL);
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
@ -648,8 +651,8 @@ COMMAND_HANDLER(esp_usb_jtag_tdo_cmd)
|
|||
if (!priv->usb_device)
|
||||
return ERROR_FAIL;
|
||||
int r = jtag_libusb_control_transfer(priv->usb_device,
|
||||
LIBUSB_ENDPOINT_IN | LIBUSB_REQUEST_TYPE_VENDOR, VEND_JTAG_GETTDO, 0, 0, &tdo, 1, LIBUSB_TIMEOUT_MS);
|
||||
if (r < 1)
|
||||
LIBUSB_ENDPOINT_IN | LIBUSB_REQUEST_TYPE_VENDOR, VEND_JTAG_GETTDO, 0, 0, &tdo, 1, LIBUSB_TIMEOUT_MS, NULL);
|
||||
if (r != ERROR_OK)
|
||||
return r;
|
||||
|
||||
command_print(CMD, "%d", tdo);
|
||||
|
@ -685,7 +688,7 @@ COMMAND_HANDLER(esp_usb_jtag_setio_cmd)
|
|||
d |= VEND_JTAG_SETIO_SRST;
|
||||
|
||||
jtag_libusb_control_transfer(priv->usb_device,
|
||||
0x40, VEND_JTAG_SETIO, d, 0, NULL, 0, LIBUSB_TIMEOUT_MS);
|
||||
0x40, VEND_JTAG_SETIO, d, 0, NULL, 0, LIBUSB_TIMEOUT_MS, NULL);
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
|
|
@ -235,7 +235,7 @@ static int ft232r_speed(int divisor)
|
|||
|
||||
if (jtag_libusb_control_transfer(adapter,
|
||||
LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE | LIBUSB_ENDPOINT_OUT,
|
||||
SIO_SET_BAUD_RATE, divisor, 0, NULL, 0, 1000) != 0) {
|
||||
SIO_SET_BAUD_RATE, divisor, 0, NULL, 0, 1000, NULL) != ERROR_OK) {
|
||||
LOG_ERROR("cannot set baud rate");
|
||||
return ERROR_JTAG_DEVICE_ERROR;
|
||||
}
|
||||
|
@ -266,7 +266,7 @@ static int ft232r_init(void)
|
|||
/* Reset the device. */
|
||||
if (jtag_libusb_control_transfer(adapter,
|
||||
LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE | LIBUSB_ENDPOINT_OUT,
|
||||
SIO_RESET, 0, 0, NULL, 0, 1000) != 0) {
|
||||
SIO_RESET, 0, 0, NULL, 0, 1000, NULL) != ERROR_OK) {
|
||||
LOG_ERROR("unable to reset device");
|
||||
return ERROR_JTAG_INIT_FAILED;
|
||||
}
|
||||
|
@ -275,7 +275,7 @@ static int ft232r_init(void)
|
|||
if (jtag_libusb_control_transfer(adapter,
|
||||
LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE | LIBUSB_ENDPOINT_OUT,
|
||||
SIO_SET_BITMODE, (1<<tck_gpio) | (1<<tdi_gpio) | (1<<tms_gpio) | (1<<ntrst_gpio) | (1<<nsysrst_gpio) | 0x400,
|
||||
0, NULL, 0, 1000) != 0) {
|
||||
0, NULL, 0, 1000, NULL) != ERROR_OK) {
|
||||
LOG_ERROR("cannot set sync bitbang mode");
|
||||
return ERROR_JTAG_INIT_FAILED;
|
||||
}
|
||||
|
@ -288,13 +288,13 @@ static int ft232r_init(void)
|
|||
if (jtag_libusb_control_transfer(adapter,
|
||||
LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE | LIBUSB_ENDPOINT_OUT,
|
||||
SIO_SET_BAUD_RATE, divisor,
|
||||
0, NULL, 0, 1000) != 0) {
|
||||
0, NULL, 0, 1000, NULL) != ERROR_OK) {
|
||||
LOG_ERROR("cannot set baud rate");
|
||||
return ERROR_JTAG_INIT_FAILED;
|
||||
}
|
||||
if (jtag_libusb_control_transfer(adapter,
|
||||
LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE | LIBUSB_ENDPOINT_OUT,
|
||||
SIO_SET_LATENCY_TIMER, latency_timer, 0, NULL, 0, 1000) != 0) {
|
||||
SIO_SET_LATENCY_TIMER, latency_timer, 0, NULL, 0, 1000, NULL) != ERROR_OK) {
|
||||
LOG_ERROR("unable to set latency timer");
|
||||
return ERROR_JTAG_INIT_FAILED;
|
||||
}
|
||||
|
@ -315,7 +315,7 @@ static int ft232r_quit(void)
|
|||
if (jtag_libusb_control_transfer(adapter,
|
||||
LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE | LIBUSB_ENDPOINT_OUT,
|
||||
SIO_SET_BITMODE, ft232r_restore_bitmode,
|
||||
0, NULL, 0, 1000) != 0) {
|
||||
0, NULL, 0, 1000, NULL) != ERROR_OK) {
|
||||
LOG_ERROR("cannot set bitmode to restore serial port");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -414,13 +414,13 @@ static int kitprog_set_protocol(uint8_t protocol)
|
|||
int transferred;
|
||||
char status = PROGRAMMER_NOK_NACK;
|
||||
|
||||
transferred = jtag_libusb_control_transfer(kitprog_handle->usb_handle,
|
||||
int retval = jtag_libusb_control_transfer(kitprog_handle->usb_handle,
|
||||
LIBUSB_ENDPOINT_IN | LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE,
|
||||
CONTROL_TYPE_WRITE,
|
||||
(CONTROL_MODE_SET_PROGRAMMER_PROTOCOL << 8) | CONTROL_COMMAND_PROGRAM,
|
||||
protocol, &status, 1, 0);
|
||||
protocol, &status, 1, 0, &transferred);
|
||||
|
||||
if (transferred == 0) {
|
||||
if (retval != ERROR_OK || transferred == 0) {
|
||||
LOG_DEBUG("Zero bytes transferred");
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
|
@ -440,11 +440,11 @@ static int kitprog_get_status(void)
|
|||
|
||||
/* Try a maximum of three times */
|
||||
for (int i = 0; (i < 3) && (transferred == 0); i++) {
|
||||
transferred = jtag_libusb_control_transfer(kitprog_handle->usb_handle,
|
||||
jtag_libusb_control_transfer(kitprog_handle->usb_handle,
|
||||
LIBUSB_ENDPOINT_IN | LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE,
|
||||
CONTROL_TYPE_READ,
|
||||
(CONTROL_MODE_POLL_PROGRAMMER_STATUS << 8) | CONTROL_COMMAND_PROGRAM,
|
||||
0, &status, 1, 0);
|
||||
0, &status, 1, 0, &transferred);
|
||||
jtag_sleep(1000);
|
||||
}
|
||||
|
||||
|
@ -466,13 +466,13 @@ static int kitprog_set_unknown(void)
|
|||
int transferred;
|
||||
char status = PROGRAMMER_NOK_NACK;
|
||||
|
||||
transferred = jtag_libusb_control_transfer(kitprog_handle->usb_handle,
|
||||
int retval = jtag_libusb_control_transfer(kitprog_handle->usb_handle,
|
||||
LIBUSB_ENDPOINT_IN | LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE,
|
||||
CONTROL_TYPE_WRITE,
|
||||
(0x03 << 8) | 0x04,
|
||||
0, &status, 1, 0);
|
||||
0, &status, 1, 0, &transferred);
|
||||
|
||||
if (transferred == 0) {
|
||||
if (retval != ERROR_OK || transferred == 0) {
|
||||
LOG_DEBUG("Zero bytes transferred");
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
|
@ -491,13 +491,13 @@ static int kitprog_acquire_psoc(uint8_t psoc_type, uint8_t acquire_mode,
|
|||
int transferred;
|
||||
char status = PROGRAMMER_NOK_NACK;
|
||||
|
||||
transferred = jtag_libusb_control_transfer(kitprog_handle->usb_handle,
|
||||
int retval = jtag_libusb_control_transfer(kitprog_handle->usb_handle,
|
||||
LIBUSB_ENDPOINT_IN | LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE,
|
||||
CONTROL_TYPE_WRITE,
|
||||
(CONTROL_MODE_ACQUIRE_SWD_TARGET << 8) | CONTROL_COMMAND_PROGRAM,
|
||||
(max_attempts << 8) | (acquire_mode << 4) | psoc_type, &status, 1, 0);
|
||||
(max_attempts << 8) | (acquire_mode << 4) | psoc_type, &status, 1, 0, &transferred);
|
||||
|
||||
if (transferred == 0) {
|
||||
if (retval != ERROR_OK || transferred == 0) {
|
||||
LOG_DEBUG("Zero bytes transferred");
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
|
@ -515,13 +515,13 @@ static int kitprog_reset_target(void)
|
|||
int transferred;
|
||||
char status = PROGRAMMER_NOK_NACK;
|
||||
|
||||
transferred = jtag_libusb_control_transfer(kitprog_handle->usb_handle,
|
||||
int retval = jtag_libusb_control_transfer(kitprog_handle->usb_handle,
|
||||
LIBUSB_ENDPOINT_IN | LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE,
|
||||
CONTROL_TYPE_WRITE,
|
||||
(CONTROL_MODE_RESET_TARGET << 8) | CONTROL_COMMAND_PROGRAM,
|
||||
0, &status, 1, 0);
|
||||
0, &status, 1, 0, &transferred);
|
||||
|
||||
if (transferred == 0) {
|
||||
if (retval != ERROR_OK || transferred == 0) {
|
||||
LOG_DEBUG("Zero bytes transferred");
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
|
@ -539,13 +539,13 @@ static int kitprog_swd_sync(void)
|
|||
int transferred;
|
||||
char status = PROGRAMMER_NOK_NACK;
|
||||
|
||||
transferred = jtag_libusb_control_transfer(kitprog_handle->usb_handle,
|
||||
int retval = jtag_libusb_control_transfer(kitprog_handle->usb_handle,
|
||||
LIBUSB_ENDPOINT_IN | LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE,
|
||||
CONTROL_TYPE_WRITE,
|
||||
(CONTROL_MODE_SYNCHRONIZE_TRANSFER << 8) | CONTROL_COMMAND_PROGRAM,
|
||||
0, &status, 1, 0);
|
||||
0, &status, 1, 0, &transferred);
|
||||
|
||||
if (transferred == 0) {
|
||||
if (retval != ERROR_OK || transferred == 0) {
|
||||
LOG_DEBUG("Zero bytes transferred");
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
|
@ -563,13 +563,13 @@ static int kitprog_swd_seq(uint8_t seq_type)
|
|||
int transferred;
|
||||
char status = PROGRAMMER_NOK_NACK;
|
||||
|
||||
transferred = jtag_libusb_control_transfer(kitprog_handle->usb_handle,
|
||||
int retval = jtag_libusb_control_transfer(kitprog_handle->usb_handle,
|
||||
LIBUSB_ENDPOINT_IN | LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE,
|
||||
CONTROL_TYPE_WRITE,
|
||||
(CONTROL_MODE_SEND_SWD_SEQUENCE << 8) | CONTROL_COMMAND_PROGRAM,
|
||||
seq_type, &status, 1, 0);
|
||||
seq_type, &status, 1, 0, &transferred);
|
||||
|
||||
if (transferred == 0) {
|
||||
if (retval != ERROR_OK || transferred == 0) {
|
||||
LOG_DEBUG("Zero bytes transferred");
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
|
|
|
@ -216,17 +216,22 @@ void jtag_libusb_close(struct libusb_device_handle *dev)
|
|||
|
||||
int jtag_libusb_control_transfer(struct libusb_device_handle *dev, uint8_t request_type,
|
||||
uint8_t request, uint16_t value, uint16_t index, char *bytes,
|
||||
uint16_t size, unsigned int timeout)
|
||||
uint16_t size, unsigned int timeout, int *transferred)
|
||||
{
|
||||
int transferred = 0;
|
||||
|
||||
transferred = libusb_control_transfer(dev, request_type, request, value, index,
|
||||
int retval = libusb_control_transfer(dev, request_type, request, value, index,
|
||||
(unsigned char *)bytes, size, timeout);
|
||||
|
||||
if (transferred < 0)
|
||||
transferred = 0;
|
||||
if (retval < 0) {
|
||||
LOG_ERROR("libusb_control_transfer error: %s", libusb_error_name(retval));
|
||||
if (transferred)
|
||||
*transferred = 0;
|
||||
return jtag_libusb_error(retval);
|
||||
}
|
||||
|
||||
return transferred;
|
||||
if (transferred)
|
||||
*transferred = retval;
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
int jtag_libusb_bulk_write(struct libusb_device_handle *dev, int ep, char *bytes,
|
||||
|
|
|
@ -38,7 +38,8 @@ int jtag_libusb_open(const uint16_t vids[], const uint16_t pids[],
|
|||
void jtag_libusb_close(struct libusb_device_handle *dev);
|
||||
int jtag_libusb_control_transfer(struct libusb_device_handle *dev,
|
||||
uint8_t request_type, uint8_t request, uint16_t value,
|
||||
uint16_t index, char *bytes, uint16_t size, unsigned int timeout);
|
||||
uint16_t index, char *bytes, uint16_t size, unsigned int timeout,
|
||||
int *transferred);
|
||||
int jtag_libusb_bulk_write(struct libusb_device_handle *dev, int ep,
|
||||
char *bytes, int size, int timeout, int *transferred);
|
||||
int jtag_libusb_bulk_read(struct libusb_device_handle *dev, int ep,
|
||||
|
|
|
@ -735,7 +735,7 @@ int opendous_usb_message(struct opendous_jtag *opendous_jtag, int out_length, in
|
|||
/* Write data from out_buffer to USB. */
|
||||
int opendous_usb_write(struct opendous_jtag *opendous_jtag, int out_length)
|
||||
{
|
||||
int result;
|
||||
int result, transferred;
|
||||
|
||||
if (out_length > OPENDOUS_OUT_BUFFER_SIZE) {
|
||||
LOG_ERROR("opendous_jtag_write illegal out_length=%d (max=%d)", out_length, OPENDOUS_OUT_BUFFER_SIZE);
|
||||
|
@ -748,7 +748,11 @@ int opendous_usb_write(struct opendous_jtag *opendous_jtag, int out_length)
|
|||
if (opendous_probe->CONTROL_TRANSFER) {
|
||||
result = jtag_libusb_control_transfer(opendous_jtag->usb_handle,
|
||||
LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE | LIBUSB_ENDPOINT_OUT,
|
||||
FUNC_WRITE_DATA, 0, 0, (char *) usb_out_buffer, out_length, OPENDOUS_USB_TIMEOUT);
|
||||
FUNC_WRITE_DATA, 0, 0, (char *)usb_out_buffer, out_length, OPENDOUS_USB_TIMEOUT,
|
||||
&transferred);
|
||||
/* FIXME: propagate error separately from transferred */
|
||||
if (result == ERROR_OK)
|
||||
result = transferred;
|
||||
} else {
|
||||
jtag_libusb_bulk_write(opendous_jtag->usb_handle, OPENDOUS_WRITE_ENDPOINT,
|
||||
(char *)usb_out_buffer, out_length, OPENDOUS_USB_TIMEOUT, &result);
|
||||
|
@ -768,6 +772,8 @@ int opendous_usb_write(struct opendous_jtag *opendous_jtag, int out_length)
|
|||
/* Read data from USB into in_buffer. */
|
||||
int opendous_usb_read(struct opendous_jtag *opendous_jtag)
|
||||
{
|
||||
int transferred;
|
||||
|
||||
#ifdef _DEBUG_USB_COMMS_
|
||||
LOG_DEBUG("USB read begin");
|
||||
#endif
|
||||
|
@ -775,7 +781,11 @@ int opendous_usb_read(struct opendous_jtag *opendous_jtag)
|
|||
if (opendous_probe->CONTROL_TRANSFER) {
|
||||
result = jtag_libusb_control_transfer(opendous_jtag->usb_handle,
|
||||
LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE | LIBUSB_ENDPOINT_IN,
|
||||
FUNC_READ_DATA, 0, 0, (char *) usb_in_buffer, OPENDOUS_IN_BUFFER_SIZE, OPENDOUS_USB_TIMEOUT);
|
||||
FUNC_READ_DATA, 0, 0, (char *)usb_in_buffer, OPENDOUS_IN_BUFFER_SIZE, OPENDOUS_USB_TIMEOUT,
|
||||
&transferred);
|
||||
/* FIXME: propagate error separately from transferred */
|
||||
if (result == ERROR_OK)
|
||||
result = transferred;
|
||||
} else {
|
||||
jtag_libusb_bulk_read(opendous_jtag->usb_handle, OPENDOUS_READ_ENDPOINT,
|
||||
(char *)usb_in_buffer, OPENDOUS_IN_BUFFER_SIZE, OPENDOUS_USB_TIMEOUT, &result);
|
||||
|
|
|
@ -239,10 +239,10 @@ static int openjtag_buf_write_cy7c65215(
|
|||
|
||||
ret = jtag_libusb_control_transfer(usbh, CY7C65215_JTAG_REQUEST,
|
||||
CY7C65215_JTAG_WRITE, size, 0,
|
||||
NULL, 0, CY7C65215_USB_TIMEOUT);
|
||||
if (ret < 0) {
|
||||
LOG_ERROR("vendor command failed, error %d", ret);
|
||||
return ERROR_JTAG_DEVICE_ERROR;
|
||||
NULL, 0, CY7C65215_USB_TIMEOUT, NULL);
|
||||
if (ret != ERROR_OK) {
|
||||
LOG_ERROR("vendor command failed");
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (jtag_libusb_bulk_write(usbh, ep_out, (char *)buf, size,
|
||||
|
@ -306,10 +306,10 @@ static int openjtag_buf_read_cy7c65215(
|
|||
|
||||
ret = jtag_libusb_control_transfer(usbh, CY7C65215_JTAG_REQUEST,
|
||||
CY7C65215_JTAG_READ, qty, 0,
|
||||
NULL, 0, CY7C65215_USB_TIMEOUT);
|
||||
if (ret < 0) {
|
||||
LOG_ERROR("vendor command failed, error %d", ret);
|
||||
return ERROR_JTAG_DEVICE_ERROR;
|
||||
NULL, 0, CY7C65215_USB_TIMEOUT, NULL);
|
||||
if (ret != ERROR_OK) {
|
||||
LOG_ERROR("vendor command failed");
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (jtag_libusb_bulk_read(usbh, ep_in, (char *)buf, qty,
|
||||
|
@ -455,8 +455,8 @@ static int openjtag_init_cy7c65215(void)
|
|||
ret = jtag_libusb_control_transfer(usbh,
|
||||
CY7C65215_JTAG_REQUEST,
|
||||
CY7C65215_JTAG_ENABLE,
|
||||
0, 0, NULL, 0, CY7C65215_USB_TIMEOUT);
|
||||
if (ret < 0) {
|
||||
0, 0, NULL, 0, CY7C65215_USB_TIMEOUT, NULL);
|
||||
if (ret != ERROR_OK) {
|
||||
LOG_ERROR("could not enable JTAG module");
|
||||
goto err;
|
||||
}
|
||||
|
@ -466,7 +466,7 @@ static int openjtag_init_cy7c65215(void)
|
|||
err:
|
||||
if (usbh)
|
||||
jtag_libusb_close(usbh);
|
||||
return ERROR_JTAG_INIT_FAILED;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int openjtag_init(void)
|
||||
|
@ -508,8 +508,8 @@ static int openjtag_quit_cy7c65215(void)
|
|||
ret = jtag_libusb_control_transfer(usbh,
|
||||
CY7C65215_JTAG_REQUEST,
|
||||
CY7C65215_JTAG_DISABLE,
|
||||
0, 0, NULL, 0, CY7C65215_USB_TIMEOUT);
|
||||
if (ret < 0)
|
||||
0, 0, NULL, 0, CY7C65215_USB_TIMEOUT, NULL);
|
||||
if (ret != ERROR_OK)
|
||||
LOG_WARNING("could not disable JTAG module");
|
||||
|
||||
jtag_libusb_close(usbh);
|
||||
|
|
|
@ -84,6 +84,8 @@
|
|||
#define STLINK_V3S_PID (0x374F)
|
||||
#define STLINK_V3_2VCP_PID (0x3753)
|
||||
#define STLINK_V3E_NO_MSD_PID (0x3754)
|
||||
#define STLINK_V3P_USBLOADER_PID (0x3755)
|
||||
#define STLINK_V3P_PID (0x3757)
|
||||
|
||||
/*
|
||||
* ST-Link/V1, ST-Link/V2 and ST-Link/V2.1 are full-speed USB devices and
|
||||
|
@ -1297,8 +1299,8 @@ static int stlink_usb_version(void *handle)
|
|||
break;
|
||||
}
|
||||
|
||||
/* STLINK-V3 requires a specific command */
|
||||
if (v == 3 && x == 0 && y == 0) {
|
||||
/* STLINK-V3 & STLINK-V3P require a specific command */
|
||||
if (v >= 3 && x == 0 && y == 0) {
|
||||
stlink_usb_init_buffer(handle, h->rx_ep, 16);
|
||||
|
||||
h->cmdbuf[h->cmdidx++] = STLINK_APIV3_GET_VERSION_EX;
|
||||
|
@ -1414,6 +1416,41 @@ static int stlink_usb_version(void *handle)
|
|||
if (h->version.jtag >= 6)
|
||||
flags |= STLINK_F_HAS_RW8_512BYTES;
|
||||
|
||||
break;
|
||||
case 4:
|
||||
/* STLINK-V3P use api-v3 */
|
||||
h->version.jtag_api = STLINK_JTAG_API_V3;
|
||||
|
||||
/* STLINK-V3P is a superset of ST-LINK/V3 */
|
||||
|
||||
/* API for trace */
|
||||
/* API for target voltage */
|
||||
flags |= STLINK_F_HAS_TRACE;
|
||||
|
||||
/* preferred API to get last R/W status */
|
||||
flags |= STLINK_F_HAS_GETLASTRWSTATUS2;
|
||||
|
||||
/* API to access DAP registers */
|
||||
flags |= STLINK_F_HAS_DAP_REG;
|
||||
|
||||
/* API to read/write memory at 16 bit */
|
||||
/* API to write memory without address increment */
|
||||
flags |= STLINK_F_HAS_MEM_16BIT;
|
||||
|
||||
/* API required to init AP before any AP access */
|
||||
flags |= STLINK_F_HAS_AP_INIT;
|
||||
|
||||
/* API required to return proper error code on close AP */
|
||||
flags |= STLINK_F_FIX_CLOSE_AP;
|
||||
|
||||
/* Banked regs (DPv1 & DPv2) support */
|
||||
/* API to read memory without address increment */
|
||||
/* Memory R/W supports CSW */
|
||||
flags |= STLINK_F_HAS_DPBANKSEL;
|
||||
|
||||
/* 8bit read/write max packet size 512 bytes */
|
||||
flags |= STLINK_F_HAS_RW8_512BYTES;
|
||||
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
@ -3402,6 +3439,8 @@ static int stlink_usb_usb_open(void *handle, struct hl_interface_param_s *param)
|
|||
case STLINK_V3S_PID:
|
||||
case STLINK_V3_2VCP_PID:
|
||||
case STLINK_V3E_NO_MSD_PID:
|
||||
case STLINK_V3P_USBLOADER_PID:
|
||||
case STLINK_V3P_PID:
|
||||
h->version.stlink = 3;
|
||||
h->tx_ep = STLINK_V2_1_TX_EP;
|
||||
h->trace_ep = STLINK_V2_1_TRACE_EP;
|
||||
|
@ -3820,7 +3859,7 @@ static int stlink_config_trace(void *handle, bool enabled,
|
|||
return ERROR_FAIL;
|
||||
}
|
||||
|
||||
unsigned int max_trace_freq = (h->version.stlink == 3) ?
|
||||
unsigned int max_trace_freq = (h->version.stlink >= 3) ?
|
||||
STLINK_V3_TRACE_MAX_HZ : STLINK_TRACE_MAX_HZ;
|
||||
|
||||
/* Only concern ourselves with the frequency if the STlink is processing it. */
|
||||
|
|
|
@ -103,7 +103,8 @@ static int ublast2_write_firmware_section(struct libusb_device_handle *libusb_de
|
|||
0,
|
||||
(char *)data_ptr,
|
||||
chunk_size,
|
||||
100);
|
||||
100,
|
||||
NULL);
|
||||
|
||||
bytes_remaining -= chunk_size;
|
||||
addr += chunk_size;
|
||||
|
@ -154,7 +155,8 @@ static int load_usb_blaster_firmware(struct libusb_device_handle *libusb_dev,
|
|||
0,
|
||||
&value,
|
||||
1,
|
||||
100);
|
||||
100,
|
||||
NULL);
|
||||
|
||||
/* Download all sections in the image to ULINK */
|
||||
for (unsigned int i = 0; i < ublast2_firmware_image.num_sections; i++) {
|
||||
|
@ -175,7 +177,8 @@ static int load_usb_blaster_firmware(struct libusb_device_handle *libusb_dev,
|
|||
0,
|
||||
&value,
|
||||
1,
|
||||
100);
|
||||
100,
|
||||
NULL);
|
||||
|
||||
error_close_firmware:
|
||||
image_close(&ublast2_firmware_image);
|
||||
|
@ -245,7 +248,8 @@ static int ublast2_libusb_init(struct ublast_lowlevel *low)
|
|||
0,
|
||||
buffer,
|
||||
5,
|
||||
100);
|
||||
100,
|
||||
NULL);
|
||||
|
||||
LOG_INFO("Altera USB-Blaster II found (Firm. rev. = %s)", buffer);
|
||||
|
||||
|
|
|
@ -579,9 +579,6 @@ static bool usb_get_response(uint32_t *total_bytes_read, uint32_t timeout)
|
|||
|
||||
static bool usb_send_command(uint16_t size)
|
||||
{
|
||||
int written = 0;
|
||||
bool success = true;
|
||||
|
||||
/* Check the packet length */
|
||||
if (size > USB_PAYLOAD_SIZE)
|
||||
return false;
|
||||
|
@ -596,13 +593,7 @@ static bool usb_send_command(uint16_t size)
|
|||
size += 3;
|
||||
|
||||
/* Send the data via the USB connection */
|
||||
success = usb_write(xds110.write_packet, (int)size, &written);
|
||||
|
||||
/* Check if the correct number of bytes was written */
|
||||
if (written != (int)size)
|
||||
success = false;
|
||||
|
||||
return success;
|
||||
return usb_write(xds110.write_packet, (int)size, NULL);
|
||||
}
|
||||
|
||||
/***************************************************************************
|
||||
|
|
|
@ -364,6 +364,7 @@ int adapter_poll_trace(uint8_t *buf, size_t *size);
|
|||
|
||||
extern struct adapter_driver am335xgpio_adapter_driver;
|
||||
extern struct adapter_driver amt_jtagaccel_adapter_driver;
|
||||
extern struct adapter_driver angie_adapter_driver;
|
||||
extern struct adapter_driver armjtagew_adapter_driver;
|
||||
extern struct adapter_driver at91rm9200_adapter_driver;
|
||||
extern struct adapter_driver bcm2835gpio_adapter_driver;
|
||||
|
|
|
@ -96,6 +96,9 @@ struct adapter_driver *adapter_drivers[] = {
|
|||
#if BUILD_ULINK == 1
|
||||
&ulink_adapter_driver,
|
||||
#endif
|
||||
#if BUILD_ANGIE == 1
|
||||
&angie_adapter_driver,
|
||||
#endif
|
||||
#if BUILD_ARMJTAGEW == 1
|
||||
&armjtagew_adapter_driver,
|
||||
#endif
|
||||
|
|
|
@ -1108,4 +1108,18 @@ proc "am335xgpio led_on_state" {state} {
|
|||
}
|
||||
}
|
||||
|
||||
lappend _telnet_autocomplete_skip "pld device"
|
||||
proc "pld device" {driver tap_name {opt 0}} {
|
||||
echo "DEPRECATED! use 'pld create ...', not 'pld device ...'"
|
||||
if {[string is integer -strict $opt]} {
|
||||
if {$opt == 0} {
|
||||
eval pld create [lindex [split $tap_name .] 0].pld $driver -chain-position $tap_name
|
||||
} else {
|
||||
eval pld create [lindex [split $tap_name .] 0].pld $driver -chain-position $tap_name -no_jstart
|
||||
}
|
||||
} else {
|
||||
eval pld create [lindex [split $tap_name .] 0].pld $driver -chain-position $tap_name -family $opt
|
||||
}
|
||||
}
|
||||
|
||||
# END MIGRATION AIDS
|
||||
|
|
|
@ -16,13 +16,29 @@
|
|||
|
||||
#define PROGRAM 0x4
|
||||
#define ENTERUSER 0x7
|
||||
#define USER1 0x8
|
||||
#define USER2 0x9
|
||||
#define USER3 0xa
|
||||
#define USER4 0xb
|
||||
|
||||
enum efinix_family_e {
|
||||
EFINIX_TRION,
|
||||
EFINIX_TITANIUM,
|
||||
EFINIX_UNKNOWN
|
||||
};
|
||||
|
||||
#define TRAILING_ZEROS 4000
|
||||
#define RUNTEST_START_CYCLES 100
|
||||
#define RUNTEST_FINISH_CYCLES 100
|
||||
|
||||
struct efinix_device {
|
||||
uint32_t idcode;
|
||||
int num_user;
|
||||
};
|
||||
|
||||
struct efinix_pld_device {
|
||||
struct jtag_tap *tap;
|
||||
enum efinix_family_e family;
|
||||
};
|
||||
|
||||
static int efinix_read_bit_file(struct raw_bit_file *bit_file, const char *filename)
|
||||
|
@ -188,23 +204,87 @@ static int efinix_load(struct pld_device *pld_device, const char *filename)
|
|||
return retval;
|
||||
}
|
||||
|
||||
PLD_DEVICE_COMMAND_HANDLER(efinix_pld_device_command)
|
||||
static int efinix_get_ipdbg_hub(int user_num, struct pld_device *pld_device, struct pld_ipdbg_hub *hub)
|
||||
{
|
||||
if (CMD_ARGC != 2)
|
||||
if (!pld_device)
|
||||
return ERROR_FAIL;
|
||||
|
||||
struct efinix_pld_device *pld_device_info = pld_device->driver_priv;
|
||||
|
||||
if (!pld_device_info || !pld_device_info->tap)
|
||||
return ERROR_FAIL;
|
||||
|
||||
hub->tap = pld_device_info->tap;
|
||||
|
||||
if (pld_device_info->family == EFINIX_UNKNOWN) {
|
||||
LOG_ERROR("family unknown, please specify for 'pld create'");
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
int num_user = 2; /* trion */
|
||||
if (pld_device_info->family == EFINIX_TITANIUM)
|
||||
num_user = 4;
|
||||
|
||||
if (user_num > num_user) {
|
||||
LOG_ERROR("Devices has only user register 1 to %d", num_user);
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
|
||||
switch (user_num) {
|
||||
case 1:
|
||||
hub->user_ir_code = USER1;
|
||||
break;
|
||||
case 2:
|
||||
hub->user_ir_code = USER2;
|
||||
break;
|
||||
case 3:
|
||||
hub->user_ir_code = USER3;
|
||||
break;
|
||||
case 4:
|
||||
hub->user_ir_code = USER4;
|
||||
break;
|
||||
default:
|
||||
LOG_ERROR("efinix devices only have user register 1 to %d", num_user);
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
PLD_CREATE_COMMAND_HANDLER(efinix_pld_create_command)
|
||||
{
|
||||
if (CMD_ARGC != 4 && CMD_ARGC != 6)
|
||||
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||
|
||||
struct jtag_tap *tap = jtag_tap_by_string(CMD_ARGV[1]);
|
||||
if (strcmp(CMD_ARGV[2], "-chain-position") != 0)
|
||||
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||
|
||||
struct jtag_tap *tap = jtag_tap_by_string(CMD_ARGV[3]);
|
||||
if (!tap) {
|
||||
command_print(CMD, "Tap: %s does not exist", CMD_ARGV[1]);
|
||||
command_print(CMD, "Tap: %s does not exist", CMD_ARGV[3]);
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
|
||||
enum efinix_family_e family = EFINIX_UNKNOWN;
|
||||
if (CMD_ARGC == 6) {
|
||||
if (strcmp(CMD_ARGV[4], "-family") != 0)
|
||||
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||
|
||||
if (strcmp(CMD_ARGV[5], "trion") == 0) {
|
||||
family = EFINIX_TRION;
|
||||
} else if (strcmp(CMD_ARGV[5], "titanium") == 0) {
|
||||
family = EFINIX_TITANIUM;
|
||||
} else {
|
||||
command_print(CMD, "unknown family");
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
}
|
||||
|
||||
struct efinix_pld_device *efinix_info = malloc(sizeof(struct efinix_pld_device));
|
||||
if (!efinix_info) {
|
||||
LOG_ERROR("Out of memory");
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
efinix_info->tap = tap;
|
||||
efinix_info->family = family;
|
||||
|
||||
pld->driver_priv = efinix_info;
|
||||
|
||||
|
@ -213,6 +293,7 @@ PLD_DEVICE_COMMAND_HANDLER(efinix_pld_device_command)
|
|||
|
||||
struct pld_driver efinix_pld = {
|
||||
.name = "efinix",
|
||||
.pld_device_command = &efinix_pld_device_command,
|
||||
.pld_create_command = &efinix_pld_create_command,
|
||||
.load = &efinix_load,
|
||||
.get_ipdbg_hub = efinix_get_ipdbg_hub,
|
||||
};
|
||||
|
|
|
@ -209,22 +209,21 @@ static int gatemate_load(struct pld_device *pld_device, const char *filename)
|
|||
return retval;
|
||||
}
|
||||
|
||||
PLD_DEVICE_COMMAND_HANDLER(gatemate_pld_device_command)
|
||||
PLD_CREATE_COMMAND_HANDLER(gatemate_pld_create_command)
|
||||
{
|
||||
struct jtag_tap *tap;
|
||||
|
||||
struct gatemate_pld_device *gatemate_info;
|
||||
|
||||
if (CMD_ARGC != 2)
|
||||
if (CMD_ARGC != 4)
|
||||
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||
|
||||
tap = jtag_tap_by_string(CMD_ARGV[1]);
|
||||
if (strcmp(CMD_ARGV[2], "-chain-position") != 0)
|
||||
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||
|
||||
struct jtag_tap *tap = jtag_tap_by_string(CMD_ARGV[3]);
|
||||
if (!tap) {
|
||||
command_print(CMD, "Tap: %s does not exist", CMD_ARGV[1]);
|
||||
command_print(CMD, "Tap: %s does not exist", CMD_ARGV[3]);
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
|
||||
gatemate_info = malloc(sizeof(struct gatemate_pld_device));
|
||||
struct gatemate_pld_device *gatemate_info = malloc(sizeof(struct gatemate_pld_device));
|
||||
if (!gatemate_info) {
|
||||
LOG_ERROR("Out of memory");
|
||||
return ERROR_FAIL;
|
||||
|
@ -238,6 +237,6 @@ PLD_DEVICE_COMMAND_HANDLER(gatemate_pld_device_command)
|
|||
|
||||
struct pld_driver gatemate_pld = {
|
||||
.name = "gatemate",
|
||||
.pld_device_command = &gatemate_pld_device_command,
|
||||
.pld_create_command = &gatemate_pld_create_command,
|
||||
.load = &gatemate_load,
|
||||
};
|
||||
|
|
|
@ -29,6 +29,9 @@
|
|||
#define ERASE_FLASH 0x75
|
||||
#define ENABLE_2ND_FLASH 0x78
|
||||
|
||||
#define USER1 0x42
|
||||
#define USER2 0x43
|
||||
|
||||
#define STAUS_MASK_MEMORY_ERASE BIT(5)
|
||||
#define STAUS_MASK_SYSTEM_EDIT_MODE BIT(7)
|
||||
|
||||
|
@ -449,17 +452,37 @@ static int gowin_reload_command(struct pld_device *pld_device)
|
|||
return gowin_reload(gowin_info->tap);
|
||||
}
|
||||
|
||||
static int gowin_get_ipdbg_hub(int user_num, struct pld_device *pld_device, struct pld_ipdbg_hub *hub)
|
||||
{
|
||||
if (!pld_device)
|
||||
return ERROR_FAIL;
|
||||
|
||||
struct gowin_pld_device *pld_device_info = pld_device->driver_priv;
|
||||
|
||||
if (!pld_device_info || !pld_device_info->tap)
|
||||
return ERROR_FAIL;
|
||||
|
||||
hub->tap = pld_device_info->tap;
|
||||
|
||||
if (user_num == 1) {
|
||||
hub->user_ir_code = USER1;
|
||||
} else if (user_num == 2) {
|
||||
hub->user_ir_code = USER2;
|
||||
} else {
|
||||
LOG_ERROR("gowin devices only have user register 1 & 2");
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
COMMAND_HANDLER(gowin_read_status_command_handler)
|
||||
{
|
||||
int dev_id;
|
||||
|
||||
if (CMD_ARGC != 1)
|
||||
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||
|
||||
COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], dev_id);
|
||||
struct pld_device *device = get_pld_device_by_num(dev_id);
|
||||
struct pld_device *device = get_pld_device_by_name_or_numstr(CMD_ARGV[0]);
|
||||
if (!device) {
|
||||
command_print(CMD, "pld device '#%s' is out of bounds", CMD_ARGV[0]);
|
||||
command_print(CMD, "pld device '#%s' is out of bounds or unknown", CMD_ARGV[0]);
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
|
||||
|
@ -474,15 +497,12 @@ COMMAND_HANDLER(gowin_read_status_command_handler)
|
|||
|
||||
COMMAND_HANDLER(gowin_read_user_register_command_handler)
|
||||
{
|
||||
int dev_id;
|
||||
|
||||
if (CMD_ARGC != 1)
|
||||
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||
|
||||
COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], dev_id);
|
||||
struct pld_device *device = get_pld_device_by_num(dev_id);
|
||||
struct pld_device *device = get_pld_device_by_name_or_numstr(CMD_ARGV[0]);
|
||||
if (!device) {
|
||||
command_print(CMD, "pld device '#%s' is out of bounds", CMD_ARGV[0]);
|
||||
command_print(CMD, "pld device '#%s' is out of bounds or unknown", CMD_ARGV[0]);
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
|
||||
|
@ -497,15 +517,12 @@ COMMAND_HANDLER(gowin_read_user_register_command_handler)
|
|||
|
||||
COMMAND_HANDLER(gowin_reload_command_handler)
|
||||
{
|
||||
int dev_id;
|
||||
|
||||
if (CMD_ARGC != 1)
|
||||
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||
|
||||
COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], dev_id);
|
||||
struct pld_device *device = get_pld_device_by_num(dev_id);
|
||||
struct pld_device *device = get_pld_device_by_name_or_numstr(CMD_ARGV[0]);
|
||||
if (!device) {
|
||||
command_print(CMD, "pld device '#%s' is out of bounds", CMD_ARGV[0]);
|
||||
command_print(CMD, "pld device '#%s' is out of bounds or unknown", CMD_ARGV[0]);
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
|
||||
|
@ -518,19 +535,19 @@ static const struct command_registration gowin_exec_command_handlers[] = {
|
|||
.mode = COMMAND_EXEC,
|
||||
.handler = gowin_read_status_command_handler,
|
||||
.help = "reading status register from FPGA",
|
||||
.usage = "num_pld",
|
||||
.usage = "pld_name",
|
||||
}, {
|
||||
.name = "read_user",
|
||||
.mode = COMMAND_EXEC,
|
||||
.handler = gowin_read_user_register_command_handler,
|
||||
.help = "reading user register from FPGA",
|
||||
.usage = "num_pld",
|
||||
.usage = "pld_name",
|
||||
}, {
|
||||
.name = "reload",
|
||||
.mode = COMMAND_EXEC,
|
||||
.handler = gowin_reload_command_handler,
|
||||
.help = "reloading bitstream from flash to SRAM",
|
||||
.usage = "num_pld",
|
||||
.usage = "pld_name",
|
||||
},
|
||||
COMMAND_REGISTRATION_DONE
|
||||
};
|
||||
|
@ -546,22 +563,21 @@ static const struct command_registration gowin_command_handler[] = {
|
|||
COMMAND_REGISTRATION_DONE
|
||||
};
|
||||
|
||||
PLD_DEVICE_COMMAND_HANDLER(gowin_pld_device_command)
|
||||
PLD_CREATE_COMMAND_HANDLER(gowin_pld_create_command)
|
||||
{
|
||||
struct jtag_tap *tap;
|
||||
|
||||
struct gowin_pld_device *gowin_info;
|
||||
|
||||
if (CMD_ARGC != 2)
|
||||
if (CMD_ARGC != 4)
|
||||
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||
|
||||
tap = jtag_tap_by_string(CMD_ARGV[1]);
|
||||
if (strcmp(CMD_ARGV[2], "-chain-position") != 0)
|
||||
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||
|
||||
struct jtag_tap *tap = jtag_tap_by_string(CMD_ARGV[3]);
|
||||
if (!tap) {
|
||||
command_print(CMD, "Tap: %s does not exist", CMD_ARGV[1]);
|
||||
command_print(CMD, "Tap: %s does not exist", CMD_ARGV[3]);
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
|
||||
gowin_info = malloc(sizeof(struct gowin_pld_device));
|
||||
struct gowin_pld_device *gowin_info = malloc(sizeof(struct gowin_pld_device));
|
||||
if (!gowin_info) {
|
||||
LOG_ERROR("Out of memory");
|
||||
return ERROR_FAIL;
|
||||
|
@ -576,6 +592,7 @@ PLD_DEVICE_COMMAND_HANDLER(gowin_pld_device_command)
|
|||
struct pld_driver gowin_pld = {
|
||||
.name = "gowin",
|
||||
.commands = gowin_command_handler,
|
||||
.pld_device_command = &gowin_pld_device_command,
|
||||
.pld_create_command = &gowin_pld_create_command,
|
||||
.load = &gowin_load_to_sram,
|
||||
.get_ipdbg_hub = gowin_get_ipdbg_hub,
|
||||
};
|
||||
|
|
|
@ -18,6 +18,8 @@
|
|||
#include "raw_bit.h"
|
||||
|
||||
#define BYPASS 0x3FF
|
||||
#define USER0 0x00C
|
||||
#define USER1 0x00E
|
||||
|
||||
enum intel_family_e {
|
||||
INTEL_CYCLONEIII,
|
||||
|
@ -337,18 +339,39 @@ static int intel_load(struct pld_device *pld_device, const char *filename)
|
|||
return jtag_execute_queue();
|
||||
}
|
||||
|
||||
static int intel_get_ipdbg_hub(int user_num, struct pld_device *pld_device, struct pld_ipdbg_hub *hub)
|
||||
{
|
||||
if (!pld_device)
|
||||
return ERROR_FAIL;
|
||||
|
||||
struct intel_pld_device *pld_device_info = pld_device->driver_priv;
|
||||
|
||||
if (!pld_device_info || !pld_device_info->tap)
|
||||
return ERROR_FAIL;
|
||||
|
||||
hub->tap = pld_device_info->tap;
|
||||
|
||||
if (user_num == 0) {
|
||||
hub->user_ir_code = USER0;
|
||||
} else if (user_num == 1) {
|
||||
hub->user_ir_code = USER1;
|
||||
} else {
|
||||
LOG_ERROR("intel devices only have user register 0 & 1");
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
COMMAND_HANDLER(intel_set_bscan_command_handler)
|
||||
{
|
||||
int dev_id;
|
||||
unsigned int boundary_scan_length;
|
||||
|
||||
if (CMD_ARGC != 2)
|
||||
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||
|
||||
COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], dev_id);
|
||||
struct pld_device *pld_device = get_pld_device_by_num(dev_id);
|
||||
struct pld_device *pld_device = get_pld_device_by_name_or_numstr(CMD_ARGV[0]);
|
||||
if (!pld_device) {
|
||||
command_print(CMD, "pld device '#%s' is out of bounds", CMD_ARGV[0]);
|
||||
command_print(CMD, "pld device '#%s' is out of bounds or unknown", CMD_ARGV[0]);
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
|
||||
|
@ -366,16 +389,14 @@ COMMAND_HANDLER(intel_set_bscan_command_handler)
|
|||
|
||||
COMMAND_HANDLER(intel_set_check_pos_command_handler)
|
||||
{
|
||||
int dev_id;
|
||||
int checkpos;
|
||||
|
||||
if (CMD_ARGC != 2)
|
||||
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||
|
||||
COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], dev_id);
|
||||
struct pld_device *pld_device = get_pld_device_by_num(dev_id);
|
||||
struct pld_device *pld_device = get_pld_device_by_name_or_numstr(CMD_ARGV[0]);
|
||||
if (!pld_device) {
|
||||
command_print(CMD, "pld device '#%s' is out of bounds", CMD_ARGV[0]);
|
||||
command_print(CMD, "pld device '#%s' is out of bounds or unknown", CMD_ARGV[0]);
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
|
||||
|
@ -392,42 +413,47 @@ COMMAND_HANDLER(intel_set_check_pos_command_handler)
|
|||
}
|
||||
|
||||
|
||||
PLD_DEVICE_COMMAND_HANDLER(intel_pld_device_command)
|
||||
PLD_CREATE_COMMAND_HANDLER(intel_pld_create_command)
|
||||
{
|
||||
if (CMD_ARGC < 2 || CMD_ARGC > 3)
|
||||
if (CMD_ARGC != 4 && CMD_ARGC != 6)
|
||||
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||
|
||||
struct jtag_tap *tap = jtag_tap_by_string(CMD_ARGV[1]);
|
||||
if (strcmp(CMD_ARGV[2], "-chain-position") != 0)
|
||||
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||
|
||||
struct jtag_tap *tap = jtag_tap_by_string(CMD_ARGV[3]);
|
||||
if (!tap) {
|
||||
command_print(CMD, "Tap: %s does not exist", CMD_ARGV[1]);
|
||||
command_print(CMD, "Tap: %s does not exist", CMD_ARGV[3]);
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
|
||||
enum intel_family_e family = INTEL_UNKNOWN;
|
||||
if (CMD_ARGC == 6) {
|
||||
if (strcmp(CMD_ARGV[4], "-family") != 0)
|
||||
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||
|
||||
if (strcmp(CMD_ARGV[5], "cycloneiii") == 0) {
|
||||
family = INTEL_CYCLONEIII;
|
||||
} else if (strcmp(CMD_ARGV[5], "cycloneiv") == 0) {
|
||||
family = INTEL_CYCLONEIV;
|
||||
} else if (strcmp(CMD_ARGV[5], "cyclonev") == 0) {
|
||||
family = INTEL_CYCLONEV;
|
||||
} else if (strcmp(CMD_ARGV[5], "cyclone10") == 0) {
|
||||
family = INTEL_CYCLONE10;
|
||||
} else if (strcmp(CMD_ARGV[5], "arriaii") == 0) {
|
||||
family = INTEL_ARRIAII;
|
||||
} else {
|
||||
command_print(CMD, "unknown family");
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
}
|
||||
|
||||
struct intel_pld_device *intel_info = malloc(sizeof(struct intel_pld_device));
|
||||
if (!intel_info) {
|
||||
LOG_ERROR("Out of memory");
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
|
||||
enum intel_family_e family = INTEL_UNKNOWN;
|
||||
|
||||
if (CMD_ARGC == 3) {
|
||||
if (strcmp(CMD_ARGV[2], "cycloneiii") == 0) {
|
||||
family = INTEL_CYCLONEIII;
|
||||
} else if (strcmp(CMD_ARGV[2], "cycloneiv") == 0) {
|
||||
family = INTEL_CYCLONEIV;
|
||||
} else if (strcmp(CMD_ARGV[2], "cyclonev") == 0) {
|
||||
family = INTEL_CYCLONEV;
|
||||
} else if (strcmp(CMD_ARGV[2], "cyclone10") == 0) {
|
||||
family = INTEL_CYCLONE10;
|
||||
} else if (strcmp(CMD_ARGV[2], "arriaii") == 0) {
|
||||
family = INTEL_ARRIAII;
|
||||
} else {
|
||||
command_print(CMD, "unknown family");
|
||||
free(intel_info);
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
}
|
||||
intel_info->tap = tap;
|
||||
intel_info->boundary_scan_length = 0;
|
||||
intel_info->checkpos = -1;
|
||||
|
@ -441,16 +467,16 @@ PLD_DEVICE_COMMAND_HANDLER(intel_pld_device_command)
|
|||
static const struct command_registration intel_exec_command_handlers[] = {
|
||||
{
|
||||
.name = "set_bscan",
|
||||
.mode = COMMAND_EXEC,
|
||||
.mode = COMMAND_ANY,
|
||||
.handler = intel_set_bscan_command_handler,
|
||||
.help = "set boundary scan register length of FPGA",
|
||||
.usage = "num_pld len",
|
||||
.usage = "pld_name len",
|
||||
}, {
|
||||
.name = "set_check_pos",
|
||||
.mode = COMMAND_EXEC,
|
||||
.mode = COMMAND_ANY,
|
||||
.handler = intel_set_check_pos_command_handler,
|
||||
.help = "set check_pos of FPGA",
|
||||
.usage = "num_pld pos",
|
||||
.usage = "pld_name pos",
|
||||
},
|
||||
COMMAND_REGISTRATION_DONE
|
||||
};
|
||||
|
@ -469,6 +495,7 @@ static const struct command_registration intel_command_handler[] = {
|
|||
struct pld_driver intel_pld = {
|
||||
.name = "intel",
|
||||
.commands = intel_command_handler,
|
||||
.pld_device_command = &intel_pld_device_command,
|
||||
.pld_create_command = &intel_pld_create_command,
|
||||
.load = &intel_load,
|
||||
.get_ipdbg_hub = intel_get_ipdbg_hub,
|
||||
};
|
||||
|
|
|
@ -18,6 +18,9 @@
|
|||
#include "certus.h"
|
||||
|
||||
#define PRELOAD 0x1C
|
||||
#define USER1 0x32
|
||||
#define USER2 0x38
|
||||
|
||||
|
||||
struct lattice_devices_elem {
|
||||
uint32_t id;
|
||||
|
@ -316,39 +319,69 @@ static int lattice_load_command(struct pld_device *pld_device, const char *filen
|
|||
return retval;
|
||||
}
|
||||
|
||||
PLD_DEVICE_COMMAND_HANDLER(lattice_pld_device_command)
|
||||
static int lattice_get_ipdbg_hub(int user_num, struct pld_device *pld_device, struct pld_ipdbg_hub *hub)
|
||||
{
|
||||
if (CMD_ARGC < 2 || CMD_ARGC > 3)
|
||||
if (!pld_device)
|
||||
return ERROR_FAIL;
|
||||
|
||||
struct lattice_pld_device *pld_device_info = pld_device->driver_priv;
|
||||
|
||||
if (!pld_device_info || !pld_device_info->tap)
|
||||
return ERROR_FAIL;
|
||||
|
||||
hub->tap = pld_device_info->tap;
|
||||
|
||||
if (user_num == 1) {
|
||||
hub->user_ir_code = USER1;
|
||||
} else if (user_num == 2) {
|
||||
hub->user_ir_code = USER2;
|
||||
} else {
|
||||
LOG_ERROR("lattice devices only have user register 1 & 2");
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
PLD_CREATE_COMMAND_HANDLER(lattice_pld_create_command)
|
||||
{
|
||||
if (CMD_ARGC != 4 && CMD_ARGC != 6)
|
||||
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||
|
||||
struct jtag_tap *tap = jtag_tap_by_string(CMD_ARGV[1]);
|
||||
if (strcmp(CMD_ARGV[2], "-chain-position") != 0)
|
||||
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||
|
||||
struct jtag_tap *tap = jtag_tap_by_string(CMD_ARGV[3]);
|
||||
if (!tap) {
|
||||
command_print(CMD, "Tap: %s does not exist", CMD_ARGV[1]);
|
||||
command_print(CMD, "Tap: %s does not exist", CMD_ARGV[3]);
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
|
||||
/* id is not known yet -> postpone lattice_check_device_family() */
|
||||
enum lattice_family_e family = LATTICE_UNKNOWN;
|
||||
if (CMD_ARGC == 6) {
|
||||
if (strcmp(CMD_ARGV[4], "-family") != 0)
|
||||
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||
|
||||
if (strcasecmp(CMD_ARGV[5], "ecp2") == 0) {
|
||||
family = LATTICE_ECP2;
|
||||
} else if (strcasecmp(CMD_ARGV[5], "ecp3") == 0) {
|
||||
family = LATTICE_ECP3;
|
||||
} else if (strcasecmp(CMD_ARGV[5], "ecp5") == 0) {
|
||||
family = LATTICE_ECP5;
|
||||
} else if (strcasecmp(CMD_ARGV[5], "certus") == 0) {
|
||||
family = LATTICE_CERTUS;
|
||||
} else {
|
||||
command_print(CMD, "unknown family");
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
}
|
||||
|
||||
struct lattice_pld_device *lattice_device = malloc(sizeof(struct lattice_pld_device));
|
||||
if (!lattice_device) {
|
||||
LOG_ERROR("Out of memory");
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
/* id is not known yet -> postpone lattice_check_device_family() */
|
||||
enum lattice_family_e family = LATTICE_UNKNOWN;
|
||||
if (CMD_ARGC == 3) {
|
||||
if (strcasecmp(CMD_ARGV[2], "ecp2") == 0) {
|
||||
family = LATTICE_ECP2;
|
||||
} else if (strcasecmp(CMD_ARGV[2], "ecp3") == 0) {
|
||||
family = LATTICE_ECP3;
|
||||
} else if (strcasecmp(CMD_ARGV[2], "ecp5") == 0) {
|
||||
family = LATTICE_ECP5;
|
||||
} else if (strcasecmp(CMD_ARGV[2], "certus") == 0) {
|
||||
family = LATTICE_CERTUS;
|
||||
} else {
|
||||
command_print(CMD, "unknown family");
|
||||
free(lattice_device);
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
}
|
||||
|
||||
lattice_device->tap = tap;
|
||||
lattice_device->family = family;
|
||||
lattice_device->preload_length = 0;
|
||||
|
@ -360,16 +393,14 @@ PLD_DEVICE_COMMAND_HANDLER(lattice_pld_device_command)
|
|||
|
||||
COMMAND_HANDLER(lattice_read_usercode_register_command_handler)
|
||||
{
|
||||
int dev_id;
|
||||
uint32_t usercode;
|
||||
|
||||
if (CMD_ARGC != 1)
|
||||
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||
|
||||
COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], dev_id);
|
||||
struct pld_device *device = get_pld_device_by_num(dev_id);
|
||||
struct pld_device *device = get_pld_device_by_name_or_numstr(CMD_ARGV[0]);
|
||||
if (!device) {
|
||||
command_print(CMD, "pld device '#%s' is out of bounds", CMD_ARGV[0]);
|
||||
command_print(CMD, "pld device '#%s' is out of bounds or unknown", CMD_ARGV[0]);
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
|
||||
|
@ -390,16 +421,14 @@ COMMAND_HANDLER(lattice_read_usercode_register_command_handler)
|
|||
|
||||
COMMAND_HANDLER(lattice_set_preload_command_handler)
|
||||
{
|
||||
int dev_id;
|
||||
unsigned int preload_length;
|
||||
|
||||
if (CMD_ARGC != 2)
|
||||
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||
|
||||
COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], dev_id);
|
||||
struct pld_device *device = get_pld_device_by_num(dev_id);
|
||||
struct pld_device *device = get_pld_device_by_name_or_numstr(CMD_ARGV[0]);
|
||||
if (!device) {
|
||||
command_print(CMD, "pld device '#%s' is out of bounds", CMD_ARGV[0]);
|
||||
command_print(CMD, "pld device '#%s' is out of bounds or unknown", CMD_ARGV[0]);
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
|
||||
|
@ -417,16 +446,14 @@ COMMAND_HANDLER(lattice_set_preload_command_handler)
|
|||
|
||||
COMMAND_HANDLER(lattice_write_usercode_register_command_handler)
|
||||
{
|
||||
int dev_id;
|
||||
uint32_t usercode;
|
||||
|
||||
if (CMD_ARGC != 2)
|
||||
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||
|
||||
COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], dev_id);
|
||||
struct pld_device *device = get_pld_device_by_num(dev_id);
|
||||
struct pld_device *device = get_pld_device_by_name_or_numstr(CMD_ARGV[0]);
|
||||
if (!device) {
|
||||
command_print(CMD, "pld device '#%s' is out of bounds", CMD_ARGV[0]);
|
||||
command_print(CMD, "pld device '#%s' is out of bounds or unknown", CMD_ARGV[0]);
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
|
||||
|
@ -445,15 +472,12 @@ COMMAND_HANDLER(lattice_write_usercode_register_command_handler)
|
|||
|
||||
COMMAND_HANDLER(lattice_read_status_command_handler)
|
||||
{
|
||||
int dev_id;
|
||||
|
||||
if (CMD_ARGC != 1)
|
||||
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||
|
||||
COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], dev_id);
|
||||
struct pld_device *device = get_pld_device_by_num(dev_id);
|
||||
struct pld_device *device = get_pld_device_by_name_or_numstr(CMD_ARGV[0]);
|
||||
if (!device) {
|
||||
command_print(CMD, "pld device '#%s' is out of bounds", CMD_ARGV[0]);
|
||||
command_print(CMD, "pld device '#%s' is out of bounds or unknown", CMD_ARGV[0]);
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
|
||||
|
@ -487,25 +511,25 @@ static const struct command_registration lattice_exec_command_handlers[] = {
|
|||
.mode = COMMAND_EXEC,
|
||||
.handler = lattice_read_status_command_handler,
|
||||
.help = "reading status register from FPGA",
|
||||
.usage = "num_pld",
|
||||
.usage = "pld_name",
|
||||
}, {
|
||||
.name = "read_user",
|
||||
.mode = COMMAND_EXEC,
|
||||
.handler = lattice_read_usercode_register_command_handler,
|
||||
.help = "reading usercode register from FPGA",
|
||||
.usage = "num_pld",
|
||||
.usage = "pld_name",
|
||||
}, {
|
||||
.name = "write_user",
|
||||
.mode = COMMAND_EXEC,
|
||||
.handler = lattice_write_usercode_register_command_handler,
|
||||
.help = "writing usercode register to FPGA",
|
||||
.usage = "num_pld value",
|
||||
.usage = "pld_name value",
|
||||
}, {
|
||||
.name = "set_preload",
|
||||
.mode = COMMAND_EXEC,
|
||||
.mode = COMMAND_ANY,
|
||||
.handler = lattice_set_preload_command_handler,
|
||||
.help = "set length for preload (device specific)",
|
||||
.usage = "num_pld value",
|
||||
.usage = "pld_name value",
|
||||
},
|
||||
COMMAND_REGISTRATION_DONE
|
||||
};
|
||||
|
@ -524,6 +548,7 @@ static const struct command_registration lattice_command_handler[] = {
|
|||
struct pld_driver lattice_pld = {
|
||||
.name = "lattice",
|
||||
.commands = lattice_command_handler,
|
||||
.pld_device_command = &lattice_pld_device_command,
|
||||
.pld_create_command = &lattice_pld_create_command,
|
||||
.load = &lattice_load_command,
|
||||
.get_ipdbg_hub = lattice_get_ipdbg_hub,
|
||||
};
|
||||
|
|
164
src/pld/pld.c
164
src/pld/pld.c
|
@ -34,68 +34,110 @@ struct pld_device *get_pld_device_by_num(int num)
|
|||
int i = 0;
|
||||
|
||||
for (p = pld_devices; p; p = p->next) {
|
||||
if (i++ == num)
|
||||
if (i++ == num) {
|
||||
LOG_WARNING("DEPRECATED: use pld name \"%s\" instead of number %d", p->name, num);
|
||||
return p;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct pld_device *get_pld_device_by_name(const char *name)
|
||||
{
|
||||
for (struct pld_device *p = pld_devices; p; p = p->next) {
|
||||
if (strcmp(p->name, name) == 0)
|
||||
return p;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* pld device <driver> [driver_options ...]
|
||||
*/
|
||||
COMMAND_HANDLER(handle_pld_device_command)
|
||||
struct pld_device *get_pld_device_by_name_or_numstr(const char *str)
|
||||
{
|
||||
int i;
|
||||
int found = 0;
|
||||
struct pld_device *dev = get_pld_device_by_name(str);
|
||||
if (dev)
|
||||
return dev;
|
||||
|
||||
if (CMD_ARGC < 1)
|
||||
char *end;
|
||||
unsigned long dev_num = strtoul(str, &end, 0);
|
||||
if (*end || dev_num > INT_MAX) {
|
||||
LOG_ERROR("Invalid argument");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return get_pld_device_by_num(dev_num);
|
||||
}
|
||||
|
||||
/* @deffn {Config Command} {pld create} pld_name driver -chain-position tap_name [options]
|
||||
*/
|
||||
COMMAND_HANDLER(handle_pld_create_command)
|
||||
{
|
||||
if (CMD_ARGC < 2)
|
||||
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||
|
||||
for (i = 0; pld_drivers[i]; i++) {
|
||||
if (strcmp(CMD_ARGV[0], pld_drivers[i]->name) == 0) {
|
||||
struct pld_device *p, *c;
|
||||
struct pld_driver *pld_driver = NULL;
|
||||
|
||||
/* register pld specific commands */
|
||||
int retval;
|
||||
if (pld_drivers[i]->commands) {
|
||||
retval = register_commands(CMD_CTX, NULL, pld_drivers[i]->commands);
|
||||
if (retval != ERROR_OK) {
|
||||
LOG_ERROR("couldn't register '%s' commands", CMD_ARGV[0]);
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
}
|
||||
|
||||
c = malloc(sizeof(struct pld_device));
|
||||
c->driver = pld_drivers[i];
|
||||
c->next = NULL;
|
||||
|
||||
retval = CALL_COMMAND_HANDLER(
|
||||
pld_drivers[i]->pld_device_command, c);
|
||||
if (retval != ERROR_OK) {
|
||||
LOG_ERROR("'%s' driver rejected pld device",
|
||||
CMD_ARGV[0]);
|
||||
free(c);
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
/* put pld device in linked list */
|
||||
if (pld_devices) {
|
||||
/* find last pld device */
|
||||
for (p = pld_devices; p && p->next; p = p->next)
|
||||
;
|
||||
if (p)
|
||||
p->next = c;
|
||||
} else
|
||||
pld_devices = c;
|
||||
|
||||
found = 1;
|
||||
for (int i = 0; pld_drivers[i]; i++) {
|
||||
if (strcmp(CMD_ARGV[1], pld_drivers[i]->name) == 0) {
|
||||
pld_driver = pld_drivers[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* no matching pld driver found */
|
||||
if (!found) {
|
||||
LOG_ERROR("pld driver '%s' not found", CMD_ARGV[0]);
|
||||
exit(-1);
|
||||
if (!pld_driver) {
|
||||
LOG_ERROR("pld driver '%s' not found", CMD_ARGV[1]);
|
||||
return ERROR_FAIL; /* exit(-1); */
|
||||
}
|
||||
|
||||
if (get_pld_device_by_name(CMD_ARGV[0])) {
|
||||
LOG_ERROR("pld device with name '%s' already exists", CMD_ARGV[0]);
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
|
||||
struct pld_device *pld_device = malloc(sizeof(struct pld_device));
|
||||
if (!pld_device) {
|
||||
LOG_ERROR("Out of memory");
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
|
||||
pld_device->driver = pld_driver;
|
||||
pld_device->next = NULL;
|
||||
|
||||
int retval = CALL_COMMAND_HANDLER(pld_driver->pld_create_command, pld_device);
|
||||
if (retval != ERROR_OK) {
|
||||
LOG_ERROR("'%s' driver rejected pld device",
|
||||
CMD_ARGV[1]);
|
||||
free(pld_device);
|
||||
return ERROR_OK;
|
||||
}
|
||||
pld_device->name = strdup(CMD_ARGV[0]);
|
||||
if (!pld_device->name) {
|
||||
LOG_ERROR("Out of memory");
|
||||
free(pld_device);
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
|
||||
/* register pld specific commands */
|
||||
if (pld_driver->commands) {
|
||||
retval = register_commands(CMD_CTX, NULL, pld_driver->commands);
|
||||
if (retval != ERROR_OK) {
|
||||
LOG_ERROR("couldn't register '%s' commands", CMD_ARGV[1]);
|
||||
free(pld_device->name);
|
||||
free(pld_device);
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
}
|
||||
|
||||
if (pld_devices) {
|
||||
/* find last pld device */
|
||||
struct pld_device *p = pld_devices;
|
||||
for (; p && p->next; p = p->next)
|
||||
;
|
||||
if (p)
|
||||
p->next = pld_device;
|
||||
} else {
|
||||
pld_devices = pld_device;
|
||||
}
|
||||
|
||||
return ERROR_OK;
|
||||
|
@ -112,7 +154,7 @@ COMMAND_HANDLER(handle_pld_devices_command)
|
|||
}
|
||||
|
||||
for (p = pld_devices; p; p = p->next)
|
||||
command_print(CMD, "#%i: %s", i++, p->driver->name);
|
||||
command_print(CMD, "#%i: %s (driver: %s)", i++, p->name, p->driver->name);
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
@ -128,11 +170,9 @@ COMMAND_HANDLER(handle_pld_load_command)
|
|||
if (CMD_ARGC < 2)
|
||||
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||
|
||||
unsigned dev_id;
|
||||
COMMAND_PARSE_NUMBER(uint, CMD_ARGV[0], dev_id);
|
||||
p = get_pld_device_by_num(dev_id);
|
||||
p = get_pld_device_by_name_or_numstr(CMD_ARGV[0]);
|
||||
if (!p) {
|
||||
command_print(CMD, "pld device '#%s' is out of bounds", CMD_ARGV[0]);
|
||||
command_print(CMD, "pld device '#%s' is out of bounds or unknown", CMD_ARGV[0]);
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
|
@ -154,15 +194,15 @@ COMMAND_HANDLER(handle_pld_load_command)
|
|||
|
||||
retval = p->driver->load(p, CMD_ARGV[1]);
|
||||
if (retval != ERROR_OK) {
|
||||
command_print(CMD, "failed loading file %s to pld device %u",
|
||||
CMD_ARGV[1], dev_id);
|
||||
command_print(CMD, "failed loading file %s to pld device %s",
|
||||
CMD_ARGV[1], CMD_ARGV[0]);
|
||||
return retval;
|
||||
} else {
|
||||
gettimeofday(&end, NULL);
|
||||
timeval_subtract(&duration, &end, &start);
|
||||
|
||||
command_print(CMD, "loaded file %s to pld device %u in %jis %jius",
|
||||
CMD_ARGV[1], dev_id,
|
||||
command_print(CMD, "loaded file %s to pld device %s in %jis %jius",
|
||||
CMD_ARGV[1], CMD_ARGV[0],
|
||||
(intmax_t)duration.tv_sec, (intmax_t)duration.tv_usec);
|
||||
}
|
||||
|
||||
|
@ -182,7 +222,7 @@ static const struct command_registration pld_exec_command_handlers[] = {
|
|||
.handler = handle_pld_load_command,
|
||||
.mode = COMMAND_EXEC,
|
||||
.help = "load configuration file into PLD",
|
||||
.usage = "pld_num filename",
|
||||
.usage = "pld_name filename",
|
||||
},
|
||||
COMMAND_REGISTRATION_DONE
|
||||
};
|
||||
|
@ -213,11 +253,11 @@ COMMAND_HANDLER(handle_pld_init_command)
|
|||
|
||||
static const struct command_registration pld_config_command_handlers[] = {
|
||||
{
|
||||
.name = "device",
|
||||
.name = "create",
|
||||
.mode = COMMAND_CONFIG,
|
||||
.handler = handle_pld_device_command,
|
||||
.help = "configure a PLD device",
|
||||
.usage = "driver_name [driver_args ... ]",
|
||||
.handler = handle_pld_create_command,
|
||||
.help = "create a PLD device",
|
||||
.usage = "name.pld driver_name [driver_args ... ]",
|
||||
},
|
||||
{
|
||||
.name = "init",
|
||||
|
|
|
@ -12,28 +12,37 @@
|
|||
|
||||
struct pld_device;
|
||||
|
||||
#define __PLD_DEVICE_COMMAND(name) \
|
||||
#define __PLD_CREATE_COMMAND(name) \
|
||||
COMMAND_HELPER(name, struct pld_device *pld)
|
||||
|
||||
struct pld_ipdbg_hub {
|
||||
struct jtag_tap *tap;
|
||||
unsigned int user_ir_code;
|
||||
};
|
||||
|
||||
struct pld_driver {
|
||||
const char *name;
|
||||
__PLD_DEVICE_COMMAND((*pld_device_command));
|
||||
__PLD_CREATE_COMMAND((*pld_create_command));
|
||||
const struct command_registration *commands;
|
||||
int (*load)(struct pld_device *pld_device, const char *filename);
|
||||
int (*get_ipdbg_hub)(int user_num, struct pld_device *pld_device, struct pld_ipdbg_hub *hub);
|
||||
};
|
||||
|
||||
#define PLD_DEVICE_COMMAND_HANDLER(name) \
|
||||
static __PLD_DEVICE_COMMAND(name)
|
||||
#define PLD_CREATE_COMMAND_HANDLER(name) \
|
||||
static __PLD_CREATE_COMMAND(name)
|
||||
|
||||
struct pld_device {
|
||||
struct pld_driver *driver;
|
||||
void *driver_priv;
|
||||
struct pld_device *next;
|
||||
char *name;
|
||||
};
|
||||
|
||||
int pld_register_commands(struct command_context *cmd_ctx);
|
||||
|
||||
struct pld_device *get_pld_device_by_num(int num);
|
||||
struct pld_device *get_pld_device_by_name(const char *name);
|
||||
struct pld_device *get_pld_device_by_name_or_numstr(const char *str);
|
||||
|
||||
#define ERROR_PLD_DEVICE_INVALID (-1000)
|
||||
#define ERROR_PLD_FILE_LOAD_FAILED (-1001)
|
||||
|
|
|
@ -13,12 +13,23 @@
|
|||
#include "xilinx_bit.h"
|
||||
#include "pld.h"
|
||||
|
||||
static int virtex2_set_instr(struct jtag_tap *tap, uint32_t new_instr)
|
||||
static const struct virtex2_command_set virtex2_default_commands = {
|
||||
.cfg_out = 0x04,
|
||||
.cfg_in = 0x05,
|
||||
.jprog_b = 0x0b,
|
||||
.jstart = 0x0c,
|
||||
.jshutdown = 0x0d,
|
||||
.bypass = 0x3f,
|
||||
.user = {0x02, 0x03},
|
||||
.num_user = 2, /* virtex II has only 2 user instructions */
|
||||
};
|
||||
|
||||
static int virtex2_set_instr(struct jtag_tap *tap, uint64_t new_instr)
|
||||
{
|
||||
if (!tap)
|
||||
return ERROR_FAIL;
|
||||
|
||||
if (buf_get_u32(tap->cur_instr, 0, tap->ir_length) != new_instr) {
|
||||
if (buf_get_u64(tap->cur_instr, 0, tap->ir_length) != new_instr) {
|
||||
struct scan_field field;
|
||||
|
||||
field.num_bits = tap->ir_length;
|
||||
|
@ -28,7 +39,7 @@ static int virtex2_set_instr(struct jtag_tap *tap, uint32_t new_instr)
|
|||
return ERROR_FAIL;
|
||||
}
|
||||
field.out_value = t;
|
||||
buf_set_u32(t, 0, field.num_bits, new_instr);
|
||||
buf_set_u64(t, 0, field.num_bits, new_instr);
|
||||
field.in_value = NULL;
|
||||
|
||||
jtag_add_ir_scan(tap, &field, TAP_IDLE);
|
||||
|
@ -60,7 +71,7 @@ static int virtex2_send_32(struct pld_device *pld_device,
|
|||
for (i = 0; i < num_words; i++)
|
||||
buf_set_u32(values + 4 * i, 0, 32, flip_u32(*words++, 32));
|
||||
|
||||
int retval = virtex2_set_instr(virtex2_info->tap, 0x5); /* CFG_IN */
|
||||
int retval = virtex2_set_instr(virtex2_info->tap, virtex2_info->command_set.cfg_in);
|
||||
if (retval != ERROR_OK) {
|
||||
free(values);
|
||||
return retval;
|
||||
|
@ -89,7 +100,7 @@ static int virtex2_receive_32(struct pld_device *pld_device,
|
|||
scan_field.out_value = NULL;
|
||||
scan_field.in_value = NULL;
|
||||
|
||||
int retval = virtex2_set_instr(virtex2_info->tap, 0x4); /* CFG_OUT */
|
||||
int retval = virtex2_set_instr(virtex2_info->tap, virtex2_info->command_set.cfg_out);
|
||||
if (retval != ERROR_OK)
|
||||
return retval;
|
||||
|
||||
|
@ -132,12 +143,41 @@ static int virtex2_read_stat(struct pld_device *pld_device, uint32_t *status)
|
|||
return retval;
|
||||
}
|
||||
|
||||
static int virtex2_program(struct pld_device *pld_device)
|
||||
{
|
||||
struct virtex2_pld_device *virtex2_info = pld_device->driver_priv;
|
||||
if (!virtex2_info)
|
||||
return ERROR_FAIL;
|
||||
|
||||
int retval = virtex2_set_instr(virtex2_info->tap, virtex2_info->command_set.jshutdown);
|
||||
if (retval != ERROR_OK)
|
||||
return retval;
|
||||
|
||||
retval = virtex2_set_instr(virtex2_info->tap, virtex2_info->command_set.jprog_b);
|
||||
if (retval != ERROR_OK)
|
||||
return retval;
|
||||
|
||||
jtag_add_runtest(62000, TAP_IDLE);
|
||||
if (!(virtex2_info->no_jstart)) {
|
||||
retval = virtex2_set_instr(virtex2_info->tap, virtex2_info->command_set.jstart);
|
||||
if (retval != ERROR_OK)
|
||||
return retval;
|
||||
}
|
||||
|
||||
retval = virtex2_set_instr(virtex2_info->tap, virtex2_info->command_set.bypass);
|
||||
if (retval != ERROR_OK)
|
||||
return retval;
|
||||
jtag_add_runtest(2000, TAP_IDLE);
|
||||
|
||||
return jtag_execute_queue();
|
||||
}
|
||||
|
||||
static int virtex2_load_prepare(struct pld_device *pld_device)
|
||||
{
|
||||
struct virtex2_pld_device *virtex2_info = pld_device->driver_priv;
|
||||
int retval;
|
||||
|
||||
retval = virtex2_set_instr(virtex2_info->tap, 0xb); /* JPROG_B */
|
||||
retval = virtex2_set_instr(virtex2_info->tap, virtex2_info->command_set.jprog_b);
|
||||
if (retval != ERROR_OK)
|
||||
return retval;
|
||||
|
||||
|
@ -146,7 +186,7 @@ static int virtex2_load_prepare(struct pld_device *pld_device)
|
|||
return retval;
|
||||
jtag_add_sleep(1000);
|
||||
|
||||
retval = virtex2_set_instr(virtex2_info->tap, 0x5); /* CFG_IN */
|
||||
retval = virtex2_set_instr(virtex2_info->tap, virtex2_info->command_set.cfg_in);
|
||||
if (retval != ERROR_OK)
|
||||
return retval;
|
||||
|
||||
|
@ -161,24 +201,24 @@ static int virtex2_load_cleanup(struct pld_device *pld_device)
|
|||
jtag_add_tlr();
|
||||
|
||||
if (!(virtex2_info->no_jstart)) {
|
||||
retval = virtex2_set_instr(virtex2_info->tap, 0xc); /* JSTART */
|
||||
retval = virtex2_set_instr(virtex2_info->tap, virtex2_info->command_set.jstart);
|
||||
if (retval != ERROR_OK)
|
||||
return retval;
|
||||
}
|
||||
jtag_add_runtest(13, TAP_IDLE);
|
||||
retval = virtex2_set_instr(virtex2_info->tap, 0x3f); /* BYPASS */
|
||||
retval = virtex2_set_instr(virtex2_info->tap, virtex2_info->command_set.bypass);
|
||||
if (retval != ERROR_OK)
|
||||
return retval;
|
||||
retval = virtex2_set_instr(virtex2_info->tap, 0x3f); /* BYPASS */
|
||||
retval = virtex2_set_instr(virtex2_info->tap, virtex2_info->command_set.bypass);
|
||||
if (retval != ERROR_OK)
|
||||
return retval;
|
||||
if (!(virtex2_info->no_jstart)) {
|
||||
retval = virtex2_set_instr(virtex2_info->tap, 0xc); /* JSTART */
|
||||
retval = virtex2_set_instr(virtex2_info->tap, virtex2_info->command_set.jstart);
|
||||
if (retval != ERROR_OK)
|
||||
return retval;
|
||||
}
|
||||
jtag_add_runtest(13, TAP_IDLE);
|
||||
retval = virtex2_set_instr(virtex2_info->tap, 0x3f); /* BYPASS */
|
||||
retval = virtex2_set_instr(virtex2_info->tap, virtex2_info->command_set.bypass);
|
||||
if (retval != ERROR_OK)
|
||||
return retval;
|
||||
|
||||
|
@ -225,6 +265,22 @@ static int virtex2_load(struct pld_device *pld_device, const char *filename)
|
|||
return retval;
|
||||
}
|
||||
|
||||
COMMAND_HANDLER(virtex2_handle_program_command)
|
||||
{
|
||||
struct pld_device *device;
|
||||
|
||||
if (CMD_ARGC != 1)
|
||||
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||
|
||||
device = get_pld_device_by_name_or_numstr(CMD_ARGV[0]);
|
||||
if (!device) {
|
||||
command_print(CMD, "pld device '#%s' is out of bounds or unknown", CMD_ARGV[0]);
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
|
||||
return virtex2_program(device);
|
||||
}
|
||||
|
||||
COMMAND_HANDLER(virtex2_handle_read_stat_command)
|
||||
{
|
||||
struct pld_device *device;
|
||||
|
@ -233,11 +289,9 @@ COMMAND_HANDLER(virtex2_handle_read_stat_command)
|
|||
if (CMD_ARGC < 1)
|
||||
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||
|
||||
unsigned dev_id;
|
||||
COMMAND_PARSE_NUMBER(uint, CMD_ARGV[0], dev_id);
|
||||
device = get_pld_device_by_num(dev_id);
|
||||
device = get_pld_device_by_name_or_numstr(CMD_ARGV[0]);
|
||||
if (!device) {
|
||||
command_print(CMD, "pld device '#%s' is out of bounds", CMD_ARGV[0]);
|
||||
command_print(CMD, "pld device '#%s' is out of bounds or unknown", CMD_ARGV[0]);
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
|
||||
|
@ -252,31 +306,107 @@ COMMAND_HANDLER(virtex2_handle_read_stat_command)
|
|||
return ERROR_OK;
|
||||
}
|
||||
|
||||
PLD_DEVICE_COMMAND_HANDLER(virtex2_pld_device_command)
|
||||
static int xilinx_get_ipdbg_hub(int user_num, struct pld_device *pld_device, struct pld_ipdbg_hub *hub)
|
||||
{
|
||||
struct jtag_tap *tap;
|
||||
if (!pld_device)
|
||||
return ERROR_FAIL;
|
||||
|
||||
struct virtex2_pld_device *virtex2_info;
|
||||
struct virtex2_pld_device *pld_device_info = pld_device->driver_priv;
|
||||
|
||||
if (CMD_ARGC < 2)
|
||||
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||
if (!pld_device_info || !pld_device_info->tap)
|
||||
return ERROR_FAIL;
|
||||
|
||||
tap = jtag_tap_by_string(CMD_ARGV[1]);
|
||||
if (!tap) {
|
||||
command_print(CMD, "Tap: %s does not exist", CMD_ARGV[1]);
|
||||
hub->tap = pld_device_info->tap;
|
||||
if (user_num < 1 || (unsigned int)user_num > pld_device_info->command_set.num_user) {
|
||||
LOG_ERROR("device has only user register 1 to %d", pld_device_info->command_set.num_user);
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
|
||||
virtex2_info = malloc(sizeof(struct virtex2_pld_device));
|
||||
hub->user_ir_code = pld_device_info->command_set.user[user_num - 1];
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
COMMAND_HANDLER(virtex2_handle_set_instuction_codes_command)
|
||||
{
|
||||
if (CMD_ARGC < 6 || CMD_ARGC > (6 + VIRTEX2_MAX_USER_INSTRUCTIONS))
|
||||
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||
|
||||
struct pld_device *device = get_pld_device_by_name(CMD_ARGV[0]);
|
||||
if (!device) {
|
||||
command_print(CMD, "pld device '#%s' is unknown", CMD_ARGV[0]);
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
|
||||
struct virtex2_pld_device *virtex2_info = device->driver_priv;
|
||||
if (!virtex2_info)
|
||||
return ERROR_FAIL;
|
||||
|
||||
struct virtex2_command_set instr_codes;
|
||||
COMMAND_PARSE_NUMBER(u64, CMD_ARGV[1], instr_codes.cfg_out);
|
||||
COMMAND_PARSE_NUMBER(u64, CMD_ARGV[2], instr_codes.cfg_in);
|
||||
COMMAND_PARSE_NUMBER(u64, CMD_ARGV[3], instr_codes.jprog_b);
|
||||
COMMAND_PARSE_NUMBER(u64, CMD_ARGV[4], instr_codes.jstart);
|
||||
COMMAND_PARSE_NUMBER(u64, CMD_ARGV[5], instr_codes.jshutdown);
|
||||
instr_codes.bypass = 0xffffffffffffffffULL;
|
||||
|
||||
unsigned int num_user = CMD_ARGC - 6;
|
||||
for (unsigned int i = 0; i < num_user; ++i)
|
||||
COMMAND_PARSE_NUMBER(u64, CMD_ARGV[6 + i], instr_codes.user[i]);
|
||||
instr_codes.num_user = num_user;
|
||||
|
||||
virtex2_info->command_set = instr_codes;
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
COMMAND_HANDLER(virtex2_handle_set_user_codes_command)
|
||||
{
|
||||
if (CMD_ARGC < 2 || CMD_ARGC > (1 + VIRTEX2_MAX_USER_INSTRUCTIONS))
|
||||
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||
|
||||
struct pld_device *device = get_pld_device_by_name(CMD_ARGV[0]);
|
||||
if (!device) {
|
||||
command_print(CMD, "pld device '#%s' is unknown", CMD_ARGV[0]);
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
|
||||
struct virtex2_pld_device *virtex2_info = device->driver_priv;
|
||||
if (!virtex2_info)
|
||||
return ERROR_FAIL;
|
||||
|
||||
uint64_t user[VIRTEX2_MAX_USER_INSTRUCTIONS];
|
||||
unsigned int num_user = CMD_ARGC - 1;
|
||||
for (unsigned int i = 0; i < num_user; ++i)
|
||||
COMMAND_PARSE_NUMBER(u64, CMD_ARGV[1 + i], user[i]);
|
||||
virtex2_info->command_set.num_user = num_user;
|
||||
memcpy(virtex2_info->command_set.user, user, num_user * sizeof(uint64_t));
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
PLD_CREATE_COMMAND_HANDLER(virtex2_pld_create_command)
|
||||
{
|
||||
if (CMD_ARGC < 4)
|
||||
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||
|
||||
if (strcmp(CMD_ARGV[2], "-chain-position") != 0)
|
||||
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||
|
||||
struct jtag_tap *tap = jtag_tap_by_string(CMD_ARGV[3]);
|
||||
if (!tap) {
|
||||
command_print(CMD, "Tap: %s does not exist", CMD_ARGV[3]);
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
|
||||
struct virtex2_pld_device *virtex2_info = malloc(sizeof(struct virtex2_pld_device));
|
||||
if (!virtex2_info) {
|
||||
LOG_ERROR("Out of memory");
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
virtex2_info->tap = tap;
|
||||
virtex2_info->command_set = virtex2_default_commands;
|
||||
|
||||
virtex2_info->no_jstart = 0;
|
||||
if (CMD_ARGC >= 3)
|
||||
COMMAND_PARSE_NUMBER(int, CMD_ARGV[2], virtex2_info->no_jstart);
|
||||
if (CMD_ARGC >= 5 && strcmp(CMD_ARGV[4], "-no_jstart") == 0)
|
||||
virtex2_info->no_jstart = 1;
|
||||
|
||||
pld->driver_priv = virtex2_info;
|
||||
|
||||
|
@ -289,10 +419,30 @@ static const struct command_registration virtex2_exec_command_handlers[] = {
|
|||
.mode = COMMAND_EXEC,
|
||||
.handler = virtex2_handle_read_stat_command,
|
||||
.help = "read status register",
|
||||
.usage = "pld_num",
|
||||
.usage = "pld_name",
|
||||
}, {
|
||||
.name = "set_instr_codes",
|
||||
.mode = COMMAND_ANY,
|
||||
.handler = virtex2_handle_set_instuction_codes_command,
|
||||
.help = "set instructions codes used for loading the bitstream/refreshing/jtag-hub",
|
||||
.usage = "pld_name cfg_out cfg_in jprogb jstart jshutdown"
|
||||
" [user1 [user2 [user3 [user4]]]]",
|
||||
}, {
|
||||
.name = "set_user_codes",
|
||||
.mode = COMMAND_ANY,
|
||||
.handler = virtex2_handle_set_user_codes_command,
|
||||
.help = "set instructions codes used for jtag-hub",
|
||||
.usage = "pld_name user1 [user2 [user3 [user4]]]",
|
||||
}, {
|
||||
.name = "program",
|
||||
.mode = COMMAND_EXEC,
|
||||
.handler = virtex2_handle_program_command,
|
||||
.help = "start loading of configuration (refresh)",
|
||||
.usage = "pld_name",
|
||||
},
|
||||
COMMAND_REGISTRATION_DONE
|
||||
};
|
||||
|
||||
static const struct command_registration virtex2_command_handler[] = {
|
||||
{
|
||||
.name = "virtex2",
|
||||
|
@ -307,6 +457,7 @@ static const struct command_registration virtex2_command_handler[] = {
|
|||
struct pld_driver virtex2_pld = {
|
||||
.name = "virtex2",
|
||||
.commands = virtex2_command_handler,
|
||||
.pld_device_command = &virtex2_pld_device_command,
|
||||
.pld_create_command = &virtex2_pld_create_command,
|
||||
.load = &virtex2_load,
|
||||
.get_ipdbg_hub = xilinx_get_ipdbg_hub,
|
||||
};
|
||||
|
|
|
@ -10,9 +10,23 @@
|
|||
|
||||
#include <jtag/jtag.h>
|
||||
|
||||
#define VIRTEX2_MAX_USER_INSTRUCTIONS 4
|
||||
|
||||
struct virtex2_command_set {
|
||||
uint64_t cfg_out;
|
||||
uint64_t cfg_in;
|
||||
uint64_t jprog_b;
|
||||
uint64_t jstart;
|
||||
uint64_t jshutdown;
|
||||
uint64_t bypass;
|
||||
uint64_t user[VIRTEX2_MAX_USER_INSTRUCTIONS];
|
||||
unsigned int num_user;
|
||||
};
|
||||
|
||||
struct virtex2_pld_device {
|
||||
struct jtag_tap *tap;
|
||||
int no_jstart;
|
||||
struct virtex2_command_set command_set;
|
||||
};
|
||||
|
||||
#endif /* OPENOCD_PLD_VIRTEX2_H */
|
||||
|
|
|
@ -1836,7 +1836,7 @@ static int gdb_breakpoint_watchpoint_packet(struct connection *connection,
|
|||
case 4:
|
||||
{
|
||||
if (packet[0] == 'Z') {
|
||||
retval = watchpoint_add(target, address, size, wp_type, 0, 0xffffffffu);
|
||||
retval = watchpoint_add(target, address, size, wp_type, 0, WATCHPOINT_IGNORE_DATA_VALUE_MASK);
|
||||
if (retval == ERROR_NOT_IMPLEMENTED) {
|
||||
/* Send empty reply to report that watchpoints of this type are not supported */
|
||||
gdb_put_packet(connection, "", 0);
|
||||
|
|
|
@ -10,11 +10,12 @@
|
|||
#include <jtag/jtag.h>
|
||||
#include <server/server.h>
|
||||
#include <target/target.h>
|
||||
#include <pld/pld.h>
|
||||
|
||||
#include "ipdbg.h"
|
||||
|
||||
#define IPDBG_BUFFER_SIZE 16384
|
||||
#define IPDBG_MIN_NUM_OF_OPTIONS 4
|
||||
#define IPDBG_MIN_NUM_OF_OPTIONS 2
|
||||
#define IPDBG_MAX_NUM_OF_OPTIONS 14
|
||||
#define IPDBG_MIN_DR_LENGTH 11
|
||||
#define IPDBG_MAX_DR_LENGTH 13
|
||||
|
@ -631,10 +632,8 @@ static int ipdbg_start(uint16_t port, struct jtag_tap *tap, uint32_t user_instru
|
|||
}
|
||||
} else {
|
||||
int retval = ipdbg_create_hub(tap, user_instruction, data_register_length, virtual_ir, &hub);
|
||||
if (retval != ERROR_OK) {
|
||||
free(virtual_ir);
|
||||
if (retval != ERROR_OK)
|
||||
return retval;
|
||||
}
|
||||
}
|
||||
|
||||
struct ipdbg_service *service = NULL;
|
||||
|
@ -716,6 +715,7 @@ COMMAND_HANDLER(handle_ipdbg_command)
|
|||
uint32_t virtual_ir_length = 5;
|
||||
uint32_t virtual_ir_value = 0x11;
|
||||
struct ipdbg_virtual_ir_info *virtual_ir = NULL;
|
||||
int user_num = 1;
|
||||
|
||||
if ((CMD_ARGC < IPDBG_MIN_NUM_OF_OPTIONS) || (CMD_ARGC > IPDBG_MAX_NUM_OF_OPTIONS))
|
||||
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||
|
@ -742,6 +742,34 @@ COMMAND_HANDLER(handle_ipdbg_command)
|
|||
IPDBG_MIN_DR_LENGTH, IPDBG_MAX_DR_LENGTH);
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
} else if (strcmp(CMD_ARGV[i], "-pld") == 0) {
|
||||
++i;
|
||||
if (i >= CMD_ARGC || CMD_ARGV[i][0] == '-')
|
||||
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||
struct pld_device *device = get_pld_device_by_name_or_numstr(CMD_ARGV[i]);
|
||||
if (!device || !device->driver) {
|
||||
command_print(CMD, "pld device '#%s' is out of bounds or unknown", CMD_ARGV[i]);
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
COMMAND_PARSE_OPTIONAL_NUMBER(int, i, user_num);
|
||||
struct pld_ipdbg_hub pld_hub;
|
||||
struct pld_driver *driver = device->driver;
|
||||
if (!driver->get_ipdbg_hub) {
|
||||
command_print(CMD, "pld driver has no ipdbg support");
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
if (driver->get_ipdbg_hub(user_num, device, &pld_hub) != ERROR_OK) {
|
||||
command_print(CMD, "unable to retrieve hub from pld driver");
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
if (!pld_hub.tap) {
|
||||
command_print(CMD, "no tap received from pld driver");
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
hub_configured = true;
|
||||
user_instruction = pld_hub.user_ir_code;
|
||||
tap = pld_hub.tap;
|
||||
|
||||
} else if (strcmp(CMD_ARGV[i], "-vir") == 0) {
|
||||
COMMAND_PARSE_OPTIONAL_NUMBER(u32, i, virtual_ir_value);
|
||||
COMMAND_PARSE_OPTIONAL_NUMBER(u32, i, virtual_ir_length);
|
||||
|
|
|
@ -846,8 +846,10 @@ static int aarch64_resume(struct target *target, int current,
|
|||
struct armv8_common *armv8 = target_to_armv8(target);
|
||||
armv8->last_run_control_op = ARMV8_RUNCONTROL_RESUME;
|
||||
|
||||
if (target->state != TARGET_HALTED)
|
||||
if (target->state != TARGET_HALTED) {
|
||||
LOG_TARGET_ERROR(target, "not halted");
|
||||
return ERROR_TARGET_NOT_HALTED;
|
||||
}
|
||||
|
||||
/*
|
||||
* If this target is part of a SMP group, prepare the others
|
||||
|
@ -1089,13 +1091,14 @@ static int aarch64_step(struct target *target, int current, target_addr_t addres
|
|||
struct armv8_common *armv8 = target_to_armv8(target);
|
||||
struct aarch64_common *aarch64 = target_to_aarch64(target);
|
||||
int saved_retval = ERROR_OK;
|
||||
int poll_retval;
|
||||
int retval;
|
||||
uint32_t edecr;
|
||||
|
||||
armv8->last_run_control_op = ARMV8_RUNCONTROL_STEP;
|
||||
|
||||
if (target->state != TARGET_HALTED) {
|
||||
LOG_WARNING("target not halted");
|
||||
LOG_TARGET_ERROR(target, "not halted");
|
||||
return ERROR_TARGET_NOT_HALTED;
|
||||
}
|
||||
|
||||
|
@ -1171,6 +1174,8 @@ static int aarch64_step(struct target *target, int current, target_addr_t addres
|
|||
if (retval == ERROR_TARGET_TIMEOUT)
|
||||
saved_retval = aarch64_halt_one(target, HALT_SYNC);
|
||||
|
||||
poll_retval = aarch64_poll(target);
|
||||
|
||||
/* restore EDECR */
|
||||
retval = mem_ap_write_atomic_u32(armv8->debug_ap,
|
||||
armv8->debug_base + CPUV8_DBG_EDECR, edecr);
|
||||
|
@ -1187,6 +1192,9 @@ static int aarch64_step(struct target *target, int current, target_addr_t addres
|
|||
if (saved_retval != ERROR_OK)
|
||||
return saved_retval;
|
||||
|
||||
if (poll_retval != ERROR_OK)
|
||||
return poll_retval;
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
|
@ -2135,7 +2143,7 @@ static int aarch64_write_cpu_memory(struct target *target,
|
|||
uint32_t dscr;
|
||||
|
||||
if (target->state != TARGET_HALTED) {
|
||||
LOG_WARNING("target not halted");
|
||||
LOG_TARGET_ERROR(target, "not halted");
|
||||
return ERROR_TARGET_NOT_HALTED;
|
||||
}
|
||||
|
||||
|
@ -2353,7 +2361,7 @@ static int aarch64_read_cpu_memory(struct target *target,
|
|||
address, size, count);
|
||||
|
||||
if (target->state != TARGET_HALTED) {
|
||||
LOG_WARNING("target not halted");
|
||||
LOG_TARGET_ERROR(target, "not halted");
|
||||
return ERROR_TARGET_NOT_HALTED;
|
||||
}
|
||||
|
||||
|
@ -2693,6 +2701,9 @@ static int aarch64_examine(struct target *target)
|
|||
if (retval == ERROR_OK)
|
||||
retval = aarch64_init_debug_access(target);
|
||||
|
||||
if (retval == ERROR_OK)
|
||||
retval = aarch64_poll(target);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
@ -2790,8 +2801,8 @@ static int aarch64_mmu(struct target *target, int *enabled)
|
|||
struct aarch64_common *aarch64 = target_to_aarch64(target);
|
||||
struct armv8_common *armv8 = &aarch64->armv8_common;
|
||||
if (target->state != TARGET_HALTED) {
|
||||
LOG_ERROR("%s: target %s not halted", __func__, target_name(target));
|
||||
return ERROR_TARGET_INVALID;
|
||||
LOG_TARGET_ERROR(target, "not halted");
|
||||
return ERROR_TARGET_NOT_HALTED;
|
||||
}
|
||||
if (armv8->is_armv8r)
|
||||
*enabled = 0;
|
||||
|
@ -3010,8 +3021,10 @@ COMMAND_HANDLER(aarch64_mcrmrc_command)
|
|||
return ERROR_FAIL;
|
||||
}
|
||||
|
||||
if (target->state != TARGET_HALTED)
|
||||
if (target->state != TARGET_HALTED) {
|
||||
command_print(CMD, "Error: [%s] not halted", target_name(target));
|
||||
return ERROR_TARGET_NOT_HALTED;
|
||||
}
|
||||
|
||||
if (arm->core_state == ARM_STATE_AARCH64) {
|
||||
command_print(CMD, "%s: not 32-bit arm target", target_name(target));
|
||||
|
|
|
@ -846,21 +846,17 @@ static int arc_save_context(struct target *target)
|
|||
memset(aux_addrs, 0xff, aux_regs_size);
|
||||
|
||||
for (i = 0; i < MIN(arc->num_core_regs, regs_to_scan); i++) {
|
||||
struct reg *reg = &(reg_list[i]);
|
||||
struct reg *reg = reg_list + i;
|
||||
struct arc_reg_desc *arc_reg = reg->arch_info;
|
||||
if (!reg->valid && reg->exist) {
|
||||
core_addrs[core_cnt] = arc_reg->arch_num;
|
||||
core_cnt += 1;
|
||||
}
|
||||
if (!reg->valid && reg->exist)
|
||||
core_addrs[core_cnt++] = arc_reg->arch_num;
|
||||
}
|
||||
|
||||
for (i = arc->num_core_regs; i < regs_to_scan; i++) {
|
||||
struct reg *reg = &(reg_list[i]);
|
||||
struct reg *reg = reg_list + i;
|
||||
struct arc_reg_desc *arc_reg = reg->arch_info;
|
||||
if (!reg->valid && reg->exist) {
|
||||
aux_addrs[aux_cnt] = arc_reg->arch_num;
|
||||
aux_cnt += 1;
|
||||
}
|
||||
if (!reg->valid && reg->exist)
|
||||
aux_addrs[aux_cnt++] = arc_reg->arch_num;
|
||||
}
|
||||
|
||||
/* Read data from target. */
|
||||
|
@ -884,30 +880,30 @@ static int arc_save_context(struct target *target)
|
|||
/* Parse core regs */
|
||||
core_cnt = 0;
|
||||
for (i = 0; i < MIN(arc->num_core_regs, regs_to_scan); i++) {
|
||||
struct reg *reg = &(reg_list[i]);
|
||||
struct reg *reg = reg_list + i;
|
||||
struct arc_reg_desc *arc_reg = reg->arch_info;
|
||||
if (!reg->valid && reg->exist) {
|
||||
target_buffer_set_u32(target, reg->value, core_values[core_cnt]);
|
||||
core_cnt += 1;
|
||||
reg->valid = true;
|
||||
reg->dirty = false;
|
||||
LOG_DEBUG("Get core register regnum=%u, name=%s, value=0x%08" PRIx32,
|
||||
i, arc_reg->name, core_values[core_cnt]);
|
||||
core_cnt++;
|
||||
}
|
||||
}
|
||||
|
||||
/* Parse aux regs */
|
||||
aux_cnt = 0;
|
||||
for (i = arc->num_core_regs; i < regs_to_scan; i++) {
|
||||
struct reg *reg = &(reg_list[i]);
|
||||
struct reg *reg = reg_list + i;
|
||||
struct arc_reg_desc *arc_reg = reg->arch_info;
|
||||
if (!reg->valid && reg->exist) {
|
||||
target_buffer_set_u32(target, reg->value, aux_values[aux_cnt]);
|
||||
aux_cnt += 1;
|
||||
reg->valid = true;
|
||||
reg->dirty = false;
|
||||
LOG_DEBUG("Get aux register regnum=%u, name=%s, value=0x%08" PRIx32,
|
||||
i, arc_reg->name, aux_values[aux_cnt]);
|
||||
aux_cnt++;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1262,7 +1258,7 @@ static int arc_resume(struct target *target, int current, target_addr_t address,
|
|||
CHECK_RETVAL(arc_reset_caches_states(target));
|
||||
|
||||
if (target->state != TARGET_HALTED) {
|
||||
LOG_WARNING("target not halted");
|
||||
LOG_TARGET_ERROR(target, "not halted");
|
||||
return ERROR_TARGET_NOT_HALTED;
|
||||
}
|
||||
|
||||
|
@ -1675,7 +1671,7 @@ static int arc_add_breakpoint(struct target *target, struct breakpoint *breakpoi
|
|||
return arc_set_breakpoint(target, breakpoint);
|
||||
|
||||
} else {
|
||||
LOG_WARNING(" > core was not halted, please try again.");
|
||||
LOG_TARGET_ERROR(target, "not halted (add breakpoint)");
|
||||
return ERROR_TARGET_NOT_HALTED;
|
||||
}
|
||||
}
|
||||
|
@ -1687,7 +1683,7 @@ static int arc_remove_breakpoint(struct target *target,
|
|||
if (breakpoint->is_set)
|
||||
CHECK_RETVAL(arc_unset_breakpoint(target, breakpoint));
|
||||
} else {
|
||||
LOG_WARNING("target not halted");
|
||||
LOG_TARGET_ERROR(target, "not halted (remove breakpoint)");
|
||||
return ERROR_TARGET_NOT_HALTED;
|
||||
}
|
||||
|
||||
|
@ -1909,7 +1905,7 @@ static int arc_add_watchpoint(struct target *target,
|
|||
struct watchpoint *watchpoint)
|
||||
{
|
||||
if (target->state != TARGET_HALTED) {
|
||||
LOG_WARNING("target not halted");
|
||||
LOG_TARGET_ERROR(target, "not halted");
|
||||
return ERROR_TARGET_NOT_HALTED;
|
||||
}
|
||||
|
||||
|
@ -1922,7 +1918,7 @@ static int arc_remove_watchpoint(struct target *target,
|
|||
struct watchpoint *watchpoint)
|
||||
{
|
||||
if (target->state != TARGET_HALTED) {
|
||||
LOG_WARNING("target not halted");
|
||||
LOG_TARGET_ERROR(target, "not halted");
|
||||
return ERROR_TARGET_NOT_HALTED;
|
||||
}
|
||||
|
||||
|
@ -2010,7 +2006,7 @@ static int arc_step(struct target *target, int current, target_addr_t address,
|
|||
struct reg *pc = &(arc->core_and_aux_cache->reg_list[arc->pc_index_in_cache]);
|
||||
|
||||
if (target->state != TARGET_HALTED) {
|
||||
LOG_WARNING("target not halted");
|
||||
LOG_TARGET_ERROR(target, "not halted");
|
||||
return ERROR_TARGET_NOT_HALTED;
|
||||
}
|
||||
|
||||
|
|
|
@ -162,7 +162,7 @@ int arc_mem_write(struct target *target, target_addr_t address, uint32_t size,
|
|||
address, size, count);
|
||||
|
||||
if (target->state != TARGET_HALTED) {
|
||||
LOG_WARNING("target not halted");
|
||||
LOG_TARGET_ERROR(target, "not halted");
|
||||
return ERROR_TARGET_NOT_HALTED;
|
||||
}
|
||||
|
||||
|
|
|
@ -58,6 +58,11 @@ enum arm_arch {
|
|||
ARM_ARCH_V8M,
|
||||
};
|
||||
|
||||
/** Known ARM implementor IDs */
|
||||
enum arm_implementor {
|
||||
ARM_IMPLEMENTOR_ARM = 0x41,
|
||||
};
|
||||
|
||||
/**
|
||||
* Represent state of an ARM core.
|
||||
*
|
||||
|
|
|
@ -449,7 +449,7 @@ static int arm11_resume(struct target *target, int current,
|
|||
|
||||
|
||||
if (target->state != TARGET_HALTED) {
|
||||
LOG_ERROR("Target not halted");
|
||||
LOG_TARGET_ERROR(target, "not halted");
|
||||
return ERROR_TARGET_NOT_HALTED;
|
||||
}
|
||||
|
||||
|
@ -551,7 +551,7 @@ static int arm11_step(struct target *target, int current,
|
|||
target_state_name(target));
|
||||
|
||||
if (target->state != TARGET_HALTED) {
|
||||
LOG_WARNING("target was not halted");
|
||||
LOG_TARGET_ERROR(target, "not halted");
|
||||
return ERROR_TARGET_NOT_HALTED;
|
||||
}
|
||||
|
||||
|
@ -798,7 +798,7 @@ static int arm11_read_memory_inner(struct target *target,
|
|||
int retval;
|
||||
|
||||
if (target->state != TARGET_HALTED) {
|
||||
LOG_WARNING("target was not halted");
|
||||
LOG_TARGET_ERROR(target, "not halted");
|
||||
return ERROR_TARGET_NOT_HALTED;
|
||||
}
|
||||
|
||||
|
@ -896,7 +896,7 @@ static int arm11_write_memory_inner(struct target *target,
|
|||
int retval;
|
||||
|
||||
if (target->state != TARGET_HALTED) {
|
||||
LOG_WARNING("target was not halted");
|
||||
LOG_TARGET_ERROR(target, "not halted");
|
||||
return ERROR_TARGET_NOT_HALTED;
|
||||
}
|
||||
|
||||
|
|
|
@ -241,8 +241,8 @@ static int arm720t_arch_state(struct target *target)
|
|||
static int arm720_mmu(struct target *target, int *enabled)
|
||||
{
|
||||
if (target->state != TARGET_HALTED) {
|
||||
LOG_ERROR("%s: target not halted", __func__);
|
||||
return ERROR_TARGET_INVALID;
|
||||
LOG_TARGET_ERROR(target, "not halted");
|
||||
return ERROR_TARGET_NOT_HALTED;
|
||||
}
|
||||
|
||||
*enabled = target_to_arm720(target)->armv4_5_mmu.mmu_enabled;
|
||||
|
|
|
@ -184,7 +184,7 @@ static int arm7_9_set_breakpoint(struct target *target, struct breakpoint *break
|
|||
breakpoint->type);
|
||||
|
||||
if (target->state != TARGET_HALTED) {
|
||||
LOG_WARNING("target not halted");
|
||||
LOG_TARGET_ERROR(target, "not halted");
|
||||
return ERROR_TARGET_NOT_HALTED;
|
||||
}
|
||||
|
||||
|
@ -451,11 +451,12 @@ static int arm7_9_set_watchpoint(struct target *target, struct watchpoint *watch
|
|||
struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
|
||||
int rw_mask = 1;
|
||||
uint32_t mask;
|
||||
const uint32_t wp_data_mask = watchpoint->mask;
|
||||
|
||||
mask = watchpoint->length - 1;
|
||||
|
||||
if (target->state != TARGET_HALTED) {
|
||||
LOG_WARNING("target not halted");
|
||||
LOG_TARGET_ERROR(target, "not halted");
|
||||
return ERROR_TARGET_NOT_HALTED;
|
||||
}
|
||||
|
||||
|
@ -469,8 +470,8 @@ static int arm7_9_set_watchpoint(struct target *target, struct watchpoint *watch
|
|||
watchpoint->address);
|
||||
embeddedice_set_reg(&arm7_9->eice_cache->reg_list[EICE_W0_ADDR_MASK], mask);
|
||||
embeddedice_set_reg(&arm7_9->eice_cache->reg_list[EICE_W0_DATA_MASK],
|
||||
watchpoint->mask);
|
||||
if (watchpoint->mask != 0xffffffffu)
|
||||
wp_data_mask);
|
||||
if (wp_data_mask != (uint32_t)WATCHPOINT_IGNORE_DATA_VALUE_MASK)
|
||||
embeddedice_set_reg(&arm7_9->eice_cache->reg_list[EICE_W0_DATA_VALUE],
|
||||
watchpoint->value);
|
||||
embeddedice_set_reg(&arm7_9->eice_cache->reg_list[EICE_W0_CONTROL_MASK],
|
||||
|
@ -488,8 +489,8 @@ static int arm7_9_set_watchpoint(struct target *target, struct watchpoint *watch
|
|||
watchpoint->address);
|
||||
embeddedice_set_reg(&arm7_9->eice_cache->reg_list[EICE_W1_ADDR_MASK], mask);
|
||||
embeddedice_set_reg(&arm7_9->eice_cache->reg_list[EICE_W1_DATA_MASK],
|
||||
watchpoint->mask);
|
||||
if (watchpoint->mask != 0xffffffffu)
|
||||
wp_data_mask);
|
||||
if (wp_data_mask != (uint32_t)WATCHPOINT_IGNORE_DATA_VALUE_MASK)
|
||||
embeddedice_set_reg(&arm7_9->eice_cache->reg_list[EICE_W1_DATA_VALUE],
|
||||
watchpoint->value);
|
||||
embeddedice_set_reg(&arm7_9->eice_cache->reg_list[EICE_W1_CONTROL_MASK],
|
||||
|
@ -524,7 +525,7 @@ static int arm7_9_unset_watchpoint(struct target *target, struct watchpoint *wat
|
|||
struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
|
||||
|
||||
if (target->state != TARGET_HALTED) {
|
||||
LOG_WARNING("target not halted");
|
||||
LOG_TARGET_ERROR(target, "not halted");
|
||||
return ERROR_TARGET_NOT_HALTED;
|
||||
}
|
||||
|
||||
|
@ -1259,7 +1260,7 @@ static int arm7_9_debug_entry(struct target *target)
|
|||
return retval;
|
||||
|
||||
if (target->state != TARGET_HALTED) {
|
||||
LOG_WARNING("target not halted");
|
||||
LOG_TARGET_ERROR(target, "not halted");
|
||||
return ERROR_TARGET_NOT_HALTED;
|
||||
}
|
||||
|
||||
|
@ -1390,7 +1391,7 @@ static int arm7_9_full_context(struct target *target)
|
|||
LOG_DEBUG("-");
|
||||
|
||||
if (target->state != TARGET_HALTED) {
|
||||
LOG_WARNING("target not halted");
|
||||
LOG_TARGET_ERROR(target, "not halted");
|
||||
return ERROR_TARGET_NOT_HALTED;
|
||||
}
|
||||
|
||||
|
@ -1506,7 +1507,7 @@ static int arm7_9_restore_context(struct target *target)
|
|||
LOG_DEBUG("-");
|
||||
|
||||
if (target->state != TARGET_HALTED) {
|
||||
LOG_WARNING("target not halted");
|
||||
LOG_TARGET_ERROR(target, "not halted");
|
||||
return ERROR_TARGET_NOT_HALTED;
|
||||
}
|
||||
|
||||
|
@ -1709,7 +1710,7 @@ int arm7_9_resume(struct target *target,
|
|||
LOG_DEBUG("-");
|
||||
|
||||
if (target->state != TARGET_HALTED) {
|
||||
LOG_WARNING("target not halted");
|
||||
LOG_TARGET_ERROR(target, "not halted");
|
||||
return ERROR_TARGET_NOT_HALTED;
|
||||
}
|
||||
|
||||
|
@ -1907,7 +1908,7 @@ int arm7_9_step(struct target *target, int current, target_addr_t address, int h
|
|||
int err, retval;
|
||||
|
||||
if (target->state != TARGET_HALTED) {
|
||||
LOG_WARNING("target not halted");
|
||||
LOG_TARGET_ERROR(target, "not halted");
|
||||
return ERROR_TARGET_NOT_HALTED;
|
||||
}
|
||||
|
||||
|
@ -2118,7 +2119,7 @@ int arm7_9_read_memory(struct target *target,
|
|||
address, size, count);
|
||||
|
||||
if (target->state != TARGET_HALTED) {
|
||||
LOG_WARNING("target not halted");
|
||||
LOG_TARGET_ERROR(target, "not halted");
|
||||
return ERROR_TARGET_NOT_HALTED;
|
||||
}
|
||||
|
||||
|
@ -2291,7 +2292,7 @@ int arm7_9_write_memory(struct target *target,
|
|||
#endif
|
||||
|
||||
if (target->state != TARGET_HALTED) {
|
||||
LOG_WARNING("target not halted");
|
||||
LOG_TARGET_ERROR(target, "not halted");
|
||||
return ERROR_TARGET_NOT_HALTED;
|
||||
}
|
||||
|
||||
|
|
|
@ -533,8 +533,8 @@ int arm920t_arch_state(struct target *target)
|
|||
static int arm920_mmu(struct target *target, int *enabled)
|
||||
{
|
||||
if (target->state != TARGET_HALTED) {
|
||||
LOG_ERROR("%s: target not halted", __func__);
|
||||
return ERROR_TARGET_INVALID;
|
||||
LOG_TARGET_ERROR(target, "not halted");
|
||||
return ERROR_TARGET_NOT_HALTED;
|
||||
}
|
||||
|
||||
*enabled = target_to_arm920(target)->armv4_5_mmu.mmu_enabled;
|
||||
|
@ -1455,9 +1455,9 @@ COMMAND_HANDLER(arm920t_handle_cp15_command)
|
|||
return retval;
|
||||
|
||||
if (target->state != TARGET_HALTED) {
|
||||
command_print(CMD, "target must be stopped for "
|
||||
command_print(CMD, "Error: target must be stopped for "
|
||||
"\"%s\" command", CMD_NAME);
|
||||
return ERROR_OK;
|
||||
return ERROR_TARGET_NOT_HALTED;
|
||||
}
|
||||
|
||||
/* one argument, read a register.
|
||||
|
|
|
@ -754,8 +754,8 @@ static int arm926ejs_mmu(struct target *target, int *enabled)
|
|||
struct arm926ejs_common *arm926ejs = target_to_arm926(target);
|
||||
|
||||
if (target->state != TARGET_HALTED) {
|
||||
LOG_ERROR("Target not halted");
|
||||
return ERROR_TARGET_INVALID;
|
||||
LOG_TARGET_ERROR(target, "not halted");
|
||||
return ERROR_TARGET_NOT_HALTED;
|
||||
}
|
||||
*enabled = arm926ejs->armv4_5_mmu.mmu_enabled;
|
||||
return ERROR_OK;
|
||||
|
|
|
@ -574,7 +574,7 @@ COMMAND_HANDLER(arm946e_handle_cp15)
|
|||
return retval;
|
||||
|
||||
if (target->state != TARGET_HALTED) {
|
||||
command_print(CMD, "target must be stopped for \"%s\" command", CMD_NAME);
|
||||
command_print(CMD, "Error: target must be stopped for \"%s\" command", CMD_NAME);
|
||||
return ERROR_TARGET_NOT_HALTED;
|
||||
}
|
||||
|
||||
|
@ -624,7 +624,7 @@ COMMAND_HANDLER(arm946e_handle_idcache)
|
|||
return retval;
|
||||
|
||||
if (target->state != TARGET_HALTED) {
|
||||
command_print(CMD, "target must be stopped for \"%s\" command", CMD_NAME);
|
||||
command_print(CMD, "Error: target must be stopped for \"%s\" command", CMD_NAME);
|
||||
return ERROR_TARGET_NOT_HALTED;
|
||||
}
|
||||
|
||||
|
|
|
@ -174,8 +174,8 @@ COMMAND_HANDLER(arm966e_handle_cp15_command)
|
|||
return retval;
|
||||
|
||||
if (target->state != TARGET_HALTED) {
|
||||
command_print(CMD, "target must be stopped for \"%s\" command", CMD_NAME);
|
||||
return ERROR_OK;
|
||||
command_print(CMD, "Error: target must be stopped for \"%s\" command", CMD_NAME);
|
||||
return ERROR_TARGET_NOT_HALTED;
|
||||
}
|
||||
|
||||
/* one or more argument, access a single register (write if second argument is given */
|
||||
|
|
|
@ -918,7 +918,7 @@ static int dpm_watchpoint_setup(struct arm_dpm *dpm, unsigned index_t,
|
|||
uint32_t control;
|
||||
|
||||
/* this hardware doesn't support data value matching or masking */
|
||||
if (wp->value || wp->mask != ~(uint32_t)0) {
|
||||
if (wp->mask != WATCHPOINT_IGNORE_DATA_VALUE_MASK) {
|
||||
LOG_DEBUG("watchpoint values and masking not supported");
|
||||
return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
|
||||
}
|
||||
|
|
|
@ -578,7 +578,7 @@ static int armv4_5_get_core_reg(struct reg *reg)
|
|||
struct target *target = reg_arch_info->target;
|
||||
|
||||
if (target->state != TARGET_HALTED) {
|
||||
LOG_ERROR("Target not halted");
|
||||
LOG_TARGET_ERROR(target, "not halted");
|
||||
return ERROR_TARGET_NOT_HALTED;
|
||||
}
|
||||
|
||||
|
@ -600,7 +600,7 @@ static int armv4_5_set_core_reg(struct reg *reg, uint8_t *buf)
|
|||
uint32_t value = buf_get_u32(buf, 0, 32);
|
||||
|
||||
if (target->state != TARGET_HALTED) {
|
||||
LOG_ERROR("Target not halted");
|
||||
LOG_TARGET_ERROR(target, "not halted");
|
||||
return ERROR_TARGET_NOT_HALTED;
|
||||
}
|
||||
|
||||
|
@ -817,8 +817,8 @@ COMMAND_HANDLER(handle_armv4_5_reg_command)
|
|||
}
|
||||
|
||||
if (target->state != TARGET_HALTED) {
|
||||
command_print(CMD, "error: target must be halted for register accesses");
|
||||
return ERROR_FAIL;
|
||||
command_print(CMD, "Error: target must be halted for register accesses");
|
||||
return ERROR_TARGET_NOT_HALTED;
|
||||
}
|
||||
|
||||
if (arm->core_type != ARM_CORE_TYPE_STD) {
|
||||
|
@ -833,7 +833,7 @@ COMMAND_HANDLER(handle_armv4_5_reg_command)
|
|||
}
|
||||
|
||||
if (!arm->full_context) {
|
||||
command_print(CMD, "error: target doesn't support %s",
|
||||
command_print(CMD, "Error: target doesn't support %s",
|
||||
CMD_NAME);
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
|
@ -1018,8 +1018,10 @@ COMMAND_HANDLER(handle_armv4_5_mcrmrc)
|
|||
return ERROR_FAIL;
|
||||
}
|
||||
|
||||
if (target->state != TARGET_HALTED)
|
||||
if (target->state != TARGET_HALTED) {
|
||||
command_print(CMD, "Error: [%s] not halted", target_name(target));
|
||||
return ERROR_TARGET_NOT_HALTED;
|
||||
}
|
||||
|
||||
int cpnum;
|
||||
uint32_t op1;
|
||||
|
@ -1307,7 +1309,7 @@ int armv4_5_run_algorithm_inner(struct target *target,
|
|||
}
|
||||
|
||||
if (target->state != TARGET_HALTED) {
|
||||
LOG_WARNING("target not halted");
|
||||
LOG_TARGET_ERROR(target, "not halted (run target algo)");
|
||||
return ERROR_TARGET_NOT_HALTED;
|
||||
}
|
||||
|
||||
|
|
|
@ -107,8 +107,10 @@ int armv4_5_mmu_read_physical(struct target *target,
|
|||
{
|
||||
int retval;
|
||||
|
||||
if (target->state != TARGET_HALTED)
|
||||
if (target->state != TARGET_HALTED) {
|
||||
LOG_TARGET_ERROR(target, "not halted");
|
||||
return ERROR_TARGET_NOT_HALTED;
|
||||
}
|
||||
|
||||
/* disable MMU and data (or unified) cache */
|
||||
retval = armv4_5_mmu->disable_mmu_caches(target, 1, 1, 0);
|
||||
|
@ -135,8 +137,10 @@ int armv4_5_mmu_write_physical(struct target *target,
|
|||
{
|
||||
int retval;
|
||||
|
||||
if (target->state != TARGET_HALTED)
|
||||
if (target->state != TARGET_HALTED) {
|
||||
LOG_TARGET_ERROR(target, "not halted");
|
||||
return ERROR_TARGET_NOT_HALTED;
|
||||
}
|
||||
|
||||
/* disable MMU and data (or unified) cache */
|
||||
retval = armv4_5_mmu->disable_mmu_caches(target, 1, 1, 0);
|
||||
|
|
|
@ -22,7 +22,7 @@ static int armv7a_l1_d_cache_sanity_check(struct target *target)
|
|||
struct armv7a_common *armv7a = target_to_armv7a(target);
|
||||
|
||||
if (target->state != TARGET_HALTED) {
|
||||
LOG_ERROR("%s: target not halted", __func__);
|
||||
LOG_TARGET_ERROR(target, "not halted");
|
||||
return ERROR_TARGET_NOT_HALTED;
|
||||
}
|
||||
|
||||
|
@ -40,7 +40,7 @@ static int armv7a_l1_i_cache_sanity_check(struct target *target)
|
|||
struct armv7a_common *armv7a = target_to_armv7a(target);
|
||||
|
||||
if (target->state != TARGET_HALTED) {
|
||||
LOG_ERROR("%s: target not halted", __func__);
|
||||
LOG_TARGET_ERROR(target, "not halted");
|
||||
return ERROR_TARGET_NOT_HALTED;
|
||||
}
|
||||
|
||||
|
|
|
@ -525,7 +525,7 @@ int armv7m_start_algorithm(struct target *target,
|
|||
}
|
||||
|
||||
if (target->state != TARGET_HALTED) {
|
||||
LOG_WARNING("target not halted");
|
||||
LOG_TARGET_ERROR(target, "not halted (start target algo)");
|
||||
return ERROR_TARGET_NOT_HALTED;
|
||||
}
|
||||
|
||||
|
|
|
@ -964,7 +964,7 @@ int armv8_mmu_translate_va_pa(struct target *target, target_addr_t va,
|
|||
};
|
||||
|
||||
if (target->state != TARGET_HALTED) {
|
||||
LOG_WARNING("target %s not halted", target_name(target));
|
||||
LOG_TARGET_ERROR(target, "not halted");
|
||||
return ERROR_TARGET_NOT_HALTED;
|
||||
}
|
||||
|
||||
|
|
|
@ -1210,7 +1210,7 @@ static int dpmv8_watchpoint_setup(struct arm_dpm *dpm, unsigned index_t,
|
|||
uint32_t control;
|
||||
|
||||
/* this hardware doesn't support data value matching or masking */
|
||||
if (wp->value || wp->mask != ~(uint32_t)0) {
|
||||
if (wp->mask != WATCHPOINT_IGNORE_DATA_VALUE_MASK) {
|
||||
LOG_DEBUG("watchpoint values and masking not supported");
|
||||
return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
|
||||
}
|
||||
|
|
|
@ -309,7 +309,7 @@ static int avr32_ap7k_resume(struct target *target, int current,
|
|||
int retval;
|
||||
|
||||
if (target->state != TARGET_HALTED) {
|
||||
LOG_WARNING("target not halted");
|
||||
LOG_TARGET_ERROR(target, "not halted");
|
||||
return ERROR_TARGET_NOT_HALTED;
|
||||
}
|
||||
|
||||
|
@ -431,7 +431,7 @@ static int avr32_ap7k_read_memory(struct target *target, target_addr_t address,
|
|||
count);
|
||||
|
||||
if (target->state != TARGET_HALTED) {
|
||||
LOG_WARNING("target not halted");
|
||||
LOG_TARGET_ERROR(target, "not halted");
|
||||
return ERROR_TARGET_NOT_HALTED;
|
||||
}
|
||||
|
||||
|
@ -471,7 +471,7 @@ static int avr32_ap7k_write_memory(struct target *target, target_addr_t address,
|
|||
count);
|
||||
|
||||
if (target->state != TARGET_HALTED) {
|
||||
LOG_WARNING("target not halted");
|
||||
LOG_TARGET_ERROR(target, "not halted");
|
||||
return ERROR_TARGET_NOT_HALTED;
|
||||
}
|
||||
|
||||
|
|
|
@ -448,7 +448,7 @@ struct breakpoint *breakpoint_find(struct target *target, target_addr_t address)
|
|||
}
|
||||
|
||||
static int watchpoint_add_internal(struct target *target, target_addr_t address,
|
||||
uint32_t length, enum watchpoint_rw rw, uint32_t value, uint32_t mask)
|
||||
uint32_t length, enum watchpoint_rw rw, uint64_t value, uint64_t mask)
|
||||
{
|
||||
struct watchpoint *watchpoint = target->watchpoints;
|
||||
struct watchpoint **watchpoint_p = &target->watchpoints;
|
||||
|
@ -515,7 +515,7 @@ bye:
|
|||
}
|
||||
|
||||
int watchpoint_add(struct target *target, target_addr_t address,
|
||||
uint32_t length, enum watchpoint_rw rw, uint32_t value, uint32_t mask)
|
||||
uint32_t length, enum watchpoint_rw rw, uint64_t value, uint64_t mask)
|
||||
{
|
||||
if (target->smp) {
|
||||
struct target_list *head;
|
||||
|
|
|
@ -36,11 +36,13 @@ struct breakpoint {
|
|||
int linked_brp;
|
||||
};
|
||||
|
||||
#define WATCHPOINT_IGNORE_DATA_VALUE_MASK (~(uint64_t)0)
|
||||
|
||||
struct watchpoint {
|
||||
target_addr_t address;
|
||||
uint32_t length;
|
||||
uint32_t mask;
|
||||
uint32_t value;
|
||||
uint64_t mask;
|
||||
uint64_t value;
|
||||
enum watchpoint_rw rw;
|
||||
bool is_set;
|
||||
unsigned int number;
|
||||
|
@ -69,7 +71,7 @@ static inline void breakpoint_hw_set(struct breakpoint *breakpoint, unsigned int
|
|||
void watchpoint_clear_target(struct target *target);
|
||||
int watchpoint_add(struct target *target,
|
||||
target_addr_t address, uint32_t length,
|
||||
enum watchpoint_rw rw, uint32_t value, uint32_t mask);
|
||||
enum watchpoint_rw rw, uint64_t value, uint64_t mask);
|
||||
void watchpoint_remove(struct target *target, target_addr_t address);
|
||||
|
||||
/* report type and address of just hit watchpoint */
|
||||
|
|
|
@ -1147,7 +1147,7 @@ static int cortex_a_step(struct target *target, int current, target_addr_t addre
|
|||
int retval;
|
||||
|
||||
if (target->state != TARGET_HALTED) {
|
||||
LOG_WARNING("target not halted");
|
||||
LOG_TARGET_ERROR(target, "not halted");
|
||||
return ERROR_TARGET_NOT_HALTED;
|
||||
}
|
||||
|
||||
|
@ -2225,7 +2225,7 @@ static int cortex_a_write_cpu_memory(struct target *target,
|
|||
LOG_DEBUG("Writing CPU memory address 0x%" PRIx32 " size %" PRIu32 " count %" PRIu32,
|
||||
address, size, count);
|
||||
if (target->state != TARGET_HALTED) {
|
||||
LOG_WARNING("target not halted");
|
||||
LOG_TARGET_ERROR(target, "not halted");
|
||||
return ERROR_TARGET_NOT_HALTED;
|
||||
}
|
||||
|
||||
|
@ -2542,7 +2542,7 @@ static int cortex_a_read_cpu_memory(struct target *target,
|
|||
LOG_DEBUG("Reading CPU memory address 0x%" PRIx32 " size %" PRIu32 " count %" PRIu32,
|
||||
address, size, count);
|
||||
if (target->state != TARGET_HALTED) {
|
||||
LOG_WARNING("target not halted");
|
||||
LOG_TARGET_ERROR(target, "not halted");
|
||||
return ERROR_TARGET_NOT_HALTED;
|
||||
}
|
||||
|
||||
|
@ -3183,8 +3183,8 @@ static int cortex_a_mmu(struct target *target, int *enabled)
|
|||
struct armv7a_common *armv7a = target_to_armv7a(target);
|
||||
|
||||
if (target->state != TARGET_HALTED) {
|
||||
LOG_ERROR("%s: target not halted", __func__);
|
||||
return ERROR_TARGET_INVALID;
|
||||
LOG_TARGET_ERROR(target, "not halted");
|
||||
return ERROR_TARGET_NOT_HALTED;
|
||||
}
|
||||
|
||||
if (armv7a->is_armv7r)
|
||||
|
|
|
@ -50,63 +50,63 @@
|
|||
/* Supported Cortex-M Cores */
|
||||
static const struct cortex_m_part_info cortex_m_parts[] = {
|
||||
{
|
||||
.partno = CORTEX_M0_PARTNO,
|
||||
.impl_part = CORTEX_M0_PARTNO,
|
||||
.name = "Cortex-M0",
|
||||
.arch = ARM_ARCH_V6M,
|
||||
},
|
||||
{
|
||||
.partno = CORTEX_M0P_PARTNO,
|
||||
.impl_part = CORTEX_M0P_PARTNO,
|
||||
.name = "Cortex-M0+",
|
||||
.arch = ARM_ARCH_V6M,
|
||||
},
|
||||
{
|
||||
.partno = CORTEX_M1_PARTNO,
|
||||
.impl_part = CORTEX_M1_PARTNO,
|
||||
.name = "Cortex-M1",
|
||||
.arch = ARM_ARCH_V6M,
|
||||
},
|
||||
{
|
||||
.partno = CORTEX_M3_PARTNO,
|
||||
.impl_part = CORTEX_M3_PARTNO,
|
||||
.name = "Cortex-M3",
|
||||
.arch = ARM_ARCH_V7M,
|
||||
.flags = CORTEX_M_F_TAR_AUTOINCR_BLOCK_4K,
|
||||
},
|
||||
{
|
||||
.partno = CORTEX_M4_PARTNO,
|
||||
.impl_part = CORTEX_M4_PARTNO,
|
||||
.name = "Cortex-M4",
|
||||
.arch = ARM_ARCH_V7M,
|
||||
.flags = CORTEX_M_F_HAS_FPV4 | CORTEX_M_F_TAR_AUTOINCR_BLOCK_4K,
|
||||
},
|
||||
{
|
||||
.partno = CORTEX_M7_PARTNO,
|
||||
.impl_part = CORTEX_M7_PARTNO,
|
||||
.name = "Cortex-M7",
|
||||
.arch = ARM_ARCH_V7M,
|
||||
.flags = CORTEX_M_F_HAS_FPV5,
|
||||
},
|
||||
{
|
||||
.partno = CORTEX_M23_PARTNO,
|
||||
.impl_part = CORTEX_M23_PARTNO,
|
||||
.name = "Cortex-M23",
|
||||
.arch = ARM_ARCH_V8M,
|
||||
},
|
||||
{
|
||||
.partno = CORTEX_M33_PARTNO,
|
||||
.impl_part = CORTEX_M33_PARTNO,
|
||||
.name = "Cortex-M33",
|
||||
.arch = ARM_ARCH_V8M,
|
||||
.flags = CORTEX_M_F_HAS_FPV5,
|
||||
},
|
||||
{
|
||||
.partno = CORTEX_M35P_PARTNO,
|
||||
.impl_part = CORTEX_M35P_PARTNO,
|
||||
.name = "Cortex-M35P",
|
||||
.arch = ARM_ARCH_V8M,
|
||||
.flags = CORTEX_M_F_HAS_FPV5,
|
||||
},
|
||||
{
|
||||
.partno = CORTEX_M55_PARTNO,
|
||||
.impl_part = CORTEX_M55_PARTNO,
|
||||
.name = "Cortex-M55",
|
||||
.arch = ARM_ARCH_V8M,
|
||||
.flags = CORTEX_M_F_HAS_FPV5,
|
||||
},
|
||||
{
|
||||
.partno = STAR_MC1_PARTNO,
|
||||
.impl_part = STAR_MC1_PARTNO,
|
||||
.name = "STAR-MC1",
|
||||
.arch = ARM_ARCH_V8M,
|
||||
.flags = CORTEX_M_F_HAS_FPV5,
|
||||
|
@ -1214,7 +1214,7 @@ static int cortex_m_restore_one(struct target *target, bool current,
|
|||
struct reg *r;
|
||||
|
||||
if (target->state != TARGET_HALTED) {
|
||||
LOG_TARGET_ERROR(target, "target not halted");
|
||||
LOG_TARGET_ERROR(target, "not halted");
|
||||
return ERROR_TARGET_NOT_HALTED;
|
||||
}
|
||||
|
||||
|
@ -1391,7 +1391,7 @@ static int cortex_m_step(struct target *target, int current,
|
|||
bool isr_timed_out = false;
|
||||
|
||||
if (target->state != TARGET_HALTED) {
|
||||
LOG_TARGET_WARNING(target, "target not halted");
|
||||
LOG_TARGET_ERROR(target, "not halted");
|
||||
return ERROR_TARGET_NOT_HALTED;
|
||||
}
|
||||
|
||||
|
@ -2046,8 +2046,14 @@ int cortex_m_add_watchpoint(struct target *target, struct watchpoint *watchpoint
|
|||
return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
|
||||
}
|
||||
|
||||
/* hardware doesn't support data value masking */
|
||||
if (watchpoint->mask != ~(uint32_t)0) {
|
||||
/* REVISIT This DWT may well be able to watch for specific data
|
||||
* values. Requires comparator #1 to set DATAVMATCH and match
|
||||
* the data, and another comparator (DATAVADDR0) matching addr.
|
||||
*
|
||||
* NOTE: hardware doesn't support data value masking, so we'll need
|
||||
* to check that mask is zero
|
||||
*/
|
||||
if (watchpoint->mask != WATCHPOINT_IGNORE_DATA_VALUE_MASK) {
|
||||
LOG_TARGET_DEBUG(target, "watchpoint value masks not supported");
|
||||
return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
|
||||
}
|
||||
|
@ -2068,18 +2074,6 @@ int cortex_m_add_watchpoint(struct target *target, struct watchpoint *watchpoint
|
|||
return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
|
||||
}
|
||||
|
||||
/* Caller doesn't seem to be able to describe watching for data
|
||||
* values of zero; that flags "no value".
|
||||
*
|
||||
* REVISIT This DWT may well be able to watch for specific data
|
||||
* values. Requires comparator #1 to set DATAVMATCH and match
|
||||
* the data, and another comparator (DATAVADDR0) matching addr.
|
||||
*/
|
||||
if (watchpoint->value) {
|
||||
LOG_TARGET_DEBUG(target, "data value watchpoint not YET supported");
|
||||
return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
|
||||
}
|
||||
|
||||
cortex_m->dwt_comp_available--;
|
||||
LOG_TARGET_DEBUG(target, "dwt_comp_available: %d", cortex_m->dwt_comp_available);
|
||||
|
||||
|
@ -2092,7 +2086,7 @@ int cortex_m_remove_watchpoint(struct target *target, struct watchpoint *watchpo
|
|||
|
||||
/* REVISIT why check? DWT can be updated with core running ... */
|
||||
if (target->state != TARGET_HALTED) {
|
||||
LOG_TARGET_WARNING(target, "target not halted");
|
||||
LOG_TARGET_ERROR(target, "not halted");
|
||||
return ERROR_TARGET_NOT_HALTED;
|
||||
}
|
||||
|
||||
|
@ -2532,18 +2526,18 @@ int cortex_m_examine(struct target *target)
|
|||
if (retval != ERROR_OK)
|
||||
return retval;
|
||||
|
||||
/* Get ARCH and CPU types */
|
||||
const enum cortex_m_partno core_partno = (cpuid & ARM_CPUID_PARTNO_MASK) >> ARM_CPUID_PARTNO_POS;
|
||||
/* Inspect implementor/part to look for recognized cores */
|
||||
unsigned int impl_part = cpuid & (ARM_CPUID_IMPLEMENTOR_MASK | ARM_CPUID_PARTNO_MASK);
|
||||
|
||||
for (unsigned int n = 0; n < ARRAY_SIZE(cortex_m_parts); n++) {
|
||||
if (core_partno == cortex_m_parts[n].partno) {
|
||||
if (impl_part == cortex_m_parts[n].impl_part) {
|
||||
cortex_m->core_info = &cortex_m_parts[n];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!cortex_m->core_info) {
|
||||
LOG_TARGET_ERROR(target, "Cortex-M PARTNO 0x%x is unrecognized", core_partno);
|
||||
LOG_TARGET_ERROR(target, "Cortex-M CPUID: 0x%x is unrecognized", cpuid);
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
|
||||
|
@ -2555,7 +2549,7 @@ int cortex_m_examine(struct target *target)
|
|||
(uint8_t)((cpuid >> 0) & 0xf));
|
||||
|
||||
cortex_m->maskints_erratum = false;
|
||||
if (core_partno == CORTEX_M7_PARTNO) {
|
||||
if (impl_part == CORTEX_M7_PARTNO) {
|
||||
uint8_t rev, patch;
|
||||
rev = (cpuid >> 20) & 0xf;
|
||||
patch = (cpuid >> 0) & 0xf;
|
||||
|
@ -2948,8 +2942,8 @@ COMMAND_HANDLER(handle_cortex_m_mask_interrupts_command)
|
|||
return retval;
|
||||
|
||||
if (target->state != TARGET_HALTED) {
|
||||
command_print(CMD, "target must be stopped for \"%s\" command", CMD_NAME);
|
||||
return ERROR_OK;
|
||||
command_print(CMD, "Error: target must be stopped for \"%s\" command", CMD_NAME);
|
||||
return ERROR_TARGET_NOT_HALTED;
|
||||
}
|
||||
|
||||
if (CMD_ARGC > 0) {
|
||||
|
|
|
@ -31,22 +31,31 @@
|
|||
|
||||
#define CPUID 0xE000ED00
|
||||
|
||||
#define ARM_CPUID_PARTNO_POS 4
|
||||
#define ARM_CPUID_PARTNO_MASK (0xFFF << ARM_CPUID_PARTNO_POS)
|
||||
#define ARM_CPUID_IMPLEMENTOR_POS 24
|
||||
#define ARM_CPUID_IMPLEMENTOR_MASK (0xFF << ARM_CPUID_IMPLEMENTOR_POS)
|
||||
#define ARM_CPUID_PARTNO_POS 4
|
||||
#define ARM_CPUID_PARTNO_MASK (0xFFF << ARM_CPUID_PARTNO_POS)
|
||||
|
||||
enum cortex_m_partno {
|
||||
#define ARM_MAKE_CPUID(impl, partno) ((((impl) << ARM_CPUID_IMPLEMENTOR_POS) & ARM_CPUID_IMPLEMENTOR_MASK) | \
|
||||
(((partno) << ARM_CPUID_PARTNO_POS) & ARM_CPUID_PARTNO_MASK))
|
||||
|
||||
/** Known Arm Cortex masked CPU Ids
|
||||
* This includes the implementor and part number, but _not_ the revision or
|
||||
* patch fields.
|
||||
*/
|
||||
enum cortex_m_impl_part {
|
||||
CORTEX_M_PARTNO_INVALID,
|
||||
STAR_MC1_PARTNO = 0x132,
|
||||
CORTEX_M0_PARTNO = 0xC20,
|
||||
CORTEX_M1_PARTNO = 0xC21,
|
||||
CORTEX_M3_PARTNO = 0xC23,
|
||||
CORTEX_M4_PARTNO = 0xC24,
|
||||
CORTEX_M7_PARTNO = 0xC27,
|
||||
CORTEX_M0P_PARTNO = 0xC60,
|
||||
CORTEX_M23_PARTNO = 0xD20,
|
||||
CORTEX_M33_PARTNO = 0xD21,
|
||||
CORTEX_M35P_PARTNO = 0xD31,
|
||||
CORTEX_M55_PARTNO = 0xD22,
|
||||
STAR_MC1_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTOR_ARM, 0x132), /* FIXME - confirm implementor! */
|
||||
CORTEX_M0_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTOR_ARM, 0xC20),
|
||||
CORTEX_M1_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTOR_ARM, 0xC21),
|
||||
CORTEX_M3_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTOR_ARM, 0xC23),
|
||||
CORTEX_M4_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTOR_ARM, 0xC24),
|
||||
CORTEX_M7_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTOR_ARM, 0xC27),
|
||||
CORTEX_M0P_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTOR_ARM, 0xC60),
|
||||
CORTEX_M23_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTOR_ARM, 0xD20),
|
||||
CORTEX_M33_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTOR_ARM, 0xD21),
|
||||
CORTEX_M35P_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTOR_ARM, 0xD31),
|
||||
CORTEX_M55_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTOR_ARM, 0xD22),
|
||||
};
|
||||
|
||||
/* Relevant Cortex-M flags, used in struct cortex_m_part_info.flags */
|
||||
|
@ -55,7 +64,7 @@ enum cortex_m_partno {
|
|||
#define CORTEX_M_F_TAR_AUTOINCR_BLOCK_4K BIT(2)
|
||||
|
||||
struct cortex_m_part_info {
|
||||
enum cortex_m_partno partno;
|
||||
enum cortex_m_impl_part impl_part;
|
||||
const char *name;
|
||||
enum arm_arch arch;
|
||||
uint32_t flags;
|
||||
|
@ -292,11 +301,11 @@ target_to_cortex_m_safe(struct target *target)
|
|||
}
|
||||
|
||||
/**
|
||||
* @returns cached value of Cortex-M part number
|
||||
* @returns cached value of the cpuid, masked for implementation and part.
|
||||
* or CORTEX_M_PARTNO_INVALID if the magic number does not match
|
||||
* or core_info is not initialised.
|
||||
*/
|
||||
static inline enum cortex_m_partno cortex_m_get_partno_safe(struct target *target)
|
||||
static inline enum cortex_m_impl_part cortex_m_get_impl_part(struct target *target)
|
||||
{
|
||||
struct cortex_m_common *cortex_m = target_to_cortex_m_safe(target);
|
||||
if (!cortex_m)
|
||||
|
@ -305,7 +314,7 @@ static inline enum cortex_m_partno cortex_m_get_partno_safe(struct target *targe
|
|||
if (!cortex_m->core_info)
|
||||
return CORTEX_M_PARTNO_INVALID;
|
||||
|
||||
return cortex_m->core_info->partno;
|
||||
return cortex_m->core_info->impl_part;
|
||||
}
|
||||
|
||||
int cortex_m_examine(struct target *target);
|
||||
|
|
|
@ -1296,7 +1296,7 @@ static int dsp563xx_step(struct target *target,
|
|||
struct dsp563xx_common *dsp563xx = target_to_dsp563xx(target);
|
||||
|
||||
if (target->state != TARGET_HALTED) {
|
||||
LOG_WARNING("target not halted");
|
||||
LOG_TARGET_ERROR(target, "not halted");
|
||||
return ERROR_TARGET_NOT_HALTED;
|
||||
}
|
||||
|
||||
|
@ -1381,7 +1381,7 @@ static int dsp563xx_run_algorithm(struct target *target,
|
|||
struct dsp563xx_common *dsp563xx = target_to_dsp563xx(target);
|
||||
|
||||
if (target->state != TARGET_HALTED) {
|
||||
LOG_WARNING("target not halted");
|
||||
LOG_TARGET_ERROR(target, "not halted (run target algo)");
|
||||
return ERROR_TARGET_NOT_HALTED;
|
||||
}
|
||||
|
||||
|
@ -1705,7 +1705,7 @@ static int dsp563xx_write_memory_core(struct target *target,
|
|||
count);
|
||||
|
||||
if (target->state != TARGET_HALTED) {
|
||||
LOG_WARNING("target not halted");
|
||||
LOG_TARGET_ERROR(target, "not halted");
|
||||
return ERROR_TARGET_NOT_HALTED;
|
||||
}
|
||||
|
||||
|
|
|
@ -318,8 +318,10 @@ static int esirisc_flush_caches(struct target *target)
|
|||
|
||||
LOG_DEBUG("-");
|
||||
|
||||
if (target->state != TARGET_HALTED)
|
||||
if (target->state != TARGET_HALTED) {
|
||||
LOG_TARGET_ERROR(target, "not halted");
|
||||
return ERROR_TARGET_NOT_HALTED;
|
||||
}
|
||||
|
||||
int retval = esirisc_jtag_flush_caches(jtag_info);
|
||||
if (retval != ERROR_OK) {
|
||||
|
@ -855,8 +857,10 @@ static int esirisc_resume_or_step(struct target *target, int current, target_add
|
|||
|
||||
LOG_DEBUG("-");
|
||||
|
||||
if (target->state != TARGET_HALTED)
|
||||
if (target->state != TARGET_HALTED) {
|
||||
LOG_TARGET_ERROR(target, "not halted");
|
||||
return ERROR_TARGET_NOT_HALTED;
|
||||
}
|
||||
|
||||
if (!debug_execution) {
|
||||
target_free_all_working_areas(target);
|
||||
|
|
|
@ -2,21 +2,23 @@
|
|||
|
||||
noinst_LTLIBRARIES += %D%/libespressif.la
|
||||
%C%_libespressif_la_SOURCES = \
|
||||
%D%/esp_xtensa.c \
|
||||
%D%/esp_xtensa.h \
|
||||
%D%/esp_xtensa_smp.c \
|
||||
%D%/esp_xtensa_smp.h \
|
||||
%D%/esp_xtensa_semihosting.c \
|
||||
%D%/esp_xtensa_semihosting.h \
|
||||
%D%/esp_xtensa_apptrace.c \
|
||||
%D%/esp_xtensa_apptrace.h \
|
||||
%D%/esp32_apptrace.c \
|
||||
%D%/esp32_apptrace.h \
|
||||
%D%/esp32.c \
|
||||
%D%/esp32s2.c \
|
||||
%D%/esp32s3.c \
|
||||
%D%/esp32_sysview.c \
|
||||
%D%/esp32_sysview.h \
|
||||
%D%/segger_sysview.h \
|
||||
%D%/esp_semihosting.c \
|
||||
%D%/esp_semihosting.h
|
||||
%D%/esp_xtensa.c \
|
||||
%D%/esp_xtensa.h \
|
||||
%D%/esp_xtensa_smp.c \
|
||||
%D%/esp_xtensa_smp.h \
|
||||
%D%/esp_xtensa_semihosting.c \
|
||||
%D%/esp_xtensa_semihosting.h \
|
||||
%D%/esp_xtensa_apptrace.c \
|
||||
%D%/esp_xtensa_apptrace.h \
|
||||
%D%/esp32_apptrace.c \
|
||||
%D%/esp32_apptrace.h \
|
||||
%D%/esp32.c \
|
||||
%D%/esp32s2.c \
|
||||
%D%/esp32s3.c \
|
||||
%D%/esp.c \
|
||||
%D%/esp.h \
|
||||
%D%/esp32_sysview.c \
|
||||
%D%/esp32_sysview.h \
|
||||
%D%/segger_sysview.h \
|
||||
%D%/esp_semihosting.c \
|
||||
%D%/esp_semihosting.h
|
||||
|
|
|
@ -0,0 +1,77 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
/***************************************************************************
|
||||
* Espressif chips common target API for OpenOCD *
|
||||
* Copyright (C) 2021 Espressif Systems Ltd. *
|
||||
***************************************************************************/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <helper/log.h>
|
||||
#include <helper/binarybuffer.h>
|
||||
#include "target/target.h"
|
||||
#include "esp.h"
|
||||
|
||||
int esp_dbgstubs_table_read(struct target *target, struct esp_dbg_stubs *dbg_stubs)
|
||||
{
|
||||
uint32_t table_size, table_start_id, desc_entry_id, gcov_entry_id;
|
||||
uint32_t entries[ESP_DBG_STUB_ENTRY_MAX] = {0};
|
||||
uint8_t entry_buff[sizeof(entries)] = {0}; /* to avoid endiannes issues */
|
||||
|
||||
LOG_TARGET_DEBUG(target, "Read debug stubs info %" PRIx32 " / %d", dbg_stubs->base, dbg_stubs->entries_count);
|
||||
|
||||
/* First of, read 2 entries to get magic num and table size */
|
||||
int res = target_read_buffer(target, dbg_stubs->base, sizeof(uint32_t) * 2, entry_buff);
|
||||
if (res != ERROR_OK) {
|
||||
LOG_ERROR("%s: Failed to read first debug stub entry!", target_name(target));
|
||||
return res;
|
||||
}
|
||||
entries[0] = target_buffer_get_u32(target, entry_buff);
|
||||
entries[1] = target_buffer_get_u32(target, entry_buff + sizeof(uint32_t));
|
||||
|
||||
if (entries[0] != ESP_DBG_STUB_MAGIC_NUM_VAL) {
|
||||
/* idf with the old table entry structure */
|
||||
table_size = 2;
|
||||
table_start_id = 0;
|
||||
desc_entry_id = 0;
|
||||
gcov_entry_id = 1;
|
||||
} else {
|
||||
table_size = entries[1];
|
||||
table_start_id = ESP_DBG_STUB_TABLE_START;
|
||||
desc_entry_id = ESP_DBG_STUB_TABLE_START;
|
||||
gcov_entry_id = ESP_DBG_STUB_ENTRY_FIRST;
|
||||
|
||||
/* discard unsupported entries */
|
||||
if (table_size > ESP_DBG_STUB_ENTRY_MAX)
|
||||
table_size = ESP_DBG_STUB_ENTRY_MAX;
|
||||
|
||||
/* now read the remaining entries */
|
||||
res = target_read_buffer(target, dbg_stubs->base + 2 * sizeof(uint32_t), sizeof(uint32_t) * table_size - 2,
|
||||
entry_buff + sizeof(uint32_t) * 2);
|
||||
if (res != ERROR_OK) {
|
||||
LOG_TARGET_ERROR(target, "Failed to read debug stubs info!");
|
||||
return res;
|
||||
}
|
||||
for (unsigned int i = 2; i < table_size; ++i)
|
||||
entries[i] = target_buffer_get_u32(target, entry_buff + sizeof(uint32_t) * i);
|
||||
|
||||
dbg_stubs->entries[ESP_DBG_STUB_CAPABILITIES] = entries[ESP_DBG_STUB_CAPABILITIES];
|
||||
}
|
||||
|
||||
dbg_stubs->entries[ESP_DBG_STUB_DESC] = entries[desc_entry_id];
|
||||
dbg_stubs->entries[ESP_DBG_STUB_ENTRY_GCOV] = entries[gcov_entry_id];
|
||||
|
||||
for (enum esp_dbg_stub_id i = ESP_DBG_STUB_DESC; i < ESP_DBG_STUB_ENTRY_MAX; i++) {
|
||||
LOG_DEBUG("Check dbg stub %d - %x", i, dbg_stubs->entries[i]);
|
||||
if (dbg_stubs->entries[i]) {
|
||||
LOG_DEBUG("New dbg stub %d at %x", dbg_stubs->entries_count, dbg_stubs->entries[i]);
|
||||
dbg_stubs->entries_count++;
|
||||
}
|
||||
}
|
||||
if (dbg_stubs->entries_count < table_size - table_start_id)
|
||||
LOG_WARNING("Not full dbg stub table %d of %d", dbg_stubs->entries_count, table_size - table_start_id);
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
|
@ -0,0 +1,85 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
/***************************************************************************
|
||||
* Espressif chips common target API for OpenOCD *
|
||||
* Copyright (C) 2021 Espressif Systems Ltd. *
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef OPENOCD_TARGET_ESP_H
|
||||
#define OPENOCD_TARGET_ESP_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <helper/bits.h>
|
||||
|
||||
/* must be in sync with ESP-IDF version */
|
||||
/** Size of the pre-compiled target buffer for stub trampoline.
|
||||
* @note Must be in sync with ESP-IDF version */
|
||||
#define ESP_DBG_STUBS_CODE_BUF_SIZE 32 /* TODO: move this info to esp_dbg_stubs_desc */
|
||||
/** Size of the pre-compiled target buffer for stack.
|
||||
* @note Must be in sync with ESP-IDF version */
|
||||
#define ESP_DBG_STUBS_STACK_MIN_SIZE 2048/* TODO: move this info to esp_dbg_stubs_desc */
|
||||
|
||||
/**
|
||||
* Debug stubs table entries IDs
|
||||
*
|
||||
* @note Must be in sync with ESP-IDF version
|
||||
*/
|
||||
enum esp_dbg_stub_id {
|
||||
ESP_DBG_STUB_ENTRY_MAGIC_NUM,
|
||||
ESP_DBG_STUB_TABLE_SIZE,
|
||||
ESP_DBG_STUB_TABLE_START,
|
||||
ESP_DBG_STUB_DESC = ESP_DBG_STUB_TABLE_START, /*< Stubs descriptor ID */
|
||||
ESP_DBG_STUB_ENTRY_FIRST,
|
||||
ESP_DBG_STUB_ENTRY_GCOV = ESP_DBG_STUB_ENTRY_FIRST, /*< GCOV stub ID */
|
||||
ESP_DBG_STUB_CAPABILITIES,
|
||||
/* add new stub entries here */
|
||||
ESP_DBG_STUB_ENTRY_MAX,
|
||||
};
|
||||
|
||||
#define ESP_DBG_STUB_MAGIC_NUM_VAL 0xFEEDBEEF
|
||||
#define ESP_DBG_STUB_CAP_GCOV_THREAD BIT(0)
|
||||
|
||||
/**
|
||||
* Debug stubs descriptor. ID: ESP_DBG_STUB_DESC
|
||||
*
|
||||
* @note Must be in sync with ESP-IDF version
|
||||
*/
|
||||
struct esp_dbg_stubs_desc {
|
||||
/** Address of pre-compiled target buffer for stub trampoline.
|
||||
* Size of the buffer is ESP_DBG_STUBS_CODE_BUF_SIZE
|
||||
*/
|
||||
uint32_t tramp_addr;
|
||||
/** Pre-compiled target buffer's addr for stack. The size of the buffer is ESP_DBG_STUBS_STACK_MIN_SIZE.
|
||||
* Target has the buffer which is used for the stack of onboard algorithms.
|
||||
* If stack size required by algorithm exceeds ESP_DBG_STUBS_STACK_MIN_SIZE,
|
||||
* it should be allocated using onboard function pointed by 'data_alloc' and
|
||||
* freed by 'data_free'. They fit to the minimal stack. See below.
|
||||
*/
|
||||
uint32_t min_stack_addr;
|
||||
/** Address of malloc-like function to allocate buffer on target. */
|
||||
uint32_t data_alloc;
|
||||
/** Address of free-like function to free buffer allocated with data_alloc. */
|
||||
uint32_t data_free;
|
||||
};
|
||||
|
||||
/**
|
||||
* Debug stubs info.
|
||||
*/
|
||||
struct esp_dbg_stubs {
|
||||
/** Address. */
|
||||
uint32_t base;
|
||||
/** Table contents. */
|
||||
uint32_t entries[ESP_DBG_STUB_ENTRY_MAX];
|
||||
/** Number of table entries. */
|
||||
uint32_t entries_count;
|
||||
/** Debug stubs decsriptor. */
|
||||
struct esp_dbg_stubs_desc desc;
|
||||
};
|
||||
|
||||
struct esp_common {
|
||||
struct esp_dbg_stubs dbg_stubs;
|
||||
};
|
||||
|
||||
int esp_dbgstubs_table_read(struct target *target, struct esp_dbg_stubs *dbg_stubs);
|
||||
|
||||
#endif /* OPENOCD_TARGET_ESP_H */
|
|
@ -24,20 +24,8 @@ implementation.
|
|||
*/
|
||||
|
||||
/* ESP32 memory map */
|
||||
#define ESP32_DRAM_LOW 0x3ffae000
|
||||
#define ESP32_DRAM_HIGH 0x40000000
|
||||
#define ESP32_IROM_MASK_LOW 0x40000000
|
||||
#define ESP32_IROM_MASK_HIGH 0x40064f00
|
||||
#define ESP32_IRAM_LOW 0x40070000
|
||||
#define ESP32_IRAM_HIGH 0x400a0000
|
||||
#define ESP32_RTC_IRAM_LOW 0x400c0000
|
||||
#define ESP32_RTC_IRAM_HIGH 0x400c2000
|
||||
#define ESP32_RTC_DRAM_LOW 0x3ff80000
|
||||
#define ESP32_RTC_DRAM_HIGH 0x3ff82000
|
||||
#define ESP32_RTC_DATA_LOW 0x50000000
|
||||
#define ESP32_RTC_DATA_HIGH 0x50002000
|
||||
#define ESP32_EXTRAM_DATA_LOW 0x3f800000
|
||||
#define ESP32_EXTRAM_DATA_HIGH 0x3fc00000
|
||||
#define ESP32_DR_REG_LOW 0x3ff00000
|
||||
#define ESP32_DR_REG_HIGH 0x3ff71000
|
||||
#define ESP32_SYS_RAM_LOW 0x60000000UL
|
||||
|
@ -266,7 +254,10 @@ static int esp32_disable_wdts(struct target *target)
|
|||
|
||||
static int esp32_on_halt(struct target *target)
|
||||
{
|
||||
return esp32_disable_wdts(target);
|
||||
int ret = esp32_disable_wdts(target);
|
||||
if (ret == ERROR_OK)
|
||||
ret = esp_xtensa_smp_on_halt(target);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int esp32_arch_state(struct target *target)
|
||||
|
|
|
@ -1252,7 +1252,7 @@ static int esp32_sysview_start(struct esp32_apptrace_cmd_ctx *ctx)
|
|||
{
|
||||
uint8_t cmds[] = { SEGGER_SYSVIEW_COMMAND_ID_START };
|
||||
uint32_t fired_target_num = 0;
|
||||
struct esp32_apptrace_target_state target_state[ESP32_APPTRACE_MAX_CORES_NUM] = {0};
|
||||
struct esp32_apptrace_target_state target_state[ESP32_APPTRACE_MAX_CORES_NUM] = {{0}};
|
||||
struct esp32_sysview_cmd_data *cmd_data = ctx->cmd_priv;
|
||||
|
||||
/* get current block id */
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue