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:
Tim Newsome 2021-04-13 11:22:43 -07:00
commit 7420382a4d
153 changed files with 7029 additions and 5306 deletions

341
COPYING
View File

@ -1,339 +1,16 @@
GNU GENERAL PUBLIC LICENSE OpenOCD is provided under:
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc., SPDX-License-Identifier: GPL-2.0-or-later
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 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 LICENSES/preferred/GPL-2.0
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 In addition, other licenses may also apply. Please see:
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 LICENSES/license-rules.txt
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 for more details.
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 All contributions to OpenOCD are subject to this COPYING file.
(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.

218
LICENSES/license-rules.txt Normal file
View 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/>`.

View File

@ -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.

View File

@ -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.

View File

@ -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.

412
LICENSES/preferred/GFDL-1.2 Normal file
View File

@ -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.

355
LICENSES/preferred/GPL-2.0 Normal file
View File

@ -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.

View File

@ -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 .

View File

@ -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>.

View File

@ -44,7 +44,6 @@ if INTERNAL_JIMTCL
AM_CPPFLAGS += -I$(top_srcdir)/jimtcl \ AM_CPPFLAGS += -I$(top_srcdir)/jimtcl \
-I$(top_builddir)/jimtcl -I$(top_builddir)/jimtcl
endif endif
EXTRA_DIST_NEWS != ls $(srcdir)/NEWS-*
EXTRA_DIST += \ EXTRA_DIST += \
BUGS \ BUGS \
HACKING \ HACKING \
@ -53,6 +52,14 @@ EXTRA_DIST += \
README.macOS \ README.macOS \
$(EXTRA_DIST_NEWS) \ $(EXTRA_DIST_NEWS) \
Doxyfile.in \ 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/logger.pl \
tools/rlink_make_speed_table \ tools/rlink_make_speed_table \
tools/st7_dtc_as \ tools/st7_dtc_as \
@ -118,6 +125,8 @@ uninstall-hook:
distclean-local: distclean-local:
rm -rf Doxyfile doxygen rm -rf Doxyfile doxygen
rm -f $(srcdir)/jimtcl/configure.gnu 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 # 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 # Travis, because it automatically makes temporary commits when merging. So

205
NEWS
View File

@ -2,232 +2,29 @@ This file includes highlights of the changes made in the OpenOCD
source archive release. source archive release.
JTAG Layer: 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: Boundary Scan:
Target Layer: 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: 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: 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: 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: RTOS:
* Chromium-EC rtos support
* hwthread pseudo rtos support
* NuttX rtos support
* RIOT rtos support
Documentation: Documentation:
* Improve STM32 flash driver
* Various typo fix and improvements
Build and Release: 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 This release also contains a number of other important functional and
cosmetic bugfixes. For more details about what has changed since the cosmetic bugfixes. For more details about what has changed since the
last release, see the git repository history: 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 For older NEWS, see the NEWS files associated with each release

238
NEWS-0.11.0 Normal file
View File

@ -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
View File

@ -220,12 +220,11 @@ You'll also need:
Additionally, for building from git: Additionally, for building from git:
- autoconf >= 2.64 - autoconf >= 2.69
- automake >= 1.14 - automake >= 1.14
- texinfo >= 5.0 - texinfo >= 5.0
USB-based adapters depend on libusb-1.0 and some older drivers require USB-based adapters depend on libusb-1.0. A compatible implementation, such as
libusb-0.1 or libusb-compat-0.1. A compatible implementation, such as
FreeBSD's, additionally needs the corresponding .pc files. FreeBSD's, additionally needs the corresponding .pc files.
USB-Blaster, ASIX Presto and OpenJTAG interface adapter USB-Blaster, ASIX Presto and OpenJTAG interface adapter

View File

@ -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 interface. To do that one needs to activate an advanced option in the
Zadig installer. 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 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 require another driver, a solution for Windows Vista and above is to
activate the IgnoreHWSerNum registry setting for the USB device. activate the IgnoreHWSerNum registry setting for the USB device.

View File

@ -27,14 +27,14 @@ With Homebrew you can either run:
brew install [--HEAD] openocd (where optional --HEAD asks brew to brew install [--HEAD] openocd (where optional --HEAD asks brew to
install the current git version) install the current git version)
or 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 (to install the needed dependencies and then proceed with the
manual building procedure) manual building procedure)
For building with MacPorts you need to run: For building with MacPorts you need to run:
sudo port install libtool automake autoconf pkgconfig \ 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 You should also specify LDFLAGS and CPPFLAGS to allow configure to use
MacPorts' libraries, so run configure like this: MacPorts' libraries, so run configure like this:

View File

@ -1,5 +1,5 @@
AC_PREREQ(2.64) AC_PREREQ([2.69])
AC_INIT([openocd], [0.11.0-rc2+dev], AC_INIT([openocd], [0.11.0+dev],
[OpenOCD Mailing List <openocd-devel@lists.sourceforge.net>]) [OpenOCD Mailing List <openocd-devel@lists.sourceforge.net>])
AC_CONFIG_SRCDIR([src/openocd.c]) AC_CONFIG_SRCDIR([src/openocd.c])
AC_CONFIG_AUX_DIR([.]) AC_CONFIG_AUX_DIR([.])
@ -121,12 +121,10 @@ m4_define([USB1_ADAPTERS],
[[cmsis_dap_v2], [CMSIS-DAP v2 Compliant Debugger], [CMSIS_DAP_USB]], [[cmsis_dap_v2], [CMSIS-DAP v2 Compliant Debugger], [CMSIS_DAP_USB]],
[[osbdm], [OSBDM (JTAG only) Programmer], [OSBDM]], [[osbdm], [OSBDM (JTAG only) Programmer], [OSBDM]],
[[opendous], [eStick/opendous JTAG Programmer], [OPENDOUS]], [[opendous], [eStick/opendous JTAG Programmer], [OPENDOUS]],
[[aice], [Andes JTAG Programmer], [AICE]]]) [[armjtagew], [Olimex ARM-JTAG-EW Programmer], [ARMJTAGEW]],
m4_define([USB0_ADAPTERS],
[[[usbprog], [USBProg JTAG Programmer], [USBPROG]],
[[rlink], [Raisonance RLink JTAG Programmer], [RLINK]], [[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], m4_define([HIDAPI_ADAPTERS],
[[[cmsis_dap], [CMSIS-DAP Compliant Debugger], [CMSIS_DAP_HID]], [[[cmsis_dap], [CMSIS-DAP Compliant Debugger], [CMSIS_DAP_HID]],
@ -247,7 +245,6 @@ m4_define([AC_ARG_ADAPTERS], [
AC_ARG_ADAPTERS([ AC_ARG_ADAPTERS([
USB1_ADAPTERS, USB1_ADAPTERS,
USB0_ADAPTERS,
HIDAPI_ADAPTERS, HIDAPI_ADAPTERS,
HIDAPI_USB1_ADAPTERS, HIDAPI_USB1_ADAPTERS,
LIBFTDI_ADAPTERS, LIBFTDI_ADAPTERS,
@ -282,18 +279,6 @@ AC_ARG_ENABLE([amtjtagaccel],
AS_HELP_STRING([--enable-amtjtagaccel], [Enable building the Amontec JTAG-Accelerator driver]), AS_HELP_STRING([--enable-amtjtagaccel], [Enable building the Amontec JTAG-Accelerator driver]),
[build_amtjtagaccel=$enableval], [build_amtjtagaccel=no]) [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}"], AS_CASE(["${host_cpu}"],
[arm*|aarch64], [ [arm*|aarch64], [
AC_ARG_ENABLE([bcm2835gpio], 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]), AS_HELP_STRING([--enable-gw16012], [Enable building support for the Gateworks GW16012 JTAG Programmer]),
[build_gw16012=$enableval], [build_gw16012=no]) [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], AC_ARG_ENABLE([buspirate],
AS_HELP_STRING([--enable-buspirate], [Enable building support for the Buspirate]), AS_HELP_STRING([--enable-buspirate], [Enable building support for the Buspirate]),
[build_buspirate=$enableval], [build_buspirate=no]) [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], AC_ARG_ENABLE([internal-jimtcl],
AS_HELP_STRING([--disable-internal-jimtcl], [Disable building internal jimtcl]), AS_HELP_STRING([--disable-internal-jimtcl], [Disable building internal jimtcl]),
[use_internal_jimtcl=$enableval], [use_internal_jimtcl=yes]) [use_internal_jimtcl=$enableval], [use_internal_jimtcl=yes])
@ -380,43 +356,10 @@ AC_ARG_ENABLE([internal-libjaylink],
[Disable building internal libjaylink]), [Disable building internal libjaylink]),
[use_internal_libjaylink=$enableval], [use_internal_libjaylink=yes]) [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], AC_ARG_ENABLE([remote-bitbang],
AS_HELP_STRING([--enable-remote-bitbang], [Enable building support for the Remote Bitbang jtag driver]), AS_HELP_STRING([--enable-remote-bitbang], [Enable building support for the Remote Bitbang jtag driver]),
[build_remote_bitbang=$enableval], [build_remote_bitbang=yes]) [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}"], AS_CASE(["${host_cpu}"],
[i?86|x86*], [], [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.]) 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"], [ AS_IF([test "x$build_at91rm9200" = "xyes"], [
build_bitbang=yes build_bitbang=yes
AC_DEFINE([BUILD_AT91RM9200], [1], [1 if you want at91rm9200.]) 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.]) 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"], [ AS_IF([test "x$build_buspirate" = "xyes"], [
AC_DEFINE([BUILD_BUSPIRATE], [1], [1 if you want the Buspirate JTAG driver.]) 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]) 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], AC_ARG_WITH([capstone],
AS_HELP_STRING([--with-capstone], [Use Capstone disassembly library (default=auto)]) 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_define([PROCESS_ADAPTERS], [
m4_foreach([adapter], [$1], [ m4_foreach([adapter], [$1], [
AS_IF([test "x$build_zy1000" = "xyes"], [
ADAPTER_VAR([adapter])=no
])
AS_IF([test $2], [ AS_IF([test $2], [
AS_IF([test "x$ADAPTER_VAR([adapter])" != "xno"], [ AS_IF([test "x$ADAPTER_VAR([adapter])" != "xno"], [
AC_DEFINE([BUILD_]ADAPTER_SYM([adapter]), [1], [1 if you want the ]ADAPTER_DESC([adapter]).) 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([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_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([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]) 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([DUMMY], [test "x$build_dummy" = "xyes"])
AM_CONDITIONAL([GIVEIO], [test "x$parport_use_giveio" = "xyes"]) AM_CONDITIONAL([GIVEIO], [test "x$parport_use_giveio" = "xyes"])
AM_CONDITIONAL([EP93XX], [test "x$build_ep93xx" = "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([AT91RM9200], [test "x$build_at91rm9200" = "xyes"])
AM_CONDITIONAL([BCM2835GPIO], [test "x$build_bcm2835gpio" = "xyes"]) AM_CONDITIONAL([BCM2835GPIO], [test "x$build_bcm2835gpio" = "xyes"])
AM_CONDITIONAL([IMX_GPIO], [test "x$build_imx_gpio" = "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([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([AMTJTAGACCEL], [test "x$build_amtjtagaccel" = "xyes"])
AM_CONDITIONAL([GW16012], [test "x$build_gw16012" = "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([REMOTE_BITBANG], [test "x$build_remote_bitbang" = "xyes"])
AM_CONDITIONAL([BUSPIRATE], [test "x$build_buspirate" = "xyes"]) AM_CONDITIONAL([BUSPIRATE], [test "x$build_buspirate" = "xyes"])
AM_CONDITIONAL([SYSFSGPIO], [test "x$build_sysfsgpio" = "xyes"]) AM_CONDITIONAL([SYSFSGPIO], [test "x$build_sysfsgpio" = "xyes"])
AM_CONDITIONAL([XLNX_PCIE_XVC], [test "x$build_xlnx_pcie_xvc" = "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([USE_LIBUSB1], [test "x$use_libusb1" = "xyes"])
AM_CONDITIONAL([IS_CYGWIN], [test "x$is_cygwin" = "xyes"]) AM_CONDITIONAL([IS_CYGWIN], [test "x$is_cygwin" = "xyes"])
AM_CONDITIONAL([IS_MINGW], [test "x$is_mingw" = "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([RSHIM], [test "x$build_rshim" = "xyes"])
AM_CONDITIONAL([HAVE_CAPSTONE], [test "x$enable_capstone" != "xno"]) 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_JIMTCL], [test "x$use_internal_jimtcl" = "xyes"])
AM_CONDITIONAL([INTERNAL_LIBJAYLINK], [test "x$use_internal_libjaylink" = "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([GCC_WARNINGS], [$GCC_WARNINGS])
]) ])
AC_SUBST(EXTRA_DIST_NEWS, ["$(echo $srcdir/NEWS-*)"])
AC_CONFIG_FILES([ AC_CONFIG_FILES([
Makefile Makefile
src/gnulib/Makefile src/gnulib/Makefile
@ -863,7 +776,7 @@ echo
echo echo
echo OpenOCD configuration summary echo OpenOCD configuration summary
echo -------------------------------------------------- echo --------------------------------------------------
m4_foreach([adapter], [USB1_ADAPTERS, USB0_ADAPTERS, m4_foreach([adapter], [USB1_ADAPTERS,
HIDAPI_ADAPTERS, HIDAPI_USB1_ADAPTERS, LIBFTDI_ADAPTERS, HIDAPI_ADAPTERS, HIDAPI_USB1_ADAPTERS, LIBFTDI_ADAPTERS,
LIBFTDI_USB1_ADAPTERS, LIBFTDI_USB1_ADAPTERS,
LIBGPIOD_ADAPTERS, LIBGPIOD_ADAPTERS,
@ -882,26 +795,3 @@ m4_foreach([adapter], [USB1_ADAPTERS, USB0_ADAPTERS,
]) ])
]) ])
echo 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
])

View File

@ -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}=="8a98", MODE="660", GROUP="plugdev", TAG+="uaccess"
ATTRS{idVendor}=="0403", ATTRS{idProduct}=="8a99", 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 # XDS100v2
ATTRS{idVendor}=="0403", ATTRS{idProduct}=="a6d0", MODE="660", GROUP="plugdev", TAG+="uaccess" 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) # Xverve Signalyzer Tool (DT-USB-ST), Signalyzer LITE (DT-USB-SLITE)
ATTRS{idVendor}=="0403", ATTRS{idProduct}=="bca0", MODE="660", GROUP="plugdev", TAG+="uaccess" 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 # Cypress KitProg in CMSIS-DAP mode
ATTRS{idVendor}=="04b4", ATTRS{idProduct}=="f138", MODE="660", GROUP="plugdev", TAG+="uaccess" 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 # Hilscher NXHX Boards
ATTRS{idVendor}=="0640", ATTRS{idProduct}=="0028", MODE="660", GROUP="plugdev", TAG+="uaccess" 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 # Hitex STM32-PerformanceStick
ATTRS{idVendor}=="0640", ATTRS{idProduct}=="002d", MODE="660", GROUP="plugdev", TAG+="uaccess" 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 # Altera USB Blaster
ATTRS{idVendor}=="09fb", ATTRS{idProduct}=="6001", MODE="660", GROUP="plugdev", TAG+="uaccess" 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 # Amontec JTAGkey-HiSpeed
ATTRS{idVendor}=="0fbb", ATTRS{idProduct}=="1000", MODE="660", GROUP="plugdev", TAG+="uaccess" 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 # Olimex ARM-USB-OCD-H
ATTRS{idVendor}=="15ba", ATTRS{idProduct}=="002b", MODE="660", GROUP="plugdev", TAG+="uaccess" 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 # USBprog with OpenOCD firmware
ATTRS{idVendor}=="1781", ATTRS{idProduct}=="0c63", MODE="660", GROUP="plugdev", TAG+="uaccess" 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 # TI Tiva-based ICDI and XDS110 probes in DFU mode
ATTRS{idVendor}=="1cbe", ATTRS{idProduct}=="00ff", MODE="660", GROUP="plugdev", TAG+="uaccess" 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. # Ambiq Micro EVK and Debug boards.
ATTRS{idVendor}=="2aec", ATTRS{idProduct}=="6010", MODE="660", GROUP="plugdev", TAG+="uaccess" ATTRS{idVendor}=="2aec", ATTRS{idProduct}=="6010", MODE="660", GROUP="plugdev", TAG+="uaccess"
ATTRS{idVendor}=="2aec", ATTRS{idProduct}=="6011", MODE="660", GROUP="plugdev", TAG+="uaccess" ATTRS{idVendor}=="2aec", ATTRS{idProduct}=="6011", MODE="660", GROUP="plugdev", TAG+="uaccess"

View File

@ -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 /* Copied from https://github.com/gcc-mirror/gcc/blob/master/libiberty/crc32.c
* and then tweaked a little. */ * and then tweaked a little. */

View File

@ -1,6 +1,5 @@
@c -*-texinfo-*- @c -*-texinfo-*-
@node License @c The GNU Free Documentation License.
@appendix The GNU Free Documentation License.
@center Version 1.2, November 2002 @center Version 1.2, November 2002
@c This file is intended to be included within another document, @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 of the GNU Free Documentation License from time to time. Such new
versions will be similar in spirit to the present version, but may versions will be similar in spirit to the present version, but may
differ in detail to address new problems or concerns. See 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. Each version of the License is given a distinguishing version number.
If the Document specifies that a particular numbered version of this 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. as a draft) by the Free Software Foundation.
@end enumerate @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 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 the License in the document and put the following copyright and

View File

@ -36,7 +36,6 @@ asynchronous transactions.
- declared in @c src/jtag/minidriver.h - declared in @c src/jtag/minidriver.h
- used @a only by the core and minidriver implementations: - used @a only by the core and minidriver implementations:
- @c jtag_driver.c (in-tree OpenOCD drivers) - @c jtag_driver.c (in-tree OpenOCD drivers)
- @c zy1000/build/include/jtag_minidriver.h (ZY1000 minidriver)
- future implementations (on other embedded hosts) - future implementations (on other embedded hosts)
- interface device drivers do @b not need this API. - interface device drivers do @b not need this API.

View File

@ -114,9 +114,9 @@ pthreads require modest and predictable stack usage.
- static inline functions should be preferred over macros: - static inline functions should be preferred over macros:
@code @code
/** do NOT define macro-like functions like this... */ /* do NOT define macro-like functions like this... */
#define CUBE(x) ((x) * (x) * (x)) #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; } static inline int cube(int x) { return x * x * x; }
@endcode @endcode
- Functions should be declared static unless required by other modules - Functions should be declared static unless required by other modules
@ -135,13 +135,13 @@ should write statements like the following:
@code @code
// separate statements should be preferred // separate statements should be preferred
result = foo(); result = foo();
if (ERROR_OK != result) if (result != ERROR_OK)
... ...
@endcode @endcode
More directly, do @b not combine these kinds of statements: More directly, do @b not combine these kinds of statements:
@code @code
// Combined statements should be avoided // Combined statements should be avoided
if (ERROR_OK != (result = foo())) if ((result = foo()) != ERROR_OK)
return result; return result;
@endcode @endcode

View File

@ -298,7 +298,6 @@ The OpenOCD Bug Tracker is hosted on SourceForge:
@cindex dongles @cindex dongles
@cindex FTDI @cindex FTDI
@cindex wiggler @cindex wiggler
@cindex zy1000
@cindex printer port @cindex printer port
@cindex USB Adapter @cindex USB Adapter
@cindex RTCK @cindex RTCK
@ -307,12 +306,7 @@ Defined: @b{dongle}: A small device that plugs into a computer and serves as
an adapter .... [snip] an adapter .... [snip]
In the OpenOCD case, this generally refers to @b{a small adapter} that In the OpenOCD case, this generally refers to @b{a small adapter} that
attaches to your computer via USB or the parallel port. One attaches to your computer via USB or the parallel port.
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.
@section Choosing a Dongle @section Choosing a Dongle
@ -334,26 +328,6 @@ Ethernet port needed?
RTCK support (also known as ``adaptive clocking'')? RTCK support (also known as ``adaptive clocking'')?
@end enumerate @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 @section USB FT2232 Based
There are many USB JTAG dongles on the market, many of them 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 When using "pipe", also use log_output to redirect the log
output to a file so as not to flood the stdin/out pipes. 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. Any other string is interpreted as named pipe to listen to.
Output pipe is the same name as input pipe, but with 'o' appended, Output pipe is the same name as input pipe, but with 'o' appended,
e.g. /var/gdb, /var/gdbo. 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. Pairs of vendor IDs and product IDs of the device.
@end deffn @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 @deffn {Command} {hla_command} command
Execute a custom adapter-specific command. The @var{command} string is Execute a custom adapter-specific command. The @var{command} string is
passed as is to the underlying adapter layout handler. 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 @emph{Note:} Either these same adapters and their older versions are
also supported by @ref{hla_interface, the hla interface driver}. 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 @deffn {Config Command} {st-link serial} serial
Specifies the serial number of the adapter. Specifies the serial number of the adapter.
@end deffn @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
@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} @deffn {Interface Driver} {bcm2835gpio}
This SoC is present in Raspberry Pi which is a cheap single-board computer This SoC is present in Raspberry Pi which is a cheap single-board computer
exposing some GPIOs on its expansion header. 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{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, @item @code{ls1_sap} -- this is the SAP on NXP LS102x CPUs,
allowing access to physical memory addresses independently of CPU cores. 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_m4k} -- a MIPS core.
@item @code{mips_mips64} -- a MIPS64 core. @item @code{mips_mips64} -- a MIPS64 core.
@item @code{nds32_v2} -- this is an Andes NDS32 v2 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 @* After target hardware trace configuration was changed
@end itemize @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 @node Flash Commands
@chapter 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 flash bank $_FLASHNAME stm32l4x 0 0 0 0 $_TARGETNAME
@end example @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 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 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 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. This will effectively write protect all sectors in flash bank 1.
@end deffn @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 @deffn Command {stm32l4x option_load} num
Forces a re-load of the option byte registers. Will cause a system reset of the device. 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}. The @var{num} parameter is a value shown by @command{flash banks}.
@ -8255,66 +8276,6 @@ with handlers for that event.
@end quotation @end quotation
@end deffn @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} @anchor{memoryaccess}
@section Memory access commands @section Memory access commands
@cindex memory access @cindex memory access
@ -8836,29 +8797,6 @@ how the event caused trouble.
@end deffn @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} @anchor{armcrosstrigger}
@section ARM Cross-Trigger Interface @section ARM Cross-Trigger Interface
@cindex CTI @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. speeds, like the 32kHz startup clock of an AT91RM9200.
@end deffn @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 @subsection ARM9 specific commands
@cindex ARM9 @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.) (Not all registers can be written.)
@end deffn @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 @deffn Command {arm920t read_cache} filename
Dump the content of ICache and DCache to a file named @file{filename}. Dump the content of ICache and DCache to a file named @file{filename}.
@end deffn @end deffn
@ -9470,61 +9379,146 @@ Selects whether interrupts will be processed when single stepping
@end deffn @end deffn
@subsection ARMv7-M specific commands @subsection ARM CoreSight TPIU and SWO specific commands
@cindex tracing @cindex tracing
@cindex SWO @cindex SWO
@cindex SWV @cindex SWV
@cindex TPIU @cindex TPIU
@cindex ITM
@cindex ETM
@deffn Command {tpiu config} (@option{disable} | ((@option{external} | @option{internal (@var{filename} | @var{:port} | -)}) @ ARM CoreSight provides several modules to generate debugging
(@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
information internally (ITM, DWT and ETM). Their output is directed 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. configuration is called SWV) or on a synchronous parallel trace port.
This command configures the TPIU module of the target and, if internal ARM CoreSight provides independent HW blocks named TPIU and SWO each with its
capture mode is selected, starts to capture trace output by using the own functionality. Embedded in Cortex-M3 and M4, ARM provides an optional HW
debugger adapter features. 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 The @command{tpiu} is used for either TPIU or SWO.
@b{trace-config} handler for trace port to be activated. 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 @itemize @minus
@item @option{disable} disable TPIU handling; @item @option{sync} -- synchronous parallel trace output mode, using @var{port_width}
@item @option{external} configure TPIU to let user capture trace data bits (default);
output externally (with an additional UART or logic analyzer hardware). @item @option{uart} -- use asynchronous SWO mode with NRZ (same as regular UART 8N1) coding;
@item @option{internal (@var{filename} | @var{:port} | -)} configure TPIU and debug adapter to @item @option{manchester} -- use asynchronous SWO mode with Manchester coding.
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.
@end itemize @end itemize
@item @option{sync @var{port_width}} use synchronous parallel trace output @item @code{-event} @var{event_name} @var{event_body} -- assigns an event handler,
mode, and set port width to @var{port_width}. a TCL string which is evaluated when the event is triggered. The events
@item @option{manchester} use asynchronous SWO mode with Manchester @code{pre-enable}, @code{post-enable}, @code{pre-disable} and @code{post-disable}
coding. are defined for TPIU/SWO.
@item @option{uart} use asynchronous SWO mode with NRZ (same as A typical use case for the event @code{pre-enable} is to enable the trace clock
regular UART 8N1) coding. of the TPIU.
@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 @item @code{-output} (@option{external}|@option{:}@var{port}|@var{filename}|@option{-}) -- specifies
data is to be output via SWO. the destination of the trace data:
@item @var{TRACECLKIN_freq} this should be specified to match target's @itemize @minus
current TRACECLKIN frequency (usually the same as HCLK). @item @option{external} -- configure TPIU/SWO to let user capture trace
@item @var{trace_freq} trace port frequency. Can be omitted in output externally, either with an additional UART or with a logic analyzer (default);
internal mode to let the adapter driver select the maximum supported @item @option{-} -- configure TPIU/SWO and debug adapter to gather trace data
rate automatically. 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 @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: Example usage:
@enumerate @enumerate
@item STM32L152 board is programmed with an application that configures @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: @item OpenOCD invocation line:
@example @example
openocd -f interface/stlink.cfg \ openocd -f interface/stlink.cfg \
-c "transport select hla_swd" \ -c "transport select hla_swd" \
-f target/stm32l1.cfg \ -f target/stm32l1.cfg \
-c "tpiu config external uart off 24000000 12000000" -c "stm32l1.tpiu configure -protocol uart" \
-c "stm32l1.tpiu configure -traceclk 24000000 -pin-freq 12000000" \
-c "stm32l1.tpiu enable"
@end example @end example
@end enumerate @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}) @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 Enable or disable trace output for ITM stimulus @var{port} (counting
@ -11932,6 +11934,8 @@ foreach who @{A B C D E@}
@} @}
@end example @end example
@node License
@appendix The GNU Free Documentation License.
@include fdl.texi @include fdl.texi
@node OpenOCD Concept Index @node OpenOCD Concept Index

View File

@ -69,6 +69,7 @@ BUILT_SOURCES += %D%/startup_tcl.inc
# Convert .tcl to c-array # Convert .tcl to c-array
%D%/startup_tcl.inc: $(STARTUP_TCL_SRCS) %D%/startup_tcl.inc: $(STARTUP_TCL_SRCS)
mkdir -p %D%
cat $^ | $(BIN2C) > $@ || { rm -f $@; false; } cat $^ | $(BIN2C) > $@ || { rm -f $@; false; }
# add generated files to make clean list # add generated files to make clean list

View File

@ -60,14 +60,14 @@ static const int lp_ooblayout[] = {
58, 59, 60, 61, 62, 63 58, 59, 60, 61, 62, 63
}; };
typedef struct { struct dmac_ll {
volatile uint32_t dma_src; volatile uint32_t dma_src;
volatile uint32_t dma_dest; volatile uint32_t dma_dest;
volatile uint32_t next_lli; volatile uint32_t next_lli;
volatile uint32_t next_ctrl; 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> /* 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_src = (do_read ? dmasrc : (dmasrc + i * 256));
dmalist[i*2].dma_dest = (do_read ? (dmadst + i * 256) : dmadst); dmalist[i*2].dma_dest = (do_read ? (dmadst + i * 256) : dmadst);
dmalist[i*2].next_lli = 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].next_ctrl = ctrl;
dmalist[(i*2) + 1].dma_src = 0x20020034;/* SLC_ECC */ dmalist[(i*2) + 1].dma_src = 0x20020034;/* SLC_ECC */
dmalist[(i*2) + 1].dma_dest = dmalist[(i*2) + 1].dma_dest =
target_mem_base + ECC_OFFS + i * 4; target_mem_base + ECC_OFFS + i * 4;
dmalist[(i*2) + 1].next_lli = 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; 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. XXX: Assumes host and target have same byte sex.
*/ */
retval = target_write_memory(target, target_mem_base, 4, retval = target_write_memory(target, target_mem_base, 4,
nll * sizeof(dmac_ll_t) / 4, nll * sizeof(struct dmac_ll) / 4,
(uint8_t *)dmalist); (uint8_t *)dmalist);
if (ERROR_OK != retval) { if (ERROR_OK != retval) {
LOG_ERROR("Could not write DMA descriptors to IRAM"); 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 */ /* Write first descriptor to DMA controller */
retval = target_write_memory(target, 0x31000100, 4, retval = target_write_memory(target, 0x31000100, 4,
sizeof(dmac_ll_t) / 4, sizeof(struct dmac_ll) / 4,
(uint8_t *)dmalist); (uint8_t *)dmalist);
if (ERROR_OK != retval) { if (ERROR_OK != retval) {
LOG_ERROR("Could not write DMA descriptor to DMAC"); 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 */ /* Write OOB descriptor to DMA controller */
retval = target_write_memory(target, 0x31000100, 4, retval = target_write_memory(target, 0x31000100, 4,
sizeof(dmac_ll_t) / 4, sizeof(struct dmac_ll) / 4,
(uint8_t *)(&dmalist[nll-1])); (uint8_t *)(&dmalist[nll-1]));
if (ERROR_OK != retval) { if (ERROR_OK != retval) {
LOG_ERROR("Could not write OOB DMA descriptor to DMAC"); 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. XXX: Assumes host and target have same byte sex.
*/ */
retval = target_write_memory(target, target_mem_base, 4, retval = target_write_memory(target, target_mem_base, 4,
nll * sizeof(dmac_ll_t) / 4, nll * sizeof(struct dmac_ll) / 4,
(uint8_t *)dmalist); (uint8_t *)dmalist);
if (ERROR_OK != retval) { if (ERROR_OK != retval) {
LOG_ERROR("Could not write DMA descriptors to IRAM"); 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 */ /* Write first descriptor to DMA controller */
retval = target_write_memory(target, 0x31000100, 4, 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) { if (ERROR_OK != retval) {
LOG_ERROR("Could not write DMA descriptor to DMAC"); LOG_ERROR("Could not write DMA descriptor to DMAC");
return retval; return retval;

View File

@ -113,7 +113,7 @@ struct samd_part {
}; };
/* See SAM D5x/E5x Family Silicon Errata and Data Sheet Clarification /* See SAM D5x/E5x Family Silicon Errata and Data Sheet Clarification
* DS80000748B */ * DS80000748K */
/* Known SAMD51 parts. */ /* Known SAMD51 parts. */
static const struct samd_part samd51_parts[] = { static const struct samd_part samd51_parts[] = {
{ 0x00, "SAMD51P20A", 1024, 256 }, { 0x00, "SAMD51P20A", 1024, 256 },
@ -134,6 +134,8 @@ static const struct samd_part same51_parts[] = {
{ 0x02, "SAME51J19A", 512, 192 }, { 0x02, "SAME51J19A", 512, 192 },
{ 0x03, "SAME51J18A", 256, 128 }, { 0x03, "SAME51J18A", 256, 128 },
{ 0x04, "SAME51J20A", 1024, 256 }, { 0x04, "SAME51J20A", 1024, 256 },
{ 0x05, "SAME51G19A", 512, 192 }, /* New in rev D */
{ 0x06, "SAME51G18A", 256, 128 }, /* New in rev D */
}; };
/* Known SAME53 parts. */ /* Known SAME53 parts. */

View File

@ -832,17 +832,13 @@ int cfi_flash_bank_cmd(struct flash_bank *bank, unsigned int argc, const char **
return ERROR_FLASH_BANK_INVALID; return ERROR_FLASH_BANK_INVALID;
} }
cfi_info = malloc(sizeof(struct cfi_flash_bank)); cfi_info = calloc(1, sizeof(struct cfi_flash_bank));
cfi_info->probed = false; if (cfi_info == NULL) {
cfi_info->erase_region_info = NULL; LOG_ERROR("No memory for flash bank info");
cfi_info->pri_ext = NULL; return ERROR_FAIL;
}
bank->driver_priv = cfi_info; 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++) { for (unsigned i = 6; i < argc; i++) {
if (strcmp(argv[i], "x16_as_x8") == 0) if (strcmp(argv[i], "x16_as_x8") == 0)
cfi_info->x16_as_x8 = true; cfi_info->x16_as_x8 = true;

File diff suppressed because it is too large Load Diff

View File

@ -56,9 +56,9 @@
#define OPTKEY1 0x08192A3B #define OPTKEY1 0x08192A3B
#define OPTKEY2 0x4C5D6E7F #define OPTKEY2 0x4C5D6E7F
#define RDP_LEVEL_0 0xAA /* FLASH_OPTR register bits */
#define RDP_LEVEL_1 0xBB #define FLASH_RDP_MASK 0xFF
#define RDP_LEVEL_2 0xCC #define FLASH_TZEN (1 << 31)
/* other registers */ /* other registers */
#define DBGMCU_IDCODE_G0 0x40015800 #define DBGMCU_IDCODE_G0 0x40015800

View File

@ -52,14 +52,6 @@
#undef SPIFLASH_READ #undef SPIFLASH_READ
#undef SPIFLASH_PAGE_PROGRAM #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 */ /* saved mode settings */
#define QSPI_MODE (stmqspi_info->saved_ccr & \ #define QSPI_MODE (stmqspi_info->saved_ccr & \
(0xF0000000U | QSPI_DCYC_MASK | QSPI_4LINE_MODE | QSPI_ALTB_MODE | QSPI_ADDR4)) (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 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 */ /* convert uint32_t into 4 uint8_t in little endian byte order */
static inline uint32_t h_to_le_32(uint32_t val) 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 */ 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) FLASH_BANK_COMMAND_HANDLER(stmqspi_flash_bank_command)
{ {
struct stmqspi_flash_bank *stmqspi_info; 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 target *target = bank->target;
struct stmqspi_flash_bank *stmqspi_info = bank->driver_priv; struct stmqspi_flash_bank *stmqspi_info = bank->driver_priv;
uint32_t io_base = stmqspi_info->io_base; uint32_t io_base = stmqspi_info->io_base;
uint32_t spi_sr;
int retval;
long long endtime; long long endtime;
endtime = timeval_ms() + timeout; endtime = timeval_ms() + timeout;
do { do {
spi_sr = READ_REG(SPI_SR); uint32_t spi_sr;
if ((spi_sr & BIT(SPI_BUSY)) == 0) { int retval = target_read_u32(target, io_base + SPI_SR, &spi_sr);
if (retval == ERROR_OK) {
/* Clear transmit finished flag */ if (retval != ERROR_OK)
retval = target_write_u32(target, io_base + SPI_FCR, BIT(SPI_TCF));
}
return retval; 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 } else
LOG_DEBUG("busy: 0x%08X", spi_sr); LOG_DEBUG("busy: 0x%08X", spi_sr);
alive_sleep(1); alive_sleep(1);
@ -264,6 +268,21 @@ static int poll_busy(struct flash_bank *bank, int timeout)
return ERROR_FLASH_OPERATION_FAILED; 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 */ /* Set to memory-mapped mode, e.g. after an error */
static int set_mm_mode(struct flash_bank *bank) static int set_mm_mode(struct flash_bank *bank)
{ {
@ -278,8 +297,7 @@ static int set_mm_mode(struct flash_bank *bank)
return retval; return retval;
/* Abort any previous operation */ /* Abort any previous operation */
retval = target_write_u32(target, io_base + SPI_CR, retval = stmqspi_abort(bank);
READ_REG(SPI_CR) | BIT(SPI_ABORT));
if (retval != ERROR_OK) if (retval != ERROR_OK)
return retval; return retval;
@ -321,8 +339,7 @@ static int read_status_reg(struct flash_bank *bank, uint16_t *status)
int count, retval; int count, retval;
/* Abort any previous operation */ /* Abort any previous operation */
retval = target_write_u32(target, io_base + SPI_CR, retval = stmqspi_abort(bank);
READ_REG(SPI_CR) | BIT(SPI_ABORT));
if (retval != ERROR_OK) if (retval != ERROR_OK)
return retval; return retval;
@ -340,7 +357,8 @@ static int read_status_reg(struct flash_bank *bank, uint16_t *status)
/* Read status */ /* Read status */
if (IS_OCTOSPI) { 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) { if (OPI_MODE) {
/* Dummy address 0, only required for 8-line mode */ /* Dummy address 0, only required for 8-line mode */
retval = target_write_u32(target, io_base + SPI_AR, 0); 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; *status = 0;
/* for debugging only */ /* 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) { for ( ; count > 0; --count) {
if ((stmqspi_info->saved_cr & (BIT(SPI_DUAL_FLASH) | BIT(SPI_FSEL_FLASH))) 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; int retval;
/* Abort any previous operation */ /* Abort any previous operation */
retval = target_write_u32(target, io_base + SPI_CR, retval = stmqspi_abort(bank);
READ_REG(SPI_CR) | BIT(SPI_ABORT));
if (retval != ERROR_OK) if (retval != ERROR_OK)
return retval; return retval;
@ -428,7 +446,8 @@ static int qspi_write_enable(struct flash_bank *bank)
/* Send write enable command */ /* Send write enable command */
if (IS_OCTOSPI) { 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) { if (OPI_MODE) {
/* Dummy address 0, only required for 8-line mode */ /* Dummy address 0, only required for 8-line mode */
retval = target_write_u32(target, io_base + SPI_AR, 0); 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 */ /* Send Mass Erase command */
if (IS_OCTOSPI) 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); stmqspi_info->dev.chip_erase_cmd);
else else
retval = target_write_u32(target, io_base + QSPI_CCR, QSPI_CCR_MASS_ERASE); 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; bank->size = stmqspi_info->dev.size_in_bytes << dual;
io_base = stmqspi_info->io_base; 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) if (retval != ERROR_OK)
return retval; return retval;
fsize = (dcr >> SPI_FSIZE_POS) & (BIT(SPI_FSIZE_LEN) - 1);
LOG_DEBUG("FSIZE = 0x%04x", fsize); LOG_DEBUG("FSIZE = 0x%04x", fsize);
if (bank->size == BIT(fsize + 1)) if (bank->size == BIT(fsize + 1))
LOG_DEBUG("FSIZE in DCR(1) matches actual capacity. Beware of silicon bug in H7, L4+, MP1."); 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 */ /* Abort any previous operation */
retval = target_write_u32(target, io_base + SPI_CR, retval = stmqspi_abort(bank);
READ_REG(SPI_CR) | BIT(SPI_ABORT));
if (retval != ERROR_OK) if (retval != ERROR_OK)
return retval; return retval;
@ -842,7 +865,7 @@ COMMAND_HANDLER(stmqspi_handle_cmd)
goto err; goto err;
if (IS_OCTOSPI) 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 & (OCTOSPI_MODE_CCR & OCTOSPI_NO_ALTB & OCTOSPI_NO_ADDR &
((num_write == 1) ? OCTOSPI_NO_DATA : ~0U)), cmd_byte); ((num_write == 1) ? OCTOSPI_NO_DATA : ~0U)), cmd_byte);
else else
@ -879,7 +902,7 @@ COMMAND_HANDLER(stmqspi_handle_cmd)
if (retval != ERROR_OK) if (retval != ERROR_OK)
goto err; goto err;
if (IS_OCTOSPI) 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 & (OCTOSPI_MODE_CCR & OCTOSPI_NO_DDTR & OCTOSPI_NO_ALTB & ~OCTOSPI_ADDR4 &
((num_write == 1) ? OCTOSPI_NO_ADDR : ~0U)) | ((num_write == 1) ? OCTOSPI_NO_ADDR : ~0U)) |
(((num_write - 2) & 0x3U) << SPI_ADSIZE_POS), cmd_byte); (((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 */ /* Send Sector Erase command */
if (IS_OCTOSPI) 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); stmqspi_info->dev.erase_cmd);
else else
retval = target_write_u32(target, io_base + QSPI_CCR, QSPI_CCR_SECTOR_ERASE); 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 target *target = bank->target;
struct stmqspi_flash_bank *stmqspi_info = bank->driver_priv; struct stmqspi_flash_bank *stmqspi_info = bank->driver_priv;
uint32_t io_base = stmqspi_info->io_base;
struct duration bench; struct duration bench;
struct reg_param reg_params[2]; struct reg_param reg_params[2];
struct armv7m_algorithm armv7m_info; struct armv7m_algorithm armv7m_info;
@ -1082,8 +1104,7 @@ static int stmqspi_blank_check(struct flash_bank *bank)
} }
/* Abort any previous operation */ /* Abort any previous operation */
retval = target_write_u32(target, io_base + SPI_CR, retval = stmqspi_abort(bank);
READ_REG(SPI_CR) | BIT(SPI_ABORT));
if (retval != ERROR_OK) if (retval != ERROR_OK)
return retval; return retval;
@ -1568,7 +1589,6 @@ static int stmqspi_read(struct flash_bank *bank, uint8_t *buffer,
{ {
struct target *target = bank->target; struct target *target = bank->target;
struct stmqspi_flash_bank *stmqspi_info = bank->driver_priv; struct stmqspi_flash_bank *stmqspi_info = bank->driver_priv;
uint32_t io_base = stmqspi_info->io_base;
int retval; int retval;
LOG_DEBUG("%s: offset=0x%08" PRIx32 " count=0x%08" PRIx32, 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 */ /* Abort any previous operation */
retval = target_write_u32(target, io_base + SPI_CR, retval = stmqspi_abort(bank);
READ_REG(SPI_CR) | BIT(SPI_ABORT));
if (retval != ERROR_OK) if (retval != ERROR_OK)
return retval; return retval;
@ -1608,7 +1627,6 @@ static int stmqspi_write(struct flash_bank *bank, const uint8_t *buffer,
{ {
struct target *target = bank->target; struct target *target = bank->target;
struct stmqspi_flash_bank *stmqspi_info = bank->driver_priv; struct stmqspi_flash_bank *stmqspi_info = bank->driver_priv;
uint32_t io_base = stmqspi_info->io_base;
unsigned int dual, sector; unsigned int dual, sector;
bool octal_dtr; bool octal_dtr;
int retval; int retval;
@ -1653,8 +1671,7 @@ static int stmqspi_write(struct flash_bank *bank, const uint8_t *buffer,
} }
/* Abort any previous operation */ /* Abort any previous operation */
retval = target_write_u32(target, io_base + SPI_CR, retval = stmqspi_abort(bank);
READ_REG(SPI_CR) | BIT(SPI_ABORT));
if (retval != ERROR_OK) if (retval != ERROR_OK)
return retval; return retval;
@ -1671,7 +1688,6 @@ static int stmqspi_verify(struct flash_bank *bank, const uint8_t *buffer,
{ {
struct target *target = bank->target; struct target *target = bank->target;
struct stmqspi_flash_bank *stmqspi_info = bank->driver_priv; struct stmqspi_flash_bank *stmqspi_info = bank->driver_priv;
uint32_t io_base = stmqspi_info->io_base;
unsigned int dual; unsigned int dual;
bool octal_dtr; bool octal_dtr;
int retval; int retval;
@ -1704,8 +1720,7 @@ static int stmqspi_verify(struct flash_bank *bank, const uint8_t *buffer,
} }
/* Abort any previous operation */ /* Abort any previous operation */
retval = target_write_u32(target, io_base + SPI_CR, retval = stmqspi_abort(bank);
READ_REG(SPI_CR) | BIT(SPI_ABORT));
if (retval != ERROR_OK) if (retval != ERROR_OK)
return retval; return retval;
@ -1757,8 +1772,8 @@ static int find_sfdp_dummy(struct flash_bank *bank, int len)
/* Read SFDP block */ /* Read SFDP block */
if (IS_OCTOSPI) if (IS_OCTOSPI)
retval = OCTOSPI_CMD(OCTOSPI_READ_MODE, OCTOSPI_CCR_READ_SFDP(len), retval = octospi_cmd(bank, OCTOSPI_READ_MODE,
SPIFLASH_READ_SFDP); OCTOSPI_CCR_READ_SFDP(len), SPIFLASH_READ_SFDP);
else else
retval = target_write_u32(target, io_base + QSPI_CCR, QSPI_CCR_READ_SFDP); retval = target_write_u32(target, io_base + QSPI_CCR, QSPI_CCR_READ_SFDP);
if (retval != ERROR_OK) if (retval != ERROR_OK)
@ -1804,8 +1819,7 @@ static int find_sfdp_dummy(struct flash_bank *bank, int len)
err: err:
/* Abort operation */ /* Abort operation */
retval = target_write_u32(target, io_base + SPI_CR, retval = stmqspi_abort(bank);
READ_REG(SPI_CR) | BIT(SPI_ABORT));
return retval; return retval;
} }
@ -1880,8 +1894,8 @@ static int read_sfdp_block(struct flash_bank *bank, uint32_t addr,
/* Read SFDP block */ /* Read SFDP block */
if (IS_OCTOSPI) if (IS_OCTOSPI)
retval = OCTOSPI_CMD(OCTOSPI_READ_MODE, OCTOSPI_CCR_READ_SFDP(len), retval = octospi_cmd(bank, OCTOSPI_READ_MODE,
SPIFLASH_READ_SFDP); OCTOSPI_CCR_READ_SFDP(len), SPIFLASH_READ_SFDP);
else else
retval = target_write_u32(target, io_base + QSPI_CCR, QSPI_CCR_READ_SFDP); retval = target_write_u32(target, io_base + QSPI_CCR, QSPI_CCR_READ_SFDP);
if (retval != ERROR_OK) 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 */ /* 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++) { for (type = (IS_OCTOSPI && OPI_MODE) ? 1 : 0; type < 2 ; type++) {
/* Abort any previous operation */ /* Abort any previous operation */
retval = target_write_u32(target, io_base + SPI_CR, retval = stmqspi_abort(bank);
READ_REG(SPI_CR) | BIT(SPI_ABORT));
if (retval != ERROR_OK) if (retval != ERROR_OK)
goto err; goto err;
@ -1986,14 +1999,16 @@ static int read_flash_id(struct flash_bank *bank, uint32_t *id1, uint32_t *id2)
switch (type) { switch (type) {
case 0: case 0:
if (IS_OCTOSPI) 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 else
retval = target_write_u32(target, io_base + QSPI_CCR, QSPI_CCR_READ_MID); retval = target_write_u32(target, io_base + QSPI_CCR, QSPI_CCR_READ_MID);
break; break;
case 1: case 1:
if (IS_OCTOSPI) 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 else
retval = target_write_u32(target, io_base + QSPI_CCR, QSPI_CCR_READ_ID); retval = target_write_u32(target, io_base + QSPI_CCR, QSPI_CCR_READ_ID);
break; break;
@ -2013,7 +2028,8 @@ static int read_flash_id(struct flash_bank *bank, uint32_t *id1, uint32_t *id2)
} }
/* for debugging only */ /* 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 */ /* Read ID from Data Register */
for (len1 = 0, len2 = 0; count > 0; --count) { for (len1 = 0, len2 = 0; count > 0; --count) {
@ -2092,8 +2108,7 @@ static int stmqspi_probe(struct flash_bank *bank)
} }
/* Abort any previous operation */ /* Abort any previous operation */
retval = target_write_u32(target, io_base + SPI_CR, retval = stmqspi_abort(bank);
READ_REG(SPI_CR) | BIT(SPI_ABORT));
if (retval != ERROR_OK) if (retval != ERROR_OK)
return retval; return retval;
@ -2112,7 +2127,12 @@ static int stmqspi_probe(struct flash_bank *bank)
if (data == magic) { if (data == magic) {
LOG_DEBUG("QSPI_ABR register present"); LOG_DEBUG("QSPI_ABR register present");
stmqspi_info->octo = false; stmqspi_info->octo = false;
} else if (READ_REG(OCTOSPI_MAGIC) == OCTO_MAGIC_ID) { } else {
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"); LOG_DEBUG("OCTOSPI_MAGIC present");
stmqspi_info->octo = true; stmqspi_info->octo = true;
} else { } else {
@ -2121,34 +2141,45 @@ static int stmqspi_probe(struct flash_bank *bank)
stmqspi_info->dev.name = "none"; stmqspi_info->dev.name = "none";
return ERROR_FAIL; return ERROR_FAIL;
} }
}
/* save current FSEL and DFM bits in QSPI/OCTOSPI_CR, current QSPI/OCTOSPI_CCR value */ /* 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) 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) { 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) 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) if (retval == ERROR_OK)
stmqspi_info->saved_ir = READ_REG(OCTOSPI_IR); retval = target_read_u32(target, io_base + OCTOSPI_IR,
if ((mtyp != 0x0) && (mtyp != 0x1)) { &stmqspi_info->saved_ir);
retval = ERROR_FAIL;
LOG_ERROR("Only regular SPI protocol supported in OCTOSPI"); if (retval != ERROR_OK) {
}
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 {
LOG_ERROR("No OCTOSPI at io_base 0x%08" PRIx32, io_base); LOG_ERROR("No OCTOSPI at io_base 0x%08" PRIx32, io_base);
stmqspi_info->probed = false; stmqspi_info->probed = false;
stmqspi_info->dev.name = "none"; stmqspi_info->dev.name = "none";
return ERROR_FAIL; 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 { } else {
if (retval == ERROR_OK) { if (retval == ERROR_OK) {
LOG_DEBUG("QSPI at 0x%08" PRIx64 ", io_base at 0x%08" PRIx32 ", QSPI_CR 0x%08" 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 */ /* Set correct size value */
bank->size = stmqspi_info->dev.size_in_bytes << dual; 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) if (retval != ERROR_OK)
goto err; goto err;
fsize = (dcr >> SPI_FSIZE_POS) & (BIT(SPI_FSIZE_LEN) - 1);
LOG_DEBUG("FSIZE = 0x%04x", fsize); LOG_DEBUG("FSIZE = 0x%04x", fsize);
if (bank->size == BIT((fsize + 1))) if (bank->size == BIT((fsize + 1)))
LOG_DEBUG("FSIZE in DCR(1) matches actual capacity. Beware of silicon bug in H7, L4+, MP1."); LOG_DEBUG("FSIZE in DCR(1) matches actual capacity. Beware of silicon bug in H7, L4+, MP1.");

View File

@ -119,14 +119,3 @@ proc stm32g4x args { eval stm32l4x $args }
proc stm32l5x args { eval stm32l4x $args } proc stm32l5x args { eval stm32l4x $args }
proc stm32wbx args { eval stm32l4x $args } proc stm32wbx args { eval stm32l4x $args }
proc stm32wlx 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
}

View File

@ -18,7 +18,6 @@ noinst_LTLIBRARIES += %D%/libhelper.la
%D%/binarybuffer.h \ %D%/binarybuffer.h \
%D%/bits.h \ %D%/bits.h \
%D%/configuration.h \ %D%/configuration.h \
%D%/ioutil.h \
%D%/list.h \ %D%/list.h \
%D%/util.h \ %D%/util.h \
%D%/types.h \ %D%/types.h \
@ -34,12 +33,6 @@ noinst_LTLIBRARIES += %D%/libhelper.la
%D%/base64.c \ %D%/base64.c \
%D%/base64.h %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) %C%_libhelper_la_CFLAGS = $(AM_CFLAGS)
if IS_MINGW if IS_MINGW
# FD_* macros are sloppy with their signs on MinGW32 platform # FD_* macros are sloppy with their signs on MinGW32 platform

View File

@ -117,6 +117,40 @@ static void command_log_capture_finish(struct log_capture_state *state)
free(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) static int command_retval_set(Jim_Interp *interp, int retval)
{ {
int *return_retval = Jim_GetAssocData(interp, "retval"); int *return_retval = Jim_GetAssocData(interp, "retval");

View File

@ -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);
}

View File

@ -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 */

View File

@ -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;
}

View File

@ -55,7 +55,6 @@ static const struct option long_options[] = {
{"search", required_argument, 0, 's'}, {"search", required_argument, 0, 's'},
{"log_output", required_argument, 0, 'l'}, {"log_output", required_argument, 0, 'l'},
{"command", required_argument, 0, 'c'}, {"command", required_argument, 0, 'c'},
{"pipe", no_argument, 0, 'p'},
{0, 0, 0, 0} {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. */ /* getopt_long stores the option index here. */
int option_index = 0; 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. */ /* Detect the end of the options. */
if (c == -1) if (c == -1)
@ -322,13 +321,6 @@ int parse_cmdline_args(struct command_context *cmd_ctx, int argc, char *argv[])
if (optarg) if (optarg)
add_config_command(optarg); add_config_command(optarg);
break; 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: /* '?' */ default: /* '?' */
/* getopt will emit an error message, all we have to do is bail. */ /* getopt will emit an error message, all we have to do is bail. */
return ERROR_FAIL; return ERROR_FAIL;

View File

@ -3,33 +3,6 @@ noinst_LTLIBRARIES += %D%/libjtag.la
JTAG_SRCS = %D%/commands.c JTAG_SRCS = %D%/commands.c
%C%_libjtag_la_LIBADD = %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 if HLADAPTER
include %D%/hla/Makefile.am include %D%/hla/Makefile.am
%C%_libjtag_la_LIBADD += $(top_builddir)/%D%/hla/libocdhla.la %C%_libjtag_la_LIBADD += $(top_builddir)/%D%/hla/libocdhla.la
@ -43,13 +16,6 @@ endif
include %D%/drivers/Makefile.am include %D%/drivers/Makefile.am
%C%_libjtag_la_LIBADD += $(top_builddir)/%D%/drivers/libocdjtagdrivers.la %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 = \ %C%_libjtag_la_SOURCES = \
%D%/adapter.c \ %D%/adapter.c \
%D%/core.c \ %D%/core.c \
@ -63,8 +29,6 @@ endif
%D%/interfaces.h \ %D%/interfaces.h \
%D%/minidriver.h \ %D%/minidriver.h \
%D%/jtag.h \ %D%/jtag.h \
%D%/minidriver/minidriver_imp.h \
%D%/minidummy/jtag_minidriver.h \
%D%/swd.h \ %D%/swd.h \
%D%/swim.h \ %D%/swim.h \
%D%/tcl.h \ %D%/tcl.h \

View File

@ -493,7 +493,6 @@ COMMAND_HANDLER(handle_adapter_reset_de_assert)
(srst == VALUE_DEASSERT) ? SRST_DEASSERT : SRST_ASSERT); (srst == VALUE_DEASSERT) ? SRST_DEASSERT : SRST_ASSERT);
} }
#ifndef HAVE_JTAG_MINIDRIVER_H
#ifdef HAVE_LIBUSB_GET_PORT_NUMBERS #ifdef HAVE_LIBUSB_GET_PORT_NUMBERS
COMMAND_HANDLER(handle_usb_location_command) 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 */ #endif /* HAVE_LIBUSB_GET_PORT_NUMBERS */
COMMAND_REGISTRATION_DONE COMMAND_REGISTRATION_DONE
}; };
#endif /* MINIDRIVER */
static const struct command_registration adapter_srst_command_handlers[] = { 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.", .help = "Declare transports the adapter supports.",
.usage = "transport ... ", .usage = "transport ... ",
}, },
#ifndef HAVE_JTAG_MINIDRIVER_H
{ {
.name = "usb", .name = "usb",
.mode = COMMAND_ANY, .mode = COMMAND_ANY,
@ -592,7 +589,6 @@ static const struct command_registration adapter_command_handlers[] = {
.usage = "", .usage = "",
.chain = adapter_usb_command_handlers, .chain = adapter_usb_command_handlers,
}, },
#endif /* MINIDRIVER */
{ {
.name = "assert", .name = "assert",
.handler = handle_adapter_reset_de_assert, .handler = handle_adapter_reset_de_assert,

View File

@ -1,6 +1,6 @@
noinst_LTLIBRARIES += %D%/libocdaice.la 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 = \ %C%_libocdaice_la_SOURCES = \
%D%/aice_transport.c \ %D%/aice_transport.c \
%D%/aice_interface.c \ %D%/aice_interface.c \

View File

@ -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++) { for (int i = 0; i < in_num_fields; i++) {
if ((in_fields[i].check_value != NULL) && (in_fields[i].in_value != NULL)) { 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_add_callback4(jtag_check_value_mask_callback,
(jtag_callback_data_t)in_fields[i].in_value, (jtag_callback_data_t)in_fields[i].in_value,
(jtag_callback_data_t)in_fields[i].check_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(); 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; struct jtag_command *cmd = jtag_command_queue;
while (debug_level >= LOG_LVL_DEBUG_IO && cmd) { while (debug_level >= LOG_LVL_DEBUG_IO && cmd) {
switch (cmd->type) { switch (cmd->type) {
@ -1018,7 +1011,6 @@ int default_interface_jtag_execute_queue(void)
} }
cmd = cmd->next; cmd = cmd->next;
} }
#endif
return result; return result;
} }

View File

@ -27,12 +27,6 @@ DRIVERFILES += %D%/libusb_helper.c
%C%_libocdjtagdrivers_la_LIBADD += $(LIBUSB1_LIBS) %C%_libocdjtagdrivers_la_LIBADD += $(LIBUSB1_LIBS)
endif 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 if USE_LIBFTDI
%C%_libocdjtagdrivers_la_CPPFLAGS += $(LIBFTDI_CFLAGS) %C%_libocdjtagdrivers_la_CPPFLAGS += $(LIBFTDI_CFLAGS)
%C%_libocdjtagdrivers_la_LIBADD += $(LIBFTDI_LIBS) %C%_libocdjtagdrivers_la_LIBADD += $(LIBFTDI_LIBS)
@ -203,7 +197,6 @@ DRIVERHEADERS = \
%D%/rlink_dtc_cmd.h \ %D%/rlink_dtc_cmd.h \
%D%/rlink_ep1_cmd.h \ %D%/rlink_ep1_cmd.h \
%D%/rlink_st7.h \ %D%/rlink_st7.h \
%D%/usb_common.h \
%D%/versaloon/usbtoxxx/usbtoxxx.h \ %D%/versaloon/usbtoxxx/usbtoxxx.h \
%D%/versaloon/usbtoxxx/usbtoxxx_internal.h \ %D%/versaloon/usbtoxxx/usbtoxxx_internal.h \
%D%/versaloon/versaloon.h \ %D%/versaloon/versaloon.h \

View File

@ -24,7 +24,7 @@
#include <jtag/commands.h> #include <jtag/commands.h>
#include "helper/system.h" #include "helper/system.h"
#include <usb.h> #include <usb.h>
#include "usb_common.h" #include "libusb_helper.h"
#define USB_VID 0x15ba #define USB_VID 0x15ba
#define USB_PID 0x001e #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 */ /* ARM-JTAG-EW lowlevel functions */
struct armjtagew { struct armjtagew {
struct usb_dev_handle *usb_handle; struct libusb_device_handle *usb_handle;
}; };
static struct armjtagew *armjtagew_usb_open(void); static struct armjtagew *armjtagew_usb_open(void);
@ -685,35 +685,37 @@ static int armjtagew_tap_execute(void)
static struct armjtagew *armjtagew_usb_open(void) static struct armjtagew *armjtagew_usb_open(void)
{ {
usb_init();
const uint16_t vids[] = { USB_VID, 0 }; const uint16_t vids[] = { USB_VID, 0 };
const uint16_t pids[] = { USB_PID, 0 }; const uint16_t pids[] = { USB_PID, 0 };
struct usb_dev_handle *dev; struct libusb_device_handle *dev;
if (jtag_usb_open(vids, pids, &dev) != ERROR_OK)
if (jtag_libusb_open(vids, pids, NULL, &dev, NULL) != ERROR_OK)
return NULL; return NULL;
struct armjtagew *result = malloc(sizeof(struct armjtagew)); struct armjtagew *result = malloc(sizeof(struct armjtagew));
result->usb_handle = dev; result->usb_handle = dev;
#if 0 #if 0
/* usb_set_configuration required under win32 */ /* libusb_set_configuration required under win32 */
usb_set_configuration(dev, dev->config[0].bConfigurationValue); 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 #endif
usb_claim_interface(dev, 0); libusb_claim_interface(dev, 0);
#if 0 #if 0
/* /*
* This makes problems under Mac OS X. And is not needed * This makes problems under Mac OS X. And is not needed
* under Windows. Hopefully this will not break a linux build * under Windows. Hopefully this will not break a linux build
*/ */
usb_set_altinterface(dev, 0); libusb_set_interface_alt_setting(dev, 0, 0);
#endif #endif
return result; return result;
} }
static void armjtagew_usb_close(struct armjtagew *armjtagew) static void armjtagew_usb_close(struct armjtagew *armjtagew)
{ {
usb_close(armjtagew->usb_handle); libusb_close(armjtagew->usb_handle);
free(armjtagew); free(armjtagew);
} }
@ -726,13 +728,13 @@ static int armjtagew_usb_message(struct armjtagew *armjtagew, int out_length, in
if (result == out_length) { if (result == out_length) {
result = armjtagew_usb_read(armjtagew, in_length); result = armjtagew_usb_read(armjtagew, in_length);
if (result != 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, in_length,
result); result);
return -1; return -1;
} }
} else { } 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 -1;
} }
return 0; 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) static int armjtagew_usb_write(struct armjtagew *armjtagew, int out_length)
{ {
int result; int result;
int transferred;
if (out_length > ARMJTAGEW_OUT_BUFFER_SIZE) { if (out_length > ARMJTAGEW_OUT_BUFFER_SIZE) {
LOG_ERROR("armjtagew_write illegal out_length=%d (max=%d)", 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; return -1;
} }
result = usb_bulk_write(armjtagew->usb_handle, ARMJTAGEW_EPT_BULK_OUT, result = jtag_libusb_bulk_write(armjtagew->usb_handle, ARMJTAGEW_EPT_BULK_OUT,
(char *)usb_out_buffer, out_length, ARMJTAGEW_USB_TIMEOUT); (char *)usb_out_buffer, out_length, ARMJTAGEW_USB_TIMEOUT, &transferred);
LOG_DEBUG_IO("armjtagew_usb_write, out_length = %d, result = %d", out_length, result); LOG_DEBUG_IO("armjtagew_usb_write, out_length = %d, result = %d", out_length, result);
#ifdef _DEBUG_USB_COMMS_ #ifdef _DEBUG_USB_COMMS_
armjtagew_debug_buffer(usb_out_buffer, out_length); armjtagew_debug_buffer(usb_out_buffer, out_length);
#endif #endif
return result; if (result != ERROR_OK)
return -1;
return transferred;
} }
/* Read data from USB into in_buffer. */ /* Read data from USB into in_buffer. */
static int armjtagew_usb_read(struct armjtagew *armjtagew, int exp_in_length) static int armjtagew_usb_read(struct armjtagew *armjtagew, int exp_in_length)
{ {
int result = usb_bulk_read(armjtagew->usb_handle, ARMJTAGEW_EPT_BULK_IN, int transferred;
(char *)usb_in_buffer, exp_in_length, ARMJTAGEW_USB_TIMEOUT); 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); LOG_DEBUG_IO("armjtagew_usb_read, result = %d", result);
#ifdef _DEBUG_USB_COMMS_ #ifdef _DEBUG_USB_COMMS_
armjtagew_debug_buffer(usb_in_buffer, result); armjtagew_debug_buffer(usb_in_buffer, result);
#endif #endif
return result; if (result != ERROR_OK)
return -1;
return transferred;
} }
#ifdef _DEBUG_USB_COMMS_ #ifdef _DEBUG_USB_COMMS_

View File

@ -170,10 +170,6 @@ static const char * const info_caps_str[] = {
"JTAG Supported" "JTAG Supported"
}; };
/* max clock speed (kHz) */
#define DAP_MAX_CLOCK 5000
struct pending_transfer_result { struct pending_transfer_result {
uint8_t cmd; uint8_t cmd;
uint32_t data; uint32_t data;
@ -230,16 +226,12 @@ static int cmsis_dap_open(void)
{ {
const struct cmsis_dap_backend *backend = NULL; 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) { if (dap == NULL) {
LOG_ERROR("unable to allocate memory"); LOG_ERROR("unable to allocate memory");
return ERROR_FAIL; return ERROR_FAIL;
} }
dap->caps = 0;
dap->mode = 0;
dap->packet_size = 0; /* initialized by backend */
if (cmsis_dap_backend >= 0) { if (cmsis_dap_backend >= 0) {
/* Use forced backend */ /* Use forced backend */
backend = cmsis_dap_backends[cmsis_dap_backend]; backend = cmsis_dap_backends[cmsis_dap_backend];
@ -262,17 +254,7 @@ static int cmsis_dap_open(void)
return ERROR_FAIL; return ERROR_FAIL;
} }
assert(dap->packet_size > 0);
dap->backend = backend; 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; 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) static int cmsis_dap_cmd_DAP_SWJ_Pins(uint8_t pins, uint8_t mask, uint32_t delay, uint8_t *input)
{ {
int retval; int retval;
uint8_t *buffer = cmsis_dap_handle->packet_buffer; uint8_t *command = cmsis_dap_handle->command;
buffer[0] = 0; /* report number */ command[0] = CMD_DAP_SWJ_PINS;
buffer[1] = CMD_DAP_SWJ_PINS; command[1] = pins;
buffer[2] = pins; command[2] = mask;
buffer[3] = mask; h_u32_to_le(&command[3], delay);
buffer[4] = delay & 0xff;
buffer[5] = (delay >> 8) & 0xff; retval = cmsis_dap_xfer(cmsis_dap_handle, 7);
buffer[6] = (delay >> 16) & 0xff;
buffer[7] = (delay >> 24) & 0xff;
retval = cmsis_dap_xfer(cmsis_dap_handle, 8);
if (retval != ERROR_OK) { if (retval != ERROR_OK) {
LOG_ERROR("CMSIS-DAP command CMD_DAP_SWJ_PINS failed."); 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) if (input)
*input = buffer[1]; *input = cmsis_dap_handle->response[1];
return ERROR_OK; 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) static int cmsis_dap_cmd_DAP_SWJ_Clock(uint32_t swj_clock)
{ {
int retval; int retval;
uint8_t *buffer = cmsis_dap_handle->packet_buffer; uint8_t *command = cmsis_dap_handle->command;
/* set clock in Hz */ /* set clock in Hz */
swj_clock *= 1000; 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."); LOG_ERROR("CMSIS-DAP command CMD_DAP_SWJ_CLOCK failed.");
return ERROR_JTAG_DEVICE_ERROR; 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) static int cmsis_dap_cmd_DAP_SWJ_Sequence(uint8_t s_len, const uint8_t *sequence)
{ {
int retval; int retval;
uint8_t *buffer = cmsis_dap_handle->packet_buffer; uint8_t *command = cmsis_dap_handle->command;
#ifdef CMSIS_DAP_JTAG_DEBUG #ifdef CMSIS_DAP_JTAG_DEBUG
LOG_DEBUG("cmsis-dap TMS sequence: len=%d", s_len); 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"); printf("\n");
#endif #endif
buffer[0] = 0; /* report number */ command[0] = CMD_DAP_SWJ_SEQ;
buffer[1] = CMD_DAP_SWJ_SEQ; command[1] = s_len;
buffer[2] = s_len; bit_copy(&command[2], 0, sequence, 0, s_len);
bit_copy(&buffer[3], 0, sequence, 0, s_len);
retval = cmsis_dap_xfer(cmsis_dap_handle, DIV_ROUND_UP(s_len, 8) + 3); 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)
if (retval != ERROR_OK || buffer[1] != DAP_OK)
return ERROR_FAIL; return ERROR_FAIL;
return ERROR_OK; 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) static int cmsis_dap_cmd_DAP_Info(uint8_t info, uint8_t **data)
{ {
int retval; int retval;
uint8_t *buffer = cmsis_dap_handle->packet_buffer; uint8_t *command = cmsis_dap_handle->command;
buffer[0] = 0; /* report number */ command[0] = CMD_DAP_INFO;
buffer[1] = CMD_DAP_INFO; command[1] = info;
buffer[2] = info;
retval = cmsis_dap_xfer(cmsis_dap_handle, 3); retval = cmsis_dap_xfer(cmsis_dap_handle, 2);
if (retval != ERROR_OK) { if (retval != ERROR_OK) {
LOG_ERROR("CMSIS-DAP command CMD_INFO failed."); LOG_ERROR("CMSIS-DAP command CMD_INFO failed.");
return ERROR_JTAG_DEVICE_ERROR; return ERROR_JTAG_DEVICE_ERROR;
} }
*data = &(buffer[1]); *data = &cmsis_dap_handle->response[1];
return ERROR_OK; 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) static int cmsis_dap_cmd_DAP_LED(uint8_t led, uint8_t state)
{ {
int retval; int retval;
uint8_t *buffer = cmsis_dap_handle->packet_buffer; uint8_t *command = cmsis_dap_handle->command;
buffer[0] = 0; /* report number */ command[0] = CMD_DAP_LED;
buffer[1] = CMD_DAP_LED; command[1] = led;
buffer[2] = led; command[2] = state;
buffer[3] = state;
retval = cmsis_dap_xfer(cmsis_dap_handle, 4);
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."); LOG_ERROR("CMSIS-DAP command CMD_LED failed.");
return ERROR_JTAG_DEVICE_ERROR; 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) static int cmsis_dap_cmd_DAP_Connect(uint8_t mode)
{ {
int retval; int retval;
uint8_t *buffer = cmsis_dap_handle->packet_buffer; uint8_t *command = cmsis_dap_handle->command;
buffer[0] = 0; /* report number */ command[0] = CMD_DAP_CONNECT;
buffer[1] = CMD_DAP_CONNECT; command[1] = mode;
buffer[2] = mode;
retval = cmsis_dap_xfer(cmsis_dap_handle, 3); retval = cmsis_dap_xfer(cmsis_dap_handle, 2);
if (retval != ERROR_OK) { if (retval != ERROR_OK) {
LOG_ERROR("CMSIS-DAP command CMD_CONNECT failed."); LOG_ERROR("CMSIS-DAP command CMD_CONNECT failed.");
return ERROR_JTAG_DEVICE_ERROR; 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); LOG_ERROR("CMSIS-DAP failed to connect in mode (%d)", mode);
return ERROR_JTAG_DEVICE_ERROR; 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) static int cmsis_dap_cmd_DAP_Disconnect(void)
{ {
int retval; int retval;
uint8_t *buffer = cmsis_dap_handle->packet_buffer; uint8_t *command = cmsis_dap_handle->command;
buffer[0] = 0; /* report number */ command[0] = CMD_DAP_DISCONNECT;
buffer[1] = CMD_DAP_DISCONNECT;
retval = cmsis_dap_xfer(cmsis_dap_handle, 2);
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."); LOG_ERROR("CMSIS-DAP command CMD_DISCONNECT failed.");
return ERROR_JTAG_DEVICE_ERROR; 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) static int cmsis_dap_cmd_DAP_TFER_Configure(uint8_t idle, uint16_t retry_count, uint16_t match_retry)
{ {
int retval; int retval;
uint8_t *buffer = cmsis_dap_handle->packet_buffer; uint8_t *command = cmsis_dap_handle->command;
buffer[0] = 0; /* report number */ command[0] = CMD_DAP_TFER_CONFIGURE;
buffer[1] = CMD_DAP_TFER_CONFIGURE; command[1] = idle;
buffer[2] = idle; h_u16_to_le(&command[2], retry_count);
buffer[3] = retry_count & 0xff; h_u16_to_le(&command[4], match_retry);
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);
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."); LOG_ERROR("CMSIS-DAP command CMD_TFER_Configure failed.");
return ERROR_JTAG_DEVICE_ERROR; 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) static int cmsis_dap_cmd_DAP_SWD_Configure(uint8_t cfg)
{ {
int retval; int retval;
uint8_t *buffer = cmsis_dap_handle->packet_buffer; uint8_t *command = cmsis_dap_handle->command;
buffer[0] = 0; /* report number */ command[0] = CMD_DAP_SWD_CONFIGURE;
buffer[1] = CMD_DAP_SWD_CONFIGURE; command[1] = cfg;
buffer[2] = cfg;
retval = cmsis_dap_xfer(cmsis_dap_handle, 3);
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."); LOG_ERROR("CMSIS-DAP command CMD_SWD_Configure failed.");
return ERROR_JTAG_DEVICE_ERROR; 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) static int cmsis_dap_cmd_DAP_Delay(uint16_t delay_us)
{ {
int retval; int retval;
uint8_t *buffer = cmsis_dap_handle->packet_buffer; uint8_t *command = cmsis_dap_handle->command;
buffer[0] = 0; /* report number */ command[0] = CMD_DAP_DELAY;
buffer[1] = CMD_DAP_DELAY; h_u16_to_le(&command[1], delay_us);
buffer[2] = delay_us & 0xff;
buffer[3] = (delay_us >> 8) & 0xff;
retval = cmsis_dap_xfer(cmsis_dap_handle, 4);
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."); LOG_ERROR("CMSIS-DAP command CMD_Delay failed.");
return ERROR_JTAG_DEVICE_ERROR; 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) 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]; 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); 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) if (block->transfer_count == 0)
goto skip; goto skip;
size_t idx = 0; command[0] = CMD_DAP_TFER;
buffer[idx++] = 0; /* report number */ command[1] = 0x00; /* DAP Index */
buffer[idx++] = CMD_DAP_TFER; command[2] = block->transfer_count;
buffer[idx++] = 0x00; /* DAP Index */ size_t idx = 3;
buffer[idx++] = block->transfer_count;
for (int i = 0; i < block->transfer_count; i++) { for (int i = 0; i < block->transfer_count; i++) {
struct pending_transfer_result *transfer = &(block->transfers[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; data &= ~CORUNDETECT;
} }
buffer[idx++] = (cmd >> 1) & 0x0f; command[idx++] = (cmd >> 1) & 0x0f;
if (!(cmd & SWD_CMD_RnW)) { if (!(cmd & SWD_CMD_RnW)) {
buffer[idx++] = (data) & 0xff; h_u32_to_le(&command[idx], data);
buffer[idx++] = (data >> 8) & 0xff; idx += 4;
buffer[idx++] = (data >> 16) & 0xff;
buffer[idx++] = (data >> 24) & 0xff;
} }
} }
@ -620,7 +589,6 @@ skip:
static void cmsis_dap_swd_read_process(struct cmsis_dap *dap, int timeout_ms) 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]; struct pending_request_block *block = &pending_fifo[pending_fifo_get_idx];
if (pending_fifo_block_count == 0) 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; goto skip;
} }
if (buffer[2] & 0x08) { uint8_t *resp = dap->response;
LOG_DEBUG("CMSIS-DAP Protocol Error @ %d (wrong parity)", buffer[1]); 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; queued_retval = ERROR_FAIL;
goto skip; goto skip;
} }
uint8_t ack = buffer[2] & 0x07;
if (ack != SWD_ACK_OK) { 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"); ack == SWD_ACK_WAIT ? "WAIT" : ack == SWD_ACK_FAULT ? "FAULT" : "JUNK");
queued_retval = ack == SWD_ACK_WAIT ? ERROR_WAIT : ERROR_FAIL; queued_retval = ack == SWD_ACK_WAIT ? ERROR_WAIT : ERROR_FAIL;
goto skip; 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", 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; 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]); struct pending_transfer_result *transfer = &(block->transfers[i]);
if (transfer->cmd & SWD_CMD_RnW) { if (transfer->cmd & SWD_CMD_RnW) {
static uint32_t last_read; 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; uint32_t tmp = data;
idx += 4; idx += 4;
@ -934,24 +905,20 @@ static int cmsis_dap_init(void)
if (data[0] == 2) { /* short */ if (data[0] == 2) { /* short */
uint16_t pkt_sz = data[1] + (data[2] << 8); 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 /* 4 bytes of command header + 5 bytes per register
* write. For bulk read sequences just 4 bytes are * write. For bulk read sequences just 4 bytes are
* needed per transfer, so this is suboptimal. */ * needed per transfer, so this is suboptimal. */
pending_queue_len = (pkt_sz - 4) / 5; pending_queue_len = (pkt_sz - 4) / 5;
if (cmsis_dap_handle->packet_size != pkt_sz + 1) { free(cmsis_dap_handle->packet_buffer);
/* reallocate buffer */ retval = cmsis_dap_handle->backend->packet_buffer_alloc(cmsis_dap_handle, pkt_sz);
cmsis_dap_handle->packet_size = pkt_sz + 1; if (retval != ERROR_OK)
cmsis_dap_handle->packet_buffer = realloc(cmsis_dap_handle->packet_buffer, return retval;
cmsis_dap_handle->packet_size);
if (cmsis_dap_handle->packet_buffer == NULL) {
LOG_ERROR("unable to reallocate memory");
return ERROR_FAIL;
}
}
LOG_DEBUG("CMSIS-DAP: Packet Size = %" PRId16, pkt_sz); LOG_DEBUG("CMSIS-DAP: Packet Size = %" PRIu16, pkt_sz);
}
} }
/* INFO_ID_PKT_CNT - byte */ /* 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", 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); queued_seq_count, queued_seq_buf_end, pending_scan_result_count);
/* prep CMSIS-DAP packet */ /* prepare CMSIS-DAP packet */
uint8_t *buffer = cmsis_dap_handle->packet_buffer; uint8_t *command = cmsis_dap_handle->command;
buffer[0] = 0; /* report number */ command[0] = CMD_DAP_JTAG_SEQ;
buffer[1] = CMD_DAP_JTAG_SEQ; command[1] = queued_seq_count;
buffer[2] = queued_seq_count; memcpy(&command[2], queued_seq_buf, queued_seq_buf_end);
memcpy(buffer + 3, queued_seq_buf, queued_seq_buf_end);
#ifdef CMSIS_DAP_JTAG_DEBUG #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 #endif
/* send command to USB device */ /* send command to USB device */
int retval = cmsis_dap_xfer(cmsis_dap_handle, queued_seq_buf_end + 3); int retval = cmsis_dap_xfer(cmsis_dap_handle, queued_seq_buf_end + 2);
if (retval != ERROR_OK || buffer[1] != DAP_OK) {
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."); LOG_ERROR("CMSIS-DAP command CMD_DAP_JTAG_SEQ failed.");
exit(-1); exit(-1);
} }
@ -1189,7 +1157,7 @@ static void cmsis_dap_flush(void)
#ifdef CMSIS_DAP_JTAG_DEBUG #ifdef CMSIS_DAP_JTAG_DEBUG
LOG_DEBUG_IO("USB response buf:"); LOG_DEBUG_IO("USB response buf:");
for (int c = 0; c < queued_seq_buf_end + 3; ++c) for (int c = 0; c < queued_seq_buf_end + 3; ++c)
printf("%02X ", buffer[c]); printf("%02X ", resp[c]);
printf("\n"); printf("\n");
#endif #endif
@ -1200,10 +1168,10 @@ static void cmsis_dap_flush(void)
i, pending_scan_result_count, scan->length, scan->first + 2, scan->buffer_offset); i, pending_scan_result_count, scan->length, scan->first + 2, scan->buffer_offset);
#ifdef CMSIS_DAP_JTAG_DEBUG #ifdef CMSIS_DAP_JTAG_DEBUG
for (uint32_t b = 0; b < DIV_ROUND_UP(scan->length, 8); ++b) 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"); printf("\n");
#endif #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 */ /* reset */
@ -1545,9 +1513,6 @@ static int cmsis_dap_execute_queue(void)
static int cmsis_dap_speed(int speed) 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) { if (speed == 0) {
LOG_ERROR("RTCK not supported. Set nonzero \"adapter speed\"."); LOG_ERROR("RTCK not supported. Set nonzero \"adapter speed\".");
return ERROR_JTAG_NOT_IMPLEMENTED; return ERROR_JTAG_NOT_IMPLEMENTED;
@ -1580,22 +1545,21 @@ COMMAND_HANDLER(cmsis_dap_handle_cmd_command)
{ {
int retval; int retval;
unsigned i; unsigned i;
uint8_t *buffer = cmsis_dap_handle->packet_buffer; uint8_t *command = cmsis_dap_handle->command;
buffer[0] = 0; /* report number */
for (i = 0; i < CMD_ARGC; i++) 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) { if (retval != ERROR_OK) {
LOG_ERROR("CMSIS-DAP command failed."); LOG_ERROR("CMSIS-DAP command failed.");
return ERROR_JTAG_DEVICE_ERROR; return ERROR_JTAG_DEVICE_ERROR;
} }
uint8_t *resp = cmsis_dap_handle->response;
LOG_INFO("Returned data %02" PRIx8 " %02" PRIx8 " %02" PRIx8 " %02" PRIx8, 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; return ERROR_OK;
} }

View File

@ -13,6 +13,9 @@ struct cmsis_dap {
uint16_t packet_size; uint16_t packet_size;
int packet_count; int packet_count;
uint8_t *packet_buffer; uint8_t *packet_buffer;
uint16_t packet_buffer_size;
uint8_t *command;
uint8_t *response;
uint8_t caps; uint8_t caps;
uint8_t mode; uint8_t mode;
}; };
@ -23,10 +26,13 @@ struct cmsis_dap_backend {
void (*close)(struct cmsis_dap *dap); void (*close)(struct cmsis_dap *dap);
int (*read)(struct cmsis_dap *dap, int timeout_ms); int (*read)(struct cmsis_dap *dap, int timeout_ms);
int (*write)(struct cmsis_dap *dap, int len, 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_hid_backend;
extern const struct cmsis_dap_backend cmsis_dap_usb_backend; extern const struct cmsis_dap_backend cmsis_dap_usb_backend;
extern const struct command_registration cmsis_dap_usb_subcommand_handlers[]; extern const struct command_registration cmsis_dap_usb_subcommand_handlers[];
#define REPORT_ID_SIZE 1
#endif #endif

View File

@ -51,6 +51,9 @@ struct cmsis_dap_backend_data {
static int cmsis_dap_usb_interface = -1; 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) static int cmsis_dap_usb_open(struct cmsis_dap *dap, uint16_t vids[], uint16_t pids[], char *serial)
{ {
int err; 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; 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->usb_ctx = ctx;
dap->bdata->dev_handle = dev_handle; dap->bdata->dev_handle = dev_handle;
dap->bdata->ep_out = ep_out; dap->bdata->ep_out = ep_out;
dap->bdata->ep_in = ep_in; dap->bdata->ep_in = ep_in;
dap->bdata->interface = interface_num; 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; return ERROR_OK;
} }
@ -382,6 +397,8 @@ static void cmsis_dap_usb_close(struct cmsis_dap *dap)
libusb_exit(dap->bdata->usb_ctx); libusb_exit(dap->bdata->usb_ctx);
free(dap->bdata); free(dap->bdata);
dap->bdata = NULL; dap->bdata = NULL;
free(dap->packet_buffer);
dap->packet_buffer = NULL;
} }
static int cmsis_dap_usb_read(struct cmsis_dap *dap, int timeout_ms) 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; 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 */ /* skip the first byte that is only used by the HID backend */
err = libusb_bulk_transfer(dap->bdata->dev_handle, dap->bdata->ep_out, 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) {
if (err == LIBUSB_ERROR_TIMEOUT) { if (err == LIBUSB_ERROR_TIMEOUT) {
return ERROR_TIMEOUT_REACHED; 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; 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) COMMAND_HANDLER(cmsis_dap_handle_usb_interface_command)
{ {
if (CMD_ARGC == 1) if (CMD_ARGC == 1)
@ -452,4 +487,5 @@ const struct cmsis_dap_backend cmsis_dap_usb_backend = {
.close = cmsis_dap_usb_close, .close = cmsis_dap_usb_close,
.read = cmsis_dap_usb_read, .read = cmsis_dap_usb_read,
.write = cmsis_dap_usb_write, .write = cmsis_dap_usb_write,
.packet_buffer_alloc = cmsis_dap_usb_alloc,
}; };

View File

@ -40,12 +40,13 @@
#include "cmsis_dap.h" #include "cmsis_dap.h"
#define PACKET_SIZE (64 + 1) /* 64 bytes plus report id */
struct cmsis_dap_backend_data { struct cmsis_dap_backend_data {
hid_device *dev_handle; 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) static int cmsis_dap_hid_open(struct cmsis_dap *dap, uint16_t vids[], uint16_t pids[], char *serial)
{ {
hid_device *dev = NULL; 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. * without this info we cannot communicate with the adapter.
* For the moment we have to hard code the packet size */ * 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 */ /* atmel cmsis-dap uses 512 byte reports */
/* except when it doesn't e.g. with mEDBG on SAMD10 Xplained /* 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 /* TODO: HID report descriptor should be parsed instead of
* hardcoding a match by VID */ * hardcoding a match by VID */
if (target_vid == 0x03eb && target_pid != 0x2145 && target_pid != 0x2175) if (target_vid == 0x03eb && target_pid != 0x2145 && target_pid != 0x2175)
dap->packet_size = 512 + 1; packet_size = 512;
dap->bdata->dev_handle = dev; 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; return ERROR_OK;
} }
@ -166,11 +175,13 @@ static void cmsis_dap_hid_close(struct cmsis_dap *dap)
hid_exit(); hid_exit();
free(dap->bdata); free(dap->bdata);
dap->bdata = NULL; dap->bdata = NULL;
free(dap->packet_buffer);
dap->packet_buffer = NULL;
} }
static int cmsis_dap_hid_read(struct cmsis_dap *dap, int timeout_ms) 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) { if (retval == 0) {
return ERROR_TIMEOUT_REACHED; 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; (void) timeout_ms;
dap->packet_buffer[0] = 0; /* HID report number */
/* Pad the rest of the TX buffer with 0's */ /* 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 */ /* 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) { if (retval == -1) {
LOG_ERROR("error writing data: %ls", hid_error(dap->bdata->dev_handle)); LOG_ERROR("error writing data: %ls", hid_error(dap->bdata->dev_handle));
return ERROR_FAIL; return ERROR_FAIL;
@ -199,10 +212,30 @@ static int cmsis_dap_hid_write(struct cmsis_dap *dap, int txlen, int timeout_ms)
return retval; 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 = { const struct cmsis_dap_backend cmsis_dap_hid_backend = {
.name = "hid", .name = "hid",
.open = cmsis_dap_hid_open, .open = cmsis_dap_hid_open,
.close = cmsis_dap_hid_close, .close = cmsis_dap_hid_close,
.read = cmsis_dap_hid_read, .read = cmsis_dap_hid_read,
.write = cmsis_dap_hid_write, .write = cmsis_dap_hid_write,
.packet_buffer_alloc = cmsis_dap_hid_alloc,
}; };

View File

@ -51,7 +51,7 @@ bool jtag_usb_location_equal(uint8_t dev_bus, uint8_t *port_path,
goto done; goto done;
} }
string_length -= 1; string_length -= strnlen(ptr, string_length);
/* check bus mismatch */ /* check bus mismatch */
if (atoi(ptr) != dev_bus) if (atoi(ptr) != dev_bus)
goto done; goto done;
@ -69,7 +69,7 @@ bool jtag_usb_location_equal(uint8_t dev_bus, uint8_t *port_path,
break; break;
path_step++; path_step++;
string_length -= 2; string_length -= strnlen(ptr, string_length) + 1;
}; };
/* walked the full path, all elements match */ /* walked the full path, all elements match */

View File

@ -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; 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); nulink_usb_init_buffer(handle, 8 + 12 * 1);
/* set command ID */ /* 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; aligned_addr = aligned_addr * 4;
offset = addr - aligned_addr; offset = addr - aligned_addr;
LOG_DEBUG("nulink_usb_read_mem8: unaligned address addr 0x%08" PRIx32 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, offset);
addr = aligned_addr; addr = aligned_addr;

View File

@ -34,7 +34,7 @@
#include "rlink_st7.h" #include "rlink_st7.h"
#include "rlink_ep1_cmd.h" #include "rlink_ep1_cmd.h"
#include "rlink_dtc_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 /* 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. */ *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_PC_TDO ST7_PC_IO9
#define ST7_PA_DBGACK ST7_PA_IO10 #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. * ep1 commands are up to USB_EP1OUT_SIZE bytes in length.
* This function takes care of zeroing the unused bytes before sending the packet. * This function takes care of zeroing the unused bytes before sending the packet.
* Any reply packet is not handled by this function. * 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[USB_EP1OUT_SIZE];
uint8_t *usb_buffer_p; uint8_t *usb_buffer_p;
va_list ap; va_list ap;
int usb_ret; int usb_ret;
int transferred;
if (length > sizeof(usb_buffer)) if (length > sizeof(usb_buffer))
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) sizeof(usb_buffer) - (usb_buffer_p - usb_buffer)
); );
usb_ret = usb_bulk_write( usb_ret = jtag_libusb_bulk_write(
pHDev_param, pHDev_param,
USB_EP1OUT_ADDR, USB_EP1OUT_ADDR,
(char *)usb_buffer, sizeof(usb_buffer), (char *)usb_buffer, sizeof(usb_buffer),
USB_TIMEOUT_MS USB_TIMEOUT_MS,
&transferred
); );
if (usb_ret != ERROR_OK)
return usb_ret; return usb_ret;
return transferred;
} }
#if 0 #if 0
static ssize_t ep1_memory_read( 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) size_t length, uint8_t *buffer)
{ {
uint8_t usb_buffer[USB_EP1OUT_SIZE]; uint8_t usb_buffer[USB_EP1OUT_SIZE];
int usb_ret; int usb_ret;
size_t remain; size_t remain;
ssize_t count; ssize_t count;
int transferred;
usb_buffer[0] = EP1_CMD_MEMORY_READ; usb_buffer[0] = EP1_CMD_MEMORY_READ;
memset( memset(
@ -168,22 +173,24 @@ static ssize_t ep1_memory_read(
usb_buffer[2] = addr; usb_buffer[2] = addr;
usb_buffer[3] = length; usb_buffer[3] = length;
usb_ret = usb_bulk_write( usb_ret = jtag_libusb_bulk_write(
pHDev, USB_EP1OUT_ADDR, pHDev_param, USB_EP1OUT_ADDR,
usb_buffer, sizeof(usb_buffer), (char *)usb_buffer, sizeof(usb_buffer),
USB_TIMEOUT_MS USB_TIMEOUT_MS,
&transferred
); );
if (usb_ret < sizeof(usb_buffer)) if (usb_ret != ERROR_OK || transferred < (int)sizeof(usb_buffer))
break; break;
usb_ret = usb_bulk_read( usb_ret = jtag_libusb_bulk_read(
pHDev, USB_EP1IN_ADDR, pHDev_param, USB_EP1IN_ADDR,
buffer, length, (char *)buffer, length,
USB_TIMEOUT_MS USB_TIMEOUT_MS,
&transferred
); );
if (usb_ret < length) if (usb_ret != ERROR_OK || transferred < (int)length)
break; break;
addr += length; addr += length;
@ -196,7 +203,7 @@ static ssize_t ep1_memory_read(
} }
#endif #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) size_t length, uint8_t const *buffer)
{ {
uint8_t usb_buffer[USB_EP1OUT_SIZE]; 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 sizeof(usb_buffer) - 4 - length
); );
usb_ret = usb_bulk_write( int transferred;
usb_ret = jtag_libusb_bulk_write(
pHDev_param, USB_EP1OUT_ADDR, pHDev_param, USB_EP1OUT_ADDR,
(char *)usb_buffer, sizeof(usb_buffer), (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; break;
addr += length; addr += length;
@ -249,7 +259,7 @@ static ssize_t ep1_memory_write(usb_dev_handle *pHDev_param, uint16_t addr,
#if 0 #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, ...) size_t length, ...)
{ {
uint8_t buffer[USB_EP1OUT_SIZE - 4]; 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--; remain--;
} }
return ep1_memory_write(pHDev, addr, length, buffer); return ep1_memory_write(pHDev_param, addr, length, buffer);
} }
#endif #endif
@ -286,7 +296,7 @@ static ssize_t ep1_memory_writel(usb_dev_handle *pHDev, uint16_t addr,
static uint8_t dtc_entry_download; static uint8_t dtc_entry_download;
/* The buffer is specially formatted to represent a valid image to load into the DTC. */ /* 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) size_t length)
{ {
struct header_s { struct header_s {
@ -401,6 +411,7 @@ static int dtc_start_download(void)
{ {
int usb_err; int usb_err;
uint8_t ep2txr; uint8_t ep2txr;
int transferred;
/* set up for download mode and make sure EP2 is set up to transmit */ /* set up for download mode and make sure EP2 is set up to transmit */
usb_err = ep1_generic_commandl( usb_err = ep1_generic_commandl(
@ -418,12 +429,13 @@ static int dtc_start_download(void)
return usb_err; return usb_err;
/* read back ep2txr */ /* read back ep2txr */
usb_err = usb_bulk_read( usb_err = jtag_libusb_bulk_read(
pHDev, USB_EP1IN_ADDR, pHDev, USB_EP1IN_ADDR,
(char *)&ep2txr, 1, (char *)&ep2txr, 1,
USB_TIMEOUT_MS USB_TIMEOUT_MS,
&transferred
); );
if (usb_err < 0) if (usb_err != ERROR_OK)
return usb_err; return usb_err;
usb_err = ep1_generic_commandl( usb_err = ep1_generic_commandl(
@ -447,17 +459,18 @@ static int dtc_start_download(void)
return usb_err; return usb_err;
/* wait for completion */ /* wait for completion */
usb_err = usb_bulk_read( usb_err = jtag_libusb_bulk_read(
pHDev, USB_EP1IN_ADDR, pHDev, USB_EP1IN_ADDR,
(char *)&ep2txr, 1, (char *)&ep2txr, 1,
USB_TIMEOUT_MS USB_TIMEOUT_MS,
&transferred
); );
return usb_err; return usb_err;
} }
static int dtc_run_download( static int dtc_run_download(
usb_dev_handle *pHDev_param, libusb_device_handle *pHDev_param,
uint8_t *command_buffer, uint8_t *command_buffer,
int command_buffer_size, int command_buffer_size,
uint8_t *reply_buffer, uint8_t *reply_buffer,
@ -467,14 +480,16 @@ static int dtc_run_download(
char dtc_status; char dtc_status;
int usb_err; int usb_err;
int i; int i;
int transferred;
LOG_DEBUG("%d/%d", command_buffer_size, reply_buffer_size); LOG_DEBUG("%d/%d", command_buffer_size, reply_buffer_size);
usb_err = usb_bulk_write( usb_err = jtag_libusb_bulk_write(
pHDev_param, pHDev_param,
USB_EP2OUT_ADDR, USB_EP2OUT_ADDR,
(char *)command_buffer, USB_EP2BANK_SIZE, (char *)command_buffer, USB_EP2BANK_SIZE,
USB_TIMEOUT_MS USB_TIMEOUT_MS,
&transferred
); );
if (usb_err < 0) if (usb_err < 0)
return usb_err; return usb_err;
@ -493,11 +508,12 @@ static int dtc_run_download(
if (usb_err < 0) if (usb_err < 0)
return usb_err; return usb_err;
usb_err = usb_bulk_read( usb_err = jtag_libusb_bulk_read(
pHDev_param, pHDev_param,
USB_EP1IN_ADDR, USB_EP1IN_ADDR,
&dtc_status, 1, &dtc_status, 1,
USB_TIMEOUT_MS USB_TIMEOUT_MS,
&transferred
); );
if (usb_err < 0) if (usb_err < 0)
return usb_err; return usb_err;
@ -507,20 +523,21 @@ static int dtc_run_download(
if (!--i) { if (!--i) {
LOG_ERROR("too many retries waiting for DTC status"); LOG_ERROR("too many retries waiting for DTC status");
return -ETIMEDOUT; return LIBUSB_ERROR_TIMEOUT;
} }
} }
if (reply_buffer && reply_buffer_size) { if (reply_buffer && reply_buffer_size) {
usb_err = usb_bulk_read( usb_err = jtag_libusb_bulk_read(
pHDev_param, pHDev_param,
USB_EP2IN_ADDR, USB_EP2IN_ADDR,
(char *)reply_buffer, reply_buffer_size, (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", LOG_ERROR("Read of endpoint 2 returned %d, expected %d",
usb_err, reply_buffer_size usb_err, reply_buffer_size
); );
@ -644,7 +661,7 @@ static int dtc_queue_run(void)
reply_buffer, sizeof(reply_buffer) reply_buffer, sizeof(reply_buffer)
); );
if (usb_err < 0) { 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); exit(1);
} }
@ -919,6 +936,7 @@ static void rlink_reset(int trst, int srst)
{ {
uint8_t bitmap; uint8_t bitmap;
int usb_err; int usb_err;
int transferred;
/* Read port A for bit op */ /* Read port A for bit op */
usb_err = ep1_generic_commandl( usb_err = ep1_generic_commandl(
@ -929,17 +947,18 @@ static void rlink_reset(int trst, int srst)
1 1
); );
if (usb_err < 0) { if (usb_err < 0) {
LOG_ERROR("%s", usb_strerror()); LOG_ERROR("%s", libusb_error_name(usb_err));
exit(1); exit(1);
} }
usb_err = usb_bulk_read( usb_err = jtag_libusb_bulk_read(
pHDev, USB_EP1IN_ADDR, pHDev, USB_EP1IN_ADDR,
(char *)&bitmap, 1, (char *)&bitmap, 1,
USB_TIMEOUT_MS USB_TIMEOUT_MS,
&transferred
); );
if (usb_err < 1) { if (usb_err != ERROR_OK || transferred < 1) {
LOG_ERROR("%s", usb_strerror()); LOG_ERROR("%s", libusb_error_name(usb_err));
exit(1); exit(1);
} }
@ -964,17 +983,18 @@ static void rlink_reset(int trst, int srst)
1 1
); );
if (usb_err < 0) { if (usb_err < 0) {
LOG_ERROR("%s", usb_strerror()); LOG_ERROR("%s", libusb_error_name(usb_err));
exit(1); exit(1);
} }
usb_err = usb_bulk_read( usb_err = jtag_libusb_bulk_read(
pHDev, USB_EP1IN_ADDR, pHDev, USB_EP1IN_ADDR,
(char *)&bitmap, 1, (char *)&bitmap, 1,
USB_TIMEOUT_MS USB_TIMEOUT_MS,
&transferred
); );
if (usb_err < 1) { if (usb_err != ERROR_OK || transferred < 1) {
LOG_ERROR("%s", usb_strerror()); LOG_ERROR("%s", libusb_error_name(usb_err));
exit(1); exit(1);
} }
@ -994,17 +1014,18 @@ static void rlink_reset(int trst, int srst)
EP1_CMD_DTC_GET_CACHED_STATUS EP1_CMD_DTC_GET_CACHED_STATUS
); );
if (usb_err < 0) { if (usb_err < 0) {
LOG_ERROR("%s", usb_strerror()); LOG_ERROR("%s", libusb_error_name(usb_err));
exit(1); exit(1);
} }
usb_err = usb_bulk_read( usb_err = jtag_libusb_bulk_read(
pHDev, USB_EP1IN_ADDR, pHDev, USB_EP1IN_ADDR,
(char *)&bitmap, 1, (char *)&bitmap, 1,
USB_TIMEOUT_MS USB_TIMEOUT_MS,
&transferred
); );
if (usb_err < 1) { if (usb_err != ERROR_OK || transferred < 1) {
LOG_ERROR("%s", usb_strerror()); LOG_ERROR("%s", libusb_error_name(usb_err));
exit(1); exit(1);
} }
} }
@ -1391,8 +1412,9 @@ static int rlink_speed(int speed)
exit(1); exit(1);
} }
if (dtc_start_download() < 0) { int ret = dtc_start_download();
LOG_ERROR("starting DTC: %s", usb_strerror()); if (ret < 0) {
LOG_ERROR("starting DTC: %s", libusb_error_name(ret));
exit(1); exit(1);
} }
@ -1444,19 +1466,28 @@ static int rlink_init(void)
{ {
int i, j, retries; int i, j, retries;
uint8_t reply_buffer[USB_EP1IN_SIZE]; uint8_t reply_buffer[USB_EP1IN_SIZE];
int transferred;
usb_init();
const uint16_t vids[] = { USB_IDVENDOR, 0 }; const uint16_t vids[] = { USB_IDVENDOR, 0 };
const uint16_t pids[] = { USB_IDPRODUCT, 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; return ERROR_FAIL;
struct usb_device *dev = usb_device(pHDev); struct libusb_device_descriptor descriptor;
if (dev->descriptor.bNumConfigurations > 1) { 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..."); LOG_ERROR("Whoops! NumConfigurations is not 1, don't know what to do...");
return ERROR_FAIL; 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..."); LOG_ERROR("Whoops! NumInterfaces is not 1, don't know what to do...");
return ERROR_FAIL; return ERROR_FAIL;
} }
@ -1464,29 +1495,27 @@ static int rlink_init(void)
LOG_DEBUG("Opened device, pHDev = %p", pHDev); LOG_DEBUG("Opened device, pHDev = %p", pHDev);
/* usb_set_configuration required under win32 */ /* usb_set_configuration required under win32 */
usb_set_configuration(pHDev, dev->config[0].bConfigurationValue); libusb_set_configuration(pHDev, config->bConfigurationValue);
retries = 3; retries = 3;
do { do {
i = usb_claim_interface(pHDev, 0); i = libusb_claim_interface(pHDev, 0);
if (i) { if (i != LIBUSB_SUCCESS) {
LOG_ERROR("usb_claim_interface: %s", usb_strerror()); LOG_ERROR("usb_claim_interface: %s", libusb_error_name(i));
#ifdef LIBUSB_HAS_DETACH_KERNEL_DRIVER_NP j = libusb_detach_kernel_driver(pHDev, 0);
j = usb_detach_kernel_driver_np(pHDev, 0); if (j != LIBUSB_SUCCESS)
if (j) LOG_ERROR("detach kernel driver: %s", libusb_error_name(j));
LOG_ERROR("detach kernel driver: %s", usb_strerror());
#endif
} else { } else {
LOG_DEBUG("interface claimed!"); LOG_DEBUG("interface claimed!");
break; break;
} }
} while (--retries); } while (--retries);
if (i) { if (i != LIBUSB_SUCCESS) {
LOG_ERROR("Initialisation failed."); LOG_ERROR("Initialisation failed.");
return ERROR_FAIL; 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."); LOG_ERROR("Failed to set interface.");
return ERROR_FAIL; return ERROR_FAIL;
} }
@ -1506,20 +1535,21 @@ static int rlink_init(void)
EP1_CMD_GET_FWREV EP1_CMD_GET_FWREV
); );
if (j < USB_EP1OUT_SIZE) { 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; return ERROR_FAIL;
} }
j = usb_bulk_read( j = jtag_libusb_bulk_read(
pHDev, USB_EP1IN_ADDR, pHDev, USB_EP1IN_ADDR,
(char *)reply_buffer, sizeof(reply_buffer), (char *)reply_buffer, sizeof(reply_buffer),
200 200,
&transferred
); );
if (j != -ETIMEDOUT) if (j != LIBUSB_ERROR_TIMEOUT)
break; break;
} }
if (j < (int)sizeof(reply_buffer)) { if (j != ERROR_OK || transferred != (int)sizeof(reply_buffer)) {
LOG_ERROR("USB read error: %s", usb_strerror()); LOG_ERROR("USB read error: %s", libusb_error_name(j));
return ERROR_FAIL; return ERROR_FAIL;
} }
LOG_DEBUG(INTERFACE_NAME " firmware version: %d.%d.%d", LOG_DEBUG(INTERFACE_NAME " firmware version: %d.%d.%d",
@ -1552,10 +1582,11 @@ static int rlink_init(void)
ST7_PE_ADAPTER_SENSE_OUT ST7_PE_ADAPTER_SENSE_OUT
); );
usb_bulk_read( jtag_libusb_bulk_read(
pHDev, USB_EP1IN_ADDR, pHDev, USB_EP1IN_ADDR,
(char *)reply_buffer, 1, (char *)reply_buffer, 1,
USB_TIMEOUT_MS USB_TIMEOUT_MS,
&transferred
); );
if ((reply_buffer[0] & ST7_PE_ADAPTER_SENSE_IN) != 0) if ((reply_buffer[0] & ST7_PE_ADAPTER_SENSE_IN) != 0)
@ -1576,10 +1607,11 @@ static int rlink_init(void)
0x00 /* OR */ 0x00 /* OR */
); );
usb_bulk_read( jtag_libusb_bulk_read(
pHDev, USB_EP1IN_ADDR, pHDev, USB_EP1IN_ADDR,
(char *)reply_buffer, 1, (char *)reply_buffer, 1,
USB_TIMEOUT_MS USB_TIMEOUT_MS,
&transferred
); );
@ -1655,8 +1687,8 @@ static int rlink_quit(void)
~0 ~0
); );
usb_release_interface(pHDev, 0); libusb_release_interface(pHDev, 0);
usb_close(pHDev); libusb_close(pHDev);
return ERROR_OK; return ERROR_OK;
} }

View File

@ -1,4 +1,7 @@
/*************************************************************************** /***************************************************************************
* Copyright (C) 2020 by Tarek Bochkati *
* Tarek Bochkati <tarek.bouchkati@gmail.com> *
* *
* SWIM contributions by Ake Rehnman * * SWIM contributions by Ake Rehnman *
* Copyright (C) 2017 Ake Rehnman * * Copyright (C) 2017 Ake Rehnman *
* ake.rehnman(at)gmail.com * * ake.rehnman(at)gmail.com *
@ -43,6 +46,16 @@
#include <target/cortex_m.h> #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" #include "libusb_helper.h"
#ifdef HAVE_LIBUSB1 #ifdef HAVE_LIBUSB1
@ -120,12 +133,48 @@ struct stlink_usb_version {
uint32_t flags; uint32_t flags;
}; };
/** */ struct stlink_usb_priv_s {
struct stlink_usb_handle_s {
/** */ /** */
struct libusb_device_handle *fd; struct libusb_device_handle *fd;
/** */ /** */
struct libusb_transfer *trans; 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; uint8_t rx_ep;
/** */ /** */
@ -133,13 +182,13 @@ struct stlink_usb_handle_s {
/** */ /** */
uint8_t trace_ep; uint8_t trace_ep;
/** */ /** */
uint8_t cmdbuf[STLINK_SG_SIZE]; uint8_t *cmdbuf;
/** */ /** */
uint8_t cmdidx; uint8_t cmdidx;
/** */ /** */
uint8_t direction; uint8_t direction;
/** */ /** */
uint8_t databuf[STLINK_DATA_SIZE]; uint8_t *databuf;
/** */ /** */
uint32_t max_mem_packet; uint32_t max_mem_packet;
/** */ /** */
@ -162,6 +211,26 @@ struct stlink_usb_handle_s {
bool reconnect_pending; 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_ERR_OK 0x00
#define STLINK_SWIM_BUSY 0x01 #define STLINK_SWIM_BUSY 0x01
#define STLINK_DEBUG_ERR_OK 0x80 #define STLINK_DEBUG_ERR_OK 0x80
@ -307,6 +376,39 @@ struct stlink_usb_handle_s {
#define REQUEST_SENSE 0x03 #define REQUEST_SENSE 0x03
#define REQUEST_SENSE_LENGTH 18 #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 * Map the relevant features, quirks and workaround for specific firmware
* version of stlink * version of stlink
@ -381,8 +483,6 @@ static unsigned int stlink_usb_block(void *handle)
return STLINK_MAX_RW8; return STLINK_MAX_RW8;
} }
#ifdef USE_LIBUSB_ASYNCIO #ifdef USE_LIBUSB_ASYNCIO
static LIBUSB_CALL void sync_transfer_cb(struct libusb_transfer *transfer) 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 */ /* read status */
memset(h->cmdbuf, 0, STLINK_SG_SIZE); 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); STLINK_READ_TIMEOUT, &tr);
if (ret || tr != 13) if (ret || tr != 13)
return ERROR_FAIL; 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( return jtag_libusb_bulk_transfer_n(
h->fd, h->usb_backend_priv.fd,
transfers, transfers,
n_transfers, n_transfers,
STLINK_WRITE_TIMEOUT); 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); 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); cmdsize, STLINK_WRITE_TIMEOUT, &tr);
if (ret || tr != cmdsize) if (ret || tr != cmdsize)
return ERROR_FAIL; return ERROR_FAIL;
if (h->direction == h->tx_ep && size) { 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); size, STLINK_WRITE_TIMEOUT, &tr);
if (ret || tr != size) { if (ret || tr != size) {
LOG_DEBUG("bulk write failed"); LOG_DEBUG("bulk write failed");
return ERROR_FAIL; return ERROR_FAIL;
} }
} else if (h->direction == h->rx_ep && size) { } 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); size, STLINK_READ_TIMEOUT, &tr);
if (ret || tr != size) { if (ret || tr != size) {
LOG_DEBUG("bulk read failed"); LOG_DEBUG("bulk read failed");
@ -668,13 +768,29 @@ static int stlink_usb_xfer_v1_get_sense(void *handle)
return ERROR_OK; 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 transfers block in cmdbuf
<size> indicates number of bytes in the following <size> indicates number of bytes in the following
data phase. data phase.
Ignore the (eventual) error code in the received packet. 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; int err, cmdsize = STLINK_CMD_SIZE_V2;
struct stlink_usb_handle_s *h = handle; 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; 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 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. 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) static int stlink_usb_read_trace(void *handle, const uint8_t *buf, int size)
{ {
struct stlink_usb_handle_s *h = handle; struct stlink_usb_handle_s *h = handle;
int tr, ret;
assert(handle != NULL); assert(handle != NULL);
assert(h->version.flags & STLINK_F_HAS_TRACE); assert(h->version.flags & STLINK_F_HAS_TRACE);
ret = jtag_libusb_bulk_read(h->fd, h->trace_ep, (char *)buf, size, return h->backend->read_trace(handle, buf, size);
STLINK_READ_TIMEOUT, &tr);
if (ret || tr != size) {
LOG_ERROR("bulk trace read failed");
return ERROR_FAIL;
}
return ERROR_OK;
} }
/* /*
@ -1749,7 +1968,7 @@ static int stlink_usb_trace_read(void *handle, uint8_t *buf, size_t *size)
return res; return res;
size_t bytes_avail = le_to_h_u16(h->databuf); 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) { if (*size > 0) {
res = stlink_usb_read_trace(handle, buf, *size); 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; 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); stlink_usb_exit_mode(h);
/* do not check return code, it prevent /* do not check return code, it prevent
us from closing jtag_libusb */ us from closing jtag_libusb */
jtag_libusb_close(h->fd); jtag_libusb_close(h->usb_backend_priv.fd);
} }
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); free(h);
}
return ERROR_OK; 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; 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->cmdbuf == NULL || h->databuf == NULL)
if (h == 0) {
LOG_DEBUG("malloc failed");
return ERROR_FAIL; 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) 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 { do {
if (jtag_libusb_open(param->vid, param->pid, param->serial, 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"); 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"); LOG_DEBUG("claim interface failed");
goto error_open; return ERROR_FAIL;
} }
/* RX EP is common for all versions */ /* RX EP is common for all versions */
h->rx_ep = STLINK_RX_EP; h->rx_ep = STLINK_RX_EP;
uint16_t pid; 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"); LOG_DEBUG("libusb_get_pid failed");
goto error_open; return ERROR_FAIL;
} }
/* wrap version for first read */ /* 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 || } else if (h->version.stlink == 1 ||
retry_count == 0) { retry_count == 0) {
LOG_ERROR("read version failed"); LOG_ERROR("read version failed");
goto error_open; return ERROR_FAIL;
} else { } else {
err = libusb_release_interface(h->fd, 0); err = libusb_release_interface(h->usb_backend_priv.fd, 0);
if (err != ERROR_OK) { if (err != ERROR_OK) {
LOG_ERROR("release interface failed"); 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) { if (err != ERROR_OK) {
LOG_ERROR("reset device failed"); 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 Give the device one second to settle down and
reenumerate. reenumerate.
@ -2927,8 +3185,265 @@ static int stlink_usb_open(struct hl_interface_param_s *param, enum stlink_mode
} }
} while (1); } 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 */ /* check if mode is supported */
err = ERROR_OK; int err = ERROR_OK;
switch (h->st_mode) { switch (h->st_mode) {
case STLINK_MODE_DEBUG_SWD: case STLINK_MODE_DEBUG_SWD:
@ -2972,6 +3487,8 @@ static int stlink_usb_open(struct hl_interface_param_s *param, enum stlink_mode
return ERROR_OK; return ERROR_OK;
} }
/* 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 /* get cpuid, so we can determine the max page size
* start with a safe default */ * start with a safe default */
h->max_mem_packet = (1 << 10); h->max_mem_packet = (1 << 10);
@ -2989,20 +3506,20 @@ static int stlink_usb_open(struct hl_interface_param_s *param, enum stlink_mode
} }
LOG_DEBUG("Using TAR autoincrement: %" PRIu32, h->max_mem_packet); LOG_DEBUG("Using TAR autoincrement: %" PRIu32, h->max_mem_packet);
}
*fd = h; *fd = h;
return ERROR_OK; return ERROR_OK;
error_open: error_open:
stlink_usb_close(h); stlink_close(h);
return ERROR_FAIL; return ERROR_FAIL;
} }
static int stlink_usb_hl_open(struct hl_interface_param_s *param, void **fd) 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, 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; struct stlink_usb_handle_s *h = handle;
if (enabled && (!(h->version.flags & STLINK_F_HAS_TRACE) || if (!(h->version.flags & STLINK_F_HAS_TRACE)) {
pin_protocol != TPIU_PIN_PROTOCOL_ASYNC_UART)) { 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"); LOG_ERROR("The attached ST-LINK version doesn't support this trace mode");
return ERROR_FAIL; 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; STLINK_V3_TRACE_MAX_HZ : STLINK_TRACE_MAX_HZ;
/* Only concern ourselves with the frequency if the STlink is processing it. */ /* 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", LOG_ERROR("ST-LINK doesn't support SWO frequency higher than %u",
max_trace_freq); max_trace_freq);
return ERROR_FAIL; return ERROR_FAIL;
} }
stlink_usb_trace_disable(h);
if (!*trace_freq) if (!*trace_freq)
*trace_freq = max_trace_freq; *trace_freq = max_trace_freq;
@ -3051,8 +3578,7 @@ static int stlink_config_trace(void *handle, bool enabled,
*prescaler = presc; *prescaler = presc;
if (!enabled) stlink_usb_trace_disable(h);
return ERROR_OK;
h->trace.source_hz = *trace_freq; h->trace.source_hz = *trace_freq;
@ -3152,7 +3678,7 @@ struct hl_layout_api_s stlink_usb_layout_api = {
/** */ /** */
.open = stlink_usb_hl_open, .open = stlink_usb_hl_open,
/** */ /** */
.close = stlink_usb_close, .close = stlink_close,
/** */ /** */
.idcode = stlink_usb_idcode, .idcode = stlink_usb_idcode,
/** */ /** */
@ -3671,6 +4197,32 @@ COMMAND_HANDLER(stlink_dap_vid_pid)
return ERROR_OK; 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[] = { 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", .help = "USB VID and PID of the adapter",
.usage = "(vid pid)+", .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 COMMAND_REGISTRATION_DONE
}; };
@ -3729,7 +4288,7 @@ static int stlink_dap_init(void)
return ERROR_FAIL; 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) if (retval != ERROR_OK)
return retval; return retval;
@ -3749,7 +4308,7 @@ static int stlink_dap_quit(void)
free((void *)stlink_dap_param.serial); free((void *)stlink_dap_param.serial);
stlink_dap_param.serial = NULL; stlink_dap_param.serial = NULL;
return stlink_usb_close(stlink_dap_handle); return stlink_close(stlink_dap_handle);
} }
/** */ /** */

View File

@ -134,13 +134,18 @@ static int load_usb_blaster_firmware(struct libusb_device_handle *libusb_dev,
return ERROR_FAIL; 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 = 0;
ublast2_firmware_image.base_address_set = false; ublast2_firmware_image.base_address_set = false;
int ret = image_open(&ublast2_firmware_image, low->firmware_path, "ihex"); int ret = image_open(&ublast2_firmware_image, low->firmware_path, "ihex");
if (ret != ERROR_OK) { if (ret != ERROR_OK) {
LOG_ERROR("Could not load firmware image"); LOG_ERROR("Could not load firmware image");
return ret; goto error_release_usb;
} }
/** A host loader program must write 0x01 to the CPUCS register /** 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); &ublast2_firmware_image, i);
if (ret != ERROR_OK) { if (ret != ERROR_OK) {
LOG_ERROR("Error while downloading the firmware"); 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, 1,
100); 100);
error_close_firmware:
image_close(&ublast2_firmware_image); 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) 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]; char buffer[5];
jtag_libusb_control_transfer(low->libusb_dev, jtag_libusb_control_transfer(low->libusb_dev,
LIBUSB_REQUEST_TYPE_VENDOR | 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) 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); jtag_libusb_close(low->libusb_dev);
return ERROR_OK; return ERROR_OK;
}; };

View File

@ -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;
}

View File

@ -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 */

View File

@ -34,7 +34,7 @@
#include <jtag/interface.h> #include <jtag/interface.h>
#include <jtag/commands.h> #include <jtag/commands.h>
#include "usb_common.h" #include "libusb_helper.h"
#define VID 0x1781 #define VID 0x1781
#define PID 0x0c63 #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 #define WRITE_TMS_CHAIN 0x0A
struct usbprog_jtag { struct usbprog_jtag {
struct usb_dev_handle *usb_handle; struct libusb_device_handle *usb_handle;
}; };
static struct usbprog_jtag *usbprog_jtag_handle; static struct usbprog_jtag *usbprog_jtag_handle;
@ -350,21 +350,19 @@ struct usb_bus *busses;
struct usbprog_jtag *usbprog_jtag_open(void) struct usbprog_jtag *usbprog_jtag_open(void)
{ {
usb_set_debug(10);
usb_init();
const uint16_t vids[] = { VID, 0 }; const uint16_t vids[] = { VID, 0 };
const uint16_t pids[] = { PID, 0 }; const uint16_t pids[] = { PID, 0 };
struct usb_dev_handle *dev; struct libusb_device_handle *dev;
if (jtag_usb_open(vids, pids, &dev) != ERROR_OK)
if (jtag_libusb_open(vids, pids, NULL, &dev, NULL) != ERROR_OK)
return NULL; return NULL;
struct usbprog_jtag *tmp = malloc(sizeof(struct usbprog_jtag)); struct usbprog_jtag *tmp = malloc(sizeof(struct usbprog_jtag));
tmp->usb_handle = dev; tmp->usb_handle = dev;
usb_set_configuration(dev, 1); libusb_set_configuration(dev, 1);
usb_claim_interface(dev, 0); libusb_claim_interface(dev, 0);
usb_set_altinterface(dev, 0); libusb_set_interface_alt_setting(dev, 0, 0);
return tmp; return tmp;
} }
@ -372,21 +370,23 @@ struct usbprog_jtag *usbprog_jtag_open(void)
#if 0 #if 0
static void usbprog_jtag_close(struct usbprog_jtag *usbprog_jtag) 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); free(usbprog_jtag);
} }
#endif #endif
static unsigned char usbprog_jtag_message(struct usbprog_jtag *usbprog_jtag, char *msg, int msglen) 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) || if ((msg[0] == 2) || (msg[0] == 1) || (msg[0] == 4) || (msg[0] == 0) ||
(msg[0] == 6) || (msg[0] == 0x0A) || (msg[0] == 9)) (msg[0] == 6) || (msg[0] == 0x0A) || (msg[0] == 9))
return 1; return 1;
if (res == msglen) { if (res == ERROR_OK && transferred == msglen) {
/* LOG_INFO("HALLLLOOO %i",(int)msg[0]); */ /* LOG_INFO("HALLLLOOO %i",(int)msg[0]); */
res = usb_bulk_read(usbprog_jtag->usb_handle, 0x82, msg, 2, 100); res = jtag_libusb_bulk_read(usbprog_jtag->usb_handle, 0x82, msg, 2, 100, &transferred);
if (res > 0) if (res == ERROR_OK && transferred > 0)
return (unsigned char)msg[1]; return (unsigned char)msg[1];
else else
return -1; return -1;
@ -428,11 +428,13 @@ static void usbprog_jtag_write_and_read(struct usbprog_jtag *usbprog_jtag, char
bufindex++; 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]); */ /* LOG_INFO("HALLLLOOO2 %i",(int)tmp[0]); */
usleep(1); usleep(1);
int timeout = 0; 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++; timeout++;
if (timeout > 10) if (timeout > 10)
break; 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[1] = (char)(send_bits >> 8); /* high */
tmp[2] = (char)(send_bits); /* low */ 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]); */ /* LOG_INFO("HALLLLOOO3 %i",(int)tmp[0]); */
int timeout = 0; int timeout = 0;
usleep(1); 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++; timeout++;
if (timeout > 10) if (timeout > 10)
break; break;
@ -513,7 +516,8 @@ static void usbprog_jtag_write_tdi(struct usbprog_jtag *usbprog_jtag, char *buff
tmp[3 + i] = buffer[bufindex]; tmp[3 + i] = buffer[bufindex];
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) static void usbprog_jtag_tms_send(struct usbprog_jtag *usbprog_jtag)
{ {
int i;
/* LOG_INFO("TMS SEND"); */ /* LOG_INFO("TMS SEND"); */
if (tms_chain_index > 0) { if (tms_chain_index > 0) {
char tmp[tms_chain_index + 2]; char tmp[tms_chain_index + 2];
tmp[0] = WRITE_TMS_CHAIN; tmp[0] = WRITE_TMS_CHAIN;
tmp[1] = (char)(tms_chain_index); 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]; 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; tms_chain_index = 0;
} }
} }

View File

@ -35,7 +35,7 @@
#include <target/target.h> #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) int hl_interface_open(enum hl_transports tr)
{ {
@ -292,6 +292,31 @@ COMMAND_HANDLER(hl_interface_handle_vid_pid_command)
return ERROR_OK; 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) COMMAND_HANDLER(interface_handle_hla_command)
{ {
if (CMD_ARGC != 1) 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", .help = "the vendor and product ID of the adapter",
.usage = "(vid pid)* ", .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", .name = "hla_command",
.handler = &interface_handle_hla_command, .handler = &interface_handle_hla_command,

View File

@ -46,6 +46,10 @@ struct hl_interface_param_s {
bool connect_under_reset; bool connect_under_reset;
/** Initial interface clock clock speed */ /** Initial interface clock clock speed */
int initial_interface_speed; int initial_interface_speed;
/** */
bool use_stlink_tcp;
/** */
uint16_t stlink_tcp_port;
}; };
struct hl_interface_s { struct hl_interface_s {

View File

@ -27,7 +27,7 @@
#include <jtag/jtag.h> #include <jtag/jtag.h>
#include <jtag/swim.h> #include <jtag/swim.h>
#include <target/armv7m_trace.h> #include <target/arm_tpiu_swo.h>
/* @file /* @file
* The "Cable Helper API" is what the cable drivers can use to help * The "Cable Helper API" is what the cable drivers can use to help

View File

@ -42,11 +42,6 @@
* that contain an adapter_driver structure that can added to this list. * 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 #if BUILD_PARPORT == 1
extern struct adapter_driver parport_adapter_driver; extern struct adapter_driver parport_adapter_driver;
#endif #endif
@ -152,21 +147,12 @@ extern struct adapter_driver stlink_dap_adapter_driver;
#if BUILD_RSHIM == 1 #if BUILD_RSHIM == 1
extern struct adapter_driver rshim_dap_adapter_driver; extern struct adapter_driver rshim_dap_adapter_driver;
#endif #endif
#endif /* standard drivers */
/** /**
* The list of built-in JTAG interfaces, containing entries for those * The list of built-in JTAG interfaces, containing entries for those
* drivers that were enabled by the @c configure script. * 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[] = { 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 #if BUILD_PARPORT == 1
&parport_adapter_driver, &parport_adapter_driver,
#endif #endif
@ -272,6 +258,5 @@ struct adapter_driver *adapter_drivers[] = {
#if BUILD_RSHIM == 1 #if BUILD_RSHIM == 1
&rshim_dap_adapter_driver, &rshim_dap_adapter_driver,
#endif #endif
#endif /* standard drivers */
NULL, NULL,
}; };

View File

@ -47,15 +47,6 @@
typedef enum tap_state { typedef enum tap_state {
TAP_INVALID = -1, 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 */ /* Proper ARM recommended numbers */
TAP_DREXIT2 = 0x0, TAP_DREXIT2 = 0x0,
TAP_DREXIT1 = 0x1, TAP_DREXIT1 = 0x1,
@ -73,8 +64,6 @@ typedef enum tap_state {
TAP_IRUPDATE = 0xd, TAP_IRUPDATE = 0xd,
TAP_IRCAPTURE = 0xe, TAP_IRCAPTURE = 0xe,
TAP_RESET = 0x0f, TAP_RESET = 0x0f,
#endif
} tap_state_t; } tap_state_t;
/** /**
@ -636,9 +625,6 @@ bool jtag_poll_get_enabled(void);
*/ */
void jtag_poll_set_enabled(bool value); 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> #include <jtag/minidriver.h>
int jim_jtag_newtap(Jim_Interp *interp, int argc, Jim_Obj *const *argv); int jim_jtag_newtap(Jim_Interp *interp, int argc, Jim_Obj *const *argv);

View File

@ -45,7 +45,7 @@
/* this header will be provided by the minidriver implementation, */ /* this header will be provided by the minidriver implementation, */
/* and it may provide additional declarations that must be defined. */ /* 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, int interface_jtag_add_ir_scan(struct jtag_tap *active,
const struct scan_field *fields, const struct scan_field *fields,

View File

@ -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 */

View File

@ -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))

View File

@ -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);
}

View File

@ -29,7 +29,7 @@ proc init_reset { mode } {
######### #########
# TODO: power_restore and power_dropout are currently neither # TODO: power_restore and power_dropout are currently neither
# documented nor supported except on ZY1000. # documented nor supported.
proc power_restore {} { proc power_restore {} {
echo "Sensed power restore, running reset init and halting GDB." 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 # TODO: srst_deasserted and srst_asserted are currently neither
# documented nor supported except on ZY1000. # documented nor supported.
proc srst_deasserted {} { proc srst_deasserted {} {
echo "Sensed nSRST deasserted, running reset init and halting GDB." 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 # JTAG-specific names despite the fact that the operations were not
# specific to JTAG, or otherwise had troublesome/misleading names. # 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 { proc jtag_reset args {
echo "DEPRECATED! use 'adapter \[de\]assert' not 'jtag_reset'" echo "DEPRECATED! use 'adapter \[de\]assert' not 'jtag_reset'"
switch $args { 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 { proc adapter_khz args {
echo "DEPRECATED! use 'adapter speed' not 'adapter_khz'" echo "DEPRECATED! use 'adapter speed' not 'adapter_khz'"
eval adapter speed $args eval adapter speed $args

View File

@ -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

View File

@ -30,7 +30,6 @@
#include <jtag/driver.h> #include <jtag/driver.h>
#include <jtag/jtag.h> #include <jtag/jtag.h>
#include <transport/transport.h> #include <transport/transport.h>
#include <helper/ioutil.h>
#include <helper/util.h> #include <helper/util.h>
#include <helper/configuration.h> #include <helper/configuration.h>
#include <flash/nor/core.h> #include <flash/nor/core.h>
@ -38,6 +37,7 @@
#include <pld/pld.h> #include <pld/pld.h>
#include <target/arm_cti.h> #include <target/arm_cti.h>
#include <target/arm_adi_v5.h> #include <target/arm_adi_v5.h>
#include <target/arm_tpiu_swo.h>
#include <rtt/rtt.h> #include <rtt/rtt.h>
#include <server/server.h> #include <server/server.h>
@ -173,6 +173,10 @@ COMMAND_HANDLER(handle_init_command)
return ERROR_FAIL; return ERROR_FAIL;
command_context_mode(CMD_CTX, COMMAND_EXEC); 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 */ /* initialize telnet subsystem */
gdb_target_add_all(all_targets); gdb_target_add_all(all_targets);
@ -255,6 +259,7 @@ static struct command_context *setup_command_handler(Jim_Interp *interp)
&pld_register_commands, &pld_register_commands,
&cti_register_commands, &cti_register_commands,
&dap_register_commands, &dap_register_commands,
&arm_tpiu_swo_register_commands,
NULL NULL
}; };
for (unsigned i = 0; NULL != command_registrants[i]; i++) { 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) if (util_init(cmd_ctx) != ERROR_OK)
return EXIT_FAILURE; return EXIT_FAILURE;
if (ioutil_init(cmd_ctx) != ERROR_OK)
return EXIT_FAILURE;
if (rtt_init() != ERROR_OK) if (rtt_init() != ERROR_OK)
return EXIT_FAILURE; return EXIT_FAILURE;
@ -355,6 +357,7 @@ int openocd_main(int argc, char *argv[])
flash_free_all_banks(); flash_free_all_banks();
gdb_service_free(); gdb_service_free();
arm_tpiu_swo_cleanup_all();
server_free(); server_free();
unregister_all_commands(cmd_ctx, NULL); unregister_all_commands(cmd_ctx, NULL);

View File

@ -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, static int FreeRTOS_get_thread_reg(struct rtos *rtos, threadid_t thread_id,
uint32_t reg_num, struct rtos_reg *reg); 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_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 = { struct rtos_type FreeRTOS_rtos = {
.name = "FreeRTOS", .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); 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; unsigned int i;
*symbol_list = calloc( *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++) { for (i = 0; i < ARRAY_SIZE(FreeRTOS_symbol_list); i++) {
(*symbol_list)[i].symbol_name = FreeRTOS_symbol_list[i].name; (*symbol_list)[i].symbol_name = FreeRTOS_symbol_list[i].name;

View File

@ -39,7 +39,7 @@ static bool ThreadX_detect_rtos(struct target *target);
static int ThreadX_create(struct target *target); static int ThreadX_create(struct target *target);
static int ThreadX_update_threads(struct rtos *rtos); 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_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); 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; unsigned int i;
*symbol_list = calloc( *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++) for (i = 0; i < ARRAY_SIZE(ThreadX_symbol_list); i++)
(*symbol_list)[i].symbol_name = ThreadX_symbol_list[i]; (*symbol_list)[i].symbol_name = ThreadX_symbol_list[i];

View File

@ -107,7 +107,7 @@ static int chibios_create(struct target *target);
static int chibios_update_threads(struct rtos *rtos); static int chibios_update_threads(struct rtos *rtos);
static int chibios_get_thread_reg_list(struct rtos *rtos, int64_t thread_id, static int chibios_get_thread_reg_list(struct rtos *rtos, int64_t thread_id,
struct rtos_reg **reg_list, int *num_regs); 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 = { struct rtos_type chibios_rtos = {
.name = "chibios", .name = "chibios",
@ -131,7 +131,7 @@ enum chibios_symbol_values {
CHIBIOS_VAL_CH_DEBUG = 2 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 */ { "rlist", 0, true}, /* Thread ready list */
{ "ch", 0, true}, /* System data structure */ { "ch", 0, true}, /* System data structure */
{ "ch_debug", 0, false}, /* Memory Signature containing offsets of fields in rlist */ { "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); 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)); *symbol_list = malloc(sizeof(chibios_symbol_list));

View File

@ -360,12 +360,12 @@ static int chromium_ec_get_thread_reg_list(struct rtos *rtos,
stack_ptr, reg_list, num_regs); 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; size_t s;
*symbol_list = calloc(ARRAY_SIZE(chromium_ec_symbol_list), *symbol_list = calloc(ARRAY_SIZE(chromium_ec_symbol_list),
sizeof(symbol_table_elem_t)); sizeof(struct symbol_table_elem));
if (!(*symbol_list)) { if (!(*symbol_list)) {
LOG_ERROR("Chromium-EC: out of memory"); LOG_ERROR("Chromium-EC: out of memory");
return ERROR_FAIL; return ERROR_FAIL;

View File

@ -31,7 +31,7 @@ static bool eCos_detect_rtos(struct target *target);
static int eCos_create(struct target *target); static int eCos_create(struct target *target);
static int eCos_update_threads(struct rtos *rtos); 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_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 { struct eCos_thread_state {
int value; int value;
@ -351,11 +351,11 @@ static int eCos_get_thread_reg_list(struct rtos *rtos, int64_t thread_id,
return -1; 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; unsigned int i;
*symbol_list = calloc( *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++) for (i = 0; i < ARRAY_SIZE(eCos_symbol_list); i++)
(*symbol_list)[i].symbol_name = eCos_symbol_list[i]; (*symbol_list)[i].symbol_name = eCos_symbol_list[i];

View File

@ -36,7 +36,7 @@ static int embKernel_create(struct target *target);
static int embKernel_update_threads(struct rtos *rtos); static int embKernel_update_threads(struct rtos *rtos);
static int embKernel_get_thread_reg_list(struct rtos *rtos, int64_t thread_id, static int embKernel_get_thread_reg_list(struct rtos *rtos, int64_t thread_id,
struct rtos_reg **reg_list, int *num_regs); 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 = { struct rtos_type embKernel_rtos = {
.name = "embKernel", .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); 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; 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++) for (i = 0; i < ARRAY_SIZE(embKernel_symbol_list); i++)
(*symbol_list)[i].symbol_name = embKernel_symbol_list[i]; (*symbol_list)[i].symbol_name = embKernel_symbol_list[i];

View File

@ -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); uint32_t reg_num, struct rtos_reg *rtos_reg);
static int hwthread_get_thread_reg_list(struct rtos *rtos, int64_t thread_id, static int hwthread_get_thread_reg_list(struct rtos *rtos, int64_t thread_id,
struct rtos_reg **reg_list, int *num_regs); 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_smp_init(struct target *target);
static int hwthread_set_reg(struct rtos *rtos, uint32_t reg_num, uint8_t *reg_value); 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); 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); 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 */ /* 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; (*symbol_list)[0].symbol_name = NULL;
return 0; return 0;
} }

View File

@ -246,11 +246,11 @@ static const char * const linux_symbol_list[] = {
NULL 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; unsigned int i;
*symbol_list = (symbol_table_elem_t *) *symbol_list = (struct symbol_table_elem *)
calloc(ARRAY_SIZE(linux_symbol_list), sizeof(symbol_table_elem_t)); calloc(ARRAY_SIZE(linux_symbol_list), sizeof(struct symbol_table_elem));
for (i = 0; i < ARRAY_SIZE(linux_symbol_list); i++) for (i = 0; i < ARRAY_SIZE(linux_symbol_list); i++)
(*symbol_list)[i].symbol_name = linux_symbol_list[i]; (*symbol_list)[i].symbol_name = linux_symbol_list[i];

View File

@ -540,9 +540,9 @@ static int mqx_get_thread_reg_list(
} }
/* API function, export list of required symbols */ /* 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) if (NULL == *symbol_list)
return ERROR_FAIL; return ERROR_FAIL;
/* export required symbols */ /* export required symbols */

View File

@ -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); (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; unsigned int i;
*symbol_list = (symbol_table_elem_t *) calloc(1, *symbol_list = (struct symbol_table_elem *) calloc(1,
sizeof(symbol_table_elem_t) * ARRAY_SIZE(nuttx_symbol_list)); sizeof(struct symbol_table_elem) * ARRAY_SIZE(nuttx_symbol_list));
for (i = 0; i < ARRAY_SIZE(nuttx_symbol_list); i++) for (i = 0; i < ARRAY_SIZE(nuttx_symbol_list); i++)
(*symbol_list)[i].symbol_name = nuttx_symbol_list[i]; (*symbol_list)[i].symbol_name = nuttx_symbol_list[i];

View File

@ -35,7 +35,7 @@ static int riot_create(struct target *target);
static int riot_update_threads(struct rtos *rtos); static int riot_update_threads(struct rtos *rtos);
static int riot_get_thread_reg_list(struct rtos *rtos, int64_t thread_id, static int riot_get_thread_reg_list(struct rtos *rtos, int64_t thread_id,
struct rtos_reg **reg_list, int *num_regs); 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 { struct riot_thread_state {
int value; int value;
@ -360,9 +360,9 @@ static int riot_get_thread_reg_list(struct rtos *rtos, int64_t thread_id,
num_regs); 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) { if (*symbol_list == NULL) {
LOG_ERROR("RIOT: out of memory"); LOG_ERROR("RIOT: out of memory");

View File

@ -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); 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) if (!os->symbols)
os->type->get_symbol_list_to_lookup(&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 */ * if 'symbol' is not declared optional */
static bool is_symbol_mandatory(const struct rtos *os, const char *symbol) 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)) if (!strcmp(s->symbol_name, symbol))
return !s->optional; return !s->optional;
} }
@ -240,7 +240,7 @@ int rtos_qsymbol(struct connection *connection, char const *packet, int packet_s
uint64_t addr = 0; uint64_t addr = 0;
size_t reply_len; size_t reply_len;
char reply[GDB_BUFFER_SIZE + 1], cur_sym[GDB_BUFFER_SIZE / 2 + 1] = ""; /* Extra byte for null-termination */ 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 target *target = get_target_from_connection(connection);
struct rtos *os = target->rtos; struct rtos *os = target->rtos;

View File

@ -31,11 +31,11 @@ struct reg;
/** /**
* Table should be terminated by an element with NULL in symbol_name * 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; const char *symbol_name;
symbol_address_t address; symbol_address_t address;
bool optional; bool optional;
} symbol_table_elem_t; };
struct thread_detail { struct thread_detail {
threadid_t threadid; threadid_t threadid;
@ -47,7 +47,7 @@ struct thread_detail {
struct rtos { struct rtos {
const struct rtos_type *type; const struct rtos_type *type;
symbol_table_elem_t *symbols; struct symbol_table_elem *symbols;
struct target *target; struct target *target;
/* add a context variable instead of global variable */ /* add a context variable instead of global variable */
/* The thread currently selected by gdb. */ /* The thread currently selected by gdb. */
@ -81,7 +81,7 @@ struct rtos_type {
struct rtos_reg **reg_list, int *num_regs); struct rtos_reg **reg_list, int *num_regs);
int (*get_thread_reg)(struct rtos *rtos, threadid_t thread_id, int (*get_thread_reg)(struct rtos *rtos, threadid_t thread_id,
uint32_t reg_num, struct rtos_reg *reg); 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); int (*clean)(struct target *target);
char * (*ps_command)(struct target *target); char * (*ps_command)(struct target *target);
int (*set_reg)(struct rtos *rtos, uint32_t reg_num, uint8_t *reg_value); int (*set_reg)(struct rtos *rtos, uint32_t reg_num, uint8_t *reg_value);

View File

@ -508,9 +508,9 @@ static int uCOS_III_get_thread_reg_list(struct rtos *rtos, threadid_t threadid,
num_regs); 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) { if (*symbol_list == NULL) {
LOG_ERROR("uCOS-III: out of memory"); LOG_ERROR("uCOS-III: out of memory");
return ERROR_FAIL; return ERROR_FAIL;

View File

@ -726,7 +726,7 @@ static void gdb_signal_reply(struct target *target, struct connection *connectio
{ {
struct gdb_connection *gdb_connection = connection->priv; struct gdb_connection *gdb_connection = connection->priv;
char sig_reply[65]; char sig_reply[65];
char stop_reason[20]; char stop_reason[32];
char current_thread[25]; char current_thread[25];
int sig_reply_len; int sig_reply_len;
int signal_var; int signal_var;
@ -3617,7 +3617,7 @@ static int gdb_target_start(struct target *target, const char *port)
ret = add_service("gdb", ret = add_service("gdb",
port, target->gdb_max_connections, &gdb_new_connection, &gdb_input, 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 */ /* initialize all targets gdb service with the same pointer */
{ {
struct target_list *head; struct target_list *head;

View File

@ -126,7 +126,7 @@ COMMAND_HANDLER(handle_rtt_start_command)
COMMAND_PARSE_NUMBER(uint, CMD_ARGV[1], service->channel); COMMAND_PARSE_NUMBER(uint, CMD_ARGV[1], service->channel);
ret = add_service("rtt", CMD_ARGV[0], CONNECTION_LIMIT_UNLIMITED, 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) { if (ret != ERROR_OK) {
free(service); free(service);

View File

@ -211,8 +211,7 @@ int add_service(char *name,
new_connection_handler_t new_connection_handler, new_connection_handler_t new_connection_handler,
input_handler_t input_handler, input_handler_t input_handler,
connection_closed_handler_t connection_closed_handler, connection_closed_handler_t connection_closed_handler,
void *priv, void *priv)
struct service **new_service)
{ {
struct service *c, **p; struct service *c, **p;
struct hostent *hp; struct hostent *hp;
@ -348,10 +347,6 @@ int add_service(char *name,
; ;
*p = c; *p = c;
/* if new_service is not NULL, return the created service into it */
if (new_service)
*new_service = c;
return ERROR_OK; return ERROR_OK;
} }

View File

@ -78,7 +78,7 @@ struct service {
int add_service(char *name, const char *port, int add_service(char *name, const char *port,
int max_connections, new_connection_handler_t new_connection_handler, int max_connections, new_connection_handler_t new_connection_handler,
input_handler_t in_handler, connection_closed_handler_t close_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 remove_service(const char *name, const char *port);
int server_host_os_entry(void); int server_host_os_entry(void);

View File

@ -285,7 +285,7 @@ int tcl_init(void)
return add_service("tcl", tcl_port, CONNECTION_LIMIT_UNLIMITED, return add_service("tcl", tcl_port, CONNECTION_LIMIT_UNLIMITED,
&tcl_new_connection, &tcl_input, &tcl_new_connection, &tcl_input,
&tcl_closed, NULL, NULL); &tcl_closed, NULL);
} }
COMMAND_HANDLER(handle_tcl_port_command) COMMAND_HANDLER(handle_tcl_port_command)

View File

@ -596,6 +596,12 @@ static int telnet_input(struct connection *connection)
telnet_history_up(connection); telnet_history_up(connection);
} else if (*buf_p == 'B') { /* cursor down */ } else if (*buf_p == 'B') { /* cursor down */
telnet_history_down(connection); 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') } else if (*buf_p == '3')
t_con->last_escape = *buf_p; t_con->last_escape = *buf_p;
else else
@ -694,7 +700,7 @@ int telnet_init(char *banner)
int ret = add_service("telnet", telnet_port, CONNECTION_LIMIT_UNLIMITED, int ret = add_service("telnet", telnet_port, CONNECTION_LIMIT_UNLIMITED,
telnet_new_connection, telnet_input, telnet_connection_closed, telnet_new_connection, telnet_input, telnet_connection_closed,
telnet_service, NULL); telnet_service);
if (ret != ERROR_OK) { if (ret != ERROR_OK) {
free(telnet_service); free(telnet_service);

View File

@ -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 \ %C%_libtarget_la_LIBADD = %D%/openrisc/libopenrisc.la \
%D%/riscv/libriscv.la %D%/riscv/libriscv.la
@ -111,8 +105,8 @@ ARM_DEBUG_SRC = \
%D%/trace.c \ %D%/trace.c \
%D%/etb.c \ %D%/etb.c \
%D%/etm.c \ %D%/etm.c \
$(OOCD_TRACE_FILES) \
%D%/etm_dummy.c \ %D%/etm_dummy.c \
%D%/arm_tpiu_swo.c \
%D%/arm_cti.c %D%/arm_cti.c
AVR32_SRC = \ AVR32_SRC = \
@ -214,6 +208,7 @@ ARC_SRC = \
%D%/etb.h \ %D%/etb.h \
%D%/etm.h \ %D%/etm.h \
%D%/etm_dummy.h \ %D%/etm_dummy.h \
%D%/arm_tpiu_swo.h \
%D%/image.h \ %D%/image.h \
%D%/mips32.h \ %D%/mips32.h \
%D%/mips64.h \ %D%/mips64.h \
@ -223,7 +218,6 @@ ARC_SRC = \
%D%/mips32_pracc.h \ %D%/mips32_pracc.h \
%D%/mips32_dmaacc.h \ %D%/mips32_dmaacc.h \
%D%/mips64_pracc.h \ %D%/mips64_pracc.h \
%D%/oocd_trace.h \
%D%/register.h \ %D%/register.h \
%D%/target.h \ %D%/target.h \
%D%/target_type.h \ %D%/target_type.h \

View File

@ -1651,7 +1651,6 @@ static int aarch64_add_hybrid_breakpoint(struct target *target,
return aarch64_set_hybrid_breakpoint(target, breakpoint); /* ??? */ return aarch64_set_hybrid_breakpoint(target, breakpoint); /* ??? */
} }
static int aarch64_remove_breakpoint(struct target *target, struct breakpoint *breakpoint) static int aarch64_remove_breakpoint(struct target *target, struct breakpoint *breakpoint)
{ {
struct aarch64_common *aarch64 = target_to_aarch64(target); struct aarch64_common *aarch64 = target_to_aarch64(target);
@ -1673,25 +1672,306 @@ static int aarch64_remove_breakpoint(struct target *target, struct breakpoint *b
return ERROR_OK; 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 * 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) static int aarch64_assert_reset(struct target *target)
{ {
struct armv8_common *armv8 = target_to_armv8(target); struct armv8_common *armv8 = target_to_armv8(target);
enum reset_types reset_config = jtag_get_reset_config();
int retval;
LOG_DEBUG(" "); LOG_DEBUG(" ");
/* FIXME when halt is requested, make it work somehow... */
/* Issue some kind of warm reset. */ /* Issue some kind of warm reset. */
if (target_has_event_action(target, TARGET_EVENT_RESET_ASSERT)) if (target_has_event_action(target, TARGET_EVENT_RESET_ASSERT))
target_handle_event(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 /* REVISIT handle "pulls" cases, if there's
* hardware that needs them to work. * hardware that needs them to work.
*/ */
if (!srst_asserted)
adapter_assert_reset(); adapter_assert_reset();
} else { } else {
LOG_ERROR("%s: how to reset?", target_name(target)); LOG_ERROR("%s: how to reset?", target_name(target));
@ -1721,23 +2001,37 @@ static int aarch64_deassert_reset(struct target *target)
if (!target_was_examined(target)) if (!target_was_examined(target))
return ERROR_OK; return ERROR_OK;
retval = aarch64_poll(target);
if (retval != ERROR_OK)
return retval;
retval = aarch64_init_debug_access(target); retval = aarch64_init_debug_access(target);
if (retval != ERROR_OK) if (retval != ERROR_OK)
return retval; return retval;
retval = aarch64_poll(target);
if (retval != ERROR_OK)
return retval;
if (target->reset_halt) { 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) { if (target->state != TARGET_HALTED) {
LOG_WARNING("%s: ran after reset and before halt ...", LOG_WARNING("%s: ran after reset and before halt ...",
target_name(target)); target_name(target));
retval = target_halt(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, 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; 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->state = TARGET_UNKNOWN;
target->debug_reason = DBG_REASON_NOTHALTED; target->debug_reason = DBG_REASON_NOTHALTED;
@ -2883,8 +3190,9 @@ struct target_type aarch64_target = {
.add_context_breakpoint = aarch64_add_context_breakpoint, .add_context_breakpoint = aarch64_add_context_breakpoint,
.add_hybrid_breakpoint = aarch64_add_hybrid_breakpoint, .add_hybrid_breakpoint = aarch64_add_hybrid_breakpoint,
.remove_breakpoint = aarch64_remove_breakpoint, .remove_breakpoint = aarch64_remove_breakpoint,
.add_watchpoint = NULL, .add_watchpoint = aarch64_add_watchpoint,
.remove_watchpoint = NULL, .remove_watchpoint = aarch64_remove_watchpoint,
.hit_watchpoint = aarch64_hit_watchpoint,
.commands = aarch64_command_handlers, .commands = aarch64_command_handlers,
.target_create = aarch64_target_create, .target_create = aarch64_target_create,

View File

@ -62,6 +62,11 @@ struct aarch64_common {
int brp_num_available; int brp_num_available;
struct aarch64_brp *brp_list; 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; struct armv8_common armv8_common;
enum aarch64_isrmasking_mode isrmasking_mode; enum aarch64_isrmasking_mode isrmasking_mode;

View File

@ -227,7 +227,7 @@ static int arc_get_register(struct reg *reg)
if (desc->is_core) { if (desc->is_core) {
/* Accessing to R61/R62 registers causes Jtag hang */ /* 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."); LOG_ERROR("It is forbidden to read core registers 61 and 62.");
return ERROR_FAIL; return ERROR_FAIL;
} }
@ -267,8 +267,8 @@ static int arc_set_register(struct reg *reg, uint8_t *buf)
return ERROR_TARGET_NOT_HALTED; return ERROR_TARGET_NOT_HALTED;
/* Accessing to R61/R62 registers causes Jtag hang */ /* Accessing to R61/R62 registers causes Jtag hang */
if (desc->is_core && (desc->arch_num == CORE_R61_NUM || if (desc->is_core && (desc->arch_num == ARC_R61 ||
desc->arch_num == CORE_R62_NUM)) { desc->arch_num == ARC_R62)) {
LOG_ERROR("It is forbidden to write core registers 61 and 62."); LOG_ERROR("It is forbidden to write core registers 61 and 62.");
return ERROR_FAIL; return ERROR_FAIL;
} }

View File

@ -45,9 +45,52 @@
#define AUX_STATUS32_REG_HALT_BIT BIT(0) #define AUX_STATUS32_REG_HALT_BIT BIT(0)
#define AUX_STATUS32_REG_IE_BIT BIT(31) /* STATUS32[31] = IE field */ #define AUX_STATUS32_REG_IE_BIT BIT(31) /* STATUS32[31] = IE field */
/* Reserved core registers */ /* ARC register numbers */
#define CORE_R61_NUM (61) enum {
#define CORE_R62_NUM (62) 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) #define CORE_REG_MAX_NUMBER (63)

View File

@ -382,7 +382,7 @@ static int jim_arc_get_core_reg(Jim_Interp *interp, int argc, Jim_Obj * const *a
/* Register number */ /* Register number */
JIM_CHECK_RETVAL(arc_cmd_jim_get_uint32(&goi, &regnum)); JIM_CHECK_RETVAL(arc_cmd_jim_get_uint32(&goi, &regnum));
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 " Jim_SetResultFormatted(goi.interp, "Core register number %i "
"is invalid. Must less then 64 and not 61 and 62.", regnum); "is invalid. Must less then 64 and not 61 and 62.", regnum);
return JIM_ERR; 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 */ /* Register number */
JIM_CHECK_RETVAL(arc_cmd_jim_get_uint32(&goi, &regnum)); JIM_CHECK_RETVAL(arc_cmd_jim_get_uint32(&goi, &regnum));
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 " Jim_SetResultFormatted(goi.interp, "Core register number %i "
"is invalid. Must less then 64 and not 61 and 62.", regnum); "is invalid. Must less then 64 and not 61 and 62.", regnum);
return JIM_ERR; return JIM_ERR;

View File

@ -562,11 +562,7 @@ static const tap_state_t arm11_MOVE_DRPAUSE_IDLE_DRPAUSE_with_delay[] = {
TAP_DRSHIFT TAP_DRSHIFT
}; };
/* This inner loop can be implemented by the minidriver, oftentimes in hardware... The static int arm11_run_instr_data_to_core_noack_inner(struct jtag_tap *tap,
* 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,
uint32_t opcode, uint32_t opcode,
uint32_t *data, uint32_t *data,
size_t count) size_t count)
@ -629,21 +625,6 @@ int arm11_run_instr_data_to_core_noack_inner_default(struct jtag_tap *tap,
return retval; 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 /** Execute one instruction via ITR repeatedly while
* passing data to the core via DTR on each execution. * passing data to the core via DTR on each execution.
* *

View File

@ -233,16 +233,6 @@ static void arm720t_pre_restore_context(struct target *target)
arm720t_write_cp15(target, 0xee060f10, arm720t->far_reg); 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) static int arm720t_arch_state(struct target *target)
{ {
struct arm720t_common *arm720t = target_to_arm720(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); 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, static int arm720t_mrc(struct target *target, int cpnum,
uint32_t op1, uint32_t op2, uint32_t op1, uint32_t op2,
uint32_t CRn, uint32_t CRm, uint32_t CRn, uint32_t CRm,
@ -523,30 +464,10 @@ static int arm720t_mcr(struct target *target, int cpnum,
value); 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[] = { static const struct command_registration arm720t_command_handlers[] = {
{ {
.chain = arm7_9_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 COMMAND_REGISTRATION_DONE
}; };

View File

@ -245,8 +245,8 @@ static int arm920t_read_cp15_interpreted(struct target *target,
uint32_t cp15_opcode, uint32_t address, uint32_t *value) uint32_t cp15_opcode, uint32_t address, uint32_t *value)
{ {
struct arm *arm = target_to_arm(target); struct arm *arm = target_to_arm(target);
uint32_t *regs_p[1]; uint32_t *regs_p[16];
uint32_t regs[2]; uint32_t regs[16];
uint32_t cp15c15 = 0x0; uint32_t cp15c15 = 0x0;
struct reg *r = arm->core_cache->reg_list; struct reg *r = arm->core_cache->reg_list;
@ -295,7 +295,7 @@ int arm920t_write_cp15_interpreted(struct target *target,
{ {
uint32_t cp15c15 = 0x0; uint32_t cp15c15 = 0x0;
struct arm *arm = target_to_arm(target); struct arm *arm = target_to_arm(target);
uint32_t regs[2]; uint32_t regs[16];
struct reg *r = arm->core_cache->reg_list; struct reg *r = arm->core_cache->reg_list;
/* load value, address into R0, R1 */ /* load value, address into R0, R1 */
@ -1511,80 +1511,6 @@ COMMAND_HANDLER(arm920t_handle_cp15_command)
return ERROR_OK; 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) COMMAND_HANDLER(arm920t_handle_cache_info_command)
{ {
int retval; int retval;
@ -1640,15 +1566,6 @@ static const struct command_registration arm920t_exec_command_handlers[] = {
.help = "display/modify cp15 register", .help = "display/modify cp15 register",
.usage = "regnum [value]", .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", .name = "cache_info",
.handler = arm920t_handle_cache_info_command, .handler = arm920t_handle_cache_info_command,

View File

@ -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); 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); buf_set_u64(arm->pc->value, 0, 64, pc + 4);
arm->pc->dirty = true; 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 { } else {
/* resume execution, this will be pc+2 to skip over the /* 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) if (target->debug_reason != DBG_REASON_BREAKPOINT)
return 0; 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) { if (arm->core_state == ARM_STATE_AARCH64) {
uint32_t insn = 0; uint32_t insn = 0;
r = arm->pc; r = arm->pc;
@ -284,9 +310,38 @@ int arm_semihosting(struct target *target, int *retval)
if (*retval != ERROR_OK) if (*retval != ERROR_OK)
return 1; return 1;
/* bkpt 0xAB */ /* HLT 0xF000 */
if (insn != 0xD45E0000) if (insn != 0xD45E0000)
return 0; 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 } else
return 1; return 1;
} else { } else {

1189
src/target/arm_tpiu_swo.c Normal file

File diff suppressed because it is too large Load Diff

21
src/target/arm_tpiu_swo.h Normal file
View File

@ -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 */

View File

@ -166,10 +166,10 @@ int armv7m_restore_context(struct target *target)
* packing of ARMV7M_PMSK_BPRI_FLTMSK_CTRL! * packing of ARMV7M_PMSK_BPRI_FLTMSK_CTRL!
* See also comments in the register table above */ * See also comments in the register table above */
for (i = cache->num_regs - 1; i >= 0; i--) { for (i = cache->num_regs - 1; i >= 0; i--) {
if (cache->reg_list[i].dirty) { struct reg *r = &cache->reg_list[i];
armv7m->arm.write_core_reg(target, &cache->reg_list[i], i,
ARM_MODE_ANY, cache->reg_list[i].value); if (r->exist && r->dirty)
} armv7m->arm.write_core_reg(target, r, i, ARM_MODE_ANY, r->value);
} }
return ERROR_OK; return ERROR_OK;

Some files were not shown because too many files have changed in this diff Show More