Merge branch 'master' into from_upstream
Conflicts: .github/workflows/snapshot.yml NEWS configure.ac contrib/loaders/checksum/riscv_crc.c jimtcl src/helper/time_support.h src/jtag/drivers/arm-jtag-ew.c src/rtos/FreeRTOS.c src/target/image.c src/target/riscv/riscv.c Change-Id: I043624ba540d4672fc123dddb2066bcb9c6b5a05
This commit is contained in:
commit
7420382a4d
341
COPYING
341
COPYING
|
@ -1,339 +1,16 @@
|
|||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 2, June 1991
|
||||
OpenOCD is provided under:
|
||||
|
||||
Copyright (C) 1989, 1991 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.
|
||||
SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
Preamble
|
||||
Being under the terms of the GNU General Public License version 2 or
|
||||
later, according with:
|
||||
|
||||
The licenses for most software are designed to take away your
|
||||
freedom to share and change it. By contrast, the GNU General Public
|
||||
License is intended to guarantee your freedom to share and change free
|
||||
software--to make sure the software is free for all its users. This
|
||||
General Public License applies to most of the Free Software
|
||||
Foundation's software and to any other program whose authors commit to
|
||||
using it. (Some other Free Software Foundation software is covered by
|
||||
the GNU Lesser General Public License instead.) You can apply it to
|
||||
your programs, too.
|
||||
LICENSES/preferred/GPL-2.0
|
||||
|
||||
When we speak of free software, we are referring to freedom, 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 or use pieces of it
|
||||
in new free programs; and that you know you can do these things.
|
||||
In addition, other licenses may also apply. Please see:
|
||||
|
||||
To protect your rights, we need to make restrictions that forbid
|
||||
anyone to deny you these rights or to ask you to surrender the rights.
|
||||
These restrictions translate to certain responsibilities for you if you
|
||||
distribute copies of the software, or if you modify it.
|
||||
LICENSES/license-rules.txt
|
||||
|
||||
For example, if you distribute copies of such a program, whether
|
||||
gratis or for a fee, you must give the recipients all the rights that
|
||||
you have. You must make sure that they, too, receive or can get the
|
||||
source code. And you must show them these terms so they know their
|
||||
rights.
|
||||
for more details.
|
||||
|
||||
We protect your rights with two steps: (1) copyright the software, and
|
||||
(2) offer you this license which gives you legal permission to copy,
|
||||
distribute and/or modify the software.
|
||||
|
||||
Also, for each author's protection and ours, we want to make certain
|
||||
that everyone understands that there is no warranty for this free
|
||||
software. If the software is modified by someone else and passed on, we
|
||||
want its recipients to know that what they have is not the original, so
|
||||
that any problems introduced by others will not reflect on the original
|
||||
authors' reputations.
|
||||
|
||||
Finally, any free program is threatened constantly by software
|
||||
patents. We wish to avoid the danger that redistributors of a free
|
||||
program will individually obtain patent licenses, in effect making the
|
||||
program proprietary. To prevent this, we have made it clear that any
|
||||
patent must be licensed for everyone's free use or not licensed at all.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. This License applies to any program or other work which contains
|
||||
a notice placed by the copyright holder saying it may be distributed
|
||||
under the terms of this General Public License. The "Program", below,
|
||||
refers to any such program or work, and a "work based on the Program"
|
||||
means either the Program or any derivative work under copyright law:
|
||||
that is to say, a work containing the Program or a portion of it,
|
||||
either verbatim or with modifications and/or translated into another
|
||||
language. (Hereinafter, translation is included without limitation in
|
||||
the term "modification".) Each licensee is addressed as "you".
|
||||
|
||||
Activities other than copying, distribution and modification are not
|
||||
covered by this License; they are outside its scope. The act of
|
||||
running the Program is not restricted, and the output from the Program
|
||||
is covered only if its contents constitute a work based on the
|
||||
Program (independent of having been made by running the Program).
|
||||
Whether that is true depends on what the Program does.
|
||||
|
||||
1. You may copy and distribute verbatim copies of the Program's
|
||||
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 give any other recipients of the Program a copy of this License
|
||||
along with the Program.
|
||||
|
||||
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 Program or any portion
|
||||
of it, thus forming a work based on the Program, 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) You must cause the modified files to carry prominent notices
|
||||
stating that you changed the files and the date of any change.
|
||||
|
||||
b) You must cause any work that you distribute or publish, that in
|
||||
whole or in part contains or is derived from the Program or any
|
||||
part thereof, to be licensed as a whole at no charge to all third
|
||||
parties under the terms of this License.
|
||||
|
||||
c) If the modified program normally reads commands interactively
|
||||
when run, you must cause it, when started running for such
|
||||
interactive use in the most ordinary way, to print or display an
|
||||
announcement including an appropriate copyright notice and a
|
||||
notice that there is no warranty (or else, saying that you provide
|
||||
a warranty) and that users may redistribute the program under
|
||||
these conditions, and telling the user how to view a copy of this
|
||||
License. (Exception: if the Program itself is interactive but
|
||||
does not normally print such an announcement, your work based on
|
||||
the Program is not required to print an announcement.)
|
||||
|
||||
These requirements apply to the modified work as a whole. If
|
||||
identifiable sections of that work are not derived from the Program,
|
||||
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 Program, 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 Program.
|
||||
|
||||
In addition, mere aggregation of another work not based on the Program
|
||||
with the Program (or with a work based on the Program) on a volume of
|
||||
a storage or distribution medium does not bring the other work under
|
||||
the scope of this License.
|
||||
|
||||
3. You may copy and distribute the Program (or a work based on it,
|
||||
under Section 2) in object code or executable form under the terms of
|
||||
Sections 1 and 2 above provided that you also do one of the following:
|
||||
|
||||
a) 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; or,
|
||||
|
||||
b) Accompany it with a written offer, valid for at least three
|
||||
years, to give any third party, for a charge no more than your
|
||||
cost of physically performing source distribution, a complete
|
||||
machine-readable copy of the corresponding source code, to be
|
||||
distributed under the terms of Sections 1 and 2 above on a medium
|
||||
customarily used for software interchange; or,
|
||||
|
||||
c) Accompany it with the information you received as to the offer
|
||||
to distribute corresponding source code. (This alternative is
|
||||
allowed only for noncommercial distribution and only if you
|
||||
received the program in object code or executable form with such
|
||||
an offer, in accord with Subsection b above.)
|
||||
|
||||
The source code for a work means the preferred form of the work for
|
||||
making modifications to it. For an executable work, 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 executable. However, as a
|
||||
special exception, the source code 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.
|
||||
|
||||
If distribution of executable or 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 counts as
|
||||
distribution of the source code, even though third parties are not
|
||||
compelled to copy the source along with the object code.
|
||||
|
||||
4. You may not copy, modify, sublicense, or distribute the Program
|
||||
except as expressly provided under this License. Any attempt
|
||||
otherwise to copy, modify, sublicense or distribute the Program 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.
|
||||
|
||||
5. 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 Program or its derivative works. These actions are
|
||||
prohibited by law if you do not accept this License. Therefore, by
|
||||
modifying or distributing the Program (or any work based on the
|
||||
Program), you indicate your acceptance of this License to do so, and
|
||||
all its terms and conditions for copying, distributing or modifying
|
||||
the Program or works based on it.
|
||||
|
||||
6. Each time you redistribute the Program (or any work based on the
|
||||
Program), the recipient automatically receives a license from the
|
||||
original licensor to copy, distribute or modify the Program 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 to
|
||||
this License.
|
||||
|
||||
7. 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 Program at all. For example, if a patent
|
||||
license would not permit royalty-free redistribution of the Program 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 Program.
|
||||
|
||||
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.
|
||||
|
||||
8. If the distribution and/or use of the Program is restricted in
|
||||
certain countries either by patents or by copyrighted interfaces, the
|
||||
original copyright holder who places the Program 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.
|
||||
|
||||
9. The Free Software Foundation may publish revised and/or new versions
|
||||
of the 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 Program
|
||||
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 Program does not specify a version number of
|
||||
this License, you may choose any version ever published by the Free Software
|
||||
Foundation.
|
||||
|
||||
10. If you wish to incorporate parts of the Program into other free
|
||||
programs whose distribution conditions are different, 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
|
||||
|
||||
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
|
||||
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
|
||||
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
|
||||
PROVIDE THE PROGRAM "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 PROGRAM IS WITH YOU. SHOULD THE
|
||||
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
|
||||
REPAIR OR CORRECTION.
|
||||
|
||||
12. 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 PROGRAM 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 PROGRAM (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 PROGRAM TO OPERATE WITH ANY OTHER
|
||||
PROGRAMS), 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 Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest
|
||||
possible use to the public, the best way to achieve this is to make it
|
||||
free software which everyone can redistribute and change under these terms.
|
||||
|
||||
To do so, attach the following notices to the program. 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 program's name and a brief idea of what it does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If the program is interactive, make it output a short notice like this
|
||||
when it starts in an interactive mode:
|
||||
|
||||
Gnomovision version 69, Copyright (C) year name of author
|
||||
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||
This is free software, and you are welcome to redistribute it
|
||||
under certain conditions; type `show c' for details.
|
||||
|
||||
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||
parts of the General Public License. Of course, the commands you use may
|
||||
be called something other than `show w' and `show c'; they could even be
|
||||
mouse-clicks or menu items--whatever suits your program.
|
||||
|
||||
You should also get your employer (if you work as a programmer) or your
|
||||
school, if any, to sign a "copyright disclaimer" for the program, if
|
||||
necessary. Here is a sample; alter the names:
|
||||
|
||||
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
|
||||
`Gnomovision' (which makes passes at compilers) written by James Hacker.
|
||||
|
||||
<signature of Ty Coon>, 1 April 1989
|
||||
Ty Coon, President of Vice
|
||||
|
||||
This General Public License does not permit incorporating your program into
|
||||
proprietary programs. If your program is a subroutine library, you may
|
||||
consider it more useful to permit linking proprietary applications with the
|
||||
library. If this is what you want to do, use the GNU Lesser General
|
||||
Public License instead of this License.
|
||||
All contributions to OpenOCD are subject to this COPYING file.
|
||||
|
|
|
@ -0,0 +1,218 @@
|
|||
# SPDX-License-Identifier: GPL-2.0-or-later OR GFDL-1.2-no-invariants-or-later
|
||||
|
||||
OpenOCD licensing rules
|
||||
=======================
|
||||
|
||||
The OpenOCD source code is provided under the terms of the GNU General
|
||||
Public License version 2 or later (GPL-2.0-or-later), as provided in
|
||||
LICENSES/preferred/GPL-2.0.
|
||||
|
||||
The OpenOCD documentation is provided under the terms of the GNU Free
|
||||
Documentation License version 1.2 or later without Invariant Sections
|
||||
(GFDL-1.2-no-invariants-or-later).
|
||||
|
||||
Few stand-alone applications coexist in the same code tree of OpenOCD
|
||||
and are provided under the terms of the GNU General Public License
|
||||
version 3 (GPL-3.0), as provided in LICENSES/stand-alone/GPL-3.0.
|
||||
|
||||
This documentation file provides a description of how each source file
|
||||
should be annotated to make its license clear and unambiguous.
|
||||
It doesn't replace the OpenOCD's license.
|
||||
|
||||
The license described in the COPYING file applies to the OpenOCD source
|
||||
as a whole, though individual source files can have a different license
|
||||
which is required to be compatible with the GPL-2.0:
|
||||
|
||||
GPL-1.0-or-later : GNU General Public License v1.0 or later
|
||||
GPL-2.0-or-later : GNU General Public License v2.0 or later
|
||||
LGPL-2.0 : GNU Library General Public License v2 only
|
||||
LGPL-2.0-or-later : GNU Library General Public License v2 or later
|
||||
LGPL-2.1 : GNU Lesser General Public License v2.1 only
|
||||
LGPL-2.1-or-later : GNU Lesser General Public License v2.1 or later
|
||||
|
||||
Aside from that, individual files can be provided under a dual license,
|
||||
e.g. one of the compatible GPL variants and alternatively under a
|
||||
permissive license like BSD, MIT etc.
|
||||
|
||||
The common way of expressing the license of a source file is to add the
|
||||
matching boilerplate text into the top comment of the file. Due to
|
||||
formatting, typos etc. these "boilerplates" are hard to validate for
|
||||
tools which are used in the context of license compliance.
|
||||
|
||||
An alternative to boilerplate text is the use of Software Package Data
|
||||
Exchange (SPDX) license identifiers in each source file. SPDX license
|
||||
identifiers are machine parsable and precise shorthands for the license
|
||||
under which the content of the file is contributed. SPDX license
|
||||
identifiers are managed by the SPDX Workgroup at the Linux Foundation and
|
||||
have been agreed on by partners throughout the industry, tool vendors, and
|
||||
legal teams. For further information see https://spdx.org/
|
||||
|
||||
OpenOCD requires the precise SPDX identifier in all source files.
|
||||
The valid identifiers used in OpenOCD are explained in the section
|
||||
`License identifiers` and have been retrieved from the official SPDX
|
||||
license list at https://spdx.org/licenses/ along with the license texts.
|
||||
|
||||
License identifier syntax
|
||||
-------------------------
|
||||
|
||||
1. Placement:
|
||||
|
||||
The SPDX license identifier in OpenOCD files shall be added at the
|
||||
first possible line in a file which can contain a comment. For the
|
||||
majority of files this is the first line, except for scripts which
|
||||
require the '#!PATH_TO_INTERPRETER' in the first line. For those
|
||||
scripts the SPDX identifier goes into the second line.
|
||||
|
||||
2. Style:
|
||||
|
||||
The SPDX license identifier is added in form of a comment. The comment
|
||||
style depends on the file type::
|
||||
|
||||
C source: // SPDX-License-Identifier: <SPDX License Expression>
|
||||
C header: /* SPDX-License-Identifier: <SPDX License Expression> */
|
||||
ASM: /* SPDX-License-Identifier: <SPDX License Expression> */
|
||||
makefiles: # SPDX-License-Identifier: <SPDX License Expression>
|
||||
scripts: # SPDX-License-Identifier: <SPDX License Expression>
|
||||
texinfo: @c SPDX-License-Identifier: <SPDX License Expression>
|
||||
text: # SPDX-License-Identifier: <SPDX License Expression>
|
||||
|
||||
If a specific tool cannot handle the standard comment style, then the
|
||||
appropriate comment mechanism which the tool accepts shall be used. This
|
||||
is the reason for having the "/\* \*/" style comment in C header
|
||||
files. There was build breakage observed with generated .lds files where
|
||||
'ld' failed to parse the C++ comment. This has been fixed by now, but
|
||||
there are still older assembler tools which cannot handle C++ style
|
||||
comments.
|
||||
|
||||
3. Syntax:
|
||||
|
||||
A <SPDX License Expression> is either an SPDX short form license
|
||||
identifier found on the SPDX License List, or the combination of two
|
||||
SPDX short form license identifiers separated by "WITH" when a license
|
||||
exception applies. When multiple licenses apply, an expression consists
|
||||
of keywords "AND", "OR" separating sub-expressions and surrounded by
|
||||
"(", ")" .
|
||||
|
||||
License identifiers for licenses like [L]GPL with the 'or later' option
|
||||
are constructed by using a "-or-later":
|
||||
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
// SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
|
||||
WITH should be used when there is a modifier to a license needed.
|
||||
Exceptions can only be used with particular License identifiers. The
|
||||
valid License identifiers are listed in the tags of the exception text
|
||||
file.
|
||||
|
||||
OR should be used if the file is dual licensed and only one license is
|
||||
to be selected. For example, some source files are available under dual
|
||||
licenses:
|
||||
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later OR BSD-1-Clause
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later OR BSD-2-Clause
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later OR BSD-3-Clause
|
||||
|
||||
AND should be used if the file has multiple licenses whose terms all
|
||||
apply to use the file. For example, if code is inherited from another
|
||||
project and permission has been given to put it in OpenOCD, but the
|
||||
original license terms need to remain in effect::
|
||||
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later AND MIT
|
||||
|
||||
License identifiers
|
||||
-------------------
|
||||
|
||||
The licenses currently used, as well as the licenses for code added to
|
||||
OpenOCD, can be broken down into:
|
||||
|
||||
1. `Preferred licenses`:
|
||||
|
||||
Whenever possible these licenses should be used as they are known to be
|
||||
fully compatible and widely used. These licenses are available from the
|
||||
directory:
|
||||
|
||||
LICENSES/preferred/
|
||||
|
||||
in the OpenOCD source tree.
|
||||
|
||||
The files in this directory contain the full license text and
|
||||
`Metatags`. The file names are identical to the SPDX license
|
||||
identifier which shall be used for the license in source files.
|
||||
|
||||
Examples:
|
||||
|
||||
LICENSES/preferred/GPL-2.0
|
||||
|
||||
Contains the GPL version 2 license text and the required metatags.
|
||||
|
||||
`Metatags`:
|
||||
|
||||
The following meta tags must be available in a license file:
|
||||
|
||||
- Valid-License-Identifier:
|
||||
|
||||
One or more lines which declare which License Identifiers are valid
|
||||
inside the project to reference this particular license text. Usually
|
||||
this is a single valid identifier, but e.g. for licenses with the 'or
|
||||
later' options two identifiers are valid.
|
||||
|
||||
- SPDX-URL:
|
||||
|
||||
The URL of the SPDX page which contains additional information related
|
||||
to the license.
|
||||
|
||||
- Usage-Guidance:
|
||||
|
||||
Freeform text for usage advice. The text must include correct examples
|
||||
for the SPDX license identifiers as they should be put into source
|
||||
files according to the `License identifier syntax` guidelines.
|
||||
|
||||
- License-Text:
|
||||
|
||||
All text after this tag is treated as the original license text
|
||||
|
||||
File format examples::
|
||||
|
||||
Valid-License-Identifier: GPL-2.0
|
||||
Valid-License-Identifier: GPL-2.0-only
|
||||
Valid-License-Identifier: GPL-2.0-or-later
|
||||
SPDX-URL: https://spdx.org/licenses/GPL-2.0.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 General Public License (GPL) version 2 only' use:
|
||||
SPDX-License-Identifier: GPL-2.0
|
||||
or
|
||||
SPDX-License-Identifier: GPL-2.0-only
|
||||
For 'GNU General Public License (GPL) version 2 or any later version' use:
|
||||
SPDX-License-Identifier: GPL-2.0-or-later
|
||||
License-Text:
|
||||
Full license text
|
||||
|
||||
2. Stand-alone licenses:
|
||||
|
||||
These licenses should only be used for stand-alone applications that are
|
||||
distributed with OpenOCD but are not included in the OpenOCD binary.
|
||||
These licenses are available from the directory:
|
||||
|
||||
LICENSES/stand-alone/
|
||||
|
||||
in the OpenOCD source tree.
|
||||
|
||||
Examples:
|
||||
|
||||
SPDX-License-Identifier: GPL-3.0
|
||||
|
||||
The format and requirements of the license files in the other sub-directories
|
||||
of directory
|
||||
|
||||
LICENSES
|
||||
|
||||
have to follow the same format and requirements of the `Preferred licenses`.
|
||||
|
||||
All SPDX license identifiers and exceptions must have a corresponding file
|
||||
in the LICENSES subdirectories. This is required to allow tool
|
||||
verification (e.g. checkpatch.pl) and to have the licenses ready to read
|
||||
and extract right from the source, which is recommended by various FOSS
|
||||
organizations, e.g. the `FSFE REUSE initiative <https://reuse.software/>`.
|
|
@ -0,0 +1,28 @@
|
|||
Valid-License-Identifier: BSD-1-Clause
|
||||
SPDX-URL: https://spdx.org/licenses/BSD-1-Clause.html
|
||||
Usage-Guide:
|
||||
To use the BSD 1-clause License put the following SPDX
|
||||
tag/value pair into a comment according to the placement guidelines in
|
||||
the licensing rules documentation:
|
||||
SPDX-License-Identifier: BSD-1-Clause
|
||||
License-Text:
|
||||
|
||||
Copyright (c) <year> <owner> . All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
|
@ -0,0 +1,32 @@
|
|||
Valid-License-Identifier: BSD-2-Clause
|
||||
SPDX-URL: https://spdx.org/licenses/BSD-2-Clause.html
|
||||
Usage-Guide:
|
||||
To use the BSD 2-clause "Simplified" License put the following SPDX
|
||||
tag/value pair into a comment according to the placement guidelines in
|
||||
the licensing rules documentation:
|
||||
SPDX-License-Identifier: BSD-2-Clause
|
||||
License-Text:
|
||||
|
||||
Copyright (c) <year> <owner> . All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
|
@ -0,0 +1,36 @@
|
|||
Valid-License-Identifier: BSD-3-Clause
|
||||
SPDX-URL: https://spdx.org/licenses/BSD-3-Clause.html
|
||||
Usage-Guide:
|
||||
To use the BSD 3-clause "New" or "Revised" License put the following SPDX
|
||||
tag/value pair into a comment according to the placement guidelines in
|
||||
the licensing rules documentation:
|
||||
SPDX-License-Identifier: BSD-3-Clause
|
||||
License-Text:
|
||||
|
||||
Copyright (c) <year> <owner> . All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
3. Neither the name of the copyright holder nor the names of its
|
||||
contributors may be used to endorse or promote products derived from this
|
||||
software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
|
@ -0,0 +1,412 @@
|
|||
Valid-License-Identifier: GPL-2.0-or-later OR GFDL-1.2-no-invariants-or-later
|
||||
Valid-License-Identifier: GFDL-1.2-no-invariants-or-later
|
||||
SPDX-URL: https://spdx.org/licenses/GFDL-1.2-no-invariants-or-later.html
|
||||
Usage-Guide:
|
||||
The GNU Free Documentation License should only be used without
|
||||
Invariant Sections, Front-Cover Texts or Back-Cover Texts.
|
||||
It should not be used for new documents.
|
||||
To use the license in source code, put the following SPDX tag/value pair
|
||||
into a comment according to the placement guidelines in the licensing
|
||||
rules documentation:
|
||||
SPDX-License-Identifier: GPL-2.0-or-later OR GFDL-1.2-no-invariants-or-later
|
||||
or
|
||||
SPDX-License-Identifier: GFDL-1.2-no-invariants-or-later
|
||||
License-Text:
|
||||
|
||||
GNU Free Documentation License
|
||||
Version 1.2, November 2002
|
||||
|
||||
|
||||
Copyright (C) 2000,2001,2002 Free Software Foundation, Inc.
|
||||
51 Franklin St, 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.
|
||||
|
||||
|
||||
0. PREAMBLE
|
||||
|
||||
The purpose of this License is to make a manual, textbook, or other
|
||||
functional and useful document "free" in the sense of freedom: to
|
||||
assure everyone the effective freedom to copy and redistribute it,
|
||||
with or without modifying it, either commercially or noncommercially.
|
||||
Secondarily, this License preserves for the author and publisher a way
|
||||
to get credit for their work, while not being considered responsible
|
||||
for modifications made by others.
|
||||
|
||||
This License is a kind of "copyleft", which means that derivative
|
||||
works of the document must themselves be free in the same sense. It
|
||||
complements the GNU General Public License, which is a copyleft
|
||||
license designed for free software.
|
||||
|
||||
We have designed this License in order to use it for manuals for free
|
||||
software, because free software needs free documentation: a free
|
||||
program should come with manuals providing the same freedoms that the
|
||||
software does. But this License is not limited to software manuals;
|
||||
it can be used for any textual work, regardless of subject matter or
|
||||
whether it is published as a printed book. We recommend this License
|
||||
principally for works whose purpose is instruction or reference.
|
||||
|
||||
|
||||
1. APPLICABILITY AND DEFINITIONS
|
||||
|
||||
This License applies to any manual or other work, in any medium, that
|
||||
contains a notice placed by the copyright holder saying it can be
|
||||
distributed under the terms of this License. Such a notice grants a
|
||||
world-wide, royalty-free license, unlimited in duration, to use that
|
||||
work under the conditions stated herein. The "Document", below,
|
||||
refers to any such manual or work. Any member of the public is a
|
||||
licensee, and is addressed as "you". You accept the license if you
|
||||
copy, modify or distribute the work in a way requiring permission
|
||||
under copyright law.
|
||||
|
||||
A "Modified Version" of the Document means any work containing the
|
||||
Document or a portion of it, either copied verbatim, or with
|
||||
modifications and/or translated into another language.
|
||||
|
||||
A "Secondary Section" is a named appendix or a front-matter section of
|
||||
the Document that deals exclusively with the relationship of the
|
||||
publishers or authors of the Document to the Document's overall subject
|
||||
(or to related matters) and contains nothing that could fall directly
|
||||
within that overall subject. (Thus, if the Document is in part a
|
||||
textbook of mathematics, a Secondary Section may not explain any
|
||||
mathematics.) The relationship could be a matter of historical
|
||||
connection with the subject or with related matters, or of legal,
|
||||
commercial, philosophical, ethical or political position regarding
|
||||
them.
|
||||
|
||||
The "Invariant Sections" are certain Secondary Sections whose titles
|
||||
are designated, as being those of Invariant Sections, in the notice
|
||||
that says that the Document is released under this License. If a
|
||||
section does not fit the above definition of Secondary then it is not
|
||||
allowed to be designated as Invariant. The Document may contain zero
|
||||
Invariant Sections. If the Document does not identify any Invariant
|
||||
Sections then there are none.
|
||||
|
||||
The "Cover Texts" are certain short passages of text that are listed,
|
||||
as Front-Cover Texts or Back-Cover Texts, in the notice that says that
|
||||
the Document is released under this License. A Front-Cover Text may
|
||||
be at most 5 words, and a Back-Cover Text may be at most 25 words.
|
||||
|
||||
A "Transparent" copy of the Document means a machine-readable copy,
|
||||
represented in a format whose specification is available to the
|
||||
general public, that is suitable for revising the document
|
||||
straightforwardly with generic text editors or (for images composed of
|
||||
pixels) generic paint programs or (for drawings) some widely available
|
||||
drawing editor, and that is suitable for input to text formatters or
|
||||
for automatic translation to a variety of formats suitable for input
|
||||
to text formatters. A copy made in an otherwise Transparent file
|
||||
format whose markup, or absence of markup, has been arranged to thwart
|
||||
or discourage subsequent modification by readers is not Transparent.
|
||||
An image format is not Transparent if used for any substantial amount
|
||||
of text. A copy that is not "Transparent" is called "Opaque".
|
||||
|
||||
Examples of suitable formats for Transparent copies include plain
|
||||
ASCII without markup, Texinfo input format, LaTeX input format, SGML
|
||||
or XML using a publicly available DTD, and standard-conforming simple
|
||||
HTML, PostScript or PDF designed for human modification. Examples of
|
||||
transparent image formats include PNG, XCF and JPG. Opaque formats
|
||||
include proprietary formats that can be read and edited only by
|
||||
proprietary word processors, SGML or XML for which the DTD and/or
|
||||
processing tools are not generally available, and the
|
||||
machine-generated HTML, PostScript or PDF produced by some word
|
||||
processors for output purposes only.
|
||||
|
||||
The "Title Page" means, for a printed book, the title page itself,
|
||||
plus such following pages as are needed to hold, legibly, the material
|
||||
this License requires to appear in the title page. For works in
|
||||
formats which do not have any title page as such, "Title Page" means
|
||||
the text near the most prominent appearance of the work's title,
|
||||
preceding the beginning of the body of the text.
|
||||
|
||||
A section "Entitled XYZ" means a named subunit of the Document whose
|
||||
title either is precisely XYZ or contains XYZ in parentheses following
|
||||
text that translates XYZ in another language. (Here XYZ stands for a
|
||||
specific section name mentioned below, such as "Acknowledgements",
|
||||
"Dedications", "Endorsements", or "History".) To "Preserve the Title"
|
||||
of such a section when you modify the Document means that it remains a
|
||||
section "Entitled XYZ" according to this definition.
|
||||
|
||||
The Document may include Warranty Disclaimers next to the notice which
|
||||
states that this License applies to the Document. These Warranty
|
||||
Disclaimers are considered to be included by reference in this
|
||||
License, but only as regards disclaiming warranties: any other
|
||||
implication that these Warranty Disclaimers may have is void and has
|
||||
no effect on the meaning of this License.
|
||||
|
||||
|
||||
2. VERBATIM COPYING
|
||||
|
||||
You may copy and distribute the Document in any medium, either
|
||||
commercially or noncommercially, provided that this License, the
|
||||
copyright notices, and the license notice saying this License applies
|
||||
to the Document are reproduced in all copies, and that you add no other
|
||||
conditions whatsoever to those of this License. You may not use
|
||||
technical measures to obstruct or control the reading or further
|
||||
copying of the copies you make or distribute. However, you may accept
|
||||
compensation in exchange for copies. If you distribute a large enough
|
||||
number of copies you must also follow the conditions in section 3.
|
||||
|
||||
You may also lend copies, under the same conditions stated above, and
|
||||
you may publicly display copies.
|
||||
|
||||
|
||||
3. COPYING IN QUANTITY
|
||||
|
||||
If you publish printed copies (or copies in media that commonly have
|
||||
printed covers) of the Document, numbering more than 100, and the
|
||||
Document's license notice requires Cover Texts, you must enclose the
|
||||
copies in covers that carry, clearly and legibly, all these Cover
|
||||
Texts: Front-Cover Texts on the front cover, and Back-Cover Texts on
|
||||
the back cover. Both covers must also clearly and legibly identify
|
||||
you as the publisher of these copies. The front cover must present
|
||||
the full title with all words of the title equally prominent and
|
||||
visible. You may add other material on the covers in addition.
|
||||
Copying with changes limited to the covers, as long as they preserve
|
||||
the title of the Document and satisfy these conditions, can be treated
|
||||
as verbatim copying in other respects.
|
||||
|
||||
If the required texts for either cover are too voluminous to fit
|
||||
legibly, you should put the first ones listed (as many as fit
|
||||
reasonably) on the actual cover, and continue the rest onto adjacent
|
||||
pages.
|
||||
|
||||
If you publish or distribute Opaque copies of the Document numbering
|
||||
more than 100, you must either include a machine-readable Transparent
|
||||
copy along with each Opaque copy, or state in or with each Opaque copy
|
||||
a computer-network location from which the general network-using
|
||||
public has access to download using public-standard network protocols
|
||||
a complete Transparent copy of the Document, free of added material.
|
||||
If you use the latter option, you must take reasonably prudent steps,
|
||||
when you begin distribution of Opaque copies in quantity, to ensure
|
||||
that this Transparent copy will remain thus accessible at the stated
|
||||
location until at least one year after the last time you distribute an
|
||||
Opaque copy (directly or through your agents or retailers) of that
|
||||
edition to the public.
|
||||
|
||||
It is requested, but not required, that you contact the authors of the
|
||||
Document well before redistributing any large number of copies, to give
|
||||
them a chance to provide you with an updated version of the Document.
|
||||
|
||||
|
||||
4. MODIFICATIONS
|
||||
|
||||
You may copy and distribute a Modified Version of the Document under
|
||||
the conditions of sections 2 and 3 above, provided that you release
|
||||
the Modified Version under precisely this License, with the Modified
|
||||
Version filling the role of the Document, thus licensing distribution
|
||||
and modification of the Modified Version to whoever possesses a copy
|
||||
of it. In addition, you must do these things in the Modified Version:
|
||||
|
||||
A. Use in the Title Page (and on the covers, if any) a title distinct
|
||||
from that of the Document, and from those of previous versions
|
||||
(which should, if there were any, be listed in the History section
|
||||
of the Document). You may use the same title as a previous version
|
||||
if the original publisher of that version gives permission.
|
||||
B. List on the Title Page, as authors, one or more persons or entities
|
||||
responsible for authorship of the modifications in the Modified
|
||||
Version, together with at least five of the principal authors of the
|
||||
Document (all of its principal authors, if it has fewer than five),
|
||||
unless they release you from this requirement.
|
||||
C. State on the Title page the name of the publisher of the
|
||||
Modified Version, as the publisher.
|
||||
D. Preserve all the copyright notices of the Document.
|
||||
E. Add an appropriate copyright notice for your modifications
|
||||
adjacent to the other copyright notices.
|
||||
F. Include, immediately after the copyright notices, a license notice
|
||||
giving the public permission to use the Modified Version under the
|
||||
terms of this License, in the form shown in the Addendum below.
|
||||
G. Preserve in that license notice the full lists of Invariant Sections
|
||||
and required Cover Texts given in the Document's license notice.
|
||||
H. Include an unaltered copy of this License.
|
||||
I. Preserve the section Entitled "History", Preserve its Title, and add
|
||||
to it an item stating at least the title, year, new authors, and
|
||||
publisher of the Modified Version as given on the Title Page. If
|
||||
there is no section Entitled "History" in the Document, create one
|
||||
stating the title, year, authors, and publisher of the Document as
|
||||
given on its Title Page, then add an item describing the Modified
|
||||
Version as stated in the previous sentence.
|
||||
J. Preserve the network location, if any, given in the Document for
|
||||
public access to a Transparent copy of the Document, and likewise
|
||||
the network locations given in the Document for previous versions
|
||||
it was based on. These may be placed in the "History" section.
|
||||
You may omit a network location for a work that was published at
|
||||
least four years before the Document itself, or if the original
|
||||
publisher of the version it refers to gives permission.
|
||||
K. For any section Entitled "Acknowledgements" or "Dedications",
|
||||
Preserve the Title of the section, and preserve in the section all
|
||||
the substance and tone of each of the contributor acknowledgements
|
||||
and/or dedications given therein.
|
||||
L. Preserve all the Invariant Sections of the Document,
|
||||
unaltered in their text and in their titles. Section numbers
|
||||
or the equivalent are not considered part of the section titles.
|
||||
M. Delete any section Entitled "Endorsements". Such a section
|
||||
may not be included in the Modified Version.
|
||||
N. Do not retitle any existing section to be Entitled "Endorsements"
|
||||
or to conflict in title with any Invariant Section.
|
||||
O. Preserve any Warranty Disclaimers.
|
||||
|
||||
If the Modified Version includes new front-matter sections or
|
||||
appendices that qualify as Secondary Sections and contain no material
|
||||
copied from the Document, you may at your option designate some or all
|
||||
of these sections as invariant. To do this, add their titles to the
|
||||
list of Invariant Sections in the Modified Version's license notice.
|
||||
These titles must be distinct from any other section titles.
|
||||
|
||||
You may add a section Entitled "Endorsements", provided it contains
|
||||
nothing but endorsements of your Modified Version by various
|
||||
parties--for example, statements of peer review or that the text has
|
||||
been approved by an organization as the authoritative definition of a
|
||||
standard.
|
||||
|
||||
You may add a passage of up to five words as a Front-Cover Text, and a
|
||||
passage of up to 25 words as a Back-Cover Text, to the end of the list
|
||||
of Cover Texts in the Modified Version. Only one passage of
|
||||
Front-Cover Text and one of Back-Cover Text may be added by (or
|
||||
through arrangements made by) any one entity. If the Document already
|
||||
includes a cover text for the same cover, previously added by you or
|
||||
by arrangement made by the same entity you are acting on behalf of,
|
||||
you may not add another; but you may replace the old one, on explicit
|
||||
permission from the previous publisher that added the old one.
|
||||
|
||||
The author(s) and publisher(s) of the Document do not by this License
|
||||
give permission to use their names for publicity for or to assert or
|
||||
imply endorsement of any Modified Version.
|
||||
|
||||
|
||||
5. COMBINING DOCUMENTS
|
||||
|
||||
You may combine the Document with other documents released under this
|
||||
License, under the terms defined in section 4 above for modified
|
||||
versions, provided that you include in the combination all of the
|
||||
Invariant Sections of all of the original documents, unmodified, and
|
||||
list them all as Invariant Sections of your combined work in its
|
||||
license notice, and that you preserve all their Warranty Disclaimers.
|
||||
|
||||
The combined work need only contain one copy of this License, and
|
||||
multiple identical Invariant Sections may be replaced with a single
|
||||
copy. If there are multiple Invariant Sections with the same name but
|
||||
different contents, make the title of each such section unique by
|
||||
adding at the end of it, in parentheses, the name of the original
|
||||
author or publisher of that section if known, or else a unique number.
|
||||
Make the same adjustment to the section titles in the list of
|
||||
Invariant Sections in the license notice of the combined work.
|
||||
|
||||
In the combination, you must combine any sections Entitled "History"
|
||||
in the various original documents, forming one section Entitled
|
||||
"History"; likewise combine any sections Entitled "Acknowledgements",
|
||||
and any sections Entitled "Dedications". You must delete all sections
|
||||
Entitled "Endorsements".
|
||||
|
||||
|
||||
6. COLLECTIONS OF DOCUMENTS
|
||||
|
||||
You may make a collection consisting of the Document and other documents
|
||||
released under this License, and replace the individual copies of this
|
||||
License in the various documents with a single copy that is included in
|
||||
the collection, provided that you follow the rules of this License for
|
||||
verbatim copying of each of the documents in all other respects.
|
||||
|
||||
You may extract a single document from such a collection, and distribute
|
||||
it individually under this License, provided you insert a copy of this
|
||||
License into the extracted document, and follow this License in all
|
||||
other respects regarding verbatim copying of that document.
|
||||
|
||||
|
||||
7. AGGREGATION WITH INDEPENDENT WORKS
|
||||
|
||||
A compilation of the Document or its derivatives with other separate
|
||||
and independent documents or works, in or on a volume of a storage or
|
||||
distribution medium, is called an "aggregate" if the copyright
|
||||
resulting from the compilation is not used to limit the legal rights
|
||||
of the compilation's users beyond what the individual works permit.
|
||||
When the Document is included in an aggregate, this License does not
|
||||
apply to the other works in the aggregate which are not themselves
|
||||
derivative works of the Document.
|
||||
|
||||
If the Cover Text requirement of section 3 is applicable to these
|
||||
copies of the Document, then if the Document is less than one half of
|
||||
the entire aggregate, the Document's Cover Texts may be placed on
|
||||
covers that bracket the Document within the aggregate, or the
|
||||
electronic equivalent of covers if the Document is in electronic form.
|
||||
Otherwise they must appear on printed covers that bracket the whole
|
||||
aggregate.
|
||||
|
||||
|
||||
8. TRANSLATION
|
||||
|
||||
Translation is considered a kind of modification, so you may
|
||||
distribute translations of the Document under the terms of section 4.
|
||||
Replacing Invariant Sections with translations requires special
|
||||
permission from their copyright holders, but you may include
|
||||
translations of some or all Invariant Sections in addition to the
|
||||
original versions of these Invariant Sections. You may include a
|
||||
translation of this License, and all the license notices in the
|
||||
Document, and any Warranty Disclaimers, provided that you also include
|
||||
the original English version of this License and the original versions
|
||||
of those notices and disclaimers. In case of a disagreement between
|
||||
the translation and the original version of this License or a notice
|
||||
or disclaimer, the original version will prevail.
|
||||
|
||||
If a section in the Document is Entitled "Acknowledgements",
|
||||
"Dedications", or "History", the requirement (section 4) to Preserve
|
||||
its Title (section 1) will typically require changing the actual
|
||||
title.
|
||||
|
||||
|
||||
9. TERMINATION
|
||||
|
||||
You may not copy, modify, sublicense, or distribute the Document except
|
||||
as expressly provided for under this License. Any other attempt to
|
||||
copy, modify, sublicense or distribute the Document 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.
|
||||
|
||||
|
||||
10. FUTURE REVISIONS OF THIS LICENSE
|
||||
|
||||
The Free Software Foundation may publish new, revised versions
|
||||
of the GNU Free Documentation 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. See
|
||||
https://www.gnu.org/licenses/.
|
||||
|
||||
Each version of the License is given a distinguishing version number.
|
||||
If the Document specifies that a particular numbered version of this
|
||||
License "or any later version" applies to it, you have the option of
|
||||
following the terms and conditions either of that specified version or
|
||||
of any later version that has been published (not as a draft) by the
|
||||
Free Software Foundation. If the Document does not specify a version
|
||||
number of this License, you may choose any version ever published (not
|
||||
as a draft) by the Free Software Foundation.
|
||||
|
||||
|
||||
ADDENDUM: How to use this License for your documents
|
||||
|
||||
To use this License in a document you have written, include a copy of
|
||||
the License in the document and put the following copyright and
|
||||
license notices just after the title page:
|
||||
|
||||
Copyright (c) YEAR YOUR NAME.
|
||||
Permission is granted to copy, distribute and/or modify this document
|
||||
under the terms of the GNU Free Documentation License, Version 1.2
|
||||
or any later version published by the Free Software Foundation;
|
||||
with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts.
|
||||
A copy of the license is included in the section entitled "GNU
|
||||
Free Documentation License".
|
||||
|
||||
If you have Invariant Sections, Front-Cover Texts and Back-Cover Texts,
|
||||
replace the "with...Texts." line with this:
|
||||
|
||||
with the Invariant Sections being LIST THEIR TITLES, with the
|
||||
Front-Cover Texts being LIST, and with the Back-Cover Texts being LIST.
|
||||
|
||||
If you have Invariant Sections without Cover Texts, or some other
|
||||
combination of the three, merge those two alternatives to suit the
|
||||
situation.
|
||||
|
||||
If your document contains nontrivial examples of program code, we
|
||||
recommend releasing these examples in parallel under your choice of
|
||||
free software license, such as the GNU General Public License,
|
||||
to permit their use in free software.
|
|
@ -0,0 +1,355 @@
|
|||
Valid-License-Identifier: GPL-2.0
|
||||
Valid-License-Identifier: GPL-2.0-only
|
||||
Valid-License-Identifier: GPL-2.0-or-later
|
||||
SPDX-URL: https://spdx.org/licenses/GPL-2.0.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 General Public License (GPL) version 2 only' use:
|
||||
SPDX-License-Identifier: GPL-2.0
|
||||
or
|
||||
SPDX-License-Identifier: GPL-2.0-only
|
||||
For 'GNU General Public License (GPL) version 2 or any later version' use:
|
||||
SPDX-License-Identifier: GPL-2.0-or-later
|
||||
License-Text:
|
||||
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 2, June 1991
|
||||
|
||||
Copyright (C) 1989, 1991 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.
|
||||
|
||||
Preamble
|
||||
|
||||
The licenses for most software are designed to take away your
|
||||
freedom to share and change it. By contrast, the GNU General Public
|
||||
License is intended to guarantee your freedom to share and change free
|
||||
software--to make sure the software is free for all its users. This
|
||||
General Public License applies to most of the Free Software
|
||||
Foundation's software and to any other program whose authors commit to
|
||||
using it. (Some other Free Software Foundation software is covered by
|
||||
the GNU Lesser General Public License instead.) You can apply it to
|
||||
your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, 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 or use pieces of it
|
||||
in new free programs; and that you know you can do these things.
|
||||
|
||||
To protect your rights, we need to make restrictions that forbid
|
||||
anyone to deny you these rights or to ask you to surrender the rights.
|
||||
These restrictions translate to certain responsibilities for you if you
|
||||
distribute copies of the software, or if you modify it.
|
||||
|
||||
For example, if you distribute copies of such a program, whether
|
||||
gratis or for a fee, you must give the recipients all the rights that
|
||||
you have. You must make sure that they, too, receive or can get the
|
||||
source code. And you must show them these terms so they know their
|
||||
rights.
|
||||
|
||||
We protect your rights with two steps: (1) copyright the software, and
|
||||
(2) offer you this license which gives you legal permission to copy,
|
||||
distribute and/or modify the software.
|
||||
|
||||
Also, for each author's protection and ours, we want to make certain
|
||||
that everyone understands that there is no warranty for this free
|
||||
software. If the software is modified by someone else and passed on, we
|
||||
want its recipients to know that what they have is not the original, so
|
||||
that any problems introduced by others will not reflect on the original
|
||||
authors' reputations.
|
||||
|
||||
Finally, any free program is threatened constantly by software
|
||||
patents. We wish to avoid the danger that redistributors of a free
|
||||
program will individually obtain patent licenses, in effect making the
|
||||
program proprietary. To prevent this, we have made it clear that any
|
||||
patent must be licensed for everyone's free use or not licensed at all.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. This License applies to any program or other work which contains
|
||||
a notice placed by the copyright holder saying it may be distributed
|
||||
under the terms of this General Public License. The "Program", below,
|
||||
refers to any such program or work, and a "work based on the Program"
|
||||
means either the Program or any derivative work under copyright law:
|
||||
that is to say, a work containing the Program or a portion of it,
|
||||
either verbatim or with modifications and/or translated into another
|
||||
language. (Hereinafter, translation is included without limitation in
|
||||
the term "modification".) Each licensee is addressed as "you".
|
||||
|
||||
Activities other than copying, distribution and modification are not
|
||||
covered by this License; they are outside its scope. The act of
|
||||
running the Program is not restricted, and the output from the Program
|
||||
is covered only if its contents constitute a work based on the
|
||||
Program (independent of having been made by running the Program).
|
||||
Whether that is true depends on what the Program does.
|
||||
|
||||
1. You may copy and distribute verbatim copies of the Program's
|
||||
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 give any other recipients of the Program a copy of this License
|
||||
along with the Program.
|
||||
|
||||
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 Program or any portion
|
||||
of it, thus forming a work based on the Program, 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) You must cause the modified files to carry prominent notices
|
||||
stating that you changed the files and the date of any change.
|
||||
|
||||
b) You must cause any work that you distribute or publish, that in
|
||||
whole or in part contains or is derived from the Program or any
|
||||
part thereof, to be licensed as a whole at no charge to all third
|
||||
parties under the terms of this License.
|
||||
|
||||
c) If the modified program normally reads commands interactively
|
||||
when run, you must cause it, when started running for such
|
||||
interactive use in the most ordinary way, to print or display an
|
||||
announcement including an appropriate copyright notice and a
|
||||
notice that there is no warranty (or else, saying that you provide
|
||||
a warranty) and that users may redistribute the program under
|
||||
these conditions, and telling the user how to view a copy of this
|
||||
License. (Exception: if the Program itself is interactive but
|
||||
does not normally print such an announcement, your work based on
|
||||
the Program is not required to print an announcement.)
|
||||
|
||||
These requirements apply to the modified work as a whole. If
|
||||
identifiable sections of that work are not derived from the Program,
|
||||
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 Program, 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 Program.
|
||||
|
||||
In addition, mere aggregation of another work not based on the Program
|
||||
with the Program (or with a work based on the Program) on a volume of
|
||||
a storage or distribution medium does not bring the other work under
|
||||
the scope of this License.
|
||||
|
||||
3. You may copy and distribute the Program (or a work based on it,
|
||||
under Section 2) in object code or executable form under the terms of
|
||||
Sections 1 and 2 above provided that you also do one of the following:
|
||||
|
||||
a) 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; or,
|
||||
|
||||
b) Accompany it with a written offer, valid for at least three
|
||||
years, to give any third party, for a charge no more than your
|
||||
cost of physically performing source distribution, a complete
|
||||
machine-readable copy of the corresponding source code, to be
|
||||
distributed under the terms of Sections 1 and 2 above on a medium
|
||||
customarily used for software interchange; or,
|
||||
|
||||
c) Accompany it with the information you received as to the offer
|
||||
to distribute corresponding source code. (This alternative is
|
||||
allowed only for noncommercial distribution and only if you
|
||||
received the program in object code or executable form with such
|
||||
an offer, in accord with Subsection b above.)
|
||||
|
||||
The source code for a work means the preferred form of the work for
|
||||
making modifications to it. For an executable work, 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 executable. However, as a
|
||||
special exception, the source code 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.
|
||||
|
||||
If distribution of executable or 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 counts as
|
||||
distribution of the source code, even though third parties are not
|
||||
compelled to copy the source along with the object code.
|
||||
|
||||
4. You may not copy, modify, sublicense, or distribute the Program
|
||||
except as expressly provided under this License. Any attempt
|
||||
otherwise to copy, modify, sublicense or distribute the Program 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.
|
||||
|
||||
5. 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 Program or its derivative works. These actions are
|
||||
prohibited by law if you do not accept this License. Therefore, by
|
||||
modifying or distributing the Program (or any work based on the
|
||||
Program), you indicate your acceptance of this License to do so, and
|
||||
all its terms and conditions for copying, distributing or modifying
|
||||
the Program or works based on it.
|
||||
|
||||
6. Each time you redistribute the Program (or any work based on the
|
||||
Program), the recipient automatically receives a license from the
|
||||
original licensor to copy, distribute or modify the Program 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 to
|
||||
this License.
|
||||
|
||||
7. 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 Program at all. For example, if a patent
|
||||
license would not permit royalty-free redistribution of the Program 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 Program.
|
||||
|
||||
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.
|
||||
|
||||
8. If the distribution and/or use of the Program is restricted in
|
||||
certain countries either by patents or by copyrighted interfaces, the
|
||||
original copyright holder who places the Program 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.
|
||||
|
||||
9. The Free Software Foundation may publish revised and/or new versions
|
||||
of the 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 Program
|
||||
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 Program does not specify a version number of
|
||||
this License, you may choose any version ever published by the Free Software
|
||||
Foundation.
|
||||
|
||||
10. If you wish to incorporate parts of the Program into other free
|
||||
programs whose distribution conditions are different, 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
|
||||
|
||||
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
|
||||
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
|
||||
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
|
||||
PROVIDE THE PROGRAM "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 PROGRAM IS WITH YOU. SHOULD THE
|
||||
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
|
||||
REPAIR OR CORRECTION.
|
||||
|
||||
12. 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 PROGRAM 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 PROGRAM (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 PROGRAM TO OPERATE WITH ANY OTHER
|
||||
PROGRAMS), 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 Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest
|
||||
possible use to the public, the best way to achieve this is to make it
|
||||
free software which everyone can redistribute and change under these terms.
|
||||
|
||||
To do so, attach the following notices to the program. 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 program's name and a brief idea of what it does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If the program is interactive, make it output a short notice like this
|
||||
when it starts in an interactive mode:
|
||||
|
||||
Gnomovision version 69, Copyright (C) year name of author
|
||||
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||
This is free software, and you are welcome to redistribute it
|
||||
under certain conditions; type `show c' for details.
|
||||
|
||||
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||
parts of the General Public License. Of course, the commands you use may
|
||||
be called something other than `show w' and `show c'; they could even be
|
||||
mouse-clicks or menu items--whatever suits your program.
|
||||
|
||||
You should also get your employer (if you work as a programmer) or your
|
||||
school, if any, to sign a "copyright disclaimer" for the program, if
|
||||
necessary. Here is a sample; alter the names:
|
||||
|
||||
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
|
||||
`Gnomovision' (which makes passes at compilers) written by James Hacker.
|
||||
|
||||
<signature of Ty Coon>, 1 April 1989
|
||||
Ty Coon, President of Vice
|
||||
|
||||
This General Public License does not permit incorporating your program into
|
||||
proprietary programs. If your program is a subroutine library, you may
|
||||
consider it more useful to permit linking proprietary applications with the
|
||||
library. If this is what you want to do, use the GNU Lesser General
|
||||
Public License instead of this License.
|
|
@ -0,0 +1,4 @@
|
|||
# SPDX-License-Identifier: GPL-2.0-or-later OR GFDL-1.2-no-invariants-or-later
|
||||
|
||||
The texinfo version of the license gfdl-1.2 is distributed in the
|
||||
file doc/fdl.texi .
|
|
@ -0,0 +1,690 @@
|
|||
Valid-License-Identifier: GPL-3.0
|
||||
Valid-License-Identifier: GPL-3.0-only
|
||||
Valid-License-Identifier: GPL-3.0-or-later
|
||||
SPDX-URL: https://spdx.org/licenses/GPL-3.0.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 General Public License (GPL) version 3 only' use:
|
||||
SPDX-License-Identifier: GPL-3.0
|
||||
or
|
||||
SPDX-License-Identifier: GPL-3.0-only
|
||||
For 'GNU General Public License (GPL) version 3 or any later version' use:
|
||||
SPDX-License-Identifier: GPL-3.0-or-later
|
||||
License-Text:
|
||||
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 3, 29 June 2007
|
||||
|
||||
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
The GNU General Public License is a free, copyleft license for
|
||||
software and other kinds of works.
|
||||
|
||||
The licenses for most software and other practical works are designed
|
||||
to take away your freedom to share and change the works. By contrast,
|
||||
the GNU General Public License is intended to guarantee your freedom to
|
||||
share and change all versions of a program--to make sure it remains free
|
||||
software for all its users. We, the Free Software Foundation, use the
|
||||
GNU General Public License for most of our software; it applies also to
|
||||
any other work released this way by its authors. You can apply it to
|
||||
your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, 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
|
||||
them if you wish), that you receive source code or can get it if you
|
||||
want it, that you can change the software or use pieces of it in new
|
||||
free programs, and that you know you can do these things.
|
||||
|
||||
To protect your rights, we need to prevent others from denying you
|
||||
these rights or asking you to surrender the rights. Therefore, you have
|
||||
certain responsibilities if you distribute copies of the software, or if
|
||||
you modify it: responsibilities to respect the freedom of others.
|
||||
|
||||
For example, if you distribute copies of such a program, whether
|
||||
gratis or for a fee, you must pass on to the recipients the same
|
||||
freedoms that you received. You must make sure that they, too, receive
|
||||
or can get the source code. And you must show them these terms so they
|
||||
know their rights.
|
||||
|
||||
Developers that use the GNU GPL protect your rights with two steps:
|
||||
(1) assert copyright on the software, and (2) offer you this License
|
||||
giving you legal permission to copy, distribute and/or modify it.
|
||||
|
||||
For the developers' and authors' protection, the GPL clearly explains
|
||||
that there is no warranty for this free software. For both users' and
|
||||
authors' sake, the GPL requires that modified versions be marked as
|
||||
changed, so that their problems will not be attributed erroneously to
|
||||
authors of previous versions.
|
||||
|
||||
Some devices are designed to deny users access to install or run
|
||||
modified versions of the software inside them, although the manufacturer
|
||||
can do so. This is fundamentally incompatible with the aim of
|
||||
protecting users' freedom to change the software. The systematic
|
||||
pattern of such abuse occurs in the area of products for individuals to
|
||||
use, which is precisely where it is most unacceptable. Therefore, we
|
||||
have designed this version of the GPL to prohibit the practice for those
|
||||
products. If such problems arise substantially in other domains, we
|
||||
stand ready to extend this provision to those domains in future versions
|
||||
of the GPL, as needed to protect the freedom of users.
|
||||
|
||||
Finally, every program is threatened constantly by software patents.
|
||||
States should not allow patents to restrict development and use of
|
||||
software on general-purpose computers, but in those that do, we wish to
|
||||
avoid the special danger that patents applied to a free program could
|
||||
make it effectively proprietary. To prevent this, the GPL assures that
|
||||
patents cannot be used to render the program non-free.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
TERMS AND CONDITIONS
|
||||
|
||||
0. Definitions.
|
||||
|
||||
"This License" refers to version 3 of the GNU General Public License.
|
||||
|
||||
"Copyright" also means copyright-like laws that apply to other kinds of
|
||||
works, such as semiconductor masks.
|
||||
|
||||
"The Program" refers to any copyrightable work licensed under this
|
||||
License. Each licensee is addressed as "you". "Licensees" and
|
||||
"recipients" may be individuals or organizations.
|
||||
|
||||
To "modify" a work means to copy from or adapt all or part of the work
|
||||
in a fashion requiring copyright permission, other than the making of an
|
||||
exact copy. The resulting work is called a "modified version" of the
|
||||
earlier work or a work "based on" the earlier work.
|
||||
|
||||
A "covered work" means either the unmodified Program or a work based
|
||||
on the Program.
|
||||
|
||||
To "propagate" a work means to do anything with it that, without
|
||||
permission, would make you directly or secondarily liable for
|
||||
infringement under applicable copyright law, except executing it on a
|
||||
computer or modifying a private copy. Propagation includes copying,
|
||||
distribution (with or without modification), making available to the
|
||||
public, and in some countries other activities as well.
|
||||
|
||||
To "convey" a work means any kind of propagation that enables other
|
||||
parties to make or receive copies. Mere interaction with a user through
|
||||
a computer network, with no transfer of a copy, is not conveying.
|
||||
|
||||
An interactive user interface displays "Appropriate Legal Notices"
|
||||
to the extent that it includes a convenient and prominently visible
|
||||
feature that (1) displays an appropriate copyright notice, and (2)
|
||||
tells the user that there is no warranty for the work (except to the
|
||||
extent that warranties are provided), that licensees may convey the
|
||||
work under this License, and how to view a copy of this License. If
|
||||
the interface presents a list of user commands or options, such as a
|
||||
menu, a prominent item in the list meets this criterion.
|
||||
|
||||
1. Source Code.
|
||||
|
||||
The "source code" for a work means the preferred form of the work
|
||||
for making modifications to it. "Object code" means any non-source
|
||||
form of a work.
|
||||
|
||||
A "Standard Interface" means an interface that either is an official
|
||||
standard defined by a recognized standards body, or, in the case of
|
||||
interfaces specified for a particular programming language, one that
|
||||
is widely used among developers working in that language.
|
||||
|
||||
The "System Libraries" of an executable work include anything, other
|
||||
than the work as a whole, that (a) is included in the normal form of
|
||||
packaging a Major Component, but which is not part of that Major
|
||||
Component, and (b) serves only to enable use of the work with that
|
||||
Major Component, or to implement a Standard Interface for which an
|
||||
implementation is available to the public in source code form. A
|
||||
"Major Component", in this context, means a major essential component
|
||||
(kernel, window system, and so on) of the specific operating system
|
||||
(if any) on which the executable work runs, or a compiler used to
|
||||
produce the work, or an object code interpreter used to run it.
|
||||
|
||||
The "Corresponding Source" for a work in object code form means all
|
||||
the source code needed to generate, install, and (for an executable
|
||||
work) run the object code and to modify the work, including scripts to
|
||||
control those activities. However, it does not include the work's
|
||||
System Libraries, or general-purpose tools or generally available free
|
||||
programs which are used unmodified in performing those activities but
|
||||
which are not part of the work. For example, Corresponding Source
|
||||
includes interface definition files associated with source files for
|
||||
the work, and the source code for shared libraries and dynamically
|
||||
linked subprograms that the work is specifically designed to require,
|
||||
such as by intimate data communication or control flow between those
|
||||
subprograms and other parts of the work.
|
||||
|
||||
The Corresponding Source need not include anything that users
|
||||
can regenerate automatically from other parts of the Corresponding
|
||||
Source.
|
||||
|
||||
The Corresponding Source for a work in source code form is that
|
||||
same work.
|
||||
|
||||
2. Basic Permissions.
|
||||
|
||||
All rights granted under this License are granted for the term of
|
||||
copyright on the Program, and are irrevocable provided the stated
|
||||
conditions are met. This License explicitly affirms your unlimited
|
||||
permission to run the unmodified Program. The output from running a
|
||||
covered work is covered by this License only if the output, given its
|
||||
content, constitutes a covered work. This License acknowledges your
|
||||
rights of fair use or other equivalent, as provided by copyright law.
|
||||
|
||||
You may make, run and propagate covered works that you do not
|
||||
convey, without conditions so long as your license otherwise remains
|
||||
in force. You may convey covered works to others for the sole purpose
|
||||
of having them make modifications exclusively for you, or provide you
|
||||
with facilities for running those works, provided that you comply with
|
||||
the terms of this License in conveying all material for which you do
|
||||
not control copyright. Those thus making or running the covered works
|
||||
for you must do so exclusively on your behalf, under your direction
|
||||
and control, on terms that prohibit them from making any copies of
|
||||
your copyrighted material outside their relationship with you.
|
||||
|
||||
Conveying under any other circumstances is permitted solely under
|
||||
the conditions stated below. Sublicensing is not allowed; section 10
|
||||
makes it unnecessary.
|
||||
|
||||
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
|
||||
|
||||
No covered work shall be deemed part of an effective technological
|
||||
measure under any applicable law fulfilling obligations under article
|
||||
11 of the WIPO copyright treaty adopted on 20 December 1996, or
|
||||
similar laws prohibiting or restricting circumvention of such
|
||||
measures.
|
||||
|
||||
When you convey a covered work, you waive any legal power to forbid
|
||||
circumvention of technological measures to the extent such circumvention
|
||||
is effected by exercising rights under this License with respect to
|
||||
the covered work, and you disclaim any intention to limit operation or
|
||||
modification of the work as a means of enforcing, against the work's
|
||||
users, your or third parties' legal rights to forbid circumvention of
|
||||
technological measures.
|
||||
|
||||
4. Conveying Verbatim Copies.
|
||||
|
||||
You may convey verbatim copies of the Program's source code as you
|
||||
receive it, in any medium, provided that you conspicuously and
|
||||
appropriately publish on each copy an appropriate copyright notice;
|
||||
keep intact all notices stating that this License and any
|
||||
non-permissive terms added in accord with section 7 apply to the code;
|
||||
keep intact all notices of the absence of any warranty; and give all
|
||||
recipients a copy of this License along with the Program.
|
||||
|
||||
You may charge any price or no price for each copy that you convey,
|
||||
and you may offer support or warranty protection for a fee.
|
||||
|
||||
5. Conveying Modified Source Versions.
|
||||
|
||||
You may convey a work based on the Program, or the modifications to
|
||||
produce it from the Program, in the form of source code under the
|
||||
terms of section 4, provided that you also meet all of these conditions:
|
||||
|
||||
a) The work must carry prominent notices stating that you modified
|
||||
it, and giving a relevant date.
|
||||
|
||||
b) The work must carry prominent notices stating that it is
|
||||
released under this License and any conditions added under section
|
||||
7. This requirement modifies the requirement in section 4 to
|
||||
"keep intact all notices".
|
||||
|
||||
c) You must license the entire work, as a whole, under this
|
||||
License to anyone who comes into possession of a copy. This
|
||||
License will therefore apply, along with any applicable section 7
|
||||
additional terms, to the whole of the work, and all its parts,
|
||||
regardless of how they are packaged. This License gives no
|
||||
permission to license the work in any other way, but it does not
|
||||
invalidate such permission if you have separately received it.
|
||||
|
||||
d) If the work has interactive user interfaces, each must display
|
||||
Appropriate Legal Notices; however, if the Program has interactive
|
||||
interfaces that do not display Appropriate Legal Notices, your
|
||||
work need not make them do so.
|
||||
|
||||
A compilation of a covered work with other separate and independent
|
||||
works, which are not by their nature extensions of the covered work,
|
||||
and which are not combined with it such as to form a larger program,
|
||||
in or on a volume of a storage or distribution medium, is called an
|
||||
"aggregate" if the compilation and its resulting copyright are not
|
||||
used to limit the access or legal rights of the compilation's users
|
||||
beyond what the individual works permit. Inclusion of a covered work
|
||||
in an aggregate does not cause this License to apply to the other
|
||||
parts of the aggregate.
|
||||
|
||||
6. Conveying Non-Source Forms.
|
||||
|
||||
You may convey a covered work in object code form under the terms
|
||||
of sections 4 and 5, provided that you also convey the
|
||||
machine-readable Corresponding Source under the terms of this License,
|
||||
in one of these ways:
|
||||
|
||||
a) Convey the object code in, or embodied in, a physical product
|
||||
(including a physical distribution medium), accompanied by the
|
||||
Corresponding Source fixed on a durable physical medium
|
||||
customarily used for software interchange.
|
||||
|
||||
b) Convey the object code in, or embodied in, a physical product
|
||||
(including a physical distribution medium), accompanied by a
|
||||
written offer, valid for at least three years and valid for as
|
||||
long as you offer spare parts or customer support for that product
|
||||
model, to give anyone who possesses the object code either (1) a
|
||||
copy of the Corresponding Source for all the software in the
|
||||
product that is covered by this License, on a durable physical
|
||||
medium customarily used for software interchange, for a price no
|
||||
more than your reasonable cost of physically performing this
|
||||
conveying of source, or (2) access to copy the
|
||||
Corresponding Source from a network server at no charge.
|
||||
|
||||
c) Convey individual copies of the object code with a copy of the
|
||||
written offer to provide the Corresponding Source. This
|
||||
alternative is allowed only occasionally and noncommercially, and
|
||||
only if you received the object code with such an offer, in accord
|
||||
with subsection 6b.
|
||||
|
||||
d) Convey the object code by offering access from a designated
|
||||
place (gratis or for a charge), and offer equivalent access to the
|
||||
Corresponding Source in the same way through the same place at no
|
||||
further charge. You need not require recipients to copy the
|
||||
Corresponding Source along with the object code. If the place to
|
||||
copy the object code is a network server, the Corresponding Source
|
||||
may be on a different server (operated by you or a third party)
|
||||
that supports equivalent copying facilities, provided you maintain
|
||||
clear directions next to the object code saying where to find the
|
||||
Corresponding Source. Regardless of what server hosts the
|
||||
Corresponding Source, you remain obligated to ensure that it is
|
||||
available for as long as needed to satisfy these requirements.
|
||||
|
||||
e) Convey the object code using peer-to-peer transmission, provided
|
||||
you inform other peers where the object code and Corresponding
|
||||
Source of the work are being offered to the general public at no
|
||||
charge under subsection 6d.
|
||||
|
||||
A separable portion of the object code, whose source code is excluded
|
||||
from the Corresponding Source as a System Library, need not be
|
||||
included in conveying the object code work.
|
||||
|
||||
A "User Product" is either (1) a "consumer product", which means any
|
||||
tangible personal property which is normally used for personal, family,
|
||||
or household purposes, or (2) anything designed or sold for incorporation
|
||||
into a dwelling. In determining whether a product is a consumer product,
|
||||
doubtful cases shall be resolved in favor of coverage. For a particular
|
||||
product received by a particular user, "normally used" refers to a
|
||||
typical or common use of that class of product, regardless of the status
|
||||
of the particular user or of the way in which the particular user
|
||||
actually uses, or expects or is expected to use, the product. A product
|
||||
is a consumer product regardless of whether the product has substantial
|
||||
commercial, industrial or non-consumer uses, unless such uses represent
|
||||
the only significant mode of use of the product.
|
||||
|
||||
"Installation Information" for a User Product means any methods,
|
||||
procedures, authorization keys, or other information required to install
|
||||
and execute modified versions of a covered work in that User Product from
|
||||
a modified version of its Corresponding Source. The information must
|
||||
suffice to ensure that the continued functioning of the modified object
|
||||
code is in no case prevented or interfered with solely because
|
||||
modification has been made.
|
||||
|
||||
If you convey an object code work under this section in, or with, or
|
||||
specifically for use in, a User Product, and the conveying occurs as
|
||||
part of a transaction in which the right of possession and use of the
|
||||
User Product is transferred to the recipient in perpetuity or for a
|
||||
fixed term (regardless of how the transaction is characterized), the
|
||||
Corresponding Source conveyed under this section must be accompanied
|
||||
by the Installation Information. But this requirement does not apply
|
||||
if neither you nor any third party retains the ability to install
|
||||
modified object code on the User Product (for example, the work has
|
||||
been installed in ROM).
|
||||
|
||||
The requirement to provide Installation Information does not include a
|
||||
requirement to continue to provide support service, warranty, or updates
|
||||
for a work that has been modified or installed by the recipient, or for
|
||||
the User Product in which it has been modified or installed. Access to a
|
||||
network may be denied when the modification itself materially and
|
||||
adversely affects the operation of the network or violates the rules and
|
||||
protocols for communication across the network.
|
||||
|
||||
Corresponding Source conveyed, and Installation Information provided,
|
||||
in accord with this section must be in a format that is publicly
|
||||
documented (and with an implementation available to the public in
|
||||
source code form), and must require no special password or key for
|
||||
unpacking, reading or copying.
|
||||
|
||||
7. Additional Terms.
|
||||
|
||||
"Additional permissions" are terms that supplement the terms of this
|
||||
License by making exceptions from one or more of its conditions.
|
||||
Additional permissions that are applicable to the entire Program shall
|
||||
be treated as though they were included in this License, to the extent
|
||||
that they are valid under applicable law. If additional permissions
|
||||
apply only to part of the Program, that part may be used separately
|
||||
under those permissions, but the entire Program remains governed by
|
||||
this License without regard to the additional permissions.
|
||||
|
||||
When you convey a copy of a covered work, you may at your option
|
||||
remove any additional permissions from that copy, or from any part of
|
||||
it. (Additional permissions may be written to require their own
|
||||
removal in certain cases when you modify the work.) You may place
|
||||
additional permissions on material, added by you to a covered work,
|
||||
for which you have or can give appropriate copyright permission.
|
||||
|
||||
Notwithstanding any other provision of this License, for material you
|
||||
add to a covered work, you may (if authorized by the copyright holders of
|
||||
that material) supplement the terms of this License with terms:
|
||||
|
||||
a) Disclaiming warranty or limiting liability differently from the
|
||||
terms of sections 15 and 16 of this License; or
|
||||
|
||||
b) Requiring preservation of specified reasonable legal notices or
|
||||
author attributions in that material or in the Appropriate Legal
|
||||
Notices displayed by works containing it; or
|
||||
|
||||
c) Prohibiting misrepresentation of the origin of that material, or
|
||||
requiring that modified versions of such material be marked in
|
||||
reasonable ways as different from the original version; or
|
||||
|
||||
d) Limiting the use for publicity purposes of names of licensors or
|
||||
authors of the material; or
|
||||
|
||||
e) Declining to grant rights under trademark law for use of some
|
||||
trade names, trademarks, or service marks; or
|
||||
|
||||
f) Requiring indemnification of licensors and authors of that
|
||||
material by anyone who conveys the material (or modified versions of
|
||||
it) with contractual assumptions of liability to the recipient, for
|
||||
any liability that these contractual assumptions directly impose on
|
||||
those licensors and authors.
|
||||
|
||||
All other non-permissive additional terms are considered "further
|
||||
restrictions" within the meaning of section 10. If the Program as you
|
||||
received it, or any part of it, contains a notice stating that it is
|
||||
governed by this License along with a term that is a further
|
||||
restriction, you may remove that term. If a license document contains
|
||||
a further restriction but permits relicensing or conveying under this
|
||||
License, you may add to a covered work material governed by the terms
|
||||
of that license document, provided that the further restriction does
|
||||
not survive such relicensing or conveying.
|
||||
|
||||
If you add terms to a covered work in accord with this section, you
|
||||
must place, in the relevant source files, a statement of the
|
||||
additional terms that apply to those files, or a notice indicating
|
||||
where to find the applicable terms.
|
||||
|
||||
Additional terms, permissive or non-permissive, may be stated in the
|
||||
form of a separately written license, or stated as exceptions;
|
||||
the above requirements apply either way.
|
||||
|
||||
8. Termination.
|
||||
|
||||
You may not propagate or modify a covered work except as expressly
|
||||
provided under this License. Any attempt otherwise to propagate or
|
||||
modify it is void, and will automatically terminate your rights under
|
||||
this License (including any patent licenses granted under the third
|
||||
paragraph of section 11).
|
||||
|
||||
However, if you cease all violation of this License, then your
|
||||
license from a particular copyright holder is reinstated (a)
|
||||
provisionally, unless and until the copyright holder explicitly and
|
||||
finally terminates your license, and (b) permanently, if the copyright
|
||||
holder fails to notify you of the violation by some reasonable means
|
||||
prior to 60 days after the cessation.
|
||||
|
||||
Moreover, your license from a particular copyright holder is
|
||||
reinstated permanently if the copyright holder notifies you of the
|
||||
violation by some reasonable means, this is the first time you have
|
||||
received notice of violation of this License (for any work) from that
|
||||
copyright holder, and you cure the violation prior to 30 days after
|
||||
your receipt of the notice.
|
||||
|
||||
Termination of your rights under this section does not terminate the
|
||||
licenses of parties who have received copies or rights from you under
|
||||
this License. If your rights have been terminated and not permanently
|
||||
reinstated, you do not qualify to receive new licenses for the same
|
||||
material under section 10.
|
||||
|
||||
9. Acceptance Not Required for Having Copies.
|
||||
|
||||
You are not required to accept this License in order to receive or
|
||||
run a copy of the Program. Ancillary propagation of a covered work
|
||||
occurring solely as a consequence of using peer-to-peer transmission
|
||||
to receive a copy likewise does not require acceptance. However,
|
||||
nothing other than this License grants you permission to propagate or
|
||||
modify any covered work. These actions infringe copyright if you do
|
||||
not accept this License. Therefore, by modifying or propagating a
|
||||
covered work, you indicate your acceptance of this License to do so.
|
||||
|
||||
10. Automatic Licensing of Downstream Recipients.
|
||||
|
||||
Each time you convey a covered work, the recipient automatically
|
||||
receives a license from the original licensors, to run, modify and
|
||||
propagate that work, subject to this License. You are not responsible
|
||||
for enforcing compliance by third parties with this License.
|
||||
|
||||
An "entity transaction" is a transaction transferring control of an
|
||||
organization, or substantially all assets of one, or subdividing an
|
||||
organization, or merging organizations. If propagation of a covered
|
||||
work results from an entity transaction, each party to that
|
||||
transaction who receives a copy of the work also receives whatever
|
||||
licenses to the work the party's predecessor in interest had or could
|
||||
give under the previous paragraph, plus a right to possession of the
|
||||
Corresponding Source of the work from the predecessor in interest, if
|
||||
the predecessor has it or can get it with reasonable efforts.
|
||||
|
||||
You may not impose any further restrictions on the exercise of the
|
||||
rights granted or affirmed under this License. For example, you may
|
||||
not impose a license fee, royalty, or other charge for exercise of
|
||||
rights granted under this License, and you may not initiate litigation
|
||||
(including a cross-claim or counterclaim in a lawsuit) alleging that
|
||||
any patent claim is infringed by making, using, selling, offering for
|
||||
sale, or importing the Program or any portion of it.
|
||||
|
||||
11. Patents.
|
||||
|
||||
A "contributor" is a copyright holder who authorizes use under this
|
||||
License of the Program or a work on which the Program is based. The
|
||||
work thus licensed is called the contributor's "contributor version".
|
||||
|
||||
A contributor's "essential patent claims" are all patent claims
|
||||
owned or controlled by the contributor, whether already acquired or
|
||||
hereafter acquired, that would be infringed by some manner, permitted
|
||||
by this License, of making, using, or selling its contributor version,
|
||||
but do not include claims that would be infringed only as a
|
||||
consequence of further modification of the contributor version. For
|
||||
purposes of this definition, "control" includes the right to grant
|
||||
patent sublicenses in a manner consistent with the requirements of
|
||||
this License.
|
||||
|
||||
Each contributor grants you a non-exclusive, worldwide, royalty-free
|
||||
patent license under the contributor's essential patent claims, to
|
||||
make, use, sell, offer for sale, import and otherwise run, modify and
|
||||
propagate the contents of its contributor version.
|
||||
|
||||
In the following three paragraphs, a "patent license" is any express
|
||||
agreement or commitment, however denominated, not to enforce a patent
|
||||
(such as an express permission to practice a patent or covenant not to
|
||||
sue for patent infringement). To "grant" such a patent license to a
|
||||
party means to make such an agreement or commitment not to enforce a
|
||||
patent against the party.
|
||||
|
||||
If you convey a covered work, knowingly relying on a patent license,
|
||||
and the Corresponding Source of the work is not available for anyone
|
||||
to copy, free of charge and under the terms of this License, through a
|
||||
publicly available network server or other readily accessible means,
|
||||
then you must either (1) cause the Corresponding Source to be so
|
||||
available, or (2) arrange to deprive yourself of the benefit of the
|
||||
patent license for this particular work, or (3) arrange, in a manner
|
||||
consistent with the requirements of this License, to extend the patent
|
||||
license to downstream recipients. "Knowingly relying" means you have
|
||||
actual knowledge that, but for the patent license, your conveying the
|
||||
covered work in a country, or your recipient's use of the covered work
|
||||
in a country, would infringe one or more identifiable patents in that
|
||||
country that you have reason to believe are valid.
|
||||
|
||||
If, pursuant to or in connection with a single transaction or
|
||||
arrangement, you convey, or propagate by procuring conveyance of, a
|
||||
covered work, and grant a patent license to some of the parties
|
||||
receiving the covered work authorizing them to use, propagate, modify
|
||||
or convey a specific copy of the covered work, then the patent license
|
||||
you grant is automatically extended to all recipients of the covered
|
||||
work and works based on it.
|
||||
|
||||
A patent license is "discriminatory" if it does not include within
|
||||
the scope of its coverage, prohibits the exercise of, or is
|
||||
conditioned on the non-exercise of one or more of the rights that are
|
||||
specifically granted under this License. You may not convey a covered
|
||||
work if you are a party to an arrangement with a third party that is
|
||||
in the business of distributing software, under which you make payment
|
||||
to the third party based on the extent of your activity of conveying
|
||||
the work, and under which the third party grants, to any of the
|
||||
parties who would receive the covered work from you, a discriminatory
|
||||
patent license (a) in connection with copies of the covered work
|
||||
conveyed by you (or copies made from those copies), or (b) primarily
|
||||
for and in connection with specific products or compilations that
|
||||
contain the covered work, unless you entered into that arrangement,
|
||||
or that patent license was granted, prior to 28 March 2007.
|
||||
|
||||
Nothing in this License shall be construed as excluding or limiting
|
||||
any implied license or other defenses to infringement that may
|
||||
otherwise be available to you under applicable patent law.
|
||||
|
||||
12. No Surrender of Others' Freedom.
|
||||
|
||||
If 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 convey a
|
||||
covered work so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you may
|
||||
not convey it at all. For example, if you agree to terms that obligate you
|
||||
to collect a royalty for further conveying from those to whom you convey
|
||||
the Program, the only way you could satisfy both those terms and this
|
||||
License would be to refrain entirely from conveying the Program.
|
||||
|
||||
13. Use with the GNU Affero General Public License.
|
||||
|
||||
Notwithstanding any other provision of this License, you have
|
||||
permission to link or combine any covered work with a work licensed
|
||||
under version 3 of the GNU Affero General Public License into a single
|
||||
combined work, and to convey the resulting work. The terms of this
|
||||
License will continue to apply to the part which is the covered work,
|
||||
but the special requirements of the GNU Affero General Public License,
|
||||
section 13, concerning interaction through a network will apply to the
|
||||
combination as such.
|
||||
|
||||
14. Revised Versions of this License.
|
||||
|
||||
The Free Software Foundation may publish revised and/or new versions of
|
||||
the GNU 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
|
||||
Program specifies that a certain numbered version of the GNU General
|
||||
Public License "or any later version" applies to it, you have the
|
||||
option of following the terms and conditions either of that numbered
|
||||
version or of any later version published by the Free Software
|
||||
Foundation. If the Program does not specify a version number of the
|
||||
GNU General Public License, you may choose any version ever published
|
||||
by the Free Software Foundation.
|
||||
|
||||
If the Program specifies that a proxy can decide which future
|
||||
versions of the GNU General Public License can be used, that proxy's
|
||||
public statement of acceptance of a version permanently authorizes you
|
||||
to choose that version for the Program.
|
||||
|
||||
Later license versions may give you additional or different
|
||||
permissions. However, no additional obligations are imposed on any
|
||||
author or copyright holder as a result of your choosing to follow a
|
||||
later version.
|
||||
|
||||
15. Disclaimer of Warranty.
|
||||
|
||||
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
|
||||
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
|
||||
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "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 PROGRAM
|
||||
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
|
||||
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
||||
|
||||
16. Limitation of Liability.
|
||||
|
||||
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
|
||||
THE PROGRAM 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 PROGRAM (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 PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
|
||||
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
|
||||
SUCH DAMAGES.
|
||||
|
||||
17. Interpretation of Sections 15 and 16.
|
||||
|
||||
If the disclaimer of warranty and limitation of liability provided
|
||||
above cannot be given local legal effect according to their terms,
|
||||
reviewing courts shall apply local law that most closely approximates
|
||||
an absolute waiver of all civil liability in connection with the
|
||||
Program, unless a warranty or assumption of liability accompanies a
|
||||
copy of the Program in return for a fee.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest
|
||||
possible use to the public, the best way to achieve this is to make it
|
||||
free software which everyone can redistribute and change under these terms.
|
||||
|
||||
To do so, attach the following notices to the program. It is safest
|
||||
to attach them to the start of each source file to most effectively
|
||||
state 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 program's name and a brief idea of what it does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If the program does terminal interaction, make it output a short
|
||||
notice like this when it starts in an interactive mode:
|
||||
|
||||
<program> Copyright (C) <year> <name of author>
|
||||
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||
This is free software, and you are welcome to redistribute it
|
||||
under certain conditions; type `show c' for details.
|
||||
|
||||
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||
parts of the General Public License. Of course, your program's commands
|
||||
might be different; for a GUI interface, you would use an "about box".
|
||||
|
||||
You should also get your employer (if you work as a programmer) or school,
|
||||
if any, to sign a "copyright disclaimer" for the program, if necessary.
|
||||
For more information on this, and how to apply and follow the GNU GPL, see
|
||||
<https://www.gnu.org/licenses/>.
|
||||
|
||||
The GNU General Public License does not permit incorporating your program
|
||||
into proprietary programs. If your program is a subroutine library, you
|
||||
may consider it more useful to permit linking proprietary applications with
|
||||
the library. If this is what you want to do, use the GNU Lesser General
|
||||
Public License instead of this License. But first, please read
|
||||
<https://www.gnu.org/licenses/why-not-lgpl.html>.
|
11
Makefile.am
11
Makefile.am
|
@ -44,7 +44,6 @@ if INTERNAL_JIMTCL
|
|||
AM_CPPFLAGS += -I$(top_srcdir)/jimtcl \
|
||||
-I$(top_builddir)/jimtcl
|
||||
endif
|
||||
EXTRA_DIST_NEWS != ls $(srcdir)/NEWS-*
|
||||
EXTRA_DIST += \
|
||||
BUGS \
|
||||
HACKING \
|
||||
|
@ -53,6 +52,14 @@ EXTRA_DIST += \
|
|||
README.macOS \
|
||||
$(EXTRA_DIST_NEWS) \
|
||||
Doxyfile.in \
|
||||
LICENSES/license-rules.txt \
|
||||
LICENSES/preferred/BSD-1-Clause \
|
||||
LICENSES/preferred/BSD-2-Clause \
|
||||
LICENSES/preferred/BSD-3-Clause \
|
||||
LICENSES/preferred/GFDL-1.2 \
|
||||
LICENSES/preferred/gfdl-1.2.texi.readme \
|
||||
LICENSES/preferred/GPL-2.0 \
|
||||
LICENSES/stand-alone/GPL-3.0 \
|
||||
tools/logger.pl \
|
||||
tools/rlink_make_speed_table \
|
||||
tools/st7_dtc_as \
|
||||
|
@ -118,6 +125,8 @@ uninstall-hook:
|
|||
distclean-local:
|
||||
rm -rf Doxyfile doxygen
|
||||
rm -f $(srcdir)/jimtcl/configure.gnu
|
||||
# FIXME: workaround for jimtcl 0.80 only. Remove from jimtcl 0.81
|
||||
rm -f jimtcl/examples.api/Makefile
|
||||
|
||||
# We want every change to have Signed-off-by. This is tricky to enforce in
|
||||
# Travis, because it automatically makes temporary commits when merging. So
|
||||
|
|
205
NEWS
205
NEWS
|
@ -2,232 +2,29 @@ This file includes highlights of the changes made in the OpenOCD
|
|||
source archive release.
|
||||
|
||||
JTAG Layer:
|
||||
* add debug level 4 for verbose I/O debug
|
||||
* bitbang, add read buffer to improve performance
|
||||
* Cadence SystemVerilog Direct Programming Interface (DPI) adapter driver
|
||||
* CMSIS-DAP v2 (USB bulk based) adapter driver
|
||||
* Cypress KitProg adapter driver
|
||||
* FTDI FT232R sync bitbang adapter driver
|
||||
* Linux GPIOD bitbang adapter driver through libgpiod
|
||||
* Mellanox rshim USB or PCIe adapter driver
|
||||
* Nuvoton Nu-Link and Nu-Link2 adapter drivers
|
||||
* NXP IMX GPIO mmap based adapter driver
|
||||
* ST-Link consolidate all versions in single config
|
||||
* ST-Link read properly old USB serial numbers
|
||||
* STLink/V3 support (for ST devices only !)
|
||||
* STM8 SWIM transport
|
||||
* TI XDS110 adapter driver
|
||||
* Xilinx XVC/PCIe adapter driver
|
||||
|
||||
Boundary Scan:
|
||||
|
||||
Target Layer:
|
||||
* 64 bit address support
|
||||
* ARCv2 target support
|
||||
* ARM Cortex-A hypervisor mode support
|
||||
* ARM Cortex-M fast PC sampling support for profiling
|
||||
* ARM generic CTI support
|
||||
* ARM generic mem-ap target support
|
||||
* ARMv7-A MMU tools
|
||||
* ARMv7m traces add TCP stream server
|
||||
* ARMv8 AARCH64 target support and semihosting support
|
||||
* ARMv8 AARCH64 disassembler support through capstone library
|
||||
* ARMv8-M target support
|
||||
* EnSilica eSi-RISC target support, including instruction tracing
|
||||
eSi-Trace support
|
||||
* MIPS64 target support
|
||||
* Motorola SREC S6 record image file support
|
||||
* RISC-V target support
|
||||
* SEGGER Real Time Transfer (RTT) initial support (for single target,
|
||||
Cortex-M only)
|
||||
* ST STM8 target support
|
||||
* Various MIPS32 target improvements
|
||||
|
||||
Flash Layer:
|
||||
* Atheros (ath79) SPI interface support
|
||||
* Atmel atmega128rfa1 support
|
||||
* Atmel SAM D21, D51, DA1, E51, E53, E54, G55, R30 support
|
||||
* Atmel SAMC2?N* support
|
||||
* Cypress PSoC5LP, PSoC6 support
|
||||
* EnSilica eSi-RISC support
|
||||
* Foshan Synwit Tech SWM050 support
|
||||
* Maxim Integrated MAX32XXX support
|
||||
* Nordic Semiconductor nRF51822, nRF52810, nRF52832 support
|
||||
* NXP Kinetis K27, K28, KE1x, KEAx, KL28, KL8x, KV5x, KWx support
|
||||
* Renesas RPC HF support
|
||||
* SH QSPI support
|
||||
* SiFive Freedom E support
|
||||
* Silicon Labs EFR-family, EZR32HG support
|
||||
* ST BlueNRG support
|
||||
* ST STM32 QUAD/OCTO-SPI interface support for Flash, FRAM and EEPROM
|
||||
* ST STM32F72x, STM32F4x3, STM32H7xx support
|
||||
* ST STM32G0xx, STM32G4xx, STM32L4x, STM32WB, STM32WL support
|
||||
* ST STM32L5x support (non secure mode)
|
||||
* TI CC13xx, CC26xx, CC32xx support
|
||||
* TI MSP432 support
|
||||
* Winner Micro w600 support
|
||||
* Xilinx XCF platform support
|
||||
* Various discrete SPI NOR flashes support
|
||||
|
||||
Board, Target, and Interface Configuration Scripts:
|
||||
* 8devices LIMA board config
|
||||
* Achilles Instant-Development Kit Arria 10 board config
|
||||
* Amazon Kindle 2 and DX board config
|
||||
* Analog Devices ADSP-SC58x, ADSP-SC584-EZBRD board config
|
||||
* Andes Technology ADP-XC7KFF676 board config
|
||||
* Andes Technology Corvette-F1 board config
|
||||
* ARM Musca A board config
|
||||
* Arty Spartan 7 FPGA board config
|
||||
* Atmel SAMD10 Xplained mini board config
|
||||
* Atmel SAMD11 Xplained Pro board config
|
||||
* Atmel SAM G55 Xplained Pro board config
|
||||
* AVNET UltraZED EG StarterKit board config
|
||||
* Blue Pill STM32F103C8 board config
|
||||
* DP Busblaster v4.1a board config
|
||||
* DPTechnics DPT-Board-v1 board config
|
||||
* Emcraft imx8 SOM BSB board config
|
||||
* Globalscale ESPRESSObin board config
|
||||
* Kasli board config
|
||||
* Kintex Ultrascale XCKU040 board config
|
||||
* Knovative KC-100 board config
|
||||
* LeMaker HiKey board config
|
||||
* Microchip (Atmel) SAME54 Xplained Pro board config
|
||||
* Microchip (Atmel) SAML11 Xplained Pro board config
|
||||
* Nordic module NRF52 board config
|
||||
* Numato Lab Mimas A7 board config
|
||||
* NXP Freedom FRDM-LS1012A board config
|
||||
* NXP IMX7SABRE board config
|
||||
* NXP IMX8MP-EVK board config
|
||||
* NXP MC-IMX8M-EVK board config
|
||||
* QuickLogic QuickFeather board config
|
||||
* Renesas R-Car E2, H2, M2 board config
|
||||
* Renesas R-Car Salvator-X(S) board config
|
||||
* Renesas RZ/A1H GR-Peach board config
|
||||
* Rigado BMD-300 board config
|
||||
* Sayma AMC board config
|
||||
* Sifive e31arty, e51arty, hifive1 board config
|
||||
* ST B-L475E-IOT01A board config
|
||||
* ST BlueNRG idb007v1, idb008v1, idb011v1 board config
|
||||
* ST STM32F412g discovery board config
|
||||
* ST STM32F413h discovery board config
|
||||
* ST STM32F469i discovery board config
|
||||
* ST STM32F7 Nucleo board config
|
||||
* ST STM32F723e discovery board config
|
||||
* ST STM32F746g discovery board config
|
||||
* ST STM32F769i discovery board config
|
||||
* ST STM32H735g discovery board config
|
||||
* ST STM32H743zi Nucleo board config
|
||||
* ST STM32H745i discovery board config
|
||||
* ST STM32H747i discovery board config
|
||||
* ST STM32H750b discovery board config
|
||||
* ST STM32H7b3i discovery board config
|
||||
* ST STM32H7x_dual_qspi board config
|
||||
* ST STM32H7x3i Eval boards config
|
||||
* ST STM32L073 Nucleo board config
|
||||
* ST STM32L476g discovery board config
|
||||
* ST STM32L496g discovery board config
|
||||
* ST STM32L4p5g discovery board config
|
||||
* ST STM32L4r9i discovery board config
|
||||
* ST STM32L5 Nucleo board config
|
||||
* ST STM32MP15x DK2 board config
|
||||
* ST STM32WB Nucleo board config
|
||||
* ST STM8L152R8 Nucleo board config
|
||||
* Synopsys DesignWare ARC EM board config
|
||||
* Synopsys DesignWare ARC HSDK board config
|
||||
* TI BeagleBone family boards config
|
||||
* TI CC13xx, CC26xx, CC32xx LaunchPad board config
|
||||
* TI MSP432 LaunchPad board config
|
||||
* Tocoding Poplar board config
|
||||
* TP-Link WDR4300 board config
|
||||
* Allwinner V3s target config
|
||||
* Andes Technology NDS V5 target config
|
||||
* Atmel atmega128rfa1 target config
|
||||
* ARM corelink SSE-200 target config
|
||||
* Atheros_ar9344 target config
|
||||
* Cypress PSoC5LP, PSoC6 target config
|
||||
* EnSilica eSi-RISC target config
|
||||
* Foshan Synwit Tech SWM050 target config
|
||||
* GigaDevice GD32VF103 target config
|
||||
* Hisilicon Hi3798 target config
|
||||
* Hisilicon Hi6220 target config
|
||||
* Infineon TLE987x target config
|
||||
* Marvell Armada 3700 target config
|
||||
* Maxim Integrated MAX32XXX target config
|
||||
* Mellanox BlueField target config
|
||||
* Microchip (Atmel) SAME5x, SAML1x target config
|
||||
* NXP IMX6SX, IMX6UL, IMX7, IMX7ULP, IMX8 target config
|
||||
* NXP Kinetis KE1xZ, KE1xF target config
|
||||
* NXP LPC84x, LPC8Nxx, LS1012A, NHS31xx target config
|
||||
* Qualcomm QCA4531 target config
|
||||
* QuickLogic EOS S3 target config
|
||||
* Renesas R-Car E2, H2, M2 target config
|
||||
* Renesas R-Car Gen3 target config
|
||||
* Renesas RZ/A1H target config
|
||||
* Rockchip RK3308 target config
|
||||
* ST BlueNRG target config
|
||||
* ST STM32G0, STM32G4, STM32H7, STM32L0, STM32L5 target config
|
||||
* ST STM32MP15x target config
|
||||
* ST STM32WBx, STM32WLEx target config
|
||||
* ST STM8L152, S003, S103, S105 target config
|
||||
* Synopsys DesignWare ARC EM target config
|
||||
* Synopsys DesignWare ARC HS Development Kit SoC target config
|
||||
* TI CC13xx, CC26xx, CC32xx target config
|
||||
* TI TNETC4401 target config
|
||||
* Xilinx UltraScale+ target config
|
||||
* Altera 5M570Z (MAXV family) CPLD config
|
||||
* Xilinx Ultrascale, XCF CPLD config
|
||||
* Intel (Altera) Arria10 FPGA config
|
||||
* Cadence SystemVerilog Direct Programming Interface (DPI) interface config
|
||||
* Cypress KitProg interface config
|
||||
* Digilent SMT2 NC interface config
|
||||
* DLN-2 example of Linux GPIOD interface config
|
||||
* FTDI C232HM interface config
|
||||
* HIE JTAG Debugger interface config
|
||||
* In-Circuit's ICprog interface config
|
||||
* isodebug isolated JTAG/SWD+UART interface config
|
||||
* Mellanox rshim USB or PCIe interface config
|
||||
* Nuvoton Nu-Link interface config
|
||||
* NXP IMX GPIO mmap based interface config
|
||||
* Steppenprobe open hardware interface config
|
||||
* TI XDS110 interface config
|
||||
|
||||
Server Layer:
|
||||
* 64 bit address support
|
||||
* default bind to IPv4 localhost
|
||||
* gdb: allow multiple connections
|
||||
* gdb: architecture element support
|
||||
* gdb: vCont, vRun support
|
||||
* telnet: handle Ctrl+A, Ctrl+E and Ctrl+K
|
||||
|
||||
RTOS:
|
||||
* Chromium-EC rtos support
|
||||
* hwthread pseudo rtos support
|
||||
* NuttX rtos support
|
||||
* RIOT rtos support
|
||||
|
||||
Documentation:
|
||||
* Improve STM32 flash driver
|
||||
* Various typo fix and improvements
|
||||
|
||||
Build and Release:
|
||||
* Add libutil to support jimtcl version 0.80
|
||||
* Clang warning fixes
|
||||
* GitHub workflow for Win32 snapshot binaries
|
||||
* Handle Tcl return values consistently
|
||||
* Mitigation for CVE-2018-5704: Prevent some forms of Cross
|
||||
Protocol Scripting attacks
|
||||
* Support for libftdi 1.5
|
||||
* Travis-CI basic support
|
||||
* Update libjaylink to version 0.2.0
|
||||
* Update jimtcl to version 0.79
|
||||
* Use external (optional) library capstone for ARM and AARCH64 disassembly
|
||||
|
||||
|
||||
This release also contains a number of other important functional and
|
||||
cosmetic bugfixes. For more details about what has changed since the
|
||||
last release, see the git repository history:
|
||||
|
||||
http://sourceforge.net/p/openocd/code/ci/v0.11.0-rc2/log/?path=
|
||||
http://sourceforge.net/p/openocd/code/ci/v0.x.0/log/?path=
|
||||
|
||||
|
||||
For older NEWS, see the NEWS files associated with each release
|
||||
|
|
|
@ -0,0 +1,238 @@
|
|||
This file includes highlights of the changes made in the OpenOCD
|
||||
source archive release.
|
||||
|
||||
JTAG Layer:
|
||||
* add debug level 4 for verbose I/O debug
|
||||
* bitbang, add read buffer to improve performance
|
||||
* Cadence SystemVerilog Direct Programming Interface (DPI) adapter driver
|
||||
* CMSIS-DAP v2 (USB bulk based) adapter driver
|
||||
* Cypress KitProg adapter driver
|
||||
* FTDI FT232R sync bitbang adapter driver
|
||||
* Linux GPIOD bitbang adapter driver through libgpiod
|
||||
* Mellanox rshim USB or PCIe adapter driver
|
||||
* Nuvoton Nu-Link and Nu-Link2 adapter drivers
|
||||
* NXP IMX GPIO mmap based adapter driver
|
||||
* ST-Link consolidate all versions in single config
|
||||
* ST-Link read properly old USB serial numbers
|
||||
* STLink/V3 support (for ST devices only !)
|
||||
* STM8 SWIM transport
|
||||
* TI XDS110 adapter driver
|
||||
* Xilinx XVC/PCIe adapter driver
|
||||
|
||||
Boundary Scan:
|
||||
|
||||
Target Layer:
|
||||
* 64 bit address support
|
||||
* ARCv2 target support
|
||||
* ARM Cortex-A hypervisor mode support
|
||||
* ARM Cortex-M fast PC sampling support for profiling
|
||||
* ARM generic CTI support
|
||||
* ARM generic mem-ap target support
|
||||
* ARMv7-A MMU tools
|
||||
* ARMv7m traces add TCP stream server
|
||||
* ARMv8 AARCH64 target support and semihosting support
|
||||
* ARMv8 AARCH64 disassembler support through capstone library
|
||||
* ARMv8-M target support
|
||||
* EnSilica eSi-RISC target support, including instruction tracing
|
||||
eSi-Trace support
|
||||
* MIPS64 target support
|
||||
* Motorola SREC S6 record image file support
|
||||
* RISC-V target support
|
||||
* SEGGER Real Time Transfer (RTT) initial support (for single target,
|
||||
Cortex-M only)
|
||||
* ST STM8 target support
|
||||
* Various MIPS32 target improvements
|
||||
|
||||
Flash Layer:
|
||||
* Atheros (ath79) SPI interface support
|
||||
* Atmel atmega128rfa1 support
|
||||
* Atmel SAM D21, D51, DA1, E51, E53, E54, G55, R30 support
|
||||
* Atmel SAMC2?N* support
|
||||
* Cypress PSoC5LP, PSoC6 support
|
||||
* EnSilica eSi-RISC support
|
||||
* Foshan Synwit Tech SWM050 support
|
||||
* Maxim Integrated MAX32XXX support
|
||||
* Nordic Semiconductor nRF51822, nRF52810, nRF52832 support
|
||||
* NXP Kinetis K27, K28, KE1x, KEAx, KL28, KL8x, KV5x, KWx support
|
||||
* Renesas RPC HF support
|
||||
* SH QSPI support
|
||||
* SiFive Freedom E support
|
||||
* Silicon Labs EFR-family, EZR32HG support
|
||||
* ST BlueNRG support
|
||||
* ST STM32 QUAD/OCTO-SPI interface support for Flash, FRAM and EEPROM
|
||||
* ST STM32F72x, STM32F4x3, STM32H7xx support
|
||||
* ST STM32G0xx, STM32G4xx, STM32L4x, STM32WB, STM32WL support
|
||||
* ST STM32L5x support (non secure mode)
|
||||
* TI CC13xx, CC26xx, CC32xx support
|
||||
* TI MSP432 support
|
||||
* Winner Micro w600 support
|
||||
* Xilinx XCF platform support
|
||||
* Various discrete SPI NOR flashes support
|
||||
|
||||
Board, Target, and Interface Configuration Scripts:
|
||||
* 8devices LIMA board config
|
||||
* Achilles Instant-Development Kit Arria 10 board config
|
||||
* Amazon Kindle 2 and DX board config
|
||||
* Analog Devices ADSP-SC58x, ADSP-SC584-EZBRD board config
|
||||
* Andes Technology ADP-XC7KFF676 board config
|
||||
* Andes Technology Corvette-F1 board config
|
||||
* ARM Musca A board config
|
||||
* Arty Spartan 7 FPGA board config
|
||||
* Atmel SAMD10 Xplained mini board config
|
||||
* Atmel SAMD11 Xplained Pro board config
|
||||
* Atmel SAM G55 Xplained Pro board config
|
||||
* AVNET UltraZED EG StarterKit board config
|
||||
* Blue Pill STM32F103C8 board config
|
||||
* DP Busblaster v4.1a board config
|
||||
* DPTechnics DPT-Board-v1 board config
|
||||
* Emcraft imx8 SOM BSB board config
|
||||
* Globalscale ESPRESSObin board config
|
||||
* Kasli board config
|
||||
* Kintex Ultrascale XCKU040 board config
|
||||
* Knovative KC-100 board config
|
||||
* LeMaker HiKey board config
|
||||
* Microchip (Atmel) SAME54 Xplained Pro board config
|
||||
* Microchip (Atmel) SAML11 Xplained Pro board config
|
||||
* Nordic module NRF52 board config
|
||||
* Numato Lab Mimas A7 board config
|
||||
* NXP Freedom FRDM-LS1012A board config
|
||||
* NXP IMX7SABRE board config
|
||||
* NXP IMX8MP-EVK board config
|
||||
* NXP MC-IMX8M-EVK board config
|
||||
* QuickLogic QuickFeather board config
|
||||
* Renesas R-Car E2, H2, M2 board config
|
||||
* Renesas R-Car Salvator-X(S) board config
|
||||
* Renesas RZ/A1H GR-Peach board config
|
||||
* Rigado BMD-300 board config
|
||||
* Sayma AMC board config
|
||||
* Sifive e31arty, e51arty, hifive1 board config
|
||||
* ST B-L475E-IOT01A board config
|
||||
* ST BlueNRG idb007v1, idb008v1, idb011v1 board config
|
||||
* ST STM32F412g discovery board config
|
||||
* ST STM32F413h discovery board config
|
||||
* ST STM32F469i discovery board config
|
||||
* ST STM32F7 Nucleo board config
|
||||
* ST STM32F723e discovery board config
|
||||
* ST STM32F746g discovery board config
|
||||
* ST STM32F769i discovery board config
|
||||
* ST STM32H735g discovery board config
|
||||
* ST STM32H743zi Nucleo board config
|
||||
* ST STM32H745i discovery board config
|
||||
* ST STM32H747i discovery board config
|
||||
* ST STM32H750b discovery board config
|
||||
* ST STM32H7b3i discovery board config
|
||||
* ST STM32H7x_dual_qspi board config
|
||||
* ST STM32H7x3i Eval boards config
|
||||
* ST STM32L073 Nucleo board config
|
||||
* ST STM32L476g discovery board config
|
||||
* ST STM32L496g discovery board config
|
||||
* ST STM32L4p5g discovery board config
|
||||
* ST STM32L4r9i discovery board config
|
||||
* ST STM32L5 Nucleo board config
|
||||
* ST STM32MP15x DK2 board config
|
||||
* ST STM32WB Nucleo board config
|
||||
* ST STM8L152R8 Nucleo board config
|
||||
* Synopsys DesignWare ARC EM board config
|
||||
* Synopsys DesignWare ARC HSDK board config
|
||||
* TI BeagleBone family boards config
|
||||
* TI CC13xx, CC26xx, CC32xx LaunchPad board config
|
||||
* TI MSP432 LaunchPad board config
|
||||
* Tocoding Poplar board config
|
||||
* TP-Link WDR4300 board config
|
||||
* Allwinner V3s target config
|
||||
* Andes Technology NDS V5 target config
|
||||
* Atmel atmega128rfa1 target config
|
||||
* ARM corelink SSE-200 target config
|
||||
* Atheros_ar9344 target config
|
||||
* Cypress PSoC5LP, PSoC6 target config
|
||||
* EnSilica eSi-RISC target config
|
||||
* Foshan Synwit Tech SWM050 target config
|
||||
* GigaDevice GD32VF103 target config
|
||||
* Hisilicon Hi3798 target config
|
||||
* Hisilicon Hi6220 target config
|
||||
* Infineon TLE987x target config
|
||||
* Marvell Armada 3700 target config
|
||||
* Maxim Integrated MAX32XXX target config
|
||||
* Mellanox BlueField target config
|
||||
* Microchip (Atmel) SAME5x, SAML1x target config
|
||||
* NXP IMX6SX, IMX6UL, IMX7, IMX7ULP, IMX8 target config
|
||||
* NXP Kinetis KE1xZ, KE1xF target config
|
||||
* NXP LPC84x, LPC8Nxx, LS1012A, NHS31xx target config
|
||||
* Qualcomm QCA4531 target config
|
||||
* QuickLogic EOS S3 target config
|
||||
* Renesas R-Car E2, H2, M2 target config
|
||||
* Renesas R-Car Gen3 target config
|
||||
* Renesas RZ/A1H target config
|
||||
* Rockchip RK3308 target config
|
||||
* ST BlueNRG target config
|
||||
* ST STM32G0, STM32G4, STM32H7, STM32L0, STM32L5 target config
|
||||
* ST STM32MP15x target config
|
||||
* ST STM32WBx, STM32WLEx target config
|
||||
* ST STM8L152, S003, S103, S105 target config
|
||||
* Synopsys DesignWare ARC EM target config
|
||||
* Synopsys DesignWare ARC HS Development Kit SoC target config
|
||||
* TI CC13xx, CC26xx, CC32xx target config
|
||||
* TI TNETC4401 target config
|
||||
* Xilinx UltraScale+ target config
|
||||
* Altera 5M570Z (MAXV family) CPLD config
|
||||
* Xilinx Ultrascale, XCF CPLD config
|
||||
* Intel (Altera) Arria10 FPGA config
|
||||
* Cadence SystemVerilog Direct Programming Interface (DPI) interface config
|
||||
* Cypress KitProg interface config
|
||||
* Digilent SMT2 NC interface config
|
||||
* DLN-2 example of Linux GPIOD interface config
|
||||
* FTDI C232HM interface config
|
||||
* HIE JTAG Debugger interface config
|
||||
* In-Circuit's ICprog interface config
|
||||
* isodebug isolated JTAG/SWD+UART interface config
|
||||
* Mellanox rshim USB or PCIe interface config
|
||||
* Nuvoton Nu-Link interface config
|
||||
* NXP IMX GPIO mmap based interface config
|
||||
* Steppenprobe open hardware interface config
|
||||
* TI XDS110 interface config
|
||||
|
||||
Server Layer:
|
||||
* 64 bit address support
|
||||
* default bind to IPv4 localhost
|
||||
* gdb: allow multiple connections
|
||||
* gdb: architecture element support
|
||||
* gdb: vCont, vRun support
|
||||
* telnet: handle Ctrl+A, Ctrl+E and Ctrl+K
|
||||
|
||||
RTOS:
|
||||
* Chromium-EC rtos support
|
||||
* hwthread pseudo rtos support
|
||||
* NuttX rtos support
|
||||
* RIOT rtos support
|
||||
|
||||
Documentation:
|
||||
* Improve STM32 flash driver
|
||||
* Various typo fix and improvements
|
||||
|
||||
Build and Release:
|
||||
* Add libutil to support jimtcl version 0.80
|
||||
* Clang warning fixes
|
||||
* GitHub workflow for Win32 snapshot binaries
|
||||
* Handle Tcl return values consistently
|
||||
* Mitigation for CVE-2018-5704: Prevent some forms of Cross
|
||||
Protocol Scripting attacks
|
||||
* Support for libftdi 1.5
|
||||
* Travis-CI basic support
|
||||
* Update libjaylink to version 0.2.0
|
||||
* Update jimtcl to version 0.79
|
||||
* Use external (optional) library capstone for ARM and AARCH64 disassembly
|
||||
|
||||
|
||||
This release also contains a number of other important functional and
|
||||
cosmetic bugfixes. For more details about what has changed since the
|
||||
last release, see the git repository history:
|
||||
|
||||
http://sourceforge.net/p/openocd/code/ci/v0.11.0/log/?path=
|
||||
|
||||
|
||||
For older NEWS, see the NEWS files associated with each release
|
||||
(i.e. NEWS-<version>).
|
||||
|
||||
For more information about contributing test reports, bug fixes, or new
|
||||
features and device support, please read the new Developer Manual (or
|
||||
the BUGS and PATCHES.txt files in the source archive).
|
5
README
5
README
|
@ -220,12 +220,11 @@ You'll also need:
|
|||
|
||||
Additionally, for building from git:
|
||||
|
||||
- autoconf >= 2.64
|
||||
- autoconf >= 2.69
|
||||
- automake >= 1.14
|
||||
- texinfo >= 5.0
|
||||
|
||||
USB-based adapters depend on libusb-1.0 and some older drivers require
|
||||
libusb-0.1 or libusb-compat-0.1. A compatible implementation, such as
|
||||
USB-based adapters depend on libusb-1.0. A compatible implementation, such as
|
||||
FreeBSD's, additionally needs the corresponding .pc files.
|
||||
|
||||
USB-Blaster, ASIX Presto and OpenJTAG interface adapter
|
||||
|
|
|
@ -40,10 +40,6 @@ WinUSB.sys to the composite parent instead of the specific
|
|||
interface. To do that one needs to activate an advanced option in the
|
||||
Zadig installer.
|
||||
|
||||
For the old drivers that use libusb-0.1 API you might need to link
|
||||
against libusb-win32 headers and install the corresponding driver with
|
||||
Zadig.
|
||||
|
||||
If you need to use the same adapter with other applications that may
|
||||
require another driver, a solution for Windows Vista and above is to
|
||||
activate the IgnoreHWSerNum registry setting for the USB device.
|
||||
|
|
|
@ -27,14 +27,14 @@ With Homebrew you can either run:
|
|||
brew install [--HEAD] openocd (where optional --HEAD asks brew to
|
||||
install the current git version)
|
||||
or
|
||||
brew install libtool automake libusb [libusb-compat] [hidapi] [libftdi]
|
||||
brew install libtool automake libusb [hidapi] [libftdi]
|
||||
(to install the needed dependencies and then proceed with the
|
||||
manual building procedure)
|
||||
|
||||
|
||||
For building with MacPorts you need to run:
|
||||
sudo port install libtool automake autoconf pkgconfig \
|
||||
libusb [libusb-compat] [libftdi1]
|
||||
libusb [libftdi1]
|
||||
|
||||
You should also specify LDFLAGS and CPPFLAGS to allow configure to use
|
||||
MacPorts' libraries, so run configure like this:
|
||||
|
|
126
configure.ac
126
configure.ac
|
@ -1,5 +1,5 @@
|
|||
AC_PREREQ(2.64)
|
||||
AC_INIT([openocd], [0.11.0-rc2+dev],
|
||||
AC_PREREQ([2.69])
|
||||
AC_INIT([openocd], [0.11.0+dev],
|
||||
[OpenOCD Mailing List <openocd-devel@lists.sourceforge.net>])
|
||||
AC_CONFIG_SRCDIR([src/openocd.c])
|
||||
AC_CONFIG_AUX_DIR([.])
|
||||
|
@ -121,12 +121,10 @@ m4_define([USB1_ADAPTERS],
|
|||
[[cmsis_dap_v2], [CMSIS-DAP v2 Compliant Debugger], [CMSIS_DAP_USB]],
|
||||
[[osbdm], [OSBDM (JTAG only) Programmer], [OSBDM]],
|
||||
[[opendous], [eStick/opendous JTAG Programmer], [OPENDOUS]],
|
||||
[[aice], [Andes JTAG Programmer], [AICE]]])
|
||||
|
||||
m4_define([USB0_ADAPTERS],
|
||||
[[[usbprog], [USBProg JTAG Programmer], [USBPROG]],
|
||||
[[armjtagew], [Olimex ARM-JTAG-EW Programmer], [ARMJTAGEW]],
|
||||
[[rlink], [Raisonance RLink JTAG Programmer], [RLINK]],
|
||||
[[armjtagew], [Olimex ARM-JTAG-EW Programmer], [ARMJTAGEW]]])
|
||||
[[usbprog], [USBProg JTAG Programmer], [USBPROG]],
|
||||
[[aice], [Andes JTAG Programmer], [AICE]]])
|
||||
|
||||
m4_define([HIDAPI_ADAPTERS],
|
||||
[[[cmsis_dap], [CMSIS-DAP Compliant Debugger], [CMSIS_DAP_HID]],
|
||||
|
@ -247,7 +245,6 @@ m4_define([AC_ARG_ADAPTERS], [
|
|||
|
||||
AC_ARG_ADAPTERS([
|
||||
USB1_ADAPTERS,
|
||||
USB0_ADAPTERS,
|
||||
HIDAPI_ADAPTERS,
|
||||
HIDAPI_USB1_ADAPTERS,
|
||||
LIBFTDI_ADAPTERS,
|
||||
|
@ -282,18 +279,6 @@ AC_ARG_ENABLE([amtjtagaccel],
|
|||
AS_HELP_STRING([--enable-amtjtagaccel], [Enable building the Amontec JTAG-Accelerator driver]),
|
||||
[build_amtjtagaccel=$enableval], [build_amtjtagaccel=no])
|
||||
|
||||
AC_ARG_ENABLE([zy1000_master],
|
||||
AS_HELP_STRING([--enable-zy1000-master], [Use ZY1000 JTAG master registers]),
|
||||
[build_zy1000_master=$enableval], [build_zy1000_master=no])
|
||||
|
||||
AC_ARG_ENABLE([zy1000],
|
||||
AS_HELP_STRING([--enable-zy1000], [Enable ZY1000 interface]),
|
||||
[build_zy1000=$enableval], [build_zy1000=no])
|
||||
|
||||
AC_ARG_ENABLE([ioutil],
|
||||
AS_HELP_STRING([--enable-ioutil], [Enable ioutil functions - useful for standalone OpenOCD implementations]),
|
||||
[build_ioutil=$enableval], [build_ioutil=no])
|
||||
|
||||
AS_CASE(["${host_cpu}"],
|
||||
[arm*|aarch64], [
|
||||
AC_ARG_ENABLE([bcm2835gpio],
|
||||
|
@ -327,11 +312,6 @@ AC_ARG_ENABLE([gw16012],
|
|||
AS_HELP_STRING([--enable-gw16012], [Enable building support for the Gateworks GW16012 JTAG Programmer]),
|
||||
[build_gw16012=$enableval], [build_gw16012=no])
|
||||
|
||||
AC_ARG_ENABLE([oocd_trace],
|
||||
AS_HELP_STRING([--enable-oocd_trace],
|
||||
[Enable building support for some prototype OpenOCD+trace ETM capture hardware]),
|
||||
[build_oocd_trace=$enableval], [build_oocd_trace=no])
|
||||
|
||||
AC_ARG_ENABLE([buspirate],
|
||||
AS_HELP_STRING([--enable-buspirate], [Enable building support for the Buspirate]),
|
||||
[build_buspirate=$enableval], [build_buspirate=no])
|
||||
|
@ -367,10 +347,6 @@ AS_CASE([$host_os],
|
|||
])
|
||||
])
|
||||
|
||||
AC_ARG_ENABLE([minidriver_dummy],
|
||||
AS_HELP_STRING([--enable-minidriver-dummy], [Enable the dummy minidriver.]),
|
||||
[build_minidriver_dummy=$enableval], [build_minidriver_dummy=no])
|
||||
|
||||
AC_ARG_ENABLE([internal-jimtcl],
|
||||
AS_HELP_STRING([--disable-internal-jimtcl], [Disable building internal jimtcl]),
|
||||
[use_internal_jimtcl=$enableval], [use_internal_jimtcl=yes])
|
||||
|
@ -380,43 +356,10 @@ AC_ARG_ENABLE([internal-libjaylink],
|
|||
[Disable building internal libjaylink]),
|
||||
[use_internal_libjaylink=$enableval], [use_internal_libjaylink=yes])
|
||||
|
||||
build_minidriver=no
|
||||
AC_MSG_CHECKING([whether to enable ZY1000 minidriver])
|
||||
AS_IF([test "x$build_zy1000" = "xyes"], [
|
||||
AS_IF([test "x$build_minidriver" = "xyes"], [
|
||||
AC_MSG_ERROR([Multiple minidriver options have been enabled.])
|
||||
])
|
||||
AC_DEFINE([HAVE_JTAG_MINIDRIVER_H], [1],
|
||||
[Define to 1 if you have the <jtag_minidriver.h> header file.])
|
||||
build_minidriver=yes
|
||||
])
|
||||
AC_MSG_RESULT([$build_zy1000])
|
||||
|
||||
AC_ARG_ENABLE([remote-bitbang],
|
||||
AS_HELP_STRING([--enable-remote-bitbang], [Enable building support for the Remote Bitbang jtag driver]),
|
||||
[build_remote_bitbang=$enableval], [build_remote_bitbang=yes])
|
||||
|
||||
AC_MSG_CHECKING([whether to enable dummy minidriver])
|
||||
AS_IF([test "x$build_minidriver_dummy" = "xyes"], [
|
||||
AS_IF([test "x$build_minidriver" = "xyes"], [
|
||||
AC_MSG_ERROR([Multiple minidriver options have been enabled.])
|
||||
])
|
||||
build_minidriver=yes
|
||||
AC_DEFINE([BUILD_MINIDRIVER_DUMMY], [1], [Use the dummy minidriver.])
|
||||
AC_DEFINE([HAVE_JTAG_MINIDRIVER_H], [1],
|
||||
[Define to 1 if you have the <jtag_minidriver.h> header file.])
|
||||
])
|
||||
AC_MSG_RESULT([$build_minidriver_dummy])
|
||||
|
||||
AC_MSG_CHECKING([whether standard drivers can be built])
|
||||
AS_IF([test "x$build_minidriver" = "xyes"], [
|
||||
AC_MSG_RESULT([no])
|
||||
AC_MSG_WARN([Using the minidriver disables all other drivers.])
|
||||
sleep 2
|
||||
], [
|
||||
AC_MSG_RESULT([yes])
|
||||
])
|
||||
|
||||
AS_CASE(["${host_cpu}"],
|
||||
[i?86|x86*], [],
|
||||
[
|
||||
|
@ -529,18 +472,6 @@ AS_IF([test "x$build_ep93xx" = "xyes"], [
|
|||
AC_DEFINE([BUILD_EP93XX], [0], [0 if you don't want ep93xx.])
|
||||
])
|
||||
|
||||
AS_IF([test "x$build_zy1000" = "xyes"], [
|
||||
AC_DEFINE([BUILD_ZY1000], [1], [1 if you want ZY1000.])
|
||||
], [
|
||||
AC_DEFINE([BUILD_ZY1000], [0], [0 if you don't want ZY1000.])
|
||||
])
|
||||
|
||||
AS_IF([test "x$build_zy1000_master" = "xyes"], [
|
||||
AC_DEFINE([BUILD_ZY1000_MASTER], [1], [1 if you want ZY1000 JTAG master registers.])
|
||||
], [
|
||||
AC_DEFINE([BUILD_ZY1000_MASTER], [0], [0 if you don't want ZY1000 JTAG master registers.])
|
||||
])
|
||||
|
||||
AS_IF([test "x$build_at91rm9200" = "xyes"], [
|
||||
build_bitbang=yes
|
||||
AC_DEFINE([BUILD_AT91RM9200], [1], [1 if you want at91rm9200.])
|
||||
|
@ -599,12 +530,6 @@ AS_IF([test "x$build_gw16012" = "xyes"], [
|
|||
AC_DEFINE([BUILD_GW16012], [0], [0 if you don't want the Gateworks GW16012 driver.])
|
||||
])
|
||||
|
||||
AS_IF([test "x$build_oocd_trace" = "xyes"], [
|
||||
AC_DEFINE([BUILD_OOCD_TRACE], [1], [1 if you want the OpenOCD+trace ETM capture driver.])
|
||||
], [
|
||||
AC_DEFINE([BUILD_OOCD_TRACE], [0], [0 if you don't want the OpenOCD+trace ETM capture driver.])
|
||||
])
|
||||
|
||||
AS_IF([test "x$build_buspirate" = "xyes"], [
|
||||
AC_DEFINE([BUILD_BUSPIRATE], [1], [1 if you want the Buspirate JTAG driver.])
|
||||
], [
|
||||
|
@ -655,8 +580,6 @@ PKG_CHECK_MODULES([LIBUSB1], [libusb-1.0], [
|
|||
AC_MSG_WARN([libusb-1.x not found, trying legacy libusb-0.1 as a fallback; consider installing libusb-1.x instead])
|
||||
])
|
||||
|
||||
PKG_CHECK_MODULES([LIBUSB0], [libusb], [use_libusb0=yes], [use_libusb0=no])
|
||||
|
||||
AC_ARG_WITH([capstone],
|
||||
AS_HELP_STRING([--with-capstone], [Use Capstone disassembly library (default=auto)])
|
||||
, [
|
||||
|
@ -701,9 +624,6 @@ PKG_CHECK_MODULES([LIBJAYLINK], [libjaylink >= 0.2],
|
|||
|
||||
m4_define([PROCESS_ADAPTERS], [
|
||||
m4_foreach([adapter], [$1], [
|
||||
AS_IF([test "x$build_zy1000" = "xyes"], [
|
||||
ADAPTER_VAR([adapter])=no
|
||||
])
|
||||
AS_IF([test $2], [
|
||||
AS_IF([test "x$ADAPTER_VAR([adapter])" != "xno"], [
|
||||
AC_DEFINE([BUILD_]ADAPTER_SYM([adapter]), [1], [1 if you want the ]ADAPTER_DESC([adapter]).)
|
||||
|
@ -721,7 +641,6 @@ m4_define([PROCESS_ADAPTERS], [
|
|||
])
|
||||
|
||||
PROCESS_ADAPTERS([USB1_ADAPTERS], ["x$use_libusb1" = "xyes"], [libusb-1.x])
|
||||
PROCESS_ADAPTERS([USB0_ADAPTERS], ["x$use_libusb0" = "xyes"], [libusb-0.1])
|
||||
PROCESS_ADAPTERS([HIDAPI_ADAPTERS], ["x$use_hidapi" = "xyes"], [hidapi])
|
||||
PROCESS_ADAPTERS([HIDAPI_USB1_ADAPTERS], ["x$use_hidapi" = "xyes" -a "x$use_libusb1" = "xyes"], [hidapi and libusb-1.x])
|
||||
PROCESS_ADAPTERS([LIBFTDI_ADAPTERS], ["x$use_libftdi" = "xyes"], [libftdi])
|
||||
|
@ -765,9 +684,6 @@ AM_CONDITIONAL([PARPORT], [test "x$build_parport" = "xyes"])
|
|||
AM_CONDITIONAL([DUMMY], [test "x$build_dummy" = "xyes"])
|
||||
AM_CONDITIONAL([GIVEIO], [test "x$parport_use_giveio" = "xyes"])
|
||||
AM_CONDITIONAL([EP93XX], [test "x$build_ep93xx" = "xyes"])
|
||||
AM_CONDITIONAL([ZY1000], [test "x$build_zy1000" = "xyes"])
|
||||
AM_CONDITIONAL([ZY1000_MASTER], [test "x$build_zy1000_master" = "xyes"])
|
||||
AM_CONDITIONAL([IOUTIL], [test "x$build_ioutil" = "xyes"])
|
||||
AM_CONDITIONAL([AT91RM9200], [test "x$build_at91rm9200" = "xyes"])
|
||||
AM_CONDITIONAL([BCM2835GPIO], [test "x$build_bcm2835gpio" = "xyes"])
|
||||
AM_CONDITIONAL([IMX_GPIO], [test "x$build_imx_gpio" = "xyes"])
|
||||
|
@ -777,12 +693,10 @@ AM_CONDITIONAL([JTAG_DPI], [test "x$build_jtag_dpi" = "xyes" -o "x$build_jtag_dp
|
|||
AM_CONDITIONAL([USB_BLASTER_DRIVER], [test "x$enable_usb_blaster" != "xno" -o "x$enable_usb_blaster_2" != "xno"])
|
||||
AM_CONDITIONAL([AMTJTAGACCEL], [test "x$build_amtjtagaccel" = "xyes"])
|
||||
AM_CONDITIONAL([GW16012], [test "x$build_gw16012" = "xyes"])
|
||||
AM_CONDITIONAL([OOCD_TRACE], [test "x$build_oocd_trace" = "xyes"])
|
||||
AM_CONDITIONAL([REMOTE_BITBANG], [test "x$build_remote_bitbang" = "xyes"])
|
||||
AM_CONDITIONAL([BUSPIRATE], [test "x$build_buspirate" = "xyes"])
|
||||
AM_CONDITIONAL([SYSFSGPIO], [test "x$build_sysfsgpio" = "xyes"])
|
||||
AM_CONDITIONAL([XLNX_PCIE_XVC], [test "x$build_xlnx_pcie_xvc" = "xyes"])
|
||||
AM_CONDITIONAL([USE_LIBUSB0], [test "x$use_libusb0" = "xyes"])
|
||||
AM_CONDITIONAL([USE_LIBUSB1], [test "x$use_libusb1" = "xyes"])
|
||||
AM_CONDITIONAL([IS_CYGWIN], [test "x$is_cygwin" = "xyes"])
|
||||
AM_CONDITIONAL([IS_MINGW], [test "x$is_mingw" = "xyes"])
|
||||
|
@ -796,9 +710,6 @@ AM_CONDITIONAL([USE_LIBJAYLINK], [test "x$use_libjaylink" = "xyes"])
|
|||
AM_CONDITIONAL([RSHIM], [test "x$build_rshim" = "xyes"])
|
||||
AM_CONDITIONAL([HAVE_CAPSTONE], [test "x$enable_capstone" != "xno"])
|
||||
|
||||
AM_CONDITIONAL([MINIDRIVER], [test "x$build_minidriver" = "xyes"])
|
||||
AM_CONDITIONAL([MINIDRIVER_DUMMY], [test "x$build_minidriver_dummy" = "xyes"])
|
||||
|
||||
AM_CONDITIONAL([INTERNAL_JIMTCL], [test "x$use_internal_jimtcl" = "xyes"])
|
||||
AM_CONDITIONAL([INTERNAL_LIBJAYLINK], [test "x$use_internal_libjaylink" = "xyes"])
|
||||
|
||||
|
@ -853,6 +764,8 @@ AS_IF([test "x$gcc_warnings" = "xyes"], [
|
|||
AC_SUBST([GCC_WARNINGS], [$GCC_WARNINGS])
|
||||
])
|
||||
|
||||
AC_SUBST(EXTRA_DIST_NEWS, ["$(echo $srcdir/NEWS-*)"])
|
||||
|
||||
AC_CONFIG_FILES([
|
||||
Makefile
|
||||
src/gnulib/Makefile
|
||||
|
@ -863,7 +776,7 @@ echo
|
|||
echo
|
||||
echo OpenOCD configuration summary
|
||||
echo --------------------------------------------------
|
||||
m4_foreach([adapter], [USB1_ADAPTERS, USB0_ADAPTERS,
|
||||
m4_foreach([adapter], [USB1_ADAPTERS,
|
||||
HIDAPI_ADAPTERS, HIDAPI_USB1_ADAPTERS, LIBFTDI_ADAPTERS,
|
||||
LIBFTDI_USB1_ADAPTERS,
|
||||
LIBGPIOD_ADAPTERS,
|
||||
|
@ -882,26 +795,3 @@ m4_foreach([adapter], [USB1_ADAPTERS, USB0_ADAPTERS,
|
|||
])
|
||||
])
|
||||
echo
|
||||
|
||||
AS_IF([test "x$build_oocd_trace" = "xyes"], [
|
||||
echo 'WARNING! Deprecated configure option (--enable-oocd_trace)'
|
||||
echo 'The oocd_trace driver is deprecated and will be removed in the next release.'
|
||||
echo 'If you regularly use this driver, please report to the OpenOCD Mailing List.'
|
||||
echo
|
||||
])
|
||||
|
||||
AS_IF([test "x$build_zy1000" = "xyes" -o "x$build_zy1000_master" = "xyes"], [
|
||||
echo 'WARNING! Deprecated configure option (--enable-zy1000, --enable-zy1000-master)'
|
||||
echo 'Support for the ZY1000 platform is deprecated and will be removed in the next'
|
||||
echo 'release. If you regularly use this platform, please report to the OpenOCD'
|
||||
echo 'Mailing List.'
|
||||
echo
|
||||
])
|
||||
|
||||
AS_IF([test "x$build_ioutil" = "xyes"], [
|
||||
echo 'WARNING! Deprecated configure option (--enable-ioutil)'
|
||||
echo 'Support for the ioutil functions is deprecated and will be removed in the next'
|
||||
echo 'release. If you regularly depend on this functionality, please report to the'
|
||||
echo 'OpenOCD Mailing List.'
|
||||
echo
|
||||
])
|
||||
|
|
|
@ -32,8 +32,19 @@ ATTRS{idVendor}=="0403", ATTRS{idProduct}=="8220", MODE="660", GROUP="plugdev",
|
|||
ATTRS{idVendor}=="0403", ATTRS{idProduct}=="8a98", MODE="660", GROUP="plugdev", TAG+="uaccess"
|
||||
ATTRS{idVendor}=="0403", ATTRS{idProduct}=="8a99", MODE="660", GROUP="plugdev", TAG+="uaccess"
|
||||
|
||||
# Marvell OpenRD JTAGKey FT2232D B
|
||||
ATTRS{idVendor}=="0403", ATTRS{idProduct}=="9e90", MODE="660", GROUP="plugdev", TAG+="uaccess"
|
||||
|
||||
# XDS100v2
|
||||
ATTRS{idVendor}=="0403", ATTRS{idProduct}=="a6d0", MODE="660", GROUP="plugdev", TAG+="uaccess"
|
||||
# XDS100v3
|
||||
ATTRS{idVendor}=="0403", ATTRS{idProduct}=="a6d1", MODE="660", GROUP="plugdev", TAG+="uaccess"
|
||||
|
||||
# OOCDLink
|
||||
ATTRS{idVendor}=="0403", ATTRS{idProduct}=="baf8", MODE="660", GROUP="plugdev", TAG+="uaccess"
|
||||
|
||||
# Kristech KT-Link
|
||||
ATTRS{idVendor}=="0403", ATTRS{idProduct}=="bbe2", MODE="660", GROUP="plugdev", TAG+="uaccess"
|
||||
|
||||
# Xverve Signalyzer Tool (DT-USB-ST), Signalyzer LITE (DT-USB-SLITE)
|
||||
ATTRS{idVendor}=="0403", ATTRS{idProduct}=="bca0", MODE="660", GROUP="plugdev", TAG+="uaccess"
|
||||
|
@ -90,6 +101,12 @@ ATTRS{idVendor}=="04b4", ATTRS{idProduct}=="f139", MODE="660", GROUP="plugdev",
|
|||
# Cypress KitProg in CMSIS-DAP mode
|
||||
ATTRS{idVendor}=="04b4", ATTRS{idProduct}=="f138", MODE="660", GROUP="plugdev", TAG+="uaccess"
|
||||
|
||||
# Infineon DAP miniWiggler v3
|
||||
ATTRS{idVendor}=="058b", ATTRS{idProduct}=="0043", MODE="660", GROUP="plugdev", TAG+="uaccess"
|
||||
|
||||
# Hitex LPC1768-Stick
|
||||
ATTRS{idVendor}=="0640", ATTRS{idProduct}=="0026", MODE="660", GROUP="plugdev", TAG+="uaccess"
|
||||
|
||||
# Hilscher NXHX Boards
|
||||
ATTRS{idVendor}=="0640", ATTRS{idProduct}=="0028", MODE="660", GROUP="plugdev", TAG+="uaccess"
|
||||
|
||||
|
@ -99,8 +116,14 @@ ATTRS{idVendor}=="0640", ATTRS{idProduct}=="002c", MODE="660", GROUP="plugdev",
|
|||
# Hitex STM32-PerformanceStick
|
||||
ATTRS{idVendor}=="0640", ATTRS{idProduct}=="002d", MODE="660", GROUP="plugdev", TAG+="uaccess"
|
||||
|
||||
# Hitex Cortino
|
||||
ATTRS{idVendor}=="0640", ATTRS{idProduct}=="0032", MODE="660", GROUP="plugdev", TAG+="uaccess"
|
||||
|
||||
# Altera USB Blaster
|
||||
ATTRS{idVendor}=="09fb", ATTRS{idProduct}=="6001", MODE="660", GROUP="plugdev", TAG+="uaccess"
|
||||
# Altera USB Blaster2
|
||||
ATTRS{idVendor}=="09fb", ATTRS{idProduct}=="6010", MODE="660", GROUP="plugdev", TAG+="uaccess"
|
||||
ATTRS{idVendor}=="09fb", ATTRS{idProduct}=="6810", MODE="660", GROUP="plugdev", TAG+="uaccess"
|
||||
|
||||
# Amontec JTAGkey-HiSpeed
|
||||
ATTRS{idVendor}=="0fbb", ATTRS{idProduct}=="1000", MODE="660", GROUP="plugdev", TAG+="uaccess"
|
||||
|
@ -146,6 +169,9 @@ ATTRS{idVendor}=="15ba", ATTRS{idProduct}=="002a", MODE="660", GROUP="plugdev",
|
|||
# Olimex ARM-USB-OCD-H
|
||||
ATTRS{idVendor}=="15ba", ATTRS{idProduct}=="002b", MODE="660", GROUP="plugdev", TAG+="uaccess"
|
||||
|
||||
# ixo-usb-jtag - Emulation of a Altera Bus Blaster I on a Cypress FX2 IC
|
||||
ATTRS{idVendor}=="16c0", ATTRS{idProduct}=="06ad", MODE="660", GROUP="plugdev", TAG+="uaccess"
|
||||
|
||||
# USBprog with OpenOCD firmware
|
||||
ATTRS{idVendor}=="1781", ATTRS{idProduct}=="0c63", MODE="660", GROUP="plugdev", TAG+="uaccess"
|
||||
|
||||
|
@ -160,6 +186,15 @@ ATTRS{idVendor}=="1cbe", ATTRS{idProduct}=="02a5", MODE="660", GROUP="plugdev",
|
|||
# TI Tiva-based ICDI and XDS110 probes in DFU mode
|
||||
ATTRS{idVendor}=="1cbe", ATTRS{idProduct}=="00ff", MODE="660", GROUP="plugdev", TAG+="uaccess"
|
||||
|
||||
# isodebug v1
|
||||
ATTRS{idVendor}=="22b7", ATTRS{idProduct}=="150d", MODE="660", GROUP="plugdev", TAG+="uaccess"
|
||||
|
||||
# PLS USB/JTAG Adapter for SPC5xxx
|
||||
ATTRS{idVendor}=="263d", ATTRS{idProduct}=="4001", MODE="660", GROUP="plugdev", TAG+="uaccess"
|
||||
|
||||
# Numato Mimas A7 - Artix 7 FPGA Board
|
||||
ATTRS{idVendor}=="2a19", ATTRS{idProduct}=="1009", MODE="660", GROUP="plugdev", TAG+="uaccess"
|
||||
|
||||
# Ambiq Micro EVK and Debug boards.
|
||||
ATTRS{idVendor}=="2aec", ATTRS{idProduct}=="6010", MODE="660", GROUP="plugdev", TAG+="uaccess"
|
||||
ATTRS{idVendor}=="2aec", ATTRS{idProduct}=="6011", MODE="660", GROUP="plugdev", TAG+="uaccess"
|
||||
|
|
|
@ -1,3 +1,8 @@
|
|||
/*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later
|
||||
* Copyright (C) 2009-2021 Free Software Foundation, Inc.
|
||||
*/
|
||||
|
||||
/* Copied from https://github.com/gcc-mirror/gcc/blob/master/libiberty/crc32.c
|
||||
* and then tweaked a little. */
|
||||
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
@c -*-texinfo-*-
|
||||
@node License
|
||||
@appendix The GNU Free Documentation License.
|
||||
@c The GNU Free Documentation License.
|
||||
@center Version 1.2, November 2002
|
||||
|
||||
@c This file is intended to be included within another document,
|
||||
|
@ -396,7 +395,7 @@ The Free Software Foundation may publish new, revised versions
|
|||
of the GNU Free Documentation 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. See
|
||||
@uref{http://www.gnu.org/copyleft/}.
|
||||
@uref{https://www.gnu.org/licenses/}.
|
||||
|
||||
Each version of the License is given a distinguishing version number.
|
||||
If the Document specifies that a particular numbered version of this
|
||||
|
@ -408,7 +407,8 @@ number of this License, you may choose any version ever published (not
|
|||
as a draft) by the Free Software Foundation.
|
||||
@end enumerate
|
||||
|
||||
@unnumberedsec ADDENDUM: How to use this License for your documents
|
||||
@page
|
||||
@heading ADDENDUM: How to use this License for your documents
|
||||
|
||||
To use this License in a document you have written, include a copy of
|
||||
the License in the document and put the following copyright and
|
||||
|
|
|
@ -36,7 +36,6 @@ asynchronous transactions.
|
|||
- declared in @c src/jtag/minidriver.h
|
||||
- used @a only by the core and minidriver implementations:
|
||||
- @c jtag_driver.c (in-tree OpenOCD drivers)
|
||||
- @c zy1000/build/include/jtag_minidriver.h (ZY1000 minidriver)
|
||||
- future implementations (on other embedded hosts)
|
||||
- interface device drivers do @b not need this API.
|
||||
|
||||
|
|
|
@ -114,9 +114,9 @@ pthreads require modest and predictable stack usage.
|
|||
|
||||
- static inline functions should be preferred over macros:
|
||||
@code
|
||||
/** do NOT define macro-like functions like this... */
|
||||
/* do NOT define macro-like functions like this... */
|
||||
#define CUBE(x) ((x) * (x) * (x))
|
||||
/** instead, define the same expression using a C99 inline function */
|
||||
/* instead, define the same expression using a C99 inline function */
|
||||
static inline int cube(int x) { return x * x * x; }
|
||||
@endcode
|
||||
- Functions should be declared static unless required by other modules
|
||||
|
@ -135,13 +135,13 @@ should write statements like the following:
|
|||
@code
|
||||
// separate statements should be preferred
|
||||
result = foo();
|
||||
if (ERROR_OK != result)
|
||||
if (result != ERROR_OK)
|
||||
...
|
||||
@endcode
|
||||
More directly, do @b not combine these kinds of statements:
|
||||
@code
|
||||
// Combined statements should be avoided
|
||||
if (ERROR_OK != (result = foo()))
|
||||
if ((result = foo()) != ERROR_OK)
|
||||
return result;
|
||||
@endcode
|
||||
|
||||
|
|
406
doc/openocd.texi
406
doc/openocd.texi
|
@ -298,7 +298,6 @@ The OpenOCD Bug Tracker is hosted on SourceForge:
|
|||
@cindex dongles
|
||||
@cindex FTDI
|
||||
@cindex wiggler
|
||||
@cindex zy1000
|
||||
@cindex printer port
|
||||
@cindex USB Adapter
|
||||
@cindex RTCK
|
||||
|
@ -307,12 +306,7 @@ Defined: @b{dongle}: A small device that plugs into a computer and serves as
|
|||
an adapter .... [snip]
|
||||
|
||||
In the OpenOCD case, this generally refers to @b{a small adapter} that
|
||||
attaches to your computer via USB or the parallel port. One
|
||||
exception is the Ultimate Solutions ZY1000, packaged as a small box you
|
||||
attach via an ethernet cable. The ZY1000 has the advantage that it does not
|
||||
require any drivers to be installed on the developer PC. It also has
|
||||
a built in web interface. It supports RTCK/RCLK or adaptive clocking
|
||||
and has a built-in relay to power cycle targets remotely.
|
||||
attaches to your computer via USB or the parallel port.
|
||||
|
||||
|
||||
@section Choosing a Dongle
|
||||
|
@ -334,26 +328,6 @@ Ethernet port needed?
|
|||
RTCK support (also known as ``adaptive clocking'')?
|
||||
@end enumerate
|
||||
|
||||
@section Stand-alone JTAG Probe
|
||||
|
||||
The ZY1000 from Ultimate Solutions is technically not a dongle but a
|
||||
stand-alone JTAG probe that, unlike most dongles, doesn't require any drivers
|
||||
running on the developer's host computer.
|
||||
Once installed on a network using DHCP or a static IP assignment, users can
|
||||
access the ZY1000 probe locally or remotely from any host with access to the
|
||||
IP address assigned to the probe.
|
||||
The ZY1000 provides an intuitive web interface with direct access to the
|
||||
OpenOCD debugger.
|
||||
Users may also run a GDBSERVER directly on the ZY1000 to take full advantage
|
||||
of GCC & GDB to debug any distribution of embedded Linux or NetBSD running on
|
||||
the target.
|
||||
The ZY1000 supports RTCK & RCLK or adaptive clocking and has a built-in relay
|
||||
to power cycle the target remotely.
|
||||
|
||||
For more information, visit:
|
||||
|
||||
@b{ZY1000} See: @url{http://www.ultsol.com/index.php/component/content/article/8/210-zylin-zy1000-main}
|
||||
|
||||
@section USB FT2232 Based
|
||||
|
||||
There are many USB JTAG dongles on the market, many of them based
|
||||
|
@ -2155,9 +2129,6 @@ disables the gdb server.
|
|||
When using "pipe", also use log_output to redirect the log
|
||||
output to a file so as not to flood the stdin/out pipes.
|
||||
|
||||
The -p/--pipe option is deprecated and a warning is printed
|
||||
as it is equivalent to passing in -c "gdb_port pipe; log_output openocd.log".
|
||||
|
||||
Any other string is interpreted as named pipe to listen to.
|
||||
Output pipe is the same name as input pipe, but with 'o' appended,
|
||||
e.g. /var/gdb, /var/gdbo.
|
||||
|
@ -3126,6 +3097,15 @@ Specifies the adapter layout to use.
|
|||
Pairs of vendor IDs and product IDs of the device.
|
||||
@end deffn
|
||||
|
||||
@deffn {Config Command} {hla_stlink_backend} (usb | tcp [port])
|
||||
@emph{ST-Link only:} Choose between 'exclusive' USB communication (the default backend) or
|
||||
'shared' mode using ST-Link TCP server (the default port is 7184).
|
||||
|
||||
@emph{Note:} ST-Link TCP server is a binary application provided by ST
|
||||
available from @url{https://www.st.com/en/development-tools/st-link-server.html,
|
||||
ST-LINK server software module}.
|
||||
@end deffn
|
||||
|
||||
@deffn {Command} {hla_command} command
|
||||
Execute a custom adapter-specific command. The @var{command} string is
|
||||
passed as is to the underlying adapter layout handler.
|
||||
|
@ -3146,6 +3126,17 @@ An error is returned for any AP number above the maximum allowed value.
|
|||
@emph{Note:} Either these same adapters and their older versions are
|
||||
also supported by @ref{hla_interface, the hla interface driver}.
|
||||
|
||||
@deffn {Config Command} {st-link backend} (usb | tcp [port])
|
||||
Choose between 'exclusive' USB communication (the default backend) or
|
||||
'shared' mode using ST-Link TCP server (the default port is 7184).
|
||||
|
||||
@emph{Note:} ST-Link TCP server is a binary application provided by ST
|
||||
available from @url{https://www.st.com/en/development-tools/st-link-server.html,
|
||||
ST-LINK server software module}.
|
||||
|
||||
@emph{Note:} ST-Link TCP server does not support the SWIM transport.
|
||||
@end deffn
|
||||
|
||||
@deffn {Config Command} {st-link serial} serial
|
||||
Specifies the serial number of the adapter.
|
||||
@end deffn
|
||||
|
@ -3205,20 +3196,6 @@ The string will be of the format "DDDD:BB:SS.F" such as "0000:65:00.1".
|
|||
@end deffn
|
||||
@end deffn
|
||||
|
||||
@deffn {Interface Driver} {ZY1000}
|
||||
This is the Zylin ZY1000 JTAG debugger.
|
||||
@end deffn
|
||||
|
||||
@quotation Note
|
||||
This defines some driver-specific commands,
|
||||
which are not currently documented here.
|
||||
@end quotation
|
||||
|
||||
@deffn Command power [@option{on}|@option{off}]
|
||||
Turn power switch to target on/off.
|
||||
No arguments: print status.
|
||||
@end deffn
|
||||
|
||||
@deffn {Interface Driver} {bcm2835gpio}
|
||||
This SoC is present in Raspberry Pi which is a cheap single-board computer
|
||||
exposing some GPIOs on its expansion header.
|
||||
|
@ -4532,7 +4509,13 @@ The current implementation supports eSi-32xx cores.
|
|||
@item @code{hla_target} -- a Cortex-M alternative to work with HL adapters like ST-Link.
|
||||
@item @code{ls1_sap} -- this is the SAP on NXP LS102x CPUs,
|
||||
allowing access to physical memory addresses independently of CPU cores.
|
||||
@item @code{mem_ap} -- this is an ARM debug infrastructure Access Port without a CPU, through which bus read and write cycles can be generated; it may be useful for working with non-CPU hardware behind an AP or during development of support for new CPUs.
|
||||
@item @code{mem_ap} -- this is an ARM debug infrastructure Access Port without
|
||||
a CPU, through which bus read and write cycles can be generated; it may be
|
||||
useful for working with non-CPU hardware behind an AP or during development of
|
||||
support for new CPUs.
|
||||
It's possible to connect a GDB client to this target (the GDB port has to be
|
||||
specified, @xref{gdbportoverride,,option -gdb-port}), and a fake ARM core will
|
||||
be emulated to comply to GDB remote protocol.
|
||||
@item @code{mips_m4k} -- a MIPS core.
|
||||
@item @code{mips_mips64} -- a MIPS64 core.
|
||||
@item @code{nds32_v2} -- this is an Andes NDS32 v2 core.
|
||||
|
@ -5035,6 +5018,19 @@ when reset disables PLLs needed to use a fast clock.
|
|||
@* After target hardware trace configuration was changed
|
||||
@end itemize
|
||||
|
||||
@quotation Note
|
||||
OpenOCD events are not supposed to be preempt by another event, but this
|
||||
is not enforced in current code. Only the target event @b{resumed} is
|
||||
executed with polling disabled; this avoids polling to trigger the event
|
||||
@b{halted}, reversing the logical order of execution of their handlers.
|
||||
Future versions of OpenOCD will prevent the event preemption and will
|
||||
disable the schedule of polling during the event execution. Do not rely
|
||||
on polling in any event handler; this means, don't expect the status of
|
||||
a core to change during the execution of the handler. The event handler
|
||||
will have to enable polling or use @command{$target_name arp_poll} to
|
||||
check if the core has changed status.
|
||||
@end quotation
|
||||
|
||||
@node Flash Commands
|
||||
@chapter Flash Commands
|
||||
|
||||
|
@ -7189,6 +7185,17 @@ the chip identification register, and autoconfigures itself.
|
|||
flash bank $_FLASHNAME stm32l4x 0 0 0 0 $_TARGETNAME
|
||||
@end example
|
||||
|
||||
If you use OTP (One-Time Programmable) memory define it as a second bank
|
||||
as per the following example.
|
||||
@example
|
||||
flash bank $_FLASHNAME stm32l4x 0x1FFF7000 0 0 0 $_TARGETNAME
|
||||
@end example
|
||||
|
||||
@deffn Command {stm32l4x otp} num (@option{enable}|@option{disable}|@option{show})
|
||||
Enables or disables OTP write commands for bank @var{num}.
|
||||
The @var{num} parameter is a value shown by @command{flash banks}.
|
||||
@end deffn
|
||||
|
||||
Note that some devices have been found that have a flash size register that contains
|
||||
an invalid value, to workaround this issue you can override the probed value used by
|
||||
the flash driver. However, specifying a wrong value might lead to a completely
|
||||
|
@ -7248,6 +7255,20 @@ Area A for bank 1. The above example set WRP1AR_END=255, WRP1AR_START=0.
|
|||
This will effectively write protect all sectors in flash bank 1.
|
||||
@end deffn
|
||||
|
||||
@deffn Command {stm32l4x wrp_info} num [device_bank]
|
||||
List the protected areas using WRP.
|
||||
The @var{num} parameter is a value shown by @command{flash banks}.
|
||||
@var{device_bank} parameter is optional, possible values 'bank1' or 'bank2',
|
||||
if not specified, the command will display the whole flash protected areas.
|
||||
|
||||
@b{Note:} @var{device_bank} is different from banks created using @code{flash bank}.
|
||||
Devices supported in this flash driver, can have main flash memory organized
|
||||
in single or dual-banks mode.
|
||||
Thus the usage of @var{device_bank} is meaningful only in dual-bank mode, to get
|
||||
write protected areas in a specific @var{device_bank}
|
||||
|
||||
@end deffn
|
||||
|
||||
@deffn Command {stm32l4x option_load} num
|
||||
Forces a re-load of the option byte registers. Will cause a system reset of the device.
|
||||
The @var{num} parameter is a value shown by @command{flash banks}.
|
||||
|
@ -8255,66 +8276,6 @@ with handlers for that event.
|
|||
@end quotation
|
||||
@end deffn
|
||||
|
||||
@section I/O Utilities
|
||||
|
||||
These commands are available when
|
||||
OpenOCD is built with @option{--enable-ioutil}.
|
||||
They are mainly useful on embedded targets,
|
||||
notably the ZY1000.
|
||||
Hosts with operating systems have complementary tools.
|
||||
|
||||
@emph{Note:} there are several more such commands.
|
||||
|
||||
@deffn Command append_file filename [string]*
|
||||
Appends the @var{string} parameters to
|
||||
the text file @file{filename}.
|
||||
Each string except the last one is followed by one space.
|
||||
The last string is followed by a newline.
|
||||
@end deffn
|
||||
|
||||
@deffn Command cat filename
|
||||
Reads and displays the text file @file{filename}.
|
||||
@end deffn
|
||||
|
||||
@deffn Command cp src_filename dest_filename
|
||||
Copies contents from the file @file{src_filename}
|
||||
into @file{dest_filename}.
|
||||
@end deffn
|
||||
|
||||
@deffn Command ip
|
||||
@emph{No description provided.}
|
||||
@end deffn
|
||||
|
||||
@deffn Command ls
|
||||
@emph{No description provided.}
|
||||
@end deffn
|
||||
|
||||
@deffn Command mac
|
||||
@emph{No description provided.}
|
||||
@end deffn
|
||||
|
||||
@deffn Command meminfo
|
||||
Display available RAM memory on OpenOCD host.
|
||||
Used in OpenOCD regression testing scripts.
|
||||
@end deffn
|
||||
|
||||
@deffn Command peek
|
||||
@emph{No description provided.}
|
||||
@end deffn
|
||||
|
||||
@deffn Command poke
|
||||
@emph{No description provided.}
|
||||
@end deffn
|
||||
|
||||
@deffn Command rm filename
|
||||
@c "rm" has both normal and Jim-level versions??
|
||||
Unlinks the file @file{filename}.
|
||||
@end deffn
|
||||
|
||||
@deffn Command trunc filename
|
||||
Removes all data in the file @file{filename}.
|
||||
@end deffn
|
||||
|
||||
@anchor{memoryaccess}
|
||||
@section Memory access commands
|
||||
@cindex memory access
|
||||
|
@ -8836,29 +8797,6 @@ how the event caused trouble.
|
|||
|
||||
@end deffn
|
||||
|
||||
@deffn {Trace Port Driver} oocd_trace
|
||||
This driver isn't available unless OpenOCD was explicitly configured
|
||||
with the @option{--enable-oocd_trace} option. You probably don't want
|
||||
to configure it unless you've built the appropriate prototype hardware;
|
||||
it's @emph{proof-of-concept} software.
|
||||
|
||||
Use the @option{oocd_trace} driver if you are configuring an ETM that's
|
||||
connected to an off-chip trace connector.
|
||||
|
||||
@deffn {Config Command} {oocd_trace config} target tty
|
||||
Associates the ETM for @var{target} with a trace driver which
|
||||
collects data through the serial port @var{tty}.
|
||||
@end deffn
|
||||
|
||||
@deffn Command {oocd_trace resync}
|
||||
Re-synchronizes with the capture clock.
|
||||
@end deffn
|
||||
|
||||
@deffn Command {oocd_trace status}
|
||||
Reports whether the capture clock is locked or not.
|
||||
@end deffn
|
||||
@end deffn
|
||||
|
||||
@anchor{armcrosstrigger}
|
||||
@section ARM Cross-Trigger Interface
|
||||
@cindex CTI
|
||||
|
@ -9081,23 +9019,6 @@ cables (FT2232), but might be unsafe if used with targets running at very low
|
|||
speeds, like the 32kHz startup clock of an AT91RM9200.
|
||||
@end deffn
|
||||
|
||||
@subsection ARM720T specific commands
|
||||
@cindex ARM720T
|
||||
|
||||
These commands are available to ARM720T based CPUs,
|
||||
which are implementations of the ARMv4T architecture
|
||||
based on the ARM7TDMI-S integer core.
|
||||
They are available in addition to the ARM and ARM7/ARM9 commands.
|
||||
|
||||
@deffn Command {arm720t cp15} opcode [value]
|
||||
@emph{DEPRECATED -- avoid using this.
|
||||
Use the @command{arm mrc} or @command{arm mcr} commands instead.}
|
||||
|
||||
Display cp15 register returned by the ARM instruction @var{opcode};
|
||||
else if a @var{value} is provided, that value is written to that register.
|
||||
The @var{opcode} should be the value of either an MRC or MCR instruction.
|
||||
@end deffn
|
||||
|
||||
@subsection ARM9 specific commands
|
||||
@cindex ARM9
|
||||
|
||||
|
@ -9151,18 +9072,6 @@ shown in bits 38..33 of table 9-9 in the ARM920T TRM.
|
|||
(Not all registers can be written.)
|
||||
@end deffn
|
||||
|
||||
@deffn Command {arm920t cp15i} opcode [value [address]]
|
||||
@emph{DEPRECATED -- avoid using this.
|
||||
Use the @command{arm mrc} or @command{arm mcr} commands instead.}
|
||||
|
||||
Interpreted access using ARM instruction @var{opcode}, which should
|
||||
be the value of either an MRC or MCR instruction
|
||||
(as shown tables 9-11, 9-12, and 9-13 in the ARM920T TRM).
|
||||
If no @var{value} is provided, the result is displayed.
|
||||
Else if that value is written using the specified @var{address},
|
||||
or using zero if no other address is provided.
|
||||
@end deffn
|
||||
|
||||
@deffn Command {arm920t read_cache} filename
|
||||
Dump the content of ICache and DCache to a file named @file{filename}.
|
||||
@end deffn
|
||||
|
@ -9470,61 +9379,146 @@ Selects whether interrupts will be processed when single stepping
|
|||
@end deffn
|
||||
|
||||
|
||||
@subsection ARMv7-M specific commands
|
||||
@subsection ARM CoreSight TPIU and SWO specific commands
|
||||
@cindex tracing
|
||||
@cindex SWO
|
||||
@cindex SWV
|
||||
@cindex TPIU
|
||||
@cindex ITM
|
||||
@cindex ETM
|
||||
|
||||
@deffn Command {tpiu config} (@option{disable} | ((@option{external} | @option{internal (@var{filename} | @var{:port} | -)}) @
|
||||
(@option{sync @var{port_width}} | ((@option{manchester} | @option{uart}) @var{formatter_enable})) @
|
||||
@var{TRACECLKIN_freq} [@var{trace_freq}]))
|
||||
|
||||
ARMv7-M architecture provides several modules to generate debugging
|
||||
ARM CoreSight provides several modules to generate debugging
|
||||
information internally (ITM, DWT and ETM). Their output is directed
|
||||
through TPIU to be captured externally either on an SWO pin (this
|
||||
through TPIU or SWO modules to be captured externally either on an SWO pin (this
|
||||
configuration is called SWV) or on a synchronous parallel trace port.
|
||||
|
||||
This command configures the TPIU module of the target and, if internal
|
||||
capture mode is selected, starts to capture trace output by using the
|
||||
debugger adapter features.
|
||||
ARM CoreSight provides independent HW blocks named TPIU and SWO each with its
|
||||
own functionality. Embedded in Cortex-M3 and M4, ARM provides an optional HW
|
||||
block that includes both TPIU and SWO functionalities and is again named TPIU,
|
||||
which causes quite some confusion.
|
||||
The registers map of all the TPIU and SWO implementations allows using a single
|
||||
driver that detects at runtime the features available.
|
||||
|
||||
Some targets require additional actions to be performed in the
|
||||
@b{trace-config} handler for trace port to be activated.
|
||||
The @command{tpiu} is used for either TPIU or SWO.
|
||||
A convenient alias @command{swo} is available to help distinguish, in scripts,
|
||||
the commands for SWO from the commands for TPIU.
|
||||
|
||||
Command options:
|
||||
@deffn Command {swo} ...
|
||||
Alias of @command{tpiu ...}. Can be used in scripts to distinguish the commands
|
||||
for SWO from the commands for TPIU.
|
||||
@end deffn
|
||||
|
||||
@deffn Command {tpiu create} tpiu_name configparams...
|
||||
Creates a TPIU or a SWO object. The two commands are equivalent.
|
||||
Add the object in a list and add new commands (@command{@var{tpiu_name}})
|
||||
which are used for various purposes including additional configuration.
|
||||
|
||||
@itemize @bullet
|
||||
@item @var{tpiu_name} -- the name of the TPIU or SWO object.
|
||||
This name is also used to create the object's command, referred to here
|
||||
as @command{$tpiu_name}, and in other places where the TPIU or SWO needs to be identified.
|
||||
@item @var{configparams} -- all parameters accepted by @command{$tpiu_name configure} are permitted.
|
||||
|
||||
You @emph{must} set here the AP and MEM_AP base_address through @code{-dap @var{dap_name}},
|
||||
@code{-ap-num @var{ap_number}} and @code{-baseaddr @var{base_address}}.
|
||||
@end itemize
|
||||
@end deffn
|
||||
|
||||
@deffn Command {tpiu names}
|
||||
Lists all the TPIU or SWO objects created so far. The two commands are equivalent.
|
||||
@end deffn
|
||||
|
||||
@deffn Command {tpiu init}
|
||||
Initialize all registered TPIU and SWO. The two commands are equivalent.
|
||||
These commands are used internally during initialization. They can be issued
|
||||
at any time after the initialization, too.
|
||||
@end deffn
|
||||
|
||||
@deffn Command {$tpiu_name cget} queryparm
|
||||
Each configuration parameter accepted by @command{$tpiu_name configure} can be
|
||||
individually queried, to return its current value.
|
||||
The @var{queryparm} is a parameter name accepted by that command, such as @code{-dap}.
|
||||
@end deffn
|
||||
|
||||
@deffn Command {$tpiu_name configure} configparams...
|
||||
The options accepted by this command may also be specified as parameters
|
||||
to @command{tpiu create}. Their values can later be queried one at a time by
|
||||
using the @command{$tpiu_name cget} command.
|
||||
|
||||
@itemize @bullet
|
||||
@item @code{-dap} @var{dap_name} -- names the DAP used to access this
|
||||
TPIU. @xref{dapdeclaration,,DAP declaration}, on how to create and manage DAP instances.
|
||||
|
||||
@item @code{-ap-num} @var{ap_number} -- sets DAP access port for TPIU,
|
||||
@var{ap_number} is the numeric index of the DAP AP the TPIU is connected to.
|
||||
|
||||
@item @code{-baseaddr} @var{base_address} -- sets the TPIU @var{base_address} where
|
||||
to access the TPIU in the DAP AP memory space.
|
||||
|
||||
@item @code{-protocol} (@option{sync}|@option{uart}|@option{manchester}) -- sets the
|
||||
protocol used for trace data:
|
||||
@itemize @minus
|
||||
@item @option{disable} disable TPIU handling;
|
||||
@item @option{external} configure TPIU to let user capture trace
|
||||
output externally (with an additional UART or logic analyzer hardware).
|
||||
@item @option{internal (@var{filename} | @var{:port} | -)} configure TPIU and debug adapter to
|
||||
gather trace data then:
|
||||
|
||||
@itemize @minus
|
||||
@item append it to a regular file or a named pipe if @var{filename} is specified.
|
||||
@item listen to a TCP/IP port if @var{:port} is specified, then broadcast the trace data over this port.
|
||||
@item if '-' is specified, OpenOCD will forward trace data to @command{tcl_trace} command.
|
||||
@*@b{Note:} while broadcasting to file or TCP, the forwarding to @command{tcl_trace} will remain active.
|
||||
@item @option{sync} -- synchronous parallel trace output mode, using @var{port_width}
|
||||
data bits (default);
|
||||
@item @option{uart} -- use asynchronous SWO mode with NRZ (same as regular UART 8N1) coding;
|
||||
@item @option{manchester} -- use asynchronous SWO mode with Manchester coding.
|
||||
@end itemize
|
||||
|
||||
@item @option{sync @var{port_width}} use synchronous parallel trace output
|
||||
mode, and set port width to @var{port_width}.
|
||||
@item @option{manchester} use asynchronous SWO mode with Manchester
|
||||
coding.
|
||||
@item @option{uart} use asynchronous SWO mode with NRZ (same as
|
||||
regular UART 8N1) coding.
|
||||
@item @var{formatter_enable} is @option{on} or @option{off} to enable
|
||||
or disable TPIU formatter which needs to be used when both ITM and ETM
|
||||
data is to be output via SWO.
|
||||
@item @var{TRACECLKIN_freq} this should be specified to match target's
|
||||
current TRACECLKIN frequency (usually the same as HCLK).
|
||||
@item @var{trace_freq} trace port frequency. Can be omitted in
|
||||
internal mode to let the adapter driver select the maximum supported
|
||||
rate automatically.
|
||||
@item @code{-event} @var{event_name} @var{event_body} -- assigns an event handler,
|
||||
a TCL string which is evaluated when the event is triggered. The events
|
||||
@code{pre-enable}, @code{post-enable}, @code{pre-disable} and @code{post-disable}
|
||||
are defined for TPIU/SWO.
|
||||
A typical use case for the event @code{pre-enable} is to enable the trace clock
|
||||
of the TPIU.
|
||||
|
||||
@item @code{-output} (@option{external}|@option{:}@var{port}|@var{filename}|@option{-}) -- specifies
|
||||
the destination of the trace data:
|
||||
@itemize @minus
|
||||
@item @option{external} -- configure TPIU/SWO to let user capture trace
|
||||
output externally, either with an additional UART or with a logic analyzer (default);
|
||||
@item @option{-} -- configure TPIU/SWO and debug adapter to gather trace data
|
||||
and forward it to @command{tcl_trace} command;
|
||||
@item @option{:}@var{port} -- configure TPIU/SWO and debug adapter to gather
|
||||
trace data, open a TCP server at port @var{port} and send the trace data to
|
||||
each connected client;
|
||||
@item @var{filename} -- configure TPIU/SWO and debug adapter to
|
||||
gather trace data and append it to @var{filename}, which can be
|
||||
either a regular file or a named pipe.
|
||||
@end itemize
|
||||
|
||||
@item @code{-traceclk} @var{TRACECLKIN_freq} -- mandatory parameter.
|
||||
Specifies the frequency in Hz of the trace clock. For the TPIU embedded in
|
||||
Cortex-M3 or M4, this is usually the same frequency as HCLK. For protocol
|
||||
@option{sync} this is twice the frequency of the pin data rate.
|
||||
|
||||
@item @code{-pin-freq} @var{trace_freq} -- specifies the expected data rate
|
||||
in Hz of the SWO pin. Parameter used only on protocols @option{uart} and
|
||||
@option{manchester}. Can be omitted to let the adapter driver select the
|
||||
maximum supported rate automatically.
|
||||
|
||||
@item @code{-port-width} @var{port_width} -- sets to @var{port_width} the width
|
||||
of the synchronous parallel port used for trace output. Parameter used only on
|
||||
protocol @option{sync}. If not specified, default value is @var{1}.
|
||||
|
||||
@item @code{-formatter} (@option{0}|@option{1}) -- specifies if the formatter
|
||||
should be enabled. Parameter used only on protocol @option{sync}. If not specified,
|
||||
default value is @var{0}.
|
||||
@end itemize
|
||||
@end deffn
|
||||
|
||||
@deffn Command {$tpiu_name enable}
|
||||
Uses the parameters specified by the previous @command{$tpiu_name configure}
|
||||
to configure and enable the TPIU or the SWO.
|
||||
If required, the adapter is also configured and enabled to receive the trace
|
||||
data.
|
||||
This command can be used before @command{init}, but it will take effect only
|
||||
after the @command{init}.
|
||||
@end deffn
|
||||
|
||||
@deffn Command {$tpiu_name disable}
|
||||
Disable the TPIU or the SWO, terminating the receiving of the trace data.
|
||||
@end deffn
|
||||
|
||||
|
||||
|
||||
Example usage:
|
||||
@enumerate
|
||||
@item STM32L152 board is programmed with an application that configures
|
||||
|
@ -9552,12 +9546,20 @@ baud with our custom divisor to get 12MHz)
|
|||
@item OpenOCD invocation line:
|
||||
@example
|
||||
openocd -f interface/stlink.cfg \
|
||||
-c "transport select hla_swd" \
|
||||
-f target/stm32l1.cfg \
|
||||
-c "tpiu config external uart off 24000000 12000000"
|
||||
-c "transport select hla_swd" \
|
||||
-f target/stm32l1.cfg \
|
||||
-c "stm32l1.tpiu configure -protocol uart" \
|
||||
-c "stm32l1.tpiu configure -traceclk 24000000 -pin-freq 12000000" \
|
||||
-c "stm32l1.tpiu enable"
|
||||
@end example
|
||||
@end enumerate
|
||||
@end deffn
|
||||
|
||||
@subsection ARMv7-M specific commands
|
||||
@cindex tracing
|
||||
@cindex SWO
|
||||
@cindex SWV
|
||||
@cindex ITM
|
||||
@cindex ETM
|
||||
|
||||
@deffn Command {itm port} @var{port} (@option{0}|@option{1}|@option{on}|@option{off})
|
||||
Enable or disable trace output for ITM stimulus @var{port} (counting
|
||||
|
@ -11932,6 +11934,8 @@ foreach who @{A B C D E@}
|
|||
@}
|
||||
@end example
|
||||
|
||||
@node License
|
||||
@appendix The GNU Free Documentation License.
|
||||
@include fdl.texi
|
||||
|
||||
@node OpenOCD Concept Index
|
||||
|
|
|
@ -69,6 +69,7 @@ BUILT_SOURCES += %D%/startup_tcl.inc
|
|||
|
||||
# Convert .tcl to c-array
|
||||
%D%/startup_tcl.inc: $(STARTUP_TCL_SRCS)
|
||||
mkdir -p %D%
|
||||
cat $^ | $(BIN2C) > $@ || { rm -f $@; false; }
|
||||
|
||||
# add generated files to make clean list
|
||||
|
|
|
@ -60,14 +60,14 @@ static const int lp_ooblayout[] = {
|
|||
58, 59, 60, 61, 62, 63
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
struct dmac_ll {
|
||||
volatile uint32_t dma_src;
|
||||
volatile uint32_t dma_dest;
|
||||
volatile uint32_t next_lli;
|
||||
volatile uint32_t next_ctrl;
|
||||
} dmac_ll_t;
|
||||
};
|
||||
|
||||
static dmac_ll_t dmalist[(2048/256) * 2 + 1];
|
||||
static struct dmac_ll dmalist[(2048/256) * 2 + 1];
|
||||
|
||||
/* nand device lpc32xx <target#> <oscillator_frequency>
|
||||
*/
|
||||
|
@ -867,14 +867,14 @@ static int lpc32xx_make_dma_list(uint32_t target_mem_base, uint32_t page_size,
|
|||
dmalist[i*2].dma_src = (do_read ? dmasrc : (dmasrc + i * 256));
|
||||
dmalist[i*2].dma_dest = (do_read ? (dmadst + i * 256) : dmadst);
|
||||
dmalist[i*2].next_lli =
|
||||
target_mem_base + (i*2 + 1) * sizeof(dmac_ll_t);
|
||||
target_mem_base + (i*2 + 1) * sizeof(struct dmac_ll);
|
||||
dmalist[i*2].next_ctrl = ctrl;
|
||||
|
||||
dmalist[(i*2) + 1].dma_src = 0x20020034;/* SLC_ECC */
|
||||
dmalist[(i*2) + 1].dma_dest =
|
||||
target_mem_base + ECC_OFFS + i * 4;
|
||||
dmalist[(i*2) + 1].next_lli =
|
||||
target_mem_base + (i*2 + 2) * sizeof(dmac_ll_t);
|
||||
target_mem_base + (i*2 + 2) * sizeof(struct dmac_ll);
|
||||
dmalist[(i*2) + 1].next_ctrl = ecc_ctrl;
|
||||
|
||||
}
|
||||
|
@ -1063,7 +1063,7 @@ static int lpc32xx_write_page_slc(struct nand_device *nand,
|
|||
XXX: Assumes host and target have same byte sex.
|
||||
*/
|
||||
retval = target_write_memory(target, target_mem_base, 4,
|
||||
nll * sizeof(dmac_ll_t) / 4,
|
||||
nll * sizeof(struct dmac_ll) / 4,
|
||||
(uint8_t *)dmalist);
|
||||
if (ERROR_OK != retval) {
|
||||
LOG_ERROR("Could not write DMA descriptors to IRAM");
|
||||
|
@ -1104,7 +1104,7 @@ static int lpc32xx_write_page_slc(struct nand_device *nand,
|
|||
|
||||
/* Write first descriptor to DMA controller */
|
||||
retval = target_write_memory(target, 0x31000100, 4,
|
||||
sizeof(dmac_ll_t) / 4,
|
||||
sizeof(struct dmac_ll) / 4,
|
||||
(uint8_t *)dmalist);
|
||||
if (ERROR_OK != retval) {
|
||||
LOG_ERROR("Could not write DMA descriptor to DMAC");
|
||||
|
@ -1161,7 +1161,7 @@ static int lpc32xx_write_page_slc(struct nand_device *nand,
|
|||
|
||||
/* Write OOB descriptor to DMA controller */
|
||||
retval = target_write_memory(target, 0x31000100, 4,
|
||||
sizeof(dmac_ll_t) / 4,
|
||||
sizeof(struct dmac_ll) / 4,
|
||||
(uint8_t *)(&dmalist[nll-1]));
|
||||
if (ERROR_OK != retval) {
|
||||
LOG_ERROR("Could not write OOB DMA descriptor to DMAC");
|
||||
|
@ -1460,7 +1460,7 @@ static int lpc32xx_read_page_slc(struct nand_device *nand,
|
|||
XXX: Assumes host and target have same byte sex.
|
||||
*/
|
||||
retval = target_write_memory(target, target_mem_base, 4,
|
||||
nll * sizeof(dmac_ll_t) / 4,
|
||||
nll * sizeof(struct dmac_ll) / 4,
|
||||
(uint8_t *)dmalist);
|
||||
if (ERROR_OK != retval) {
|
||||
LOG_ERROR("Could not write DMA descriptors to IRAM");
|
||||
|
@ -1489,7 +1489,7 @@ static int lpc32xx_read_page_slc(struct nand_device *nand,
|
|||
|
||||
/* Write first descriptor to DMA controller */
|
||||
retval = target_write_memory(target, 0x31000100, 4,
|
||||
sizeof(dmac_ll_t) / 4, (uint8_t *)dmalist);
|
||||
sizeof(struct dmac_ll) / 4, (uint8_t *)dmalist);
|
||||
if (ERROR_OK != retval) {
|
||||
LOG_ERROR("Could not write DMA descriptor to DMAC");
|
||||
return retval;
|
||||
|
|
|
@ -113,7 +113,7 @@ struct samd_part {
|
|||
};
|
||||
|
||||
/* See SAM D5x/E5x Family Silicon Errata and Data Sheet Clarification
|
||||
* DS80000748B */
|
||||
* DS80000748K */
|
||||
/* Known SAMD51 parts. */
|
||||
static const struct samd_part samd51_parts[] = {
|
||||
{ 0x00, "SAMD51P20A", 1024, 256 },
|
||||
|
@ -134,6 +134,8 @@ static const struct samd_part same51_parts[] = {
|
|||
{ 0x02, "SAME51J19A", 512, 192 },
|
||||
{ 0x03, "SAME51J18A", 256, 128 },
|
||||
{ 0x04, "SAME51J20A", 1024, 256 },
|
||||
{ 0x05, "SAME51G19A", 512, 192 }, /* New in rev D */
|
||||
{ 0x06, "SAME51G18A", 256, 128 }, /* New in rev D */
|
||||
};
|
||||
|
||||
/* Known SAME53 parts. */
|
||||
|
|
|
@ -832,17 +832,13 @@ int cfi_flash_bank_cmd(struct flash_bank *bank, unsigned int argc, const char **
|
|||
return ERROR_FLASH_BANK_INVALID;
|
||||
}
|
||||
|
||||
cfi_info = malloc(sizeof(struct cfi_flash_bank));
|
||||
cfi_info->probed = false;
|
||||
cfi_info->erase_region_info = NULL;
|
||||
cfi_info->pri_ext = NULL;
|
||||
cfi_info = calloc(1, sizeof(struct cfi_flash_bank));
|
||||
if (cfi_info == NULL) {
|
||||
LOG_ERROR("No memory for flash bank info");
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
bank->driver_priv = cfi_info;
|
||||
|
||||
cfi_info->x16_as_x8 = false;
|
||||
cfi_info->jedec_probe = false;
|
||||
cfi_info->not_cfi = false;
|
||||
cfi_info->data_swap = false;
|
||||
|
||||
for (unsigned i = 6; i < argc; i++) {
|
||||
if (strcmp(argv[i], "x16_as_x8") == 0)
|
||||
cfi_info->x16_as_x8 = true;
|
||||
|
|
|
@ -1243,7 +1243,7 @@ static uint32_t numicro_fmc_cmd(struct target *target, uint32_t cmd, uint32_t ad
|
|||
retval = target_read_u32(target, NUMICRO_FLASH_ISPTRG, &status);
|
||||
if (retval != ERROR_OK)
|
||||
return retval;
|
||||
LOG_DEBUG("status: 0x%" PRIx32 "", status);
|
||||
LOG_DEBUG("status: 0x%" PRIx32 "", status);
|
||||
if ((status & (ISPTRG_ISPGO)) == 0)
|
||||
break;
|
||||
if (timeout-- <= 0) {
|
||||
|
@ -1512,7 +1512,7 @@ static int numicro_erase(struct flash_bank *bank, unsigned int first,
|
|||
retval = target_read_u32(target, NUMICRO_FLASH_ISPTRG, &status);
|
||||
if (retval != ERROR_OK)
|
||||
return retval;
|
||||
LOG_DEBUG("status: 0x%" PRIx32 "", status);
|
||||
LOG_DEBUG("status: 0x%" PRIx32 "", status);
|
||||
if (status == 0)
|
||||
break;
|
||||
if (timeout-- <= 0) {
|
||||
|
@ -1601,7 +1601,7 @@ static int numicro_write(struct flash_bank *bank, const uint8_t *buffer,
|
|||
retval = target_read_u32(target, NUMICRO_FLASH_ISPTRG, &status);
|
||||
if (retval != ERROR_OK)
|
||||
return retval;
|
||||
LOG_DEBUG("status: 0x%" PRIx32 "", status);
|
||||
LOG_DEBUG("status: 0x%" PRIx32 "", status);
|
||||
if (status == 0)
|
||||
break;
|
||||
if (timeout-- <= 0) {
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -56,9 +56,9 @@
|
|||
#define OPTKEY1 0x08192A3B
|
||||
#define OPTKEY2 0x4C5D6E7F
|
||||
|
||||
#define RDP_LEVEL_0 0xAA
|
||||
#define RDP_LEVEL_1 0xBB
|
||||
#define RDP_LEVEL_2 0xCC
|
||||
/* FLASH_OPTR register bits */
|
||||
#define FLASH_RDP_MASK 0xFF
|
||||
#define FLASH_TZEN (1 << 31)
|
||||
|
||||
/* other registers */
|
||||
#define DBGMCU_IDCODE_G0 0x40015800
|
||||
|
|
|
@ -52,14 +52,6 @@
|
|||
#undef SPIFLASH_READ
|
||||
#undef SPIFLASH_PAGE_PROGRAM
|
||||
|
||||
#define READ_REG(a) \
|
||||
({ \
|
||||
uint32_t _result; \
|
||||
\
|
||||
retval = target_read_u32(target, io_base + (a), &_result); \
|
||||
(retval == ERROR_OK) ? _result : 0x0; \
|
||||
})
|
||||
|
||||
/* saved mode settings */
|
||||
#define QSPI_MODE (stmqspi_info->saved_ccr & \
|
||||
(0xF0000000U | QSPI_DCYC_MASK | QSPI_4LINE_MODE | QSPI_ALTB_MODE | QSPI_ADDR4))
|
||||
|
@ -156,23 +148,6 @@
|
|||
|
||||
#define OPI_CMD(cmd) ((OPI_MODE ? ((((uint16_t)(cmd)) << 8) | (~(cmd) & 0xFFU)) : (cmd)))
|
||||
|
||||
#define OCTOSPI_CMD(mode, ccr, ir) \
|
||||
({ \
|
||||
retval = target_write_u32(target, io_base + OCTOSPI_CR, \
|
||||
OCTOSPI_MODE | (mode)); \
|
||||
if (retval == ERROR_OK) \
|
||||
retval = target_write_u32(target, io_base + OCTOSPI_TCR, \
|
||||
(stmqspi_info->saved_tcr & ~OCTOSPI_DCYC_MASK) | \
|
||||
((OPI_MODE && ((mode) == OCTOSPI_READ_MODE)) ? \
|
||||
(OPI_DUMMY << OCTOSPI_DCYC_POS) : 0)); \
|
||||
if (retval == ERROR_OK) \
|
||||
retval = target_write_u32(target, io_base + OCTOSPI_CCR, ccr); \
|
||||
if (retval == ERROR_OK) \
|
||||
retval = target_write_u32(target, io_base + OCTOSPI_IR, \
|
||||
OPI_CMD(ir)); \
|
||||
retval; \
|
||||
})
|
||||
|
||||
/* convert uint32_t into 4 uint8_t in little endian byte order */
|
||||
static inline uint32_t h_to_le_32(uint32_t val)
|
||||
{
|
||||
|
@ -208,6 +183,35 @@ struct stmqspi_flash_bank {
|
|||
unsigned int sfdp_dummy2; /* number of dummy bytes for SFDP read for flash2 */
|
||||
};
|
||||
|
||||
static inline int octospi_cmd(struct flash_bank *bank, uint32_t mode,
|
||||
uint32_t ccr, uint32_t ir)
|
||||
{
|
||||
struct target *target = bank->target;
|
||||
const struct stmqspi_flash_bank *stmqspi_info = bank->driver_priv;
|
||||
const uint32_t io_base = stmqspi_info->io_base;
|
||||
|
||||
int retval = target_write_u32(target, io_base + OCTOSPI_CR,
|
||||
OCTOSPI_MODE | mode);
|
||||
|
||||
if (retval != ERROR_OK)
|
||||
return retval;
|
||||
|
||||
retval = target_write_u32(target, io_base + OCTOSPI_TCR,
|
||||
(stmqspi_info->saved_tcr & ~OCTOSPI_DCYC_MASK) |
|
||||
((OPI_MODE && (mode == OCTOSPI_READ_MODE)) ?
|
||||
(OPI_DUMMY << OCTOSPI_DCYC_POS) : 0));
|
||||
|
||||
if (retval != ERROR_OK)
|
||||
return retval;
|
||||
|
||||
retval = target_write_u32(target, io_base + OCTOSPI_CCR, ccr);
|
||||
|
||||
if (retval != ERROR_OK)
|
||||
return retval;
|
||||
|
||||
return target_write_u32(target, io_base + OCTOSPI_IR, OPI_CMD(ir));
|
||||
}
|
||||
|
||||
FLASH_BANK_COMMAND_HANDLER(stmqspi_flash_bank_command)
|
||||
{
|
||||
struct stmqspi_flash_bank *stmqspi_info;
|
||||
|
@ -242,19 +246,19 @@ static int poll_busy(struct flash_bank *bank, int timeout)
|
|||
struct target *target = bank->target;
|
||||
struct stmqspi_flash_bank *stmqspi_info = bank->driver_priv;
|
||||
uint32_t io_base = stmqspi_info->io_base;
|
||||
uint32_t spi_sr;
|
||||
int retval;
|
||||
long long endtime;
|
||||
|
||||
endtime = timeval_ms() + timeout;
|
||||
do {
|
||||
spi_sr = READ_REG(SPI_SR);
|
||||
if ((spi_sr & BIT(SPI_BUSY)) == 0) {
|
||||
if (retval == ERROR_OK) {
|
||||
/* Clear transmit finished flag */
|
||||
retval = target_write_u32(target, io_base + SPI_FCR, BIT(SPI_TCF));
|
||||
}
|
||||
uint32_t spi_sr;
|
||||
int retval = target_read_u32(target, io_base + SPI_SR, &spi_sr);
|
||||
|
||||
if (retval != ERROR_OK)
|
||||
return retval;
|
||||
|
||||
if ((spi_sr & BIT(SPI_BUSY)) == 0) {
|
||||
/* Clear transmit finished flag */
|
||||
return target_write_u32(target, io_base + SPI_FCR, BIT(SPI_TCF));
|
||||
} else
|
||||
LOG_DEBUG("busy: 0x%08X", spi_sr);
|
||||
alive_sleep(1);
|
||||
|
@ -264,6 +268,21 @@ static int poll_busy(struct flash_bank *bank, int timeout)
|
|||
return ERROR_FLASH_OPERATION_FAILED;
|
||||
}
|
||||
|
||||
static int stmqspi_abort(struct flash_bank *bank)
|
||||
{
|
||||
struct target *target = bank->target;
|
||||
const struct stmqspi_flash_bank *stmqspi_info = bank->driver_priv;
|
||||
const uint32_t io_base = stmqspi_info->io_base;
|
||||
uint32_t cr;
|
||||
|
||||
int retval = target_read_u32(target, io_base + SPI_CR, &cr);
|
||||
|
||||
if (retval != ERROR_OK)
|
||||
cr = 0;
|
||||
|
||||
return target_write_u32(target, io_base + SPI_CR, cr | BIT(SPI_ABORT));
|
||||
}
|
||||
|
||||
/* Set to memory-mapped mode, e.g. after an error */
|
||||
static int set_mm_mode(struct flash_bank *bank)
|
||||
{
|
||||
|
@ -278,8 +297,7 @@ static int set_mm_mode(struct flash_bank *bank)
|
|||
return retval;
|
||||
|
||||
/* Abort any previous operation */
|
||||
retval = target_write_u32(target, io_base + SPI_CR,
|
||||
READ_REG(SPI_CR) | BIT(SPI_ABORT));
|
||||
retval = stmqspi_abort(bank);
|
||||
if (retval != ERROR_OK)
|
||||
return retval;
|
||||
|
||||
|
@ -321,8 +339,7 @@ static int read_status_reg(struct flash_bank *bank, uint16_t *status)
|
|||
int count, retval;
|
||||
|
||||
/* Abort any previous operation */
|
||||
retval = target_write_u32(target, io_base + SPI_CR,
|
||||
READ_REG(SPI_CR) | BIT(SPI_ABORT));
|
||||
retval = stmqspi_abort(bank);
|
||||
if (retval != ERROR_OK)
|
||||
return retval;
|
||||
|
||||
|
@ -340,7 +357,8 @@ static int read_status_reg(struct flash_bank *bank, uint16_t *status)
|
|||
|
||||
/* Read status */
|
||||
if (IS_OCTOSPI) {
|
||||
retval = OCTOSPI_CMD(OCTOSPI_READ_MODE, OCTOSPI_CCR_READ_STATUS, SPIFLASH_READ_STATUS);
|
||||
retval = octospi_cmd(bank, OCTOSPI_READ_MODE, OCTOSPI_CCR_READ_STATUS,
|
||||
SPIFLASH_READ_STATUS);
|
||||
if (OPI_MODE) {
|
||||
/* Dummy address 0, only required for 8-line mode */
|
||||
retval = target_write_u32(target, io_base + SPI_AR, 0);
|
||||
|
@ -355,7 +373,8 @@ static int read_status_reg(struct flash_bank *bank, uint16_t *status)
|
|||
*status = 0;
|
||||
|
||||
/* for debugging only */
|
||||
(void)READ_REG(SPI_SR);
|
||||
uint32_t dummy;
|
||||
(void)target_read_u32(target, io_base + SPI_SR, &dummy);
|
||||
|
||||
for ( ; count > 0; --count) {
|
||||
if ((stmqspi_info->saved_cr & (BIT(SPI_DUAL_FLASH) | BIT(SPI_FSEL_FLASH)))
|
||||
|
@ -416,8 +435,7 @@ static int qspi_write_enable(struct flash_bank *bank)
|
|||
int retval;
|
||||
|
||||
/* Abort any previous operation */
|
||||
retval = target_write_u32(target, io_base + SPI_CR,
|
||||
READ_REG(SPI_CR) | BIT(SPI_ABORT));
|
||||
retval = stmqspi_abort(bank);
|
||||
if (retval != ERROR_OK)
|
||||
return retval;
|
||||
|
||||
|
@ -428,7 +446,8 @@ static int qspi_write_enable(struct flash_bank *bank)
|
|||
|
||||
/* Send write enable command */
|
||||
if (IS_OCTOSPI) {
|
||||
retval = OCTOSPI_CMD(OCTOSPI_WRITE_MODE, OCTOSPI_CCR_WRITE_ENABLE, SPIFLASH_WRITE_ENABLE);
|
||||
retval = octospi_cmd(bank, OCTOSPI_WRITE_MODE, OCTOSPI_CCR_WRITE_ENABLE,
|
||||
SPIFLASH_WRITE_ENABLE);
|
||||
if (OPI_MODE) {
|
||||
/* Dummy address 0, only required for 8-line mode */
|
||||
retval = target_write_u32(target, io_base + SPI_AR, 0);
|
||||
|
@ -527,7 +546,7 @@ COMMAND_HANDLER(stmqspi_handle_mass_erase_command)
|
|||
|
||||
/* Send Mass Erase command */
|
||||
if (IS_OCTOSPI)
|
||||
retval = OCTOSPI_CMD(OCTOSPI_WRITE_MODE, OCTOSPI_CCR_MASS_ERASE,
|
||||
retval = octospi_cmd(bank, OCTOSPI_WRITE_MODE, OCTOSPI_CCR_MASS_ERASE,
|
||||
stmqspi_info->dev.chip_erase_cmd);
|
||||
else
|
||||
retval = target_write_u32(target, io_base + QSPI_CCR, QSPI_CCR_MASS_ERASE);
|
||||
|
@ -714,10 +733,15 @@ COMMAND_HANDLER(stmqspi_handle_set)
|
|||
bank->size = stmqspi_info->dev.size_in_bytes << dual;
|
||||
|
||||
io_base = stmqspi_info->io_base;
|
||||
fsize = (READ_REG(SPI_DCR) >> SPI_FSIZE_POS) & (BIT(SPI_FSIZE_LEN) - 1);
|
||||
|
||||
uint32_t dcr;
|
||||
retval = target_read_u32(target, io_base + SPI_DCR, &dcr);
|
||||
|
||||
if (retval != ERROR_OK)
|
||||
return retval;
|
||||
|
||||
fsize = (dcr >> SPI_FSIZE_POS) & (BIT(SPI_FSIZE_LEN) - 1);
|
||||
|
||||
LOG_DEBUG("FSIZE = 0x%04x", fsize);
|
||||
if (bank->size == BIT(fsize + 1))
|
||||
LOG_DEBUG("FSIZE in DCR(1) matches actual capacity. Beware of silicon bug in H7, L4+, MP1.");
|
||||
|
@ -823,8 +847,7 @@ COMMAND_HANDLER(stmqspi_handle_cmd)
|
|||
}
|
||||
|
||||
/* Abort any previous operation */
|
||||
retval = target_write_u32(target, io_base + SPI_CR,
|
||||
READ_REG(SPI_CR) | BIT(SPI_ABORT));
|
||||
retval = stmqspi_abort(bank);
|
||||
if (retval != ERROR_OK)
|
||||
return retval;
|
||||
|
||||
|
@ -842,7 +865,7 @@ COMMAND_HANDLER(stmqspi_handle_cmd)
|
|||
goto err;
|
||||
|
||||
if (IS_OCTOSPI)
|
||||
retval = OCTOSPI_CMD(OCTOSPI_WRITE_MODE,
|
||||
retval = octospi_cmd(bank, OCTOSPI_WRITE_MODE,
|
||||
(OCTOSPI_MODE_CCR & OCTOSPI_NO_ALTB & OCTOSPI_NO_ADDR &
|
||||
((num_write == 1) ? OCTOSPI_NO_DATA : ~0U)), cmd_byte);
|
||||
else
|
||||
|
@ -879,7 +902,7 @@ COMMAND_HANDLER(stmqspi_handle_cmd)
|
|||
if (retval != ERROR_OK)
|
||||
goto err;
|
||||
if (IS_OCTOSPI)
|
||||
retval = OCTOSPI_CMD(OCTOSPI_READ_MODE,
|
||||
retval = octospi_cmd(bank, OCTOSPI_READ_MODE,
|
||||
(OCTOSPI_MODE_CCR & OCTOSPI_NO_DDTR & OCTOSPI_NO_ALTB & ~OCTOSPI_ADDR4 &
|
||||
((num_write == 1) ? OCTOSPI_NO_ADDR : ~0U)) |
|
||||
(((num_write - 2) & 0x3U) << SPI_ADSIZE_POS), cmd_byte);
|
||||
|
@ -930,7 +953,7 @@ static int qspi_erase_sector(struct flash_bank *bank, unsigned int sector)
|
|||
|
||||
/* Send Sector Erase command */
|
||||
if (IS_OCTOSPI)
|
||||
retval = OCTOSPI_CMD(OCTOSPI_WRITE_MODE, OCTOSPI_CCR_SECTOR_ERASE,
|
||||
retval = octospi_cmd(bank, OCTOSPI_WRITE_MODE, OCTOSPI_CCR_SECTOR_ERASE,
|
||||
stmqspi_info->dev.erase_cmd);
|
||||
else
|
||||
retval = target_write_u32(target, io_base + QSPI_CCR, QSPI_CCR_SECTOR_ERASE);
|
||||
|
@ -1059,7 +1082,6 @@ static int stmqspi_blank_check(struct flash_bank *bank)
|
|||
{
|
||||
struct target *target = bank->target;
|
||||
struct stmqspi_flash_bank *stmqspi_info = bank->driver_priv;
|
||||
uint32_t io_base = stmqspi_info->io_base;
|
||||
struct duration bench;
|
||||
struct reg_param reg_params[2];
|
||||
struct armv7m_algorithm armv7m_info;
|
||||
|
@ -1082,8 +1104,7 @@ static int stmqspi_blank_check(struct flash_bank *bank)
|
|||
}
|
||||
|
||||
/* Abort any previous operation */
|
||||
retval = target_write_u32(target, io_base + SPI_CR,
|
||||
READ_REG(SPI_CR) | BIT(SPI_ABORT));
|
||||
retval = stmqspi_abort(bank);
|
||||
if (retval != ERROR_OK)
|
||||
return retval;
|
||||
|
||||
|
@ -1568,7 +1589,6 @@ static int stmqspi_read(struct flash_bank *bank, uint8_t *buffer,
|
|||
{
|
||||
struct target *target = bank->target;
|
||||
struct stmqspi_flash_bank *stmqspi_info = bank->driver_priv;
|
||||
uint32_t io_base = stmqspi_info->io_base;
|
||||
int retval;
|
||||
|
||||
LOG_DEBUG("%s: offset=0x%08" PRIx32 " count=0x%08" PRIx32,
|
||||
|
@ -1590,8 +1610,7 @@ static int stmqspi_read(struct flash_bank *bank, uint8_t *buffer,
|
|||
}
|
||||
|
||||
/* Abort any previous operation */
|
||||
retval = target_write_u32(target, io_base + SPI_CR,
|
||||
READ_REG(SPI_CR) | BIT(SPI_ABORT));
|
||||
retval = stmqspi_abort(bank);
|
||||
if (retval != ERROR_OK)
|
||||
return retval;
|
||||
|
||||
|
@ -1608,7 +1627,6 @@ static int stmqspi_write(struct flash_bank *bank, const uint8_t *buffer,
|
|||
{
|
||||
struct target *target = bank->target;
|
||||
struct stmqspi_flash_bank *stmqspi_info = bank->driver_priv;
|
||||
uint32_t io_base = stmqspi_info->io_base;
|
||||
unsigned int dual, sector;
|
||||
bool octal_dtr;
|
||||
int retval;
|
||||
|
@ -1653,8 +1671,7 @@ static int stmqspi_write(struct flash_bank *bank, const uint8_t *buffer,
|
|||
}
|
||||
|
||||
/* Abort any previous operation */
|
||||
retval = target_write_u32(target, io_base + SPI_CR,
|
||||
READ_REG(SPI_CR) | BIT(SPI_ABORT));
|
||||
retval = stmqspi_abort(bank);
|
||||
if (retval != ERROR_OK)
|
||||
return retval;
|
||||
|
||||
|
@ -1671,7 +1688,6 @@ static int stmqspi_verify(struct flash_bank *bank, const uint8_t *buffer,
|
|||
{
|
||||
struct target *target = bank->target;
|
||||
struct stmqspi_flash_bank *stmqspi_info = bank->driver_priv;
|
||||
uint32_t io_base = stmqspi_info->io_base;
|
||||
unsigned int dual;
|
||||
bool octal_dtr;
|
||||
int retval;
|
||||
|
@ -1704,8 +1720,7 @@ static int stmqspi_verify(struct flash_bank *bank, const uint8_t *buffer,
|
|||
}
|
||||
|
||||
/* Abort any previous operation */
|
||||
retval = target_write_u32(target, io_base + SPI_CR,
|
||||
READ_REG(SPI_CR) | BIT(SPI_ABORT));
|
||||
retval = stmqspi_abort(bank);
|
||||
if (retval != ERROR_OK)
|
||||
return retval;
|
||||
|
||||
|
@ -1757,8 +1772,8 @@ static int find_sfdp_dummy(struct flash_bank *bank, int len)
|
|||
|
||||
/* Read SFDP block */
|
||||
if (IS_OCTOSPI)
|
||||
retval = OCTOSPI_CMD(OCTOSPI_READ_MODE, OCTOSPI_CCR_READ_SFDP(len),
|
||||
SPIFLASH_READ_SFDP);
|
||||
retval = octospi_cmd(bank, OCTOSPI_READ_MODE,
|
||||
OCTOSPI_CCR_READ_SFDP(len), SPIFLASH_READ_SFDP);
|
||||
else
|
||||
retval = target_write_u32(target, io_base + QSPI_CCR, QSPI_CCR_READ_SFDP);
|
||||
if (retval != ERROR_OK)
|
||||
|
@ -1804,8 +1819,7 @@ static int find_sfdp_dummy(struct flash_bank *bank, int len)
|
|||
|
||||
err:
|
||||
/* Abort operation */
|
||||
retval = target_write_u32(target, io_base + SPI_CR,
|
||||
READ_REG(SPI_CR) | BIT(SPI_ABORT));
|
||||
retval = stmqspi_abort(bank);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
@ -1880,8 +1894,8 @@ static int read_sfdp_block(struct flash_bank *bank, uint32_t addr,
|
|||
|
||||
/* Read SFDP block */
|
||||
if (IS_OCTOSPI)
|
||||
retval = OCTOSPI_CMD(OCTOSPI_READ_MODE, OCTOSPI_CCR_READ_SFDP(len),
|
||||
SPIFLASH_READ_SFDP);
|
||||
retval = octospi_cmd(bank, OCTOSPI_READ_MODE,
|
||||
OCTOSPI_CCR_READ_SFDP(len), SPIFLASH_READ_SFDP);
|
||||
else
|
||||
retval = target_write_u32(target, io_base + QSPI_CCR, QSPI_CCR_READ_SFDP);
|
||||
if (retval != ERROR_OK)
|
||||
|
@ -1959,8 +1973,7 @@ static int read_flash_id(struct flash_bank *bank, uint32_t *id1, uint32_t *id2)
|
|||
/* SPIFLASH_READ_MID causes device in octal mode to go berserk, so don't use in this case */
|
||||
for (type = (IS_OCTOSPI && OPI_MODE) ? 1 : 0; type < 2 ; type++) {
|
||||
/* Abort any previous operation */
|
||||
retval = target_write_u32(target, io_base + SPI_CR,
|
||||
READ_REG(SPI_CR) | BIT(SPI_ABORT));
|
||||
retval = stmqspi_abort(bank);
|
||||
if (retval != ERROR_OK)
|
||||
goto err;
|
||||
|
||||
|
@ -1986,14 +1999,16 @@ static int read_flash_id(struct flash_bank *bank, uint32_t *id1, uint32_t *id2)
|
|||
switch (type) {
|
||||
case 0:
|
||||
if (IS_OCTOSPI)
|
||||
retval = OCTOSPI_CMD(OCTOSPI_READ_MODE, OCTOSPI_CCR_READ_MID, SPIFLASH_READ_MID);
|
||||
retval = octospi_cmd(bank, OCTOSPI_READ_MODE,
|
||||
OCTOSPI_CCR_READ_MID, SPIFLASH_READ_MID);
|
||||
else
|
||||
retval = target_write_u32(target, io_base + QSPI_CCR, QSPI_CCR_READ_MID);
|
||||
break;
|
||||
|
||||
case 1:
|
||||
if (IS_OCTOSPI)
|
||||
retval = OCTOSPI_CMD(OCTOSPI_READ_MODE, OCTOSPI_CCR_READ_ID, SPIFLASH_READ_ID);
|
||||
retval = octospi_cmd(bank, OCTOSPI_READ_MODE,
|
||||
OCTOSPI_CCR_READ_ID, SPIFLASH_READ_ID);
|
||||
else
|
||||
retval = target_write_u32(target, io_base + QSPI_CCR, QSPI_CCR_READ_ID);
|
||||
break;
|
||||
|
@ -2013,7 +2028,8 @@ static int read_flash_id(struct flash_bank *bank, uint32_t *id1, uint32_t *id2)
|
|||
}
|
||||
|
||||
/* for debugging only */
|
||||
(void)READ_REG(SPI_SR);
|
||||
uint32_t dummy;
|
||||
(void)target_read_u32(target, io_base + SPI_SR, &dummy);
|
||||
|
||||
/* Read ID from Data Register */
|
||||
for (len1 = 0, len2 = 0; count > 0; --count) {
|
||||
|
@ -2092,8 +2108,7 @@ static int stmqspi_probe(struct flash_bank *bank)
|
|||
}
|
||||
|
||||
/* Abort any previous operation */
|
||||
retval = target_write_u32(target, io_base + SPI_CR,
|
||||
READ_REG(SPI_CR) | BIT(SPI_ABORT));
|
||||
retval = stmqspi_abort(bank);
|
||||
if (retval != ERROR_OK)
|
||||
return retval;
|
||||
|
||||
|
@ -2112,43 +2127,59 @@ static int stmqspi_probe(struct flash_bank *bank)
|
|||
if (data == magic) {
|
||||
LOG_DEBUG("QSPI_ABR register present");
|
||||
stmqspi_info->octo = false;
|
||||
} else if (READ_REG(OCTOSPI_MAGIC) == OCTO_MAGIC_ID) {
|
||||
LOG_DEBUG("OCTOSPI_MAGIC present");
|
||||
stmqspi_info->octo = true;
|
||||
} else {
|
||||
LOG_ERROR("No QSPI, no OCTOSPI at 0x%08" PRIx32, io_base);
|
||||
stmqspi_info->probed = false;
|
||||
stmqspi_info->dev.name = "none";
|
||||
return ERROR_FAIL;
|
||||
uint32_t magic_id;
|
||||
|
||||
retval = target_read_u32(target, io_base + OCTOSPI_MAGIC, &magic_id);
|
||||
|
||||
if (retval == ERROR_OK && magic_id == OCTO_MAGIC_ID) {
|
||||
LOG_DEBUG("OCTOSPI_MAGIC present");
|
||||
stmqspi_info->octo = true;
|
||||
} else {
|
||||
LOG_ERROR("No QSPI, no OCTOSPI at 0x%08" PRIx32, io_base);
|
||||
stmqspi_info->probed = false;
|
||||
stmqspi_info->dev.name = "none";
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
}
|
||||
|
||||
/* save current FSEL and DFM bits in QSPI/OCTOSPI_CR, current QSPI/OCTOSPI_CCR value */
|
||||
stmqspi_info->saved_cr = READ_REG(SPI_CR);
|
||||
retval = target_read_u32(target, io_base + SPI_CR, &stmqspi_info->saved_cr);
|
||||
if (retval == ERROR_OK)
|
||||
stmqspi_info->saved_ccr = READ_REG(SPI_CCR);
|
||||
retval = target_read_u32(target, io_base + SPI_CCR, &stmqspi_info->saved_ccr);
|
||||
|
||||
if (IS_OCTOSPI) {
|
||||
uint32_t mtyp;
|
||||
uint32_t dcr1;
|
||||
|
||||
retval = target_read_u32(target, io_base + OCTOSPI_DCR1, &dcr1);
|
||||
|
||||
mtyp = ((READ_REG(OCTOSPI_DCR1) & OCTOSPI_MTYP_MASK)) >> OCTOSPI_MTYP_POS;
|
||||
if (retval == ERROR_OK)
|
||||
stmqspi_info->saved_tcr = READ_REG(OCTOSPI_TCR);
|
||||
retval = target_read_u32(target, io_base + OCTOSPI_TCR,
|
||||
&stmqspi_info->saved_tcr);
|
||||
|
||||
if (retval == ERROR_OK)
|
||||
stmqspi_info->saved_ir = READ_REG(OCTOSPI_IR);
|
||||
if ((mtyp != 0x0) && (mtyp != 0x1)) {
|
||||
retval = ERROR_FAIL;
|
||||
LOG_ERROR("Only regular SPI protocol supported in OCTOSPI");
|
||||
}
|
||||
if (retval == ERROR_OK) {
|
||||
LOG_DEBUG("OCTOSPI at 0x%08" PRIx64 ", io_base at 0x%08" PRIx32 ", OCTOSPI_CR 0x%08"
|
||||
PRIx32 ", OCTOSPI_CCR 0x%08" PRIx32 ", %d-byte addr", bank->base, io_base,
|
||||
stmqspi_info->saved_cr, stmqspi_info->saved_ccr, SPI_ADSIZE);
|
||||
} else {
|
||||
retval = target_read_u32(target, io_base + OCTOSPI_IR,
|
||||
&stmqspi_info->saved_ir);
|
||||
|
||||
if (retval != ERROR_OK) {
|
||||
LOG_ERROR("No OCTOSPI at io_base 0x%08" PRIx32, io_base);
|
||||
stmqspi_info->probed = false;
|
||||
stmqspi_info->dev.name = "none";
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
|
||||
const uint32_t mtyp = (dcr1 & OCTOSPI_MTYP_MASK) >> OCTOSPI_MTYP_POS;
|
||||
|
||||
if ((mtyp != 0x0) && (mtyp != 0x1)) {
|
||||
LOG_ERROR("Only regular SPI protocol supported in OCTOSPI");
|
||||
stmqspi_info->probed = false;
|
||||
stmqspi_info->dev.name = "none";
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
|
||||
LOG_DEBUG("OCTOSPI at 0x%08" PRIx64 ", io_base at 0x%08" PRIx32 ", OCTOSPI_CR 0x%08"
|
||||
PRIx32 ", OCTOSPI_CCR 0x%08" PRIx32 ", %d-byte addr", bank->base, io_base,
|
||||
stmqspi_info->saved_cr, stmqspi_info->saved_ccr, SPI_ADSIZE);
|
||||
} else {
|
||||
if (retval == ERROR_OK) {
|
||||
LOG_DEBUG("QSPI at 0x%08" PRIx64 ", io_base at 0x%08" PRIx32 ", QSPI_CR 0x%08"
|
||||
|
@ -2301,10 +2332,14 @@ static int stmqspi_probe(struct flash_bank *bank)
|
|||
/* Set correct size value */
|
||||
bank->size = stmqspi_info->dev.size_in_bytes << dual;
|
||||
|
||||
fsize = ((READ_REG(SPI_DCR) >> SPI_FSIZE_POS) & (BIT(SPI_FSIZE_LEN) - 1));
|
||||
uint32_t dcr;
|
||||
retval = target_read_u32(target, io_base + SPI_DCR, &dcr);
|
||||
|
||||
if (retval != ERROR_OK)
|
||||
goto err;
|
||||
|
||||
fsize = (dcr >> SPI_FSIZE_POS) & (BIT(SPI_FSIZE_LEN) - 1);
|
||||
|
||||
LOG_DEBUG("FSIZE = 0x%04x", fsize);
|
||||
if (bank->size == BIT((fsize + 1)))
|
||||
LOG_DEBUG("FSIZE in DCR(1) matches actual capacity. Beware of silicon bug in H7, L4+, MP1.");
|
||||
|
|
|
@ -119,14 +119,3 @@ proc stm32g4x args { eval stm32l4x $args }
|
|||
proc stm32l5x args { eval stm32l4x $args }
|
||||
proc stm32wbx args { eval stm32l4x $args }
|
||||
proc stm32wlx args { eval stm32l4x $args }
|
||||
|
||||
# ease migration to updated flash driver
|
||||
proc stm32x args {
|
||||
echo "DEPRECATED! use 'stm32f1x $args' not 'stm32x $args'"
|
||||
eval stm32f1x $args
|
||||
}
|
||||
|
||||
proc stm32f2xxx args {
|
||||
echo "DEPRECATED! use 'stm32f2x $args' not 'stm32f2xxx $args'"
|
||||
eval stm32f2x $args
|
||||
}
|
||||
|
|
|
@ -18,7 +18,6 @@ noinst_LTLIBRARIES += %D%/libhelper.la
|
|||
%D%/binarybuffer.h \
|
||||
%D%/bits.h \
|
||||
%D%/configuration.h \
|
||||
%D%/ioutil.h \
|
||||
%D%/list.h \
|
||||
%D%/util.h \
|
||||
%D%/types.h \
|
||||
|
@ -34,12 +33,6 @@ noinst_LTLIBRARIES += %D%/libhelper.la
|
|||
%D%/base64.c \
|
||||
%D%/base64.h
|
||||
|
||||
if IOUTIL
|
||||
%C%_libhelper_la_SOURCES += %D%/ioutil.c
|
||||
else
|
||||
%C%_libhelper_la_SOURCES += %D%/ioutil_stubs.c
|
||||
endif
|
||||
|
||||
%C%_libhelper_la_CFLAGS = $(AM_CFLAGS)
|
||||
if IS_MINGW
|
||||
# FD_* macros are sloppy with their signs on MinGW32 platform
|
||||
|
|
|
@ -117,6 +117,40 @@ static void command_log_capture_finish(struct log_capture_state *state)
|
|||
free(state);
|
||||
}
|
||||
|
||||
/*
|
||||
* FIXME: workaround for memory leak in jimtcl 0.80
|
||||
* Jim API Jim_CreateCommand() converts the command name in a Jim object and
|
||||
* does not free the object. Fixed for jimtcl 0.81 by e4416cf86f0b
|
||||
* Use the internal jimtcl API Jim_CreateCommandObj, not exported by jim.h,
|
||||
* and override the bugged API through preprocessor's macro.
|
||||
* This workaround works only when jimtcl is compiled as OpenOCD submodule.
|
||||
* If jimtcl is linked-in from a precompiled library, either static or dynamic,
|
||||
* the symbol Jim_CreateCommandObj is not exported and the build will use the
|
||||
* bugged API.
|
||||
* To be removed when OpenOCD will switch to jimtcl 0.81
|
||||
*/
|
||||
#if JIM_VERSION == 80
|
||||
static int workaround_createcommand(Jim_Interp *interp, const char *cmdName,
|
||||
Jim_CmdProc *cmdProc, void *privData, Jim_DelCmdProc *delProc);
|
||||
int Jim_CreateCommandObj(Jim_Interp *interp, Jim_Obj *cmdNameObj,
|
||||
Jim_CmdProc *cmdProc, void *privData, Jim_DelCmdProc *delProc)
|
||||
__attribute__((weak, alias("workaround_createcommand")));
|
||||
static int workaround_createcommand(Jim_Interp *interp, const char *cmdName,
|
||||
Jim_CmdProc *cmdProc, void *privData, Jim_DelCmdProc *delProc)
|
||||
{
|
||||
if ((void *)Jim_CreateCommandObj == (void *)workaround_createcommand)
|
||||
return Jim_CreateCommand(interp, cmdName, cmdProc, privData, delProc);
|
||||
|
||||
Jim_Obj *cmd_name = Jim_NewStringObj(interp, cmdName, -1);
|
||||
Jim_IncrRefCount(cmd_name);
|
||||
int retval = Jim_CreateCommandObj(interp, cmd_name, cmdProc, privData, delProc);
|
||||
Jim_DecrRefCount(interp, cmd_name);
|
||||
return retval;
|
||||
}
|
||||
#define Jim_CreateCommand workaround_createcommand
|
||||
#endif /* JIM_VERSION == 80 */
|
||||
/* FIXME: end of workaround for memory leak in jimtcl 0.80 */
|
||||
|
||||
static int command_retval_set(Jim_Interp *interp, int retval)
|
||||
{
|
||||
int *return_retval = Jim_GetAssocData(interp, "retval");
|
||||
|
|
|
@ -1,534 +0,0 @@
|
|||
/***************************************************************************
|
||||
* Copyright (C) 2007-2010 by Øyvind Harboe *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation; either version 2 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
* This program is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License *
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
|
||||
***************************************************************************/
|
||||
|
||||
/* this file contains various functionality useful to standalone systems */
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "log.h"
|
||||
#include "time_support.h"
|
||||
|
||||
#ifdef HAVE_ARPA_INET_H
|
||||
#include <arpa/inet.h>
|
||||
#endif
|
||||
#ifdef HAVE_DIRENT_H
|
||||
#include <dirent.h>
|
||||
#endif
|
||||
#ifdef HAVE_NETDB_H
|
||||
#include <netdb.h>
|
||||
#endif
|
||||
#ifdef HAVE_NET_IF_H
|
||||
#include <net/if.h>
|
||||
#endif
|
||||
#ifdef HAVE_SYS_IOCTL_H
|
||||
#include <sys/ioctl.h>
|
||||
#endif
|
||||
#ifdef HAVE_SYS_STAT_H
|
||||
#include <sys/stat.h>
|
||||
#endif
|
||||
#ifdef HAVE_IFADDRS_H
|
||||
#include <ifaddrs.h>
|
||||
#endif
|
||||
#ifdef HAVE_MALLOC_H
|
||||
#include <malloc.h>
|
||||
#endif
|
||||
|
||||
/* loads a file and returns a pointer to it in memory. The file contains
|
||||
* a 0 byte(sentinel) after len bytes - the length of the file. */
|
||||
static int load_file(const char *fileName, char **data, size_t *len)
|
||||
{
|
||||
/* ensure returned length is always sane */
|
||||
*len = 0;
|
||||
|
||||
FILE *pFile;
|
||||
pFile = fopen(fileName, "rb");
|
||||
if (pFile == NULL) {
|
||||
LOG_ERROR("Can't open %s", fileName);
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
if (fseek(pFile, 0, SEEK_END) != 0) {
|
||||
LOG_ERROR("Can't open %s", fileName);
|
||||
fclose(pFile);
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
long fsize = ftell(pFile);
|
||||
if (fsize == -1) {
|
||||
LOG_ERROR("Can't open %s", fileName);
|
||||
fclose(pFile);
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
*len = fsize;
|
||||
|
||||
if (fseek(pFile, 0, SEEK_SET) != 0) {
|
||||
LOG_ERROR("Can't open %s", fileName);
|
||||
fclose(pFile);
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
*data = malloc(*len + 1);
|
||||
if (*data == NULL) {
|
||||
LOG_ERROR("Can't open %s", fileName);
|
||||
fclose(pFile);
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
|
||||
if (fread(*data, 1, *len, pFile) != *len) {
|
||||
fclose(pFile);
|
||||
free(*data);
|
||||
LOG_ERROR("Can't open %s", fileName);
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
fclose(pFile);
|
||||
|
||||
/* 0-byte after buffer (not included in *len) serves as a sentinel */
|
||||
(*data)[*len] = 0;
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
COMMAND_HANDLER(handle_cat_command)
|
||||
{
|
||||
if (CMD_ARGC != 1)
|
||||
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||
|
||||
/* NOTE!!! we only have line printing capability so we print the entire file as a single
|
||||
* line. */
|
||||
char *data;
|
||||
size_t len;
|
||||
|
||||
int retval = load_file(CMD_ARGV[0], &data, &len);
|
||||
if (retval == ERROR_OK) {
|
||||
command_print(CMD, "%s", data);
|
||||
free(data);
|
||||
} else
|
||||
command_print(CMD, "%s not found", CMD_ARGV[0]);
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
COMMAND_HANDLER(handle_trunc_command)
|
||||
{
|
||||
if (CMD_ARGC != 1)
|
||||
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||
|
||||
FILE *config_file = NULL;
|
||||
config_file = fopen(CMD_ARGV[0], "w");
|
||||
if (config_file != NULL)
|
||||
fclose(config_file);
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
#ifdef HAVE_MALLOC_H
|
||||
COMMAND_HANDLER(handle_meminfo_command)
|
||||
{
|
||||
static int prev;
|
||||
struct mallinfo info;
|
||||
|
||||
if (CMD_ARGC != 0)
|
||||
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||
|
||||
info = mallinfo();
|
||||
|
||||
if (prev > 0)
|
||||
command_print(CMD, "Diff: %d", prev - info.fordblks);
|
||||
prev = info.fordblks;
|
||||
|
||||
command_print(CMD, "Available ram: %d", info.fordblks);
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
COMMAND_HANDLER(handle_append_command)
|
||||
{
|
||||
if (CMD_ARGC < 1)
|
||||
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||
|
||||
int retval = ERROR_FAIL;
|
||||
FILE *config_file = NULL;
|
||||
|
||||
config_file = fopen(CMD_ARGV[0], "a");
|
||||
if (config_file != NULL) {
|
||||
fseek(config_file, 0, SEEK_END);
|
||||
|
||||
unsigned i;
|
||||
for (i = 1; i < CMD_ARGC; i++) {
|
||||
if (fwrite(CMD_ARGV[i], 1, strlen(CMD_ARGV[i]),
|
||||
config_file) != strlen(CMD_ARGV[i]))
|
||||
break;
|
||||
if (i != CMD_ARGC - 1) {
|
||||
if (fwrite(" ", 1, 1, config_file) != 1)
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ((i == CMD_ARGC) && (fwrite("\n", 1, 1, config_file) == 1))
|
||||
retval = ERROR_OK;
|
||||
|
||||
fclose(config_file);
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
COMMAND_HANDLER(handle_cp_command)
|
||||
{
|
||||
if (CMD_ARGC != 2)
|
||||
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||
|
||||
/* NOTE!!! we only have line printing capability so we print the entire file as a single
|
||||
* line. */
|
||||
char *data;
|
||||
size_t len;
|
||||
|
||||
int retval = load_file(CMD_ARGV[0], &data, &len);
|
||||
if (retval != ERROR_OK)
|
||||
return retval;
|
||||
|
||||
FILE *f = fopen(CMD_ARGV[1], "wb");
|
||||
if (f == NULL)
|
||||
retval = ERROR_COMMAND_SYNTAX_ERROR;
|
||||
|
||||
size_t pos = 0;
|
||||
for (;; ) {
|
||||
size_t chunk = len - pos;
|
||||
static const size_t maxChunk = 512 * 1024; /* ~1/sec */
|
||||
if (chunk > maxChunk)
|
||||
chunk = maxChunk;
|
||||
|
||||
if ((retval == ERROR_OK) && (fwrite(data + pos, 1, chunk, f) != chunk))
|
||||
retval = ERROR_COMMAND_SYNTAX_ERROR;
|
||||
|
||||
if (retval != ERROR_OK)
|
||||
break;
|
||||
|
||||
command_print(CMD, "%zu", len - pos);
|
||||
|
||||
pos += chunk;
|
||||
|
||||
if (pos == len)
|
||||
break;
|
||||
}
|
||||
|
||||
if (retval == ERROR_OK)
|
||||
command_print(CMD, "Copied %s to %s", CMD_ARGV[0], CMD_ARGV[1]);
|
||||
else
|
||||
command_print(CMD, "copy failed");
|
||||
|
||||
free(data);
|
||||
if (f != NULL)
|
||||
fclose(f);
|
||||
|
||||
if (retval != ERROR_OK)
|
||||
unlink(CMD_ARGV[1]);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
COMMAND_HANDLER(handle_rm_command)
|
||||
{
|
||||
if (CMD_ARGC != 1)
|
||||
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||
|
||||
bool del = false;
|
||||
if (rmdir(CMD_ARGV[0]) == 0)
|
||||
del = true;
|
||||
else if (unlink(CMD_ARGV[0]) == 0)
|
||||
del = true;
|
||||
|
||||
return del ? ERROR_OK : ERROR_FAIL;
|
||||
}
|
||||
|
||||
static int ioutil_Jim_Command_ls(Jim_Interp *interp,
|
||||
int argc,
|
||||
Jim_Obj * const *argv)
|
||||
{
|
||||
if (argc != 2) {
|
||||
Jim_WrongNumArgs(interp, 1, argv, "ls ?dir?");
|
||||
return JIM_ERR;
|
||||
}
|
||||
|
||||
const char *name = Jim_GetString(argv[1], NULL);
|
||||
|
||||
DIR *dirp = NULL;
|
||||
dirp = opendir(name);
|
||||
if (dirp == NULL)
|
||||
return JIM_ERR;
|
||||
Jim_Obj *objPtr = Jim_NewListObj(interp, NULL, 0);
|
||||
|
||||
for (;; ) {
|
||||
struct dirent *entry = NULL;
|
||||
entry = readdir(dirp);
|
||||
if (entry == NULL)
|
||||
break;
|
||||
|
||||
if ((strcmp(".", entry->d_name) == 0) || (strcmp("..", entry->d_name) == 0))
|
||||
continue;
|
||||
|
||||
Jim_ListAppendElement(interp, objPtr,
|
||||
Jim_NewStringObj(interp, entry->d_name, strlen(entry->d_name)));
|
||||
}
|
||||
closedir(dirp);
|
||||
|
||||
Jim_SetResult(interp, objPtr);
|
||||
|
||||
return JIM_OK;
|
||||
}
|
||||
|
||||
static int ioutil_Jim_Command_peek(Jim_Interp *interp,
|
||||
int argc,
|
||||
Jim_Obj *const *argv)
|
||||
{
|
||||
if (argc != 2) {
|
||||
Jim_WrongNumArgs(interp, 1, argv, "peek ?address?");
|
||||
return JIM_ERR;
|
||||
}
|
||||
|
||||
long address;
|
||||
if (Jim_GetLong(interp, argv[1], &address) != JIM_OK)
|
||||
return JIM_ERR;
|
||||
|
||||
int value = *((volatile int *) address);
|
||||
|
||||
Jim_SetResult(interp, Jim_NewIntObj(interp, value));
|
||||
|
||||
return JIM_OK;
|
||||
}
|
||||
|
||||
static int ioutil_Jim_Command_poke(Jim_Interp *interp,
|
||||
int argc,
|
||||
Jim_Obj *const *argv)
|
||||
{
|
||||
if (argc != 3) {
|
||||
Jim_WrongNumArgs(interp, 1, argv, "poke ?address? ?value?");
|
||||
return JIM_ERR;
|
||||
}
|
||||
|
||||
long address;
|
||||
if (Jim_GetLong(interp, argv[1], &address) != JIM_OK)
|
||||
return JIM_ERR;
|
||||
long value;
|
||||
if (Jim_GetLong(interp, argv[2], &value) != JIM_OK)
|
||||
return JIM_ERR;
|
||||
|
||||
*((volatile int *) address) = value;
|
||||
|
||||
return JIM_OK;
|
||||
}
|
||||
|
||||
/* not so pretty code to fish out ip number*/
|
||||
static int ioutil_Jim_Command_ip(Jim_Interp *interp, int argc,
|
||||
Jim_Obj *const *argv)
|
||||
{
|
||||
#if !defined(__CYGWIN__)
|
||||
Jim_Obj *tclOutput = Jim_NewStringObj(interp, "", 0);
|
||||
|
||||
struct ifaddrs *ifa = NULL, *ifp = NULL;
|
||||
|
||||
if (getifaddrs(&ifp) < 0)
|
||||
return JIM_ERR;
|
||||
|
||||
for (ifa = ifp; ifa; ifa = ifa->ifa_next) {
|
||||
char ip[200];
|
||||
socklen_t salen;
|
||||
|
||||
if (ifa->ifa_addr->sa_family == AF_INET)
|
||||
salen = sizeof(struct sockaddr_in);
|
||||
else if (ifa->ifa_addr->sa_family == AF_INET6)
|
||||
salen = sizeof(struct sockaddr_in6);
|
||||
else
|
||||
continue;
|
||||
|
||||
if (getnameinfo(ifa->ifa_addr, salen, ip, sizeof(ip), NULL, 0,
|
||||
NI_NUMERICHOST) < 0)
|
||||
continue;
|
||||
|
||||
Jim_AppendString(interp, tclOutput, ip, strlen(ip));
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
freeifaddrs(ifp);
|
||||
#else
|
||||
Jim_Obj *tclOutput = Jim_NewStringObj(interp, "fixme!!!", 0);
|
||||
LOG_ERROR("NOT IMPLEMENTED!!!");
|
||||
#endif
|
||||
Jim_SetResult(interp, tclOutput);
|
||||
|
||||
return JIM_OK;
|
||||
}
|
||||
|
||||
#ifdef HAVE_SYS_IOCTL_H
|
||||
#ifdef SIOCGIFHWADDR
|
||||
/* not so pretty code to fish out eth0 mac address */
|
||||
static int ioutil_Jim_Command_mac(Jim_Interp *interp, int argc,
|
||||
Jim_Obj *const *argv)
|
||||
{
|
||||
struct ifreq *ifr, *ifend;
|
||||
struct ifreq ifreq;
|
||||
struct ifconf ifc;
|
||||
struct ifreq ifs[5];
|
||||
int SockFD;
|
||||
|
||||
SockFD = socket(AF_INET, SOCK_DGRAM, 0);
|
||||
if (SockFD < 0)
|
||||
return JIM_ERR;
|
||||
|
||||
ifc.ifc_len = sizeof(ifs);
|
||||
ifc.ifc_req = ifs;
|
||||
if (ioctl(SockFD, SIOCGIFCONF, &ifc) < 0) {
|
||||
close(SockFD);
|
||||
return JIM_ERR;
|
||||
}
|
||||
|
||||
ifend = ifs + (ifc.ifc_len / sizeof(struct ifreq));
|
||||
for (ifr = ifc.ifc_req; ifr < ifend; ifr++) {
|
||||
/* if (ifr->ifr_addr.sa_family == AF_INET) */
|
||||
{
|
||||
if (strcmp("eth0", ifr->ifr_name) != 0)
|
||||
continue;
|
||||
strncpy(ifreq.ifr_name, ifr->ifr_name, sizeof(ifreq.ifr_name) - 1);
|
||||
if (ioctl(SockFD, SIOCGIFHWADDR, &ifreq) < 0) {
|
||||
close(SockFD);
|
||||
return JIM_ERR;
|
||||
}
|
||||
|
||||
close(SockFD);
|
||||
|
||||
Jim_Obj *tclOutput = Jim_NewStringObj(interp, "", 0);
|
||||
|
||||
char buffer[256];
|
||||
sprintf(buffer, "%02x-%02x-%02x-%02x-%02x-%02x",
|
||||
ifreq.ifr_hwaddr.sa_data[0]&0xff,
|
||||
ifreq.ifr_hwaddr.sa_data[1]&0xff,
|
||||
ifreq.ifr_hwaddr.sa_data[2]&0xff,
|
||||
ifreq.ifr_hwaddr.sa_data[3]&0xff,
|
||||
ifreq.ifr_hwaddr.sa_data[4]&0xff,
|
||||
ifreq.ifr_hwaddr.sa_data[5]&0xff);
|
||||
|
||||
Jim_AppendString(interp, tclOutput, buffer, strlen(buffer));
|
||||
|
||||
Jim_SetResult(interp, tclOutput);
|
||||
|
||||
return JIM_OK;
|
||||
}
|
||||
}
|
||||
close(SockFD);
|
||||
|
||||
return JIM_ERR;
|
||||
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
static const struct command_registration ioutil_command_handlers[] = {
|
||||
{
|
||||
.name = "cat",
|
||||
.handler = handle_cat_command,
|
||||
.mode = COMMAND_ANY,
|
||||
.help = "display text file content",
|
||||
.usage = "file_name",
|
||||
},
|
||||
{
|
||||
.name = "trunc",
|
||||
.handler = handle_trunc_command,
|
||||
.mode = COMMAND_ANY,
|
||||
.help = "truncate a file to zero length",
|
||||
.usage = "file_name",
|
||||
},
|
||||
{
|
||||
.name = "cp",
|
||||
.handler = handle_cp_command,
|
||||
.mode = COMMAND_ANY,
|
||||
.help = "copy a file",
|
||||
.usage = "src_file_name dst_file_name",
|
||||
},
|
||||
{
|
||||
.name = "append_file",
|
||||
.handler = handle_append_command,
|
||||
.mode = COMMAND_ANY,
|
||||
.help = "append a variable number of strings to a file",
|
||||
.usage = "file_name [<string1>, [<string2>, ...]]",
|
||||
},
|
||||
#ifdef HAVE_MALLOC_H
|
||||
{
|
||||
.name = "meminfo",
|
||||
.handler = handle_meminfo_command,
|
||||
.mode = COMMAND_ANY,
|
||||
.help = "display free heap space",
|
||||
.usage = "",
|
||||
},
|
||||
#endif
|
||||
{
|
||||
.name = "rm",
|
||||
.mode = COMMAND_ANY,
|
||||
.handler = handle_rm_command,
|
||||
.help = "remove a directory or file",
|
||||
.usage = "file_name",
|
||||
},
|
||||
|
||||
/*
|
||||
* Peek and poke are security holes -- they manipulate
|
||||
* server-internal addresses.
|
||||
*/
|
||||
|
||||
/* jim handlers */
|
||||
{
|
||||
.name = "peek",
|
||||
.mode = COMMAND_ANY,
|
||||
.jim_handler = ioutil_Jim_Command_peek,
|
||||
.help = "peek at a memory address",
|
||||
.usage = "address",
|
||||
},
|
||||
{
|
||||
.name = "poke",
|
||||
.mode = COMMAND_ANY,
|
||||
.jim_handler = ioutil_Jim_Command_poke,
|
||||
.help = "poke at a memory address",
|
||||
.usage = "address value",
|
||||
},
|
||||
{
|
||||
.name = "ls",
|
||||
.mode = COMMAND_ANY,
|
||||
.jim_handler = ioutil_Jim_Command_ls,
|
||||
.help = "show a listing of files",
|
||||
.usage = "dirname",
|
||||
},
|
||||
#ifdef HAVE_SYS_IOCTL_H
|
||||
#ifdef SIOCGIFHWADDR
|
||||
{
|
||||
.name = "mac",
|
||||
.mode = COMMAND_ANY,
|
||||
.jim_handler = ioutil_Jim_Command_mac,
|
||||
.help = "show MAC address",
|
||||
},
|
||||
#endif
|
||||
#endif
|
||||
{
|
||||
.name = "ip",
|
||||
.jim_handler = ioutil_Jim_Command_ip,
|
||||
.mode = COMMAND_ANY,
|
||||
.help = "show IP address",
|
||||
},
|
||||
COMMAND_REGISTRATION_DONE
|
||||
};
|
||||
|
||||
int ioutil_init(struct command_context *cmd_ctx)
|
||||
{
|
||||
return register_commands(cmd_ctx, NULL, ioutil_command_handlers);
|
||||
}
|
|
@ -1,25 +0,0 @@
|
|||
/***************************************************************************
|
||||
* Copyright (C) 2009 Zachary T Welch <zw@superlucidity.net> *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation; either version 2 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
* This program is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License *
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef OPENOCD_HELPER_IOUTIL_H
|
||||
#define OPENOCD_HELPER_IOUTIL_H
|
||||
|
||||
struct command_context;
|
||||
|
||||
int ioutil_init(struct command_context *cmd_ctx);
|
||||
|
||||
#endif /* OPENOCD_HELPER_IOUTIL_H */
|
|
@ -1,28 +0,0 @@
|
|||
/***************************************************************************
|
||||
* Copyright (C) 2009 Zachary T Welch <zw@superlucidity.net> *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation; either version 2 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
* This program is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License *
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
|
||||
***************************************************************************/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
#include "ioutil.h"
|
||||
#include "log.h"
|
||||
|
||||
int ioutil_init(struct command_context *cmd_ctx)
|
||||
{
|
||||
LOG_DEBUG("libocdhelper was built without I/O utility support");
|
||||
return ERROR_OK;
|
||||
}
|
|
@ -55,7 +55,6 @@ static const struct option long_options[] = {
|
|||
{"search", required_argument, 0, 's'},
|
||||
{"log_output", required_argument, 0, 'l'},
|
||||
{"command", required_argument, 0, 'c'},
|
||||
{"pipe", no_argument, 0, 'p'},
|
||||
{0, 0, 0, 0}
|
||||
};
|
||||
|
||||
|
@ -282,7 +281,7 @@ int parse_cmdline_args(struct command_context *cmd_ctx, int argc, char *argv[])
|
|||
/* getopt_long stores the option index here. */
|
||||
int option_index = 0;
|
||||
|
||||
c = getopt_long(argc, argv, "hvd::l:f:s:c:p", long_options, &option_index);
|
||||
c = getopt_long(argc, argv, "hvd::l:f:s:c:", long_options, &option_index);
|
||||
|
||||
/* Detect the end of the options. */
|
||||
if (c == -1)
|
||||
|
@ -322,13 +321,6 @@ int parse_cmdline_args(struct command_context *cmd_ctx, int argc, char *argv[])
|
|||
if (optarg)
|
||||
add_config_command(optarg);
|
||||
break;
|
||||
case 'p':
|
||||
/* to replicate the old syntax this needs to be synchronous
|
||||
* otherwise the gdb stdin will overflow with the warning message */
|
||||
command_run_line(cmd_ctx, "gdb_port pipe; log_output openocd.log");
|
||||
LOG_WARNING("deprecated option: -p/--pipe. Use '-c \"gdb_port pipe; "
|
||||
"log_output openocd.log\"' instead.");
|
||||
break;
|
||||
default: /* '?' */
|
||||
/* getopt will emit an error message, all we have to do is bail. */
|
||||
return ERROR_FAIL;
|
||||
|
|
|
@ -3,33 +3,6 @@ noinst_LTLIBRARIES += %D%/libjtag.la
|
|||
JTAG_SRCS = %D%/commands.c
|
||||
%C%_libjtag_la_LIBADD =
|
||||
|
||||
BUILT_SOURCES += %D%/minidriver_imp.h
|
||||
CLEANFILES += %D%/minidriver_imp.h
|
||||
|
||||
if MINIDRIVER
|
||||
|
||||
if ZY1000
|
||||
JTAG_SRCS += %D%/zy1000/zy1000.c
|
||||
JTAG_MINIDRIVER_DIR = %D%/zy1000
|
||||
endif
|
||||
if MINIDRIVER_DUMMY
|
||||
JTAG_SRCS += %D%/minidummy/minidummy.c
|
||||
JTAG_MINIDRIVER_DIR = %D%/minidummy
|
||||
endif
|
||||
|
||||
MINIDRIVER_IMP_DIR = %D%/minidriver
|
||||
|
||||
%D%/jtag_minidriver.h: $(JTAG_MINIDRIVER_DIR)/jtag_minidriver.h
|
||||
cp $< $@
|
||||
|
||||
BUILT_SOURCES += %D%/jtag_minidriver.h
|
||||
|
||||
CLEANFILES += %D%/jtag_minidriver.h
|
||||
|
||||
else
|
||||
|
||||
MINIDRIVER_IMP_DIR = %D%/drivers
|
||||
|
||||
if HLADAPTER
|
||||
include %D%/hla/Makefile.am
|
||||
%C%_libjtag_la_LIBADD += $(top_builddir)/%D%/hla/libocdhla.la
|
||||
|
@ -43,13 +16,6 @@ endif
|
|||
include %D%/drivers/Makefile.am
|
||||
%C%_libjtag_la_LIBADD += $(top_builddir)/%D%/drivers/libocdjtagdrivers.la
|
||||
|
||||
endif
|
||||
# endif // MINIDRIVER
|
||||
|
||||
%D%/minidriver_imp.h: $(MINIDRIVER_IMP_DIR)/minidriver_imp.h
|
||||
cp $< $@
|
||||
|
||||
|
||||
%C%_libjtag_la_SOURCES = \
|
||||
%D%/adapter.c \
|
||||
%D%/core.c \
|
||||
|
@ -63,8 +29,6 @@ endif
|
|||
%D%/interfaces.h \
|
||||
%D%/minidriver.h \
|
||||
%D%/jtag.h \
|
||||
%D%/minidriver/minidriver_imp.h \
|
||||
%D%/minidummy/jtag_minidriver.h \
|
||||
%D%/swd.h \
|
||||
%D%/swim.h \
|
||||
%D%/tcl.h \
|
||||
|
|
|
@ -493,7 +493,6 @@ COMMAND_HANDLER(handle_adapter_reset_de_assert)
|
|||
(srst == VALUE_DEASSERT) ? SRST_DEASSERT : SRST_ASSERT);
|
||||
}
|
||||
|
||||
#ifndef HAVE_JTAG_MINIDRIVER_H
|
||||
#ifdef HAVE_LIBUSB_GET_PORT_NUMBERS
|
||||
COMMAND_HANDLER(handle_usb_location_command)
|
||||
{
|
||||
|
@ -518,7 +517,6 @@ static const struct command_registration adapter_usb_command_handlers[] = {
|
|||
#endif /* HAVE_LIBUSB_GET_PORT_NUMBERS */
|
||||
COMMAND_REGISTRATION_DONE
|
||||
};
|
||||
#endif /* MINIDRIVER */
|
||||
|
||||
static const struct command_registration adapter_srst_command_handlers[] = {
|
||||
{
|
||||
|
@ -584,7 +582,6 @@ static const struct command_registration adapter_command_handlers[] = {
|
|||
.help = "Declare transports the adapter supports.",
|
||||
.usage = "transport ... ",
|
||||
},
|
||||
#ifndef HAVE_JTAG_MINIDRIVER_H
|
||||
{
|
||||
.name = "usb",
|
||||
.mode = COMMAND_ANY,
|
||||
|
@ -592,7 +589,6 @@ static const struct command_registration adapter_command_handlers[] = {
|
|||
.usage = "",
|
||||
.chain = adapter_usb_command_handlers,
|
||||
},
|
||||
#endif /* MINIDRIVER */
|
||||
{
|
||||
.name = "assert",
|
||||
.handler = handle_adapter_reset_de_assert,
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
noinst_LTLIBRARIES += %D%/libocdaice.la
|
||||
|
||||
%C%_libocdaice_la_CPPFLAGS = -I$(top_srcdir)/src/jtag/drivers $(AM_CPPFLAGS) $(LIBUSB1_CFLAGS) $(LIBUSB0_CFLAGS)
|
||||
%C%_libocdaice_la_CPPFLAGS = -I$(top_srcdir)/src/jtag/drivers $(AM_CPPFLAGS) $(LIBUSB1_CFLAGS)
|
||||
%C%_libocdaice_la_SOURCES = \
|
||||
%D%/aice_transport.c \
|
||||
%D%/aice_interface.c \
|
||||
|
|
|
@ -427,7 +427,6 @@ static void jtag_add_scan_check(struct jtag_tap *active, void (*jtag_add_scan)(
|
|||
|
||||
for (int i = 0; i < in_num_fields; i++) {
|
||||
if ((in_fields[i].check_value != NULL) && (in_fields[i].in_value != NULL)) {
|
||||
/* this is synchronous for a minidriver */
|
||||
jtag_add_callback4(jtag_check_value_mask_callback,
|
||||
(jtag_callback_data_t)in_fields[i].in_value,
|
||||
(jtag_callback_data_t)in_fields[i].check_value,
|
||||
|
@ -954,12 +953,6 @@ int default_interface_jtag_execute_queue(void)
|
|||
|
||||
int result = jtag->jtag_ops->execute_queue();
|
||||
|
||||
#if !HAVE_JTAG_MINIDRIVER_H
|
||||
/* Only build this if we use a regular driver with a command queue.
|
||||
* Otherwise jtag_command_queue won't be found at compile/link time. Its
|
||||
* definition is in jtag/commands.c, which is only built/linked by
|
||||
* jtag/Makefile.am if MINIDRIVER_DUMMY || !MINIDRIVER, but those variables
|
||||
* aren't accessible here. Use HAVE_JTAG_MINIDRIVER_H */
|
||||
struct jtag_command *cmd = jtag_command_queue;
|
||||
while (debug_level >= LOG_LVL_DEBUG_IO && cmd) {
|
||||
switch (cmd->type) {
|
||||
|
@ -1018,7 +1011,6 @@ int default_interface_jtag_execute_queue(void)
|
|||
}
|
||||
cmd = cmd->next;
|
||||
}
|
||||
#endif
|
||||
|
||||
return result;
|
||||
}
|
||||
|
|
|
@ -27,12 +27,6 @@ DRIVERFILES += %D%/libusb_helper.c
|
|||
%C%_libocdjtagdrivers_la_LIBADD += $(LIBUSB1_LIBS)
|
||||
endif
|
||||
|
||||
if USE_LIBUSB0
|
||||
DRIVERFILES += %D%/usb_common.c
|
||||
%C%_libocdjtagdrivers_la_CPPFLAGS += $(LIBUSB0_CFLAGS)
|
||||
%C%_libocdjtagdrivers_la_LIBADD += $(LIBUSB0_LIBS)
|
||||
endif
|
||||
|
||||
if USE_LIBFTDI
|
||||
%C%_libocdjtagdrivers_la_CPPFLAGS += $(LIBFTDI_CFLAGS)
|
||||
%C%_libocdjtagdrivers_la_LIBADD += $(LIBFTDI_LIBS)
|
||||
|
@ -203,7 +197,6 @@ DRIVERHEADERS = \
|
|||
%D%/rlink_dtc_cmd.h \
|
||||
%D%/rlink_ep1_cmd.h \
|
||||
%D%/rlink_st7.h \
|
||||
%D%/usb_common.h \
|
||||
%D%/versaloon/usbtoxxx/usbtoxxx.h \
|
||||
%D%/versaloon/usbtoxxx/usbtoxxx_internal.h \
|
||||
%D%/versaloon/versaloon.h \
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
#include <jtag/commands.h>
|
||||
#include "helper/system.h"
|
||||
#include <usb.h>
|
||||
#include "usb_common.h"
|
||||
#include "libusb_helper.h"
|
||||
|
||||
#define USB_VID 0x15ba
|
||||
#define USB_PID 0x001e
|
||||
|
@ -76,7 +76,7 @@ static void armjtagew_tap_append_scan(int length, uint8_t *buffer, struct scan_c
|
|||
|
||||
/* ARM-JTAG-EW lowlevel functions */
|
||||
struct armjtagew {
|
||||
struct usb_dev_handle *usb_handle;
|
||||
struct libusb_device_handle *usb_handle;
|
||||
};
|
||||
|
||||
static struct armjtagew *armjtagew_usb_open(void);
|
||||
|
@ -685,35 +685,37 @@ static int armjtagew_tap_execute(void)
|
|||
|
||||
static struct armjtagew *armjtagew_usb_open(void)
|
||||
{
|
||||
usb_init();
|
||||
|
||||
const uint16_t vids[] = { USB_VID, 0 };
|
||||
const uint16_t pids[] = { USB_PID, 0 };
|
||||
struct usb_dev_handle *dev;
|
||||
if (jtag_usb_open(vids, pids, &dev) != ERROR_OK)
|
||||
struct libusb_device_handle *dev;
|
||||
|
||||
if (jtag_libusb_open(vids, pids, NULL, &dev, NULL) != ERROR_OK)
|
||||
return NULL;
|
||||
|
||||
struct armjtagew *result = malloc(sizeof(struct armjtagew));
|
||||
result->usb_handle = dev;
|
||||
|
||||
#if 0
|
||||
/* usb_set_configuration required under win32 */
|
||||
usb_set_configuration(dev, dev->config[0].bConfigurationValue);
|
||||
/* libusb_set_configuration required under win32 */
|
||||
struct libusb_config_descriptor *config;
|
||||
struct libusb_device *usb_dev = libusb_get_device(dev);
|
||||
libusb_get_config_descriptor(usb_dev, 0, &config);
|
||||
libusb_set_configuration(dev, config->bConfigurationValue);
|
||||
#endif
|
||||
usb_claim_interface(dev, 0);
|
||||
libusb_claim_interface(dev, 0);
|
||||
#if 0
|
||||
/*
|
||||
* This makes problems under Mac OS X. And is not needed
|
||||
* under Windows. Hopefully this will not break a linux build
|
||||
*/
|
||||
usb_set_altinterface(dev, 0);
|
||||
libusb_set_interface_alt_setting(dev, 0, 0);
|
||||
#endif
|
||||
return result;
|
||||
}
|
||||
|
||||
static void armjtagew_usb_close(struct armjtagew *armjtagew)
|
||||
{
|
||||
usb_close(armjtagew->usb_handle);
|
||||
libusb_close(armjtagew->usb_handle);
|
||||
free(armjtagew);
|
||||
}
|
||||
|
||||
|
@ -726,13 +728,13 @@ static int armjtagew_usb_message(struct armjtagew *armjtagew, int out_length, in
|
|||
if (result == out_length) {
|
||||
result = armjtagew_usb_read(armjtagew, in_length);
|
||||
if (result != in_length) {
|
||||
LOG_ERROR("usb_bulk_read failed (requested=%d, result=%d)",
|
||||
LOG_ERROR("jtag_libusb_bulk_read failed (requested=%d, result=%d)",
|
||||
in_length,
|
||||
result);
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
LOG_ERROR("usb_bulk_write failed (requested=%d, result=%d)", out_length, result);
|
||||
LOG_ERROR("jtag_libusb_bulk_write failed (requested=%d, result=%d)", out_length, result);
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
|
@ -742,6 +744,7 @@ static int armjtagew_usb_message(struct armjtagew *armjtagew, int out_length, in
|
|||
static int armjtagew_usb_write(struct armjtagew *armjtagew, int out_length)
|
||||
{
|
||||
int result;
|
||||
int transferred;
|
||||
|
||||
if (out_length > ARMJTAGEW_OUT_BUFFER_SIZE) {
|
||||
LOG_ERROR("armjtagew_write illegal out_length=%d (max=%d)",
|
||||
|
@ -750,29 +753,34 @@ static int armjtagew_usb_write(struct armjtagew *armjtagew, int out_length)
|
|||
return -1;
|
||||
}
|
||||
|
||||
result = usb_bulk_write(armjtagew->usb_handle, ARMJTAGEW_EPT_BULK_OUT,
|
||||
(char *)usb_out_buffer, out_length, ARMJTAGEW_USB_TIMEOUT);
|
||||
result = jtag_libusb_bulk_write(armjtagew->usb_handle, ARMJTAGEW_EPT_BULK_OUT,
|
||||
(char *)usb_out_buffer, out_length, ARMJTAGEW_USB_TIMEOUT, &transferred);
|
||||
|
||||
LOG_DEBUG_IO("armjtagew_usb_write, out_length = %d, result = %d", out_length, result);
|
||||
|
||||
#ifdef _DEBUG_USB_COMMS_
|
||||
armjtagew_debug_buffer(usb_out_buffer, out_length);
|
||||
#endif
|
||||
return result;
|
||||
if (result != ERROR_OK)
|
||||
return -1;
|
||||
return transferred;
|
||||
}
|
||||
|
||||
/* Read data from USB into in_buffer. */
|
||||
static int armjtagew_usb_read(struct armjtagew *armjtagew, int exp_in_length)
|
||||
{
|
||||
int result = usb_bulk_read(armjtagew->usb_handle, ARMJTAGEW_EPT_BULK_IN,
|
||||
(char *)usb_in_buffer, exp_in_length, ARMJTAGEW_USB_TIMEOUT);
|
||||
int transferred;
|
||||
int result = jtag_libusb_bulk_read(armjtagew->usb_handle, ARMJTAGEW_EPT_BULK_IN,
|
||||
(char *)usb_in_buffer, exp_in_length, ARMJTAGEW_USB_TIMEOUT, &transferred);
|
||||
|
||||
LOG_DEBUG_IO("armjtagew_usb_read, result = %d", result);
|
||||
|
||||
#ifdef _DEBUG_USB_COMMS_
|
||||
armjtagew_debug_buffer(usb_in_buffer, result);
|
||||
#endif
|
||||
return result;
|
||||
if (result != ERROR_OK)
|
||||
return -1;
|
||||
return transferred;
|
||||
}
|
||||
|
||||
#ifdef _DEBUG_USB_COMMS_
|
||||
|
|
|
@ -170,10 +170,6 @@ static const char * const info_caps_str[] = {
|
|||
"JTAG Supported"
|
||||
};
|
||||
|
||||
/* max clock speed (kHz) */
|
||||
#define DAP_MAX_CLOCK 5000
|
||||
|
||||
|
||||
struct pending_transfer_result {
|
||||
uint8_t cmd;
|
||||
uint32_t data;
|
||||
|
@ -230,16 +226,12 @@ static int cmsis_dap_open(void)
|
|||
{
|
||||
const struct cmsis_dap_backend *backend = NULL;
|
||||
|
||||
struct cmsis_dap *dap = malloc(sizeof(struct cmsis_dap));
|
||||
struct cmsis_dap *dap = calloc(1, sizeof(struct cmsis_dap));
|
||||
if (dap == NULL) {
|
||||
LOG_ERROR("unable to allocate memory");
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
|
||||
dap->caps = 0;
|
||||
dap->mode = 0;
|
||||
dap->packet_size = 0; /* initialized by backend */
|
||||
|
||||
if (cmsis_dap_backend >= 0) {
|
||||
/* Use forced backend */
|
||||
backend = cmsis_dap_backends[cmsis_dap_backend];
|
||||
|
@ -262,17 +254,7 @@ static int cmsis_dap_open(void)
|
|||
return ERROR_FAIL;
|
||||
}
|
||||
|
||||
assert(dap->packet_size > 0);
|
||||
|
||||
dap->backend = backend;
|
||||
dap->packet_buffer = malloc(dap->packet_size);
|
||||
|
||||
if (dap->packet_buffer == NULL) {
|
||||
LOG_ERROR("unable to allocate memory");
|
||||
dap->backend->close(dap);
|
||||
free(dap);
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
|
||||
cmsis_dap_handle = dap;
|
||||
|
||||
|
@ -326,17 +308,14 @@ static int cmsis_dap_xfer(struct cmsis_dap *dap, int txlen)
|
|||
static int cmsis_dap_cmd_DAP_SWJ_Pins(uint8_t pins, uint8_t mask, uint32_t delay, uint8_t *input)
|
||||
{
|
||||
int retval;
|
||||
uint8_t *buffer = cmsis_dap_handle->packet_buffer;
|
||||
uint8_t *command = cmsis_dap_handle->command;
|
||||
|
||||
buffer[0] = 0; /* report number */
|
||||
buffer[1] = CMD_DAP_SWJ_PINS;
|
||||
buffer[2] = pins;
|
||||
buffer[3] = mask;
|
||||
buffer[4] = delay & 0xff;
|
||||
buffer[5] = (delay >> 8) & 0xff;
|
||||
buffer[6] = (delay >> 16) & 0xff;
|
||||
buffer[7] = (delay >> 24) & 0xff;
|
||||
retval = cmsis_dap_xfer(cmsis_dap_handle, 8);
|
||||
command[0] = CMD_DAP_SWJ_PINS;
|
||||
command[1] = pins;
|
||||
command[2] = mask;
|
||||
h_u32_to_le(&command[3], delay);
|
||||
|
||||
retval = cmsis_dap_xfer(cmsis_dap_handle, 7);
|
||||
|
||||
if (retval != ERROR_OK) {
|
||||
LOG_ERROR("CMSIS-DAP command CMD_DAP_SWJ_PINS failed.");
|
||||
|
@ -344,7 +323,7 @@ static int cmsis_dap_cmd_DAP_SWJ_Pins(uint8_t pins, uint8_t mask, uint32_t delay
|
|||
}
|
||||
|
||||
if (input)
|
||||
*input = buffer[1];
|
||||
*input = cmsis_dap_handle->response[1];
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
@ -352,19 +331,17 @@ static int cmsis_dap_cmd_DAP_SWJ_Pins(uint8_t pins, uint8_t mask, uint32_t delay
|
|||
static int cmsis_dap_cmd_DAP_SWJ_Clock(uint32_t swj_clock)
|
||||
{
|
||||
int retval;
|
||||
uint8_t *buffer = cmsis_dap_handle->packet_buffer;
|
||||
uint8_t *command = cmsis_dap_handle->command;
|
||||
|
||||
/* set clock in Hz */
|
||||
swj_clock *= 1000;
|
||||
buffer[0] = 0; /* report number */
|
||||
buffer[1] = CMD_DAP_SWJ_CLOCK;
|
||||
buffer[2] = swj_clock & 0xff;
|
||||
buffer[3] = (swj_clock >> 8) & 0xff;
|
||||
buffer[4] = (swj_clock >> 16) & 0xff;
|
||||
buffer[5] = (swj_clock >> 24) & 0xff;
|
||||
retval = cmsis_dap_xfer(cmsis_dap_handle, 6);
|
||||
|
||||
if (retval != ERROR_OK || buffer[1] != DAP_OK) {
|
||||
command[0] = CMD_DAP_SWJ_CLOCK;
|
||||
h_u32_to_le(&command[1], swj_clock);
|
||||
|
||||
retval = cmsis_dap_xfer(cmsis_dap_handle, 5);
|
||||
|
||||
if (retval != ERROR_OK || cmsis_dap_handle->response[1] != DAP_OK) {
|
||||
LOG_ERROR("CMSIS-DAP command CMD_DAP_SWJ_CLOCK failed.");
|
||||
return ERROR_JTAG_DEVICE_ERROR;
|
||||
}
|
||||
|
@ -376,7 +353,7 @@ static int cmsis_dap_cmd_DAP_SWJ_Clock(uint32_t swj_clock)
|
|||
static int cmsis_dap_cmd_DAP_SWJ_Sequence(uint8_t s_len, const uint8_t *sequence)
|
||||
{
|
||||
int retval;
|
||||
uint8_t *buffer = cmsis_dap_handle->packet_buffer;
|
||||
uint8_t *command = cmsis_dap_handle->command;
|
||||
|
||||
#ifdef CMSIS_DAP_JTAG_DEBUG
|
||||
LOG_DEBUG("cmsis-dap TMS sequence: len=%d", s_len);
|
||||
|
@ -386,14 +363,12 @@ static int cmsis_dap_cmd_DAP_SWJ_Sequence(uint8_t s_len, const uint8_t *sequence
|
|||
printf("\n");
|
||||
#endif
|
||||
|
||||
buffer[0] = 0; /* report number */
|
||||
buffer[1] = CMD_DAP_SWJ_SEQ;
|
||||
buffer[2] = s_len;
|
||||
bit_copy(&buffer[3], 0, sequence, 0, s_len);
|
||||
command[0] = CMD_DAP_SWJ_SEQ;
|
||||
command[1] = s_len;
|
||||
bit_copy(&command[2], 0, sequence, 0, s_len);
|
||||
|
||||
retval = cmsis_dap_xfer(cmsis_dap_handle, DIV_ROUND_UP(s_len, 8) + 3);
|
||||
|
||||
if (retval != ERROR_OK || buffer[1] != DAP_OK)
|
||||
retval = cmsis_dap_xfer(cmsis_dap_handle, 2 + DIV_ROUND_UP(s_len, 8));
|
||||
if (retval != ERROR_OK || cmsis_dap_handle->response[1] != DAP_OK)
|
||||
return ERROR_FAIL;
|
||||
|
||||
return ERROR_OK;
|
||||
|
@ -402,19 +377,19 @@ static int cmsis_dap_cmd_DAP_SWJ_Sequence(uint8_t s_len, const uint8_t *sequence
|
|||
static int cmsis_dap_cmd_DAP_Info(uint8_t info, uint8_t **data)
|
||||
{
|
||||
int retval;
|
||||
uint8_t *buffer = cmsis_dap_handle->packet_buffer;
|
||||
uint8_t *command = cmsis_dap_handle->command;
|
||||
|
||||
buffer[0] = 0; /* report number */
|
||||
buffer[1] = CMD_DAP_INFO;
|
||||
buffer[2] = info;
|
||||
retval = cmsis_dap_xfer(cmsis_dap_handle, 3);
|
||||
command[0] = CMD_DAP_INFO;
|
||||
command[1] = info;
|
||||
|
||||
retval = cmsis_dap_xfer(cmsis_dap_handle, 2);
|
||||
|
||||
if (retval != ERROR_OK) {
|
||||
LOG_ERROR("CMSIS-DAP command CMD_INFO failed.");
|
||||
return ERROR_JTAG_DEVICE_ERROR;
|
||||
}
|
||||
|
||||
*data = &(buffer[1]);
|
||||
*data = &cmsis_dap_handle->response[1];
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
@ -422,15 +397,15 @@ static int cmsis_dap_cmd_DAP_Info(uint8_t info, uint8_t **data)
|
|||
static int cmsis_dap_cmd_DAP_LED(uint8_t led, uint8_t state)
|
||||
{
|
||||
int retval;
|
||||
uint8_t *buffer = cmsis_dap_handle->packet_buffer;
|
||||
uint8_t *command = cmsis_dap_handle->command;
|
||||
|
||||
buffer[0] = 0; /* report number */
|
||||
buffer[1] = CMD_DAP_LED;
|
||||
buffer[2] = led;
|
||||
buffer[3] = state;
|
||||
retval = cmsis_dap_xfer(cmsis_dap_handle, 4);
|
||||
command[0] = CMD_DAP_LED;
|
||||
command[1] = led;
|
||||
command[2] = state;
|
||||
|
||||
if (retval != ERROR_OK || buffer[1] != 0x00) {
|
||||
retval = cmsis_dap_xfer(cmsis_dap_handle, 3);
|
||||
|
||||
if (retval != ERROR_OK || cmsis_dap_handle->response[1] != DAP_OK) {
|
||||
LOG_ERROR("CMSIS-DAP command CMD_LED failed.");
|
||||
return ERROR_JTAG_DEVICE_ERROR;
|
||||
}
|
||||
|
@ -441,19 +416,19 @@ static int cmsis_dap_cmd_DAP_LED(uint8_t led, uint8_t state)
|
|||
static int cmsis_dap_cmd_DAP_Connect(uint8_t mode)
|
||||
{
|
||||
int retval;
|
||||
uint8_t *buffer = cmsis_dap_handle->packet_buffer;
|
||||
uint8_t *command = cmsis_dap_handle->command;
|
||||
|
||||
buffer[0] = 0; /* report number */
|
||||
buffer[1] = CMD_DAP_CONNECT;
|
||||
buffer[2] = mode;
|
||||
retval = cmsis_dap_xfer(cmsis_dap_handle, 3);
|
||||
command[0] = CMD_DAP_CONNECT;
|
||||
command[1] = mode;
|
||||
|
||||
retval = cmsis_dap_xfer(cmsis_dap_handle, 2);
|
||||
|
||||
if (retval != ERROR_OK) {
|
||||
LOG_ERROR("CMSIS-DAP command CMD_CONNECT failed.");
|
||||
return ERROR_JTAG_DEVICE_ERROR;
|
||||
}
|
||||
|
||||
if (buffer[1] != mode) {
|
||||
if (cmsis_dap_handle->response[1] != mode) {
|
||||
LOG_ERROR("CMSIS-DAP failed to connect in mode (%d)", mode);
|
||||
return ERROR_JTAG_DEVICE_ERROR;
|
||||
}
|
||||
|
@ -464,13 +439,13 @@ static int cmsis_dap_cmd_DAP_Connect(uint8_t mode)
|
|||
static int cmsis_dap_cmd_DAP_Disconnect(void)
|
||||
{
|
||||
int retval;
|
||||
uint8_t *buffer = cmsis_dap_handle->packet_buffer;
|
||||
uint8_t *command = cmsis_dap_handle->command;
|
||||
|
||||
buffer[0] = 0; /* report number */
|
||||
buffer[1] = CMD_DAP_DISCONNECT;
|
||||
retval = cmsis_dap_xfer(cmsis_dap_handle, 2);
|
||||
command[0] = CMD_DAP_DISCONNECT;
|
||||
|
||||
if (retval != ERROR_OK || buffer[1] != DAP_OK) {
|
||||
retval = cmsis_dap_xfer(cmsis_dap_handle, 1);
|
||||
|
||||
if (retval != ERROR_OK || cmsis_dap_handle->response[1] != DAP_OK) {
|
||||
LOG_ERROR("CMSIS-DAP command CMD_DISCONNECT failed.");
|
||||
return ERROR_JTAG_DEVICE_ERROR;
|
||||
}
|
||||
|
@ -481,18 +456,16 @@ static int cmsis_dap_cmd_DAP_Disconnect(void)
|
|||
static int cmsis_dap_cmd_DAP_TFER_Configure(uint8_t idle, uint16_t retry_count, uint16_t match_retry)
|
||||
{
|
||||
int retval;
|
||||
uint8_t *buffer = cmsis_dap_handle->packet_buffer;
|
||||
uint8_t *command = cmsis_dap_handle->command;
|
||||
|
||||
buffer[0] = 0; /* report number */
|
||||
buffer[1] = CMD_DAP_TFER_CONFIGURE;
|
||||
buffer[2] = idle;
|
||||
buffer[3] = retry_count & 0xff;
|
||||
buffer[4] = (retry_count >> 8) & 0xff;
|
||||
buffer[5] = match_retry & 0xff;
|
||||
buffer[6] = (match_retry >> 8) & 0xff;
|
||||
retval = cmsis_dap_xfer(cmsis_dap_handle, 7);
|
||||
command[0] = CMD_DAP_TFER_CONFIGURE;
|
||||
command[1] = idle;
|
||||
h_u16_to_le(&command[2], retry_count);
|
||||
h_u16_to_le(&command[4], match_retry);
|
||||
|
||||
if (retval != ERROR_OK || buffer[1] != DAP_OK) {
|
||||
retval = cmsis_dap_xfer(cmsis_dap_handle, 6);
|
||||
|
||||
if (retval != ERROR_OK || cmsis_dap_handle->response[1] != DAP_OK) {
|
||||
LOG_ERROR("CMSIS-DAP command CMD_TFER_Configure failed.");
|
||||
return ERROR_JTAG_DEVICE_ERROR;
|
||||
}
|
||||
|
@ -503,14 +476,14 @@ static int cmsis_dap_cmd_DAP_TFER_Configure(uint8_t idle, uint16_t retry_count,
|
|||
static int cmsis_dap_cmd_DAP_SWD_Configure(uint8_t cfg)
|
||||
{
|
||||
int retval;
|
||||
uint8_t *buffer = cmsis_dap_handle->packet_buffer;
|
||||
uint8_t *command = cmsis_dap_handle->command;
|
||||
|
||||
buffer[0] = 0; /* report number */
|
||||
buffer[1] = CMD_DAP_SWD_CONFIGURE;
|
||||
buffer[2] = cfg;
|
||||
retval = cmsis_dap_xfer(cmsis_dap_handle, 3);
|
||||
command[0] = CMD_DAP_SWD_CONFIGURE;
|
||||
command[1] = cfg;
|
||||
|
||||
if (retval != ERROR_OK || buffer[1] != DAP_OK) {
|
||||
retval = cmsis_dap_xfer(cmsis_dap_handle, 2);
|
||||
|
||||
if (retval != ERROR_OK || cmsis_dap_handle->response[1] != DAP_OK) {
|
||||
LOG_ERROR("CMSIS-DAP command CMD_SWD_Configure failed.");
|
||||
return ERROR_JTAG_DEVICE_ERROR;
|
||||
}
|
||||
|
@ -522,15 +495,14 @@ static int cmsis_dap_cmd_DAP_SWD_Configure(uint8_t cfg)
|
|||
static int cmsis_dap_cmd_DAP_Delay(uint16_t delay_us)
|
||||
{
|
||||
int retval;
|
||||
uint8_t *buffer = cmsis_dap_handle->packet_buffer;
|
||||
uint8_t *command = cmsis_dap_handle->command;
|
||||
|
||||
buffer[0] = 0; /* report number */
|
||||
buffer[1] = CMD_DAP_DELAY;
|
||||
buffer[2] = delay_us & 0xff;
|
||||
buffer[3] = (delay_us >> 8) & 0xff;
|
||||
retval = cmsis_dap_xfer(cmsis_dap_handle, 4);
|
||||
command[0] = CMD_DAP_DELAY;
|
||||
h_u16_to_le(&command[1], delay_us);
|
||||
|
||||
if (retval != ERROR_OK || buffer[1] != DAP_OK) {
|
||||
retval = cmsis_dap_xfer(cmsis_dap_handle, 3);
|
||||
|
||||
if (retval != ERROR_OK || cmsis_dap_handle->response[1] != DAP_OK) {
|
||||
LOG_ERROR("CMSIS-DAP command CMD_Delay failed.");
|
||||
return ERROR_JTAG_DEVICE_ERROR;
|
||||
}
|
||||
|
@ -541,7 +513,7 @@ static int cmsis_dap_cmd_DAP_Delay(uint16_t delay_us)
|
|||
|
||||
static void cmsis_dap_swd_write_from_queue(struct cmsis_dap *dap)
|
||||
{
|
||||
uint8_t *buffer = dap->packet_buffer;
|
||||
uint8_t *command = cmsis_dap_handle->command;
|
||||
struct pending_request_block *block = &pending_fifo[pending_fifo_put_idx];
|
||||
|
||||
LOG_DEBUG_IO("Executing %d queued transactions from FIFO index %d", block->transfer_count, pending_fifo_put_idx);
|
||||
|
@ -554,11 +526,10 @@ static void cmsis_dap_swd_write_from_queue(struct cmsis_dap *dap)
|
|||
if (block->transfer_count == 0)
|
||||
goto skip;
|
||||
|
||||
size_t idx = 0;
|
||||
buffer[idx++] = 0; /* report number */
|
||||
buffer[idx++] = CMD_DAP_TFER;
|
||||
buffer[idx++] = 0x00; /* DAP Index */
|
||||
buffer[idx++] = block->transfer_count;
|
||||
command[0] = CMD_DAP_TFER;
|
||||
command[1] = 0x00; /* DAP Index */
|
||||
command[2] = block->transfer_count;
|
||||
size_t idx = 3;
|
||||
|
||||
for (int i = 0; i < block->transfer_count; i++) {
|
||||
struct pending_transfer_result *transfer = &(block->transfers[i]);
|
||||
|
@ -589,12 +560,10 @@ static void cmsis_dap_swd_write_from_queue(struct cmsis_dap *dap)
|
|||
data &= ~CORUNDETECT;
|
||||
}
|
||||
|
||||
buffer[idx++] = (cmd >> 1) & 0x0f;
|
||||
command[idx++] = (cmd >> 1) & 0x0f;
|
||||
if (!(cmd & SWD_CMD_RnW)) {
|
||||
buffer[idx++] = (data) & 0xff;
|
||||
buffer[idx++] = (data >> 8) & 0xff;
|
||||
buffer[idx++] = (data >> 16) & 0xff;
|
||||
buffer[idx++] = (data >> 24) & 0xff;
|
||||
h_u32_to_le(&command[idx], data);
|
||||
idx += 4;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -620,7 +589,6 @@ skip:
|
|||
|
||||
static void cmsis_dap_swd_read_process(struct cmsis_dap *dap, int timeout_ms)
|
||||
{
|
||||
uint8_t *buffer = dap->packet_buffer;
|
||||
struct pending_request_block *block = &pending_fifo[pending_fifo_get_idx];
|
||||
|
||||
if (pending_fifo_block_count == 0)
|
||||
|
@ -637,30 +605,33 @@ static void cmsis_dap_swd_read_process(struct cmsis_dap *dap, int timeout_ms)
|
|||
goto skip;
|
||||
}
|
||||
|
||||
if (buffer[2] & 0x08) {
|
||||
LOG_DEBUG("CMSIS-DAP Protocol Error @ %d (wrong parity)", buffer[1]);
|
||||
uint8_t *resp = dap->response;
|
||||
uint8_t transfer_count = resp[1];
|
||||
uint8_t ack = resp[2] & 0x07;
|
||||
if (resp[2] & 0x08) {
|
||||
LOG_DEBUG("CMSIS-DAP Protocol Error @ %d (wrong parity)", transfer_count);
|
||||
queued_retval = ERROR_FAIL;
|
||||
goto skip;
|
||||
}
|
||||
uint8_t ack = buffer[2] & 0x07;
|
||||
if (ack != SWD_ACK_OK) {
|
||||
LOG_DEBUG("SWD ack not OK @ %d %s", buffer[1],
|
||||
LOG_DEBUG("SWD ack not OK @ %d %s", transfer_count,
|
||||
ack == SWD_ACK_WAIT ? "WAIT" : ack == SWD_ACK_FAULT ? "FAULT" : "JUNK");
|
||||
queued_retval = ack == SWD_ACK_WAIT ? ERROR_WAIT : ERROR_FAIL;
|
||||
goto skip;
|
||||
}
|
||||
|
||||
if (block->transfer_count != buffer[1])
|
||||
if (block->transfer_count != transfer_count)
|
||||
LOG_ERROR("CMSIS-DAP transfer count mismatch: expected %d, got %d",
|
||||
block->transfer_count, buffer[1]);
|
||||
block->transfer_count, transfer_count);
|
||||
|
||||
LOG_DEBUG_IO("Received results of %d queued transactions FIFO index %d", buffer[1], pending_fifo_get_idx);
|
||||
LOG_DEBUG_IO("Received results of %d queued transactions FIFO index %d",
|
||||
transfer_count, pending_fifo_get_idx);
|
||||
size_t idx = 3;
|
||||
for (int i = 0; i < buffer[1]; i++) {
|
||||
for (int i = 0; i < transfer_count; i++) {
|
||||
struct pending_transfer_result *transfer = &(block->transfers[i]);
|
||||
if (transfer->cmd & SWD_CMD_RnW) {
|
||||
static uint32_t last_read;
|
||||
uint32_t data = le_to_h_u32(&buffer[idx]);
|
||||
uint32_t data = le_to_h_u32(&resp[idx]);
|
||||
uint32_t tmp = data;
|
||||
idx += 4;
|
||||
|
||||
|
@ -934,24 +905,20 @@ static int cmsis_dap_init(void)
|
|||
|
||||
if (data[0] == 2) { /* short */
|
||||
uint16_t pkt_sz = data[1] + (data[2] << 8);
|
||||
if (pkt_sz != cmsis_dap_handle->packet_size) {
|
||||
|
||||
/* 4 bytes of command header + 5 bytes per register
|
||||
* write. For bulk read sequences just 4 bytes are
|
||||
* needed per transfer, so this is suboptimal. */
|
||||
pending_queue_len = (pkt_sz - 4) / 5;
|
||||
/* 4 bytes of command header + 5 bytes per register
|
||||
* write. For bulk read sequences just 4 bytes are
|
||||
* needed per transfer, so this is suboptimal. */
|
||||
pending_queue_len = (pkt_sz - 4) / 5;
|
||||
|
||||
if (cmsis_dap_handle->packet_size != pkt_sz + 1) {
|
||||
/* reallocate buffer */
|
||||
cmsis_dap_handle->packet_size = pkt_sz + 1;
|
||||
cmsis_dap_handle->packet_buffer = realloc(cmsis_dap_handle->packet_buffer,
|
||||
cmsis_dap_handle->packet_size);
|
||||
if (cmsis_dap_handle->packet_buffer == NULL) {
|
||||
LOG_ERROR("unable to reallocate memory");
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
free(cmsis_dap_handle->packet_buffer);
|
||||
retval = cmsis_dap_handle->backend->packet_buffer_alloc(cmsis_dap_handle, pkt_sz);
|
||||
if (retval != ERROR_OK)
|
||||
return retval;
|
||||
|
||||
LOG_DEBUG("CMSIS-DAP: Packet Size = %" PRIu16, pkt_sz);
|
||||
}
|
||||
|
||||
LOG_DEBUG("CMSIS-DAP: Packet Size = %" PRId16, pkt_sz);
|
||||
}
|
||||
|
||||
/* INFO_ID_PKT_CNT - byte */
|
||||
|
@ -1168,20 +1135,21 @@ static void cmsis_dap_flush(void)
|
|||
LOG_DEBUG_IO("Flushing %d queued sequences (%d bytes) with %d pending scan results to capture",
|
||||
queued_seq_count, queued_seq_buf_end, pending_scan_result_count);
|
||||
|
||||
/* prep CMSIS-DAP packet */
|
||||
uint8_t *buffer = cmsis_dap_handle->packet_buffer;
|
||||
buffer[0] = 0; /* report number */
|
||||
buffer[1] = CMD_DAP_JTAG_SEQ;
|
||||
buffer[2] = queued_seq_count;
|
||||
memcpy(buffer + 3, queued_seq_buf, queued_seq_buf_end);
|
||||
/* prepare CMSIS-DAP packet */
|
||||
uint8_t *command = cmsis_dap_handle->command;
|
||||
command[0] = CMD_DAP_JTAG_SEQ;
|
||||
command[1] = queued_seq_count;
|
||||
memcpy(&command[2], queued_seq_buf, queued_seq_buf_end);
|
||||
|
||||
#ifdef CMSIS_DAP_JTAG_DEBUG
|
||||
debug_parse_cmsis_buf(buffer, queued_seq_buf_end + 3);
|
||||
debug_parse_cmsis_buf(command, queued_seq_buf_end + 2);
|
||||
#endif
|
||||
|
||||
/* send command to USB device */
|
||||
int retval = cmsis_dap_xfer(cmsis_dap_handle, queued_seq_buf_end + 3);
|
||||
if (retval != ERROR_OK || buffer[1] != DAP_OK) {
|
||||
int retval = cmsis_dap_xfer(cmsis_dap_handle, queued_seq_buf_end + 2);
|
||||
|
||||
uint8_t *resp = cmsis_dap_handle->response;
|
||||
if (retval != ERROR_OK || resp[1] != DAP_OK) {
|
||||
LOG_ERROR("CMSIS-DAP command CMD_DAP_JTAG_SEQ failed.");
|
||||
exit(-1);
|
||||
}
|
||||
|
@ -1189,7 +1157,7 @@ static void cmsis_dap_flush(void)
|
|||
#ifdef CMSIS_DAP_JTAG_DEBUG
|
||||
LOG_DEBUG_IO("USB response buf:");
|
||||
for (int c = 0; c < queued_seq_buf_end + 3; ++c)
|
||||
printf("%02X ", buffer[c]);
|
||||
printf("%02X ", resp[c]);
|
||||
printf("\n");
|
||||
#endif
|
||||
|
||||
|
@ -1200,10 +1168,10 @@ static void cmsis_dap_flush(void)
|
|||
i, pending_scan_result_count, scan->length, scan->first + 2, scan->buffer_offset);
|
||||
#ifdef CMSIS_DAP_JTAG_DEBUG
|
||||
for (uint32_t b = 0; b < DIV_ROUND_UP(scan->length, 8); ++b)
|
||||
printf("%02X ", buffer[2+scan->first+b]);
|
||||
printf("%02X ", resp[2+scan->first+b]);
|
||||
printf("\n");
|
||||
#endif
|
||||
bit_copy(scan->buffer, scan->buffer_offset, buffer + 2 + scan->first, 0, scan->length);
|
||||
bit_copy(scan->buffer, scan->buffer_offset, &resp[2 + scan->first], 0, scan->length);
|
||||
}
|
||||
|
||||
/* reset */
|
||||
|
@ -1545,9 +1513,6 @@ static int cmsis_dap_execute_queue(void)
|
|||
|
||||
static int cmsis_dap_speed(int speed)
|
||||
{
|
||||
if (speed > DAP_MAX_CLOCK)
|
||||
LOG_INFO("High speed (adapter speed %d) may be limited by adapter firmware.", speed);
|
||||
|
||||
if (speed == 0) {
|
||||
LOG_ERROR("RTCK not supported. Set nonzero \"adapter speed\".");
|
||||
return ERROR_JTAG_NOT_IMPLEMENTED;
|
||||
|
@ -1580,22 +1545,21 @@ COMMAND_HANDLER(cmsis_dap_handle_cmd_command)
|
|||
{
|
||||
int retval;
|
||||
unsigned i;
|
||||
uint8_t *buffer = cmsis_dap_handle->packet_buffer;
|
||||
|
||||
buffer[0] = 0; /* report number */
|
||||
uint8_t *command = cmsis_dap_handle->command;
|
||||
|
||||
for (i = 0; i < CMD_ARGC; i++)
|
||||
buffer[i + 1] = strtoul(CMD_ARGV[i], NULL, 16);
|
||||
command[i] = strtoul(CMD_ARGV[i], NULL, 16);
|
||||
|
||||
retval = cmsis_dap_xfer(cmsis_dap_handle, CMD_ARGC + 1);
|
||||
retval = cmsis_dap_xfer(cmsis_dap_handle, CMD_ARGC);
|
||||
|
||||
if (retval != ERROR_OK) {
|
||||
LOG_ERROR("CMSIS-DAP command failed.");
|
||||
return ERROR_JTAG_DEVICE_ERROR;
|
||||
}
|
||||
|
||||
uint8_t *resp = cmsis_dap_handle->response;
|
||||
LOG_INFO("Returned data %02" PRIx8 " %02" PRIx8 " %02" PRIx8 " %02" PRIx8,
|
||||
buffer[1], buffer[2], buffer[3], buffer[4]);
|
||||
resp[1], resp[2], resp[3], resp[4]);
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
|
|
@ -13,6 +13,9 @@ struct cmsis_dap {
|
|||
uint16_t packet_size;
|
||||
int packet_count;
|
||||
uint8_t *packet_buffer;
|
||||
uint16_t packet_buffer_size;
|
||||
uint8_t *command;
|
||||
uint8_t *response;
|
||||
uint8_t caps;
|
||||
uint8_t mode;
|
||||
};
|
||||
|
@ -23,10 +26,13 @@ struct cmsis_dap_backend {
|
|||
void (*close)(struct cmsis_dap *dap);
|
||||
int (*read)(struct cmsis_dap *dap, int timeout_ms);
|
||||
int (*write)(struct cmsis_dap *dap, int len, int timeout_ms);
|
||||
int (*packet_buffer_alloc)(struct cmsis_dap *dap, unsigned int pkt_sz);
|
||||
};
|
||||
|
||||
extern const struct cmsis_dap_backend cmsis_dap_hid_backend;
|
||||
extern const struct cmsis_dap_backend cmsis_dap_usb_backend;
|
||||
extern const struct command_registration cmsis_dap_usb_subcommand_handlers[];
|
||||
|
||||
#define REPORT_ID_SIZE 1
|
||||
|
||||
#endif
|
||||
|
|
|
@ -51,6 +51,9 @@ struct cmsis_dap_backend_data {
|
|||
|
||||
static int cmsis_dap_usb_interface = -1;
|
||||
|
||||
static void cmsis_dap_usb_close(struct cmsis_dap *dap);
|
||||
static int cmsis_dap_usb_alloc(struct cmsis_dap *dap, unsigned int pkt_sz);
|
||||
|
||||
static int cmsis_dap_usb_open(struct cmsis_dap *dap, uint16_t vids[], uint16_t pids[], char *serial)
|
||||
{
|
||||
int err;
|
||||
|
@ -357,12 +360,24 @@ static int cmsis_dap_usb_open(struct cmsis_dap *dap, uint16_t vids[], uint16_t p
|
|||
return ERROR_FAIL;
|
||||
}
|
||||
|
||||
dap->packet_size = packet_size + 1; /* "+ 1" for compatibility with the HID backend */
|
||||
dap->packet_size = packet_size;
|
||||
dap->packet_buffer_size = packet_size;
|
||||
dap->bdata->usb_ctx = ctx;
|
||||
dap->bdata->dev_handle = dev_handle;
|
||||
dap->bdata->ep_out = ep_out;
|
||||
dap->bdata->ep_in = ep_in;
|
||||
dap->bdata->interface = interface_num;
|
||||
|
||||
dap->packet_buffer = malloc(dap->packet_buffer_size);
|
||||
if (dap->packet_buffer == NULL) {
|
||||
LOG_ERROR("unable to allocate memory");
|
||||
cmsis_dap_usb_close(dap);
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
|
||||
dap->command = dap->packet_buffer;
|
||||
dap->response = dap->packet_buffer;
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
|
@ -382,6 +397,8 @@ static void cmsis_dap_usb_close(struct cmsis_dap *dap)
|
|||
libusb_exit(dap->bdata->usb_ctx);
|
||||
free(dap->bdata);
|
||||
dap->bdata = NULL;
|
||||
free(dap->packet_buffer);
|
||||
dap->packet_buffer = NULL;
|
||||
}
|
||||
|
||||
static int cmsis_dap_usb_read(struct cmsis_dap *dap, int timeout_ms)
|
||||
|
@ -400,7 +417,7 @@ static int cmsis_dap_usb_read(struct cmsis_dap *dap, int timeout_ms)
|
|||
}
|
||||
}
|
||||
|
||||
memset(&dap->packet_buffer[transferred], 0, dap->packet_size - transferred);
|
||||
memset(&dap->packet_buffer[transferred], 0, dap->packet_buffer_size - transferred);
|
||||
|
||||
return transferred;
|
||||
}
|
||||
|
@ -412,7 +429,7 @@ static int cmsis_dap_usb_write(struct cmsis_dap *dap, int txlen, int timeout_ms)
|
|||
|
||||
/* skip the first byte that is only used by the HID backend */
|
||||
err = libusb_bulk_transfer(dap->bdata->dev_handle, dap->bdata->ep_out,
|
||||
dap->packet_buffer + 1, txlen - 1, &transferred, timeout_ms);
|
||||
dap->packet_buffer, txlen, &transferred, timeout_ms);
|
||||
if (err) {
|
||||
if (err == LIBUSB_ERROR_TIMEOUT) {
|
||||
return ERROR_TIMEOUT_REACHED;
|
||||
|
@ -425,6 +442,24 @@ static int cmsis_dap_usb_write(struct cmsis_dap *dap, int txlen, int timeout_ms)
|
|||
return transferred;
|
||||
}
|
||||
|
||||
static int cmsis_dap_usb_alloc(struct cmsis_dap *dap, unsigned int pkt_sz)
|
||||
{
|
||||
uint8_t *buf = malloc(pkt_sz);
|
||||
if (buf == NULL) {
|
||||
LOG_ERROR("unable to allocate CMSIS-DAP packet buffer");
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
|
||||
dap->packet_buffer = buf;
|
||||
dap->packet_size = pkt_sz;
|
||||
dap->packet_buffer_size = pkt_sz;
|
||||
|
||||
dap->command = dap->packet_buffer;
|
||||
dap->response = dap->packet_buffer;
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
COMMAND_HANDLER(cmsis_dap_handle_usb_interface_command)
|
||||
{
|
||||
if (CMD_ARGC == 1)
|
||||
|
@ -452,4 +487,5 @@ const struct cmsis_dap_backend cmsis_dap_usb_backend = {
|
|||
.close = cmsis_dap_usb_close,
|
||||
.read = cmsis_dap_usb_read,
|
||||
.write = cmsis_dap_usb_write,
|
||||
.packet_buffer_alloc = cmsis_dap_usb_alloc,
|
||||
};
|
||||
|
|
|
@ -40,12 +40,13 @@
|
|||
|
||||
#include "cmsis_dap.h"
|
||||
|
||||
#define PACKET_SIZE (64 + 1) /* 64 bytes plus report id */
|
||||
|
||||
struct cmsis_dap_backend_data {
|
||||
hid_device *dev_handle;
|
||||
};
|
||||
|
||||
static void cmsis_dap_hid_close(struct cmsis_dap *dap);
|
||||
static int cmsis_dap_hid_alloc(struct cmsis_dap *dap, unsigned int pkt_sz);
|
||||
|
||||
static int cmsis_dap_hid_open(struct cmsis_dap *dap, uint16_t vids[], uint16_t pids[], char *serial)
|
||||
{
|
||||
hid_device *dev = NULL;
|
||||
|
@ -145,7 +146,7 @@ static int cmsis_dap_hid_open(struct cmsis_dap *dap, uint16_t vids[], uint16_t p
|
|||
* without this info we cannot communicate with the adapter.
|
||||
* For the moment we have to hard code the packet size */
|
||||
|
||||
dap->packet_size = PACKET_SIZE;
|
||||
unsigned int packet_size = 64;
|
||||
|
||||
/* atmel cmsis-dap uses 512 byte reports */
|
||||
/* except when it doesn't e.g. with mEDBG on SAMD10 Xplained
|
||||
|
@ -153,10 +154,18 @@ static int cmsis_dap_hid_open(struct cmsis_dap *dap, uint16_t vids[], uint16_t p
|
|||
/* TODO: HID report descriptor should be parsed instead of
|
||||
* hardcoding a match by VID */
|
||||
if (target_vid == 0x03eb && target_pid != 0x2145 && target_pid != 0x2175)
|
||||
dap->packet_size = 512 + 1;
|
||||
packet_size = 512;
|
||||
|
||||
dap->bdata->dev_handle = dev;
|
||||
|
||||
int retval = cmsis_dap_hid_alloc(dap, packet_size);
|
||||
if (retval != ERROR_OK) {
|
||||
cmsis_dap_hid_close(dap);
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
|
||||
dap->command = dap->packet_buffer + REPORT_ID_SIZE;
|
||||
dap->response = dap->packet_buffer;
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
|
@ -166,11 +175,13 @@ static void cmsis_dap_hid_close(struct cmsis_dap *dap)
|
|||
hid_exit();
|
||||
free(dap->bdata);
|
||||
dap->bdata = NULL;
|
||||
free(dap->packet_buffer);
|
||||
dap->packet_buffer = NULL;
|
||||
}
|
||||
|
||||
static int cmsis_dap_hid_read(struct cmsis_dap *dap, int timeout_ms)
|
||||
{
|
||||
int retval = hid_read_timeout(dap->bdata->dev_handle, dap->packet_buffer, dap->packet_size, timeout_ms);
|
||||
int retval = hid_read_timeout(dap->bdata->dev_handle, dap->packet_buffer, dap->packet_buffer_size, timeout_ms);
|
||||
|
||||
if (retval == 0) {
|
||||
return ERROR_TIMEOUT_REACHED;
|
||||
|
@ -186,11 +197,13 @@ static int cmsis_dap_hid_write(struct cmsis_dap *dap, int txlen, int timeout_ms)
|
|||
{
|
||||
(void) timeout_ms;
|
||||
|
||||
dap->packet_buffer[0] = 0; /* HID report number */
|
||||
|
||||
/* Pad the rest of the TX buffer with 0's */
|
||||
memset(dap->packet_buffer + txlen, 0, dap->packet_size - txlen);
|
||||
memset(dap->command + txlen, 0, dap->packet_size - txlen);
|
||||
|
||||
/* write data to device */
|
||||
int retval = hid_write(dap->bdata->dev_handle, dap->packet_buffer, dap->packet_size);
|
||||
int retval = hid_write(dap->bdata->dev_handle, dap->packet_buffer, dap->packet_buffer_size);
|
||||
if (retval == -1) {
|
||||
LOG_ERROR("error writing data: %ls", hid_error(dap->bdata->dev_handle));
|
||||
return ERROR_FAIL;
|
||||
|
@ -199,10 +212,30 @@ static int cmsis_dap_hid_write(struct cmsis_dap *dap, int txlen, int timeout_ms)
|
|||
return retval;
|
||||
}
|
||||
|
||||
static int cmsis_dap_hid_alloc(struct cmsis_dap *dap, unsigned int pkt_sz)
|
||||
{
|
||||
unsigned int packet_buffer_size = pkt_sz + REPORT_ID_SIZE;
|
||||
uint8_t *buf = malloc(packet_buffer_size);
|
||||
if (buf == NULL) {
|
||||
LOG_ERROR("unable to allocate CMSIS-DAP packet buffer");
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
|
||||
dap->packet_buffer = buf;
|
||||
dap->packet_size = pkt_sz;
|
||||
dap->packet_buffer_size = packet_buffer_size;
|
||||
|
||||
dap->command = dap->packet_buffer + REPORT_ID_SIZE;
|
||||
dap->response = dap->packet_buffer;
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
const struct cmsis_dap_backend cmsis_dap_hid_backend = {
|
||||
.name = "hid",
|
||||
.open = cmsis_dap_hid_open,
|
||||
.close = cmsis_dap_hid_close,
|
||||
.read = cmsis_dap_hid_read,
|
||||
.write = cmsis_dap_hid_write,
|
||||
.packet_buffer_alloc = cmsis_dap_hid_alloc,
|
||||
};
|
||||
|
|
|
@ -51,7 +51,7 @@ bool jtag_usb_location_equal(uint8_t dev_bus, uint8_t *port_path,
|
|||
goto done;
|
||||
}
|
||||
|
||||
string_length -= 1;
|
||||
string_length -= strnlen(ptr, string_length);
|
||||
/* check bus mismatch */
|
||||
if (atoi(ptr) != dev_bus)
|
||||
goto done;
|
||||
|
@ -69,7 +69,7 @@ bool jtag_usb_location_equal(uint8_t dev_bus, uint8_t *port_path,
|
|||
break;
|
||||
|
||||
path_step++;
|
||||
string_length -= 2;
|
||||
string_length -= strnlen(ptr, string_length) + 1;
|
||||
};
|
||||
|
||||
/* walked the full path, all elements match */
|
||||
|
|
|
@ -253,7 +253,7 @@ static int nulink_usb_write_debug_reg(void *handle, uint32_t addr, uint32_t val)
|
|||
{
|
||||
struct nulink_usb_handle_s *h = handle;
|
||||
|
||||
LOG_DEBUG("nulink_usb_write_debug_reg 0x%08" PRIX32 "0x%08" PRIX32, addr, val);
|
||||
LOG_DEBUG("nulink_usb_write_debug_reg 0x%08" PRIX32 " 0x%08" PRIX32, addr, val);
|
||||
|
||||
nulink_usb_init_buffer(handle, 8 + 12 * 1);
|
||||
/* set command ID */
|
||||
|
@ -503,7 +503,7 @@ static int nulink_usb_read_mem8(void *handle, uint32_t addr, uint16_t len,
|
|||
aligned_addr = aligned_addr * 4;
|
||||
offset = addr - aligned_addr;
|
||||
LOG_DEBUG("nulink_usb_read_mem8: unaligned address addr 0x%08" PRIx32
|
||||
"/aligned addr 0x%08" PRIx32 "offset %" PRIu32,
|
||||
"/aligned addr 0x%08" PRIx32 " offset %" PRIu32,
|
||||
addr, aligned_addr, offset);
|
||||
|
||||
addr = aligned_addr;
|
||||
|
|
|
@ -34,7 +34,7 @@
|
|||
#include "rlink_st7.h"
|
||||
#include "rlink_ep1_cmd.h"
|
||||
#include "rlink_dtc_cmd.h"
|
||||
#include "usb_common.h"
|
||||
#include "libusb_helper.h"
|
||||
|
||||
/* This feature is made useless by running the DTC all the time. When automatic, the LED is on
|
||||
*whenever the DTC is running. Otherwise, USB messages are sent to turn it on and off. */
|
||||
|
@ -97,19 +97,20 @@
|
|||
#define ST7_PC_TDO ST7_PC_IO9
|
||||
#define ST7_PA_DBGACK ST7_PA_IO10
|
||||
|
||||
static usb_dev_handle *pHDev;
|
||||
static libusb_device_handle *pHDev;
|
||||
|
||||
/*
|
||||
* ep1 commands are up to USB_EP1OUT_SIZE bytes in length.
|
||||
* This function takes care of zeroing the unused bytes before sending the packet.
|
||||
* Any reply packet is not handled by this function.
|
||||
*/
|
||||
static int ep1_generic_commandl(usb_dev_handle *pHDev_param, size_t length, ...)
|
||||
static int ep1_generic_commandl(libusb_device_handle *pHDev_param, size_t length, ...)
|
||||
{
|
||||
uint8_t usb_buffer[USB_EP1OUT_SIZE];
|
||||
uint8_t *usb_buffer_p;
|
||||
va_list ap;
|
||||
int usb_ret;
|
||||
int transferred;
|
||||
|
||||
if (length > sizeof(usb_buffer))
|
||||
length = sizeof(usb_buffer);
|
||||
|
@ -128,25 +129,29 @@ static int ep1_generic_commandl(usb_dev_handle *pHDev_param, size_t length, ...)
|
|||
sizeof(usb_buffer) - (usb_buffer_p - usb_buffer)
|
||||
);
|
||||
|
||||
usb_ret = usb_bulk_write(
|
||||
usb_ret = jtag_libusb_bulk_write(
|
||||
pHDev_param,
|
||||
USB_EP1OUT_ADDR,
|
||||
(char *)usb_buffer, sizeof(usb_buffer),
|
||||
USB_TIMEOUT_MS
|
||||
USB_TIMEOUT_MS,
|
||||
&transferred
|
||||
);
|
||||
|
||||
return usb_ret;
|
||||
if (usb_ret != ERROR_OK)
|
||||
return usb_ret;
|
||||
return transferred;
|
||||
}
|
||||
|
||||
#if 0
|
||||
static ssize_t ep1_memory_read(
|
||||
usb_dev_handle *pHDev, uint16_t addr,
|
||||
libusb_device_handle *pHDev_param, uint16_t addr,
|
||||
size_t length, uint8_t *buffer)
|
||||
{
|
||||
uint8_t usb_buffer[USB_EP1OUT_SIZE];
|
||||
int usb_ret;
|
||||
size_t remain;
|
||||
ssize_t count;
|
||||
int transferred;
|
||||
|
||||
usb_buffer[0] = EP1_CMD_MEMORY_READ;
|
||||
memset(
|
||||
|
@ -168,22 +173,24 @@ static ssize_t ep1_memory_read(
|
|||
usb_buffer[2] = addr;
|
||||
usb_buffer[3] = length;
|
||||
|
||||
usb_ret = usb_bulk_write(
|
||||
pHDev, USB_EP1OUT_ADDR,
|
||||
usb_buffer, sizeof(usb_buffer),
|
||||
USB_TIMEOUT_MS
|
||||
usb_ret = jtag_libusb_bulk_write(
|
||||
pHDev_param, USB_EP1OUT_ADDR,
|
||||
(char *)usb_buffer, sizeof(usb_buffer),
|
||||
USB_TIMEOUT_MS,
|
||||
&transferred
|
||||
);
|
||||
|
||||
if (usb_ret < sizeof(usb_buffer))
|
||||
if (usb_ret != ERROR_OK || transferred < (int)sizeof(usb_buffer))
|
||||
break;
|
||||
|
||||
usb_ret = usb_bulk_read(
|
||||
pHDev, USB_EP1IN_ADDR,
|
||||
buffer, length,
|
||||
USB_TIMEOUT_MS
|
||||
usb_ret = jtag_libusb_bulk_read(
|
||||
pHDev_param, USB_EP1IN_ADDR,
|
||||
(char *)buffer, length,
|
||||
USB_TIMEOUT_MS,
|
||||
&transferred
|
||||
);
|
||||
|
||||
if (usb_ret < length)
|
||||
if (usb_ret != ERROR_OK || transferred < (int)length)
|
||||
break;
|
||||
|
||||
addr += length;
|
||||
|
@ -196,7 +203,7 @@ static ssize_t ep1_memory_read(
|
|||
}
|
||||
#endif
|
||||
|
||||
static ssize_t ep1_memory_write(usb_dev_handle *pHDev_param, uint16_t addr,
|
||||
static ssize_t ep1_memory_write(libusb_device_handle *pHDev_param, uint16_t addr,
|
||||
size_t length, uint8_t const *buffer)
|
||||
{
|
||||
uint8_t usb_buffer[USB_EP1OUT_SIZE];
|
||||
|
@ -229,13 +236,16 @@ static ssize_t ep1_memory_write(usb_dev_handle *pHDev_param, uint16_t addr,
|
|||
sizeof(usb_buffer) - 4 - length
|
||||
);
|
||||
|
||||
usb_ret = usb_bulk_write(
|
||||
int transferred;
|
||||
|
||||
usb_ret = jtag_libusb_bulk_write(
|
||||
pHDev_param, USB_EP1OUT_ADDR,
|
||||
(char *)usb_buffer, sizeof(usb_buffer),
|
||||
USB_TIMEOUT_MS
|
||||
USB_TIMEOUT_MS,
|
||||
&transferred
|
||||
);
|
||||
|
||||
if ((size_t)usb_ret < sizeof(usb_buffer))
|
||||
if (usb_ret != ERROR_OK || transferred < (int)sizeof(usb_buffer))
|
||||
break;
|
||||
|
||||
addr += length;
|
||||
|
@ -249,7 +259,7 @@ static ssize_t ep1_memory_write(usb_dev_handle *pHDev_param, uint16_t addr,
|
|||
|
||||
|
||||
#if 0
|
||||
static ssize_t ep1_memory_writel(usb_dev_handle *pHDev, uint16_t addr,
|
||||
static ssize_t ep1_memory_writel(libusb_device_handle *pHDev_param, uint16_t addr,
|
||||
size_t length, ...)
|
||||
{
|
||||
uint8_t buffer[USB_EP1OUT_SIZE - 4];
|
||||
|
@ -269,7 +279,7 @@ static ssize_t ep1_memory_writel(usb_dev_handle *pHDev, uint16_t addr,
|
|||
remain--;
|
||||
}
|
||||
|
||||
return ep1_memory_write(pHDev, addr, length, buffer);
|
||||
return ep1_memory_write(pHDev_param, addr, length, buffer);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -286,7 +296,7 @@ static ssize_t ep1_memory_writel(usb_dev_handle *pHDev, uint16_t addr,
|
|||
static uint8_t dtc_entry_download;
|
||||
|
||||
/* The buffer is specially formatted to represent a valid image to load into the DTC. */
|
||||
static int dtc_load_from_buffer(usb_dev_handle *pHDev_param, const uint8_t *buffer,
|
||||
static int dtc_load_from_buffer(libusb_device_handle *pHDev_param, const uint8_t *buffer,
|
||||
size_t length)
|
||||
{
|
||||
struct header_s {
|
||||
|
@ -401,6 +411,7 @@ static int dtc_start_download(void)
|
|||
{
|
||||
int usb_err;
|
||||
uint8_t ep2txr;
|
||||
int transferred;
|
||||
|
||||
/* set up for download mode and make sure EP2 is set up to transmit */
|
||||
usb_err = ep1_generic_commandl(
|
||||
|
@ -418,12 +429,13 @@ static int dtc_start_download(void)
|
|||
return usb_err;
|
||||
|
||||
/* read back ep2txr */
|
||||
usb_err = usb_bulk_read(
|
||||
usb_err = jtag_libusb_bulk_read(
|
||||
pHDev, USB_EP1IN_ADDR,
|
||||
(char *)&ep2txr, 1,
|
||||
USB_TIMEOUT_MS
|
||||
USB_TIMEOUT_MS,
|
||||
&transferred
|
||||
);
|
||||
if (usb_err < 0)
|
||||
if (usb_err != ERROR_OK)
|
||||
return usb_err;
|
||||
|
||||
usb_err = ep1_generic_commandl(
|
||||
|
@ -447,17 +459,18 @@ static int dtc_start_download(void)
|
|||
return usb_err;
|
||||
|
||||
/* wait for completion */
|
||||
usb_err = usb_bulk_read(
|
||||
usb_err = jtag_libusb_bulk_read(
|
||||
pHDev, USB_EP1IN_ADDR,
|
||||
(char *)&ep2txr, 1,
|
||||
USB_TIMEOUT_MS
|
||||
USB_TIMEOUT_MS,
|
||||
&transferred
|
||||
);
|
||||
|
||||
return usb_err;
|
||||
}
|
||||
|
||||
static int dtc_run_download(
|
||||
usb_dev_handle *pHDev_param,
|
||||
libusb_device_handle *pHDev_param,
|
||||
uint8_t *command_buffer,
|
||||
int command_buffer_size,
|
||||
uint8_t *reply_buffer,
|
||||
|
@ -467,14 +480,16 @@ static int dtc_run_download(
|
|||
char dtc_status;
|
||||
int usb_err;
|
||||
int i;
|
||||
int transferred;
|
||||
|
||||
LOG_DEBUG("%d/%d", command_buffer_size, reply_buffer_size);
|
||||
|
||||
usb_err = usb_bulk_write(
|
||||
usb_err = jtag_libusb_bulk_write(
|
||||
pHDev_param,
|
||||
USB_EP2OUT_ADDR,
|
||||
(char *)command_buffer, USB_EP2BANK_SIZE,
|
||||
USB_TIMEOUT_MS
|
||||
USB_TIMEOUT_MS,
|
||||
&transferred
|
||||
);
|
||||
if (usb_err < 0)
|
||||
return usb_err;
|
||||
|
@ -493,11 +508,12 @@ static int dtc_run_download(
|
|||
if (usb_err < 0)
|
||||
return usb_err;
|
||||
|
||||
usb_err = usb_bulk_read(
|
||||
usb_err = jtag_libusb_bulk_read(
|
||||
pHDev_param,
|
||||
USB_EP1IN_ADDR,
|
||||
&dtc_status, 1,
|
||||
USB_TIMEOUT_MS
|
||||
USB_TIMEOUT_MS,
|
||||
&transferred
|
||||
);
|
||||
if (usb_err < 0)
|
||||
return usb_err;
|
||||
|
@ -507,20 +523,21 @@ static int dtc_run_download(
|
|||
|
||||
if (!--i) {
|
||||
LOG_ERROR("too many retries waiting for DTC status");
|
||||
return -ETIMEDOUT;
|
||||
return LIBUSB_ERROR_TIMEOUT;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (reply_buffer && reply_buffer_size) {
|
||||
usb_err = usb_bulk_read(
|
||||
usb_err = jtag_libusb_bulk_read(
|
||||
pHDev_param,
|
||||
USB_EP2IN_ADDR,
|
||||
(char *)reply_buffer, reply_buffer_size,
|
||||
USB_TIMEOUT_MS
|
||||
USB_TIMEOUT_MS,
|
||||
&transferred
|
||||
);
|
||||
|
||||
if (usb_err < reply_buffer_size) {
|
||||
if (usb_err != ERROR_OK || transferred < reply_buffer_size) {
|
||||
LOG_ERROR("Read of endpoint 2 returned %d, expected %d",
|
||||
usb_err, reply_buffer_size
|
||||
);
|
||||
|
@ -644,7 +661,7 @@ static int dtc_queue_run(void)
|
|||
reply_buffer, sizeof(reply_buffer)
|
||||
);
|
||||
if (usb_err < 0) {
|
||||
LOG_ERROR("dtc_run_download: %s", usb_strerror());
|
||||
LOG_ERROR("dtc_run_download: %s", libusb_error_name(usb_err));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
@ -919,6 +936,7 @@ static void rlink_reset(int trst, int srst)
|
|||
{
|
||||
uint8_t bitmap;
|
||||
int usb_err;
|
||||
int transferred;
|
||||
|
||||
/* Read port A for bit op */
|
||||
usb_err = ep1_generic_commandl(
|
||||
|
@ -929,17 +947,18 @@ static void rlink_reset(int trst, int srst)
|
|||
1
|
||||
);
|
||||
if (usb_err < 0) {
|
||||
LOG_ERROR("%s", usb_strerror());
|
||||
LOG_ERROR("%s", libusb_error_name(usb_err));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
usb_err = usb_bulk_read(
|
||||
usb_err = jtag_libusb_bulk_read(
|
||||
pHDev, USB_EP1IN_ADDR,
|
||||
(char *)&bitmap, 1,
|
||||
USB_TIMEOUT_MS
|
||||
USB_TIMEOUT_MS,
|
||||
&transferred
|
||||
);
|
||||
if (usb_err < 1) {
|
||||
LOG_ERROR("%s", usb_strerror());
|
||||
if (usb_err != ERROR_OK || transferred < 1) {
|
||||
LOG_ERROR("%s", libusb_error_name(usb_err));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
@ -964,17 +983,18 @@ static void rlink_reset(int trst, int srst)
|
|||
1
|
||||
);
|
||||
if (usb_err < 0) {
|
||||
LOG_ERROR("%s", usb_strerror());
|
||||
LOG_ERROR("%s", libusb_error_name(usb_err));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
usb_err = usb_bulk_read(
|
||||
usb_err = jtag_libusb_bulk_read(
|
||||
pHDev, USB_EP1IN_ADDR,
|
||||
(char *)&bitmap, 1,
|
||||
USB_TIMEOUT_MS
|
||||
USB_TIMEOUT_MS,
|
||||
&transferred
|
||||
);
|
||||
if (usb_err < 1) {
|
||||
LOG_ERROR("%s", usb_strerror());
|
||||
if (usb_err != ERROR_OK || transferred < 1) {
|
||||
LOG_ERROR("%s", libusb_error_name(usb_err));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
@ -994,17 +1014,18 @@ static void rlink_reset(int trst, int srst)
|
|||
EP1_CMD_DTC_GET_CACHED_STATUS
|
||||
);
|
||||
if (usb_err < 0) {
|
||||
LOG_ERROR("%s", usb_strerror());
|
||||
LOG_ERROR("%s", libusb_error_name(usb_err));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
usb_err = usb_bulk_read(
|
||||
usb_err = jtag_libusb_bulk_read(
|
||||
pHDev, USB_EP1IN_ADDR,
|
||||
(char *)&bitmap, 1,
|
||||
USB_TIMEOUT_MS
|
||||
USB_TIMEOUT_MS,
|
||||
&transferred
|
||||
);
|
||||
if (usb_err < 1) {
|
||||
LOG_ERROR("%s", usb_strerror());
|
||||
if (usb_err != ERROR_OK || transferred < 1) {
|
||||
LOG_ERROR("%s", libusb_error_name(usb_err));
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
@ -1391,8 +1412,9 @@ static int rlink_speed(int speed)
|
|||
exit(1);
|
||||
}
|
||||
|
||||
if (dtc_start_download() < 0) {
|
||||
LOG_ERROR("starting DTC: %s", usb_strerror());
|
||||
int ret = dtc_start_download();
|
||||
if (ret < 0) {
|
||||
LOG_ERROR("starting DTC: %s", libusb_error_name(ret));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
@ -1444,19 +1466,28 @@ static int rlink_init(void)
|
|||
{
|
||||
int i, j, retries;
|
||||
uint8_t reply_buffer[USB_EP1IN_SIZE];
|
||||
int transferred;
|
||||
|
||||
usb_init();
|
||||
const uint16_t vids[] = { USB_IDVENDOR, 0 };
|
||||
const uint16_t pids[] = { USB_IDPRODUCT, 0 };
|
||||
if (jtag_usb_open(vids, pids, &pHDev) != ERROR_OK)
|
||||
if (jtag_libusb_open(vids, pids, NULL, &pHDev, NULL) != ERROR_OK)
|
||||
return ERROR_FAIL;
|
||||
|
||||
struct usb_device *dev = usb_device(pHDev);
|
||||
if (dev->descriptor.bNumConfigurations > 1) {
|
||||
struct libusb_device_descriptor descriptor;
|
||||
struct libusb_device *usb_dev = libusb_get_device(pHDev);
|
||||
int r = libusb_get_device_descriptor(usb_dev, &descriptor);
|
||||
if (r < 0) {
|
||||
LOG_ERROR("error %d getting device descriptor", r);
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
|
||||
if (descriptor.bNumConfigurations > 1) {
|
||||
LOG_ERROR("Whoops! NumConfigurations is not 1, don't know what to do...");
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
if (dev->config->bNumInterfaces > 1) {
|
||||
struct libusb_config_descriptor *config;
|
||||
libusb_get_config_descriptor(usb_dev, 0, &config);
|
||||
if (config->bNumInterfaces > 1) {
|
||||
LOG_ERROR("Whoops! NumInterfaces is not 1, don't know what to do...");
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
|
@ -1464,29 +1495,27 @@ static int rlink_init(void)
|
|||
LOG_DEBUG("Opened device, pHDev = %p", pHDev);
|
||||
|
||||
/* usb_set_configuration required under win32 */
|
||||
usb_set_configuration(pHDev, dev->config[0].bConfigurationValue);
|
||||
libusb_set_configuration(pHDev, config->bConfigurationValue);
|
||||
|
||||
retries = 3;
|
||||
do {
|
||||
i = usb_claim_interface(pHDev, 0);
|
||||
if (i) {
|
||||
LOG_ERROR("usb_claim_interface: %s", usb_strerror());
|
||||
#ifdef LIBUSB_HAS_DETACH_KERNEL_DRIVER_NP
|
||||
j = usb_detach_kernel_driver_np(pHDev, 0);
|
||||
if (j)
|
||||
LOG_ERROR("detach kernel driver: %s", usb_strerror());
|
||||
#endif
|
||||
i = libusb_claim_interface(pHDev, 0);
|
||||
if (i != LIBUSB_SUCCESS) {
|
||||
LOG_ERROR("usb_claim_interface: %s", libusb_error_name(i));
|
||||
j = libusb_detach_kernel_driver(pHDev, 0);
|
||||
if (j != LIBUSB_SUCCESS)
|
||||
LOG_ERROR("detach kernel driver: %s", libusb_error_name(j));
|
||||
} else {
|
||||
LOG_DEBUG("interface claimed!");
|
||||
break;
|
||||
}
|
||||
} while (--retries);
|
||||
|
||||
if (i) {
|
||||
if (i != LIBUSB_SUCCESS) {
|
||||
LOG_ERROR("Initialisation failed.");
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
if (usb_set_altinterface(pHDev, 0) != 0) {
|
||||
if (libusb_set_interface_alt_setting(pHDev, 0, 0) != LIBUSB_SUCCESS) {
|
||||
LOG_ERROR("Failed to set interface.");
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
|
@ -1506,20 +1535,21 @@ static int rlink_init(void)
|
|||
EP1_CMD_GET_FWREV
|
||||
);
|
||||
if (j < USB_EP1OUT_SIZE) {
|
||||
LOG_ERROR("USB write error: %s", usb_strerror());
|
||||
LOG_ERROR("USB write error: %s", libusb_error_name(j));
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
j = usb_bulk_read(
|
||||
j = jtag_libusb_bulk_read(
|
||||
pHDev, USB_EP1IN_ADDR,
|
||||
(char *)reply_buffer, sizeof(reply_buffer),
|
||||
200
|
||||
200,
|
||||
&transferred
|
||||
);
|
||||
if (j != -ETIMEDOUT)
|
||||
if (j != LIBUSB_ERROR_TIMEOUT)
|
||||
break;
|
||||
}
|
||||
|
||||
if (j < (int)sizeof(reply_buffer)) {
|
||||
LOG_ERROR("USB read error: %s", usb_strerror());
|
||||
if (j != ERROR_OK || transferred != (int)sizeof(reply_buffer)) {
|
||||
LOG_ERROR("USB read error: %s", libusb_error_name(j));
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
LOG_DEBUG(INTERFACE_NAME " firmware version: %d.%d.%d",
|
||||
|
@ -1552,10 +1582,11 @@ static int rlink_init(void)
|
|||
ST7_PE_ADAPTER_SENSE_OUT
|
||||
);
|
||||
|
||||
usb_bulk_read(
|
||||
jtag_libusb_bulk_read(
|
||||
pHDev, USB_EP1IN_ADDR,
|
||||
(char *)reply_buffer, 1,
|
||||
USB_TIMEOUT_MS
|
||||
USB_TIMEOUT_MS,
|
||||
&transferred
|
||||
);
|
||||
|
||||
if ((reply_buffer[0] & ST7_PE_ADAPTER_SENSE_IN) != 0)
|
||||
|
@ -1576,10 +1607,11 @@ static int rlink_init(void)
|
|||
0x00 /* OR */
|
||||
);
|
||||
|
||||
usb_bulk_read(
|
||||
jtag_libusb_bulk_read(
|
||||
pHDev, USB_EP1IN_ADDR,
|
||||
(char *)reply_buffer, 1,
|
||||
USB_TIMEOUT_MS
|
||||
USB_TIMEOUT_MS,
|
||||
&transferred
|
||||
);
|
||||
|
||||
|
||||
|
@ -1655,8 +1687,8 @@ static int rlink_quit(void)
|
|||
~0
|
||||
);
|
||||
|
||||
usb_release_interface(pHDev, 0);
|
||||
usb_close(pHDev);
|
||||
libusb_release_interface(pHDev, 0);
|
||||
libusb_close(pHDev);
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
|
|
@ -1,4 +1,7 @@
|
|||
/***************************************************************************
|
||||
* Copyright (C) 2020 by Tarek Bochkati *
|
||||
* Tarek Bochkati <tarek.bouchkati@gmail.com> *
|
||||
* *
|
||||
* SWIM contributions by Ake Rehnman *
|
||||
* Copyright (C) 2017 Ake Rehnman *
|
||||
* ake.rehnman(at)gmail.com *
|
||||
|
@ -43,6 +46,16 @@
|
|||
|
||||
#include <target/cortex_m.h>
|
||||
|
||||
#include <helper/system.h>
|
||||
|
||||
#ifdef HAVE_ARPA_INET_H
|
||||
#include <arpa/inet.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_NETINET_TCP_H
|
||||
#include <netinet/tcp.h>
|
||||
#endif
|
||||
|
||||
#include "libusb_helper.h"
|
||||
|
||||
#ifdef HAVE_LIBUSB1
|
||||
|
@ -120,12 +133,48 @@ struct stlink_usb_version {
|
|||
uint32_t flags;
|
||||
};
|
||||
|
||||
/** */
|
||||
struct stlink_usb_handle_s {
|
||||
struct stlink_usb_priv_s {
|
||||
/** */
|
||||
struct libusb_device_handle *fd;
|
||||
/** */
|
||||
struct libusb_transfer *trans;
|
||||
};
|
||||
|
||||
struct stlink_tcp_priv_s {
|
||||
/** */
|
||||
int fd;
|
||||
/** */
|
||||
bool connected;
|
||||
/** */
|
||||
uint32_t device_id;
|
||||
/** */
|
||||
uint32_t connect_id;
|
||||
/** */
|
||||
uint8_t *send_buf;
|
||||
/** */
|
||||
uint8_t *recv_buf;
|
||||
};
|
||||
|
||||
struct stlink_backend_s {
|
||||
/** */
|
||||
int (*open)(void *handle, struct hl_interface_param_s *param);
|
||||
/** */
|
||||
int (*close)(void *handle);
|
||||
/** */
|
||||
int (*xfer_noerrcheck)(void *handle, const uint8_t *buf, int size);
|
||||
/** */
|
||||
int (*read_trace)(void *handle, const uint8_t *buf, int size);
|
||||
};
|
||||
|
||||
/** */
|
||||
struct stlink_usb_handle_s {
|
||||
/** */
|
||||
struct stlink_backend_s *backend;
|
||||
/** */
|
||||
union {
|
||||
struct stlink_usb_priv_s usb_backend_priv;
|
||||
struct stlink_tcp_priv_s tcp_backend_priv;
|
||||
};
|
||||
/** */
|
||||
uint8_t rx_ep;
|
||||
/** */
|
||||
|
@ -133,13 +182,13 @@ struct stlink_usb_handle_s {
|
|||
/** */
|
||||
uint8_t trace_ep;
|
||||
/** */
|
||||
uint8_t cmdbuf[STLINK_SG_SIZE];
|
||||
uint8_t *cmdbuf;
|
||||
/** */
|
||||
uint8_t cmdidx;
|
||||
/** */
|
||||
uint8_t direction;
|
||||
/** */
|
||||
uint8_t databuf[STLINK_DATA_SIZE];
|
||||
uint8_t *databuf;
|
||||
/** */
|
||||
uint32_t max_mem_packet;
|
||||
/** */
|
||||
|
@ -162,6 +211,26 @@ struct stlink_usb_handle_s {
|
|||
bool reconnect_pending;
|
||||
};
|
||||
|
||||
/** */
|
||||
static inline int stlink_usb_open(void *handle, struct hl_interface_param_s *param)
|
||||
{
|
||||
struct stlink_usb_handle_s *h = handle;
|
||||
return h->backend->open(handle, param);
|
||||
}
|
||||
|
||||
/** */
|
||||
static inline int stlink_usb_close(void *handle)
|
||||
{
|
||||
struct stlink_usb_handle_s *h = handle;
|
||||
return h->backend->close(handle);
|
||||
}
|
||||
/** */
|
||||
static inline int stlink_usb_xfer_noerrcheck(void *handle, const uint8_t *buf, int size)
|
||||
{
|
||||
struct stlink_usb_handle_s *h = handle;
|
||||
return h->backend->xfer_noerrcheck(handle, buf, size);
|
||||
}
|
||||
|
||||
#define STLINK_SWIM_ERR_OK 0x00
|
||||
#define STLINK_SWIM_BUSY 0x01
|
||||
#define STLINK_DEBUG_ERR_OK 0x80
|
||||
|
@ -307,6 +376,39 @@ struct stlink_usb_handle_s {
|
|||
#define REQUEST_SENSE 0x03
|
||||
#define REQUEST_SENSE_LENGTH 18
|
||||
|
||||
/* STLINK TCP commands */
|
||||
#define STLINK_TCP_CMD_REFRESH_DEVICE_LIST 0x00
|
||||
#define STLINK_TCP_CMD_GET_NB_DEV 0x01
|
||||
#define STLINK_TCP_CMD_GET_DEV_INFO 0x02
|
||||
#define STLINK_TCP_CMD_OPEN_DEV 0x03
|
||||
#define STLINK_TCP_CMD_CLOSE_DEV 0x04
|
||||
#define STLINK_TCP_CMD_SEND_USB_CMD 0x05
|
||||
#define STLINK_TCP_CMD_GET_SERVER_VERSION 0x06
|
||||
#define STLINK_TCP_CMD_GET_NB_OF_DEV_CLIENTS 0x07
|
||||
|
||||
/* STLINK TCP constants */
|
||||
#define OPENOCD_STLINK_TCP_API_VERSION 1
|
||||
#define STLINK_TCP_REQUEST_WRITE 0
|
||||
#define STLINK_TCP_REQUEST_READ 1
|
||||
#define STLINK_TCP_REQUEST_READ_SWO 3
|
||||
#define STLINK_TCP_SS_SIZE 4
|
||||
#define STLINK_TCP_USB_CMD_SIZE 32
|
||||
#define STLINK_TCP_SERIAL_SIZE 32
|
||||
#define STLINK_TCP_SEND_BUFFER_SIZE 10240
|
||||
#define STLINK_TCP_RECV_BUFFER_SIZE 10240
|
||||
|
||||
/* STLINK TCP command status */
|
||||
#define STLINK_TCP_SS_OK 0x00000001
|
||||
#define STLINK_TCP_SS_MEMORY_PROBLEM 0x00001000
|
||||
#define STLINK_TCP_SS_TIMEOUT 0x00001001
|
||||
#define STLINK_TCP_SS_BAD_PARAMETER 0x00001002
|
||||
#define STLINK_TCP_SS_OPEN_ERR 0x00001003
|
||||
#define STLINK_TCP_SS_TRUNCATED_DATA 0x00001052
|
||||
#define STLINK_TCP_SS_CMD_NOT_AVAILABLE 0x00001053
|
||||
#define STLINK_TCP_SS_TCP_ERROR 0x00002001
|
||||
#define STLINK_TCP_SS_TCP_CANT_CONNECT 0x00002002
|
||||
#define STLINK_TCP_SS_WIN32_ERROR 0x00010000
|
||||
|
||||
/*
|
||||
* Map the relevant features, quirks and workaround for specific firmware
|
||||
* version of stlink
|
||||
|
@ -381,8 +483,6 @@ static unsigned int stlink_usb_block(void *handle)
|
|||
return STLINK_MAX_RW8;
|
||||
}
|
||||
|
||||
|
||||
|
||||
#ifdef USE_LIBUSB_ASYNCIO
|
||||
|
||||
static LIBUSB_CALL void sync_transfer_cb(struct libusb_transfer *transfer)
|
||||
|
@ -546,7 +646,7 @@ static int stlink_usb_xfer_v1_get_status(void *handle)
|
|||
/* read status */
|
||||
memset(h->cmdbuf, 0, STLINK_SG_SIZE);
|
||||
|
||||
ret = jtag_libusb_bulk_read(h->fd, h->rx_ep, (char *)h->cmdbuf, 13,
|
||||
ret = jtag_libusb_bulk_read(h->usb_backend_priv.fd, h->rx_ep, (char *)h->cmdbuf, 13,
|
||||
STLINK_READ_TIMEOUT, &tr);
|
||||
if (ret || tr != 13)
|
||||
return ERROR_FAIL;
|
||||
|
@ -603,7 +703,7 @@ static int stlink_usb_xfer_rw(void *handle, int cmdsize, const uint8_t *buf, int
|
|||
}
|
||||
|
||||
return jtag_libusb_bulk_transfer_n(
|
||||
h->fd,
|
||||
h->usb_backend_priv.fd,
|
||||
transfers,
|
||||
n_transfers,
|
||||
STLINK_WRITE_TIMEOUT);
|
||||
|
@ -616,20 +716,20 @@ static int stlink_usb_xfer_rw(void *handle, int cmdsize, const uint8_t *buf, int
|
|||
|
||||
assert(handle != NULL);
|
||||
|
||||
ret = jtag_libusb_bulk_write(h->fd, h->tx_ep, (char *)h->cmdbuf,
|
||||
ret = jtag_libusb_bulk_write(h->usb_backend_priv.fd, h->tx_ep, (char *)h->cmdbuf,
|
||||
cmdsize, STLINK_WRITE_TIMEOUT, &tr);
|
||||
if (ret || tr != cmdsize)
|
||||
return ERROR_FAIL;
|
||||
|
||||
if (h->direction == h->tx_ep && size) {
|
||||
ret = jtag_libusb_bulk_write(h->fd, h->tx_ep, (char *)buf,
|
||||
ret = jtag_libusb_bulk_write(h->usb_backend_priv.fd, h->tx_ep, (char *)buf,
|
||||
size, STLINK_WRITE_TIMEOUT, &tr);
|
||||
if (ret || tr != size) {
|
||||
LOG_DEBUG("bulk write failed");
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
} else if (h->direction == h->rx_ep && size) {
|
||||
ret = jtag_libusb_bulk_read(h->fd, h->rx_ep, (char *)buf,
|
||||
ret = jtag_libusb_bulk_read(h->usb_backend_priv.fd, h->rx_ep, (char *)buf,
|
||||
size, STLINK_READ_TIMEOUT, &tr);
|
||||
if (ret || tr != size) {
|
||||
LOG_DEBUG("bulk read failed");
|
||||
|
@ -668,13 +768,29 @@ static int stlink_usb_xfer_v1_get_sense(void *handle)
|
|||
return ERROR_OK;
|
||||
}
|
||||
|
||||
/** */
|
||||
static int stlink_usb_usb_read_trace(void *handle, const uint8_t *buf, int size)
|
||||
{
|
||||
struct stlink_usb_handle_s *h = handle;
|
||||
int tr, ret;
|
||||
|
||||
ret = jtag_libusb_bulk_read(h->usb_backend_priv.fd, h->trace_ep, (char *)buf, size,
|
||||
STLINK_READ_TIMEOUT, &tr);
|
||||
if (ret || tr != size) {
|
||||
LOG_ERROR("bulk trace read failed");
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
transfers block in cmdbuf
|
||||
<size> indicates number of bytes in the following
|
||||
data phase.
|
||||
Ignore the (eventual) error code in the received packet.
|
||||
*/
|
||||
static int stlink_usb_xfer_noerrcheck(void *handle, const uint8_t *buf, int size)
|
||||
static int stlink_usb_usb_xfer_noerrcheck(void *handle, const uint8_t *buf, int size)
|
||||
{
|
||||
int err, cmdsize = STLINK_CMD_SIZE_V2;
|
||||
struct stlink_usb_handle_s *h = handle;
|
||||
|
@ -707,6 +823,117 @@ static int stlink_usb_xfer_noerrcheck(void *handle, const uint8_t *buf, int size
|
|||
return ERROR_OK;
|
||||
}
|
||||
|
||||
|
||||
static int stlink_tcp_send_cmd(void *handle, int send_size, int recv_size, bool check_tcp_status)
|
||||
{
|
||||
struct stlink_usb_handle_s *h = handle;
|
||||
|
||||
assert(handle != NULL);
|
||||
|
||||
/* send the TCP command */
|
||||
int sent_size = send(h->tcp_backend_priv.fd, (void *)h->tcp_backend_priv.send_buf, send_size, 0);
|
||||
if (sent_size != send_size) {
|
||||
LOG_ERROR("failed to send USB CMD");
|
||||
if (sent_size == -1)
|
||||
LOG_DEBUG("socket send error: %s (errno %d)", strerror(errno), errno);
|
||||
else
|
||||
LOG_DEBUG("sent size %d (expected %d)", sent_size, send_size);
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
|
||||
keep_alive();
|
||||
|
||||
/* read the TCP response */
|
||||
int received_size = recv(h->tcp_backend_priv.fd, (void *)h->tcp_backend_priv.recv_buf, recv_size, 0);
|
||||
if (received_size != recv_size) {
|
||||
LOG_ERROR("failed to receive USB CMD response");
|
||||
if (received_size == -1)
|
||||
LOG_DEBUG("socket recv error: %s (errno %d)", strerror(errno), errno);
|
||||
else
|
||||
LOG_DEBUG("received size %d (expected %d)", received_size, recv_size);
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
|
||||
if (check_tcp_status) {
|
||||
uint32_t tcp_ss = le_to_h_u32(h->tcp_backend_priv.recv_buf);
|
||||
if (tcp_ss != STLINK_TCP_SS_OK) {
|
||||
LOG_ERROR("TCP error status 0x%X", tcp_ss);
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
}
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
/** */
|
||||
static int stlink_tcp_xfer_noerrcheck(void *handle, const uint8_t *buf, int size)
|
||||
{
|
||||
struct stlink_usb_handle_s *h = handle;
|
||||
|
||||
int send_size = STLINK_TCP_USB_CMD_SIZE;
|
||||
int recv_size = STLINK_TCP_SS_SIZE;
|
||||
|
||||
assert(handle != NULL);
|
||||
|
||||
/* prepare the TCP command */
|
||||
h->tcp_backend_priv.send_buf[0] = STLINK_TCP_CMD_SEND_USB_CMD;
|
||||
memset(&h->tcp_backend_priv.send_buf[1], 0, 3); /* reserved for alignment and future use, must be zero */
|
||||
h_u32_to_le(&h->tcp_backend_priv.send_buf[4], h->tcp_backend_priv.connect_id);
|
||||
/* tcp_backend_priv.send_buf[8..23] already contains the constructed stlink command */
|
||||
h->tcp_backend_priv.send_buf[24] = h->direction;
|
||||
memset(&h->tcp_backend_priv.send_buf[25], 0, 3); /* reserved for alignment and future use, must be zero */
|
||||
|
||||
h_u32_to_le(&h->tcp_backend_priv.send_buf[28], size);
|
||||
|
||||
/*
|
||||
* if the xfer is a write request (tx_ep)
|
||||
* > then buf content will be copied
|
||||
* into &cmdbuf[32].
|
||||
* else : the xfer is a read or trace read request (rx_ep or trace_ep)
|
||||
* > the buf content will be filled from &databuf[4].
|
||||
*
|
||||
* note : if h->direction is trace_ep, h->cmdbuf is zeros.
|
||||
*/
|
||||
|
||||
if (h->direction == h->tx_ep) { /* STLINK_TCP_REQUEST_WRITE */
|
||||
send_size += size;
|
||||
if (send_size > STLINK_TCP_SEND_BUFFER_SIZE) {
|
||||
LOG_ERROR("STLINK_TCP command buffer overflow");
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
memcpy(&h->tcp_backend_priv.send_buf[32], buf, size);
|
||||
} else { /* STLINK_TCP_REQUEST_READ or STLINK_TCP_REQUEST_READ_SWO */
|
||||
recv_size += size;
|
||||
if (recv_size > STLINK_TCP_RECV_BUFFER_SIZE) {
|
||||
LOG_ERROR("STLINK_TCP data buffer overflow");
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
}
|
||||
|
||||
int ret = stlink_tcp_send_cmd(h, send_size, recv_size, true);
|
||||
if (ret != ERROR_OK)
|
||||
return ret;
|
||||
|
||||
if (h->direction != h->tx_ep) {
|
||||
/* the read data is located in tcp_backend_priv.recv_buf[4] */
|
||||
/* most of the case it will be copying the data from tcp_backend_priv.recv_buf[4]
|
||||
* to handle->cmd_buff which are the same, so let's avoid unnecessary copying */
|
||||
if (buf != &h->tcp_backend_priv.recv_buf[4])
|
||||
memcpy((uint8_t *)buf, &h->tcp_backend_priv.recv_buf[4], size);
|
||||
}
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
/** */
|
||||
static int stlink_tcp_read_trace(void *handle, const uint8_t *buf, int size)
|
||||
{
|
||||
struct stlink_usb_handle_s *h = handle;
|
||||
|
||||
stlink_usb_init_buffer(h, h->trace_ep, 0);
|
||||
return stlink_tcp_xfer_noerrcheck(handle, buf, size);
|
||||
}
|
||||
|
||||
/**
|
||||
Converts an STLINK status code held in the first byte of a response
|
||||
to an openocd error, logs any error/wait status as debug output.
|
||||
|
@ -853,20 +1080,12 @@ static int stlink_cmd_allow_retry(void *handle, const uint8_t *buf, int size)
|
|||
static int stlink_usb_read_trace(void *handle, const uint8_t *buf, int size)
|
||||
{
|
||||
struct stlink_usb_handle_s *h = handle;
|
||||
int tr, ret;
|
||||
|
||||
assert(handle != NULL);
|
||||
|
||||
assert(h->version.flags & STLINK_F_HAS_TRACE);
|
||||
|
||||
ret = jtag_libusb_bulk_read(h->fd, h->trace_ep, (char *)buf, size,
|
||||
STLINK_READ_TIMEOUT, &tr);
|
||||
if (ret || tr != size) {
|
||||
LOG_ERROR("bulk trace read failed");
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
|
||||
return ERROR_OK;
|
||||
return h->backend->read_trace(handle, buf, size);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1749,7 +1968,7 @@ static int stlink_usb_trace_read(void *handle, uint8_t *buf, size_t *size)
|
|||
return res;
|
||||
|
||||
size_t bytes_avail = le_to_h_u16(h->databuf);
|
||||
*size = bytes_avail < *size ? bytes_avail : *size - 1;
|
||||
*size = bytes_avail < *size ? bytes_avail : *size;
|
||||
|
||||
if (*size > 0) {
|
||||
res = stlink_usb_read_trace(handle, buf, *size);
|
||||
|
@ -2716,18 +2935,68 @@ static int stlink_speed(void *handle, int khz, bool query)
|
|||
}
|
||||
|
||||
/** */
|
||||
static int stlink_usb_close(void *handle)
|
||||
static int stlink_usb_usb_close(void *handle)
|
||||
{
|
||||
struct stlink_usb_handle_s *h = handle;
|
||||
|
||||
if (h && h->fd) {
|
||||
if (!h)
|
||||
return ERROR_OK;
|
||||
|
||||
if (h->usb_backend_priv.fd) {
|
||||
stlink_usb_exit_mode(h);
|
||||
/* do not check return code, it prevent
|
||||
us from closing jtag_libusb */
|
||||
jtag_libusb_close(h->fd);
|
||||
jtag_libusb_close(h->usb_backend_priv.fd);
|
||||
}
|
||||
|
||||
free(h);
|
||||
free(h->cmdbuf);
|
||||
free(h->databuf);
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
/** */
|
||||
static int stlink_tcp_close(void *handle)
|
||||
{
|
||||
struct stlink_usb_handle_s *h = handle;
|
||||
|
||||
if (!h)
|
||||
return ERROR_OK;
|
||||
|
||||
int ret = ERROR_OK;
|
||||
if (h->tcp_backend_priv.connected) {
|
||||
if (h->tcp_backend_priv.connect_id) {
|
||||
stlink_usb_exit_mode(h);
|
||||
|
||||
/* close the stlink */
|
||||
h->tcp_backend_priv.send_buf[0] = STLINK_TCP_CMD_CLOSE_DEV;
|
||||
memset(&h->tcp_backend_priv.send_buf[1], 0, 4); /* reserved */
|
||||
h_u32_to_le(&h->tcp_backend_priv.send_buf[4], h->tcp_backend_priv.connect_id);
|
||||
ret = stlink_tcp_send_cmd(h, 8, 4, true);
|
||||
if (ret != ERROR_OK)
|
||||
LOG_ERROR("cannot close the STLINK");
|
||||
}
|
||||
|
||||
if (close_socket(h->tcp_backend_priv.fd) != 0)
|
||||
LOG_ERROR("error closing the socket, errno: %s", strerror(errno));
|
||||
}
|
||||
|
||||
free(h->tcp_backend_priv.send_buf);
|
||||
free(h->tcp_backend_priv.recv_buf);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/** */
|
||||
static int stlink_close(void *handle)
|
||||
{
|
||||
if (handle != NULL) {
|
||||
struct stlink_usb_handle_s *h = handle;
|
||||
|
||||
stlink_usb_close(handle);
|
||||
|
||||
free(h);
|
||||
}
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
@ -2812,27 +3081,16 @@ static char *stlink_usb_get_alternate_serial(libusb_device_handle *device,
|
|||
}
|
||||
|
||||
/** */
|
||||
static int stlink_usb_open(struct hl_interface_param_s *param, enum stlink_mode mode, void **fd)
|
||||
static int stlink_usb_usb_open(void *handle, struct hl_interface_param_s *param)
|
||||
{
|
||||
struct stlink_usb_handle_s *h = handle;
|
||||
int err, retry_count = 1;
|
||||
struct stlink_usb_handle_s *h;
|
||||
|
||||
LOG_DEBUG("stlink_usb_open");
|
||||
h->cmdbuf = malloc(STLINK_SG_SIZE);
|
||||
h->databuf = malloc(STLINK_DATA_SIZE);
|
||||
|
||||
h = calloc(1, sizeof(struct stlink_usb_handle_s));
|
||||
|
||||
if (h == 0) {
|
||||
LOG_DEBUG("malloc failed");
|
||||
if (h->cmdbuf == NULL || h->databuf == NULL)
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
|
||||
h->st_mode = mode;
|
||||
|
||||
for (unsigned i = 0; param->vid[i]; i++) {
|
||||
LOG_DEBUG("transport: %d vid: 0x%04x pid: 0x%04x serial: %s",
|
||||
h->st_mode, param->vid[i], param->pid[i],
|
||||
param->serial ? param->serial : "");
|
||||
}
|
||||
|
||||
/*
|
||||
On certain host USB configurations(e.g. MacBook Air)
|
||||
|
@ -2845,25 +3103,25 @@ static int stlink_usb_open(struct hl_interface_param_s *param, enum stlink_mode
|
|||
*/
|
||||
do {
|
||||
if (jtag_libusb_open(param->vid, param->pid, param->serial,
|
||||
&h->fd, stlink_usb_get_alternate_serial) != ERROR_OK) {
|
||||
&h->usb_backend_priv.fd, stlink_usb_get_alternate_serial) != ERROR_OK) {
|
||||
LOG_ERROR("open failed");
|
||||
goto error_open;
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
|
||||
jtag_libusb_set_configuration(h->fd, 0);
|
||||
jtag_libusb_set_configuration(h->usb_backend_priv.fd, 0);
|
||||
|
||||
if (libusb_claim_interface(h->fd, 0) != ERROR_OK) {
|
||||
if (libusb_claim_interface(h->usb_backend_priv.fd, 0) != ERROR_OK) {
|
||||
LOG_DEBUG("claim interface failed");
|
||||
goto error_open;
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
|
||||
/* RX EP is common for all versions */
|
||||
h->rx_ep = STLINK_RX_EP;
|
||||
|
||||
uint16_t pid;
|
||||
if (jtag_libusb_get_pid(libusb_get_device(h->fd), &pid) != ERROR_OK) {
|
||||
if (jtag_libusb_get_pid(libusb_get_device(h->usb_backend_priv.fd), &pid) != ERROR_OK) {
|
||||
LOG_DEBUG("libusb_get_pid failed");
|
||||
goto error_open;
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
|
||||
/* wrap version for first read */
|
||||
|
@ -2903,21 +3161,21 @@ static int stlink_usb_open(struct hl_interface_param_s *param, enum stlink_mode
|
|||
} else if (h->version.stlink == 1 ||
|
||||
retry_count == 0) {
|
||||
LOG_ERROR("read version failed");
|
||||
goto error_open;
|
||||
return ERROR_FAIL;
|
||||
} else {
|
||||
err = libusb_release_interface(h->fd, 0);
|
||||
err = libusb_release_interface(h->usb_backend_priv.fd, 0);
|
||||
if (err != ERROR_OK) {
|
||||
LOG_ERROR("release interface failed");
|
||||
goto error_open;
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
|
||||
err = libusb_reset_device(h->fd);
|
||||
err = libusb_reset_device(h->usb_backend_priv.fd);
|
||||
if (err != ERROR_OK) {
|
||||
LOG_ERROR("reset device failed");
|
||||
goto error_open;
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
|
||||
jtag_libusb_close(h->fd);
|
||||
jtag_libusb_close(h->usb_backend_priv.fd);
|
||||
/*
|
||||
Give the device one second to settle down and
|
||||
reenumerate.
|
||||
|
@ -2927,8 +3185,265 @@ static int stlink_usb_open(struct hl_interface_param_s *param, enum stlink_mode
|
|||
}
|
||||
} while (1);
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
/** */
|
||||
static int stlink_tcp_open(void *handle, struct hl_interface_param_s *param)
|
||||
{
|
||||
struct stlink_usb_handle_s *h = handle;
|
||||
int ret;
|
||||
|
||||
/* SWIM is not supported using stlink-server */
|
||||
if (h->st_mode == STLINK_MODE_DEBUG_SWIM) {
|
||||
LOG_ERROR("stlink-server does not support SWIM mode");
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
|
||||
h->tcp_backend_priv.send_buf = malloc(STLINK_TCP_SEND_BUFFER_SIZE);
|
||||
h->tcp_backend_priv.recv_buf = malloc(STLINK_TCP_RECV_BUFFER_SIZE);
|
||||
|
||||
if (h->tcp_backend_priv.send_buf == NULL || h->tcp_backend_priv.recv_buf == NULL)
|
||||
return ERROR_FAIL;
|
||||
|
||||
h->cmdbuf = &h->tcp_backend_priv.send_buf[8];
|
||||
h->databuf = &h->tcp_backend_priv.recv_buf[4];
|
||||
|
||||
/* configure directions */
|
||||
h->rx_ep = STLINK_TCP_REQUEST_READ;
|
||||
h->tx_ep = STLINK_TCP_REQUEST_WRITE;
|
||||
h->trace_ep = STLINK_TCP_REQUEST_READ_SWO;
|
||||
|
||||
h->tcp_backend_priv.fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
|
||||
h->tcp_backend_priv.connected = false;
|
||||
h->tcp_backend_priv.device_id = 0;
|
||||
h->tcp_backend_priv.connect_id = 0;
|
||||
|
||||
if (h->tcp_backend_priv.fd == -1) {
|
||||
LOG_ERROR("error creating the socket, errno: %s", strerror(errno));
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
|
||||
struct sockaddr_in serv;
|
||||
memset(&serv, 0, sizeof(struct sockaddr_in));
|
||||
serv.sin_family = AF_INET;
|
||||
serv.sin_port = htons(param->stlink_tcp_port);
|
||||
serv.sin_addr.s_addr = inet_addr("127.0.0.1");
|
||||
|
||||
LOG_DEBUG("socket : %x", h->tcp_backend_priv.fd);
|
||||
|
||||
int optval = 1;
|
||||
if (setsockopt(h->tcp_backend_priv.fd, IPPROTO_TCP, TCP_NODELAY, (const void *)&optval, sizeof(int)) == -1) {
|
||||
LOG_ERROR("cannot set sock option 'TCP_NODELAY', errno: %s", strerror(errno));
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
|
||||
optval = STLINK_TCP_RECV_BUFFER_SIZE;
|
||||
if (setsockopt(h->tcp_backend_priv.fd, SOL_SOCKET, SO_RCVBUF, (const void *)&optval, sizeof(int)) == -1) {
|
||||
LOG_ERROR("cannot set sock option 'SO_RCVBUF', errno: %s", strerror(errno));
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
|
||||
optval = STLINK_TCP_SEND_BUFFER_SIZE;
|
||||
if (setsockopt(h->tcp_backend_priv.fd, SOL_SOCKET, SO_SNDBUF, (const void *)&optval, sizeof(int)) == -1) {
|
||||
LOG_ERROR("cannot set sock option 'SO_SNDBUF', errno: %s", strerror(errno));
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
|
||||
if (connect(h->tcp_backend_priv.fd, (const struct sockaddr *)&serv, sizeof(serv)) == -1) {
|
||||
LOG_ERROR("cannot connect to stlink server, errno: %s", strerror(errno));
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
|
||||
h->tcp_backend_priv.connected = true;
|
||||
|
||||
LOG_INFO("connected to stlink-server");
|
||||
|
||||
/* print stlink-server version */
|
||||
h->tcp_backend_priv.send_buf[0] = STLINK_TCP_CMD_GET_SERVER_VERSION;
|
||||
h->tcp_backend_priv.send_buf[1] = OPENOCD_STLINK_TCP_API_VERSION;
|
||||
memset(&h->tcp_backend_priv.send_buf[2], 0, 2); /* reserved */
|
||||
ret = stlink_tcp_send_cmd(h, 4, 16, false);
|
||||
if (ret != ERROR_OK) {
|
||||
LOG_ERROR("cannot get the stlink-server version");
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
|
||||
uint32_t api_ver = le_to_h_u32(&h->tcp_backend_priv.recv_buf[0]);
|
||||
uint32_t ver_major = le_to_h_u32(&h->tcp_backend_priv.recv_buf[4]);
|
||||
uint32_t ver_minor = le_to_h_u32(&h->tcp_backend_priv.recv_buf[8]);
|
||||
uint32_t ver_build = le_to_h_u32(&h->tcp_backend_priv.recv_buf[12]);
|
||||
LOG_INFO("stlink-server API v%d, version %d.%d.%d",
|
||||
api_ver, ver_major, ver_minor, ver_build);
|
||||
|
||||
/* in stlink-server API v1 sending more than 1428 bytes will cause stlink-server
|
||||
* to crash in windows: select a safe default value (1K) */
|
||||
if (api_ver < 2)
|
||||
h->max_mem_packet = (1 << 10);
|
||||
|
||||
/* refresh stlink list (re-enumerate) */
|
||||
h->tcp_backend_priv.send_buf[0] = STLINK_TCP_CMD_REFRESH_DEVICE_LIST;
|
||||
h->tcp_backend_priv.send_buf[1] = 0; /* don't clear the list, just refresh it */
|
||||
ret = stlink_tcp_send_cmd(h, 2, 4, true);
|
||||
if (ret != ERROR_OK)
|
||||
return ret;
|
||||
|
||||
/* get the number of connected stlinks */
|
||||
h->tcp_backend_priv.send_buf[0] = STLINK_TCP_CMD_GET_NB_DEV;
|
||||
ret = stlink_tcp_send_cmd(h, 1, 4, false);
|
||||
if (ret != ERROR_OK)
|
||||
return ret;
|
||||
|
||||
uint32_t connected_stlinks = le_to_h_u32(h->tcp_backend_priv.recv_buf);
|
||||
|
||||
if (connected_stlinks == 0) {
|
||||
LOG_ERROR("no ST-LINK detected");
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
|
||||
LOG_DEBUG("%d ST-LINK detected", connected_stlinks);
|
||||
|
||||
if (connected_stlinks > 255) {
|
||||
LOG_WARNING("STLink server cannot handle more than 255 ST-LINK connected");
|
||||
connected_stlinks = 255;
|
||||
}
|
||||
|
||||
/* list all connected ST-Link and seek for the requested vid:pid and serial */
|
||||
char serial[STLINK_TCP_SERIAL_SIZE + 1] = {0};
|
||||
uint8_t stlink_used;
|
||||
bool stlink_id_matched = false;
|
||||
bool stlink_serial_matched = (param->serial == NULL);
|
||||
|
||||
for (uint32_t stlink_id = 0; stlink_id < connected_stlinks; stlink_id++) {
|
||||
/* get the stlink info */
|
||||
h->tcp_backend_priv.send_buf[0] = STLINK_TCP_CMD_GET_DEV_INFO;
|
||||
h->tcp_backend_priv.send_buf[1] = (uint8_t)stlink_id;
|
||||
memset(&h->tcp_backend_priv.send_buf[2], 0, 2); /* reserved */
|
||||
h_u32_to_le(&h->tcp_backend_priv.send_buf[4], 41); /* size of TDeviceInfo2 */
|
||||
ret = stlink_tcp_send_cmd(h, 8, 45, true);
|
||||
if (ret != ERROR_OK)
|
||||
return ret;
|
||||
|
||||
h->tcp_backend_priv.device_id = le_to_h_u32(&h->tcp_backend_priv.recv_buf[4]);
|
||||
memcpy(serial, &h->tcp_backend_priv.recv_buf[8], STLINK_TCP_SERIAL_SIZE);
|
||||
h->vid = le_to_h_u16(&h->tcp_backend_priv.recv_buf[40]);
|
||||
h->pid = le_to_h_u16(&h->tcp_backend_priv.recv_buf[42]);
|
||||
stlink_used = h->tcp_backend_priv.recv_buf[44];
|
||||
|
||||
/* check the vid:pid */
|
||||
for (int i = 0; param->vid[i]; i++) {
|
||||
if (param->vid[i] == h->vid && param->pid[i] == h->pid) {
|
||||
stlink_id_matched = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!stlink_id_matched)
|
||||
continue;
|
||||
|
||||
/* check the serial if specified */
|
||||
if (param->serial) {
|
||||
/* ST-Link server fixes the buggy serial returned by old ST-Link DFU
|
||||
* for further details refer to stlink_usb_get_alternate_serial
|
||||
* so if the user passes the buggy serial, we need to fix it before
|
||||
* comparing with the serial returned by ST-Link server */
|
||||
if (strlen(param->serial) == STLINK_SERIAL_LEN / 2) {
|
||||
char fixed_serial[STLINK_SERIAL_LEN + 1];
|
||||
|
||||
for (unsigned int i = 0; i < STLINK_SERIAL_LEN; i += 2)
|
||||
sprintf(fixed_serial + i, "%02X", param->serial[i / 2]);
|
||||
|
||||
fixed_serial[STLINK_SERIAL_LEN] = '\0';
|
||||
|
||||
stlink_serial_matched = strcmp(fixed_serial, serial) == 0;
|
||||
} else
|
||||
stlink_serial_matched = strcmp(param->serial, serial) == 0;
|
||||
}
|
||||
|
||||
if (!stlink_serial_matched)
|
||||
LOG_DEBUG("Device serial number '%s' doesn't match requested serial '%s'",
|
||||
serial, param->serial);
|
||||
else /* exit the search loop if there is match */
|
||||
break;
|
||||
}
|
||||
|
||||
if (!stlink_id_matched) {
|
||||
LOG_ERROR("ST-LINK open failed (vid/pid mismatch)");
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
|
||||
if (!stlink_serial_matched) {
|
||||
LOG_ERROR("ST-LINK open failed (serial mismatch)");
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
|
||||
/* check if device is 'exclusively' used by another application */
|
||||
if (stlink_used) {
|
||||
LOG_ERROR("the selected device is already used");
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
|
||||
LOG_DEBUG("transport: vid: 0x%04x pid: 0x%04x serial: %s", h->vid, h->pid, serial);
|
||||
|
||||
/* now let's open the stlink */
|
||||
h->tcp_backend_priv.send_buf[0] = STLINK_TCP_CMD_OPEN_DEV;
|
||||
memset(&h->tcp_backend_priv.send_buf[1], 0, 4); /* reserved */
|
||||
h_u32_to_le(&h->tcp_backend_priv.send_buf[4], h->tcp_backend_priv.device_id);
|
||||
ret = stlink_tcp_send_cmd(h, 8, 8, true);
|
||||
if (ret != ERROR_OK)
|
||||
return ret;
|
||||
|
||||
h->tcp_backend_priv.connect_id = le_to_h_u32(&h->tcp_backend_priv.recv_buf[4]);
|
||||
|
||||
/* get stlink version */
|
||||
return stlink_usb_version(h);
|
||||
}
|
||||
|
||||
static struct stlink_backend_s stlink_usb_backend = {
|
||||
.open = stlink_usb_usb_open,
|
||||
.close = stlink_usb_usb_close,
|
||||
.xfer_noerrcheck = stlink_usb_usb_xfer_noerrcheck,
|
||||
.read_trace = stlink_usb_usb_read_trace,
|
||||
};
|
||||
|
||||
static struct stlink_backend_s stlink_tcp_backend = {
|
||||
.open = stlink_tcp_open,
|
||||
.close = stlink_tcp_close,
|
||||
.xfer_noerrcheck = stlink_tcp_xfer_noerrcheck,
|
||||
.read_trace = stlink_tcp_read_trace,
|
||||
};
|
||||
|
||||
static int stlink_open(struct hl_interface_param_s *param, enum stlink_mode mode, void **fd)
|
||||
{
|
||||
struct stlink_usb_handle_s *h;
|
||||
|
||||
LOG_DEBUG("stlink_open");
|
||||
|
||||
h = calloc(1, sizeof(struct stlink_usb_handle_s));
|
||||
|
||||
if (h == 0) {
|
||||
LOG_DEBUG("malloc failed");
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
|
||||
h->st_mode = mode;
|
||||
|
||||
for (unsigned i = 0; param->vid[i]; i++) {
|
||||
LOG_DEBUG("transport: %d vid: 0x%04x pid: 0x%04x serial: %s",
|
||||
h->st_mode, param->vid[i], param->pid[i],
|
||||
param->serial ? param->serial : "");
|
||||
}
|
||||
|
||||
if (param->use_stlink_tcp)
|
||||
h->backend = &stlink_tcp_backend;
|
||||
else
|
||||
h->backend = &stlink_usb_backend;
|
||||
|
||||
if (stlink_usb_open(h, param) != ERROR_OK)
|
||||
goto error_open;
|
||||
|
||||
/* check if mode is supported */
|
||||
err = ERROR_OK;
|
||||
int err = ERROR_OK;
|
||||
|
||||
switch (h->st_mode) {
|
||||
case STLINK_MODE_DEBUG_SWD:
|
||||
|
@ -2972,37 +3487,39 @@ static int stlink_usb_open(struct hl_interface_param_s *param, enum stlink_mode
|
|||
return ERROR_OK;
|
||||
}
|
||||
|
||||
/* get cpuid, so we can determine the max page size
|
||||
* start with a safe default */
|
||||
h->max_mem_packet = (1 << 10);
|
||||
/* set max_mem_packet if it was not set by the low-level interface */
|
||||
if (h->max_mem_packet == 0) {
|
||||
/* get cpuid, so we can determine the max page size
|
||||
* start with a safe default */
|
||||
h->max_mem_packet = (1 << 10);
|
||||
|
||||
uint8_t buffer[4];
|
||||
stlink_usb_open_ap(h, 0);
|
||||
err = stlink_usb_read_mem32(h, CPUID, 4, buffer);
|
||||
if (err == ERROR_OK) {
|
||||
uint32_t cpuid = le_to_h_u32(buffer);
|
||||
int i = (cpuid >> 4) & 0xf;
|
||||
if (i == 4 || i == 3) {
|
||||
/* Cortex-M3/M4 has 4096 bytes autoincrement range */
|
||||
h->max_mem_packet = (1 << 12);
|
||||
uint8_t buffer[4];
|
||||
stlink_usb_open_ap(h, 0);
|
||||
err = stlink_usb_read_mem32(h, CPUID, 4, buffer);
|
||||
if (err == ERROR_OK) {
|
||||
uint32_t cpuid = le_to_h_u32(buffer);
|
||||
int i = (cpuid >> 4) & 0xf;
|
||||
if (i == 4 || i == 3) {
|
||||
/* Cortex-M3/M4 has 4096 bytes autoincrement range */
|
||||
h->max_mem_packet = (1 << 12);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LOG_DEBUG("Using TAR autoincrement: %" PRIu32, h->max_mem_packet);
|
||||
LOG_DEBUG("Using TAR autoincrement: %" PRIu32, h->max_mem_packet);
|
||||
}
|
||||
|
||||
*fd = h;
|
||||
|
||||
return ERROR_OK;
|
||||
|
||||
error_open:
|
||||
stlink_usb_close(h);
|
||||
|
||||
stlink_close(h);
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
|
||||
static int stlink_usb_hl_open(struct hl_interface_param_s *param, void **fd)
|
||||
{
|
||||
return stlink_usb_open(param, stlink_get_mode(param->transport), fd);
|
||||
return stlink_open(param, stlink_get_mode(param->transport), fd);
|
||||
}
|
||||
|
||||
static int stlink_config_trace(void *handle, bool enabled,
|
||||
|
@ -3012,8 +3529,20 @@ static int stlink_config_trace(void *handle, bool enabled,
|
|||
{
|
||||
struct stlink_usb_handle_s *h = handle;
|
||||
|
||||
if (enabled && (!(h->version.flags & STLINK_F_HAS_TRACE) ||
|
||||
pin_protocol != TPIU_PIN_PROTOCOL_ASYNC_UART)) {
|
||||
if (!(h->version.flags & STLINK_F_HAS_TRACE)) {
|
||||
LOG_ERROR("The attached ST-LINK version doesn't support trace");
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
|
||||
if (!enabled) {
|
||||
stlink_usb_trace_disable(h);
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
assert(trace_freq != NULL);
|
||||
assert(prescaler != NULL);
|
||||
|
||||
if (pin_protocol != TPIU_PIN_PROTOCOL_ASYNC_UART) {
|
||||
LOG_ERROR("The attached ST-LINK version doesn't support this trace mode");
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
|
@ -3022,14 +3551,12 @@ static int stlink_config_trace(void *handle, bool enabled,
|
|||
STLINK_V3_TRACE_MAX_HZ : STLINK_TRACE_MAX_HZ;
|
||||
|
||||
/* Only concern ourselves with the frequency if the STlink is processing it. */
|
||||
if (enabled && *trace_freq > max_trace_freq) {
|
||||
if (*trace_freq > max_trace_freq) {
|
||||
LOG_ERROR("ST-LINK doesn't support SWO frequency higher than %u",
|
||||
max_trace_freq);
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
|
||||
stlink_usb_trace_disable(h);
|
||||
|
||||
if (!*trace_freq)
|
||||
*trace_freq = max_trace_freq;
|
||||
|
||||
|
@ -3051,8 +3578,7 @@ static int stlink_config_trace(void *handle, bool enabled,
|
|||
|
||||
*prescaler = presc;
|
||||
|
||||
if (!enabled)
|
||||
return ERROR_OK;
|
||||
stlink_usb_trace_disable(h);
|
||||
|
||||
h->trace.source_hz = *trace_freq;
|
||||
|
||||
|
@ -3152,7 +3678,7 @@ struct hl_layout_api_s stlink_usb_layout_api = {
|
|||
/** */
|
||||
.open = stlink_usb_hl_open,
|
||||
/** */
|
||||
.close = stlink_usb_close,
|
||||
.close = stlink_close,
|
||||
/** */
|
||||
.idcode = stlink_usb_idcode,
|
||||
/** */
|
||||
|
@ -3671,6 +4197,32 @@ COMMAND_HANDLER(stlink_dap_vid_pid)
|
|||
return ERROR_OK;
|
||||
}
|
||||
|
||||
/** */
|
||||
COMMAND_HANDLER(stlink_dap_backend_command)
|
||||
{
|
||||
/* default values */
|
||||
bool use_stlink_tcp = false;
|
||||
uint16_t stlink_tcp_port = 7184;
|
||||
|
||||
if (CMD_ARGC == 0 || CMD_ARGC > 2)
|
||||
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||
else if (strcmp(CMD_ARGV[0], "usb") == 0) {
|
||||
if (CMD_ARGC > 1)
|
||||
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||
/* else use_stlink_tcp = false (already the case ) */
|
||||
} else if (strcmp(CMD_ARGV[0], "tcp") == 0) {
|
||||
use_stlink_tcp = true;
|
||||
if (CMD_ARGC == 2)
|
||||
COMMAND_PARSE_NUMBER(u16, CMD_ARGV[1], stlink_tcp_port);
|
||||
} else
|
||||
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||
|
||||
stlink_dap_param.use_stlink_tcp = use_stlink_tcp;
|
||||
stlink_dap_param.stlink_tcp_port = stlink_tcp_port;
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
/** */
|
||||
static const struct command_registration stlink_dap_subcommand_handlers[] = {
|
||||
{
|
||||
|
@ -3687,6 +4239,13 @@ static const struct command_registration stlink_dap_subcommand_handlers[] = {
|
|||
.help = "USB VID and PID of the adapter",
|
||||
.usage = "(vid pid)+",
|
||||
},
|
||||
{
|
||||
.name = "backend",
|
||||
.handler = &stlink_dap_backend_command,
|
||||
.mode = COMMAND_CONFIG,
|
||||
.help = "select which ST-Link backend to use",
|
||||
.usage = "usb | tcp [port]",
|
||||
},
|
||||
COMMAND_REGISTRATION_DONE
|
||||
};
|
||||
|
||||
|
@ -3729,7 +4288,7 @@ static int stlink_dap_init(void)
|
|||
return ERROR_FAIL;
|
||||
}
|
||||
|
||||
retval = stlink_usb_open(&stlink_dap_param, mode, (void **)&stlink_dap_handle);
|
||||
retval = stlink_open(&stlink_dap_param, mode, (void **)&stlink_dap_handle);
|
||||
if (retval != ERROR_OK)
|
||||
return retval;
|
||||
|
||||
|
@ -3749,7 +4308,7 @@ static int stlink_dap_quit(void)
|
|||
free((void *)stlink_dap_param.serial);
|
||||
stlink_dap_param.serial = NULL;
|
||||
|
||||
return stlink_usb_close(stlink_dap_handle);
|
||||
return stlink_close(stlink_dap_handle);
|
||||
}
|
||||
|
||||
/** */
|
||||
|
|
|
@ -134,13 +134,18 @@ static int load_usb_blaster_firmware(struct libusb_device_handle *libusb_dev,
|
|||
return ERROR_FAIL;
|
||||
}
|
||||
|
||||
if (libusb_claim_interface(libusb_dev, 0)) {
|
||||
LOG_ERROR("unable to claim interface");
|
||||
return ERROR_JTAG_INIT_FAILED;
|
||||
}
|
||||
|
||||
ublast2_firmware_image.base_address = 0;
|
||||
ublast2_firmware_image.base_address_set = false;
|
||||
|
||||
int ret = image_open(&ublast2_firmware_image, low->firmware_path, "ihex");
|
||||
if (ret != ERROR_OK) {
|
||||
LOG_ERROR("Could not load firmware image");
|
||||
return ret;
|
||||
goto error_release_usb;
|
||||
}
|
||||
|
||||
/** A host loader program must write 0x01 to the CPUCS register
|
||||
|
@ -168,7 +173,7 @@ static int load_usb_blaster_firmware(struct libusb_device_handle *libusb_dev,
|
|||
&ublast2_firmware_image, i);
|
||||
if (ret != ERROR_OK) {
|
||||
LOG_ERROR("Error while downloading the firmware");
|
||||
return ret;
|
||||
goto error_close_firmware;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -183,9 +188,18 @@ static int load_usb_blaster_firmware(struct libusb_device_handle *libusb_dev,
|
|||
1,
|
||||
100);
|
||||
|
||||
error_close_firmware:
|
||||
image_close(&ublast2_firmware_image);
|
||||
|
||||
return ERROR_OK;
|
||||
error_release_usb:
|
||||
/*
|
||||
* Release claimed interface. Most probably it is already disconnected
|
||||
* and re-enumerated as new devices after firmware upload, so we do
|
||||
* not need to care about errors.
|
||||
*/
|
||||
libusb_release_interface(libusb_dev, 0);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int ublast2_libusb_init(struct ublast_lowlevel *low)
|
||||
|
@ -229,6 +243,12 @@ static int ublast2_libusb_init(struct ublast_lowlevel *low)
|
|||
}
|
||||
}
|
||||
|
||||
if (libusb_claim_interface(low->libusb_dev, 0)) {
|
||||
LOG_ERROR("unable to claim interface");
|
||||
jtag_libusb_close(low->libusb_dev);
|
||||
return ERROR_JTAG_INIT_FAILED;
|
||||
}
|
||||
|
||||
char buffer[5];
|
||||
jtag_libusb_control_transfer(low->libusb_dev,
|
||||
LIBUSB_REQUEST_TYPE_VENDOR |
|
||||
|
@ -247,6 +267,9 @@ static int ublast2_libusb_init(struct ublast_lowlevel *low)
|
|||
|
||||
static int ublast2_libusb_quit(struct ublast_lowlevel *low)
|
||||
{
|
||||
if (libusb_release_interface(low->libusb_dev, 0))
|
||||
LOG_ERROR("usb release interface failed");
|
||||
|
||||
jtag_libusb_close(low->libusb_dev);
|
||||
return ERROR_OK;
|
||||
};
|
||||
|
|
|
@ -1,57 +0,0 @@
|
|||
/***************************************************************************
|
||||
* Copyright (C) 2009 by Zachary T Welch <zw@superlucidity.net> *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation; either version 2 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
* This program is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License *
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
|
||||
***************************************************************************/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
#include "usb_common.h"
|
||||
#include "log.h"
|
||||
|
||||
|
||||
static bool jtag_usb_match(struct usb_device *dev,
|
||||
const uint16_t vids[], const uint16_t pids[])
|
||||
{
|
||||
for (unsigned i = 0; vids[i] && pids[i]; i++) {
|
||||
if (dev->descriptor.idVendor == vids[i] &&
|
||||
dev->descriptor.idProduct == pids[i])
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
int jtag_usb_open(const uint16_t vids[], const uint16_t pids[],
|
||||
struct usb_dev_handle **out)
|
||||
{
|
||||
usb_find_busses();
|
||||
usb_find_devices();
|
||||
|
||||
struct usb_bus *busses = usb_get_busses();
|
||||
for (struct usb_bus *bus = busses; bus; bus = bus->next) {
|
||||
for (struct usb_device *dev = bus->devices; dev; dev = dev->next) {
|
||||
if (!jtag_usb_match(dev, vids, pids))
|
||||
continue;
|
||||
|
||||
*out = usb_open(dev);
|
||||
if (NULL == *out) {
|
||||
LOG_ERROR("usb_open() failed with %s", usb_strerror());
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
return ERROR_OK;
|
||||
}
|
||||
}
|
||||
return ERROR_FAIL;
|
||||
}
|
|
@ -1,26 +0,0 @@
|
|||
/***************************************************************************
|
||||
* Copyright (C) 2009 by Zachary T Welch <zw@superlucidity.net> *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation; either version 2 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
* This program is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License *
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef OPENOCD_JTAG_DRIVERS_USB_COMMON_H
|
||||
#define OPENOCD_JTAG_DRIVERS_USB_COMMON_H
|
||||
|
||||
#include <usb.h>
|
||||
|
||||
int jtag_usb_open(const uint16_t vids[], const uint16_t pids[],
|
||||
struct usb_dev_handle **out);
|
||||
|
||||
#endif /* OPENOCD_JTAG_DRIVERS_USB_COMMON_H */
|
|
@ -34,7 +34,7 @@
|
|||
|
||||
#include <jtag/interface.h>
|
||||
#include <jtag/commands.h>
|
||||
#include "usb_common.h"
|
||||
#include "libusb_helper.h"
|
||||
|
||||
#define VID 0x1781
|
||||
#define PID 0x0c63
|
||||
|
@ -64,7 +64,7 @@ static void usbprog_scan(bool ir_scan, enum scan_type type, uint8_t *buffer, int
|
|||
#define WRITE_TMS_CHAIN 0x0A
|
||||
|
||||
struct usbprog_jtag {
|
||||
struct usb_dev_handle *usb_handle;
|
||||
struct libusb_device_handle *usb_handle;
|
||||
};
|
||||
|
||||
static struct usbprog_jtag *usbprog_jtag_handle;
|
||||
|
@ -350,21 +350,19 @@ struct usb_bus *busses;
|
|||
|
||||
struct usbprog_jtag *usbprog_jtag_open(void)
|
||||
{
|
||||
usb_set_debug(10);
|
||||
usb_init();
|
||||
|
||||
const uint16_t vids[] = { VID, 0 };
|
||||
const uint16_t pids[] = { PID, 0 };
|
||||
struct usb_dev_handle *dev;
|
||||
if (jtag_usb_open(vids, pids, &dev) != ERROR_OK)
|
||||
struct libusb_device_handle *dev;
|
||||
|
||||
if (jtag_libusb_open(vids, pids, NULL, &dev, NULL) != ERROR_OK)
|
||||
return NULL;
|
||||
|
||||
struct usbprog_jtag *tmp = malloc(sizeof(struct usbprog_jtag));
|
||||
tmp->usb_handle = dev;
|
||||
|
||||
usb_set_configuration(dev, 1);
|
||||
usb_claim_interface(dev, 0);
|
||||
usb_set_altinterface(dev, 0);
|
||||
libusb_set_configuration(dev, 1);
|
||||
libusb_claim_interface(dev, 0);
|
||||
libusb_set_interface_alt_setting(dev, 0, 0);
|
||||
|
||||
return tmp;
|
||||
}
|
||||
|
@ -372,21 +370,23 @@ struct usbprog_jtag *usbprog_jtag_open(void)
|
|||
#if 0
|
||||
static void usbprog_jtag_close(struct usbprog_jtag *usbprog_jtag)
|
||||
{
|
||||
usb_close(usbprog_jtag->usb_handle);
|
||||
libusb_close(usbprog_jtag->usb_handle);
|
||||
free(usbprog_jtag);
|
||||
}
|
||||
#endif
|
||||
|
||||
static unsigned char usbprog_jtag_message(struct usbprog_jtag *usbprog_jtag, char *msg, int msglen)
|
||||
{
|
||||
int res = usb_bulk_write(usbprog_jtag->usb_handle, 3, msg, msglen, 100);
|
||||
int transferred;
|
||||
|
||||
int res = jtag_libusb_bulk_write(usbprog_jtag->usb_handle, 3, msg, msglen, 100, &transferred);
|
||||
if ((msg[0] == 2) || (msg[0] == 1) || (msg[0] == 4) || (msg[0] == 0) ||
|
||||
(msg[0] == 6) || (msg[0] == 0x0A) || (msg[0] == 9))
|
||||
return 1;
|
||||
if (res == msglen) {
|
||||
if (res == ERROR_OK && transferred == msglen) {
|
||||
/* LOG_INFO("HALLLLOOO %i",(int)msg[0]); */
|
||||
res = usb_bulk_read(usbprog_jtag->usb_handle, 0x82, msg, 2, 100);
|
||||
if (res > 0)
|
||||
res = jtag_libusb_bulk_read(usbprog_jtag->usb_handle, 0x82, msg, 2, 100, &transferred);
|
||||
if (res == ERROR_OK && transferred > 0)
|
||||
return (unsigned char)msg[1];
|
||||
else
|
||||
return -1;
|
||||
|
@ -428,11 +428,13 @@ static void usbprog_jtag_write_and_read(struct usbprog_jtag *usbprog_jtag, char
|
|||
bufindex++;
|
||||
}
|
||||
|
||||
if (usb_bulk_write(usbprog_jtag->usb_handle, 3, tmp, 64, 1000) == 64) {
|
||||
int transferred;
|
||||
int res = jtag_libusb_bulk_write(usbprog_jtag->usb_handle, 3, tmp, 64, 1000, &transferred);
|
||||
if (res == ERROR_OK && transferred == 64) {
|
||||
/* LOG_INFO("HALLLLOOO2 %i",(int)tmp[0]); */
|
||||
usleep(1);
|
||||
int timeout = 0;
|
||||
while (usb_bulk_read(usbprog_jtag->usb_handle, 0x82, tmp, 64, 1000) < 1) {
|
||||
while (jtag_libusb_bulk_read(usbprog_jtag->usb_handle, 0x82, tmp, 64, 1000, &transferred) != ERROR_OK) {
|
||||
timeout++;
|
||||
if (timeout > 10)
|
||||
break;
|
||||
|
@ -469,12 +471,13 @@ static void usbprog_jtag_read_tdo(struct usbprog_jtag *usbprog_jtag, char *buffe
|
|||
tmp[1] = (char)(send_bits >> 8); /* high */
|
||||
tmp[2] = (char)(send_bits); /* low */
|
||||
|
||||
usb_bulk_write(usbprog_jtag->usb_handle, 3, tmp, 3, 1000);
|
||||
int transferred;
|
||||
jtag_libusb_bulk_write(usbprog_jtag->usb_handle, 3, tmp, 3, 1000, &transferred);
|
||||
|
||||
/* LOG_INFO("HALLLLOOO3 %i",(int)tmp[0]); */
|
||||
int timeout = 0;
|
||||
usleep(1);
|
||||
while (usb_bulk_read(usbprog_jtag->usb_handle, 0x82, tmp, 64, 10) < 1) {
|
||||
while (jtag_libusb_bulk_read(usbprog_jtag->usb_handle, 0x82, tmp, 64, 10, &transferred) != ERROR_OK) {
|
||||
timeout++;
|
||||
if (timeout > 10)
|
||||
break;
|
||||
|
@ -513,7 +516,8 @@ static void usbprog_jtag_write_tdi(struct usbprog_jtag *usbprog_jtag, char *buff
|
|||
tmp[3 + i] = buffer[bufindex];
|
||||
bufindex++;
|
||||
}
|
||||
usb_bulk_write(usbprog_jtag->usb_handle, 3, tmp, 64, 1000);
|
||||
int transferred;
|
||||
jtag_libusb_bulk_write(usbprog_jtag->usb_handle, 3, tmp, 64, 1000, &transferred);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -582,15 +586,15 @@ static void usbprog_jtag_tms_collect(char tms_scan)
|
|||
|
||||
static void usbprog_jtag_tms_send(struct usbprog_jtag *usbprog_jtag)
|
||||
{
|
||||
int i;
|
||||
/* LOG_INFO("TMS SEND"); */
|
||||
if (tms_chain_index > 0) {
|
||||
char tmp[tms_chain_index + 2];
|
||||
tmp[0] = WRITE_TMS_CHAIN;
|
||||
tmp[1] = (char)(tms_chain_index);
|
||||
for (i = 0; i < tms_chain_index + 1; i++)
|
||||
for (int i = 0; i < tms_chain_index + 1; i++)
|
||||
tmp[2 + i] = tms_chain[i];
|
||||
usb_bulk_write(usbprog_jtag->usb_handle, 3, tmp, tms_chain_index + 2, 1000);
|
||||
int transferred;
|
||||
jtag_libusb_bulk_write(usbprog_jtag->usb_handle, 3, tmp, tms_chain_index + 2, 1000, &transferred);
|
||||
tms_chain_index = 0;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -35,7 +35,7 @@
|
|||
|
||||
#include <target/target.h>
|
||||
|
||||
static struct hl_interface_s hl_if = { {0, 0, { 0 }, { 0 }, HL_TRANSPORT_UNKNOWN, false, -1}, 0, 0 };
|
||||
static struct hl_interface_s hl_if = { {0, 0, { 0 }, { 0 }, HL_TRANSPORT_UNKNOWN, false, -1, false, 7184}, 0, 0 };
|
||||
|
||||
int hl_interface_open(enum hl_transports tr)
|
||||
{
|
||||
|
@ -292,6 +292,31 @@ COMMAND_HANDLER(hl_interface_handle_vid_pid_command)
|
|||
return ERROR_OK;
|
||||
}
|
||||
|
||||
COMMAND_HANDLER(hl_interface_handle_stlink_backend_command)
|
||||
{
|
||||
/* default values */
|
||||
bool use_stlink_tcp = false;
|
||||
uint16_t stlink_tcp_port = 7184;
|
||||
|
||||
if (CMD_ARGC == 0 || CMD_ARGC > 2)
|
||||
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||
else if (strcmp(CMD_ARGV[0], "usb") == 0) {
|
||||
if (CMD_ARGC > 1)
|
||||
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||
/* else use_stlink_tcp = false (already the case ) */
|
||||
} else if (strcmp(CMD_ARGV[0], "tcp") == 0) {
|
||||
use_stlink_tcp = true;
|
||||
if (CMD_ARGC == 2)
|
||||
COMMAND_PARSE_NUMBER(u16, CMD_ARGV[1], stlink_tcp_port);
|
||||
} else
|
||||
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||
|
||||
hl_if.param.use_stlink_tcp = use_stlink_tcp;
|
||||
hl_if.param.stlink_tcp_port = stlink_tcp_port;
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
COMMAND_HANDLER(interface_handle_hla_command)
|
||||
{
|
||||
if (CMD_ARGC != 1)
|
||||
|
@ -336,6 +361,13 @@ static const struct command_registration hl_interface_command_handlers[] = {
|
|||
.help = "the vendor and product ID of the adapter",
|
||||
.usage = "(vid pid)* ",
|
||||
},
|
||||
{
|
||||
.name = "hla_stlink_backend",
|
||||
.handler = &hl_interface_handle_stlink_backend_command,
|
||||
.mode = COMMAND_CONFIG,
|
||||
.help = "select which ST-Link backend to use",
|
||||
.usage = "usb | tcp [port]",
|
||||
},
|
||||
{
|
||||
.name = "hla_command",
|
||||
.handler = &interface_handle_hla_command,
|
||||
|
|
|
@ -46,6 +46,10 @@ struct hl_interface_param_s {
|
|||
bool connect_under_reset;
|
||||
/** Initial interface clock clock speed */
|
||||
int initial_interface_speed;
|
||||
/** */
|
||||
bool use_stlink_tcp;
|
||||
/** */
|
||||
uint16_t stlink_tcp_port;
|
||||
};
|
||||
|
||||
struct hl_interface_s {
|
||||
|
|
|
@ -27,7 +27,7 @@
|
|||
|
||||
#include <jtag/jtag.h>
|
||||
#include <jtag/swim.h>
|
||||
#include <target/armv7m_trace.h>
|
||||
#include <target/arm_tpiu_swo.h>
|
||||
|
||||
/* @file
|
||||
* The "Cable Helper API" is what the cable drivers can use to help
|
||||
|
|
|
@ -42,11 +42,6 @@
|
|||
* that contain an adapter_driver structure that can added to this list.
|
||||
*/
|
||||
|
||||
#if BUILD_ZY1000 == 1
|
||||
extern struct adapter_driver zy1000_adapter_driver;
|
||||
#elif defined(BUILD_MINIDRIVER_DUMMY)
|
||||
extern struct adapter_driver minidummy_adapter_driver;
|
||||
#else /* standard drivers */
|
||||
#if BUILD_PARPORT == 1
|
||||
extern struct adapter_driver parport_adapter_driver;
|
||||
#endif
|
||||
|
@ -152,21 +147,12 @@ extern struct adapter_driver stlink_dap_adapter_driver;
|
|||
#if BUILD_RSHIM == 1
|
||||
extern struct adapter_driver rshim_dap_adapter_driver;
|
||||
#endif
|
||||
#endif /* standard drivers */
|
||||
|
||||
/**
|
||||
* The list of built-in JTAG interfaces, containing entries for those
|
||||
* drivers that were enabled by the @c configure script.
|
||||
*
|
||||
* The list should be defined to contain either one minidriver interface
|
||||
* or some number of standard driver interfaces, never both.
|
||||
*/
|
||||
struct adapter_driver *adapter_drivers[] = {
|
||||
#if BUILD_ZY1000 == 1
|
||||
&zy1000_adapter_driver,
|
||||
#elif defined(BUILD_MINIDRIVER_DUMMY)
|
||||
&minidummy_adapter_driver,
|
||||
#else /* standard drivers */
|
||||
#if BUILD_PARPORT == 1
|
||||
&parport_adapter_driver,
|
||||
#endif
|
||||
|
@ -272,6 +258,5 @@ struct adapter_driver *adapter_drivers[] = {
|
|||
#if BUILD_RSHIM == 1
|
||||
&rshim_dap_adapter_driver,
|
||||
#endif
|
||||
#endif /* standard drivers */
|
||||
NULL,
|
||||
};
|
||||
|
|
|
@ -47,15 +47,6 @@
|
|||
typedef enum tap_state {
|
||||
TAP_INVALID = -1,
|
||||
|
||||
#if BUILD_ZY1000
|
||||
/* These are the old numbers. Leave as-is for now... */
|
||||
TAP_RESET = 0, TAP_IDLE = 8,
|
||||
TAP_DRSELECT = 1, TAP_DRCAPTURE = 2, TAP_DRSHIFT = 3, TAP_DREXIT1 = 4,
|
||||
TAP_DRPAUSE = 5, TAP_DREXIT2 = 6, TAP_DRUPDATE = 7,
|
||||
TAP_IRSELECT = 9, TAP_IRCAPTURE = 10, TAP_IRSHIFT = 11, TAP_IREXIT1 = 12,
|
||||
TAP_IRPAUSE = 13, TAP_IREXIT2 = 14, TAP_IRUPDATE = 15,
|
||||
|
||||
#else
|
||||
/* Proper ARM recommended numbers */
|
||||
TAP_DREXIT2 = 0x0,
|
||||
TAP_DREXIT1 = 0x1,
|
||||
|
@ -73,8 +64,6 @@ typedef enum tap_state {
|
|||
TAP_IRUPDATE = 0xd,
|
||||
TAP_IRCAPTURE = 0xe,
|
||||
TAP_RESET = 0x0f,
|
||||
|
||||
#endif
|
||||
} tap_state_t;
|
||||
|
||||
/**
|
||||
|
@ -636,9 +625,6 @@ bool jtag_poll_get_enabled(void);
|
|||
*/
|
||||
void jtag_poll_set_enabled(bool value);
|
||||
|
||||
|
||||
/* The minidriver may have inline versions of some of the low
|
||||
* level APIs that are used in inner loops. */
|
||||
#include <jtag/minidriver.h>
|
||||
|
||||
int jim_jtag_newtap(Jim_Interp *interp, int argc, Jim_Obj *const *argv);
|
||||
|
|
|
@ -45,7 +45,7 @@
|
|||
|
||||
/* this header will be provided by the minidriver implementation, */
|
||||
/* and it may provide additional declarations that must be defined. */
|
||||
#include <jtag/minidriver_imp.h>
|
||||
#include <jtag/drivers/minidriver_imp.h>
|
||||
|
||||
int interface_jtag_add_ir_scan(struct jtag_tap *active,
|
||||
const struct scan_field *fields,
|
||||
|
|
|
@ -1,30 +0,0 @@
|
|||
/***************************************************************************
|
||||
* Copyright (C) 2005 by Dominic Rath <Dominic.Rath@gmx.de> *
|
||||
* Copyright (C) 2007,2008 Øyvind Harboe <oyvind.harboe@zylin.com> *
|
||||
* Copyright (C) 2009 Zachary T Welch <zw@superlucidity.net> *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation; either version 2 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
* This program is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License *
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef OPENOCD_JTAG_MINIDRIVER_MINIDRIVER_IMP_H
|
||||
#define OPENOCD_JTAG_MINIDRIVER_MINIDRIVER_IMP_H
|
||||
|
||||
#include <jtag/jtag_minidriver.h>
|
||||
|
||||
#define jtag_add_callback(callback, in) interface_jtag_add_callback(callback, in)
|
||||
|
||||
#define jtag_add_callback4(callback, in, data1, data2, data3) \
|
||||
interface_jtag_add_callback4(callback, in, data1, data2, data3)
|
||||
|
||||
#endif /* OPENOCD_JTAG_MINIDRIVER_MINIDRIVER_IMP_H */
|
|
@ -1,21 +0,0 @@
|
|||
/***************************************************************************
|
||||
* Copyright (C) 2007-2008 by Øyvind Harboe *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation; either version 2 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
* This program is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License *
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
|
||||
***************************************************************************/
|
||||
|
||||
#define interface_jtag_add_callback(callback, in) callback(in)
|
||||
|
||||
#define interface_jtag_add_callback4(callback, in, data1, data2, data3) \
|
||||
jtag_set_error(callback(in, data1, data2, data3))
|
|
@ -1,176 +0,0 @@
|
|||
/***************************************************************************
|
||||
* Copyright (C) 2007-2008 by Øyvind Harboe *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation; either version 2 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
* This program is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License *
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
|
||||
***************************************************************************/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <jtag/jtag.h>
|
||||
#include <target/embeddedice.h>
|
||||
#include <jtag/minidriver.h>
|
||||
#include <jtag/interface.h>
|
||||
|
||||
static struct jtag_interface minidummy_interface = {
|
||||
.execute_queue = NULL,
|
||||
};
|
||||
|
||||
struct adapter_driver minidummy_adapter_driver = {
|
||||
.name = "minidummy",
|
||||
.transports = jtag_only,
|
||||
.commands = NULL,
|
||||
|
||||
.init = NULL,
|
||||
.quit = NULL,
|
||||
.speed = NULL,
|
||||
.khz = NULL,
|
||||
.speed_div = NULL,
|
||||
.power_dropout = NULL,
|
||||
.srst_asserted = NULL,
|
||||
|
||||
.jtag_ops = &minidummy_interface,
|
||||
};
|
||||
|
||||
int interface_jtag_execute_queue(void)
|
||||
{
|
||||
/* synchronously do the operation here */
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
int interface_jtag_add_ir_scan(struct jtag_tap *active, const struct scan_field *fields,
|
||||
tap_state_t state)
|
||||
{
|
||||
/* synchronously do the operation here */
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
int interface_jtag_add_plain_ir_scan(int num_bits, const uint8_t *out_bits,
|
||||
uint8_t *in_bits, tap_state_t state)
|
||||
{
|
||||
/* synchronously do the operation here */
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
int interface_jtag_add_dr_scan(struct jtag_tap *active, int num_fields,
|
||||
const struct scan_field *fields, tap_state_t state)
|
||||
{
|
||||
/* synchronously do the operation here */
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
int interface_jtag_add_plain_dr_scan(int num_bits, const uint8_t *out_bits,
|
||||
uint8_t *in_bits, tap_state_t state)
|
||||
{
|
||||
/* synchronously do the operation here */
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
int interface_jtag_add_tlr(void)
|
||||
{
|
||||
/* synchronously do the operation here */
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
int interface_jtag_add_reset(int req_trst, int req_srst)
|
||||
{
|
||||
/* synchronously do the operation here */
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
int interface_jtag_add_runtest(int num_cycles, tap_state_t state)
|
||||
{
|
||||
/* synchronously do the operation here */
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
int interface_jtag_add_clocks(int num_cycles)
|
||||
{
|
||||
/* synchronously do the operation here */
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
int interface_jtag_add_sleep(uint32_t us)
|
||||
{
|
||||
jtag_sleep(us);
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
int interface_jtag_add_pathmove(int num_states, const tap_state_t *path)
|
||||
{
|
||||
int state_count;
|
||||
int tms = 0;
|
||||
|
||||
state_count = 0;
|
||||
|
||||
tap_state_t cur_state = cmd_queue_cur_state;
|
||||
|
||||
while (num_states) {
|
||||
if (tap_state_transition(cur_state, false) == path[state_count])
|
||||
tms = 0;
|
||||
else if (tap_state_transition(cur_state, true) == path[state_count])
|
||||
tms = 1;
|
||||
else {
|
||||
LOG_ERROR("BUG: %s -> %s isn't a valid TAP transition",
|
||||
tap_state_name(cur_state), tap_state_name(path[state_count]));
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
/* synchronously do the operation here */
|
||||
|
||||
cur_state = path[state_count];
|
||||
state_count++;
|
||||
num_states--;
|
||||
}
|
||||
|
||||
|
||||
/* synchronously do the operation here */
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
int interface_add_tms_seq(unsigned num_bits, const uint8_t *seq, enum tap_state state)
|
||||
{
|
||||
/* synchronously do the operation here */
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
void embeddedice_write_dcc(struct jtag_tap *tap, int reg_addr, const uint8_t *buffer,
|
||||
int little, int count)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < count; i++) {
|
||||
embeddedice_write_reg_inner(tap, reg_addr, fast_target_buffer_get_u32(buffer, little));
|
||||
buffer += 4;
|
||||
}
|
||||
}
|
||||
|
||||
int arm11_run_instr_data_to_core_noack_inner(struct jtag_tap *tap, uint32_t opcode,
|
||||
uint32_t *data, size_t count)
|
||||
{
|
||||
int arm11_run_instr_data_to_core_noack_inner_default(struct jtag_tap *tap,
|
||||
uint32_t opcode, uint32_t *data, size_t count);
|
||||
return arm11_run_instr_data_to_core_noack_inner_default(tap, opcode, data, count);
|
||||
}
|
|
@ -29,7 +29,7 @@ proc init_reset { mode } {
|
|||
#########
|
||||
|
||||
# TODO: power_restore and power_dropout are currently neither
|
||||
# documented nor supported except on ZY1000.
|
||||
# documented nor supported.
|
||||
|
||||
proc power_restore {} {
|
||||
echo "Sensed power restore, running reset init and halting GDB."
|
||||
|
@ -55,7 +55,7 @@ proc power_dropout {} {
|
|||
#########
|
||||
|
||||
# TODO: srst_deasserted and srst_asserted are currently neither
|
||||
# documented nor supported except on ZY1000.
|
||||
# documented nor supported.
|
||||
|
||||
proc srst_deasserted {} {
|
||||
echo "Sensed nSRST deasserted, running reset init and halting GDB."
|
||||
|
@ -117,23 +117,8 @@ proc jtag_ntrst_assert_width args {
|
|||
# JTAG-specific names despite the fact that the operations were not
|
||||
# specific to JTAG, or otherwise had troublesome/misleading names.
|
||||
#
|
||||
# FIXME phase these aids out after about April 2011
|
||||
# FIXME phase these aids out after some releases
|
||||
#
|
||||
proc jtag_khz args {
|
||||
echo "DEPRECATED! use 'adapter speed' not 'jtag_khz'"
|
||||
eval adapter speed $args
|
||||
}
|
||||
|
||||
proc jtag_nsrst_delay args {
|
||||
echo "DEPRECATED! use 'adapter srst delay' not 'jtag_nsrst_delay'"
|
||||
eval adapter srst delay $args
|
||||
}
|
||||
|
||||
proc jtag_nsrst_assert_width args {
|
||||
echo "DEPRECATED! use 'adapter srst pulse_width' not 'jtag_nsrst_assert_width'"
|
||||
eval adapter srst pulse_width $args
|
||||
}
|
||||
|
||||
proc jtag_reset args {
|
||||
echo "DEPRECATED! use 'adapter \[de\]assert' not 'jtag_reset'"
|
||||
switch $args {
|
||||
|
@ -150,32 +135,6 @@ proc jtag_reset args {
|
|||
}
|
||||
}
|
||||
|
||||
# stlink migration helpers
|
||||
proc stlink_device_desc args {
|
||||
echo "DEPRECATED! use 'hla_device_desc' not 'stlink_device_desc'"
|
||||
eval hla_device_desc $args
|
||||
}
|
||||
|
||||
proc stlink_serial args {
|
||||
echo "DEPRECATED! use 'hla_serial' not 'stlink_serial'"
|
||||
eval hla_serial $args
|
||||
}
|
||||
|
||||
proc stlink_layout args {
|
||||
echo "DEPRECATED! use 'hla_layout' not 'stlink_layout'"
|
||||
eval hla_layout $args
|
||||
}
|
||||
|
||||
proc stlink_vid_pid args {
|
||||
echo "DEPRECATED! use 'hla_vid_pid' not 'stlink_vid_pid'"
|
||||
eval hla_vid_pid $args
|
||||
}
|
||||
|
||||
proc stlink args {
|
||||
echo "DEPRECATED! use 'hla' not 'stlink'"
|
||||
eval hla $args
|
||||
}
|
||||
|
||||
proc adapter_khz args {
|
||||
echo "DEPRECATED! use 'adapter speed' not 'adapter_khz'"
|
||||
eval adapter speed $args
|
||||
|
|
|
@ -1,182 +0,0 @@
|
|||
/***************************************************************************
|
||||
* Copyright (C) 2007-2010 by Øyvind Harboe *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation; either version 2 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
* This program is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License *
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
|
||||
***************************************************************************/
|
||||
|
||||
/* used to test manual mode */
|
||||
#define TEST_MANUAL() 0
|
||||
#define VERBOSE(a)
|
||||
|
||||
#if BUILD_ZY1000_MASTER
|
||||
|
||||
#define ZY1000_PEEK(a, b) do {b = *((volatile uint32_t *)(a)); } while (0)
|
||||
#define ZY1000_POKE(a, b) do {*((volatile uint32_t *)(a)) = b; } while (0)
|
||||
extern volatile void *zy1000_jtag_master;
|
||||
#define ZY1000_JTAG_BASE ((unsigned long)zy1000_jtag_master)
|
||||
|
||||
#else
|
||||
|
||||
/* redirect this to TCP/IP */
|
||||
#define ZY1000_JTAG_BASE 0
|
||||
extern void zy1000_tcpout(uint32_t address, uint32_t data);
|
||||
extern uint32_t zy1000_tcpin(uint32_t address);
|
||||
#define ZY1000_PEEK(a, b) b = zy1000_tcpin(a)
|
||||
#define ZY1000_POKE(a, b) zy1000_tcpout(a, b)
|
||||
|
||||
#endif
|
||||
|
||||
#if BUILD_ZY1000_MASTER
|
||||
/* FIFO empty? */
|
||||
static inline void waitIdle(void)
|
||||
{
|
||||
uint32_t empty;
|
||||
do {
|
||||
ZY1000_PEEK(ZY1000_JTAG_BASE + 0x10, empty);
|
||||
} while ((empty & 0x100) == 0);
|
||||
}
|
||||
|
||||
static inline void zy1000_flush_readqueue(void)
|
||||
{
|
||||
/* Not used w/hardware fifo */
|
||||
}
|
||||
static inline void zy1000_flush_callbackqueue(void)
|
||||
{
|
||||
/* Not used w/hardware fifo */
|
||||
}
|
||||
#else
|
||||
extern void waitIdle(void);
|
||||
void zy1000_flush_readqueue(void);
|
||||
void zy1000_flush_callbackqueue(void);
|
||||
void zy1000_jtag_add_callback4(jtag_callback_t callback,
|
||||
jtag_callback_data_t data0,
|
||||
jtag_callback_data_t data1,
|
||||
jtag_callback_data_t data2,
|
||||
jtag_callback_data_t data3);
|
||||
void zy1000_jtag_add_callback(jtag_callback1_t callback, jtag_callback_data_t data0);
|
||||
#endif
|
||||
|
||||
static inline void waitQueue(void)
|
||||
{
|
||||
/* waitIdle(); */
|
||||
}
|
||||
|
||||
static inline void sampleShiftRegister(void)
|
||||
{
|
||||
#if 0
|
||||
uint32_t dummy;
|
||||
waitIdle();
|
||||
ZY1000_PEEK(ZY1000_JTAG_BASE + 0xc, dummy);
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline void setCurrentState(enum tap_state state)
|
||||
{
|
||||
uint32_t a;
|
||||
a = state;
|
||||
int repeat = 0;
|
||||
if (state == TAP_RESET) {
|
||||
/* The FPGA nor we know the current state of the CPU TAP */
|
||||
/* controller. This will move it to TAP for sure. */
|
||||
/* */
|
||||
/* 5 should be enough here, 7 is what OpenOCD uses */
|
||||
repeat = 7;
|
||||
}
|
||||
waitQueue();
|
||||
sampleShiftRegister();
|
||||
ZY1000_POKE(ZY1000_JTAG_BASE + 0x8, (repeat << 8) | (a << 4) | a);
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* Enter state and cause repeat transitions *out* of that state. So if the endState != state, then
|
||||
* the transition from state to endState counts as a transition out of state.
|
||||
*/
|
||||
static inline void shiftValueInner(const enum tap_state state,
|
||||
const enum tap_state endState,
|
||||
int repeat,
|
||||
uint32_t value)
|
||||
{
|
||||
uint32_t a, b;
|
||||
a = state;
|
||||
b = endState;
|
||||
waitQueue();
|
||||
sampleShiftRegister();
|
||||
ZY1000_POKE(ZY1000_JTAG_BASE + 0xc, value);
|
||||
#if 1
|
||||
#if TEST_MANUAL()
|
||||
if ((state == TAP_DRSHIFT) && (endState != TAP_DRSHIFT)) {
|
||||
int i;
|
||||
setCurrentState(state);
|
||||
for (i = 0; i < repeat; i++) {
|
||||
int tms;
|
||||
tms = 0;
|
||||
if ((i == repeat-1) && (state != endState))
|
||||
tms = 1;
|
||||
/* shift out value */
|
||||
waitIdle();
|
||||
ZY1000_POKE(ZY1000_JTAG_BASE + 0x28, (((value >> i)&1) << 1) | tms);
|
||||
}
|
||||
waitIdle();
|
||||
ZY1000_POKE(ZY1000_JTAG_BASE + 0x28, 0);
|
||||
waitIdle();
|
||||
/* ZY1000_POKE(ZY1000_JTAG_BASE + 0x20, TAP_DRSHIFT); // set this state and things
|
||||
* break => expected */
|
||||
ZY1000_POKE(ZY1000_JTAG_BASE + 0x20, TAP_DRPAUSE); /* set this and things will
|
||||
* work => expected. Not
|
||||
* setting this is not
|
||||
* sufficient to make things
|
||||
* break. */
|
||||
setCurrentState(endState);
|
||||
} else
|
||||
ZY1000_POKE(ZY1000_JTAG_BASE + 0x8, (repeat << 8) | (a << 4) | b);
|
||||
|
||||
#else
|
||||
/* fast version */
|
||||
ZY1000_POKE(ZY1000_JTAG_BASE + 0x8, (repeat << 8) | (a << 4) | b);
|
||||
#endif
|
||||
#else
|
||||
/* maximum debug version */
|
||||
if ((repeat > 0) && ((state == TAP_DRSHIFT) || (state == TAP_SI))) {
|
||||
int i;
|
||||
/* sample shift register for every bit. */
|
||||
for (i = 0; i < repeat-1; i++) {
|
||||
sampleShiftRegister();
|
||||
ZY1000_POKE(ZY1000_JTAG_BASE + 0xc, value >> i);
|
||||
ZY1000_POKE(ZY1000_JTAG_BASE + 0x8, (1 << 8) | (a << 4) | a);
|
||||
}
|
||||
sampleShiftRegister();
|
||||
ZY1000_POKE(ZY1000_JTAG_BASE + 0xc, value >> (repeat-1));
|
||||
ZY1000_POKE(ZY1000_JTAG_BASE + 0x8, (1 << 8) | (a << 4) | b);
|
||||
} else {
|
||||
sampleShiftRegister();
|
||||
ZY1000_POKE(ZY1000_JTAG_BASE + 0x8, (repeat << 8) | (a << 4) | b);
|
||||
}
|
||||
sampleShiftRegister();
|
||||
#endif
|
||||
}
|
||||
|
||||
#if BUILD_ZY1000_MASTER
|
||||
#define interface_jtag_add_callback(callback, in) callback(in)
|
||||
#define interface_jtag_add_callback4(callback, in, data1, data2, \
|
||||
data3) jtag_set_error(callback(in, data1, data2, data3))
|
||||
#else
|
||||
#define interface_jtag_add_callback(callback, in) zy1000_jtag_add_callback(callback, in)
|
||||
#define interface_jtag_add_callback4(callback, in, data1, data2, data3) zy1000_jtag_add_callback4( \
|
||||
callback, \
|
||||
in, \
|
||||
data1, \
|
||||
data2, \
|
||||
data3)
|
||||
#endif
|
File diff suppressed because it is too large
Load Diff
|
@ -30,7 +30,6 @@
|
|||
#include <jtag/driver.h>
|
||||
#include <jtag/jtag.h>
|
||||
#include <transport/transport.h>
|
||||
#include <helper/ioutil.h>
|
||||
#include <helper/util.h>
|
||||
#include <helper/configuration.h>
|
||||
#include <flash/nor/core.h>
|
||||
|
@ -38,6 +37,7 @@
|
|||
#include <pld/pld.h>
|
||||
#include <target/arm_cti.h>
|
||||
#include <target/arm_adi_v5.h>
|
||||
#include <target/arm_tpiu_swo.h>
|
||||
#include <rtt/rtt.h>
|
||||
|
||||
#include <server/server.h>
|
||||
|
@ -173,6 +173,10 @@ COMMAND_HANDLER(handle_init_command)
|
|||
return ERROR_FAIL;
|
||||
command_context_mode(CMD_CTX, COMMAND_EXEC);
|
||||
|
||||
/* in COMMAND_EXEC, after target_examine(), only tpiu or only swo */
|
||||
if (command_run_line(CMD_CTX, "tpiu init") != ERROR_OK)
|
||||
return ERROR_FAIL;
|
||||
|
||||
/* initialize telnet subsystem */
|
||||
gdb_target_add_all(all_targets);
|
||||
|
||||
|
@ -255,6 +259,7 @@ static struct command_context *setup_command_handler(Jim_Interp *interp)
|
|||
&pld_register_commands,
|
||||
&cti_register_commands,
|
||||
&dap_register_commands,
|
||||
&arm_tpiu_swo_register_commands,
|
||||
NULL
|
||||
};
|
||||
for (unsigned i = 0; NULL != command_registrants[i]; i++) {
|
||||
|
@ -335,9 +340,6 @@ int openocd_main(int argc, char *argv[])
|
|||
if (util_init(cmd_ctx) != ERROR_OK)
|
||||
return EXIT_FAILURE;
|
||||
|
||||
if (ioutil_init(cmd_ctx) != ERROR_OK)
|
||||
return EXIT_FAILURE;
|
||||
|
||||
if (rtt_init() != ERROR_OK)
|
||||
return EXIT_FAILURE;
|
||||
|
||||
|
@ -355,6 +357,7 @@ int openocd_main(int argc, char *argv[])
|
|||
|
||||
flash_free_all_banks();
|
||||
gdb_service_free();
|
||||
arm_tpiu_swo_cleanup_all();
|
||||
server_free();
|
||||
|
||||
unregister_all_commands(cmd_ctx, NULL);
|
||||
|
|
|
@ -215,7 +215,7 @@ static int FreeRTOS_get_thread_reg_list(struct rtos *rtos, threadid_t thread_id,
|
|||
static int FreeRTOS_get_thread_reg(struct rtos *rtos, threadid_t thread_id,
|
||||
uint32_t reg_num, struct rtos_reg *reg);
|
||||
static int FreeRTOS_set_reg(struct rtos *rtos, uint32_t reg_num, uint8_t *reg_value);
|
||||
static int FreeRTOS_get_symbol_list_to_lookup(symbol_table_elem_t *symbol_list[]);
|
||||
static int FreeRTOS_get_symbol_list_to_lookup(struct symbol_table_elem *symbol_list[]);
|
||||
|
||||
struct rtos_type FreeRTOS_rtos = {
|
||||
.name = "FreeRTOS",
|
||||
|
@ -790,11 +790,11 @@ static int FreeRTOS_set_reg(struct rtos *rtos, uint32_t reg_num, uint8_t *reg_va
|
|||
reg_num, reg_value);
|
||||
}
|
||||
|
||||
static int FreeRTOS_get_symbol_list_to_lookup(symbol_table_elem_t *symbol_list[])
|
||||
static int FreeRTOS_get_symbol_list_to_lookup(struct symbol_table_elem *symbol_list[])
|
||||
{
|
||||
unsigned int i;
|
||||
*symbol_list = calloc(
|
||||
ARRAY_SIZE(FreeRTOS_symbol_list), sizeof(symbol_table_elem_t));
|
||||
ARRAY_SIZE(FreeRTOS_symbol_list), sizeof(struct symbol_table_elem));
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(FreeRTOS_symbol_list); i++) {
|
||||
(*symbol_list)[i].symbol_name = FreeRTOS_symbol_list[i].name;
|
||||
|
|
|
@ -39,7 +39,7 @@ static bool ThreadX_detect_rtos(struct target *target);
|
|||
static int ThreadX_create(struct target *target);
|
||||
static int ThreadX_update_threads(struct rtos *rtos);
|
||||
static int ThreadX_get_thread_reg_list(struct rtos *rtos, int64_t thread_id, struct rtos_reg **reg_list, int *num_regs);
|
||||
static int ThreadX_get_symbol_list_to_lookup(symbol_table_elem_t *symbol_list[]);
|
||||
static int ThreadX_get_symbol_list_to_lookup(struct symbol_table_elem *symbol_list[]);
|
||||
|
||||
|
||||
|
||||
|
@ -477,11 +477,11 @@ static int ThreadX_get_thread_reg_list(struct rtos *rtos, int64_t thread_id,
|
|||
return rtos_generic_stack_read(rtos->target, stacking_info, stack_ptr, reg_list, num_regs);
|
||||
}
|
||||
|
||||
static int ThreadX_get_symbol_list_to_lookup(symbol_table_elem_t *symbol_list[])
|
||||
static int ThreadX_get_symbol_list_to_lookup(struct symbol_table_elem *symbol_list[])
|
||||
{
|
||||
unsigned int i;
|
||||
*symbol_list = calloc(
|
||||
ARRAY_SIZE(ThreadX_symbol_list), sizeof(symbol_table_elem_t));
|
||||
ARRAY_SIZE(ThreadX_symbol_list), sizeof(struct symbol_table_elem));
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(ThreadX_symbol_list); i++)
|
||||
(*symbol_list)[i].symbol_name = ThreadX_symbol_list[i];
|
||||
|
|
|
@ -107,7 +107,7 @@ static int chibios_create(struct target *target);
|
|||
static int chibios_update_threads(struct rtos *rtos);
|
||||
static int chibios_get_thread_reg_list(struct rtos *rtos, int64_t thread_id,
|
||||
struct rtos_reg **reg_list, int *num_regs);
|
||||
static int chibios_get_symbol_list_to_lookup(symbol_table_elem_t *symbol_list[]);
|
||||
static int chibios_get_symbol_list_to_lookup(struct symbol_table_elem *symbol_list[]);
|
||||
|
||||
struct rtos_type chibios_rtos = {
|
||||
.name = "chibios",
|
||||
|
@ -131,7 +131,7 @@ enum chibios_symbol_values {
|
|||
CHIBIOS_VAL_CH_DEBUG = 2
|
||||
};
|
||||
|
||||
static symbol_table_elem_t chibios_symbol_list[] = {
|
||||
static struct symbol_table_elem chibios_symbol_list[] = {
|
||||
{ "rlist", 0, true}, /* Thread ready list */
|
||||
{ "ch", 0, true}, /* System data structure */
|
||||
{ "ch_debug", 0, false}, /* Memory Signature containing offsets of fields in rlist */
|
||||
|
@ -497,7 +497,7 @@ static int chibios_get_thread_reg_list(struct rtos *rtos, int64_t thread_id,
|
|||
return rtos_generic_stack_read(rtos->target, param->stacking_info, stack_ptr, reg_list, num_regs);
|
||||
}
|
||||
|
||||
static int chibios_get_symbol_list_to_lookup(symbol_table_elem_t *symbol_list[])
|
||||
static int chibios_get_symbol_list_to_lookup(struct symbol_table_elem *symbol_list[])
|
||||
{
|
||||
*symbol_list = malloc(sizeof(chibios_symbol_list));
|
||||
|
||||
|
|
|
@ -360,12 +360,12 @@ static int chromium_ec_get_thread_reg_list(struct rtos *rtos,
|
|||
stack_ptr, reg_list, num_regs);
|
||||
}
|
||||
|
||||
static int chromium_ec_get_symbol_list_to_lookup(symbol_table_elem_t *symbol_list[])
|
||||
static int chromium_ec_get_symbol_list_to_lookup(struct symbol_table_elem *symbol_list[])
|
||||
{
|
||||
size_t s;
|
||||
|
||||
*symbol_list = calloc(ARRAY_SIZE(chromium_ec_symbol_list),
|
||||
sizeof(symbol_table_elem_t));
|
||||
sizeof(struct symbol_table_elem));
|
||||
if (!(*symbol_list)) {
|
||||
LOG_ERROR("Chromium-EC: out of memory");
|
||||
return ERROR_FAIL;
|
||||
|
|
|
@ -31,7 +31,7 @@ static bool eCos_detect_rtos(struct target *target);
|
|||
static int eCos_create(struct target *target);
|
||||
static int eCos_update_threads(struct rtos *rtos);
|
||||
static int eCos_get_thread_reg_list(struct rtos *rtos, int64_t thread_id, struct rtos_reg **reg_list, int *num_regs);
|
||||
static int eCos_get_symbol_list_to_lookup(symbol_table_elem_t *symbol_list[]);
|
||||
static int eCos_get_symbol_list_to_lookup(struct symbol_table_elem *symbol_list[]);
|
||||
|
||||
struct eCos_thread_state {
|
||||
int value;
|
||||
|
@ -351,11 +351,11 @@ static int eCos_get_thread_reg_list(struct rtos *rtos, int64_t thread_id,
|
|||
return -1;
|
||||
}
|
||||
|
||||
static int eCos_get_symbol_list_to_lookup(symbol_table_elem_t *symbol_list[])
|
||||
static int eCos_get_symbol_list_to_lookup(struct symbol_table_elem *symbol_list[])
|
||||
{
|
||||
unsigned int i;
|
||||
*symbol_list = calloc(
|
||||
ARRAY_SIZE(eCos_symbol_list), sizeof(symbol_table_elem_t));
|
||||
ARRAY_SIZE(eCos_symbol_list), sizeof(struct symbol_table_elem));
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(eCos_symbol_list); i++)
|
||||
(*symbol_list)[i].symbol_name = eCos_symbol_list[i];
|
||||
|
|
|
@ -36,7 +36,7 @@ static int embKernel_create(struct target *target);
|
|||
static int embKernel_update_threads(struct rtos *rtos);
|
||||
static int embKernel_get_thread_reg_list(struct rtos *rtos, int64_t thread_id,
|
||||
struct rtos_reg **reg_list, int *num_regs);
|
||||
static int embKernel_get_symbol_list_to_lookup(symbol_table_elem_t *symbol_list[]);
|
||||
static int embKernel_get_symbol_list_to_lookup(struct symbol_table_elem *symbol_list[]);
|
||||
|
||||
struct rtos_type embKernel_rtos = {
|
||||
.name = "embKernel",
|
||||
|
@ -330,10 +330,10 @@ static int embKernel_get_thread_reg_list(struct rtos *rtos, int64_t thread_id,
|
|||
return rtos_generic_stack_read(rtos->target, param->stacking_info, stack_ptr, reg_list, num_regs);
|
||||
}
|
||||
|
||||
static int embKernel_get_symbol_list_to_lookup(symbol_table_elem_t *symbol_list[])
|
||||
static int embKernel_get_symbol_list_to_lookup(struct symbol_table_elem *symbol_list[])
|
||||
{
|
||||
unsigned int i;
|
||||
*symbol_list = calloc(ARRAY_SIZE(embKernel_symbol_list), sizeof(symbol_table_elem_t));
|
||||
*symbol_list = calloc(ARRAY_SIZE(embKernel_symbol_list), sizeof(struct symbol_table_elem));
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(embKernel_symbol_list); i++)
|
||||
(*symbol_list)[i].symbol_name = embKernel_symbol_list[i];
|
||||
|
|
|
@ -35,7 +35,7 @@ static int hwthread_get_thread_reg(struct rtos *rtos, int64_t thread_id,
|
|||
uint32_t reg_num, struct rtos_reg *rtos_reg);
|
||||
static int hwthread_get_thread_reg_list(struct rtos *rtos, int64_t thread_id,
|
||||
struct rtos_reg **reg_list, int *num_regs);
|
||||
static int hwthread_get_symbol_list_to_lookup(symbol_table_elem_t *symbol_list[]);
|
||||
static int hwthread_get_symbol_list_to_lookup(struct symbol_table_elem *symbol_list[]);
|
||||
static int hwthread_smp_init(struct target *target);
|
||||
static int hwthread_set_reg(struct rtos *rtos, uint32_t reg_num, uint8_t *reg_value);
|
||||
static bool hwthread_needs_fake_step(struct target *target, int64_t thread_id);
|
||||
|
@ -338,10 +338,10 @@ static int hwthread_set_reg(struct rtos *rtos, uint32_t reg_num, uint8_t *reg_va
|
|||
return reg->type->set(reg, reg_value);
|
||||
}
|
||||
|
||||
static int hwthread_get_symbol_list_to_lookup(symbol_table_elem_t *symbol_list[])
|
||||
static int hwthread_get_symbol_list_to_lookup(struct symbol_table_elem *symbol_list[])
|
||||
{
|
||||
/* return an empty list, we don't have any symbols to look up */
|
||||
*symbol_list = calloc(1, sizeof(symbol_table_elem_t));
|
||||
*symbol_list = calloc(1, sizeof(struct symbol_table_elem));
|
||||
(*symbol_list)[0].symbol_name = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -246,11 +246,11 @@ static const char * const linux_symbol_list[] = {
|
|||
NULL
|
||||
};
|
||||
|
||||
static int linux_get_symbol_list_to_lookup(symbol_table_elem_t *symbol_list[])
|
||||
static int linux_get_symbol_list_to_lookup(struct symbol_table_elem *symbol_list[])
|
||||
{
|
||||
unsigned int i;
|
||||
*symbol_list = (symbol_table_elem_t *)
|
||||
calloc(ARRAY_SIZE(linux_symbol_list), sizeof(symbol_table_elem_t));
|
||||
*symbol_list = (struct symbol_table_elem *)
|
||||
calloc(ARRAY_SIZE(linux_symbol_list), sizeof(struct symbol_table_elem));
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(linux_symbol_list); i++)
|
||||
(*symbol_list)[i].symbol_name = linux_symbol_list[i];
|
||||
|
|
|
@ -540,9 +540,9 @@ static int mqx_get_thread_reg_list(
|
|||
}
|
||||
|
||||
/* API function, export list of required symbols */
|
||||
static int mqx_get_symbol_list_to_lookup(symbol_table_elem_t *symbol_list[])
|
||||
static int mqx_get_symbol_list_to_lookup(struct symbol_table_elem *symbol_list[])
|
||||
{
|
||||
*symbol_list = calloc(ARRAY_SIZE(mqx_symbol_list), sizeof(symbol_table_elem_t));
|
||||
*symbol_list = calloc(ARRAY_SIZE(mqx_symbol_list), sizeof(struct symbol_table_elem));
|
||||
if (NULL == *symbol_list)
|
||||
return ERROR_FAIL;
|
||||
/* export required symbols */
|
||||
|
|
|
@ -378,12 +378,12 @@ static int nuttx_get_thread_reg_list(struct rtos *rtos, int64_t thread_id,
|
|||
(uint32_t)thread_id + xcpreg_offset, reg_list, num_regs);
|
||||
}
|
||||
|
||||
static int nuttx_get_symbol_list_to_lookup(symbol_table_elem_t *symbol_list[])
|
||||
static int nuttx_get_symbol_list_to_lookup(struct symbol_table_elem *symbol_list[])
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
*symbol_list = (symbol_table_elem_t *) calloc(1,
|
||||
sizeof(symbol_table_elem_t) * ARRAY_SIZE(nuttx_symbol_list));
|
||||
*symbol_list = (struct symbol_table_elem *) calloc(1,
|
||||
sizeof(struct symbol_table_elem) * ARRAY_SIZE(nuttx_symbol_list));
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(nuttx_symbol_list); i++)
|
||||
(*symbol_list)[i].symbol_name = nuttx_symbol_list[i];
|
||||
|
|
|
@ -35,7 +35,7 @@ static int riot_create(struct target *target);
|
|||
static int riot_update_threads(struct rtos *rtos);
|
||||
static int riot_get_thread_reg_list(struct rtos *rtos, int64_t thread_id,
|
||||
struct rtos_reg **reg_list, int *num_regs);
|
||||
static int riot_get_symbol_list_to_lookup(symbol_table_elem_t *symbol_list[]);
|
||||
static int riot_get_symbol_list_to_lookup(struct symbol_table_elem *symbol_list[]);
|
||||
|
||||
struct riot_thread_state {
|
||||
int value;
|
||||
|
@ -360,9 +360,9 @@ static int riot_get_thread_reg_list(struct rtos *rtos, int64_t thread_id,
|
|||
num_regs);
|
||||
}
|
||||
|
||||
static int riot_get_symbol_list_to_lookup(symbol_table_elem_t *symbol_list[])
|
||||
static int riot_get_symbol_list_to_lookup(struct symbol_table_elem *symbol_list[])
|
||||
{
|
||||
*symbol_list = calloc(ARRAY_SIZE(riot_symbol_list), sizeof(symbol_table_elem_t));
|
||||
*symbol_list = calloc(ARRAY_SIZE(riot_symbol_list), sizeof(struct symbol_table_elem));
|
||||
|
||||
if (*symbol_list == NULL) {
|
||||
LOG_ERROR("RIOT: out of memory");
|
||||
|
|
|
@ -184,9 +184,9 @@ int gdb_thread_packet(struct connection *connection, char const *packet, int pac
|
|||
return target->rtos->gdb_thread_packet(connection, packet, packet_size);
|
||||
}
|
||||
|
||||
static symbol_table_elem_t *next_symbol(struct rtos *os, char *cur_symbol, uint64_t cur_addr)
|
||||
static struct symbol_table_elem *next_symbol(struct rtos *os, char *cur_symbol, uint64_t cur_addr)
|
||||
{
|
||||
symbol_table_elem_t *s;
|
||||
struct symbol_table_elem *s;
|
||||
|
||||
if (!os->symbols)
|
||||
os->type->get_symbol_list_to_lookup(&os->symbols);
|
||||
|
@ -208,7 +208,7 @@ static symbol_table_elem_t *next_symbol(struct rtos *os, char *cur_symbol, uint6
|
|||
* if 'symbol' is not declared optional */
|
||||
static bool is_symbol_mandatory(const struct rtos *os, const char *symbol)
|
||||
{
|
||||
for (symbol_table_elem_t *s = os->symbols; s->symbol_name; ++s) {
|
||||
for (struct symbol_table_elem *s = os->symbols; s->symbol_name; ++s) {
|
||||
if (!strcmp(s->symbol_name, symbol))
|
||||
return !s->optional;
|
||||
}
|
||||
|
@ -240,7 +240,7 @@ int rtos_qsymbol(struct connection *connection, char const *packet, int packet_s
|
|||
uint64_t addr = 0;
|
||||
size_t reply_len;
|
||||
char reply[GDB_BUFFER_SIZE + 1], cur_sym[GDB_BUFFER_SIZE / 2 + 1] = ""; /* Extra byte for null-termination */
|
||||
symbol_table_elem_t *next_sym = NULL;
|
||||
struct symbol_table_elem *next_sym = NULL;
|
||||
struct target *target = get_target_from_connection(connection);
|
||||
struct rtos *os = target->rtos;
|
||||
|
||||
|
|
|
@ -31,11 +31,11 @@ struct reg;
|
|||
/**
|
||||
* Table should be terminated by an element with NULL in symbol_name
|
||||
*/
|
||||
typedef struct symbol_table_elem_struct {
|
||||
struct symbol_table_elem {
|
||||
const char *symbol_name;
|
||||
symbol_address_t address;
|
||||
bool optional;
|
||||
} symbol_table_elem_t;
|
||||
};
|
||||
|
||||
struct thread_detail {
|
||||
threadid_t threadid;
|
||||
|
@ -47,7 +47,7 @@ struct thread_detail {
|
|||
struct rtos {
|
||||
const struct rtos_type *type;
|
||||
|
||||
symbol_table_elem_t *symbols;
|
||||
struct symbol_table_elem *symbols;
|
||||
struct target *target;
|
||||
/* add a context variable instead of global variable */
|
||||
/* The thread currently selected by gdb. */
|
||||
|
@ -81,7 +81,7 @@ struct rtos_type {
|
|||
struct rtos_reg **reg_list, int *num_regs);
|
||||
int (*get_thread_reg)(struct rtos *rtos, threadid_t thread_id,
|
||||
uint32_t reg_num, struct rtos_reg *reg);
|
||||
int (*get_symbol_list_to_lookup)(symbol_table_elem_t *symbol_list[]);
|
||||
int (*get_symbol_list_to_lookup)(struct symbol_table_elem *symbol_list[]);
|
||||
int (*clean)(struct target *target);
|
||||
char * (*ps_command)(struct target *target);
|
||||
int (*set_reg)(struct rtos *rtos, uint32_t reg_num, uint8_t *reg_value);
|
||||
|
|
|
@ -508,9 +508,9 @@ static int uCOS_III_get_thread_reg_list(struct rtos *rtos, threadid_t threadid,
|
|||
num_regs);
|
||||
}
|
||||
|
||||
static int uCOS_III_get_symbol_list_to_lookup(symbol_table_elem_t *symbol_list[])
|
||||
static int uCOS_III_get_symbol_list_to_lookup(struct symbol_table_elem *symbol_list[])
|
||||
{
|
||||
*symbol_list = calloc(ARRAY_SIZE(uCOS_III_symbol_list), sizeof(symbol_table_elem_t));
|
||||
*symbol_list = calloc(ARRAY_SIZE(uCOS_III_symbol_list), sizeof(struct symbol_table_elem));
|
||||
if (*symbol_list == NULL) {
|
||||
LOG_ERROR("uCOS-III: out of memory");
|
||||
return ERROR_FAIL;
|
||||
|
|
|
@ -726,7 +726,7 @@ static void gdb_signal_reply(struct target *target, struct connection *connectio
|
|||
{
|
||||
struct gdb_connection *gdb_connection = connection->priv;
|
||||
char sig_reply[65];
|
||||
char stop_reason[20];
|
||||
char stop_reason[32];
|
||||
char current_thread[25];
|
||||
int sig_reply_len;
|
||||
int signal_var;
|
||||
|
@ -3617,7 +3617,7 @@ static int gdb_target_start(struct target *target, const char *port)
|
|||
|
||||
ret = add_service("gdb",
|
||||
port, target->gdb_max_connections, &gdb_new_connection, &gdb_input,
|
||||
&gdb_connection_closed, gdb_service, NULL);
|
||||
&gdb_connection_closed, gdb_service);
|
||||
/* initialize all targets gdb service with the same pointer */
|
||||
{
|
||||
struct target_list *head;
|
||||
|
|
|
@ -126,7 +126,7 @@ COMMAND_HANDLER(handle_rtt_start_command)
|
|||
COMMAND_PARSE_NUMBER(uint, CMD_ARGV[1], service->channel);
|
||||
|
||||
ret = add_service("rtt", CMD_ARGV[0], CONNECTION_LIMIT_UNLIMITED,
|
||||
rtt_new_connection, rtt_input, rtt_connection_closed, service, NULL);
|
||||
rtt_new_connection, rtt_input, rtt_connection_closed, service);
|
||||
|
||||
if (ret != ERROR_OK) {
|
||||
free(service);
|
||||
|
|
|
@ -211,8 +211,7 @@ int add_service(char *name,
|
|||
new_connection_handler_t new_connection_handler,
|
||||
input_handler_t input_handler,
|
||||
connection_closed_handler_t connection_closed_handler,
|
||||
void *priv,
|
||||
struct service **new_service)
|
||||
void *priv)
|
||||
{
|
||||
struct service *c, **p;
|
||||
struct hostent *hp;
|
||||
|
@ -348,10 +347,6 @@ int add_service(char *name,
|
|||
;
|
||||
*p = c;
|
||||
|
||||
/* if new_service is not NULL, return the created service into it */
|
||||
if (new_service)
|
||||
*new_service = c;
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
|
|
|
@ -78,7 +78,7 @@ struct service {
|
|||
int add_service(char *name, const char *port,
|
||||
int max_connections, new_connection_handler_t new_connection_handler,
|
||||
input_handler_t in_handler, connection_closed_handler_t close_handler,
|
||||
void *priv, struct service **new_service);
|
||||
void *priv);
|
||||
int remove_service(const char *name, const char *port);
|
||||
|
||||
int server_host_os_entry(void);
|
||||
|
|
|
@ -285,7 +285,7 @@ int tcl_init(void)
|
|||
|
||||
return add_service("tcl", tcl_port, CONNECTION_LIMIT_UNLIMITED,
|
||||
&tcl_new_connection, &tcl_input,
|
||||
&tcl_closed, NULL, NULL);
|
||||
&tcl_closed, NULL);
|
||||
}
|
||||
|
||||
COMMAND_HANDLER(handle_tcl_port_command)
|
||||
|
|
|
@ -596,6 +596,12 @@ static int telnet_input(struct connection *connection)
|
|||
telnet_history_up(connection);
|
||||
} else if (*buf_p == 'B') { /* cursor down */
|
||||
telnet_history_down(connection);
|
||||
} else if (*buf_p == 'F') { /* end key */
|
||||
telnet_move_cursor(connection, t_con->line_size);
|
||||
t_con->state = TELNET_STATE_DATA;
|
||||
} else if (*buf_p == 'H') { /* home key */
|
||||
telnet_move_cursor(connection, 0);
|
||||
t_con->state = TELNET_STATE_DATA;
|
||||
} else if (*buf_p == '3')
|
||||
t_con->last_escape = *buf_p;
|
||||
else
|
||||
|
@ -694,7 +700,7 @@ int telnet_init(char *banner)
|
|||
|
||||
int ret = add_service("telnet", telnet_port, CONNECTION_LIMIT_UNLIMITED,
|
||||
telnet_new_connection, telnet_input, telnet_connection_closed,
|
||||
telnet_service, NULL);
|
||||
telnet_service);
|
||||
|
||||
if (ret != ERROR_OK) {
|
||||
free(telnet_service);
|
||||
|
|
|
@ -1,9 +1,3 @@
|
|||
if OOCD_TRACE
|
||||
OOCD_TRACE_FILES = %D%/oocd_trace.c
|
||||
else
|
||||
OOCD_TRACE_FILES =
|
||||
endif
|
||||
|
||||
%C%_libtarget_la_LIBADD = %D%/openrisc/libopenrisc.la \
|
||||
%D%/riscv/libriscv.la
|
||||
|
||||
|
@ -111,8 +105,8 @@ ARM_DEBUG_SRC = \
|
|||
%D%/trace.c \
|
||||
%D%/etb.c \
|
||||
%D%/etm.c \
|
||||
$(OOCD_TRACE_FILES) \
|
||||
%D%/etm_dummy.c \
|
||||
%D%/arm_tpiu_swo.c \
|
||||
%D%/arm_cti.c
|
||||
|
||||
AVR32_SRC = \
|
||||
|
@ -214,6 +208,7 @@ ARC_SRC = \
|
|||
%D%/etb.h \
|
||||
%D%/etm.h \
|
||||
%D%/etm_dummy.h \
|
||||
%D%/arm_tpiu_swo.h \
|
||||
%D%/image.h \
|
||||
%D%/mips32.h \
|
||||
%D%/mips64.h \
|
||||
|
@ -223,7 +218,6 @@ ARC_SRC = \
|
|||
%D%/mips32_pracc.h \
|
||||
%D%/mips32_dmaacc.h \
|
||||
%D%/mips64_pracc.h \
|
||||
%D%/oocd_trace.h \
|
||||
%D%/register.h \
|
||||
%D%/target.h \
|
||||
%D%/target_type.h \
|
||||
|
|
|
@ -1651,7 +1651,6 @@ static int aarch64_add_hybrid_breakpoint(struct target *target,
|
|||
return aarch64_set_hybrid_breakpoint(target, breakpoint); /* ??? */
|
||||
}
|
||||
|
||||
|
||||
static int aarch64_remove_breakpoint(struct target *target, struct breakpoint *breakpoint)
|
||||
{
|
||||
struct aarch64_common *aarch64 = target_to_aarch64(target);
|
||||
|
@ -1673,26 +1672,307 @@ static int aarch64_remove_breakpoint(struct target *target, struct breakpoint *b
|
|||
return ERROR_OK;
|
||||
}
|
||||
|
||||
/* Setup hardware Watchpoint Register Pair */
|
||||
static int aarch64_set_watchpoint(struct target *target,
|
||||
struct watchpoint *watchpoint)
|
||||
{
|
||||
int retval;
|
||||
int wp_i = 0;
|
||||
uint32_t control, offset, length;
|
||||
struct aarch64_common *aarch64 = target_to_aarch64(target);
|
||||
struct armv8_common *armv8 = &aarch64->armv8_common;
|
||||
struct aarch64_brp *wp_list = aarch64->wp_list;
|
||||
|
||||
if (watchpoint->set) {
|
||||
LOG_WARNING("watchpoint already set");
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
while (wp_list[wp_i].used && (wp_i < aarch64->wp_num))
|
||||
wp_i++;
|
||||
if (wp_i >= aarch64->wp_num) {
|
||||
LOG_ERROR("ERROR Can not find free Watchpoint Register Pair");
|
||||
return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
|
||||
}
|
||||
|
||||
control = (1 << 0) /* enable */
|
||||
| (3 << 1) /* both user and privileged access */
|
||||
| (1 << 13); /* higher mode control */
|
||||
|
||||
switch (watchpoint->rw) {
|
||||
case WPT_READ:
|
||||
control |= 1 << 3;
|
||||
break;
|
||||
case WPT_WRITE:
|
||||
control |= 2 << 3;
|
||||
break;
|
||||
case WPT_ACCESS:
|
||||
control |= 3 << 3;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Match up to 8 bytes. */
|
||||
offset = watchpoint->address & 7;
|
||||
length = watchpoint->length;
|
||||
if (offset + length > sizeof(uint64_t)) {
|
||||
length = sizeof(uint64_t) - offset;
|
||||
LOG_WARNING("Adjust watchpoint match inside 8-byte boundary");
|
||||
}
|
||||
for (; length > 0; offset++, length--)
|
||||
control |= (1 << offset) << 5;
|
||||
|
||||
wp_list[wp_i].value = watchpoint->address & 0xFFFFFFFFFFFFFFF8ULL;
|
||||
wp_list[wp_i].control = control;
|
||||
|
||||
retval = aarch64_dap_write_memap_register_u32(target, armv8->debug_base
|
||||
+ CPUV8_DBG_WVR_BASE + 16 * wp_list[wp_i].BRPn,
|
||||
(uint32_t)(wp_list[wp_i].value & 0xFFFFFFFF));
|
||||
if (retval != ERROR_OK)
|
||||
return retval;
|
||||
retval = aarch64_dap_write_memap_register_u32(target, armv8->debug_base
|
||||
+ CPUV8_DBG_WVR_BASE + 4 + 16 * wp_list[wp_i].BRPn,
|
||||
(uint32_t)(wp_list[wp_i].value >> 32));
|
||||
if (retval != ERROR_OK)
|
||||
return retval;
|
||||
|
||||
retval = aarch64_dap_write_memap_register_u32(target, armv8->debug_base
|
||||
+ CPUV8_DBG_WCR_BASE + 16 * wp_list[wp_i].BRPn,
|
||||
control);
|
||||
if (retval != ERROR_OK)
|
||||
return retval;
|
||||
LOG_DEBUG("wp %i control 0x%0" PRIx32 " value 0x%" TARGET_PRIxADDR, wp_i,
|
||||
wp_list[wp_i].control, wp_list[wp_i].value);
|
||||
|
||||
/* Ensure that halting debug mode is enable */
|
||||
retval = aarch64_set_dscr_bits(target, DSCR_HDE, DSCR_HDE);
|
||||
if (retval != ERROR_OK) {
|
||||
LOG_DEBUG("Failed to set DSCR.HDE");
|
||||
return retval;
|
||||
}
|
||||
|
||||
wp_list[wp_i].used = 1;
|
||||
watchpoint->set = wp_i + 1;
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
/* Clear hardware Watchpoint Register Pair */
|
||||
static int aarch64_unset_watchpoint(struct target *target,
|
||||
struct watchpoint *watchpoint)
|
||||
{
|
||||
int retval, wp_i;
|
||||
struct aarch64_common *aarch64 = target_to_aarch64(target);
|
||||
struct armv8_common *armv8 = &aarch64->armv8_common;
|
||||
struct aarch64_brp *wp_list = aarch64->wp_list;
|
||||
|
||||
if (!watchpoint->set) {
|
||||
LOG_WARNING("watchpoint not set");
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
wp_i = watchpoint->set - 1;
|
||||
if ((wp_i < 0) || (wp_i >= aarch64->wp_num)) {
|
||||
LOG_DEBUG("Invalid WP number in watchpoint");
|
||||
return ERROR_OK;
|
||||
}
|
||||
LOG_DEBUG("rwp %i control 0x%0" PRIx32 " value 0x%0" PRIx64, wp_i,
|
||||
wp_list[wp_i].control, wp_list[wp_i].value);
|
||||
wp_list[wp_i].used = 0;
|
||||
wp_list[wp_i].value = 0;
|
||||
wp_list[wp_i].control = 0;
|
||||
retval = aarch64_dap_write_memap_register_u32(target, armv8->debug_base
|
||||
+ CPUV8_DBG_WCR_BASE + 16 * wp_list[wp_i].BRPn,
|
||||
wp_list[wp_i].control);
|
||||
if (retval != ERROR_OK)
|
||||
return retval;
|
||||
retval = aarch64_dap_write_memap_register_u32(target, armv8->debug_base
|
||||
+ CPUV8_DBG_WVR_BASE + 16 * wp_list[wp_i].BRPn,
|
||||
wp_list[wp_i].value);
|
||||
if (retval != ERROR_OK)
|
||||
return retval;
|
||||
|
||||
retval = aarch64_dap_write_memap_register_u32(target, armv8->debug_base
|
||||
+ CPUV8_DBG_WVR_BASE + 4 + 16 * wp_list[wp_i].BRPn,
|
||||
(uint32_t)wp_list[wp_i].value);
|
||||
if (retval != ERROR_OK)
|
||||
return retval;
|
||||
watchpoint->set = 0;
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
static int aarch64_add_watchpoint(struct target *target,
|
||||
struct watchpoint *watchpoint)
|
||||
{
|
||||
int retval;
|
||||
struct aarch64_common *aarch64 = target_to_aarch64(target);
|
||||
|
||||
if (aarch64->wp_num_available < 1) {
|
||||
LOG_INFO("no hardware watchpoint available");
|
||||
return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
|
||||
}
|
||||
|
||||
retval = aarch64_set_watchpoint(target, watchpoint);
|
||||
if (retval == ERROR_OK)
|
||||
aarch64->wp_num_available--;
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
static int aarch64_remove_watchpoint(struct target *target,
|
||||
struct watchpoint *watchpoint)
|
||||
{
|
||||
struct aarch64_common *aarch64 = target_to_aarch64(target);
|
||||
|
||||
if (watchpoint->set) {
|
||||
aarch64_unset_watchpoint(target, watchpoint);
|
||||
aarch64->wp_num_available++;
|
||||
}
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* find out which watchpoint hits
|
||||
* get exception address and compare the address to watchpoints
|
||||
*/
|
||||
int aarch64_hit_watchpoint(struct target *target,
|
||||
struct watchpoint **hit_watchpoint)
|
||||
{
|
||||
if (target->debug_reason != DBG_REASON_WATCHPOINT)
|
||||
return ERROR_FAIL;
|
||||
|
||||
struct armv8_common *armv8 = target_to_armv8(target);
|
||||
|
||||
uint64_t exception_address;
|
||||
struct watchpoint *wp;
|
||||
|
||||
exception_address = armv8->dpm.wp_pc;
|
||||
|
||||
if (exception_address == 0xFFFFFFFF)
|
||||
return ERROR_FAIL;
|
||||
|
||||
/**********************************************************/
|
||||
/* see if a watchpoint address matches a value read from */
|
||||
/* the EDWAR register. Testing shows that on some ARM CPUs*/
|
||||
/* the EDWAR value needs to have 8 added to it so we add */
|
||||
/* that check as well not sure if that is a core bug) */
|
||||
/**********************************************************/
|
||||
for (exception_address = armv8->dpm.wp_pc; exception_address <= (armv8->dpm.wp_pc + 8);
|
||||
exception_address += 8) {
|
||||
for (wp = target->watchpoints; wp; wp = wp->next) {
|
||||
if ((exception_address >= wp->address) && (exception_address < (wp->address + wp->length))) {
|
||||
*hit_watchpoint = wp;
|
||||
if (exception_address != armv8->dpm.wp_pc)
|
||||
LOG_DEBUG("watchpoint hit required EDWAR to be increased by 8");
|
||||
return ERROR_OK;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Cortex-A8 Reset functions
|
||||
*/
|
||||
|
||||
static int aarch64_enable_reset_catch(struct target *target, bool enable)
|
||||
{
|
||||
struct armv8_common *armv8 = target_to_armv8(target);
|
||||
uint32_t edecr;
|
||||
int retval;
|
||||
|
||||
retval = mem_ap_read_atomic_u32(armv8->debug_ap,
|
||||
armv8->debug_base + CPUV8_DBG_EDECR, &edecr);
|
||||
LOG_DEBUG("EDECR = 0x%08" PRIx32 ", enable=%d", edecr, enable);
|
||||
if (retval != ERROR_OK)
|
||||
return retval;
|
||||
|
||||
if (enable)
|
||||
edecr |= ECR_RCE;
|
||||
else
|
||||
edecr &= ~ECR_RCE;
|
||||
|
||||
return mem_ap_write_atomic_u32(armv8->debug_ap,
|
||||
armv8->debug_base + CPUV8_DBG_EDECR, edecr);
|
||||
}
|
||||
|
||||
static int aarch64_clear_reset_catch(struct target *target)
|
||||
{
|
||||
struct armv8_common *armv8 = target_to_armv8(target);
|
||||
uint32_t edesr;
|
||||
int retval;
|
||||
bool was_triggered;
|
||||
|
||||
/* check if Reset Catch debug event triggered as expected */
|
||||
retval = mem_ap_read_atomic_u32(armv8->debug_ap,
|
||||
armv8->debug_base + CPUV8_DBG_EDESR, &edesr);
|
||||
if (retval != ERROR_OK)
|
||||
return retval;
|
||||
|
||||
was_triggered = !!(edesr & ESR_RC);
|
||||
LOG_DEBUG("Reset Catch debug event %s",
|
||||
was_triggered ? "triggered" : "NOT triggered!");
|
||||
|
||||
if (was_triggered) {
|
||||
/* clear pending Reset Catch debug event */
|
||||
edesr &= ~ESR_RC;
|
||||
retval = mem_ap_write_atomic_u32(armv8->debug_ap,
|
||||
armv8->debug_base + CPUV8_DBG_EDESR, edesr);
|
||||
if (retval != ERROR_OK)
|
||||
return retval;
|
||||
}
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
static int aarch64_assert_reset(struct target *target)
|
||||
{
|
||||
struct armv8_common *armv8 = target_to_armv8(target);
|
||||
enum reset_types reset_config = jtag_get_reset_config();
|
||||
int retval;
|
||||
|
||||
LOG_DEBUG(" ");
|
||||
|
||||
/* FIXME when halt is requested, make it work somehow... */
|
||||
|
||||
/* Issue some kind of warm reset. */
|
||||
if (target_has_event_action(target, TARGET_EVENT_RESET_ASSERT))
|
||||
target_handle_event(target, TARGET_EVENT_RESET_ASSERT);
|
||||
else if (jtag_get_reset_config() & RESET_HAS_SRST) {
|
||||
else if (reset_config & RESET_HAS_SRST) {
|
||||
bool srst_asserted = false;
|
||||
|
||||
if (target->reset_halt) {
|
||||
if (target_was_examined(target)) {
|
||||
|
||||
if (reset_config & RESET_SRST_NO_GATING) {
|
||||
/*
|
||||
* SRST needs to be asserted *before* Reset Catch
|
||||
* debug event can be set up.
|
||||
*/
|
||||
adapter_assert_reset();
|
||||
srst_asserted = true;
|
||||
|
||||
/* make sure to clear all sticky errors */
|
||||
mem_ap_write_atomic_u32(armv8->debug_ap,
|
||||
armv8->debug_base + CPUV8_DBG_DRCR, DRCR_CSE);
|
||||
}
|
||||
|
||||
/* set up Reset Catch debug event to halt the CPU after reset */
|
||||
retval = aarch64_enable_reset_catch(target, true);
|
||||
if (retval != ERROR_OK)
|
||||
LOG_WARNING("%s: Error enabling Reset Catch debug event; the CPU will not halt immediately after reset!",
|
||||
target_name(target));
|
||||
} else {
|
||||
LOG_WARNING("%s: Target not examined, will not halt immediately after reset!",
|
||||
target_name(target));
|
||||
}
|
||||
}
|
||||
|
||||
/* REVISIT handle "pulls" cases, if there's
|
||||
* hardware that needs them to work.
|
||||
*/
|
||||
adapter_assert_reset();
|
||||
if (!srst_asserted)
|
||||
adapter_assert_reset();
|
||||
} else {
|
||||
LOG_ERROR("%s: how to reset?", target_name(target));
|
||||
return ERROR_FAIL;
|
||||
|
@ -1721,23 +2001,37 @@ static int aarch64_deassert_reset(struct target *target)
|
|||
if (!target_was_examined(target))
|
||||
return ERROR_OK;
|
||||
|
||||
retval = aarch64_poll(target);
|
||||
if (retval != ERROR_OK)
|
||||
return retval;
|
||||
|
||||
retval = aarch64_init_debug_access(target);
|
||||
if (retval != ERROR_OK)
|
||||
return retval;
|
||||
|
||||
retval = aarch64_poll(target);
|
||||
if (retval != ERROR_OK)
|
||||
return retval;
|
||||
|
||||
if (target->reset_halt) {
|
||||
/* clear pending Reset Catch debug event */
|
||||
retval = aarch64_clear_reset_catch(target);
|
||||
if (retval != ERROR_OK)
|
||||
LOG_WARNING("%s: Clearing Reset Catch debug event failed",
|
||||
target_name(target));
|
||||
|
||||
/* disable Reset Catch debug event */
|
||||
retval = aarch64_enable_reset_catch(target, false);
|
||||
if (retval != ERROR_OK)
|
||||
LOG_WARNING("%s: Disabling Reset Catch debug event failed",
|
||||
target_name(target));
|
||||
|
||||
if (target->state != TARGET_HALTED) {
|
||||
LOG_WARNING("%s: ran after reset and before halt ...",
|
||||
target_name(target));
|
||||
retval = target_halt(target);
|
||||
if (retval != ERROR_OK)
|
||||
return retval;
|
||||
}
|
||||
}
|
||||
|
||||
return retval;
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
static int aarch64_write_cpu_memory_slow(struct target *target,
|
||||
|
@ -2367,7 +2661,20 @@ static int aarch64_examine_first(struct target *target)
|
|||
aarch64->brp_list[i].BRPn = i;
|
||||
}
|
||||
|
||||
LOG_DEBUG("Configured %i hw breakpoints", aarch64->brp_num);
|
||||
/* Setup Watchpoint Register Pairs */
|
||||
aarch64->wp_num = (uint32_t)((debug >> 20) & 0x0F) + 1;
|
||||
aarch64->wp_num_available = aarch64->wp_num;
|
||||
aarch64->wp_list = calloc(aarch64->wp_num, sizeof(struct aarch64_brp));
|
||||
for (i = 0; i < aarch64->wp_num; i++) {
|
||||
aarch64->wp_list[i].used = 0;
|
||||
aarch64->wp_list[i].type = BRP_NORMAL;
|
||||
aarch64->wp_list[i].value = 0;
|
||||
aarch64->wp_list[i].control = 0;
|
||||
aarch64->wp_list[i].BRPn = i;
|
||||
}
|
||||
|
||||
LOG_DEBUG("Configured %i hw breakpoints, %i watchpoints",
|
||||
aarch64->brp_num, aarch64->wp_num);
|
||||
|
||||
target->state = TARGET_UNKNOWN;
|
||||
target->debug_reason = DBG_REASON_NOTHALTED;
|
||||
|
@ -2883,8 +3190,9 @@ struct target_type aarch64_target = {
|
|||
.add_context_breakpoint = aarch64_add_context_breakpoint,
|
||||
.add_hybrid_breakpoint = aarch64_add_hybrid_breakpoint,
|
||||
.remove_breakpoint = aarch64_remove_breakpoint,
|
||||
.add_watchpoint = NULL,
|
||||
.remove_watchpoint = NULL,
|
||||
.add_watchpoint = aarch64_add_watchpoint,
|
||||
.remove_watchpoint = aarch64_remove_watchpoint,
|
||||
.hit_watchpoint = aarch64_hit_watchpoint,
|
||||
|
||||
.commands = aarch64_command_handlers,
|
||||
.target_create = aarch64_target_create,
|
||||
|
|
|
@ -62,6 +62,11 @@ struct aarch64_common {
|
|||
int brp_num_available;
|
||||
struct aarch64_brp *brp_list;
|
||||
|
||||
/* Watchpoint register pairs */
|
||||
int wp_num;
|
||||
int wp_num_available;
|
||||
struct aarch64_brp *wp_list;
|
||||
|
||||
struct armv8_common armv8_common;
|
||||
|
||||
enum aarch64_isrmasking_mode isrmasking_mode;
|
||||
|
|
|
@ -227,7 +227,7 @@ static int arc_get_register(struct reg *reg)
|
|||
|
||||
if (desc->is_core) {
|
||||
/* Accessing to R61/R62 registers causes Jtag hang */
|
||||
if (desc->arch_num == CORE_R61_NUM || desc->arch_num == CORE_R62_NUM) {
|
||||
if (desc->arch_num == ARC_R61 || desc->arch_num == ARC_R62) {
|
||||
LOG_ERROR("It is forbidden to read core registers 61 and 62.");
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
|
@ -267,8 +267,8 @@ static int arc_set_register(struct reg *reg, uint8_t *buf)
|
|||
return ERROR_TARGET_NOT_HALTED;
|
||||
|
||||
/* Accessing to R61/R62 registers causes Jtag hang */
|
||||
if (desc->is_core && (desc->arch_num == CORE_R61_NUM ||
|
||||
desc->arch_num == CORE_R62_NUM)) {
|
||||
if (desc->is_core && (desc->arch_num == ARC_R61 ||
|
||||
desc->arch_num == ARC_R62)) {
|
||||
LOG_ERROR("It is forbidden to write core registers 61 and 62.");
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
|
|
|
@ -45,9 +45,52 @@
|
|||
#define AUX_STATUS32_REG_HALT_BIT BIT(0)
|
||||
#define AUX_STATUS32_REG_IE_BIT BIT(31) /* STATUS32[31] = IE field */
|
||||
|
||||
/* Reserved core registers */
|
||||
#define CORE_R61_NUM (61)
|
||||
#define CORE_R62_NUM (62)
|
||||
/* ARC register numbers */
|
||||
enum {
|
||||
ARC_R0,
|
||||
ARC_R1,
|
||||
ARC_R2,
|
||||
ARC_R3,
|
||||
ARC_R4,
|
||||
ARC_R5,
|
||||
ARC_R6,
|
||||
ARC_R7,
|
||||
ARC_R8,
|
||||
ARC_R9,
|
||||
ARC_R10,
|
||||
ARC_R11,
|
||||
ARC_R12,
|
||||
ARC_R13,
|
||||
ARC_R14,
|
||||
ARC_R15,
|
||||
ARC_R16,
|
||||
ARC_R17,
|
||||
ARC_R18,
|
||||
ARC_R19,
|
||||
ARC_R20,
|
||||
ARC_R21,
|
||||
ARC_R22,
|
||||
ARC_R23,
|
||||
ARC_R24,
|
||||
ARC_R25,
|
||||
ARC_GP = 26,
|
||||
ARC_FP = 27,
|
||||
ARC_SP = 28,
|
||||
ARC_ILINK = 29,
|
||||
ARC_R30,
|
||||
ARC_BLINK = 31,
|
||||
ARC_LP_COUNT = 60,
|
||||
|
||||
/* Reserved registers */
|
||||
ARC_R61 = 61,
|
||||
ARC_R62 = 62,
|
||||
|
||||
ARC_PCL = 63,
|
||||
ARC_PC = 64,
|
||||
ARC_LP_START = 65,
|
||||
ARC_LP_END = 66,
|
||||
ARC_STATUS32 = 67,
|
||||
};
|
||||
|
||||
#define CORE_REG_MAX_NUMBER (63)
|
||||
|
||||
|
|
|
@ -382,7 +382,7 @@ static int jim_arc_get_core_reg(Jim_Interp *interp, int argc, Jim_Obj * const *a
|
|||
|
||||
/* Register number */
|
||||
JIM_CHECK_RETVAL(arc_cmd_jim_get_uint32(&goi, ®num));
|
||||
if (regnum > CORE_REG_MAX_NUMBER || regnum == CORE_R61_NUM || regnum == CORE_R62_NUM) {
|
||||
if (regnum > CORE_REG_MAX_NUMBER || regnum == ARC_R61 || regnum == ARC_R62) {
|
||||
Jim_SetResultFormatted(goi.interp, "Core register number %i "
|
||||
"is invalid. Must less then 64 and not 61 and 62.", regnum);
|
||||
return JIM_ERR;
|
||||
|
@ -425,7 +425,7 @@ static int jim_arc_set_core_reg(Jim_Interp *interp, int argc, Jim_Obj * const *a
|
|||
|
||||
/* Register number */
|
||||
JIM_CHECK_RETVAL(arc_cmd_jim_get_uint32(&goi, ®num));
|
||||
if (regnum > CORE_REG_MAX_NUMBER || regnum == CORE_R61_NUM || regnum == CORE_R62_NUM) {
|
||||
if (regnum > CORE_REG_MAX_NUMBER || regnum == ARC_R61 || regnum == ARC_R62) {
|
||||
Jim_SetResultFormatted(goi.interp, "Core register number %i "
|
||||
"is invalid. Must less then 64 and not 61 and 62.", regnum);
|
||||
return JIM_ERR;
|
||||
|
|
|
@ -562,11 +562,7 @@ static const tap_state_t arm11_MOVE_DRPAUSE_IDLE_DRPAUSE_with_delay[] = {
|
|||
TAP_DRSHIFT
|
||||
};
|
||||
|
||||
/* This inner loop can be implemented by the minidriver, oftentimes in hardware... The
|
||||
* minidriver can call the default implementation as a fallback or implement it
|
||||
* from scratch.
|
||||
*/
|
||||
int arm11_run_instr_data_to_core_noack_inner_default(struct jtag_tap *tap,
|
||||
static int arm11_run_instr_data_to_core_noack_inner(struct jtag_tap *tap,
|
||||
uint32_t opcode,
|
||||
uint32_t *data,
|
||||
size_t count)
|
||||
|
@ -629,21 +625,6 @@ int arm11_run_instr_data_to_core_noack_inner_default(struct jtag_tap *tap,
|
|||
return retval;
|
||||
}
|
||||
|
||||
int arm11_run_instr_data_to_core_noack_inner(struct jtag_tap *tap,
|
||||
uint32_t opcode,
|
||||
uint32_t *data,
|
||||
size_t count);
|
||||
|
||||
#ifndef HAVE_JTAG_MINIDRIVER_H
|
||||
int arm11_run_instr_data_to_core_noack_inner(struct jtag_tap *tap,
|
||||
uint32_t opcode,
|
||||
uint32_t *data,
|
||||
size_t count)
|
||||
{
|
||||
return arm11_run_instr_data_to_core_noack_inner_default(tap, opcode, data, count);
|
||||
}
|
||||
#endif
|
||||
|
||||
/** Execute one instruction via ITR repeatedly while
|
||||
* passing data to the core via DTR on each execution.
|
||||
*
|
||||
|
|
|
@ -233,16 +233,6 @@ static void arm720t_pre_restore_context(struct target *target)
|
|||
arm720t_write_cp15(target, 0xee060f10, arm720t->far_reg);
|
||||
}
|
||||
|
||||
static int arm720t_verify_pointer(struct command_invocation *cmd,
|
||||
struct arm720t_common *arm720t)
|
||||
{
|
||||
if (arm720t->common_magic != ARM720T_COMMON_MAGIC) {
|
||||
command_print(cmd, "target is not an ARM720");
|
||||
return ERROR_TARGET_INVALID;
|
||||
}
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
static int arm720t_arch_state(struct target *target)
|
||||
{
|
||||
struct arm720t_common *arm720t = target_to_arm720(target);
|
||||
|
@ -441,55 +431,6 @@ static int arm720t_target_create(struct target *target, Jim_Interp *interp)
|
|||
return arm720t_init_arch_info(target, arm720t, target->tap);
|
||||
}
|
||||
|
||||
COMMAND_HANDLER(arm720t_handle_cp15_command)
|
||||
{
|
||||
int retval;
|
||||
struct target *target = get_current_target(CMD_CTX);
|
||||
struct arm720t_common *arm720t = target_to_arm720(target);
|
||||
|
||||
retval = arm720t_verify_pointer(CMD, arm720t);
|
||||
if (retval != ERROR_OK)
|
||||
return retval;
|
||||
|
||||
if (target->state != TARGET_HALTED) {
|
||||
command_print(CMD, "target must be stopped for \"%s\" command", CMD_NAME);
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
/* one or more argument, access a single register (write if second argument is given */
|
||||
if (CMD_ARGC >= 1) {
|
||||
uint32_t opcode;
|
||||
COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], opcode);
|
||||
|
||||
if (CMD_ARGC == 1) {
|
||||
uint32_t value;
|
||||
retval = arm720t_read_cp15(target, opcode, &value);
|
||||
if (retval != ERROR_OK) {
|
||||
command_print(CMD, "couldn't access cp15 with opcode 0x%8.8" PRIx32 "", opcode);
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
retval = jtag_execute_queue();
|
||||
if (retval != ERROR_OK)
|
||||
return retval;
|
||||
|
||||
command_print(CMD, "0x%8.8" PRIx32 ": 0x%8.8" PRIx32 "", opcode, value);
|
||||
} else if (CMD_ARGC == 2) {
|
||||
uint32_t value;
|
||||
COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], value);
|
||||
|
||||
retval = arm720t_write_cp15(target, opcode, value);
|
||||
if (retval != ERROR_OK) {
|
||||
command_print(CMD, "couldn't access cp15 with opcode 0x%8.8" PRIx32 "", opcode);
|
||||
return ERROR_OK;
|
||||
}
|
||||
command_print(CMD, "0x%8.8" PRIx32 ": 0x%8.8" PRIx32 "", opcode, value);
|
||||
}
|
||||
}
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
static int arm720t_mrc(struct target *target, int cpnum,
|
||||
uint32_t op1, uint32_t op2,
|
||||
uint32_t CRn, uint32_t CRm,
|
||||
|
@ -523,30 +464,10 @@ static int arm720t_mcr(struct target *target, int cpnum,
|
|||
value);
|
||||
}
|
||||
|
||||
static const struct command_registration arm720t_exec_command_handlers[] = {
|
||||
{
|
||||
.name = "cp15",
|
||||
.handler = arm720t_handle_cp15_command,
|
||||
.mode = COMMAND_EXEC,
|
||||
/* prefer using less error-prone "arm mcr" or "arm mrc" */
|
||||
.help = "display/modify cp15 register using ARM opcode"
|
||||
" (DEPRECATED)",
|
||||
.usage = "instruction [value]",
|
||||
},
|
||||
COMMAND_REGISTRATION_DONE
|
||||
};
|
||||
|
||||
static const struct command_registration arm720t_command_handlers[] = {
|
||||
{
|
||||
.chain = arm7_9_command_handlers,
|
||||
},
|
||||
{
|
||||
.name = "arm720t",
|
||||
.mode = COMMAND_ANY,
|
||||
.help = "arm720t command group",
|
||||
.usage = "",
|
||||
.chain = arm720t_exec_command_handlers,
|
||||
},
|
||||
COMMAND_REGISTRATION_DONE
|
||||
};
|
||||
|
||||
|
|
|
@ -245,8 +245,8 @@ static int arm920t_read_cp15_interpreted(struct target *target,
|
|||
uint32_t cp15_opcode, uint32_t address, uint32_t *value)
|
||||
{
|
||||
struct arm *arm = target_to_arm(target);
|
||||
uint32_t *regs_p[1];
|
||||
uint32_t regs[2];
|
||||
uint32_t *regs_p[16];
|
||||
uint32_t regs[16];
|
||||
uint32_t cp15c15 = 0x0;
|
||||
struct reg *r = arm->core_cache->reg_list;
|
||||
|
||||
|
@ -295,7 +295,7 @@ int arm920t_write_cp15_interpreted(struct target *target,
|
|||
{
|
||||
uint32_t cp15c15 = 0x0;
|
||||
struct arm *arm = target_to_arm(target);
|
||||
uint32_t regs[2];
|
||||
uint32_t regs[16];
|
||||
struct reg *r = arm->core_cache->reg_list;
|
||||
|
||||
/* load value, address into R0, R1 */
|
||||
|
@ -1511,80 +1511,6 @@ COMMAND_HANDLER(arm920t_handle_cp15_command)
|
|||
return ERROR_OK;
|
||||
}
|
||||
|
||||
COMMAND_HANDLER(arm920t_handle_cp15i_command)
|
||||
{
|
||||
int retval;
|
||||
struct target *target = get_current_target(CMD_CTX);
|
||||
struct arm920t_common *arm920t = target_to_arm920(target);
|
||||
|
||||
retval = arm920t_verify_pointer(CMD, arm920t);
|
||||
if (retval != ERROR_OK)
|
||||
return retval;
|
||||
|
||||
|
||||
if (target->state != TARGET_HALTED) {
|
||||
command_print(CMD, "target must be stopped for "
|
||||
"\"%s\" command", CMD_NAME);
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
/* one argument, read a register.
|
||||
* two arguments, write it.
|
||||
*/
|
||||
if (CMD_ARGC >= 1) {
|
||||
uint32_t opcode;
|
||||
COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], opcode);
|
||||
|
||||
if (CMD_ARGC == 1) {
|
||||
uint32_t value;
|
||||
retval = arm920t_read_cp15_interpreted(target,
|
||||
opcode, 0x0, &value);
|
||||
if (retval != ERROR_OK) {
|
||||
command_print(CMD,
|
||||
"couldn't execute %8.8" PRIx32,
|
||||
opcode);
|
||||
/* REVISIT why lie? "return retval"? */
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
command_print(CMD, "%8.8" PRIx32 ": %8.8" PRIx32,
|
||||
opcode, value);
|
||||
} else if (CMD_ARGC == 2) {
|
||||
uint32_t value;
|
||||
COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], value);
|
||||
retval = arm920t_write_cp15_interpreted(target,
|
||||
opcode, value, 0);
|
||||
if (retval != ERROR_OK) {
|
||||
command_print(CMD,
|
||||
"couldn't execute %8.8" PRIx32,
|
||||
opcode);
|
||||
/* REVISIT why lie? "return retval"? */
|
||||
return ERROR_OK;
|
||||
}
|
||||
command_print(CMD, "%8.8" PRIx32 ": %8.8" PRIx32,
|
||||
opcode, value);
|
||||
} else if (CMD_ARGC == 3) {
|
||||
uint32_t value;
|
||||
COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], value);
|
||||
uint32_t address;
|
||||
COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], address);
|
||||
retval = arm920t_write_cp15_interpreted(target,
|
||||
opcode, value, address);
|
||||
if (retval != ERROR_OK) {
|
||||
command_print(CMD,
|
||||
"couldn't execute %8.8" PRIx32, opcode);
|
||||
/* REVISIT why lie? "return retval"? */
|
||||
return ERROR_OK;
|
||||
}
|
||||
command_print(CMD, "%8.8" PRIx32 ": %8.8" PRIx32
|
||||
" %8.8" PRIx32, opcode, value, address);
|
||||
}
|
||||
} else
|
||||
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
COMMAND_HANDLER(arm920t_handle_cache_info_command)
|
||||
{
|
||||
int retval;
|
||||
|
@ -1640,15 +1566,6 @@ static const struct command_registration arm920t_exec_command_handlers[] = {
|
|||
.help = "display/modify cp15 register",
|
||||
.usage = "regnum [value]",
|
||||
},
|
||||
{
|
||||
.name = "cp15i",
|
||||
.handler = arm920t_handle_cp15i_command,
|
||||
.mode = COMMAND_EXEC,
|
||||
/* prefer using less error-prone "arm mcr" or "arm mrc" */
|
||||
.help = "display/modify cp15 register using ARM opcode"
|
||||
" (DEPRECATED)",
|
||||
.usage = "instruction [value [address]]",
|
||||
},
|
||||
{
|
||||
.name = "cache_info",
|
||||
.handler = arm920t_handle_cache_info_command,
|
||||
|
|
|
@ -123,6 +123,22 @@ static int post_result(struct target *target)
|
|||
uint64_t pc = buf_get_u64(arm->core_cache->reg_list[32].value, 0, 64);
|
||||
buf_set_u64(arm->pc->value, 0, 64, pc + 4);
|
||||
arm->pc->dirty = true;
|
||||
} else if (arm->core_state == ARM_STATE_ARM) {
|
||||
/* return value in R0 */
|
||||
buf_set_u32(arm->core_cache->reg_list[0].value, 0, 32, target->semihosting->result);
|
||||
arm->core_cache->reg_list[0].dirty = true;
|
||||
|
||||
uint32_t pc = buf_get_u32(arm->core_cache->reg_list[32].value, 0, 32);
|
||||
buf_set_u32(arm->pc->value, 0, 32, pc + 4);
|
||||
arm->pc->dirty = true;
|
||||
} else if (arm->core_state == ARM_STATE_THUMB) {
|
||||
/* return value in R0 */
|
||||
buf_set_u32(arm->core_cache->reg_list[0].value, 0, 32, target->semihosting->result);
|
||||
arm->core_cache->reg_list[0].dirty = true;
|
||||
|
||||
uint32_t pc = buf_get_u32(arm->core_cache->reg_list[32].value, 0, 32);
|
||||
buf_set_u32(arm->pc->value, 0, 32, pc + 2);
|
||||
arm->pc->dirty = true;
|
||||
}
|
||||
} else {
|
||||
/* resume execution, this will be pc+2 to skip over the
|
||||
|
@ -275,6 +291,16 @@ int arm_semihosting(struct target *target, int *retval)
|
|||
if (target->debug_reason != DBG_REASON_BREAKPOINT)
|
||||
return 0;
|
||||
|
||||
/* According to ARM Semihosting for AArch32 and AArch64:
|
||||
* The HLT encodings are new in version 2.0 of the semihosting specification.
|
||||
* Where possible, have semihosting callers continue to use the previously
|
||||
* existing trap instructions to ensure compatibility with legacy semihosting
|
||||
* implementations.
|
||||
* These trap instructions are HLT for A64, SVC on A+R profile A32 or T32,
|
||||
* and BKPT on M profile.
|
||||
* However, it is necessary to change from SVC to HLT instructions to support
|
||||
* AArch32 semihosting properly in a mixed AArch32/AArch64 system. */
|
||||
|
||||
if (arm->core_state == ARM_STATE_AARCH64) {
|
||||
uint32_t insn = 0;
|
||||
r = arm->pc;
|
||||
|
@ -284,9 +310,38 @@ int arm_semihosting(struct target *target, int *retval)
|
|||
if (*retval != ERROR_OK)
|
||||
return 1;
|
||||
|
||||
/* bkpt 0xAB */
|
||||
/* HLT 0xF000 */
|
||||
if (insn != 0xD45E0000)
|
||||
return 0;
|
||||
} else if (arm->core_state == ARM_STATE_ARM) {
|
||||
r = arm->pc;
|
||||
pc = buf_get_u32(arm->pc->value, 0, 32);
|
||||
|
||||
/* A32 instruction => check for HLT 0xF000 (0xE10F0070) */
|
||||
uint32_t insn = 0;
|
||||
|
||||
*retval = target_read_u32(target, pc, &insn);
|
||||
|
||||
if (*retval != ERROR_OK)
|
||||
return 1;
|
||||
|
||||
/* HLT 0xF000*/
|
||||
if (insn != 0xE10F0070)
|
||||
return 0;
|
||||
} else if (arm->core_state == ARM_STATE_THUMB) {
|
||||
r = arm->pc;
|
||||
pc = buf_get_u32(arm->pc->value, 0, 32);
|
||||
|
||||
/* T32 instruction => check for HLT 0x3C (0xBABC) */
|
||||
uint16_t insn = 0;
|
||||
*retval = target_read_u16(target, pc, &insn);
|
||||
|
||||
if (*retval != ERROR_OK)
|
||||
return 1;
|
||||
|
||||
/* HLT 0x3C*/
|
||||
if (insn != 0xBABC)
|
||||
return 0;
|
||||
} else
|
||||
return 1;
|
||||
} else {
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,21 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
#ifndef OPENOCD_TARGET_ARM_TPIU_SWO_H
|
||||
#define OPENOCD_TARGET_ARM_TPIU_SWO_H
|
||||
|
||||
/* Values should match TPIU_SPPR_PROTOCOL_xxx */
|
||||
enum tpiu_pin_protocol {
|
||||
TPIU_PIN_PROTOCOL_SYNC = 0, /**< synchronous trace output */
|
||||
TPIU_PIN_PROTOCOL_ASYNC_MANCHESTER = 1, /**< asynchronous output with Manchester coding */
|
||||
TPIU_PIN_PROTOCOL_ASYNC_UART = 2, /**< asynchronous output with NRZ coding */
|
||||
};
|
||||
|
||||
/* START_DEPRECATED_TPIU */
|
||||
/* DEPRECATED: emulation of old command 'tpiu config' */
|
||||
extern const struct command_registration arm_tpiu_deprecated_command_handlers[];
|
||||
/* END_DEPRECATED_TPIU */
|
||||
|
||||
int arm_tpiu_swo_register_commands(struct command_context *cmd_ctx);
|
||||
int arm_tpiu_swo_cleanup_all(void);
|
||||
|
||||
#endif /* OPENOCD_TARGET_ARM_TPIU_SWO_H */
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue