Merge commit '05ee88915520d1dd82da94a016a9374a1f3a8129' into from_upstream

Conflicts:
	src/jtag/drivers/xds110.c
	src/target/riscv/riscv.c
	src/target/riscv/riscv_semihosting.c
	tcl/target/esp_common.cfg

Change-Id: If0c02817df03b7fd700cc84b4da2c02d36737d28
This commit is contained in:
Tim Newsome 2023-11-03 10:43:48 -07:00
commit b5bd88441c
152 changed files with 9261 additions and 728 deletions

503
LICENSES/preferred/LGPL-2.1 Normal file
View File

@ -0,0 +1,503 @@
Valid-License-Identifier: LGPL-2.1-only
Valid-License-Identifier: LGPL-2.1-or-later
SPDX-URL: https://spdx.org/licenses/LGPL-2.1.html
Usage-Guide:
To use this license in source code, put one of the following SPDX
tag/value pairs into a comment according to the placement
guidelines in the licensing rules documentation.
For 'GNU Lesser General Public License (LGPL) version 2.1 only' use:
SPDX-License-Identifier: LGPL-2.1-only
For 'GNU Lesser General Public License (LGPL) version 2.1 or any later
version' use:
SPDX-License-Identifier: LGPL-2.1-or-later
License-Text:
GNU LESSER GENERAL PUBLIC LICENSE
Version 2.1, February 1999
Copyright (C) 1991, 1999 Free Software Foundation, Inc.
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies of this
license document, but changing it is not allowed.
[This is the first released version of the Lesser GPL. It also counts as
the successor of the GNU Library Public License, version 2, hence the
version number 2.1.]
Preamble
The licenses for most software are designed to take away your freedom to
share and change it. By contrast, the GNU General Public Licenses are
intended to guarantee your freedom to share and change free software--to
make sure the software is free for all its users.
This license, the Lesser General Public License, applies to some specially
designated software packages--typically libraries--of the Free Software
Foundation and other authors who decide to use it. You can use it too, but
we suggest you first think carefully about whether this license or the
ordinary General Public License is the better strategy to use in any
particular case, based on the explanations below.
When we speak of free software, we are referring to freedom of use, not
price. Our General Public Licenses are designed to make sure that you have
the freedom to distribute copies of free software (and charge for this
service if you wish); that you receive source code or can get it if you
want it; that you can change the software and use pieces of it in new free
programs; and that you are informed that you can do these things.
To protect your rights, we need to make restrictions that forbid
distributors to deny you these rights or to ask you to surrender these
rights. These restrictions translate to certain responsibilities for you if
you distribute copies of the library or if you modify it.
For example, if you distribute copies of the library, whether gratis or for
a fee, you must give the recipients all the rights that we gave you. You
must make sure that they, too, receive or can get the source code. If you
link other code with the library, you must provide complete object files to
the recipients, so that they can relink them with the library after making
changes to the library and recompiling it. And you must show them these
terms so they know their rights.
We protect your rights with a two-step method: (1) we copyright the
library, and (2) we offer you this license, which gives you legal
permission to copy, distribute and/or modify the library.
To protect each distributor, we want to make it very clear that there is no
warranty for the free library. Also, if the library is modified by someone
else and passed on, the recipients should know that what they have is not
the original version, so that the original author's reputation will not be
affected by problems that might be introduced by others.
Finally, software patents pose a constant threat to the existence of any
free program. We wish to make sure that a company cannot effectively
restrict the users of a free program by obtaining a restrictive license
from a patent holder. Therefore, we insist that any patent license obtained
for a version of the library must be consistent with the full freedom of
use specified in this license.
Most GNU software, including some libraries, is covered by the ordinary GNU
General Public License. This license, the GNU Lesser General Public
License, applies to certain designated libraries, and is quite different
from the ordinary General Public License. We use this license for certain
libraries in order to permit linking those libraries into non-free
programs.
When a program is linked with a library, whether statically or using a
shared library, the combination of the two is legally speaking a combined
work, a derivative of the original library. The ordinary General Public
License therefore permits such linking only if the entire combination fits
its criteria of freedom. The Lesser General Public License permits more lax
criteria for linking other code with the library.
We call this license the "Lesser" General Public License because it does
Less to protect the user's freedom than the ordinary General Public
License. It also provides other free software developers Less of an
advantage over competing non-free programs. These disadvantages are the
reason we use the ordinary General Public License for many
libraries. However, the Lesser license provides advantages in certain
special circumstances.
For example, on rare occasions, there may be a special need to encourage
the widest possible use of a certain library, so that it becomes a de-facto
standard. To achieve this, non-free programs must be allowed to use the
library. A more frequent case is that a free library does the same job as
widely used non-free libraries. In this case, there is little to gain by
limiting the free library to free software only, so we use the Lesser
General Public License.
In other cases, permission to use a particular library in non-free programs
enables a greater number of people to use a large body of free
software. For example, permission to use the GNU C Library in non-free
programs enables many more people to use the whole GNU operating system, as
well as its variant, the GNU/Linux operating system.
Although the Lesser General Public License is Less protective of the users'
freedom, it does ensure that the user of a program that is linked with the
Library has the freedom and the wherewithal to run that program using a
modified version of the Library.
The precise terms and conditions for copying, distribution and modification
follow. Pay close attention to the difference between a "work based on the
library" and a "work that uses the library". The former contains code
derived from the library, whereas the latter must be combined with the
library in order to run.
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License Agreement applies to any software library or other program
which contains a notice placed by the copyright holder or other
authorized party saying it may be distributed under the terms of this
Lesser General Public License (also called "this License"). Each
licensee is addressed as "you".
A "library" means a collection of software functions and/or data
prepared so as to be conveniently linked with application programs
(which use some of those functions and data) to form executables.
The "Library", below, refers to any such software library or work which
has been distributed under these terms. A "work based on the Library"
means either the Library or any derivative work under copyright law:
that is to say, a work containing the Library or a portion of it, either
verbatim or with modifications and/or translated straightforwardly into
another language. (Hereinafter, translation is included without
limitation in the term "modification".)
"Source code" for a work means the preferred form of the work for making
modifications to it. For a library, complete source code means all the
source code for all modules it contains, plus any associated interface
definition files, plus the scripts used to control compilation and
installation of the library.
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of running
a program using the Library is not restricted, and output from such a
program is covered only if its contents constitute a work based on the
Library (independent of the use of the Library in a tool for writing
it). Whether that is true depends on what the Library does and what the
program that uses the Library does.
1. You may copy and distribute verbatim copies of the Library's complete
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the notices
that refer to this License and to the absence of any warranty; and
distribute a copy of this License along with the Library.
You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Library or any portion of it,
thus forming a work based on the Library, and copy and distribute such
modifications or work under the terms of Section 1 above, provided that
you also meet all of these conditions:
a) The modified work must itself be a software library.
b) You must cause the files modified to carry prominent notices stating
that you changed the files and the date of any change.
c) You must cause the whole of the work to be licensed at no charge to
all third parties under the terms of this License.
d) If a facility in the modified Library refers to a function or a table
of data to be supplied by an application program that uses the
facility, other than as an argument passed when the facility is
invoked, then you must make a good faith effort to ensure that, in
the event an application does not supply such function or table, the
facility still operates, and performs whatever part of its purpose
remains meaningful.
(For example, a function in a library to compute square roots has a
purpose that is entirely well-defined independent of the
application. Therefore, Subsection 2d requires that any
application-supplied function or table used by this function must be
optional: if the application does not supply it, the square root
function must still compute square roots.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Library, and
can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based on
the Library, the distribution of the whole must be on the terms of this
License, whose permissions for other licensees extend to the entire
whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Library.
In addition, mere aggregation of another work not based on the Library
with the Library (or with a work based on the Library) on a volume of a
storage or distribution medium does not bring the other work under the
scope of this License.
3. You may opt to apply the terms of the ordinary GNU General Public
License instead of this License to a given copy of the Library. To do
this, you must alter all the notices that refer to this License, so that
they refer to the ordinary GNU General Public License, version 2,
instead of to this License. (If a newer version than version 2 of the
ordinary GNU General Public License has appeared, then you can specify
that version instead if you wish.) Do not make any other change in these
notices.
Once this change is made in a given copy, it is irreversible for that
copy, so the ordinary GNU General Public License applies to all
subsequent copies and derivative works made from that copy.
This option is useful when you wish to copy part of the code of the
Library into a program that is not a library.
4. You may copy and distribute the Library (or a portion or derivative of
it, under Section 2) in object code or executable form under the terms
of Sections 1 and 2 above provided that you accompany it with the
complete corresponding machine-readable source code, which must be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange.
If distribution of object code is made by offering access to copy from a
designated place, then offering equivalent access to copy the source
code from the same place satisfies the requirement to distribute the
source code, even though third parties are not compelled to copy the
source along with the object code.
5. A program that contains no derivative of any portion of the Library, but
is designed to work with the Library by being compiled or linked with
it, is called a "work that uses the Library". Such a work, in isolation,
is not a derivative work of the Library, and therefore falls outside the
scope of this License.
However, linking a "work that uses the Library" with the Library creates
an executable that is a derivative of the Library (because it contains
portions of the Library), rather than a "work that uses the
library". The executable is therefore covered by this License. Section 6
states terms for distribution of such executables.
When a "work that uses the Library" uses material from a header file
that is part of the Library, the object code for the work may be a
derivative work of the Library even though the source code is
not. Whether this is true is especially significant if the work can be
linked without the Library, or if the work is itself a library. The
threshold for this to be true is not precisely defined by law.
If such an object file uses only numerical parameters, data structure
layouts and accessors, and small macros and small inline functions (ten
lines or less in length), then the use of the object file is
unrestricted, regardless of whether it is legally a derivative
work. (Executables containing this object code plus portions of the
Library will still fall under Section 6.)
Otherwise, if the work is a derivative of the Library, you may
distribute the object code for the work under the terms of Section
6. Any executables containing that work also fall under Section 6,
whether or not they are linked directly with the Library itself.
6. As an exception to the Sections above, you may also combine or link a
"work that uses the Library" with the Library to produce a work
containing portions of the Library, and distribute that work under terms
of your choice, provided that the terms permit modification of the work
for the customer's own use and reverse engineering for debugging such
modifications.
You must give prominent notice with each copy of the work that the
Library is used in it and that the Library and its use are covered by
this License. You must supply a copy of this License. If the work during
execution displays copyright notices, you must include the copyright
notice for the Library among them, as well as a reference directing the
user to the copy of this License. Also, you must do one of these things:
a) Accompany the work with the complete corresponding machine-readable
source code for the Library including whatever changes were used in
the work (which must be distributed under Sections 1 and 2 above);
and, if the work is an executable linked with the Library, with the
complete machine-readable "work that uses the Library", as object
code and/or source code, so that the user can modify the Library and
then relink to produce a modified executable containing the modified
Library. (It is understood that the user who changes the contents of
definitions files in the Library will not necessarily be able to
recompile the application to use the modified definitions.)
b) Use a suitable shared library mechanism for linking with the
Library. A suitable mechanism is one that (1) uses at run time a copy
of the library already present on the user's computer system, rather
than copying library functions into the executable, and (2) will
operate properly with a modified version of the library, if the user
installs one, as long as the modified version is interface-compatible
with the version that the work was made with.
c) Accompany the work with a written offer, valid for at least three
years, to give the same user the materials specified in Subsection
6a, above, for a charge no more than the cost of performing this
distribution.
d) If distribution of the work is made by offering access to copy from a
designated place, offer equivalent access to copy the above specified
materials from the same place.
e) Verify that the user has already received a copy of these materials
or that you have already sent this user a copy.
For an executable, the required form of the "work that uses the Library"
must include any data and utility programs needed for reproducing the
executable from it. However, as a special exception, the materials to be
distributed need not include anything that is normally distributed (in
either source or binary form) with the major components (compiler,
kernel, and so on) of the operating system on which the executable runs,
unless that component itself accompanies the executable.
It may happen that this requirement contradicts the license restrictions
of other proprietary libraries that do not normally accompany the
operating system. Such a contradiction means you cannot use both them
and the Library together in an executable that you distribute.
7. You may place library facilities that are a work based on the Library
side-by-side in a single library together with other library facilities
not covered by this License, and distribute such a combined library,
provided that the separate distribution of the work based on the Library
and of the other library facilities is otherwise permitted, and provided
that you do these two things:
a) Accompany the combined library with a copy of the same work based on
the Library, uncombined with any other library facilities. This must
be distributed under the terms of the Sections above.
b) Give prominent notice with the combined library of the fact that part
of it is a work based on the Library, and explaining where to find
the accompanying uncombined form of the same work.
8. You may not copy, modify, sublicense, link with, or distribute the
Library except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense, link with, or distribute the
Library is void, and will automatically terminate your rights under this
License. However, parties who have received copies, or rights, from you
under this License will not have their licenses terminated so long as
such parties remain in full compliance.
9. You are not required to accept this License, since you have not signed
it. However, nothing else grants you permission to modify or distribute
the Library or its derivative works. These actions are prohibited by law
if you do not accept this License. Therefore, by modifying or
distributing the Library (or any work based on the Library), you
indicate your acceptance of this License to do so, and all its terms and
conditions for copying, distributing or modifying the Library or works
based on it.
10. Each time you redistribute the Library (or any work based on the
Library), the recipient automatically receives a license from the
original licensor to copy, distribute, link with or modify the Library
subject to these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted
herein. You are not responsible for enforcing compliance by third
parties with this License.
11. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Library at all. For example, if a patent license
would not permit royalty-free redistribution of the Library by all
those who receive copies directly or indirectly through you, then the
only way you could satisfy both it and this License would be to refrain
entirely from distribution of the Library.
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply, and the section as a whole is intended to apply in other
circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system which is implemented
by public license practices. Many people have made generous
contributions to the wide range of software distributed through that
system in reliance on consistent application of that system; it is up
to the author/donor to decide if he or she is willing to distribute
software through any other system and a licensee cannot impose that
choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
12. If the distribution and/or use of the Library is restricted in certain
countries either by patents or by copyrighted interfaces, the original
copyright holder who places the Library under this License may add an
explicit geographical distribution limitation excluding those
countries, so that distribution is permitted only in or among countries
not thus excluded. In such case, this License incorporates the
limitation as if written in the body of this License.
13. The Free Software Foundation may publish revised and/or new versions of
the Lesser General Public License from time to time. Such new versions
will be similar in spirit to the present version, but may differ in
detail to address new problems or concerns.
Each version is given a distinguishing version number. If the Library
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and
conditions either of that version or of any later version published by
the Free Software Foundation. If the Library does not specify a license
version number, you may choose any version ever published by the Free
Software Foundation.
14. If you wish to incorporate parts of the Library into other free
programs whose distribution conditions are incompatible with these,
write to the author to ask for permission. For software which is
copyrighted by the Free Software Foundation, write to the Free Software
Foundation; we sometimes make exceptions for this. Our decision will be
guided by the two goals of preserving the free status of all
derivatives of our free software and of promoting the sharing and reuse
of software generally.
NO WARRANTY
15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE
ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE LIBRARY IS WITH
YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL
NECESSARY SERVICING, REPAIR OR CORRECTION.
16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU FOR
DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL
DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE LIBRARY
(INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED
INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF
THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR
OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Libraries
If you develop a new library, and you want it to be of the greatest
possible use to the public, we recommend making it free software that
everyone can redistribute and change. You can do so by permitting
redistribution under these terms (or, alternatively, under the terms of the
ordinary General Public License).
To apply these terms, attach the following notices to the library. It is
safest to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least the
"copyright" line and a pointer to where the full notice is found.
one line to give the library's name and an idea of what it does.
Copyright (C) year name of author
This library is free software; you can redistribute it and/or modify it
under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2.1 of the License, or (at
your option) any later version.
This library is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
for more details.
You should have received a copy of the GNU Lesser General Public License
along with this library; if not, write to the Free Software Foundation,
Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Also add
information on how to contact you by electronic and paper mail.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the library, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in
the library `Frob' (a library for tweaking knobs) written
by James Random Hacker.
signature of Ty Coon, 1 April 1990
Ty Coon, President of Vice
That's all there is to it!

View File

@ -69,6 +69,7 @@ EXTRA_DIST += \
LICENSES/preferred/GFDL-1.2 \
LICENSES/preferred/gfdl-1.2.texi.readme \
LICENSES/preferred/GPL-2.0 \
LICENSES/preferred/LGPL-2.1 \
LICENSES/preferred/MIT \
LICENSES/stand-alone/GPL-3.0 \
tools/logger.pl \

View File

@ -119,6 +119,7 @@ m4_define([USB1_ADAPTERS],
[[stlink], [ST-Link Programmer], [HLADAPTER_STLINK]],
[[ti_icdi], [TI ICDI JTAG Programmer], [HLADAPTER_ICDI]],
[[ulink], [Keil ULINK JTAG Programmer], [ULINK]],
[[angie], [ANGIE Adapter], [ANGIE]],
[[usb_blaster_2], [Altera USB-Blaster II Compatible], [USB_BLASTER_2]],
[[ft232r], [Bitbang mode of FT232R based devices], [FT232R]],
[[vsllink], [Versaloon-Link JTAG Programmer], [VSLLINK]],

View File

@ -99,6 +99,8 @@ ATTRS{idVendor}=="0483", ATTRS{idProduct}=="374e", MODE="660", GROUP="plugdev",
ATTRS{idVendor}=="0483", ATTRS{idProduct}=="374f", MODE="660", GROUP="plugdev", TAG+="uaccess"
ATTRS{idVendor}=="0483", ATTRS{idProduct}=="3753", MODE="660", GROUP="plugdev", TAG+="uaccess"
ATTRS{idVendor}=="0483", ATTRS{idProduct}=="3754", MODE="660", GROUP="plugdev", TAG+="uaccess"
ATTRS{idVendor}=="0483", ATTRS{idProduct}=="3755", MODE="660", GROUP="plugdev", TAG+="uaccess"
ATTRS{idVendor}=="0483", ATTRS{idProduct}=="3757", MODE="660", GROUP="plugdev", TAG+="uaccess"
# Cypress SuperSpeed Explorer Kit
ATTRS{idVendor}=="04b4", ATTRS{idProduct}=="0007", MODE="660", GROUP="plugdev", TAG+="uaccess"
@ -222,6 +224,10 @@ ATTRS{idVendor}=="2aec", ATTRS{idProduct}=="1106", MODE="660", GROUP="plugdev",
ATTRS{idVendor}=="303a", ATTRS{idProduct}=="1001", MODE="660", GROUP="plugdev", TAG+="uaccess"
ATTRS{idVendor}=="303a", ATTRS{idProduct}=="1002", MODE="660", GROUP="plugdev", TAG+="uaccess"
# ANGIE USB-JTAG Adapter
ATTRS{idVendor}=="584e", ATTRS{idProduct}=="424e", MODE="660", GROUP="plugdev", TAG+="uaccess"
ATTRS{idVendor}=="584e", ATTRS{idProduct}=="4a55", MODE="660", GROUP="plugdev", TAG+="uaccess"
# Marvell Sheevaplug
ATTRS{idVendor}=="9e88", ATTRS{idProduct}=="9e8f", MODE="660", GROUP="plugdev", TAG+="uaccess"

View File

@ -0,0 +1,75 @@
# SPDX-License-Identifier: GPL-2.0-or-later
#****************************************************************************
# File : Makefile *
# Contents : Code for NanoXplore USB-JTAG ANGIE adapter hardware. *
# Based on openULINK project by: Martin Schmoelzer. *
# Copyright 2023, Ahmed Errached BOUDJELIDA, NanoXplore SAS. *
# <aboudjelida@nanoxplore.com> *
# <ahmederrachedbjld@gmail.com> *
# ***************************************************************************/
# Define the name of tools.
PREFIX =
# Small Device C Compiler: http://sdcc.sourceforge.net/
CC = $(PREFIX)sdcc
# 8051 assembler, part of the SDCC software package.
AS = $(PREFIX)sdas8051
# SDCC produces quite messy Intel HEX files. This tool is be used to re-format
# those files. It is not required for the firmware download functionality in
# the OpenOCD driver, but the resulting file is smaller.
PACKIHX = $(PREFIX)packihx
# GNU binutils size. Used to print the size of the IHX file generated by SDCC.
SIZE = size
# Source and header directories.
SRC_DIR = src
INCLUDE_DIR = include
CODE_SIZE = 0x3C00
XRAM_LOC = 0x3C00
XRAM_SIZE = 0x0400
CFLAGS = --std-sdcc99 --opt-code-size --model-small
LDFLAGS = --code-loc 0x0000 --code-size $(CODE_SIZE) --xram-loc $(XRAM_LOC) \
--xram-size $(XRAM_SIZE) --iram-size 256 --model-small
# list of base object files
OBJECTS = main.rel usb.rel protocol.rel jtag.rel delay.rel USBJmpTb.rel serial.rel gpif.rel
HEADERS = $(INCLUDE_DIR)/usb.h \
$(INCLUDE_DIR)/protocol.h \
$(INCLUDE_DIR)/jtag.h \
$(INCLUDE_DIR)/delay.h \
$(INCLUDE_DIR)/reg_ezusb.h \
$(INCLUDE_DIR)/io.h \
$(INCLUDE_DIR)/serial.h \
$(INCLUDE_DIR)/fx2macros.h \
$(INCLUDE_DIR)/msgtypes.h
# Disable all built-in rules.
.SUFFIXES:
# Targets which are executed even when identically named file is present.
.PHONY: all, clean
all: angie_firmware.ihx
$(SIZE) angie_firmware.ihx
angie_firmware.ihx: $(OBJECTS)
$(CC) -mmcs51 $(LDFLAGS) -o $@ $^
# Rebuild every C module (there are only 5 of them) if any header changes.
%.rel: $(SRC_DIR)/%.c $(HEADERS)
$(CC) -c $(CFLAGS) -mmcs51 -I$(INCLUDE_DIR) -o $@ $<
%.rel: $(SRC_DIR)/%.a51
$(AS) -lsgo $@ $<
clean:
rm -f *.asm *.lst *.rel *.rst *.sym *.ihx *.lk *.map *.mem
bin: angie_firmware.ihx
makebin -p angie_firmware.ihx angie_firmware.bin

View File

@ -0,0 +1,37 @@
#SPDX-License-Identifier: GPL-2.0-or-later
This is the ANGIE firmware for ANGIE USB-JTAG adapter.
The main components of ANGIE adapter are:
- Cypress EZ-USB FX2 microcontroller
- Spartan-6 FPGA
- SRAM memory chip
- Pin headers for various JTAG pin assignments
To compile the firmware, the SDCC compiler package is required. Most Linux
distributions include SDCC in their official package repositories. The SDCC
source code can be found at http://sdcc.sourceforge.net/
Simply type "make hex" in the ANGIE directory to compile the firmware.
"make clean" will remove all generated files except the Intel HEX file
required for downloading the firmware to ANGIE.
Note that the EZ-USB FX2 microcontroller does not have on-chip flash,
ANGIE include on-board EEPROM memory to store the firmware program of
the FX2, but we are not going to use this method.
Instead, upon initial connection of the ANGIE adapter to the host PC
via USB, the EZ-USB FX2 core has enough intelligence to act as a
stand-alone USB device, responding to USB control requests and allowing
firmware download via a special VENDOR-type control request. Then, the
EZ-USB microcontroller simulates a disconnect and re-connect to the USB bus.
It may take up to two seconds for the host to recognize the newly connected
device before OpenOCD can proceed to execute JTAG commands. This delay is
only visible when OpenOCD first uses a blank (unconfigured) ANGIE device.
Once the firmware downloaded, the FX2 microcontroller activate its GPIF mode,
download the Spartan-6 FPGA's bitstream, program the FPGA rapidly, and switch
back to default io mode.
Once the user disconnects the ANGIE adapter, all its memory contents are lost
and the firmware & bitstream download process has to be executed again.

View File

@ -0,0 +1,50 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
/****************************************************************
File : delay.h *
Contents : Delays handling header file for NanoXplore *
USB-JTAG ANGIE adapter hardware. *
Based on openULINK project code by: Martin Schmoelzer. *
Copyright 2023, Ahmed Errached BOUDJELIDA, NanoXplore SAS. *
<aboudjelida@nanoxplore.com> *
<ahmederrachedbjld@gmail.com> *
*****************************************************************/
#ifndef __DELAY_H
#define __DELAY_H
#include <stdint.h>
void syncdelay(uint8_t count);
void delay_5us(void);
void delay_1ms(void);
void delay_us(uint16_t delay);
void delay_ms(uint16_t delay);
#ifndef _IFREQ
#define _IFREQ 48000 /* IFCLK frequency in kHz */
#endif
/* CFREQ can be any one of: 48000, 24000, or 12000 */
#ifndef _CFREQ
#define _CFREQ 48000 /* CLKOUT frequency in kHz */
#endif
#if (_IFREQ < 5000)
#error "_IFREQ too small! Valid Range: 5000 to 48000..."
#endif
#if (_IFREQ > 48000)
#error "_IFREQ too large! Valid Range: 5000 to 48000..."
#endif
#if (_CFREQ != 48000)
#if (_CFREQ != 24000)
#if (_CFREQ != 12000)
#error "_CFREQ invalid! Valid values: 48000, 24000, 12000..."
#endif
#endif
#endif
/* Synchronization Delay formula: see TRM section 15-14 */
#define _SCYCL (3 * (_CFREQ) + 5 * (_IFREQ) - 1) / (2 * (_IFREQ))
#endif

View File

@ -0,0 +1,31 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
/*
* This code was taken from the fx2lib project from this link:
* https://github.com/djmuhlestein/fx2lib
*
* Copyright (C) 2009 Ubixum, Inc.
*/
/*! \file
* Macros for simple common tasks in fx2 firmware.
* */
#ifndef FX2MACROS_H
#define FX2MACROS_H
#include "reg_ezusb.h"
typedef enum {FALSE = 0, TRUE} BOOL_VALS;
/**
* \brief Used for getting and setting the CPU clock speed.
**/
typedef enum {CLK_12M = 0, CLK_24M, CLK_48M} CLK_SPD;
/**
* \brief Evaluates to a CLK_SPD enum.
**/
#define CPUFREQ (CLK_SPD)((CPUCS & bmclkspd) >> 3)
#endif

View File

@ -0,0 +1,65 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
/****************************************************************************
File : io.h *
Contents : input/output declaration header file for NanoXplore *
USB-JTAG ANGIE adapter hardware. *
Based on openULINK project code by: Martin Schmoelzer. *
Copyright 2023, Ahmed Errached BOUDJELIDA, NanoXplore SAS. *
<aboudjelida@nanoxplore.com> *
<ahmederrachedbjld@gmail.com> *
*****************************************************************************/
#ifndef __IO_H
#define __IO_H
#include "reg_ezusb.h"
/***************************************************************************
* JTAG Signals: *
***************************************************************************
* TMS ....... Test Mode Select *
* TCK ....... Test Clock *
* TDI ....... Test Data Input (from device point of view, not JTAG *
* adapter point of view!) *
* TDO ....... Test Data Output (from device point of view, not JTAG *
* adapter point of view!) *
* TRST ...... Test Reset: Used to reset the TAP Finite State Machine *
* into the Test Logic Reset state *
* SRST ..... Chip Reset *
***************************************************************************/
/* PORT A */
/* PA0 Not Connected */
/* PA1 Not Connected */
#define PIN_RDWR_B IOA2
#define PIN_CSI_B IOA3
#define PIN_INIT_B IOA4
#define PIN_PROGRAM_B IOA5
/* PA6 Not Connected */
/* PA7 Not Connected */
/* PORT B */
#define PIN_TRST IOB0
#define PIN_TMS IOB1
#define PIN_TCK IOB2
#define PIN_TDI IOB3
#define PIN_TDO IOB4
#define PIN_SRST IOB5
/* PA6 Not Connected */
/* PA7 Not Connected */
/* JTAG Signals with direction 'OUT' on port B */
/* PIN_TDI - PIN_TCK - PIN_TMS - PIN_TRST - PIN_SRST */
#define MASK_PORTB_DIRECTION_OUT (bmbit0 | bmbit1 | bmbit2 | bmbit3 | bmbit5)
/* PORT C */ // Debug:
#define PIN_T0 IOC0
#define PIN_T1 IOC1
#define PIN_T2 IOC2
#define PIN_T3 IOC3
#define PIN_T4 IOC4
/* PC5 Not Connected */
/* PC6 Not Connected */
/* PC7 Not Connected */
#endif

View File

@ -0,0 +1,31 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
/****************************************************************************
File : jtag.h *
Contents : Jtag handling functions header file for NanoXplore *
USB-JTAG ANGIE adapter hardware. *
Based on openULINK project code by: Martin Schmoelzer. *
Copyright 2023, Ahmed Errached BOUDJELIDA, NanoXplore SAS. *
<aboudjelida@nanoxplore.com> *
<ahmederrachedbjld@gmail.com> *
*****************************************************************************/
#ifndef __JTAG_H
#define __JTAG_H
#include <stdint.h>
uint16_t jtag_get_signals(void);
void jtag_configure_tck_delay(uint8_t scan_in, uint8_t scan_out,
uint8_t scan_io, uint8_t tck, uint8_t tms);
void jtag_clock_tms(uint8_t count, uint8_t sequence);
void jtag_slow_clock_tms(uint8_t count, uint8_t sequence);
void jtag_set_signals(uint8_t low, uint8_t high);
void jtag_clock_tck(uint16_t count);
void jtag_slow_clock_tck(uint16_t count);
void jtag_scan_in(uint8_t out_offset, uint8_t in_offset);
void jtag_scan_out(uint8_t out_offset);
void jtag_scan_io(uint8_t out_offset, uint8_t in_offset);
void jtag_slow_scan_in(uint8_t out_offset, uint8_t in_offset);
void jtag_slow_scan_out(uint8_t out_offset);
void jtag_slow_scan_io(uint8_t out_offset, uint8_t in_offset);
#endif

View File

@ -0,0 +1,171 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
/****************************************************************************
File : msgtypes.h *
Contents : Definition of the commands supported by NanoXplore *
USB-JTAG ANGIE adapter hardware. *
Based on openULINK project code by: Martin Schmoelzer. *
Copyright 2023, Ahmed Errached BOUDJELIDA, NanoXplore SAS. *
<aboudjelida@nanoxplore.com> *
<ahmederrachedbjld@gmail.com> *
*****************************************************************************/
/**
* @file
* Definition of the commands supported by the ANGIE firmware.
*
* Basically, two types of commands can be distinguished:
* - Commands with fixed payload size
* - Commands with variable payload size
*
* SCAN commands (in all variations) carry payloads of variable size, all
* other commands carry payloads of fixed size.
*
* In the case of SCAN commands, the payload size (n) is calculated by
* dividing the scan_size_bits variable by 8, rounding up the result.
*
* Offset zero always contains the command ID.
*
****************************************************************************
* CMD_SCAN_IN, CMD_SLOW_SCAN_IN: *
* *
* OUT: *
* offset 1: scan_size_bytes *
* offset 2: bits_last_byte *
* offset 3: tms_count_start + tms_count_end *
* offset 4: tms_sequence_start *
* offset 5: tms_sequence_end *
* *
* IN: *
* offset 0..n: TDO data *
****************************************************************************
* CMD_SCAN_OUT, CMD_SLOW_SCAN_OUT: *
* *
* OUT: *
* offset 1: scan_size_bytes *
* offset 2: bits_last_byte *
* offset 3: tms_count_start + tms_count_end *
* offset 4: tms_sequence_start *
* offset 5: tms_sequence_end *
* offset 6..x: TDI data *
****************************************************************************
* CMD_SCAN_IO, CMD_SLOW_SCAN_IO: *
* *
* OUT: *
* offset 1: scan_size_bytes *
* offset 2: bits_last_byte *
* offset 3: tms_count_start + tms_count_end *
* offset 4: tms_sequence_start *
* offset 5: tms_sequence_end *
* offset 6..x: TDI data *
* *
* IN: *
* offset 0..n: TDO data *
****************************************************************************
* CMD_CLOCK_TMS, CMD_SLOW_CLOCK_TMS: *
* *
* OUT: *
* offset 1: tms_count *
* offset 2: tms_sequence *
****************************************************************************
* CMD_CLOCK_TCK, CMD_SLOW_CLOCK_TCK: *
* *
* OUT: *
* offset 1: low byte of tck_count *
* offset 2: high byte of tck_count *
****************************************************************************
* CMD_CLOCK_SLEEP_US: *
* *
* OUT: *
* offset 1: low byte of sleep_us *
* offset 2: high byte of sleep_us *
****************************************************************************
* CMD_CLOCK_SLEEP_MS: *
* *
* OUT: *
* offset 1: low byte of sleep_ms *
* offset 2: high byte of sleep_ms *
****************************************************************************
* CMD_GET_SIGNALS: *
* *
* IN: *
* offset 0: current state of input signals *
* offset 1: current state of output signals *
****************************************************************************
* CMD_SET_SIGNALS: *
* *
* OUT: *
* offset 1: signals that should be de-asserted *
* offset 2: signals that should be asserted *
****************************************************************************
* CMD_CONFIGURE_TCK_FREQ: *
* *
* OUT: *
* offset 1: delay value for scan_in function *
* offset 2: delay value for scan_out function *
* offset 3: delay value for scan_io function *
* offset 4: delay value for clock_tck function *
* offset 5: delay value for clock_tms function *
****************************************************************************
* CMD_SET_LEDS: *
* *
* OUT: *
* offset 1: LED states: *
* Bit 0: turn COM LED on *
* Bit 1: turn RUN LED on *
* Bit 2: turn COM LED off *
* Bit 3: turn RUN LED off *
* Bits 7..4: Reserved *
****************************************************************************
* CMD_TEST: *
* *
* OUT: *
* offset 1: unused dummy value *
****************************************************************************
*/
#ifndef __MSGTYPES_H
#define __MSGTYPES_H
/*
* Command IDs:
*
* Bits 7..6: Reserved, should always be zero
* Bits 5..0: Command ID. There are 62 usable IDs. Of this 63 available IDs,
* the IDs 0x00..0x1F are commands with variable payload size,
* the IDs 0x20..0x3F are commands with fixed payload size.
*/
#define CMD_ID_MASK 0x3F
/* Commands with variable payload size */
#define CMD_SCAN_IN 0x00
#define CMD_SLOW_SCAN_IN 0x01
#define CMD_SCAN_OUT 0x02
#define CMD_SLOW_SCAN_OUT 0x03
#define CMD_SCAN_IO 0x04
#define CMD_SLOW_SCAN_IO 0x05
/* Commands with fixed payload size */
#define CMD_CLOCK_TMS 0x20
#define CMD_SLOW_CLOCK_TMS 0x21
#define CMD_CLOCK_TCK 0x22
#define CMD_SLOW_CLOCK_TCK 0x23
#define CMD_SLEEP_US 0x24
#define CMD_SLEEP_MS 0x25
#define CMD_GET_SIGNALS 0x26
#define CMD_SET_SIGNALS 0x27
#define CMD_CONFIGURE_TCK_FREQ 0x28
#define CMD_SET_LEDS 0x29
#define CMD_TEST 0x2A
/* JTAG signal definition for jtag_get_signals() -- Input signals! */
#define SIGNAL_TDO 1
/* JTAG signal definition for jtag_get_signals() -- Output signals! */
#define SIGNAL_TDI 8
#define SIGNAL_TMS 2
#define SIGNAL_TCK 4
#define SIGNAL_TRST 1
#define SIGNAL_SRST 32
#endif

View File

@ -0,0 +1,20 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
/****************************************************************************
File : protocol.h *
Contents : Jtag commands handling protocol header file for NanoXplore *
USB-JTAG ANGIE adapter hardware. *
Based on openULINK project code by: Martin Schmoelzer. *
Copyright 2023, Ahmed Errached BOUDJELIDA, NanoXplore SAS. *
<aboudjelida@nanoxplore.com> *
<ahmederrachedbjld@gmail.com> *
*****************************************************************************/
#ifndef __PROTOCOL_H
#define __PROTOCOL_H
#include <stdbool.h>
bool execute_command(void);
void command_loop(void);
#endif

View File

@ -0,0 +1,656 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
/****************************************************************************
File : reg_ezusb.h *
Contents : FX2 microcontroller registers file for NanoXplore *
USB-JTAG ANGIE adapter hardware. *
Based on openULINK project code by: Martin Schmoelzer. *
Copyright 2023, Ahmed Errached BOUDJELIDA, NanoXplore SAS. *
<aboudjelida@nanoxplore.com> *
<ahmederrachedbjld@gmail.com> *
*****************************************************************************/
#ifndef REG_EZUSB_H
#define REG_EZUSB_H
/**
* @file
* All information in this file was taken from the EZ-USB FX2 Technical
* Reference Manual, Cypress Semiconductor, 3901 North First Street
* San Jose, CA 95134 (www.cypress.com).
*
* The EZ-USB Technical Reference Manual is called "EZ-USB FX2 TRM" hereafter.
*/
/* Compiler-specific definitions of SBIT, SFR, SFRX, ... macros */
#include <mcs51/compiler.h>
/* Bit vectors */
#define bmbit0 0x01
#define bmbit1 0x02
#define bmbit2 0x04
#define bmbit3 0x08
#define bmbit4 0x10
#define bmbit5 0x20
#define bmbit6 0x40
#define bmbit7 0x80
/**************************************************************************
************************ Special Function Registers **********************
***************************************************************************/
SFR(IOA, 0x80);
SBIT(IOA0, 0x80, 0);
SBIT(IOA1, 0x80, 1);
SBIT(IOA2, 0x80, 2);
SBIT(IOA3, 0x80, 3);
SBIT(IOA4, 0x80, 4);
SBIT(IOA5, 0x80, 5);
SBIT(IOA6, 0x80, 6);
SBIT(IOA7, 0x80, 7);
SFR(SP, 0x81);
SFR(DPL0, 0x82);
SFR(DPH0, 0x83);
SFR(DPL1, 0x84);
SFR(DPL2, 0x85);
SFR(DPS, 0x86);
#define SEL bmbit0
/* Bit 1 read-only, always reads '0' */
/* Bit 2 read-only, always reads '0' */
/* Bit 3 read-only, always reads '0' */
/* Bit 4 read-only, always reads '0' */
/* Bit 5 read-only, always reads '0' */
/* Bit 6 read-only, always reads '0' */
/* Bit 7 read-only, always reads '0' */
SFR(PCON, 0x87);
#define IDLE bmbit0
#define STOP bmbit1
#define GF0 bmbit2
#define GF1 bmbit3
/* Bit 4 read-only, always reads '1' */
/* Bit 5 read-only, always reads '1' */
/* Bit 6 unused */
#define SMOD0 bmbit7
SFR(TCON, 0x88);
SBIT(IT0, 0x88, 0);
SBIT(IE0, 0x88, 1);
SBIT(IT1, 0x88, 2);
SBIT(IE1, 0x88, 3);
SBIT(TR0, 0x88, 4);
SBIT(TF0, 0x88, 5);
SBIT(TR1, 0x88, 6);
SBIT(TF1, 0x88, 7);
SFR(TMOD, 0x89);
SFR(TL0, 0x8A);
SFR(TL1, 0x8B);
SFR(TH0, 0x8C);
SFR(TH1, 0x8D);
SFR(CKCON, 0x8E);
#define MD0 bmbit0
#define MD1 bmbit1
#define MD2 bmbit2
#define T0M bmbit3
#define T1M bmbit4
#define T2M bmbit5
/* Bit 6 unused */
/* Bit 7 unused */
SFR(SPC_FNC, 0x8F);
#define BMWRS bmbit0
/* Bit 1 read-only, always reads '0' */
/* Bit 2 read-only, always reads '0' */
/* Bit 3 read-only, always reads '0' */
/* Bit 4 read-only, always reads '0' */
/* Bit 5 read-only, always reads '0' */
/* Bit 6 read-only, always reads '0' */
/* Bit 7 read-only, always reads '0' */
SFR(IOB, 0x90);
SBIT(IOB0, 0x90, 0);
SBIT(IOB1, 0x90, 1);
SBIT(IOB2, 0x90, 2);
SBIT(IOB3, 0x90, 3);
SBIT(IOB4, 0x90, 4);
SBIT(IOB5, 0x90, 5);
SBIT(IOB6, 0x90, 6);
SBIT(IOB7, 0x90, 7);
SFR(EXIF, 0x91);
SBIT(USBINT, 0x91, 4);
SBIT(I2CINT, 0x91, 5);
SBIT(IE4, 0x91, 6);
SBIT(IE5, 0x91, 7);
SFR(MPAGE, 0x92);
SFR(SCON0, 0x98);
SBIT(RI, 0x98, 0);
SBIT(TI, 0x98, 1);
SBIT(RB8, 0x98, 2);
SBIT(TB8, 0x98, 3);
SBIT(REN, 0x98, 4);
SBIT(SM2, 0x98, 5);
SBIT(SM1, 0x98, 6);
SBIT(SM0, 0x98, 7);
SFR(SBUF0, 0x99);
SFR(AUTOPTRH1, 0x9A);
SFR(AUTOPTRL1, 0x9B);
SFR(AUTOPTRH2, 0x9D);
SFR(AUTOPTRL2, 0x9E);
#define AUTOPTR1H AUTOPTRH1 /* for backwards compatibility with examples */
#define AUTOPTR1L AUTOPTRL1 /* for backwards compatibility with examples */
#define APTR1H AUTOPTRH1 /* for backwards compatibility with examples */
#define APTR1L AUTOPTRL1 /* for backwards compatibility with examples */
SFR(IOC, 0xA0);
SBIT(IOC0, 0xA0, 0);
SBIT(IOC1, 0xA0, 1);
SBIT(IOC2, 0xA0, 2);
SBIT(IOC3, 0xA0, 3);
SBIT(IOC4, 0xA0, 4);
SBIT(IOC5, 0xA0, 5);
SBIT(IOC6, 0xA0, 6);
SBIT(IOC7, 0xA0, 7);
SFR(INT2CLR, 0xA1);
SFR(INT4CLR, 0xA2);
SFR(IE, 0xA8);
SBIT(EX0, 0xA8, 0);
SBIT(ET0, 0xA8, 1);
SBIT(EX1, 0xA8, 2);
SBIT(ET1, 0xA8, 3);
SBIT(ES0, 0xA8, 4);
SBIT(ET2, 0xA8, 5);
SBIT(ES1, 0xA8, 6);
SBIT(EA, 0xA8, 7);
SFR(EP2468STAT, 0xAA);
#define EP8F bmbit7
#define EP8E bmbit6
#define EP6F bmbit5
#define EP6E bmbit4
#define EP4F bmbit3
#define EP4E bmbit2
#define EP2F bmbit1
#define EP2E bmbit0
SFR(EP24FIFOFLGS, 0xAB);
SFR(EP68FIFOFLGS, 0xAC);
SFR(AUTOPTRSETUP, 0xAF);
SFR(IOD, 0xB0);
SBIT(IOD0, 0xB0, 0);
SBIT(IOD1, 0xB0, 1);
SBIT(IOD2, 0xB0, 2);
SBIT(IOD3, 0xB0, 3);
SBIT(IOD4, 0xB0, 4);
SBIT(IOD5, 0xB0, 5);
SBIT(IOD6, 0xB0, 6);
SBIT(IOD7, 0xB0, 7);
SFR(IOE, 0xB1);
SFR(OEA, 0xB2);
SFR(OEB, 0xB3);
SFR(OEC, 0xB4);
SFR(OED, 0xB5);
SFR(OEE, 0xB6);
SFR(IP, 0xB8);
SBIT(PX0, 0xB8, 0);
SBIT(PT0, 0xB8, 1);
SBIT(PX1, 0xB8, 2);
SBIT(PT1, 0xB8, 3);
SBIT(PS0, 0xB8, 4);
SBIT(PT2, 0xB8, 5);
SBIT(PS1, 0xB8, 6);
/* Bit 7 read-only, always reads '1' */
SFR(EP01STAT, 0xBA);
SFR(GPIFTRIG, 0xBB);
#define BMGPIFDONE bmbit7
#define BMGPIFREAD bmbit2
#define GPIF_EP2 0
#define GPIF_EP4 1
#define GPIF_EP6 2
#define GPIF_EP8 3
SFR(GPIFSGLDATH, 0xBD);
SFR(GPIFSGLDATLX, 0xBE);
SFR(GPIFSGLDATLNOX, 0xBF);
SFR(SCON1, 0xC0);
SBIT(RI_1, 0xC0, 0);
SBIT(TI_1, 0xC0, 1);
SBIT(RB8_1, 0xC0, 2);
SBIT(TB8_1, 0xC0, 3);
SBIT(REN_1, 0xC0, 4);
SBIT(SM2_1, 0xC0, 5);
SBIT(SM1_1, 0xC0, 6);
SBIT(SM0_1, 0xC0, 7);
SFR(SBUF1, 0xC1);
SFR(T2CON, 0xC8);
SBIT(CPRL2, 0xC8, 0);
SBIT(C_T2, 0xC8, 1);
SBIT(TR2, 0xC8, 2);
SBIT(EXEN2, 0xC8, 3);
SBIT(TCLK, 0xC8, 4);
SBIT(RCLK, 0xC8, 5);
SBIT(EXF2, 0xC8, 6);
SBIT(TF2, 0xC8, 7);
SFR(RCAP2L, 0xCA);
SFR(RCAP2H, 0xCB);
SFR(TL2, 0xCC);
SFR(TH2, 0xCD);
SFR(PSW, 0xD0);
SBIT(P, 0xD0, 0);
SBIT(F1, 0xD0, 1);
SBIT(OV, 0xD0, 2);
SBIT(RS0, 0xD0, 3);
SBIT(RS1, 0xD0, 4);
SBIT(F0, 0xD0, 5);
SBIT(AC, 0xD0, 6);
SBIT(CY, 0xD0, 7);
SFR(EICON, 0xD8);
/* Bit 0 read-only, always reads '0' */
/* Bit 1 read-only, always reads '0' */
/* Bit 2 read-only, always reads '0' */
SBIT(INT6, 0xD8, 3);
SBIT(RESI, 0xD8, 4);
SBIT(ERESI, 0xD8, 5);
/* Bit 6 read-only, always reads '1' */
SBIT(SMOD1, 0xD8, 7);
SFR(ACC, 0xE0);
SFR(EIE, 0xE8);
SBIT(EUSB, 0xE8, 0);
SBIT(EI2C, 0xE8, 1);
SBIT(EX4, 0xE8, 2);
SBIT(EX5, 0xE8, 3);
SBIT(EWDI, 0xE8, 4);
/* Bit 5 read-only, always reads '1' */
/* Bit 6 read-only, always reads '1' */
/* Bit 7 read-only, always reads '1' */
SFR(B, 0xF0);
SFR(EIP, 0xF8);
SBIT(PUSB, 0xF8, 0);
SBIT(PI2C, 0xF8, 1);
SBIT(PX4, 0xF8, 2);
SBIT(PX5, 0xF8, 3);
SBIT(PX6, 0xF8, 4);
/* Bit 5 read-only, always reads '1' */
/* Bit 6 read-only, always reads '1' */
/* Bit 7 read-only, always reads '1' */
/**************************************************************************
***************************** XDATA Registers ****************************
***************************************************************************/
SFRX(GPIF_WAVE_DATA, 0xE400);
SFRX(RES_WAVEDATA_END, 0xE480);
/* General Configuration */
SFRX(CPUCS, 0xE600);
#define RES8051 bmbit0
#define CLKOE bmbit1
#define BMCLKINV bmbit2
#define bmclkspd0 bmbit3
#define bmclkspd1 bmbit4
#define bmclkspd (bmbit4 | bmbit3)
#define BMPRTCSTB bmbit5
/* PCON register */
#define BMSMOD0 bmbit7
SFRX(IFCONFIG, 0xE601);
#define BMIFCLKSRC bmbit7
#define BM3048MHZ bmbit6
#define BMIFCLKOE bmbit5
#define BMIFCLKPOL bmbit4
#define BMASYNC bmbit3
#define BMGSTATE bmbit2
#define BMIFCFG1 bmbit1
#define BMIFCFG0 bmbit0
#define BMIFCFGMASK (BMIFCFG0 | BMIFCFG1)
#define BMIFGPIF BMIFCFG1
SFRX(PINFLAGSAB, 0xE602);
SFRX(PINFLAGSCD, 0xE603);
SFRX(FIFORESET, 0xE604);
#define BMNAKALL bmbit7
SFRX(BREAKPT, 0xE605);
#define BMBREAK bmbit3
#define BMBPPULSE bmbit2
#define BMBPEN bmbit1
SFRX(BPADDRH, 0xE606);
SFRX(BPADDRL, 0xE607);
SFRX(UART230, 0xE608);
SFRX(FIFOPINPOLAR, 0xE609);
SFRX(REVID, 0xE60A);
SFRX(REVCTL, 0xE60B);
#define BMNOAUTOARM bmbit1
#define BMSKIPCOMMIT bmbit0
/* Endpoint Configuration */
SFRX(EP1OUTCFG, 0xE610);
SFRX(EP1INCFG, 0xE611);
SFRX(EP2CFG, 0xE612);
SFRX(EP4CFG, 0xE613);
SFRX(EP6CFG, 0xE614);
SFRX(EP8CFG, 0xE615);
SFRX(EP2FIFOCFG, 0xE618);
SFRX(EP4FIFOCFG, 0xE619);
SFRX(EP6FIFOCFG, 0xE61A);
SFRX(EP8FIFOCFG, 0xE61B);
#define BMINFM bmbit6
#define BMOEP bmbit5
#define BMAUTOOUT bmbit4
#define BMAUTOIN bmbit3
#define BMZEROLENIN bmbit2
#define BMWORDWIDE bmbit0
SFRX(EP2AUTOINLENH, 0xE620);
SFRX(EP2AUTOINLENL, 0xE621);
SFRX(EP4AUTOINLENH, 0xE622);
SFRX(EP4AUTOINLENL, 0xE623);
SFRX(EP6AUTOINLENH, 0xE612);
SFRX(EP6AUTOINLENL, 0xE613);
SFRX(EP8AUTOINLENH, 0xE614);
SFRX(EP8AUTOINLENL, 0xE615);
SFRX(EP2FIFOPFH, 0xE630);
SFRX(EP2FIFOPFL, 0xE631);
SFRX(EP4FIFOPFH, 0xE632);
SFRX(EP4FIFOPFL, 0xE633);
SFRX(EP6FIFOPFH, 0xE634);
SFRX(EP6FIFOPFL, 0xE635);
SFRX(EP8FIFOPFH, 0xE636);
SFRX(EP8FIFOPFL, 0xE637);
SFRX(EP2ISOINPKTS, 0xE640);
SFRX(EP4ISOINPKTS, 0xE641);
SFRX(EP6ISOINPKTS, 0xE642);
SFRX(EP8ISOINPKTS, 0xE643);
SFRX(INPKTEND, 0xE648);
SFRX(OUTPKTEND, 0xE649);
/* Interrupts */
SFRX(EP2FIFOIE, 0xE650);
SFRX(EP2FIFOIRQ, 0xE651);
SFRX(EP4FIFOIE, 0xE652);
SFRX(EP4FIFOIRQ, 0xE653);
SFRX(EP6FIFOIE, 0xE654);
SFRX(EP6FIFOIRQ, 0xE655);
SFRX(EP8FIFOIE, 0xE656);
SFRX(EP8FIFOIRQ, 0xE657);
SFRX(IBNIE, 0xE658);
SFRX(IBNIRQ, 0xE659);
#define EP0IBN bmbit0
#define EP1IBN bmbit1
#define EP2IBN bmbit2
#define EP4IBN bmbit3
#define EP6IBN bmbit4
#define EP8IBN bmbit5
SFRX(NAKIE, 0xE65A);
SFRX(NAKIRQ, 0xE65B);
#define EP8PING bmbit7
#define EP6PING bmbit6
#define EP4PING bmbit5
#define EP2PING bmbit4
#define EP1PING bmbit3
#define EP0PING bmbit2
#define IBN bmbit0
SFRX(USBIEN, 0xE65C);
SFRX(USBIRQ, 0xE65D);
#define SUDAVI bmbit0
#define SOFI bmbit1
#define SUTOKI bmbit2
#define SUSPI bmbit3
#define URESI bmbit4
#define HSGRANT bmbit5
#define EP0ACK bmbit6
SFRX(EPIE, 0xE65E);
SFRX(EPIRQ, 0xE65F);
SFRX(GPIFIE, 0xE660);
SFRX(GPIFIRQ, 0xE661);
SFRX(USBERRIE, 0xE662);
SFRX(USBERRIRQ, 0xE663);
SFRX(ERRCNTLIM, 0xE664);
SFRX(CLRERRCNT, 0xE665);
SFRX(INT2IVEC, 0xE666);
#define I2V0 bmbit2
#define I2V1 bmbit3
#define I2V2 bmbit4
#define I2V3 bmbit5
#define I2V4 bmbit6
SFRX(INT4IVEC, 0xE667);
SFRX(INTSETUP, 0xE668);
#define AV4EN bmbit0
#define INT4IN bmbit1
#define AV2EN bmbit3
/* Input/Output */
SFRX(PORTACFG, 0xE670);
#define BMINT0 bmbit0
#define BMINT1 bmbit1
#define BMFLAGD bmbit7
SFRX(PORTCCFG, 0xE671);
#define BMGPIFA0 bmbit0
#define BMGPIFA1 bmbit1
#define BMGPIFA2 bmbit2
#define BMGPIFA3 bmbit3
#define BMGPIFA4 bmbit4
#define BMGPIFA5 bmbit5
#define BMGPIFA6 bmbit6
#define BMGPIFA7 bmbit7
SFRX(PORTECFG, 0xE672);
#define BMT0OUT bmbit0
#define BMT1OUT bmbit1
#define BMT2OUT bmbit2
#define BMRXD0OUT bmbit3
#define BMRXD1OUT bmbit4
#define BMINT6 bmbit5
#define BMT2EX bmbit6
#define BMGPIFA8 bmbit7
SFRX(I2CS, 0xE678);
#define BMDONE bmbit0
#define BMACK bmbit1
#define BMBERR bmbit2
#define BMID (bmbit4 | bmbit3)
#define BMLASTRD bmbit5
#define BMSTOP bmbit6
#define BMSTART bmbit7
SFRX(I2DAT, 0xE679);
SFRX(I2CTL, 0xE67A);
#define BMSTOPIE bmbit1
#define BM400KHZ bmbit0
SFRX(XAUTODAT1, 0xE67B);
SFRX(XAUTODAT2, 0xE67C);
#define EXTAUTODAT1 XAUTODAT1
#define EXTAUTODAT2 XAUTODAT2
/* USB Control */
SFRX(USBCS, 0xE680);
#define SIGRSUME bmbit0
#define RENUM bmbit1
#define NOSYNSOF bmbit2
#define DISCON bmbit3
#define HSM bmbit7
SFRX(SUSPEND, 0xE681);
SFRX(WAKEUPCS, 0xE682);
#define BMWU2 bmbit7
#define BMWU bmbit6
#define BMWU2POL bmbit5
#define BMWUPOL bmbit4
#define BMDPEN bmbit2
#define BMWU2EN bmbit1
#define BMWUEN bmbit0
SFRX(TOGCTL, 0xE683);
#define BMTOGCTLEPMASK bmbit3 | bmbit2 | bmbit1 | bmbit0
#define BMRESETTOGGLE bmbit5
#define BMSETTOGGLE bmbit6
#define BMQUERYTOGGLE bmbit7
SFRX(USBFRAMEH, 0xE684);
SFRX(USBFRAMEL, 0xE685);
SFRX(MICROFRAME, 0xE686);
SFRX(FNADDR, 0xE687);
/* Endpoints */
SFRX(EP0BCH, 0xE68A);
SFRX(EP0BCL, 0xE68B);
SFRX(EP1OUTBC, 0xE68D);
SFRX(EP1INBC, 0xE68F);
SFRX(EP2BCH, 0xE690);
SFRX(EP2BCL, 0xE691);
SFRX(EP4BCH, 0xE694);
SFRX(EP4BCL, 0xE695);
SFRX(EP6BCH, 0xE698);
SFRX(EP6BCL, 0xE699);
SFRX(EP8BCH, 0xE69C);
SFRX(EP8BCL, 0xE69D);
SFRX(EP0CS, 0xE6A0);
#define HSNAK bmbit7
SFRX(EP1INCS, 0xE6A2);
SFRX(EP1OUTCS, 0xE6A1);
#define EPSTALL bmbit0
#define EPBSY bmbit1
SFRX(EP2CS, 0xE6A3);
SFRX(EP4CS, 0xE6A4);
SFRX(EP6CS, 0xE6A5);
SFRX(EP8CS, 0xE6A6);
#define BMEPEMPTY bmbit2
#define BMEPFULL bmbit3
#define BMNPAK (bmbit6 | bmbit5 | bmbit4)
SFRX(EP2FIFOFLGS, 0xE6A7);
SFRX(EP4FIFOFLGS, 0xE6A8);
SFRX(EP6FIFOFLGS, 0xE6A9);
SFRX(EP8FIFOFLGS, 0xE6AA);
SFRX(EP2FIFOBCH, 0xE6AB);
SFRX(EP2FIFOBCL, 0xE6AC);
SFRX(EP4FIFOBCH, 0xE6AD);
SFRX(EP4FIFOBCL, 0xE6AE);
SFRX(EP6FIFOBCH, 0xE6AF);
SFRX(EP6FIFOBCL, 0xE6B0);
SFRX(EP8FIFOBCH, 0xE6B1);
SFRX(EP8FIFOBCL, 0xE6B2);
SFRX(SUDPTRH, 0xE6B3);
SFRX(SUDPTRL, 0xE6B4);
SFRX(SUDPTRCTL, 0xE6B5);
#define BMSDPAUTO bmbit0
SFRX(SETUPDAT[8], 0xE6B8);
/* GPIF */
SFRX(GPIFWFSELECT, 0xE6C0);
SFRX(GPIFIDLECS, 0xE6C1);
SFRX(GPIFIDLECTL, 0xE6C2);
SFRX(GPIFCTLCFG, 0xE6C3);
SFRX(GPIFADRH, 0xE6C4);
SFRX(GPIFADRL, 0xE6C5);
SFRX(GPIFTCB3, 0xE6CE);
SFRX(GPIFTCB2, 0xE6CF);
SFRX(GPIFTCB1, 0xE6D0);
SFRX(GPIFTCB0, 0xE6D1);
#define EP2GPIFTCH GPIFTCB1 /* these are here for backwards compatibility */
#define EP2GPIFTCL GPIFTCB0
#define EP4GPIFTCH GPIFTCB1 /* these are here for backwards compatibility */
#define EP4GPIFTCL GPIFTCB0
#define EP6GPIFTCH GPIFTCB1 /* these are here for backwards compatibility */
#define EP6GPIFTCL GPIFTCB0
#define EP8GPIFTCH GPIFTCB1 /* these are here for backwards compatibility */
#define EP8GPIFTCL GPIFTCB0
SFRX(EP2GPIFFLGSEL, 0xE6D2);
SFRX(EP2GPIFPFSTOP, 0xE6D3);
SFRX(EP2GPIFTRIG, 0xE6D4);
SFRX(EP4GPIFFLGSEL, 0xE6DA);
SFRX(EP4GPIFPFSTOP, 0xE6DB);
SFRX(EP4GPIFTRIG, 0xE6DC);
SFRX(EP6GPIFFLGSEL, 0xE6E2);
SFRX(EP6GPIFPFSTOP, 0xE6E3);
SFRX(EP6GPIFTRIG, 0xE6E4);
SFRX(EP8GPIFFLGSEL, 0xE6EA);
SFRX(EP8GPIFPFSTOP, 0xE6EB);
SFRX(EP8GPIFTRIG, 0xE6EC);
SFRX(XGPIFSGLDATH, 0xE6F0);
SFRX(XGPIFSGLDATLX, 0xE6F1);
SFRX(XGPIFSGLDATLNOX, 0xE6F2);
SFRX(GPIFREADYCFG, 0xE6F3);
SFRX(GPIFREADYSTAT, 0xE6F4);
SFRX(GPIFABORT, 0xE6F5);
// UDMA
SFRX(FLOWSTATE, 0xE6C6);
SFRX(FLOWLOGIC, 0xE6C7);
SFRX(FLOWEQ0CTL, 0xE6C8);
SFRX(FLOWEQ1CTL, 0xE6C9);
SFRX(FLOWHOLDOFF, 0xE6CA);
SFRX(FLOWSTB, 0xE6CB);
SFRX(FLOWSTBEDGE, 0xE6CC);
SFRX(FLOWSTBHPERIOD, 0xE6CD);
SFRX(GPIFHOLDAMOUNT, 0xE60C);
SFRX(UDMACRCH, 0xE67D);
SFRX(UDMACRCL, 0xE67E);
SFRX(UDMACRCQUAL, 0xE67F);
/* Debug/Test
* The following registers are for Cypress's internal testing purposes only.
* These registers are not documented in the datasheet or the Technical Reference
* Manual as they were not designed for end user application usage
*/
SFRX(DBUG, 0xE6F8);
SFRX(TESTCFG, 0xE6F9);
SFRX(USBTEST, 0xE6FA);
SFRX(CT1, 0xE6FB);
SFRX(CT2, 0xE6FC);
SFRX(CT3, 0xE6FD);
SFRX(CT4, 0xE6FE);
/* Endpoint Buffers */
SFRX(EP0BUF[64], 0xE740);
SFRX(EP1INBUF[64], 0xE7C0);
SFRX(EP1OUTBUF[64], 0xE780);
SFRX(EP2FIFOBUF[512], 0xF000);
SFRX(EP4FIFOBUF[512], 0xF400);
SFRX(EP6FIFOBUF[512], 0xF800);
SFRX(EP8FIFOBUF[512], 0xFC00);
/* Error Correction Code (ECC) Registers (FX2LP/FX1 only) */
SFRX(ECCCFG, 0xE628);
SFRX(ECCRESET, 0xE629);
SFRX(ECC1B0, 0xE62A);
SFRX(ECC1B1, 0xE62B);
SFRX(ECC1B2, 0xE62C);
SFRX(ECC2B0, 0xE62D);
SFRX(ECC2B1, 0xE62E);
SFRX(ECC2B2, 0xE62F);
/* Feature Registers (FX2LP/FX1 only) */
SFRX(GPCR2, 0xE50D);
#define BMFULLSPEEDONLY bmbit4
#endif

View File

@ -0,0 +1,47 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
/**
* This code was taken from the fx2lib project from this link:
* https://github.com/djmuhlestein/fx2lib
*
* Copyright (C) 2009 Ubixum, Inc.
**/
/** \file serial.h
* defines functions to print to a serial console with SIO0
**/
#include "fx2macros.h"
#include <stdint.h>
/**
* This function inits sio0 to use T2CON (timer 2)
* See TRM 14.3.4.1 (Table 14-16)
* Certain baud rates have too high an error rate to work. All baud rates are .16%
* except:
*
* 12MHZ 24MHZ
* \li 57600 -6.99%
* \li 38400 -2.34% -2.34%
* \li 19200 -2.34%
*
* Possible Baud rates:
* \li 2400
* \li 4800
* \li 9600
* \li 19200
* \li 28800
* \li 38400
* \li 57600
*
* Any of these rates should work except 57600 at 12mhz. -2.34% is pushing
* most hardware specs for working. All rates at 48mhz work at .16%
**/
void sio0_init(uint32_t baud_rate) __critical; /* baud_rate max should be 57600 since int=2 bytes */
/**
* putchar('\\n') or putchar('\\r') both transmit \\r\\n
* Just use one or the other. (This makes terminal echo easy)
**/
int putchar(char c);
int getchar(void);

View File

@ -0,0 +1,273 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
/****************************************************************************
File : usb.h *
Contents : usb communication handling header file for NanoXplore *
USB-JTAG ANGIE adapter hardware. *
Based on openULINK project code by: Martin Schmoelzer. *
Copyright 2023, Ahmed Errached BOUDJELIDA, NanoXplore SAS. *
<aboudjelida@nanoxplore.com> *
<ahmederrachedbjld@gmail.com> *
*****************************************************************************/
#ifndef __USB_H
#define __USB_H
#include "reg_ezusb.h"
#include <stdint.h>
#include <stdbool.h>
/* High and Low byte of a word (uint16_t) */
#define HI8(word) (uint8_t)(((uint16_t)(word) >> 8) & 0xff)
#define LO8(word) (uint8_t)((uint16_t)(word) & 0xff)
/* Convenience functions */
#define STALL_EP0() (EP0CS |= EPSTALL)
#define CLEAR_IRQ() (USBINT = 0)
/*********** USB descriptors. See section 9.5 of the USB 1.1 spec **********/
/* USB Descriptor Types. See USB 1.1 spec, page 187, table 9-5 */
#define DESCRIPTOR_TYPE_DEVICE 0x01
#define DESCRIPTOR_TYPE_CONFIGURATION 0x02
#define DESCRIPTOR_TYPE_STRING 0x03
#define DESCRIPTOR_TYPE_INTERFACE 0x04
#define DESCRIPTOR_TYPE_ENDPOINT 0x05
#define STR_DESCR(len, ...) { (len) * 2 + 2, DESCRIPTOR_TYPE_STRING, { __VA_ARGS__ } }
/** USB Device Descriptor. See USB 1.1 spec, pp. 196 - 198 */
struct usb_device_descriptor {
uint8_t blength; /**< Size of this descriptor in bytes. */
uint8_t bdescriptortype; /**< DEVICE Descriptor Type. */
uint16_t bcdusb; /**< USB specification release number (BCD). */
uint8_t bdeviceclass; /**< Class code. */
uint8_t bdevicesubclass; /**< Subclass code. */
uint8_t bdeviceprotocol; /**< Protocol code. */
uint8_t bmaxpacketsize0; /**< Maximum packet size for EP0 (8, 16, 32, 64). */
uint16_t idvendor; /**< USB Vendor ID. */
uint16_t idproduct; /**< USB Product ID. */
uint16_t bcddevice; /**< Device Release Number (BCD). */
uint8_t imanufacturer; /**< Index of manufacturer string descriptor. */
uint8_t iproduct; /**< Index of product string descriptor. */
uint8_t iserialnumber; /**< Index of string descriptor containing serial #. */
uint8_t bnumconfigurations; /**< Number of possible configurations. */
};
/** USB Configuration Descriptor. See USB 1.1 spec, pp. 199 - 200 */
struct usb_config_descriptor {
uint8_t blength; /**< Size of this descriptor in bytes. */
uint8_t bdescriptortype; /**< CONFIGURATION descriptor type. */
uint16_t wtotallength; /**< Combined total length of all descriptors. */
uint8_t bnuminterfaces; /**< Number of interfaces in this configuration. */
uint8_t bconfigurationvalue; /**< Value used to select this configuration. */
uint8_t iconfiguration; /**< Index of configuration string descriptor. */
uint8_t bmattributes; /**< Configuration characteristics. */
uint8_t maxpower; /**< Maximum power consumption in 2 mA units. */
};
/** USB Interface Descriptor. See USB 1.1 spec, pp. 201 - 203 */
struct usb_interface_descriptor {
uint8_t blength; /**< Size of this descriptor in bytes. */
uint8_t bdescriptortype; /**< INTERFACE descriptor type. */
uint8_t binterfacenumber; /**< Interface number. */
uint8_t balternatesetting; /**< Value used to select alternate setting. */
uint8_t bnumendpoints; /**< Number of endpoints used by this interface. */
uint8_t binterfaceclass; /**< Class code. */
uint8_t binterfacesubclass; /**< Subclass code. */
uint8_t binterfaceprotocol; /**< Protocol code. */
uint8_t iinterface; /**< Index of interface string descriptor. */
};
/** USB Endpoint Descriptor. See USB 1.1 spec, pp. 203 - 204 */
struct usb_endpoint_descriptor {
uint8_t blength; /**< Size of this descriptor in bytes. */
uint8_t bdescriptortype; /**< ENDPOINT descriptor type. */
uint8_t bendpointaddress; /**< Endpoint Address: IN/OUT + EP number. */
uint8_t bmattributes; /**< Endpoint Attributes: BULK/INTR/ISO/CTRL. */
uint16_t wmaxpacketsize; /**< Maximum packet size for this endpoint. */
uint8_t binterval; /**< Polling interval (in ms) for this endpoint. */
};
/** USB Language Descriptor. See USB 1.1 spec, pp. 204 - 205 */
struct usb_language_descriptor {
uint8_t blength; /**< Size of this descriptor in bytes. */
uint8_t bdescriptortype; /**< STRING descriptor type. */
uint16_t wlangid[]; /**< LANGID codes. */
};
/** USB String Descriptor. See USB 1.1 spec, pp. 204 - 205 */
struct usb_string_descriptor {
uint8_t blength; /**< Size of this descriptor in bytes. */
uint8_t bdescriptortype; /**< STRING descriptor type. */
uint16_t bstring[]; /**< UNICODE encoded string. */
};
/********************** USB Control Endpoint 0 related *********************/
/** USB Control Setup Data. See USB 1.1 spec, pp. 183 - 185 */
struct setup_data {
uint8_t bmrequesttype; /**< Characteristics of a request. */
uint8_t brequest; /**< Specific request. */
uint16_t wvalue; /**< Field that varies according to request. */
uint16_t windex; /**< Field that varies according to request. */
uint16_t wlength; /**< Number of bytes to transfer in data stage. */
};
/* External declarations for variables that need to be accessed outside of
* the USB module */
extern volatile bool ep1_out;
extern volatile bool ep1_in;
extern volatile __xdata __at 0xE6B8 struct setup_data setup_data;
/*
* USB Request Types (bmRequestType): See USB 1.1 spec, page 183, table 9-2
*
* Bit 7: Data transfer direction
* 0 = Host-to-device
* 1 = Device-to-host
* Bit 6...5: Type
* 0 = Standard
* 1 = Class
* 2 = Vendor
* 3 = Reserved
* Bit 4...0: Recipient
* 0 = Device
* 1 = Interface
* 2 = Endpoint
* 3 = Other
* 4...31 = Reserved
*/
#define USB_DIR_OUT 0x00
#define USB_DIR_IN 0x80
#define USB_REQ_TYPE_STANDARD (0x00 << 5)
#define USB_REQ_TYPE_CLASS (0x01 << 5)
#define USB_REQ_TYPE_VENDOR (0x02 << 5)
#define USB_REQ_TYPE_RESERVED (0x03 << 5)
#define USB_RECIP_DEVICE 0x00
#define USB_RECIP_INTERFACE 0x01
#define USB_RECIP_ENDPOINT 0x02
#define USB_RECIP_OTHER 0x03
/* Clear Interface Request */
#define CF_DEVICE (USB_DIR_OUT | USB_REQ_TYPE_STANDARD | USB_RECIP_DEVICE)
#define CF_INTERFACE (USB_DIR_OUT | USB_REQ_TYPE_STANDARD | USB_RECIP_INTERFACE)
#define CF_ENDPOINT (USB_DIR_OUT | USB_REQ_TYPE_STANDARD | USB_RECIP_ENDPOINT)
/* Get Configuration Request */
#define GC_DEVICE (USB_DIR_IN | USB_REQ_TYPE_STANDARD | USB_RECIP_DEVICE)
/* Get Descriptor Request */
#define GD_DEVICE (USB_DIR_IN | USB_REQ_TYPE_STANDARD | USB_RECIP_DEVICE)
/* Get Interface Request */
#define GI_INTERFACE (USB_DIR_IN | USB_REQ_TYPE_STANDARD | USB_RECIP_INTERFACE)
/* Get Status Request: See USB 1.1 spec, page 190 */
#define GS_DEVICE (USB_DIR_IN | USB_REQ_TYPE_STANDARD | USB_RECIP_DEVICE)
#define GS_INTERFACE (USB_DIR_IN | USB_REQ_TYPE_STANDARD | USB_RECIP_INTERFACE)
#define GS_ENDPOINT (USB_DIR_IN | USB_REQ_TYPE_STANDARD | USB_RECIP_ENDPOINT)
/* Set Address Request is handled by EZ-USB core */
/* Set Configuration Request */
#define SC_DEVICE (USB_DIR_OUT | USB_REQ_TYPE_STANDARD | USB_RECIP_DEVICE)
/* Set Descriptor Request */
#define SD_DEVICE (USB_DIR_OUT | USB_REQ_TYPE_STANDARD | USB_RECIP_DEVICE)
/* Set Feature Request */
#define SF_DEVICE (USB_DIR_OUT | USB_REQ_TYPE_STANDARD | USB_RECIP_DEVICE)
#define SF_INTERFACE (USB_DIR_OUT | USB_REQ_TYPE_STANDARD | USB_RECIP_INTERFACE)
#define SF_ENDPOINT (USB_DIR_OUT | USB_REQ_TYPE_STANDARD | USB_RECIP_ENDPOINT)
/* Set Interface Request */
#define SI_INTERFACE (USB_DIR_OUT | USB_REQ_TYPE_STANDARD | USB_RECIP_INTERFACE)
/* Synch Frame Request */
#define SY_ENDPOINT (USB_DIR_IN | USB_REQ_TYPE_STANDARD | USB_RECIP_ENDPOINT)
/* USB Requests (bRequest): See USB 1.1 spec, table 9-4 on page 187 */
#define GET_STATUS 0
#define CLEAR_FEATURE 1
/* Value '2' is reserved for future use */
#define SET_FEATURE 3
/* Value '4' is reserved for future use */
#define SET_ADDRESS 5
#define GET_DESCRIPTOR 6
#define SET_DESCRIPTOR 7
#define GET_CONFIGURATION 8
#define SET_CONFIGURATION 9
#define GET_INTERFACE 10
#define SET_INTERFACE 11
#define SYNCH_FRAME 12
/* Standard Feature Selectors: See USB 1.1 spec, table 9-6 on page 188 */
#define DEVICE_REMOTE_WAKEUP 1
#define ENDPOINT_HALT 0
/************************** EZ-USB specific stuff **************************/
/** USB Interrupts. See AN2131-TRM, page 9-4 for details */
enum usb_isr {
SUDAV_ISR = 13,
SOF_ISR,
SUTOK_ISR,
SUSPEND_ISR,
USBRESET_ISR,
HIGHSPEED_ISR,
EP0ACK_ISR,
STUB_ISR,
EP0IN_ISR,
EP0OUT_ISR,
EP1IN_ISR,
EP1OUT_ISR,
EP2_ISR,
EP4_ISR,
EP6_ISR,
EP8_ISR,
IBN_ISR,
EP0PINGNAK_ISR,
EP1PINGNAK_ISR,
EP2PINGNAK_ISR,
EP4PINGNAK_ISR,
EP6PINGNAK_ISR,
EP8PINGNAK_ISR,
ERRORLIMIT_ISR,
EP2PIDERROR_ISR,
EP4PIDERROR_ISR,
EP6PIDERROR_ISR,
EP8PIDERROR_ISR,
EP2PFLAG_ISR,
EP4PFLAG_ISR,
EP6PFLAG_ISR,
EP8PFLAG_ISR,
EP2EFLAG_ISR,
EP4EFLAG_ISR,
EP6EFLAG_ISR,
EP8EFLAG_ISR,
EP2FFLAG_ISR,
EP4FFLAG_ISR,
EP6FFLAG_ISR,
EP8FFLAG_ISR,
GPIFCOMPLETE_ISR,
GPIFWAVEFORM_ISR
};
/*************************** Function Prototypes ***************************/
__xdata uint8_t *usb_get_endpoint_cs_reg(uint8_t ep);
void usb_reset_data_toggle(uint8_t ep);
bool usb_handle_get_status(void);
bool usb_handle_clear_feature(void);
bool usb_handle_set_feature(void);
bool usb_handle_get_descriptor(void);
void usb_handle_set_interface(void);
void usb_handle_setup_data(void);
void ep_init(void);
void interrupt_init(void);
void io_init(void);
#endif

View File

@ -0,0 +1,125 @@
; SPDX-License-Identifier: GPL-2.0-or-later
;****************************************************************************
; File : USBJmpTb.a51 *
; Contents : Interruptions vector configuration. *
; Based on openULINK project code by: Martin Schmoelzer. *
; Copyright 2023, Ahmed Errached BOUDJELIDA, NanoXplore SAS. *
; <aboudjelida@nanoxplore.com> *
; <ahmederrachedbjld@gmail.com> *
;****************************************************************************
.module JUMPTABLE
.globl USB_AutoVector
.globl USB_Jump_Table
.globl _sudav_isr, _sof_isr, _sutok_isr, _suspend_isr, _usbreset_isr, _highspeed_isr, _ep0ack_isr, _stub_isr, _ep0in_isr, _ep0out_isr, _ep1in_isr, _ep1out_isr, _ep2_isr, _ep4_isr, _ep6_isr, _ep8_isr, _ibn_isr
.globl _ep0pingnak_isr, _ep1pingnak_isr, _ep2pingnak_isr, _ep4pingnak_isr, _ep6pingnak_isr, _ep8pingnak_isr, _errorlimit_isr, _stub_isr, _stub_isr, _stub_isr, _ep2piderror_isr, _ep4piderror_isr, _ep6piderror_isr, _ep8piderror_isr
.globl _ep2pflag_isr, _ep4pflag_isr, _ep6pflag_isr, _ep8pflag_isr, _ep2eflag_isr, _ep4eflag_isr, _ep6eflag_isr, _ep8eflag_isr, _ep2fflag_isr, _ep4fflag_isr, _ep6fflag_isr, _ep8fflag_isr, _gpifcomplete_isr, _gpifwaveform_isr
;--------------------------------------------------------------------------;
; Interrupt Vectors ;
;--------------------------------------------------------------------------;
.area USB_JV (ABS,OVR) ; Absolute, Overlay
.org 0x43 ; USB interrupt (INT2) jumps here
USB_AutoVector = #. + 2
ljmp USB_Jump_Table ; Autovector will replace byte 45
;--------------------------------------------------------------------------;
; USB Jump Table ;
;--------------------------------------------------------------------------;
.area USB_JT (ABS) ; Absolute placement
.org 0x0200 ; Place jump table at 0x0200
USB_Jump_Table: ; autovector jump table
ljmp _sudav_isr ; (00) Setup Data Available
.db 0
ljmp _sof_isr ; (04) Start of Frame
.db 0
ljmp _sutok_isr ; (08) Setup Data Loading
.db 0
ljmp _suspend_isr ; (0C) Global Suspend
.db 0
ljmp _usbreset_isr ; (10) USB Reset
.db 0
ljmp _highspeed_isr ; (14) Entered High Speed
.db 0
ljmp _ep0ack_isr ; (18) EP0ACK
.db 0
ljmp _stub_isr ; (1C) Reserved
.db 0
ljmp _ep0in_isr ; (20) EP0 In
.db 0
ljmp _ep0out_isr ; (24) EP0 Out
.db 0
ljmp _ep1in_isr ; (28) EP1 In
.db 0
ljmp _ep1out_isr ; (2C) EP1 Out
.db 0
ljmp _ep2_isr ; (30) EP2 In/Out
.db 0
ljmp _ep4_isr ; (34) EP4 In/Out
.db 0
ljmp _ep6_isr ; (38) EP6 In/Out
.db 0
ljmp _ep8_isr ; (3C) EP8 In/Out
.db 0
ljmp _ibn_isr ; (40) IBN
.db 0
ljmp _stub_isr ; (44) Reserved
.db 0
ljmp _ep0pingnak_isr ; (48) EP0 PING NAK
.db 0
ljmp _ep1pingnak_isr ; (4C) EP1 PING NAK
.db 0
ljmp _ep2pingnak_isr ; (50) EP2 PING NAK
.db 0
ljmp _ep4pingnak_isr ; (54) EP4 PING NAK
.db 0
ljmp _ep6pingnak_isr ; (58) EP6 PING NAK
.db 0
ljmp _ep8pingnak_isr ; (5C) EP8 PING NAK
.db 0
ljmp _errorlimit_isr ; (60) Error Limit
.db 0
ljmp _stub_isr ; (64) Reserved
.db 0
ljmp _stub_isr ; (68) Reserved
.db 0
ljmp _stub_isr ; (6C) Reserved
.db 0
ljmp _ep2piderror_isr ; (70) EP2 ISO Pid Sequence Error
.db 0
ljmp _ep4piderror_isr ; (74) EP4 ISO Pid Sequence Error
.db 0
ljmp _ep6piderror_isr ; (78) EP6 ISO Pid Sequence Error
.db 0
ljmp _ep8piderror_isr ; (7C) EP8 ISO Pid Sequence Error
.db 0
ljmp _ep2pflag_isr ; (80) EP2 Programmable Flag
.db 0
ljmp _ep4pflag_isr ; (84) EP4 Programmable Flag
.db 0
ljmp _ep6pflag_isr ; (88) EP6 Programmable Flag
.db 0
ljmp _ep8pflag_isr ; (8C) EP8 Programmable Flag
.db 0
ljmp _ep2eflag_isr ; (90) EP2 Empty Flag
.db 0
ljmp _ep4eflag_isr ; (94) EP4 Empty Flag
.db 0
ljmp _ep6eflag_isr ; (98) EP6 Empty Flag
.db 0
ljmp _ep8eflag_isr ; (9C) EP8 Empty Flag
.db 0
ljmp _ep2fflag_isr ; (A0) EP2 Full Flag
.db 0
ljmp _ep4fflag_isr ; (A4) EP4 Full Flag
.db 0
ljmp _ep6fflag_isr ; (A8) EP6 Full Flag
.db 0
ljmp _ep8fflag_isr ; (AC) EP8 Full Flag
.db 0
ljmp _gpifcomplete_isr ; (B0) GPIF Operation Complete
.db 0
ljmp _gpifwaveform_isr ; (B4) GPIF Waveform
.db 0

View File

@ -0,0 +1,49 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/****************************************************************************
File : delay.c *
Contents : Delays handling fucntions code for NanoXplore *
USB-JTAG ANGIE adapter hardware. *
Based on openULINK project code by: Martin Schmoelzer. *
Copyright 2023, Ahmed Errached BOUDJELIDA, NanoXplore SAS. *
<aboudjelida@nanoxplore.com> *
<ahmederrachedbjld@gmail.com> *
*****************************************************************************/
#include "delay.h"
#include <mcs51/compiler.h>
void syncdelay(uint8_t count)
{
for (uint8_t i = 0; i < count; i++)
NOP();
}
void delay_5us(void)
{
NOP();
}
void delay_1ms(void)
{
uint16_t i;
for (i = 0; i < 598; i++)
;
}
void delay_us(uint16_t delay)
{
uint16_t i;
uint16_t maxcount = (delay / 5);
for (i = 0; i < maxcount; i++)
delay_5us();
}
void delay_ms(uint16_t delay)
{
uint16_t i;
for (i = 0; i < delay; i++)
delay_1ms();
}

View File

@ -0,0 +1,98 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
This program configures the General Programmable Interface (GPIF) for FX2.
Please do not modify sections of text which are marked as "DO NOT EDIT ...".
*/
/* GPIF Program Code */
#include "reg_ezusb.h"
#include "delay.h"
/****************************** GPIF PROGRAM CODE ********************************/
/* DO NOT EDIT ... */
const char wavedata[128] = {
/* Wave 0 */
/* LenBr */ 0x01, 0x3F, 0x01, 0x01, 0x01, 0x01, 0x01, 0x07,
/* Opcode*/ 0x02, 0x07, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00,
/* Output*/ 0x04, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
/* LFun */ 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F,
/* Wave 1 */
/* LenBr */ 0x88, 0x01, 0x3F, 0x01, 0x01, 0x01, 0x01, 0x07,
/* Opcode*/ 0x01, 0x02, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00,
/* Output*/ 0x07, 0x05, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
/* LFun */ 0x09, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x3F,
/* Wave 2 */
/* LenBr */ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x07,
/* Opcode*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* Output*/ 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
/* LFun */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F,
/* Wave 3 */
/* LenBr */ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x07,
/* Opcode*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* Output*/ 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
/* LFun */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F,
};
/* END DO NOT EDIT */
/* DO NOT EDIT ... */
const char flowstates[36] = {
/* Wave 0 flowstates */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* Wave 1 flowstates */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* Wave 2 flowstates */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* Wave 3 flowstates */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
};
/* END DO NOT EDIT */
/* DO NOT EDIT ... */
const char initdata[7] = {
/* Regs */ 0xE0, 0x00, 0x00, 0x07, 0xEE, 0xF2, 0x00
};
/* END DO NOT EDIT */
void gpif_init(void)
{
uint8_t i;
IFCONFIG = 0xEE;
GPIFABORT = 0xFF; /* abort any waveforms pending */
GPIFREADYCFG = initdata[0];
GPIFCTLCFG = initdata[1];
GPIFIDLECS = initdata[2];
GPIFIDLECTL = initdata[3];
GPIFWFSELECT = initdata[5];
GPIFREADYSTAT = initdata[6];
/* use dual autopointer feature... */
AUTOPTRSETUP = 0x07;
/* source */
AUTOPTRH1 = (uint8_t)(((uint16_t)(&wavedata) >> 8) & 0xff);
AUTOPTRL1 = (uint8_t)((uint16_t)(&wavedata) & 0xff);
/* destination */
AUTOPTRH2 = 0xE4;
AUTOPTRL2 = 0x00;
/* transfer */
for (i = 0x00; i < 128; i++)
EXTAUTODAT2 = EXTAUTODAT1;
/* GPIF address pins update when GPIFADRH/L written */
syncdelay(3);
GPIFADRH = 0x00; /* bits[7:1] always 0 */
syncdelay(3);
GPIFADRL = 0x00; /* point to PERIPHERAL address 0x0000 */
/* Configure GPIF flowstates registers for Wave 0 of wavedata */
FLOWSTATE = flowstates[0];
FLOWLOGIC = flowstates[1];
FLOWEQ0CTL = flowstates[2];
FLOWEQ1CTL = flowstates[3];
FLOWHOLDOFF = flowstates[4];
FLOWSTB = flowstates[5];
FLOWSTBEDGE = flowstates[6];
FLOWSTBHPERIOD = flowstates[7];
}

View File

@ -0,0 +1,674 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/****************************************************************************
File : jtag.c *
Contents : Jtag handling functions code for NanoXplore *
USB-JTAG ANGIE adapter hardware. *
Based on openULINK project code by: Martin Schmoelzer. *
Copyright 2023, Ahmed Errached BOUDJELIDA, NanoXplore SAS. *
<aboudjelida@nanoxplore.com> *
<ahmederrachedbjld@gmail.com> *
*****************************************************************************/
#include "jtag.h"
#include "io.h"
#include "msgtypes.h"
#include "reg_ezusb.h"
#include <stdbool.h>
#include <serial.h>
#include <stdio.h>
/** Delay value for SCAN_IN operations with less than maximum TCK frequency */
uint8_t delay_scan_in;
/** Delay value for SCAN_OUT operations with less than maximum TCK frequency */
uint8_t delay_scan_out;
/** Delay value for SCAN_IO operations with less than maximum TCK frequency */
uint8_t delay_scan_io;
/** Delay value for CLOCK_TCK operations with less than maximum frequency */
uint8_t delay_tck;
/** Delay value for CLOCK_TMS operations with less than maximum frequency */
uint8_t delay_tms;
/**
* Perform JTAG SCAN-IN operation at maximum TCK frequency.
*
* Dummy data is shifted into the JTAG chain via TDI, TDO data is sampled and
* stored in the EP2 IN buffer.
*
* Maximum achievable TCK frequency is 182 kHz for ANGIE clocked at 24 MHz.
*
* @param out_offset offset in EP1OUTBUF where payload data starts
* @param in_offset
*/
void jtag_scan_in(uint8_t out_offset, uint8_t in_offset)
{
uint8_t scan_size_bytes, bits_last_byte;
uint8_t tms_count_start, tms_count_end;
uint8_t tms_sequence_start, tms_sequence_end;
uint8_t tdo_data, i, j;
uint8_t outb_buffer;
/* Get parameters from EP1OUTBUF */
scan_size_bytes = EP1OUTBUF[out_offset];
bits_last_byte = EP1OUTBUF[out_offset + 1];
tms_count_start = (EP1OUTBUF[out_offset + 2] >> 4) & 0x0F;
tms_count_end = EP1OUTBUF[out_offset + 2] & 0x0F;
tms_sequence_start = EP1OUTBUF[out_offset + 3];
tms_sequence_end = EP1OUTBUF[out_offset + 4];
if (tms_count_start > 0)
jtag_clock_tms(tms_count_start, tms_sequence_start);
outb_buffer = IOB & ~(bmbit1 | bmbit2 | bmbit3);
/* Shift all bytes except the last byte */
for (i = 0; i < scan_size_bytes - 1; i++) {
tdo_data = 0;
for (j = 0; j < 8; j++) {
IOB = outb_buffer; /* TCK changes here */
tdo_data = tdo_data >> 1;
IOB = (outb_buffer | bmbit2);
if (PIN_TDO)
tdo_data |= 0x80;
}
/* Copy TDO data to EP1INBUF */
EP1INBUF[i + in_offset] = tdo_data;
}
tdo_data = 0;
/* Shift the last byte */
for (j = 0; j < bits_last_byte; j++) {
/* Assert TMS signal if requested and this is the last bit */
if (j == (bits_last_byte - 1) && tms_count_end > 0) {
outb_buffer |= bmbit1;
tms_count_end--;
tms_sequence_end = tms_sequence_end >> 1;
}
IOB = outb_buffer; /* TCK changes here */
tdo_data = tdo_data >> 1;
IOB = (outb_buffer | bmbit2);
if (PIN_TDO)
tdo_data |= 0x80;
}
tdo_data = tdo_data >> (8 - bits_last_byte);
/* Copy TDO data to EP1INBUF */
EP1INBUF[i + in_offset] = tdo_data;
/* Move to correct end state */
if (tms_count_end > 0)
jtag_clock_tms(tms_count_end, tms_sequence_end);
}
/**
* Perform JTAG SCAN-IN operation at variable TCK frequency.
*
* Dummy data is shifted into the JTAG chain via TDI, TDO data is sampled and
* stored in the EP2 IN buffer.
*
* Maximum achievable TCK frequency is 113 kHz for ANGIE clocked at 24 MHz.
*
* @param out_offset offset in EP1OUTBUF where payload data starts
* @param in_offset
*/
void jtag_slow_scan_in(uint8_t out_offset, uint8_t in_offset)
{
uint8_t scan_size_bytes, bits_last_byte;
uint8_t tms_count_start, tms_count_end;
uint8_t tms_sequence_start, tms_sequence_end;
uint8_t tdo_data, i, j, k;
uint8_t outb_buffer;
/* Get parameters from EP1OUTBUF */
scan_size_bytes = EP1OUTBUF[out_offset];
bits_last_byte = EP1OUTBUF[out_offset + 1];
tms_count_start = (EP1OUTBUF[out_offset + 2] >> 4) & 0x0F;
tms_count_end = EP1OUTBUF[out_offset + 2] & 0x0F;
tms_sequence_start = EP1OUTBUF[out_offset + 3];
tms_sequence_end = EP1OUTBUF[out_offset + 4];
if (tms_count_start > 0)
jtag_slow_clock_tms(tms_count_start, tms_sequence_start);
outb_buffer = IOB & ~(bmbit3 | bmbit2 | bmbit1);
/* Shift all bytes except the last byte */
for (i = 0; i < scan_size_bytes - 1; i++) {
tdo_data = 0;
for (j = 0; j < 8; j++) {
IOB = outb_buffer; /* TCK changes here */
for (k = 0; k < delay_scan_in; k++)
;
tdo_data = tdo_data >> 1;
IOB = (outb_buffer | bmbit2);
for (k = 0; k < delay_scan_in; k++)
;
if (PIN_TDO)
tdo_data |= 0x80;
}
/* Copy TDO data to EP1INBUF */
EP1INBUF[i + in_offset] = tdo_data;
}
tdo_data = 0;
/* Shift the last byte */
for (j = 0; j < bits_last_byte; j++) {
/* Assert TMS signal if requested and this is the last bit */
if (j == (bits_last_byte - 1) && tms_count_end > 0) {
outb_buffer |= bmbit1;
tms_count_end--;
tms_sequence_end = tms_sequence_end >> 1;
}
IOB = outb_buffer; /* TCK changes here */
for (k = 0; k < delay_scan_in; k++)
;
tdo_data = tdo_data >> 1;
IOB = (outb_buffer | bmbit2);
for (k = 0; k < delay_scan_in; k++)
;
if (PIN_TDO)
tdo_data |= 0x80;
}
tdo_data = tdo_data >> (8 - bits_last_byte);
/* Copy TDO data to EP1INBUF */
EP1INBUF[i + in_offset] = tdo_data;
/* Move to correct end state */
if (tms_count_end > 0)
jtag_slow_clock_tms(tms_count_end, tms_sequence_end);
}
/**
* Perform JTAG SCAN-OUT operation at maximum TCK frequency.
*
* Data stored in EP2 OUT buffer is shifted into the JTAG chain via TDI, TDO
* data is not sampled.
* The TAP-FSM state is always left in the PAUSE-DR/PAUSE-IR state.
*
* Maximum achievable TCK frequency is 142 kHz for ANGIE clocked at 24 MHz.
*
* @param out_offset offset in EP1OUTBUF where payload data starts
*/
void jtag_scan_out(uint8_t out_offset)
{
uint8_t scan_size_bytes, bits_last_byte;
uint8_t tms_count_start, tms_count_end;
uint8_t tms_sequence_start, tms_sequence_end;
uint8_t tdi_data, i, j;
uint8_t outb_buffer;
/* Get parameters from EP1OUTBUF */
scan_size_bytes = EP1OUTBUF[out_offset];
bits_last_byte = EP1OUTBUF[out_offset + 1];
tms_count_start = (EP1OUTBUF[out_offset + 2] >> 4) & 0x0F;
tms_count_end = EP1OUTBUF[out_offset + 2] & 0x0F;
tms_sequence_start = EP1OUTBUF[out_offset + 3];
tms_sequence_end = EP1OUTBUF[out_offset + 4];
if (tms_count_start > 0)
jtag_clock_tms(tms_count_start, tms_sequence_start);
outb_buffer = IOB & ~(bmbit2 | bmbit1);
/* Shift all bytes except the last byte */
for (i = 0; i < scan_size_bytes - 1; i++) {
tdi_data = EP1OUTBUF[i + out_offset + 5];
for (j = 0; j < 8; j++) {
if (tdi_data & 0x01)
outb_buffer |= bmbit3;
else
outb_buffer &= ~bmbit3;
IOB = outb_buffer; /* TDI and TCK change here */
tdi_data = tdi_data >> 1;
IOB = (outb_buffer | bmbit2);
}
}
tdi_data = EP1OUTBUF[i + out_offset + 5];
/* Shift the last byte */
for (j = 0; j < bits_last_byte; j++) {
if (tdi_data & 0x01)
outb_buffer |= bmbit3;
else
outb_buffer &= ~bmbit3;
/* Assert TMS signal if requested and this is the last bit */
if (j == (bits_last_byte - 1) && tms_count_end > 0) {
outb_buffer |= bmbit1;
tms_count_end--;
tms_sequence_end = tms_sequence_end >> 1;
}
IOB = outb_buffer; /* TDI and TCK change here */
tdi_data = tdi_data >> 1;
IOB = (outb_buffer | bmbit2);
}
/* Move to correct end state */
if (tms_count_end > 0)
jtag_clock_tms(tms_count_end, tms_sequence_end);
}
/**
* Perform JTAG SCAN-OUT operation at maximum TCK frequency.
*
* Data stored in EP2 OUT buffer is shifted into the JTAG chain via TDI, TDO
* data is not sampled.
* The TAP-FSM state is always left in the PAUSE-DR/PAUSE-IR state.
*
* Maximum achievable TCK frequency is 97 kHz for ANGIE clocked at 24 MHz.
*
* @param out_offset offset in EP1OUTBUF where payload data starts
*/
void jtag_slow_scan_out(uint8_t out_offset)
{
uint8_t scan_size_bytes, bits_last_byte;
uint8_t tms_count_start, tms_count_end;
uint8_t tms_sequence_start, tms_sequence_end;
uint8_t tdi_data, i, j, k;
uint8_t outb_buffer;
/* Get parameters from EP1OUTBUF */
scan_size_bytes = EP1OUTBUF[out_offset];
bits_last_byte = EP1OUTBUF[out_offset + 1];
tms_count_start = (EP1OUTBUF[out_offset + 2] >> 4) & 0x0F;
tms_count_end = EP1OUTBUF[out_offset + 2] & 0x0F;
tms_sequence_start = EP1OUTBUF[out_offset + 3];
tms_sequence_end = EP1OUTBUF[out_offset + 4];
if (tms_count_start > 0)
jtag_slow_clock_tms(tms_count_start, tms_sequence_start);
outb_buffer = IOB & ~(bmbit2 | bmbit1);
/* Shift all bytes except the last byte */
for (i = 0; i < scan_size_bytes - 1; i++) {
tdi_data = EP1OUTBUF[i + out_offset + 5];
for (j = 0; j < 8; j++) {
if (tdi_data & 0x01)
outb_buffer |= bmbit3;
else
outb_buffer &= ~bmbit3;
IOB = outb_buffer; /* TDI and TCK change here */
for (k = 0; k < delay_scan_out; k++)
;
tdi_data = tdi_data >> 1;
IOB = (outb_buffer | bmbit2);
for (k = 0; k < delay_scan_out; k++)
;
}
}
tdi_data = EP1OUTBUF[i + out_offset + 5];
/* Shift the last byte */
for (j = 0; j < bits_last_byte; j++) {
if (tdi_data & 0x01)
outb_buffer |= bmbit3;
else
outb_buffer &= ~bmbit3;
/* Assert TMS signal if requested and this is the last bit */
if (j == (bits_last_byte - 1) && tms_count_end > 0) {
outb_buffer |= bmbit1;
tms_count_end--;
tms_sequence_end = tms_sequence_end >> 1;
}
IOB = outb_buffer; /* TDI and TCK change here */
for (k = 0; k < delay_scan_out; k++)
;
tdi_data = tdi_data >> 1;
IOB = (outb_buffer | bmbit2);
for (k = 0; k < delay_scan_out; k++)
;
}
/* Move to correct end state */
if (tms_count_end > 0)
jtag_slow_clock_tms(tms_count_end, tms_sequence_end);
}
/**
* Perform bidirectional JTAG SCAN operation at maximum TCK frequency.
*
* Data stored in EP2 OUT buffer is shifted into the JTAG chain via TDI, TDO
* data is sampled and stored in the EP2 IN buffer.
* The TAP-FSM state is always left in the PAUSE-DR/PAUSE-IR state.
*
* Maximum achievable TCK frequency is 100 kHz for ANGIE clocked at 24 MHz.
*
* @param out_offset offset in EP1OUTBUF where payload data starts
* @param in_offset
*/
int it;
void jtag_scan_io(uint8_t out_offset, uint8_t in_offset)
{
uint8_t scan_size_bytes, bits_last_byte;
uint8_t tms_count_start, tms_count_end;
uint8_t tms_sequence_start, tms_sequence_end;
uint8_t tdi_data, tdo_data, i, j;
uint8_t outb_buffer;
it++;
/* Get parameters from EP1OUTBUF */
scan_size_bytes = EP1OUTBUF[out_offset];
bits_last_byte = EP1OUTBUF[out_offset + 1];
tms_count_start = (EP1OUTBUF[out_offset + 2] >> 4) & 0x0F;
tms_count_end = EP1OUTBUF[out_offset + 2] & 0x0F;
tms_sequence_start = EP1OUTBUF[out_offset + 3];
tms_sequence_end = EP1OUTBUF[out_offset + 4];
if (tms_count_start > 0)
jtag_clock_tms(tms_count_start, tms_sequence_start);
outb_buffer = IOB & ~(bmbit2 | bmbit1);
/* Shift all bytes except the last byte */
for (i = 0; i < scan_size_bytes - 1; i++) {
tdi_data = EP1OUTBUF[i + out_offset + 5];
tdo_data = 0;
for (j = 0; j < 8; j++) {
if (tdi_data & 0x01)
outb_buffer |= bmbit3;
else
outb_buffer &= ~bmbit3;
IOB = outb_buffer; /* TDI and TCK change here */
tdi_data = tdi_data >> 1;
IOB = (outb_buffer | bmbit2);
tdo_data = tdo_data >> 1;
if (PIN_TDO)
tdo_data |= 0x80;
}
/* Copy TDO data to EP1INBUF */
EP1INBUF[i + in_offset] = tdo_data;
}
tdi_data = EP1OUTBUF[i + out_offset + 5];
tdo_data = 0;
/* Shift the last byte */
for (j = 0; j < bits_last_byte; j++) {
if (tdi_data & 0x01)
outb_buffer |= bmbit3;
else
outb_buffer &= ~bmbit3;
/* Assert TMS signal if requested and this is the last bit */
if (j == (bits_last_byte - 1) && tms_count_end > 0) {
outb_buffer |= bmbit1;
tms_count_end--;
tms_sequence_end = tms_sequence_end >> 1;
}
IOB = outb_buffer; /* TDI and TCK change here */
tdi_data = tdi_data >> 1;
IOB = (outb_buffer | bmbit2);
tdo_data = tdo_data >> 1;
if (PIN_TDO)
tdo_data |= 0x80;
}
tdo_data = tdo_data >> (8 - bits_last_byte);
/* Copy TDO data to EP1INBUF */
EP1INBUF[i + in_offset] = tdo_data;
/* Move to correct end state */
if (tms_count_end > 0)
jtag_clock_tms(tms_count_end, tms_sequence_end);
}
/**
* Perform bidirectional JTAG SCAN operation at maximum TCK frequency.
*
* Data stored in EP2 OUT buffer is shifted into the JTAG chain via TDI, TDO
* data is sampled and stored in the EP2 IN buffer.
* The TAP-FSM state is always left in the PAUSE-DR/PAUSE-IR state.
*
* Maximum achievable TCK frequency is 78 kHz for ANGIE clocked at 24 MHz.
*
* @param out_offset offset in EP1OUTBUF where payload data starts
* @param in_offset
*/
void jtag_slow_scan_io(uint8_t out_offset, uint8_t in_offset)
{
uint8_t scan_size_bytes, bits_last_byte;
uint8_t tms_count_start, tms_count_end;
uint8_t tms_sequence_start, tms_sequence_end;
uint8_t tdi_data, tdo_data, i, j, k;
uint8_t outb_buffer;
/* Get parameters from EP1OUTBUF */
scan_size_bytes = EP1OUTBUF[out_offset];
bits_last_byte = EP1OUTBUF[out_offset + 1];
tms_count_start = (EP1OUTBUF[out_offset + 2] >> 4) & 0x0F;
tms_count_end = EP1OUTBUF[out_offset + 2] & 0x0F;
tms_sequence_start = EP1OUTBUF[out_offset + 3];
tms_sequence_end = EP1OUTBUF[out_offset + 4];
if (tms_count_start > 0)
jtag_slow_clock_tms(tms_count_start, tms_sequence_start);
outb_buffer = IOB & ~(bmbit2 | bmbit1);
/* Shift all bytes except the last byte */
for (i = 0; i < scan_size_bytes - 1; i++) {
tdi_data = EP1OUTBUF[i + out_offset + 5];
tdo_data = 0;
for (j = 0; j < 8; j++) {
if (tdi_data & 0x01)
outb_buffer |= bmbit3;
else
outb_buffer &= ~bmbit3;
IOB = outb_buffer; /* TDI and TCK change here */
for (k = 0; k < delay_scan_io; k++)
;
tdi_data = tdi_data >> 1;
IOB = (outb_buffer | bmbit2);
for (k = 0; k < delay_scan_io; k++)
;
tdo_data = tdo_data >> 1;
if (PIN_TDO)
tdo_data |= 0x80;
}
/* Copy TDO data to EP1INBUF */
EP1INBUF[i + in_offset] = tdo_data;
}
tdi_data = EP1OUTBUF[i + out_offset + 5];
tdo_data = 0;
/* Shift the last byte */
for (j = 0; j < bits_last_byte; j++) {
if (tdi_data & 0x01)
outb_buffer |= bmbit3;
else
outb_buffer &= ~bmbit3;
/* Assert TMS signal if requested and this is the last bit */
if (j == (bits_last_byte - 1) && tms_count_end > 0) {
outb_buffer |= bmbit1;
tms_count_end--;
tms_sequence_end = tms_sequence_end >> 1;
}
IOB = outb_buffer; /* TDI and TCK change here */
for (k = 0; k < delay_scan_io; k++)
;
tdi_data = tdi_data >> 1;
IOB = (outb_buffer | bmbit2);
for (k = 0; k < delay_scan_io; k++)
;
tdo_data = tdo_data >> 1;
if (PIN_TDO)
tdo_data |= 0x80;
}
tdo_data = tdo_data >> (8 - bits_last_byte);
/* Copy TDO data to EP1INBUF */
EP1INBUF[i + in_offset] = tdo_data;
/* Move to correct end state */
if (tms_count_end > 0)
jtag_slow_clock_tms(tms_count_end, tms_sequence_end);
}
/**
* Generate TCK clock cycles.
*
* Maximum achievable TCK frequency is 375 kHz for ANGIE clocked at 24 MHz.
*
* @param count number of TCK clock cycles to generate.
*/
void jtag_clock_tck(uint16_t count)
{
uint16_t i;
uint8_t outb_buffer = IOB & ~(bmbit2);
for (i = 0; i < count; i++) {
IOB = outb_buffer;
IOB = outb_buffer | bmbit2;
}
}
/**
* Generate TCK clock cycles at variable frequency.
*
* Maximum achievable TCK frequency is 166.6 kHz for ANGIE clocked at 24 MHz.
*
* @param count number of TCK clock cycles to generate.
*/
void jtag_slow_clock_tck(uint16_t count)
{
uint16_t i;
uint8_t j;
uint8_t outb_buffer = IOB & ~(bmbit2);
for (i = 0; i < count; i++) {
IOB = outb_buffer;
for (j = 0; j < delay_tck; j++)
;
IOB = outb_buffer | bmbit2;
for (j = 0; j < delay_tck; j++)
;
}
}
/**
* Perform TAP FSM state transitions at maximum TCK frequency.
*
* Maximum achievable TCK frequency is 176 kHz for ANGIE clocked at 24 MHz.
*
* @param count the number of state transitions to perform.
* @param sequence the TMS pin levels for each state transition, starting with
* the least-significant bit.
*/
void jtag_clock_tms(uint8_t count, uint8_t sequence)
{
uint8_t outb_buffer = IOB & ~(bmbit2);
uint8_t i;
for (i = 0; i < count; i++) {
/* Set TMS pin according to sequence parameter */
if (sequence & 0x1)
outb_buffer |= bmbit1;
else
outb_buffer &= ~bmbit1;
IOB = outb_buffer;
sequence = sequence >> 1;
IOB = outb_buffer | bmbit2;
}
}
/**
* Perform TAP-FSM state transitions at less than maximum TCK frequency.
*
* Maximum achievable TCK frequency is 117 kHz for ANGIE clocked at 24 MHz.
*
* @param count the number of state transitions to perform.
* @param sequence the TMS pin levels for each state transition, starting with
* the least-significant bit.
*/
void jtag_slow_clock_tms(uint8_t count, uint8_t sequence)
{
uint8_t outb_buffer = IOB & ~(bmbit2);
uint8_t i, j;
for (i = 0; i < count; i++) {
/* Set TMS pin according to sequence parameter */
if (sequence & 0x1)
outb_buffer |= bmbit1;
else
outb_buffer &= ~bmbit1;
IOB = outb_buffer;
for (j = 0; j < delay_tms; j++)
;
sequence = sequence >> 1;
IOB = outb_buffer | bmbit2;
for (j = 0; j < delay_tms; j++)
;
}
}
uint16_t jtag_get_signals(void)
{
uint8_t input_signal_state, output_signal_state;
input_signal_state = 0;
output_signal_state = 0;
/* Get states of input pins */
if (PIN_TDO)
input_signal_state |= SIGNAL_TDO;
/* Get states of output pins */
output_signal_state = IOB & MASK_PORTB_DIRECTION_OUT;
return ((uint16_t)input_signal_state << 8) | ((uint16_t)output_signal_state);
}
/**
* Set state of JTAG output signals.
*
* @param low signals which should be de-asserted.
* @param high signals which should be asserted.
*/
void jtag_set_signals(uint8_t low, uint8_t high)
{
IOB &= ~(low & MASK_PORTB_DIRECTION_OUT);
IOB |= (high & MASK_PORTB_DIRECTION_OUT);
}
/**
* Configure TCK delay parameters.
*
* @param scan_in number of delay cycles in scan_in operations.
* @param scan_out number of delay cycles in scan_out operations.
* @param scan_io number of delay cycles in scan_io operations.
* @param tck number of delay cycles in clock_tck operations.
* @param tms number of delay cycles in clock_tms operations.
*/
void jtag_configure_tck_delay(uint8_t scan_in, uint8_t scan_out,
uint8_t scan_io, uint8_t tck, uint8_t tms)
{
delay_scan_in = scan_in;
delay_scan_out = scan_out;
delay_scan_io = scan_io;
delay_tck = tck;
delay_tms = tms;
}

View File

@ -0,0 +1,85 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/****************************************************************************
File : main.c *
Contents : main code for NanoXplore USB-JTAG ANGIE adapter *
hardware. *
Based on openULINK project code by: Martin Schmoelzer. *
Copyright 2023, Ahmed Errached BOUDJELIDA, NanoXplore SAS. *
<aboudjelida@nanoxplore.com> *
<ahmederrachedbjld@gmail.com> *
*****************************************************************************/
#include "usb.h"
#include "delay.h"
#include "protocol.h"
#include "reg_ezusb.h"
#include <serial.h>
#include <stdio.h>
extern void sudav_isr(void)__interrupt SUDAV_ISR;
extern void sof_isr(void)__interrupt;
extern void sutok_isr(void)__interrupt;
extern void suspend_isr(void)__interrupt;
extern void usbreset_isr(void)__interrupt;
extern void highspeed_isr(void)__interrupt;
extern void ep0ack_isr(void)__interrupt;
extern void stub_isr(void)__interrupt;
extern void ep0in_isr(void)__interrupt;
extern void ep0out_isr(void)__interrupt;
extern void ep1in_isr(void)__interrupt;
extern void ep1out_isr(void)__interrupt;
extern void ep2_isr(void)__interrupt;
extern void ep4_isr(void)__interrupt;
extern void ep6_isr(void)__interrupt;
extern void ep8_isr(void)__interrupt;
extern void ibn_isr(void)__interrupt;
extern void ep0pingnak_isr(void)__interrupt;
extern void ep1pingnak_isr(void)__interrupt;
extern void ep2pingnak_isr(void)__interrupt;
extern void ep4pingnak_isr(void)__interrupt;
extern void ep6pingnak_isr(void)__interrupt;
extern void ep8pingnak_isr(void)__interrupt;
extern void errorlimit_isr(void)__interrupt;
extern void ep2piderror_isr(void)__interrupt;
extern void ep4piderror_isr(void)__interrupt;
extern void ep6piderror_isr(void)__interrupt;
extern void ep8piderror_isr(void)__interrupt;
extern void ep2pflag_isr(void)__interrupt;
extern void ep4pflag_isr(void)__interrupt;
extern void ep6pflag_isr(void)__interrupt;
extern void ep8pflag_isr(void)__interrupt;
extern void ep2eflag_isr(void)__interrupt;
extern void ep4eflag_isr(void)__interrupt;
extern void ep6eflag_isr(void)__interrupt;
extern void ep8eflag_isr(void)__interrupt;
extern void ep2fflag_isr(void)__interrupt;
extern void ep4fflag_isr(void)__interrupt;
extern void ep6fflag_isr(void)__interrupt;
extern void ep8fflag_isr(void)__interrupt;
extern void gpifcomplete_isr(void)__interrupt;
extern void gpifwaveform_isr(void)__interrupt;
void gpif_init(void);
int main(void)
{
CPUCS = ((CPUCS & ~bmclkspd) | (CLK_48M << 3) | CLKOE); /* required for sio0_init */
sio0_init(57600); /* needed for printf */
ep_init();
gpif_init();
interrupt_init();
io_init();
/* Perform ReNumeration */
USBCS |= (DISCON | RENUM);
delay_ms(250);
USBCS &= ~DISCON;
/* Begin executing command(s). This function never returns. */
command_loop();
/* Never reached, but SDCC complains about missing return statement */
return 0;
}

View File

@ -0,0 +1,189 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/****************************************************************************
File : protocol.c *
Contents : Jtag commands handling protocol code for NanoXplore *
USB-JTAG ANGIE adapter hardware. *
Based on openULINK project code by: Martin Schmoelzer. *
Copyright 2023, Ahmed Errached BOUDJELIDA, NanoXplore SAS. *
<aboudjelida@nanoxplore.com> *
<ahmederrachedbjld@gmail.com> *
*****************************************************************************/
#include "usb.h"
#include "protocol.h"
#include "jtag.h"
#include "delay.h"
#include "io.h"
#include "msgtypes.h"
#include "reg_ezusb.h"
#include <serial.h>
#include <stdio.h>
/** Index in EP1 Bulk-OUT data buffer that contains the current command ID */
volatile uint8_t cmd_id_index;
/** Number of data bytes already in EP1 Bulk-IN buffer */
volatile uint8_t payload_index_in;
/**
* Executes one command and updates global command indexes.
*
* @return true if this command was the last command.
* @return false if there are more commands within the current contents of the
* Bulk EP1-OUT data buffer.
*/
bool execute_command(void)
{
uint8_t usb_out_bytecount, usb_in_bytecount;
uint16_t signal_state = 0;
uint16_t count;
/* Most commands do not transfer IN data. To save code space, we write 0 to
* usb_in_bytecount here, then modify it in the switch statement below where
* necessary */
usb_in_bytecount = 0;
switch (EP1OUTBUF[cmd_id_index] /* Command ID */) {
case CMD_SCAN_IN:
usb_out_bytecount = 5;
usb_in_bytecount = EP1OUTBUF[cmd_id_index + 1];
jtag_scan_in((cmd_id_index + 1), payload_index_in);
break;
case CMD_SCAN_OUT:
usb_out_bytecount = EP1OUTBUF[cmd_id_index + 1] + 5;
jtag_scan_out(cmd_id_index + 1);
break;
case CMD_SCAN_IO:
usb_in_bytecount = EP1OUTBUF[cmd_id_index + 1];
usb_out_bytecount = usb_in_bytecount + 5;
jtag_scan_io((cmd_id_index + 1), payload_index_in);
break;
case CMD_CLOCK_TMS:
usb_out_bytecount = 2;
jtag_clock_tms(EP1OUTBUF[cmd_id_index + 1], EP1OUTBUF[cmd_id_index + 2]);
break;
case CMD_CLOCK_TCK:
usb_out_bytecount = 2;
count = (uint16_t)EP1OUTBUF[cmd_id_index + 1];
count |= ((uint16_t)EP1OUTBUF[cmd_id_index + 2]) << 8;
jtag_clock_tck(count);
break;
case CMD_SLOW_SCAN_IN:
usb_out_bytecount = 5;
usb_in_bytecount = EP1OUTBUF[cmd_id_index + 1];
jtag_slow_scan_in(cmd_id_index + 1, payload_index_in);
break;
case CMD_SLOW_SCAN_OUT:
usb_out_bytecount = EP1OUTBUF[cmd_id_index + 1] + 5;
jtag_slow_scan_out(cmd_id_index + 1);
break;
case CMD_SLOW_SCAN_IO:
usb_in_bytecount = EP1OUTBUF[cmd_id_index + 1];
usb_out_bytecount = usb_in_bytecount + 5;
jtag_slow_scan_io(cmd_id_index + 1, payload_index_in);
break;
case CMD_SLOW_CLOCK_TMS:
usb_out_bytecount = 2;
jtag_slow_clock_tms(EP1OUTBUF[cmd_id_index + 1], EP1OUTBUF[cmd_id_index + 2]);
break;
case CMD_SLOW_CLOCK_TCK:
usb_out_bytecount = 2;
count = (uint16_t)EP1OUTBUF[cmd_id_index + 1];
count |= ((uint16_t)EP1OUTBUF[cmd_id_index + 2]) << 8;
jtag_slow_clock_tck(count);
break;
case CMD_SLEEP_US:
usb_out_bytecount = 2;
count = (uint16_t)EP1OUTBUF[cmd_id_index + 1];
count |= ((uint16_t)EP1OUTBUF[cmd_id_index + 2]) << 8;
delay_us(count);
break;
case CMD_SLEEP_MS:
usb_out_bytecount = 2;
count = (uint16_t)EP1OUTBUF[cmd_id_index + 1];
count |= ((uint16_t)EP1OUTBUF[cmd_id_index + 2]) << 8;
delay_ms(count);
break;
case CMD_GET_SIGNALS:
usb_out_bytecount = 0;
usb_in_bytecount = 2;
signal_state = jtag_get_signals();
EP1INBUF[payload_index_in] = (signal_state >> 8);
EP1INBUF[payload_index_in + 1] = (signal_state & 0xFF);
break;
case CMD_SET_SIGNALS:
usb_out_bytecount = 2;
jtag_set_signals(EP1OUTBUF[cmd_id_index + 1], EP1OUTBUF[cmd_id_index + 2]);
break;
case CMD_CONFIGURE_TCK_FREQ:
usb_out_bytecount = 5;
jtag_configure_tck_delay(EP1OUTBUF[cmd_id_index + 1], /* scan_in */
EP1OUTBUF[cmd_id_index + 2], /* scan_out */
EP1OUTBUF[cmd_id_index + 3], /* scan_io */
EP1OUTBUF[cmd_id_index + 4], /* clock_tck */
EP1OUTBUF[cmd_id_index + 5]); /* clock_tms */
break;
case CMD_TEST:
usb_out_bytecount = 1;
/* Do nothing... This command is only used to test if the device is ready
* to accept new commands */
break;
default:
/* Should never be reached */
usb_out_bytecount = 0;
break;
}
/* Update EP1 Bulk-IN data byte count */
payload_index_in += usb_in_bytecount;
/* Determine if this was the last command */
if ((cmd_id_index + usb_out_bytecount + 1) >= EP1OUTBC) {
return true;
/* Line between return and else required by checkpatch: */
uint8_t a = 0;
} else {
/* Not the last command, update cmd_id_index */
cmd_id_index += (usb_out_bytecount + 1);
return false;
}
}
/**
* Forever wait for commands and execute them as they arrive.
*/
void command_loop(void)
{
bool last_command;
while (1) {
cmd_id_index = 0;
payload_index_in = 0;
/* Wait until host sends EP1 Bulk-OUT packet */
while (!ep1_out)
;
ep1_out = false;
/* Execute the commands */
last_command = false;
while (!last_command)
last_command = execute_command();
/* Send back EP6 Bulk-IN packet if required */
if (payload_index_in > 0) {
EP1INBC = payload_index_in;
syncdelay(3);
while (!ep1_in)
;
ep1_in = false;
}
/* Re-arm EP1-OUT after command execution */
EP1OUTBC = 0;
syncdelay(3);
EP1OUTBC = 0;
syncdelay(3);
}
}

View File

@ -0,0 +1,77 @@
// SPDX-License-Identifier: LGPL-2.1-or-later
/*
* This code was taken from the fx2lib project from this link:
* https://github.com/djmuhlestein/fx2lib
*
* Copyright (C) 2009 Ubixum, Inc.
*/
#include <reg_ezusb.h>
#include <fx2macros.h>
#include <serial.h>
#include <stdint.h>
/**
* using the comp port implies that timer 2 will be used as
* a baud rate generator. (Don't use timer 2)
**/
void sio0_init(uint32_t baud_rate) __critical
{
uint16_t hl; /* hl value for reload */
uint8_t mult; /* multiplier for clock speed */
uint32_t tmp; /* scratch for mult/divide */
mult = (CPUFREQ == CLK_12M) ? 1 : ((CPUFREQ == CLK_24M) ? 2 : 4);
/* set the clock rate */
/* use clock 2 */
RCLK = 1; TCLK = 1;
tmp = mult * 375000L * 2;
tmp /= baud_rate;
tmp += 1;
tmp /= 2;
hl = 0xFFFF - (uint16_t)tmp;
RCAP2H = (uint8_t)(((uint16_t)(hl) >> 8) & 0xff);
/* seems that the 24/48mhz calculations are always one less than suggested values */
/* trm table 14-16 */
RCAP2L = ((uint8_t)((uint16_t)(hl) & 0xff)) + (mult > 0 ? 1 : 0);
/* start the timer */
TR2 = 1;
/* set up the serial port */
SM0 = 0; SM1 = 1; /* serial mode 1 (asyncronous) */
SM2 = 0 ; /* has to do with receiving */
REN = 1 ; /* to enable receiving */
PCON |= 0x80; /* SET SMOD0, baud rate doubler */
TI = 1; /* we send initial byte */
}
int getchar(void)
{
char c;
while (!RI)
;
c = SBUF0;
RI = 0;
return c;
}
void _transchar(char c)
{
while (!TI)
; /* wait for TI=1 */
TI = 0;
SBUF0 = c;
}
int putchar (char c)
{
if (c == '\n')
_transchar('\r'); /* transmit \r\n */
_transchar(c);
if (c == '\r')
_transchar('\n'); /* transmit \r\n */
return c;
}

View File

@ -0,0 +1,784 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/****************************************************************************
File : usb.c *
Contents : usb communication handling code for NanoXplore USB-JTAG *
ANGIE adapter hardware. *
Based on openULINK project code by: Martin Schmoelzer. *
Copyright 2023, Ahmed Errached BOUDJELIDA, NanoXplore SAS. *
<aboudjelida@nanoxplore.com> *
<ahmederrachedbjld@gmail.com> *
*****************************************************************************/
#include "usb.h"
#include "stdint.h"
#include "delay.h"
#include "io.h"
#include "reg_ezusb.h"
#include <fx2macros.h>
#include <serial.h>
#include <stdio.h>
/* Also update external declarations in "include/usb.h" if making changes to
* these variables!
*/
volatile bool ep1_out;
volatile bool ep1_in;
volatile __xdata __at 0xE6B8 struct setup_data setup_data;
/* Define number of endpoints (except Control Endpoint 0) in a central place.
* Be sure to include the necessary endpoint descriptors!
*/
#define NUM_ENDPOINTS 3
__code struct usb_device_descriptor device_descriptor = {
.blength = sizeof(struct usb_device_descriptor),
.bdescriptortype = DESCRIPTOR_TYPE_DEVICE,
.bcdusb = 0x0200, /* BCD: 02.00 (Version 2.0 USB spec) */
.bdeviceclass = 0xFF, /* 0xFF = vendor-specific */
.bdevicesubclass = 0xFF,
.bdeviceprotocol = 0xFF,
.bmaxpacketsize0 = 64,
.idvendor = 0x584e,
.idproduct = 0x424e,
.bcddevice = 0x0000,
.imanufacturer = 1,
.iproduct = 2,
.iserialnumber = 3,
.bnumconfigurations = 1
};
/* WARNING: ALL config, interface and endpoint descriptors MUST be adjacent! */
__code struct usb_config_descriptor config_descriptor = {
.blength = sizeof(struct usb_config_descriptor),
.bdescriptortype = DESCRIPTOR_TYPE_CONFIGURATION,
.wtotallength = sizeof(struct usb_config_descriptor) +
sizeof(struct usb_interface_descriptor) +
(NUM_ENDPOINTS * sizeof(struct usb_endpoint_descriptor)),
.bnuminterfaces = 1,
.bconfigurationvalue = 1,
.iconfiguration = 4, /* String describing this configuration */
.bmattributes = 0x80, /* Only MSB set according to USB spec */
.maxpower = 50 /* 100 mA */
};
__code struct usb_interface_descriptor interface_descriptor00 = {
.blength = sizeof(struct usb_interface_descriptor),
.bdescriptortype = DESCRIPTOR_TYPE_INTERFACE,
.binterfacenumber = 0,
.balternatesetting = 0,
.bnumendpoints = NUM_ENDPOINTS,
.binterfaceclass = 0xFF,
.binterfacesubclass = 0xFF,
.binterfaceprotocol = 0xFF,
.iinterface = 0
};
__code struct usb_endpoint_descriptor bulk_ep1_out_endpoint_descriptor = {
.blength = sizeof(struct usb_endpoint_descriptor),
.bdescriptortype = 0x05,
.bendpointaddress = (1 | USB_DIR_OUT),
.bmattributes = 0x02,
.wmaxpacketsize = 64,
.binterval = 0
};
__code struct usb_endpoint_descriptor bulk_ep1_in_endpoint_descriptor = {
.blength = sizeof(struct usb_endpoint_descriptor),
.bdescriptortype = 0x05,
.bendpointaddress = (1 | USB_DIR_IN),
.bmattributes = 0x02,
.wmaxpacketsize = 64,
.binterval = 0
};
__code struct usb_endpoint_descriptor bulk_ep2_endpoint_descriptor = {
.blength = sizeof(struct usb_endpoint_descriptor),
.bdescriptortype = 0x05,
.bendpointaddress = (2 | USB_DIR_OUT),
.bmattributes = 0x02,
.wmaxpacketsize = 512,
.binterval = 0
};
__code struct usb_endpoint_descriptor bulk_ep4_endpoint_descriptor = {
.blength = sizeof(struct usb_endpoint_descriptor),
.bdescriptortype = 0x05,
.bendpointaddress = (4 | USB_DIR_IN),
.bmattributes = 0x02,
.wmaxpacketsize = 512,
.binterval = 0
};
__code struct usb_endpoint_descriptor bulk_ep6_endpoint_descriptor = {
.blength = sizeof(struct usb_endpoint_descriptor),
.bdescriptortype = 0x05,
.bendpointaddress = (6 | USB_DIR_OUT),
.bmattributes = 0x02,
.wmaxpacketsize = 512,
.binterval = 0
};
__code struct usb_endpoint_descriptor bulk_ep8_endpoint_descriptor = {
.blength = sizeof(struct usb_endpoint_descriptor),
.bdescriptortype = 0x05,
.bendpointaddress = (8 | USB_DIR_OUT),
.bmattributes = 0x02,
.wmaxpacketsize = 512,
.binterval = 0
};
__code struct usb_language_descriptor language_descriptor = {
.blength = 4,
.bdescriptortype = DESCRIPTOR_TYPE_STRING,
.wlangid = {0x0409 /* US English */}
};
__code struct usb_string_descriptor strmanufacturer =
STR_DESCR(16, 'N', 'a', 'n', 'o', 'X', 'p', 'l', 'o', 'r', 'e', ',', ' ', 'S', 'A', 'S', '.');
__code struct usb_string_descriptor strproduct =
STR_DESCR(13, 'A', 'N', 'G', 'I', 'E', ' ', 'A', 'd', 'a', 'p', 't', 'e', 'r');
__code struct usb_string_descriptor strserialnumber =
STR_DESCR(6, '0', '0', '0', '0', '0', '1');
__code struct usb_string_descriptor strconfigdescr =
STR_DESCR(12, 'J', 'T', 'A', 'G', ' ', 'A', 'd', 'a', 'p', 't', 'e', 'r');
/* Table containing pointers to string descriptors */
__code struct usb_string_descriptor *__code en_string_descriptors[4] = {
&strmanufacturer,
&strproduct,
&strserialnumber,
&strconfigdescr
};
void sudav_isr(void)__interrupt SUDAV_ISR
{
EXIF &= ~0x10; /* Clear USBINT: Main global interrupt */
USBIRQ = SUDAVI;
EP0CS |= HSNAK;
usb_handle_setup_data();
}
void sof_isr(void)__interrupt SOF_ISR
{
}
void sutok_isr(void)__interrupt SUTOK_ISR
{
}
void suspend_isr(void)__interrupt SUSPEND_ISR
{
}
void usbreset_isr(void)__interrupt USBRESET_ISR
{
}
void highspeed_isr(void)__interrupt HIGHSPEED_ISR
{
}
void ep0ack_isr(void)__interrupt EP0ACK_ISR
{
}
void stub_isr(void)__interrupt STUB_ISR
{
}
void ep0in_isr(void)__interrupt EP0IN_ISR
{
}
void ep0out_isr(void)__interrupt EP0OUT_ISR
{
}
void ep1in_isr(void)__interrupt EP1IN_ISR
{
ep1_in = true;
EXIF &= ~0x10; /* Clear USBINT: Main global interrupt */
EPIRQ = 0x04; /* Clear individual EP1IN IRQ */
}
void ep1out_isr(void)__interrupt EP1OUT_ISR
{
ep1_out = true;
EXIF &= ~0x10; /* Clear USBINT: Main global interrupt */
EPIRQ = 0x08; /* Clear individual EP1OUT IRQ */
}
void ep2_isr(void)__interrupt EP2_ISR
{
ep1_out = false; /* Does nothing but required by the compiler */
}
void ep4_isr(void)__interrupt EP4_ISR
{
}
void ep6_isr(void)__interrupt EP6_ISR
{
}
void ep8_isr(void)__interrupt EP8_ISR
{
}
void ibn_isr(void)__interrupt IBN_ISR
{
}
void ep0pingnak_isr(void)__interrupt EP0PINGNAK_ISR
{
}
void ep1pingnak_isr(void)__interrupt EP1PINGNAK_ISR
{
}
void ep2pingnak_isr(void)__interrupt EP2PINGNAK_ISR
{
}
void ep4pingnak_isr(void)__interrupt EP4PINGNAK_ISR
{
}
void ep6pingnak_isr(void)__interrupt EP6PINGNAK_ISR
{
}
void ep8pingnak_isr(void)__interrupt EP8PINGNAK_ISR
{
}
void errorlimit_isr(void)__interrupt ERRORLIMIT_ISR
{
}
void ep2piderror_isr(void)__interrupt EP2PIDERROR_ISR
{
}
void ep4piderror_isr(void)__interrupt EP4PIDERROR_ISR
{
}
void ep6piderror_isr(void)__interrupt EP6PIDERROR_ISR
{
}
void ep8piderror_isr(void)__interrupt EP8PIDERROR_ISR
{
}
void ep2pflag_isr(void)__interrupt EP2PFLAG_ISR
{
}
void ep4pflag_isr(void)__interrupt EP4PFLAG_ISR
{
}
void ep6pflag_isr(void)__interrupt EP6PFLAG_ISR
{
}
void ep8pflag_isr(void)__interrupt EP8PFLAG_ISR
{
}
void ep2eflag_isr(void)__interrupt EP2EFLAG_ISR
{
}
void ep4eflag_isr(void)__interrupt EP4EFLAG_ISR
{
}
void ep6eflag_isr(void)__interrupt EP6EFLAG_ISR
{
}
void ep8eflag_isr(void)__interrupt EP8EFLAG_ISR
{
}
void ep2fflag_isr(void)__interrupt EP2FFLAG_ISR
{
}
void ep4fflag_isr(void)__interrupt EP4FFLAG_ISR
{
}
void ep6fflag_isr(void)__interrupt EP6FFLAG_ISR
{
}
void ep8fflag_isr(void)__interrupt EP8FFLAG_ISR
{
}
void gpifcomplete_isr(void)__interrupt GPIFCOMPLETE_ISR
{
}
void gpifwaveform_isr(void)__interrupt GPIFWAVEFORM_ISR
{
}
/**
* Return the control/status register for an endpoint
*
* @param ep endpoint address
* @return on success: pointer to Control & Status register for endpoint
* specified in \a ep
* @return on failure: NULL
*/
__xdata uint8_t *usb_get_endpoint_cs_reg(uint8_t ep)
{
/* Mask direction bit */
uint8_t ep_num = ep & ~0x80;
switch (ep_num) {
case 0:
return &EP0CS;
case 1:
return ep & 0x80 ? &EP1INCS : &EP1OUTCS;
case 2:
return &EP2CS;
case 4:
return &EP4CS;
case 6:
return &EP6CS;
case 8:
return &EP8CS;
default:
return NULL;
}
}
void usb_reset_data_toggle(uint8_t ep)
{
/* TOGCTL register:
+----+-----+-----+------+-----+-------+-------+-------+
| Q | S | R | IO | EP3 | EP2 | EP1 | EP0 |
+----+-----+-----+------+-----+-------+-------+-------+
To reset data toggle bits, we have to write the endpoint direction (IN/OUT)
to the IO bit and the endpoint number to the EP2..EP0 bits. Then, in a
separate write cycle, the R bit needs to be set.
*/
TOGCTL = (((ep & 0x80) >> 3) + (ep & 0x0F));
TOGCTL |= BMRESETTOGGLE;
}
/**
* Handle GET_STATUS request.
*
* @return on success: true
* @return on failure: false
*/
bool usb_handle_get_status(void)
{
uint8_t *ep_cs;
switch (setup_data.bmrequesttype) {
case GS_DEVICE:
/* Two byte response: Byte 0, Bit 0 = self-powered, Bit 1 = remote wakeup.
* Byte 1: reserved, reset to zero */
EP0BUF[0] = 0;
EP0BUF[1] = 0;
/* Send response */
EP0BCH = 0;
syncdelay(3);
EP0BCL = 2;
syncdelay(3);
break;
case GS_INTERFACE:
/* Always return two zero bytes according to USB 1.1 spec, p. 191 */
EP0BUF[0] = 0;
EP0BUF[1] = 0;
/* Send response */
EP0BCH = 0;
syncdelay(3);
EP0BCL = 2;
syncdelay(3);
break;
case GS_ENDPOINT:
/* Get stall bit for endpoint specified in low byte of wIndex */
ep_cs = usb_get_endpoint_cs_reg(setup_data.windex & 0xff);
if (*ep_cs & EPSTALL)
EP0BUF[0] = 0x01;
else
EP0BUF[0] = 0x00;
/* Second byte sent has to be always zero */
EP0BUF[1] = 0;
/* Send response */
EP0BCH = 0;
syncdelay(3);
EP0BCL = 2;
syncdelay(3);
break;
default:
return false;
}
return true;
}
/**
* Handle CLEAR_FEATURE request.
*
* @return on success: true
* @return on failure: false
*/
bool usb_handle_clear_feature(void)
{
__xdata uint8_t *ep_cs;
switch (setup_data.bmrequesttype) {
case CF_DEVICE:
/* Clear remote wakeup not supported: stall EP0 */
STALL_EP0();
break;
case CF_ENDPOINT:
if (setup_data.wvalue == 0) {
/* Unstall the endpoint specified in wIndex */
ep_cs = usb_get_endpoint_cs_reg(setup_data.windex);
if (!ep_cs)
return false;
*ep_cs &= ~EPSTALL;
} else {
/* Unsupported feature, stall EP0 */
STALL_EP0();
}
break;
default:
/* Vendor commands... */
break;
}
return true;
}
/**
* Handle SET_FEATURE request.
*
* @return on success: true
* @return on failure: false
*/
bool usb_handle_set_feature(void)
{
__xdata uint8_t *ep_cs;
switch (setup_data.bmrequesttype) {
case SF_DEVICE:
if (setup_data.wvalue == 2)
return true;
break;
case SF_ENDPOINT:
if (setup_data.wvalue == 0) {
/* Stall the endpoint specified in wIndex */
ep_cs = usb_get_endpoint_cs_reg(setup_data.windex);
if (!ep_cs)
return false;
*ep_cs |= EPSTALL;
} else {
/* Unsupported endpoint feature */
return false;
}
break;
default:
/* Vendor commands... */
break;
}
return true;
}
/**
* Handle GET_DESCRIPTOR request.
*
* @return on success: true
* @return on failure: false
*/
bool usb_handle_get_descriptor(void)
{
__xdata uint8_t descriptor_type;
__xdata uint8_t descriptor_index;
descriptor_type = (setup_data.wvalue & 0xff00) >> 8;
descriptor_index = setup_data.wvalue & 0x00ff;
switch (descriptor_type) {
case DESCRIPTOR_TYPE_DEVICE:
SUDPTRH = HI8(&device_descriptor);
SUDPTRL = LO8(&device_descriptor);
break;
case DESCRIPTOR_TYPE_CONFIGURATION:
SUDPTRH = HI8(&config_descriptor);
SUDPTRL = LO8(&config_descriptor);
break;
case DESCRIPTOR_TYPE_STRING:
if (setup_data.windex == 0) {
/* Supply language descriptor */
SUDPTRH = HI8(&language_descriptor);
SUDPTRL = LO8(&language_descriptor);
} else if (setup_data.windex == 0x0409 /* US English */) {
/* Supply string descriptor */
SUDPTRH = HI8(en_string_descriptors[descriptor_index - 1]);
SUDPTRL = LO8(en_string_descriptors[descriptor_index - 1]);
} else {
return false;
}
break;
default:
/* Unsupported descriptor type */
return false;
}
return true;
}
/**
* Handle SET_INTERFACE request.
*/
void usb_handle_set_interface(void)
{
/* Reset Data Toggle */
usb_reset_data_toggle(USB_DIR_IN | 4);
usb_reset_data_toggle(USB_DIR_OUT | 2);
/* Unstall & clear busy flag of all valid IN endpoints */
EP1INCS = 0 | EPBSY;
/* Unstall all valid OUT endpoints, reset bytecounts */
EP1OUTCS = 0;
EP1OUTBC = 0;
syncdelay(3);
}
/* Initialize GPIF interface transfer count */
void set_gpif_cnt(uint32_t count)
{
GPIFTCB3 = (uint8_t)(((uint32_t)(count) >> 24) & 0x000000ff);
syncdelay(3);
GPIFTCB2 = (uint8_t)(((uint32_t)(count) >> 16) & 0x000000ff);
syncdelay(3);
GPIFTCB1 = (uint8_t)(((uint32_t)(count) >> 8) & 0x000000ff);
syncdelay(3);
GPIFTCB0 = (uint8_t)((uint32_t)(count) & 0x000000ff);
}
/*
* Vendor commands handling:
*/
#define VR_CFGOPEN 0xB0
#define VR_CFGCLOSE 0xB1
uint8_t ix;
uint8_t bcnt;
uint8_t __xdata *eptr;
uint16_t wcnt;
uint32_t __xdata gcnt;
bool usb_handle_send_bitstream(void)
{
eptr = EP0BUF; /* points to EP0BUF 64-byte register */
wcnt = setup_data.wlength; /* total transfer count */
/* Clear EP0BUF for OUT requests */
if (setup_data.bmrequesttype & 0x80) {
bcnt = ((wcnt > 64) ? 64 : wcnt);
for (ix = 0; ix < bcnt; ix++)
eptr[ix] = 0;
}
switch (setup_data.brequest) {
case VR_CFGOPEN:
/* Clear bytecount / to allow new data in / to stops NAKing */
EP0BCH = 0;
EP0BCL = 0;
while (EP0CS & EPBSY)
; /* wait to finish transferring in EP0BUF, until not busy */
gcnt = ((uint32_t)(eptr[0]) << 24) | ((uint32_t)(eptr[1]) << 16)
| ((uint32_t)(eptr[2]) << 8) | (uint32_t)(eptr[3]);
/* Angie board FPGA bitstream download */
switch ((setup_data.wvalue) & 0x00C0) {
case 0x00:
PIN_PROGRAM_B = 0; /* Apply RPGM- pulse */
GPIFWFSELECT = 0xF2; /* Restore Config mode waveforms select */
syncdelay(3);
EP2FIFOCFG = BMAUTOOUT; /* and Automatic 8-bit GPIF OUT mode */
syncdelay(3);
PIN_PROGRAM_B = 1; /* Negate RPGM- pulse */
delay_ms(10); /* FPGA init time < 10mS */
set_gpif_cnt(gcnt); /* Initialize GPIF interface transfer count */
PIN_RDWR_B = 0;
PIN_CSI_B = 0;
GPIFTRIG = GPIF_EP2; /* Trigger GPIF OUT transfer on EP2 */
syncdelay(3);
break;
default:
break;
}
break;
case VR_CFGCLOSE:
ix = 10;
/* wait until GPIF transaction has been completed */
while ((GPIFTRIG & BMGPIFDONE) == 0) {
if (ix-- == 0) {
printf("GPIF done time out\n");
break;
}
delay_ms(1);
}
switch ((setup_data.wvalue) & 0x00C0) {
case 0x00:
PIN_CSI_B = 1;
PIN_RDWR_B = 1;
IFCONFIG &= 0xFC; /* Exit gpif mode */
break;
default:
break;
}
EP0BCH = 0;
EP0BCL = (uint8_t)(setup_data.wlength); /* Signal buffer is filled */
break;
default:
return true; /* Error: unknown VR command */
}
return false; /* no error; command handled OK */
}
/**
* Handle the arrival of a USB Control Setup Packet.
*/
void usb_handle_setup_data(void)
{
switch (setup_data.brequest) {
case GET_STATUS:
if (!usb_handle_get_status())
STALL_EP0();
break;
case CLEAR_FEATURE:
if (!usb_handle_clear_feature())
STALL_EP0();
break;
case 2: case 4:
/* Reserved values */
STALL_EP0();
break;
case SET_FEATURE:
if (!usb_handle_set_feature())
STALL_EP0();
break;
case SET_ADDRESS:
/* Handled by USB core */
break;
case SET_DESCRIPTOR:
/* Set Descriptor not supported. */
STALL_EP0();
break;
case GET_DESCRIPTOR:
if (!usb_handle_get_descriptor())
STALL_EP0();
break;
case GET_CONFIGURATION:
/* ANGIE has only one configuration, return its index */
EP0BUF[0] = config_descriptor.bconfigurationvalue;
EP0BCH = 0;
EP0BCL = 1;
syncdelay(3);
break;
case SET_CONFIGURATION:
/* ANGIE has only one configuration -> nothing to do */
break;
case GET_INTERFACE:
/* ANGIE only has one interface, return its number */
EP0BUF[0] = interface_descriptor00.binterfacenumber;
EP0BCH = 0;
EP0BCL = 1;
syncdelay(3);
break;
case SET_INTERFACE:
usb_handle_set_interface();
break;
case SYNCH_FRAME:
/* Isochronous endpoints not used -> nothing to do */
break;
default:
/* if not Vendor command, Stall EndPoint 0 */
if (usb_handle_send_bitstream())
STALL_EP0();
break;
}
}
/**
* Handle the initialization of endpoints.
*/
void ep_init(void)
{
EP1INCFG = 0xA0;
syncdelay(3);
EP1OUTCFG = 0xA0;
syncdelay(3);
EP2CFG = 0xA0;
syncdelay(3);
EP4CFG = 0x00;
syncdelay(3);
EP6CFG = 0x00;
syncdelay(3);
EP8CFG = 0x00;
syncdelay(3);
/* arm EP1-OUT */
EP1OUTBC = 0;
syncdelay(3);
EP1OUTBC = 0;
syncdelay(3);
/* arm EP1-IN */
EP1INBC = 0;
syncdelay(3);
EP1INBC = 0;
syncdelay(3);
/* Standard procedure to reset FIFOs */
FIFORESET = BMNAKALL; /* NAK all transfers during the reset */
syncdelay(3);
FIFORESET = 0x02; /* reset EP2 FIFO */
syncdelay(3);
FIFORESET = 0x00; /* deactivate the NAK all */
syncdelay(3);
EP2FIFOCFG = 0x00;
syncdelay(3);
EP2FIFOCFG = BMAUTOOUT; /* Automatic 8-bit GPIF OUT mode */
syncdelay(3);
}
/**
* Interrupt initialization. Configures USB interrupts.
*/
void interrupt_init(void)
{
/* Enable Interrupts */
EA = 1;
/* Enable USB interrupt (EIE register) */
EUSB = 1;
EICON |= 0x20;
/* Enable INT 2 & 4 Autovectoring */
INTSETUP |= (AV2EN | AV4EN);
/* Enable individual EP1OUT&IN interrupts */
EPIE |= 0x0C;
/* Clear individual USB interrupt IRQ */
EPIRQ = 0x0C;
/* Enable SUDAV interrupt */
USBIEN |= SUDAVI;
/* Clear SUDAV interrupt */
USBIRQ = SUDAVI;
}
/**
* Handle the initialization of io ports.
*/
void io_init(void)
{
/* PORT A */
PORTACFG = 0x01; /* 0: normal ou 1: alternate function (each bit) */
OEA = 0xEF; /* all OUT exept INIT_B IN */
IOA = 0xFF;
PIN_RDWR_B = 1;
PIN_CSI_B = 1;
PIN_PROGRAM_B = 1;
/* PORT B */
OEB = 0xEF; /* all OUT exept TDO */
IOB = 0xFF;
PIN_TRST = 1;
PIN_TMS = 0;
PIN_TCK = 0;
PIN_TDI = 0;
PIN_SRST = 1;
/* PORT C */
PORTCCFG = 0x00; /* 0: normal ou 1: alternate function (each bit) */
OEC = 0xEF;
IOC = 0xFF;
}

View File

@ -0,0 +1,109 @@
# SPDX-License-Identifier: BSD-3-Clause
# Copyright (C) 2023 by NanoXplore, France - all rights reserved
# Needed by timing test
export PROJECT := angie_openocd
TARGET_PART := xc6slx9-2tqg144
export TOPLEVEL := S609
# Detects the ROOT dir from the .git marker
sp :=
sp +=
_walk = $(if $1,$(wildcard /$(subst $(sp),/,$1)/$2) $(call _walk,$(wordlist 2,$(words $1),x $1),$2))
_find = $(firstword $(call _walk,$(strip $(subst /, ,$1)),$2))
_ROOT := $(patsubst %/.git,%,$(call _find,$(CURDIR),.git))
SHELL := /bin/bash
TOP_DIR := $(realpath $(_ROOT))
HDL_DIR := $(CURDIR)
SRC_DIR := $(HDL_DIR)/src
TOOLS_DIR := $(TOP_DIR)/tools/build
COMMON_DIR := $(TOP_DIR)/common/hdl
COMMON_HDL_DIR := $(COMMON_DIR)/src
COMMON_LIBS := $(COMMON_DIR)/libs
HDL_BUILD_DIR := $(HDL_DIR)/build
OUTPUT_DIR ?= $(HDL_BUILD_DIR)/output
FINAL_OUTPUT_DIR := $(OUTPUT_DIR)/$(PROJECT)
# Tools
MKDIR := mkdir -p
CP := cp -f
HDL_SRC_PATH := $(addprefix $(COMMON_DIR)/ips/, $(HDL_IPS)) $(HDL_DIR)
VHDSOURCE += $(foreach ip,$(HDL_SRC_PATH),$(wildcard $(ip)/src/*.vhd))
VSOURCE += $(foreach ip,$(HDL_SRC_PATH),$(wildcard $(ip)/src/*.v))
VSOURCE += $(foreach ip,$(HDL_SRC_PATH),$(wildcard $(ip)/src/*.vh))
CONSTRAINTS ?= $(SRC_DIR)/$(PROJECT).ucf
COMMON_OPTS := -intstyle xflow
XST_OPTS :=
NGDBUILD_OPTS :=
MAP_OPTS := -mt 2
PAR_OPTS := -mt 4
BITGEN_OPTS := -g Binary:Yes
XILINX_PLATFORM := lin64
PATH := $(PATH):$(XILINX_HOME)/bin/$(XILINX_PLATFORM)
RUN = @echo -ne "\n\n\e[1;33m======== $(1) ========\e[m\n\n"; \
cd $(HDL_BUILD_DIR) && $(XILINX_HOME)/bin/$(XILINX_PLATFORM)/$(1)
compile: $(HDL_BUILD_DIR)/$(PROJECT).bin
install: $(HDL_BUILD_DIR)/$(PROJECT).bin
$(MKDIR) $(FINAL_OUTPUT_DIR)
$(CP) $(HDL_BUILD_DIR)/$(PROJECT).bin $(FINAL_OUTPUT_DIR)
clean:
rm -rf $(HDL_BUILD_DIR)
$(HDL_BUILD_DIR)/$(PROJECT).bin: $(HDL_BUILD_DIR)/$(PROJECT).ncd
$(call RUN,bitgen) $(COMMON_OPTS) $(BITGEN_OPTS) \
-w $(PROJECT).ncd $(PROJECT).bit
$(HDL_BUILD_DIR)/$(PROJECT).ncd: $(HDL_BUILD_DIR)/$(PROJECT).map.ncd
$(call RUN,par) $(COMMON_OPTS) $(PAR_OPTS) \
-w $(PROJECT).map.ncd $(PROJECT).ncd $(PROJECT).pcf
$(HDL_BUILD_DIR)/$(PROJECT).map.ncd: $(HDL_BUILD_DIR)/$(PROJECT).ngd
$(call RUN,map) $(COMMON_OPTS) $(MAP_OPTS) \
-p $(TARGET_PART) \
-w $(PROJECT).ngd -o $(PROJECT).map.ncd $(PROJECT).pcf
$(HDL_BUILD_DIR)/$(PROJECT).ngd: $(HDL_BUILD_DIR)/$(PROJECT).ngc
$(call RUN,ngdbuild) $(COMMON_OPTS) $(NGDBUILD_OPTS) \
-p $(TARGET_PART) -uc $(CONSTRAINTS) \
$(PROJECT).ngc $(PROJECT).ngd
$(HDL_BUILD_DIR)/$(PROJECT).ngc: $(HDL_BUILD_DIR)/$(PROJECT).prj $(HDL_BUILD_DIR)/$(PROJECT).scr
$(call RUN,xst) $(COMMON_OPTS) -ifn $(PROJECT).scr
$(HDL_BUILD_DIR)/$(PROJECT).scr: | $(HDL_BUILD_DIR)
@echo "Updating $@"
@mkdir -p $(HDL_BUILD_DIR)
@rm -f $@
@echo "run" \
"-ifn $(PROJECT).prj" \
"-ofn $(PROJECT).ngc" \
"-ifmt mixed" \
"$(XST_OPTS)" \
"-top $(TOPLEVEL)" \
"-ofmt NGC" \
"-p $(TARGET_PART)" \
> $(HDL_BUILD_DIR)/$(PROJECT).scr
$(HDL_BUILD_DIR)/$(PROJECT).prj: | $(HDL_BUILD_DIR)
@echo "Updating $@"
@rm -f $@
@$(foreach file,$(VSOURCE),echo "verilog work \"$(file)\"" >> $@;)
@$(foreach file,$(VHDSOURCE),echo "vhdl work \"$(file)\"" >> $@;)
@$(foreach lib,$(HDL_LIBS),$(foreach file,$(wildcard $(COMMON_LIBS)/$(lib)/src/*.vhd),echo "vhdl $(lib) \"$(file)\"" >> $@;))
@$(foreach lib,$(HDL_LIBS),$(foreach file,$(wildcard $(COMMON_LIBS)/$(lib)/src/*.v),echo "verilog $(lib) \"$(file)\"" >> $@;))
@$(foreach lib,$(HDL_LIBS),$(foreach file,$(wildcard $(COMMON_LIBS)/$(lib)/src/*.vh),echo "verilog $(lib) \"$(file)\"" >> $@;))
$(HDL_BUILD_DIR):
$(MKDIR) $(HDL_BUILD_DIR)
.PHONY: clean compile install

View File

@ -0,0 +1,18 @@
# SPDX-License-Identifier: BSD-3-Clause
# Copyright (C) 2023 by NanoXplore, France - all rights reserved
This is the source code of Nanoxplore USB-JTAG Adapter Angie's bitstream.
This bitstream is for the "xc6slx9-2tqg144" Spartan-6 Xilinx FPGA.
To generate this bitstream, you need to install Xilinx ISE Webpack 14.7
You will need to give the ISE software path : export XILINX_HOME=path/to/ise/sw
Please set the enviromnent first by executing the ". ./set_env.sh"
All you have to do now is to write your vhd and constrains codes.
One all is setup, you can use the make commands:
make compile : to compile your (.vhd & .ucf) files in the "src" directory
A directory named "build" will be created, which contains all the generated
files including the bitstream file.
make clean : to delete the build directory.

View File

@ -0,0 +1,14 @@
#!/bin/bash
# SPDX-License-Identifier: BSD-3-Clause
# Copyright (C) 2023 by NanoXplore, France - all rights reserved
[ -z "${XILINX_HOME}" ] && export XILINX_HOME=/home/software/Xilinx/ISE/14.7/ISE_DS/ISE
export PATH="$XILINX_HOME:$PATH"
echo "SET XILINX_HOME to ${XILINX_HOME}"
# This is needed for isim
XILINX_HOME_BASE=${XILINX_HOME}/..
for part in common EDK PlanAhead ISE
do
el=${XILINX_HOME_BASE}/${part}
. ${el}/.settings64.sh ${el}
done

View File

@ -0,0 +1,35 @@
## SPDX-License-Identifier: BSD-3-Clause
##--------------------------------------------------------------------------
## Project Context: nanoXplore USB-JTAG Adapter Board, Spartan6
## Design Name: NJTAG USB-JTAG Adapter FPGA source code
## Module Name: _angie_openocd.ucf
## Target Device: XC6SLX9-2 TQ144
## Tool versions: ISE Webpack 13.2 -> 14.2
## Author: Ahmed BOUDJELIDA nanoXplore SAS
##--------------------------------------------------------------------------
# WARNING: PullUps on JTAG inputs should be enabled after configuration
# (bitgen option) since the pins are not connected.
net TRST LOC = 'P48' ;
net TMS LOC = 'P43' ;
net TCK LOC = 'P44' ;
net TDI LOC = 'P45' ;
net TDO LOC = 'P46' ;
net SRST LOC = 'P61' ;
net SI_TDO LOC = 'P16' ;
net SO_TRST LOC = 'P32' ;
net SO_TMS LOC = 'P27' ;
net SO_TCK LOC = 'P30' ;
net SO_TDI LOC = 'P26' ;
net SO_SRST LOC = 'P12' ;
net ST_0 LOC = 'P29' ;
net ST_1 LOC = 'P21' ;
net ST_2 LOC = 'P11' ;
net FTP<0> LOC = 'P121' ;
net FTP<1> LOC = 'P120' ;
net FTP<2> LOC = 'P119' ;
net FTP<3> LOC = 'P116' ;
net FTP<4> LOC = 'P111' ;
net FTP<5> LOC = 'P112' ;
net FTP<6> LOC = 'P115' ;
net FTP<7> LOC = 'P114' ;

View File

@ -0,0 +1,66 @@
-- SPDX-License-Identifier: BSD-3-Clause
----------------------------------------------------------------------------
-- Project Context: nanoXplore USB-JTAG Adapter Board, Spartan6
-- Design Name: NJTAG USB-JTAG Adapter FPGA source code
-- Module Name: _angie_openocd.vhd
-- Target Device: XC6SLX9-2 TQ144
-- Tool versions: ISE Webpack 13.2 -> 14.2
-- Author: Ahmed BOUDJELIDA nanoXplore SAS
----------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;
library UNISIM;
use UNISIM.VComponents.all;
entity S609 is port(
TRST : in std_logic;
TMS : in std_logic;
TCK : in std_logic;
TDI : in std_logic;
TDO : out std_logic;
SRST : in std_logic;
FTP : out std_logic_vector(7 downto 0); -- Test points
SI_TDO : in std_logic;
ST_0 : out std_logic;
ST_1 : out std_logic;
ST_2 : out std_logic;
SO_TRST : out std_logic;
SO_TMS : out std_logic;
SO_TCK : out std_logic;
SO_TDI : out std_logic;
SO_SRST :out std_logic
);
end S609;
architecture A_S609 of S609 is
begin
--Directions:
ST_0 <= '0';
ST_1 <= '1';
--TDO:
TDO <= not SI_TDO;
--TRST - TCK - TMS - TDI:
SO_TRST <= TRST;
SO_TMS <= TMS;
SO_TCK <= TCK;
SO_TDI <= TDI;
ST_2 <= SRST;
SO_SRST <= '0';
--Points de test:
FTP(0) <= TRST;
FTP(1) <= TMS;
FTP(2) <= TCK;
FTP(3) <= TDI;
FTP(5) <= SRST;
FTP(4) <= SI_TDO;
FTP(6) <= '1';
FTP(7) <= '1';
end A_S609;

View File

@ -463,6 +463,12 @@ They only work with STMicroelectronics chips, notably STM32 and STM8.
@item @b{STLINK-V3}
@* This is available standalone and as part of some kits.
@* Link: @url{http://www.st.com/stlink-v3}
@item @b{STLINK-V3PWR}
@* This is available standalone.
Beside the debugger functionality, the probe includes a SMU (source
measurement unit) aimed at analyzing power consumption during code
execution. The SMU is not supported by OpenOCD.
@* Link: @url{http://www.st.com/stlink-v3pwr}
@end itemize
For info the original ST-LINK enumerates using the mass storage usb class; however,
@ -502,6 +508,9 @@ debuggers to ARM Cortex based targets @url{http://www.keil.com/support/man/docs/
@item @b{ARM-JTAG-EW}
@* Link: @url{http://www.olimex.com/dev/arm-jtag-ew.html}
@item @b{angie}
@* Link: @url{https://nanoxplore.org/}
@item @b{Buspirate}
@* Link: @url{http://dangerousprototypes.com/bus-pirate-manual/}
@ -2174,6 +2183,9 @@ In such cases, just specify the relevant port number as "disabled".
If you disable all access through TCP/IP, you will need to
use the command line @option{-pipe} option.
You can request the operating system to select one of the available
ports for the server by specifying the relevant port number as "0".
@anchor{gdb_port}
@deffn {Config Command} {gdb_port} [number]
@cindex GDB server
@ -2506,6 +2518,10 @@ Optionally sets that option first.
@end deffn
@end deffn
@deffn {Interface Driver} {angie}
This is the NanoXplore's ANGIE USB-JTAG Adapter.
@end deffn
@deffn {Interface Driver} {arm-jtag-ew}
Olimex ARM-JTAG-EW USB adapter
This has one driver-specific command:
@ -3213,7 +3229,7 @@ passed as is to the underlying adapter layout handler.
@anchor{st_link_dap_interface}
@deffn {Interface Driver} {st-link}
This is a driver that supports STMicroelectronics adapters ST-LINK/V2
(from firmware V2J24) and STLINK-V3, thanks to a new API that provides
(from firmware V2J24), STLINK-V3 and STLINK-V3PWR, thanks to a new API that provides
directly access the arm ADIv5 DAP.
The new API provide access to multiple AP on the same DAP, but the
@ -8604,22 +8620,24 @@ As it does for JTAG TAPs, debug targets, and flash chips (both NOR and NAND),
OpenOCD maintains a list of PLDs available for use in various commands.
Also, each such PLD requires a driver.
They are referenced by the number shown by the @command{pld devices} command,
and new PLDs are defined by @command{pld device driver_name}.
They are referenced by the name which was given when the pld was created or
the number shown by the @command{pld devices} command.
New PLDs are defined by @command{pld create pld_name driver_name -chain-position tap_name [driver_options]}.
@deffn {Config Command} {pld device} driver_name tap_name [driver_options]
Defines a new PLD device, supported by driver @var{driver_name},
using the TAP named @var{tap_name}.
The driver may make use of any @var{driver_options} to configure its
behavior.
@deffn {Config Command} {pld create} pld_name driver_name -chain-position tap_name [driver_options]
Creates a new PLD device, supported by driver @var{driver_name},
assigning @var{pld_name} for further reference.
@code{-chain-position} @var{tap_name} names the TAP
used to access this target.
The driver may make use of any @var{driver_options} to configure its behavior.
@end deffn
@deffn {Command} {pld devices}
Lists the PLDs and their numbers.
List the known PLDs with their name.
@end deffn
@deffn {Command} {pld load} num filename
Loads the file @file{filename} into the PLD identified by @var{num}.
@deffn {Command} {pld load} pld_name filename
Loads the file @file{filename} into the PLD identified by @var{pld_name}.
The file format must be inferred by the driver.
@end deffn
@ -8629,12 +8647,12 @@ Drivers may support PLD-specific options to the @command{pld device}
definition command, and may also define commands usable only with
that particular type of PLD.
@deffn {FPGA Driver} {virtex2} [no_jstart]
@deffn {FPGA Driver} {virtex2} [@option{-no_jstart}]
Virtex-II is a family of FPGAs sold by Xilinx.
This driver can also be used to load Series3, Series6, Series7 and Zynq 7000 devices.
It supports the IEEE 1532 standard for In-System Configuration (ISC).
If @var{no_jstart} is non-zero, the JSTART instruction is not used after
If @var{-no_jstart} is given, the JSTART instruction is not used after
loading the bitstream. While required for Series2, Series3, and Series6, it
breaks bitstream loading on Series7.
@ -8644,70 +8662,92 @@ openocd -f board/digilent_zedboard.cfg -c "init" \
@end example
@deffn {Command} {virtex2 read_stat} num
@deffn {Command} {virtex2 read_stat} pld_name
Reads and displays the Virtex-II status register (STAT)
for FPGA @var{num}.
for FPGA @var{pld_name}.
@end deffn
@deffn {Command} {virtex2 set_instr_codes} pld_name cfg_out cfg_in jprogb jstart jshutdown [user1 [user2 [user3 [user4]]]]
Change values for boundary scan instructions. Default are values for Virtex 2, devices Virtex 4/5/6 and
SSI devices are using different values.
@var{pld_name} is the name of the pld device.
@var{cfg_out} is the value used to select CFG_OUT instruction.
@var{cfg_in} is the value used to select CFG_IN instruction.
@var{jprogb} is the value used to select JPROGRAM instruction.
@var{jstart} is the value used to select JSTART instruction.
@var{jshutdown} is the value used to select JSHUTDOWN instruction.
@var{user1} to @var{user4} are the intruction used to select the user registers USER1 to USER4.
@end deffn
@deffn {Command} {virtex2 set_user_codes} pld_name user1 [user2 [user3 [user4]]]
Change values for boundary scan instructions selecting the registers USER1 to USER4.
Description of the arguments can be found at command @command{virtex2 set_instr_codes}.
@end deffn
@deffn {Command} {virtex2 program} pld_name
Load the bitstream from external memory for FPGA @var{pld_name}. A.k.a. refresh.
@end deffn
@end deffn
@deffn {FPGA Driver} {lattice} [family]
@deffn {FPGA Driver} {lattice} [@option{-family} <name>]
The FGPA families ECP2, ECP3, ECP5, Certus and CertusPro by Lattice are supported.
This driver can be used to load the bitstream into the FPGA or read the status register and read/write the usercode register.
The option @option{family} is one of @var{ecp2 ecp3 ecp5 certus}. This is needed when the JTAG ID of the device is not known by openocd (newer NX devices).
For the option @option{-family} @var{name} is one of @var{ecp2 ecp3 ecp5 certus}. This is needed when the JTAG ID of the device is not known by openocd (newer NX devices).
@deffn {Command} {lattice read_status} num
@deffn {Command} {lattice read_status} pld_name
Reads and displays the status register
for FPGA @var{num}.
for FPGA @var{pld_name}.
@end deffn
@deffn {Command} {lattice read_user} num
@deffn {Command} {lattice read_user} pld_name
Reads and displays the user register
for FPGA @var{num}.
for FPGA @var{pld_name}.
@end deffn
@deffn {Command} {lattice write_user} num val
@deffn {Command} {lattice write_user} pld_name val
Writes the user register.
for FPGA @var{num} with value @var{val}.
for FPGA @var{pld_name} with value @var{val}.
@end deffn
@deffn {Command} {lattice set_preload} num length
@deffn {Command} {lattice set_preload} pld_name length
Set the length of the register for the preload. This is needed when the JTAG ID of the device is not known by openocd (newer NX devices).
The load command for the FPGA @var{num} will use a length for the preload of @var{length}.
The load command for the FPGA @var{pld_name} will use a length for the preload of @var{length}.
@end deffn
@end deffn
@deffn {FPGA Driver} {efinix}
@deffn {FPGA Driver} {efinix} [@option{-family} <name>]
Both families (Trion and Titanium) sold by Efinix are supported as both use the same protocol for In-System Configuration.
This driver can be used to load the bitstream into the FPGA.
For the option @option{-family} @var{name} is one of @var{trion|titanium}.
@end deffn
@deffn {FPGA Driver} {intel} [@option{family}]
@deffn {FPGA Driver} {intel} [@option{-family} <name>]
This driver can be used to load the bitstream into Intel (former Altera) FPGAs.
The families Cyclone III, Cyclone IV, Cyclone V, Cyclone 10, Arria II are supported.
@c Arria V and Arria 10, MAX II, MAX V, MAX10)
The option @option{family} is one of @var{cycloneiii cycloneiv cyclonev cyclone10 arriaii}.
For the option @option{-family} @var{name} is one of @var{cycloneiii cycloneiv cyclonev cyclone10 arriaii}.
This is needed when the JTAG ID of the device is ambiguous (same ID is used for chips in different families).
As input file format the driver supports a '.rbf' (raw bitstream file) file. The '.rbf' file can be generated
from a '.sof' file with @verb{|quartus_cpf -c blinker.sof blinker.rbf|}
Defines a new PLD device, an FPGA of the Cyclone III family, using the TAP named @verb{|cycloneiii.tap|}:
Creates a new PLD device, an FPGA of the Cyclone III family, using the TAP named @verb{|cycloneiii.tap|}:
@example
pld device intel cycloneiii.tap cycloneiii
pld create cycloneiii.pld intel -chain-position cycloneiii.tap -family cycloneiii
@end example
@deffn {Command} {intel set_bscan} num len
Set boundary scan register length of FPGA @var{num} to @var{len}. This is needed because the
@deffn {Command} {intel set_bscan} pld_name len
Set boundary scan register length of FPGA @var{pld_name} to @var{len}. This is needed because the
length can vary between chips with the same JTAG ID.
@end deffn
@deffn {Command} {intel set_check_pos} num pos
@deffn {Command} {intel set_check_pos} pld_name pos
Selects the position @var{pos} in the boundary-scan register. The bit at this
position is checked after loading the bitstream and must be '1', which is the case when no error occurred.
With a value of -1 for @var{pos} the check will be omitted.
@ -8719,6 +8759,21 @@ With a value of -1 for @var{pos} the check will be omitted.
This driver can be used to load the bitstream into FPGAs from Gowin.
It is possible to program the SRAM. Programming the flash is not supported.
The files @verb{|.fs|} and @verb{|.bin|} generated by Gowin FPGA Designer are supported.
@deffn {Command} {gowin read_status} pld_name
Reads and displays the status register
for FPGA @var{pld_name}.
@end deffn
@deffn {Command} {gowin read_user} pld_name
Reads and displays the user register
for FPGA @var{pld_name}.
@end deffn
@deffn {Command} {gowin reload} pld_name
Load the bitstream from external memory for
FPGA @var{pld_name}. A.k.a. refresh.
@end deffn
@end deffn
@ -12022,7 +12077,7 @@ In a session using JTAG for its transport protocol, OpenOCD supports the functio
of a JTAG-Host. The JTAG-Host is needed to connect the circuit over JTAG to the
control-software. For more details see @url{http://ipdbg.org}.
@deffn {Command} {ipdbg} [@option{-start|-stop}] @option{-tap @var{tapname}} @option{-hub @var{ir_value} [@var{dr_length}]} [@option{-port @var{number}}] [@option{-tool @var{number}}] [@option{-vir [@var{vir_value} [@var{length} [@var{instr_code}]]]}]
@deffn {Command} {ipdbg} [@option{-start|-stop}] @option{-tap @var{tapname}} @option{-hub @var{ir_value} [@var{dr_length}]} [@option{-vir [@var{vir_value} [@var{length} [@var{instr_code}]]]}] [@option{-port @var{number}}] [@option{-tool @var{number}}]
Starts or stops a IPDBG JTAG-Host server. Arguments can be specified in any order.
Command options:
@ -12031,15 +12086,28 @@ Command options:
@item @option{-tap @var{tapname}} targeting the TAP @var{tapname}.
@item @option{-hub @var{ir_value}} states that the JTAG hub is
reachable with dr-scans while the JTAG instruction register has the value @var{ir_value}.
@item @option{-port @var{number}} tcp port number where the JTAG-Host is listening.
@item @option{-tool @var{number}} number of the tool/feature. These corresponds to the ports "data_(up/down)_(0..6)" at the JtagHub.
@item @option{-vir [@var{vir_value} [@var{length} [@var{instr_code}]]]} On some devices, the user data-register is only reachable if there is a
@item @option{-port @var{number}} tcp port number where the JTAG-Host will listen. The default is 4242 which is used when the option is not given.
@item @option{-tool @var{number}} number of the tool/feature. These corresponds to the ports "data_(up/down)_(0..6)" at the JtagHub. The default is 1 which is used when the option is not given.
@item @option{-vir [@var{vir_value} [@var{length} [@var{instr_code}]]]} On some devices, the user data-register is reachable if there is a
specific value in a second dr. This second dr is called vir (virtual ir). With this parameter given, the IPDBG satisfies this condition prior an
access to the IPDBG-Hub. The value shifted into the vir is given by the first parameter @var{vir_value} (default: 0x11). The second
parameter @var{length} is the length of the vir data register (default: 5). With the @var{instr_code} (default: 0x00e) parameter the ir value to
shift data through vir can be configured.
@end itemize
@end deffn
or
@deffn {Command} {ipdbg} [@option{-start|-stop}] @option{-pld @var{name} [@var{user}]} [@option{-port @var{number}}] [@option{-tool @var{number}}]
Also starts or stops a IPDBG JTAG-Host server. The pld drivers are able to provide the tap and hub/IR for the IPDBG JTAG-Host server.
With the @option{-pld @var{name} [@var{user}]} the information from the pld-driver is used and the options @option{-tap} and @option{-hub} are not required.
The defined driver for the pld @var{name} gets selected. (The pld devices names can be shown by the command @command{pld devices}).
The @verb{|USERx|} instructions are vendor specific and don't change between families of the same vendor.
So if there's a pld driver for your vendor it should work with your FPGA even when the driver is not compatible with your device for the remaining features. If your device/vendor is not supported you have to use the previous command.
With [@var{user}] one can select a different @verb{|USERx|}-Instruction. If the IPDBG JTAG-Hub is used without modification the default value of 1 which selects the first @verb{|USERx|} instruction is adequate.
The remaining options are described in the previous command.
@end deffn
Examples:
@example
@ -12054,6 +12122,13 @@ ipdbg -start -tap 10m50.tap -hub 0x00C -vir -port 60000 -tool 1
Starts a server listening on tcp-port 60000 which connects to tool 1 (data_up_1/data_down_1).
The connection is through the TAP of a Intel MAX10 virtual jtag component (sld_instance_index is 0; sld_ir_width is smaller than 5).
@example
ipdbg -start -pld xc7.pld -port 5555 -tool 0
@end example
Starts a server listening on tcp-port 5555 which connects to tool 0 (data_up_0/data_down_0).
The TAP and ir value used to reach the JTAG Hub is given by the pld driver.
@node Utility Commands
@chapter Utility Commands
@cindex Utility Commands

View File

@ -0,0 +1,68 @@
# SPDX-License-Identifier: GPL-2.0-or-later OR GFDL-1.2-no-invariants-or-later
Bus 001 Device 056: ID 584e:424e NanoXplore, SAS. ANGIE Adapter
Device Descriptor:
bLength 18
bDescriptorType 1
bcdUSB 2.00
bDeviceClass 255 Vendor Specific Class
bDeviceSubClass 255 Vendor Specific Subclass
bDeviceProtocol 255 Vendor Specific Protocol
bMaxPacketSize0 64
idVendor 0x584e
idProduct 0x424e
bcdDevice 0.00
iManufacturer 1 NanoXplore, SAS.
iProduct 2 ANGIE Adapter
iSerial 3 000001
bNumConfigurations 1
Configuration Descriptor:
bLength 9
bDescriptorType 2
wTotalLength 0x0027
bNumInterfaces 1
bConfigurationValue 1
iConfiguration 4 (error)
bmAttributes 0x80
(Bus Powered)
MaxPower 100mA
Interface Descriptor:
bLength 9
bDescriptorType 4
bInterfaceNumber 0
bAlternateSetting 0
bNumEndpoints 3
bInterfaceClass 255 Vendor Specific Class
bInterfaceSubClass 255 Vendor Specific Subclass
bInterfaceProtocol 255 Vendor Specific Protocol
iInterface 0
Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x01 EP 1 OUT
bmAttributes 2
Transfer Type Bulk
Synch Type None
Usage Type Data
wMaxPacketSize 0x0040 1x 64 bytes
bInterval 0
Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x81 EP 1 IN
bmAttributes 2
Transfer Type Bulk
Synch Type None
Usage Type Data
wMaxPacketSize 0x0040 1x 64 bytes
bInterval 0
Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x02 EP 2 OUT
bmAttributes 2
Transfer Type Bulk
Synch Type None
Usage Type Data
wMaxPacketSize 0x0200 1x 512 bytes
bInterval 0

View File

@ -0,0 +1,71 @@
# SPDX-License-Identifier: GPL-2.0-or-later OR GFDL-1.2-no-invariants-or-later
# STLINK-V3PWR standalone in firmware update mode
Bus 003 Device 054: ID 0483:3755 STMicroelectronics USB2.0 Hub
Device Descriptor:
bLength 18
bDescriptorType 1
bcdUSB 2.00
bDeviceClass 0
bDeviceSubClass 0
bDeviceProtocol 0
bMaxPacketSize0 64
idVendor 0x0483 STMicroelectronics
idProduct 0x3755
bcdDevice 1.00
iManufacturer 1 STMicroelectronics
iProduct 2 STLINK-V3PWR
iSerial 3 123456780000
bNumConfigurations 1
Configuration Descriptor:
bLength 9
bDescriptorType 2
wTotalLength 0x0020
bNumInterfaces 1
bConfigurationValue 1
iConfiguration 4 DFU Config
bmAttributes 0x80
(Bus Powered)
MaxPower 100mA
Interface Descriptor:
bLength 9
bDescriptorType 4
bInterfaceNumber 0
bAlternateSetting 0
bNumEndpoints 2
bInterfaceClass 255 Vendor Specific Class
bInterfaceSubClass 255 Vendor Specific Subclass
bInterfaceProtocol 255 Vendor Specific Protocol
iInterface 5 ST-Link Usbloader
Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x81 EP 1 IN
bmAttributes 2
Transfer Type Bulk
Synch Type None
Usage Type Data
wMaxPacketSize 0x0200 1x 512 bytes
bInterval 0
Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x01 EP 1 OUT
bmAttributes 2
Transfer Type Bulk
Synch Type None
Usage Type Data
wMaxPacketSize 0x0200 1x 512 bytes
bInterval 0
Device Qualifier (for other device speed):
bLength 10
bDescriptorType 6
bcdUSB 2.00
bDeviceClass 0
bDeviceSubClass 0
bDeviceProtocol 0
bMaxPacketSize0 64
bNumConfigurations 1
Device Status: 0x0000
(Bus Powered)

View File

@ -0,0 +1,253 @@
# SPDX-License-Identifier: GPL-2.0-or-later OR GFDL-1.2-no-invariants-or-later
# STLINK-V3PWR standalone
Bus 003 Device 053: ID 0483:3757 STMicroelectronics USB2.0 Hub
Device Descriptor:
bLength 18
bDescriptorType 1
bcdUSB 2.00
bDeviceClass 239 Miscellaneous Device
bDeviceSubClass 2
bDeviceProtocol 1 Interface Association
bMaxPacketSize0 64
idVendor 0x0483 STMicroelectronics
idProduct 0x3757
bcdDevice 1.00
iManufacturer 1 STMicroelectronics
iProduct 2 STLINK-V3PWR
iSerial 3 123456780000
bNumConfigurations 1
Configuration Descriptor:
bLength 9
bDescriptorType 2
wTotalLength 0x00c2
bNumInterfaces 6
bConfigurationValue 1
iConfiguration 4 Default Config
bmAttributes 0x80
(Bus Powered)
MaxPower 500mA
Interface Descriptor:
bLength 9
bDescriptorType 4
bInterfaceNumber 0
bAlternateSetting 0
bNumEndpoints 3
bInterfaceClass 255 Vendor Specific Class
bInterfaceSubClass 255 Vendor Specific Subclass
bInterfaceProtocol 255 Vendor Specific Protocol
iInterface 5 ST-Link Debug
Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x81 EP 1 IN
bmAttributes 2
Transfer Type Bulk
Synch Type None
Usage Type Data
wMaxPacketSize 0x0200 1x 512 bytes
bInterval 0
Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x01 EP 1 OUT
bmAttributes 2
Transfer Type Bulk
Synch Type None
Usage Type Data
wMaxPacketSize 0x0200 1x 512 bytes
bInterval 0
Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x82 EP 2 IN
bmAttributes 2
Transfer Type Bulk
Synch Type None
Usage Type Data
wMaxPacketSize 0x0200 1x 512 bytes
bInterval 0
Interface Association:
bLength 8
bDescriptorType 11
bFirstInterface 1
bInterfaceCount 2
bFunctionClass 2 Communications
bFunctionSubClass 2 Abstract (modem)
bFunctionProtocol 1 AT-commands (v.25ter)
iFunction 6 ST-Link VCP Ctrl
Interface Descriptor:
bLength 9
bDescriptorType 4
bInterfaceNumber 1
bAlternateSetting 0
bNumEndpoints 1
bInterfaceClass 2 Communications
bInterfaceSubClass 2 Abstract (modem)
bInterfaceProtocol 1 AT-commands (v.25ter)
iInterface 6 ST-Link VCP Ctrl
CDC Header:
bcdCDC 1.10
CDC Call Management:
bmCapabilities 0x00
bDataInterface 2
CDC ACM:
bmCapabilities 0x06
sends break
line coding and serial state
CDC Union:
bMasterInterface 1
bSlaveInterface 2
Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x84 EP 4 IN
bmAttributes 3
Transfer Type Interrupt
Synch Type None
Usage Type Data
wMaxPacketSize 0x000a 1x 10 bytes
bInterval 16
Interface Descriptor:
bLength 9
bDescriptorType 4
bInterfaceNumber 2
bAlternateSetting 0
bNumEndpoints 2
bInterfaceClass 10 CDC Data
bInterfaceSubClass 0
bInterfaceProtocol 0
iInterface 7 ST-Link VCP Data
Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x05 EP 5 OUT
bmAttributes 2
Transfer Type Bulk
Synch Type None
Usage Type Data
wMaxPacketSize 0x0200 1x 512 bytes
bInterval 0
Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x85 EP 5 IN
bmAttributes 2
Transfer Type Bulk
Synch Type None
Usage Type Data
wMaxPacketSize 0x0200 1x 512 bytes
bInterval 0
Interface Descriptor:
bLength 9
bDescriptorType 4
bInterfaceNumber 3
bAlternateSetting 0
bNumEndpoints 2
bInterfaceClass 255 Vendor Specific Class
bInterfaceSubClass 255 Vendor Specific Subclass
bInterfaceProtocol 255 Vendor Specific Protocol
iInterface 8 ST-Link Bridge
Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x86 EP 6 IN
bmAttributes 2
Transfer Type Bulk
Synch Type None
Usage Type Data
wMaxPacketSize 0x0200 1x 512 bytes
bInterval 0
Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x06 EP 6 OUT
bmAttributes 2
Transfer Type Bulk
Synch Type None
Usage Type Data
wMaxPacketSize 0x0200 1x 512 bytes
bInterval 0
Interface Association:
bLength 8
bDescriptorType 11
bFirstInterface 4
bInterfaceCount 2
bFunctionClass 2 Communications
bFunctionSubClass 2 Abstract (modem)
bFunctionProtocol 1 AT-commands (v.25ter)
iFunction 9 ST-Link VCP-PWR Ctrl
Interface Descriptor:
bLength 9
bDescriptorType 4
bInterfaceNumber 4
bAlternateSetting 0
bNumEndpoints 1
bInterfaceClass 2 Communications
bInterfaceSubClass 2 Abstract (modem)
bInterfaceProtocol 1 AT-commands (v.25ter)
iInterface 9 ST-Link VCP-PWR Ctrl
CDC Header:
bcdCDC 1.10
CDC Call Management:
bmCapabilities 0x00
bDataInterface 5
CDC ACM:
bmCapabilities 0x06
sends break
line coding and serial state
CDC Union:
bMasterInterface 4
bSlaveInterface 5
Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x87 EP 7 IN
bmAttributes 3
Transfer Type Interrupt
Synch Type None
Usage Type Data
wMaxPacketSize 0x000a 1x 10 bytes
bInterval 16
Interface Descriptor:
bLength 9
bDescriptorType 4
bInterfaceNumber 5
bAlternateSetting 0
bNumEndpoints 2
bInterfaceClass 10 CDC Data
bInterfaceSubClass 0
bInterfaceProtocol 0
iInterface 10 ST-Link VCP-PWR Data
Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x03 EP 3 OUT
bmAttributes 2
Transfer Type Bulk
Synch Type None
Usage Type Data
wMaxPacketSize 0x0200 1x 512 bytes
bInterval 0
Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x83 EP 3 IN
bmAttributes 2
Transfer Type Bulk
Synch Type None
Usage Type Data
wMaxPacketSize 0x0200 1x 512 bytes
bInterval 0
Device Qualifier (for other device speed):
bLength 10
bDescriptorType 6
bcdUSB 2.00
bDeviceClass 0
bDeviceSubClass 0
bDeviceProtocol 0
bMaxPacketSize0 64
bNumConfigurations 1
Device Status: 0x0000
(Bus Powered)

View File

@ -251,18 +251,6 @@ static int efm32x_read_info(struct flash_bank *bank)
memset(efm32_info, 0, sizeof(struct efm32_info));
const struct cortex_m_common *cortex_m = target_to_cm(bank->target);
switch (cortex_m->core_info->partno) {
case CORTEX_M3_PARTNO:
case CORTEX_M4_PARTNO:
case CORTEX_M0P_PARTNO:
break;
default:
LOG_ERROR("Target is not Cortex-Mx Device");
return ERROR_FAIL;
}
ret = efm32x_get_flash_size(bank, &(efm32_info->flash_sz_kib));
if (ret != ERROR_OK)
return ret;

View File

@ -171,6 +171,7 @@ const struct flash_device flash_devices[] = {
FLASH_ID("xtx xt25q32b", 0x03, 0x0b, 0x02, 0xd8, 0xc7, 0x0016600b, 0x100, 0x10000, 0x400000), /* exists ? */
FLASH_ID("xtx xt25q64b", 0x03, 0x0b, 0x02, 0xd8, 0xc7, 0x0017600b, 0x100, 0x10000, 0x800000),
FLASH_ID("xtx xt25q128b", 0x03, 0x0b, 0x02, 0xd8, 0xc7, 0x0018600b, 0x100, 0x10000, 0x1000000),
FLASH_ID("zetta zd25q16", 0x03, 0x00, 0x02, 0xd8, 0xc7, 0x001560ba, 0x100, 0x10000, 0x200000),
/* FRAM, no erase commands, no write page or sectors */
FRAM_ID("fu mb85rs16n", 0x03, 0, 0x02, 0x00010104, 0x800),

View File

@ -743,7 +743,7 @@ static int stm32x_get_property_addr(struct target *target, struct stm32x_propert
return ERROR_TARGET_NOT_EXAMINED;
}
switch (cortex_m_get_partno_safe(target)) {
switch (cortex_m_get_impl_part(target)) {
case CORTEX_M0_PARTNO: /* STM32F0x devices */
addr->device_id = 0x40015800;
addr->flash_size = 0x1FFFF7CC;

View File

@ -961,7 +961,7 @@ static int stm32x_get_device_id(struct flash_bank *bank, uint32_t *device_id)
return retval;
if ((*device_id & 0xfff) == 0x411
&& cortex_m_get_partno_safe(target) == CORTEX_M4_PARTNO) {
&& cortex_m_get_impl_part(target) == CORTEX_M4_PARTNO) {
*device_id &= ~((0xFFFF << 16) | 0xfff);
*device_id |= (0x1000 << 16) | 0x413;
LOG_INFO("stm32f4x errata detected - fixing incorrect MCU_IDCODE");

View File

@ -795,7 +795,7 @@ static int stm32x_probe(struct flash_bank *bank)
/* STM32H74x/H75x, the second core (Cortex-M4) cannot read the flash size */
retval = ERROR_FAIL;
if (device_id == DEVID_STM32H74_H75XX
&& cortex_m_get_partno_safe(target) == CORTEX_M4_PARTNO)
&& cortex_m_get_impl_part(target) == CORTEX_M4_PARTNO)
LOG_WARNING("%s cannot read the flash size register", target_name(target));
else
retval = target_read_u16(target, stm32x_info->part_info->fsize_addr, &flash_size_in_kb);

View File

@ -326,6 +326,7 @@ static const struct stm32l4_rev stm32g47_g48xx_revs[] = {
static const struct stm32l4_rev stm32l4r_l4sxx_revs[] = {
{ 0x1000, "A" }, { 0x1001, "Z" }, { 0x1003, "Y" }, { 0x100F, "W" },
{ 0x101F, "V" },
};
static const struct stm32l4_rev stm32l4p_l4qxx_revs[] = {
@ -1681,7 +1682,7 @@ static int stm32l4_read_idcode(struct flash_bank *bank, uint32_t *id)
/* CPU2 (Cortex-M0+) is supported only with non-hla adapters because it is on AP1.
* Using HLA adapters armv7m.debug_ap is null, and checking ap_num triggers a segfault */
if (cortex_m_get_partno_safe(target) == CORTEX_M0P_PARTNO &&
if (cortex_m_get_impl_part(target) == CORTEX_M0P_PARTNO &&
armv7m->debug_ap && armv7m->debug_ap->ap_num == 1) {
uint32_t uid64_ids;

View File

@ -8,7 +8,9 @@
* identification code list, please visit the JEDEC website at www.jedec.org .
*/
/* This file is aligned to revision JEP106BF.01 October 2022. */
/* This file is aligned to revision JEP106BG May 2023. */
/* "NXP (Philips)" is reported below, while missing in JEP106BG */
[0][0x01 - 1] = "AMD",
[0][0x02 - 1] = "AMI",
@ -86,7 +88,7 @@
[0][0x4a - 1] = "Compaq",
[0][0x4b - 1] = "Protocol Engines",
[0][0x4c - 1] = "SCI",
[0][0x4d - 1] = "Seiko Instruments",
[0][0x4d - 1] = "ABLIC",
[0][0x4e - 1] = "Samsung",
[0][0x4f - 1] = "I3 Design System",
[0][0x50 - 1] = "Klic",
@ -972,7 +974,7 @@
[7][0x4e - 1] = "Mustang",
[7][0x4f - 1] = "Orca Systems",
[7][0x50 - 1] = "Passif Semiconductor",
[7][0x51 - 1] = "GigaDevice Semiconductor (Beijing) Inc",
[7][0x51 - 1] = "GigaDevice Semiconductor (Beijing)",
[7][0x52 - 1] = "Memphis Electronic",
[7][0x53 - 1] = "Beckhoff Automation GmbH",
[7][0x54 - 1] = "Harmony Semiconductor Corp",
@ -1786,4 +1788,57 @@
[14][0x0a - 1] = "UltraRISC Technology (Shanghai) Co Ltd",
[14][0x0b - 1] = "Shenzhen Jing Da Kang Technology Co Ltd",
[14][0x0c - 1] = "Hangzhou Hongjun Microelectronics Co Ltd",
[14][0x0d - 1] = "Pliops Ltd",
[14][0x0e - 1] = "Cix Technology (Shanghai) Co Ltd",
[14][0x0f - 1] = "TeraDevices Inc",
[14][0x10 - 1] = "SpacemiT (Hangzhou)Technology Co Ltd",
[14][0x11 - 1] = "InnoPhase loT Inc",
[14][0x12 - 1] = "InnoPhase loT Inc",
[14][0x13 - 1] = "Yunhight Microelectronics",
[14][0x14 - 1] = "Samnix",
[14][0x15 - 1] = "HKC Storage Co Ltd",
[14][0x16 - 1] = "Chiplego Technology (Shanghai) Co Ltd",
[14][0x17 - 1] = "StoreSkill",
[14][0x18 - 1] = "Shenzhen Astou Technology Company",
[14][0x19 - 1] = "Guangdong LeafFive Technology Limited",
[14][0x1a - 1] = "Jin JuQuan",
[14][0x1b - 1] = "Huaxuan Technology (Shenzhen) Co Ltd",
[14][0x1c - 1] = "Gigastone Corporation",
[14][0x1d - 1] = "Kinsotin",
[14][0x1e - 1] = "PengYing",
[14][0x1f - 1] = "Shenzhen Xunhi Technology Co Ltd",
[14][0x20 - 1] = "FOXX Storage Inc",
[14][0x21 - 1] = "Shanghai Belling Corporation Ltd",
[14][0x22 - 1] = "Glenfy Tech Co Ltd",
[14][0x23 - 1] = "Sahasra Semiconductors Pvt Ltd",
[14][0x24 - 1] = "Chongqing SeekWave Technology Co Ltd",
[14][0x25 - 1] = "Shenzhen Zhixing Intelligent Manufacturing",
[14][0x26 - 1] = "Ethernovia",
[14][0x27 - 1] = "Shenzhen Xinrongda Technology Co Ltd",
[14][0x28 - 1] = "Hangzhou Clounix Technology Limited",
[14][0x29 - 1] = "JGINYUE",
[14][0x2a - 1] = "Shenzhen Xinwei Semiconductor Co Ltd",
[14][0x2b - 1] = "COLORFIRE Technology Co Ltd",
[14][0x2c - 1] = "B LKE",
[14][0x2d - 1] = "ZHUDIAN",
[14][0x2e - 1] = "REECHO",
[14][0x2f - 1] = "Enphase Energy Inc",
[14][0x30 - 1] = "Shenzhen Yingrui Storage Technology Co Ltd",
[14][0x31 - 1] = "Shenzhen Sinomos Semiconductor Technology",
[14][0x32 - 1] = "O2micro International Limited",
[14][0x33 - 1] = "Axelera AI BV",
[14][0x34 - 1] = "Silicon Legend Technology (Suzhou) Co Ltd",
[14][0x35 - 1] = "Suzhou Novosense Microelectronics Co Ltd",
[14][0x36 - 1] = "Pirateman",
[14][0x37 - 1] = "Yangtze MasonSemi",
[14][0x38 - 1] = "Shanghai Yunsilicon Technology Co Ltd",
[14][0x39 - 1] = "Rayson",
[14][0x3a - 1] = "Alphawave IP",
[14][0x3b - 1] = "Shenzhen Visions Chip Electronic Technology",
[14][0x3c - 1] = "KYO Group",
[14][0x3d - 1] = "Shenzhen Aboison Technology Co Ltd",
[14][0x3e - 1] = "Shenzhen JingSheng Semiconducto Co Ltd",
[14][0x3f - 1] = "Shenzhen Dingsheng Technology Co Ltd",
[14][0x40 - 1] = "EVAS Intelligence Co Ltd",
[14][0x41 - 1] = "Kaibright Electronic Technologies",
/* EOF */

View File

@ -10,8 +10,10 @@ noinst_LTLIBRARIES += %D%/libocdjtagdrivers.la
%C%_libocdjtagdrivers_la_CPPFLAGS = $(AM_CPPFLAGS)
ULINK_FIRMWARE = %D%/OpenULINK
ANGIE_FILES = %D%/angie
EXTRA_DIST += $(ULINK_FIRMWARE) \
$(ANGIE_FILES) \
%D%/usb_blaster/README.CheapClone \
%D%/Makefile.rlink \
%D%/rlink_call.m4 \
@ -123,6 +125,12 @@ ulinkdir = $(pkgdatadir)/OpenULINK
dist_ulink_DATA = $(ULINK_FIRMWARE)/ulink_firmware.hex
%C%_libocdjtagdrivers_la_LIBADD += -lm
endif
if ANGIE
DRIVERFILES += %D%/angie.c
angiedir = $(pkgdatadir)/angie
dist_angie_DATA = $(ANGIE_FILES)/angie_firmware.bin $(ANGIE_FILES)/angie_bitstream.bit
%C%_libocdjtagdrivers_la_LIBADD += -lm
endif
if VSLLINK
DRIVERFILES += %D%/versaloon/usbtoxxx/usbtogpio.c
DRIVERFILES += %D%/versaloon/usbtoxxx/usbtojtagraw.c

2280
src/jtag/drivers/angie.c Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,3 @@
This folder contain only the files needed by ANGIE's driver.
You will find the complete ANGIE's firmware and the bitstream's code source in
contrib/firmware.

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,172 @@
/* SPDX-License-Identifier: GPL-2.0-or-later
****************************************************************************
File : msgtypes.h *
Contents : Definition of the commands supported by NanoXplore *
USB-JTAG ANGIE adapter hardware. *
Based on openULINK project code by: Martin Schmoelzer. *
Copyright 2023, Ahmed Errached BOUDJELIDA, NanoXplore SAS. *
<aboudjelida@nanoxplore.com> *
<ahmederrachedbjld@gmail.com> *
*****************************************************************************/
/**
* @file
* Definition of the commands supported by the ANGIE firmware.
*
* Basically, two types of commands can be distinguished:
* - Commands with fixed payload size
* - Commands with variable payload size
*
* SCAN commands (in all variations) carry payloads of variable size, all
* other commands carry payloads of fixed size.
*
* In the case of SCAN commands, the payload size (n) is calculated by
* dividing the scan_size_bits variable by 8, rounding up the result.
*
* Offset zero always contains the command ID.
*
****************************************************************************
* CMD_SCAN_IN, CMD_SLOW_SCAN_IN: *
* *
* OUT: *
* offset 1: scan_size_bytes *
* offset 2: bits_last_byte *
* offset 3: tms_count_start + tms_count_end *
* offset 4: tms_sequence_start *
* offset 5: tms_sequence_end *
* *
* IN: *
* offset 0..n: TDO data *
****************************************************************************
* CMD_SCAN_OUT, CMD_SLOW_SCAN_OUT: *
* *
* OUT: *
* offset 1: scan_size_bytes *
* offset 2: bits_last_byte *
* offset 3: tms_count_start + tms_count_end *
* offset 4: tms_sequence_start *
* offset 5: tms_sequence_end *
* offset 6..x: TDI data *
****************************************************************************
* CMD_SCAN_IO, CMD_SLOW_SCAN_IO: *
* *
* OUT: *
* offset 1: scan_size_bytes *
* offset 2: bits_last_byte *
* offset 3: tms_count_start + tms_count_end *
* offset 4: tms_sequence_start *
* offset 5: tms_sequence_end *
* offset 6..x: TDI data *
* *
* IN: *
* offset 0..n: TDO data *
****************************************************************************
* CMD_CLOCK_TMS, CMD_SLOW_CLOCK_TMS: *
* *
* OUT: *
* offset 1: tms_count *
* offset 2: tms_sequence *
****************************************************************************
* CMD_CLOCK_TCK, CMD_SLOW_CLOCK_TCK: *
* *
* OUT: *
* offset 1: low byte of tck_count *
* offset 2: high byte of tck_count *
****************************************************************************
* CMD_CLOCK_SLEEP_US: *
* *
* OUT: *
* offset 1: low byte of sleep_us *
* offset 2: high byte of sleep_us *
****************************************************************************
* CMD_CLOCK_SLEEP_MS: *
* *
* OUT: *
* offset 1: low byte of sleep_ms *
* offset 2: high byte of sleep_ms *
****************************************************************************
* CMD_GET_SIGNALS: *
* *
* IN: *
* offset 0: current state of input signals *
* offset 1: current state of output signals *
****************************************************************************
* CMD_SET_SIGNALS: *
* *
* OUT: *
* offset 1: signals that should be de-asserted *
* offset 2: signals that should be asserted *
****************************************************************************
* CMD_CONFIGURE_TCK_FREQ: *
* *
* OUT: *
* offset 1: delay value for scan_in function *
* offset 2: delay value for scan_out function *
* offset 3: delay value for scan_io function *
* offset 4: delay value for clock_tck function *
* offset 5: delay value for clock_tms function *
****************************************************************************
* CMD_SET_LEDS: *
* *
* OUT: *
* offset 1: LED states: *
* Bit 0: turn COM LED on *
* Bit 1: turn RUN LED on *
* Bit 2: turn COM LED off *
* Bit 3: turn RUN LED off *
* Bits 7..4: Reserved *
****************************************************************************
* CMD_TEST: *
* *
* OUT: *
* offset 1: unused dummy value *
****************************************************************************
*/
#ifndef __MSGTYPES_H
#define __MSGTYPES_H
/*
* Command IDs:
*
* Bits 7..6: Reserved, should always be zero
* Bits 5..0: Command ID. There are 62 usable IDs. Of this 63 available IDs,
* the IDs 0x00..0x1F are commands with variable payload size,
* the IDs 0x20..0x3F are commands with fixed payload size.
*/
#define CMD_ID_MASK 0x3F
/* Commands with variable payload size */
#define CMD_SCAN_IN 0x00
#define CMD_SLOW_SCAN_IN 0x01
#define CMD_SCAN_OUT 0x02
#define CMD_SLOW_SCAN_OUT 0x03
#define CMD_SCAN_IO 0x04
#define CMD_SLOW_SCAN_IO 0x05
/* Commands with fixed payload size */
#define CMD_CLOCK_TMS 0x20
#define CMD_SLOW_CLOCK_TMS 0x21
#define CMD_CLOCK_TCK 0x22
#define CMD_SLOW_CLOCK_TCK 0x23
#define CMD_SLEEP_US 0x24
#define CMD_SLEEP_MS 0x25
#define CMD_GET_SIGNALS 0x26
#define CMD_SET_SIGNALS 0x27
#define CMD_CONFIGURE_TCK_FREQ 0x28
#define CMD_SET_LEDS 0x29
#define CMD_TEST 0x2A
/* JTAG signal definition for jtag_get_signals() -- Input signals! */
#define SIGNAL_TDO 1
/* JTAG signal definition for jtag_get_signals() -- Output signals! */
#define SIGNAL_TDI 8
#define SIGNAL_TMS 2
#define SIGNAL_TCK 4
#define SIGNAL_TRST 1
#define SIGNAL_SRST 32
#endif

View File

@ -506,11 +506,13 @@ static int esp_usb_jtag_init(void)
* 1- With the minimum size required to get to know the total length of that struct,
* 2- Then exactly the length of that struct. */
uint8_t jtag_caps_desc[JTAG_PROTO_CAPS_DATA_LEN];
int jtag_caps_read_len = jtag_libusb_control_transfer(priv->usb_device,
int jtag_caps_read_len;
r = jtag_libusb_control_transfer(priv->usb_device,
LIBUSB_ENDPOINT_IN | LIBUSB_REQUEST_TYPE_STANDARD | LIBUSB_RECIPIENT_DEVICE,
LIBUSB_REQUEST_GET_DESCRIPTOR, esp_usb_jtag_caps, 0,
(char *)jtag_caps_desc, JTAG_PROTO_CAPS_DATA_LEN, LIBUSB_TIMEOUT_MS);
if (jtag_caps_read_len <= 0) {
(char *)jtag_caps_desc, JTAG_PROTO_CAPS_DATA_LEN, LIBUSB_TIMEOUT_MS,
&jtag_caps_read_len);
if (r != ERROR_OK) {
LOG_ERROR("esp_usb_jtag: could not retrieve jtag_caps descriptor!");
goto out;
}
@ -580,7 +582,8 @@ static int esp_usb_jtag_init(void)
0,
NULL,
0,
LIBUSB_TIMEOUT_MS);
LIBUSB_TIMEOUT_MS,
NULL);
return ERROR_OK;
@ -637,7 +640,7 @@ static int esp_usb_jtag_speed(int divisor)
LOG_DEBUG("esp_usb_jtag: setting divisor %d", divisor);
jtag_libusb_control_transfer(priv->usb_device,
LIBUSB_REQUEST_TYPE_VENDOR, VEND_JTAG_SETDIV, divisor, 0, NULL, 0, LIBUSB_TIMEOUT_MS);
LIBUSB_REQUEST_TYPE_VENDOR, VEND_JTAG_SETDIV, divisor, 0, NULL, 0, LIBUSB_TIMEOUT_MS, NULL);
return ERROR_OK;
}
@ -648,8 +651,8 @@ COMMAND_HANDLER(esp_usb_jtag_tdo_cmd)
if (!priv->usb_device)
return ERROR_FAIL;
int r = jtag_libusb_control_transfer(priv->usb_device,
LIBUSB_ENDPOINT_IN | LIBUSB_REQUEST_TYPE_VENDOR, VEND_JTAG_GETTDO, 0, 0, &tdo, 1, LIBUSB_TIMEOUT_MS);
if (r < 1)
LIBUSB_ENDPOINT_IN | LIBUSB_REQUEST_TYPE_VENDOR, VEND_JTAG_GETTDO, 0, 0, &tdo, 1, LIBUSB_TIMEOUT_MS, NULL);
if (r != ERROR_OK)
return r;
command_print(CMD, "%d", tdo);
@ -685,7 +688,7 @@ COMMAND_HANDLER(esp_usb_jtag_setio_cmd)
d |= VEND_JTAG_SETIO_SRST;
jtag_libusb_control_transfer(priv->usb_device,
0x40, VEND_JTAG_SETIO, d, 0, NULL, 0, LIBUSB_TIMEOUT_MS);
0x40, VEND_JTAG_SETIO, d, 0, NULL, 0, LIBUSB_TIMEOUT_MS, NULL);
return ERROR_OK;
}

View File

@ -235,7 +235,7 @@ static int ft232r_speed(int divisor)
if (jtag_libusb_control_transfer(adapter,
LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE | LIBUSB_ENDPOINT_OUT,
SIO_SET_BAUD_RATE, divisor, 0, NULL, 0, 1000) != 0) {
SIO_SET_BAUD_RATE, divisor, 0, NULL, 0, 1000, NULL) != ERROR_OK) {
LOG_ERROR("cannot set baud rate");
return ERROR_JTAG_DEVICE_ERROR;
}
@ -266,7 +266,7 @@ static int ft232r_init(void)
/* Reset the device. */
if (jtag_libusb_control_transfer(adapter,
LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE | LIBUSB_ENDPOINT_OUT,
SIO_RESET, 0, 0, NULL, 0, 1000) != 0) {
SIO_RESET, 0, 0, NULL, 0, 1000, NULL) != ERROR_OK) {
LOG_ERROR("unable to reset device");
return ERROR_JTAG_INIT_FAILED;
}
@ -275,7 +275,7 @@ static int ft232r_init(void)
if (jtag_libusb_control_transfer(adapter,
LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE | LIBUSB_ENDPOINT_OUT,
SIO_SET_BITMODE, (1<<tck_gpio) | (1<<tdi_gpio) | (1<<tms_gpio) | (1<<ntrst_gpio) | (1<<nsysrst_gpio) | 0x400,
0, NULL, 0, 1000) != 0) {
0, NULL, 0, 1000, NULL) != ERROR_OK) {
LOG_ERROR("cannot set sync bitbang mode");
return ERROR_JTAG_INIT_FAILED;
}
@ -288,13 +288,13 @@ static int ft232r_init(void)
if (jtag_libusb_control_transfer(adapter,
LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE | LIBUSB_ENDPOINT_OUT,
SIO_SET_BAUD_RATE, divisor,
0, NULL, 0, 1000) != 0) {
0, NULL, 0, 1000, NULL) != ERROR_OK) {
LOG_ERROR("cannot set baud rate");
return ERROR_JTAG_INIT_FAILED;
}
if (jtag_libusb_control_transfer(adapter,
LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE | LIBUSB_ENDPOINT_OUT,
SIO_SET_LATENCY_TIMER, latency_timer, 0, NULL, 0, 1000) != 0) {
SIO_SET_LATENCY_TIMER, latency_timer, 0, NULL, 0, 1000, NULL) != ERROR_OK) {
LOG_ERROR("unable to set latency timer");
return ERROR_JTAG_INIT_FAILED;
}
@ -315,7 +315,7 @@ static int ft232r_quit(void)
if (jtag_libusb_control_transfer(adapter,
LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE | LIBUSB_ENDPOINT_OUT,
SIO_SET_BITMODE, ft232r_restore_bitmode,
0, NULL, 0, 1000) != 0) {
0, NULL, 0, 1000, NULL) != ERROR_OK) {
LOG_ERROR("cannot set bitmode to restore serial port");
}
}

View File

@ -414,13 +414,13 @@ static int kitprog_set_protocol(uint8_t protocol)
int transferred;
char status = PROGRAMMER_NOK_NACK;
transferred = jtag_libusb_control_transfer(kitprog_handle->usb_handle,
int retval = jtag_libusb_control_transfer(kitprog_handle->usb_handle,
LIBUSB_ENDPOINT_IN | LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE,
CONTROL_TYPE_WRITE,
(CONTROL_MODE_SET_PROGRAMMER_PROTOCOL << 8) | CONTROL_COMMAND_PROGRAM,
protocol, &status, 1, 0);
protocol, &status, 1, 0, &transferred);
if (transferred == 0) {
if (retval != ERROR_OK || transferred == 0) {
LOG_DEBUG("Zero bytes transferred");
return ERROR_FAIL;
}
@ -440,11 +440,11 @@ static int kitprog_get_status(void)
/* Try a maximum of three times */
for (int i = 0; (i < 3) && (transferred == 0); i++) {
transferred = jtag_libusb_control_transfer(kitprog_handle->usb_handle,
jtag_libusb_control_transfer(kitprog_handle->usb_handle,
LIBUSB_ENDPOINT_IN | LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE,
CONTROL_TYPE_READ,
(CONTROL_MODE_POLL_PROGRAMMER_STATUS << 8) | CONTROL_COMMAND_PROGRAM,
0, &status, 1, 0);
0, &status, 1, 0, &transferred);
jtag_sleep(1000);
}
@ -466,13 +466,13 @@ static int kitprog_set_unknown(void)
int transferred;
char status = PROGRAMMER_NOK_NACK;
transferred = jtag_libusb_control_transfer(kitprog_handle->usb_handle,
int retval = jtag_libusb_control_transfer(kitprog_handle->usb_handle,
LIBUSB_ENDPOINT_IN | LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE,
CONTROL_TYPE_WRITE,
(0x03 << 8) | 0x04,
0, &status, 1, 0);
0, &status, 1, 0, &transferred);
if (transferred == 0) {
if (retval != ERROR_OK || transferred == 0) {
LOG_DEBUG("Zero bytes transferred");
return ERROR_FAIL;
}
@ -491,13 +491,13 @@ static int kitprog_acquire_psoc(uint8_t psoc_type, uint8_t acquire_mode,
int transferred;
char status = PROGRAMMER_NOK_NACK;
transferred = jtag_libusb_control_transfer(kitprog_handle->usb_handle,
int retval = jtag_libusb_control_transfer(kitprog_handle->usb_handle,
LIBUSB_ENDPOINT_IN | LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE,
CONTROL_TYPE_WRITE,
(CONTROL_MODE_ACQUIRE_SWD_TARGET << 8) | CONTROL_COMMAND_PROGRAM,
(max_attempts << 8) | (acquire_mode << 4) | psoc_type, &status, 1, 0);
(max_attempts << 8) | (acquire_mode << 4) | psoc_type, &status, 1, 0, &transferred);
if (transferred == 0) {
if (retval != ERROR_OK || transferred == 0) {
LOG_DEBUG("Zero bytes transferred");
return ERROR_FAIL;
}
@ -515,13 +515,13 @@ static int kitprog_reset_target(void)
int transferred;
char status = PROGRAMMER_NOK_NACK;
transferred = jtag_libusb_control_transfer(kitprog_handle->usb_handle,
int retval = jtag_libusb_control_transfer(kitprog_handle->usb_handle,
LIBUSB_ENDPOINT_IN | LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE,
CONTROL_TYPE_WRITE,
(CONTROL_MODE_RESET_TARGET << 8) | CONTROL_COMMAND_PROGRAM,
0, &status, 1, 0);
0, &status, 1, 0, &transferred);
if (transferred == 0) {
if (retval != ERROR_OK || transferred == 0) {
LOG_DEBUG("Zero bytes transferred");
return ERROR_FAIL;
}
@ -539,13 +539,13 @@ static int kitprog_swd_sync(void)
int transferred;
char status = PROGRAMMER_NOK_NACK;
transferred = jtag_libusb_control_transfer(kitprog_handle->usb_handle,
int retval = jtag_libusb_control_transfer(kitprog_handle->usb_handle,
LIBUSB_ENDPOINT_IN | LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE,
CONTROL_TYPE_WRITE,
(CONTROL_MODE_SYNCHRONIZE_TRANSFER << 8) | CONTROL_COMMAND_PROGRAM,
0, &status, 1, 0);
0, &status, 1, 0, &transferred);
if (transferred == 0) {
if (retval != ERROR_OK || transferred == 0) {
LOG_DEBUG("Zero bytes transferred");
return ERROR_FAIL;
}
@ -563,13 +563,13 @@ static int kitprog_swd_seq(uint8_t seq_type)
int transferred;
char status = PROGRAMMER_NOK_NACK;
transferred = jtag_libusb_control_transfer(kitprog_handle->usb_handle,
int retval = jtag_libusb_control_transfer(kitprog_handle->usb_handle,
LIBUSB_ENDPOINT_IN | LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE,
CONTROL_TYPE_WRITE,
(CONTROL_MODE_SEND_SWD_SEQUENCE << 8) | CONTROL_COMMAND_PROGRAM,
seq_type, &status, 1, 0);
seq_type, &status, 1, 0, &transferred);
if (transferred == 0) {
if (retval != ERROR_OK || transferred == 0) {
LOG_DEBUG("Zero bytes transferred");
return ERROR_FAIL;
}

View File

@ -216,17 +216,22 @@ void jtag_libusb_close(struct libusb_device_handle *dev)
int jtag_libusb_control_transfer(struct libusb_device_handle *dev, uint8_t request_type,
uint8_t request, uint16_t value, uint16_t index, char *bytes,
uint16_t size, unsigned int timeout)
uint16_t size, unsigned int timeout, int *transferred)
{
int transferred = 0;
transferred = libusb_control_transfer(dev, request_type, request, value, index,
int retval = libusb_control_transfer(dev, request_type, request, value, index,
(unsigned char *)bytes, size, timeout);
if (transferred < 0)
transferred = 0;
if (retval < 0) {
LOG_ERROR("libusb_control_transfer error: %s", libusb_error_name(retval));
if (transferred)
*transferred = 0;
return jtag_libusb_error(retval);
}
return transferred;
if (transferred)
*transferred = retval;
return ERROR_OK;
}
int jtag_libusb_bulk_write(struct libusb_device_handle *dev, int ep, char *bytes,

View File

@ -38,7 +38,8 @@ int jtag_libusb_open(const uint16_t vids[], const uint16_t pids[],
void jtag_libusb_close(struct libusb_device_handle *dev);
int jtag_libusb_control_transfer(struct libusb_device_handle *dev,
uint8_t request_type, uint8_t request, uint16_t value,
uint16_t index, char *bytes, uint16_t size, unsigned int timeout);
uint16_t index, char *bytes, uint16_t size, unsigned int timeout,
int *transferred);
int jtag_libusb_bulk_write(struct libusb_device_handle *dev, int ep,
char *bytes, int size, int timeout, int *transferred);
int jtag_libusb_bulk_read(struct libusb_device_handle *dev, int ep,

View File

@ -735,7 +735,7 @@ int opendous_usb_message(struct opendous_jtag *opendous_jtag, int out_length, in
/* Write data from out_buffer to USB. */
int opendous_usb_write(struct opendous_jtag *opendous_jtag, int out_length)
{
int result;
int result, transferred;
if (out_length > OPENDOUS_OUT_BUFFER_SIZE) {
LOG_ERROR("opendous_jtag_write illegal out_length=%d (max=%d)", out_length, OPENDOUS_OUT_BUFFER_SIZE);
@ -748,7 +748,11 @@ int opendous_usb_write(struct opendous_jtag *opendous_jtag, int out_length)
if (opendous_probe->CONTROL_TRANSFER) {
result = jtag_libusb_control_transfer(opendous_jtag->usb_handle,
LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE | LIBUSB_ENDPOINT_OUT,
FUNC_WRITE_DATA, 0, 0, (char *) usb_out_buffer, out_length, OPENDOUS_USB_TIMEOUT);
FUNC_WRITE_DATA, 0, 0, (char *)usb_out_buffer, out_length, OPENDOUS_USB_TIMEOUT,
&transferred);
/* FIXME: propagate error separately from transferred */
if (result == ERROR_OK)
result = transferred;
} else {
jtag_libusb_bulk_write(opendous_jtag->usb_handle, OPENDOUS_WRITE_ENDPOINT,
(char *)usb_out_buffer, out_length, OPENDOUS_USB_TIMEOUT, &result);
@ -768,6 +772,8 @@ int opendous_usb_write(struct opendous_jtag *opendous_jtag, int out_length)
/* Read data from USB into in_buffer. */
int opendous_usb_read(struct opendous_jtag *opendous_jtag)
{
int transferred;
#ifdef _DEBUG_USB_COMMS_
LOG_DEBUG("USB read begin");
#endif
@ -775,7 +781,11 @@ int opendous_usb_read(struct opendous_jtag *opendous_jtag)
if (opendous_probe->CONTROL_TRANSFER) {
result = jtag_libusb_control_transfer(opendous_jtag->usb_handle,
LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE | LIBUSB_ENDPOINT_IN,
FUNC_READ_DATA, 0, 0, (char *) usb_in_buffer, OPENDOUS_IN_BUFFER_SIZE, OPENDOUS_USB_TIMEOUT);
FUNC_READ_DATA, 0, 0, (char *)usb_in_buffer, OPENDOUS_IN_BUFFER_SIZE, OPENDOUS_USB_TIMEOUT,
&transferred);
/* FIXME: propagate error separately from transferred */
if (result == ERROR_OK)
result = transferred;
} else {
jtag_libusb_bulk_read(opendous_jtag->usb_handle, OPENDOUS_READ_ENDPOINT,
(char *)usb_in_buffer, OPENDOUS_IN_BUFFER_SIZE, OPENDOUS_USB_TIMEOUT, &result);

View File

@ -239,10 +239,10 @@ static int openjtag_buf_write_cy7c65215(
ret = jtag_libusb_control_transfer(usbh, CY7C65215_JTAG_REQUEST,
CY7C65215_JTAG_WRITE, size, 0,
NULL, 0, CY7C65215_USB_TIMEOUT);
if (ret < 0) {
LOG_ERROR("vendor command failed, error %d", ret);
return ERROR_JTAG_DEVICE_ERROR;
NULL, 0, CY7C65215_USB_TIMEOUT, NULL);
if (ret != ERROR_OK) {
LOG_ERROR("vendor command failed");
return ret;
}
if (jtag_libusb_bulk_write(usbh, ep_out, (char *)buf, size,
@ -306,10 +306,10 @@ static int openjtag_buf_read_cy7c65215(
ret = jtag_libusb_control_transfer(usbh, CY7C65215_JTAG_REQUEST,
CY7C65215_JTAG_READ, qty, 0,
NULL, 0, CY7C65215_USB_TIMEOUT);
if (ret < 0) {
LOG_ERROR("vendor command failed, error %d", ret);
return ERROR_JTAG_DEVICE_ERROR;
NULL, 0, CY7C65215_USB_TIMEOUT, NULL);
if (ret != ERROR_OK) {
LOG_ERROR("vendor command failed");
return ret;
}
if (jtag_libusb_bulk_read(usbh, ep_in, (char *)buf, qty,
@ -455,8 +455,8 @@ static int openjtag_init_cy7c65215(void)
ret = jtag_libusb_control_transfer(usbh,
CY7C65215_JTAG_REQUEST,
CY7C65215_JTAG_ENABLE,
0, 0, NULL, 0, CY7C65215_USB_TIMEOUT);
if (ret < 0) {
0, 0, NULL, 0, CY7C65215_USB_TIMEOUT, NULL);
if (ret != ERROR_OK) {
LOG_ERROR("could not enable JTAG module");
goto err;
}
@ -466,7 +466,7 @@ static int openjtag_init_cy7c65215(void)
err:
if (usbh)
jtag_libusb_close(usbh);
return ERROR_JTAG_INIT_FAILED;
return ret;
}
static int openjtag_init(void)
@ -508,8 +508,8 @@ static int openjtag_quit_cy7c65215(void)
ret = jtag_libusb_control_transfer(usbh,
CY7C65215_JTAG_REQUEST,
CY7C65215_JTAG_DISABLE,
0, 0, NULL, 0, CY7C65215_USB_TIMEOUT);
if (ret < 0)
0, 0, NULL, 0, CY7C65215_USB_TIMEOUT, NULL);
if (ret != ERROR_OK)
LOG_WARNING("could not disable JTAG module");
jtag_libusb_close(usbh);

View File

@ -84,6 +84,8 @@
#define STLINK_V3S_PID (0x374F)
#define STLINK_V3_2VCP_PID (0x3753)
#define STLINK_V3E_NO_MSD_PID (0x3754)
#define STLINK_V3P_USBLOADER_PID (0x3755)
#define STLINK_V3P_PID (0x3757)
/*
* ST-Link/V1, ST-Link/V2 and ST-Link/V2.1 are full-speed USB devices and
@ -1297,8 +1299,8 @@ static int stlink_usb_version(void *handle)
break;
}
/* STLINK-V3 requires a specific command */
if (v == 3 && x == 0 && y == 0) {
/* STLINK-V3 & STLINK-V3P require a specific command */
if (v >= 3 && x == 0 && y == 0) {
stlink_usb_init_buffer(handle, h->rx_ep, 16);
h->cmdbuf[h->cmdidx++] = STLINK_APIV3_GET_VERSION_EX;
@ -1414,6 +1416,41 @@ static int stlink_usb_version(void *handle)
if (h->version.jtag >= 6)
flags |= STLINK_F_HAS_RW8_512BYTES;
break;
case 4:
/* STLINK-V3P use api-v3 */
h->version.jtag_api = STLINK_JTAG_API_V3;
/* STLINK-V3P is a superset of ST-LINK/V3 */
/* API for trace */
/* API for target voltage */
flags |= STLINK_F_HAS_TRACE;
/* preferred API to get last R/W status */
flags |= STLINK_F_HAS_GETLASTRWSTATUS2;
/* API to access DAP registers */
flags |= STLINK_F_HAS_DAP_REG;
/* API to read/write memory at 16 bit */
/* API to write memory without address increment */
flags |= STLINK_F_HAS_MEM_16BIT;
/* API required to init AP before any AP access */
flags |= STLINK_F_HAS_AP_INIT;
/* API required to return proper error code on close AP */
flags |= STLINK_F_FIX_CLOSE_AP;
/* Banked regs (DPv1 & DPv2) support */
/* API to read memory without address increment */
/* Memory R/W supports CSW */
flags |= STLINK_F_HAS_DPBANKSEL;
/* 8bit read/write max packet size 512 bytes */
flags |= STLINK_F_HAS_RW8_512BYTES;
break;
default:
break;
@ -3402,6 +3439,8 @@ static int stlink_usb_usb_open(void *handle, struct hl_interface_param_s *param)
case STLINK_V3S_PID:
case STLINK_V3_2VCP_PID:
case STLINK_V3E_NO_MSD_PID:
case STLINK_V3P_USBLOADER_PID:
case STLINK_V3P_PID:
h->version.stlink = 3;
h->tx_ep = STLINK_V2_1_TX_EP;
h->trace_ep = STLINK_V2_1_TRACE_EP;
@ -3820,7 +3859,7 @@ static int stlink_config_trace(void *handle, bool enabled,
return ERROR_FAIL;
}
unsigned int max_trace_freq = (h->version.stlink == 3) ?
unsigned int max_trace_freq = (h->version.stlink >= 3) ?
STLINK_V3_TRACE_MAX_HZ : STLINK_TRACE_MAX_HZ;
/* Only concern ourselves with the frequency if the STlink is processing it. */

View File

@ -103,7 +103,8 @@ static int ublast2_write_firmware_section(struct libusb_device_handle *libusb_de
0,
(char *)data_ptr,
chunk_size,
100);
100,
NULL);
bytes_remaining -= chunk_size;
addr += chunk_size;
@ -154,7 +155,8 @@ static int load_usb_blaster_firmware(struct libusb_device_handle *libusb_dev,
0,
&value,
1,
100);
100,
NULL);
/* Download all sections in the image to ULINK */
for (unsigned int i = 0; i < ublast2_firmware_image.num_sections; i++) {
@ -175,7 +177,8 @@ static int load_usb_blaster_firmware(struct libusb_device_handle *libusb_dev,
0,
&value,
1,
100);
100,
NULL);
error_close_firmware:
image_close(&ublast2_firmware_image);
@ -245,7 +248,8 @@ static int ublast2_libusb_init(struct ublast_lowlevel *low)
0,
buffer,
5,
100);
100,
NULL);
LOG_INFO("Altera USB-Blaster II found (Firm. rev. = %s)", buffer);

View File

@ -579,9 +579,6 @@ static bool usb_get_response(uint32_t *total_bytes_read, uint32_t timeout)
static bool usb_send_command(uint16_t size)
{
int written = 0;
bool success = true;
/* Check the packet length */
if (size > USB_PAYLOAD_SIZE)
return false;
@ -596,13 +593,7 @@ static bool usb_send_command(uint16_t size)
size += 3;
/* Send the data via the USB connection */
success = usb_write(xds110.write_packet, (int)size, &written);
/* Check if the correct number of bytes was written */
if (written != (int)size)
success = false;
return success;
return usb_write(xds110.write_packet, (int)size, NULL);
}
/***************************************************************************

View File

@ -364,6 +364,7 @@ int adapter_poll_trace(uint8_t *buf, size_t *size);
extern struct adapter_driver am335xgpio_adapter_driver;
extern struct adapter_driver amt_jtagaccel_adapter_driver;
extern struct adapter_driver angie_adapter_driver;
extern struct adapter_driver armjtagew_adapter_driver;
extern struct adapter_driver at91rm9200_adapter_driver;
extern struct adapter_driver bcm2835gpio_adapter_driver;

View File

@ -96,6 +96,9 @@ struct adapter_driver *adapter_drivers[] = {
#if BUILD_ULINK == 1
&ulink_adapter_driver,
#endif
#if BUILD_ANGIE == 1
&angie_adapter_driver,
#endif
#if BUILD_ARMJTAGEW == 1
&armjtagew_adapter_driver,
#endif

View File

@ -1108,4 +1108,18 @@ proc "am335xgpio led_on_state" {state} {
}
}
lappend _telnet_autocomplete_skip "pld device"
proc "pld device" {driver tap_name {opt 0}} {
echo "DEPRECATED! use 'pld create ...', not 'pld device ...'"
if {[string is integer -strict $opt]} {
if {$opt == 0} {
eval pld create [lindex [split $tap_name .] 0].pld $driver -chain-position $tap_name
} else {
eval pld create [lindex [split $tap_name .] 0].pld $driver -chain-position $tap_name -no_jstart
}
} else {
eval pld create [lindex [split $tap_name .] 0].pld $driver -chain-position $tap_name -family $opt
}
}
# END MIGRATION AIDS

View File

@ -16,13 +16,29 @@
#define PROGRAM 0x4
#define ENTERUSER 0x7
#define USER1 0x8
#define USER2 0x9
#define USER3 0xa
#define USER4 0xb
enum efinix_family_e {
EFINIX_TRION,
EFINIX_TITANIUM,
EFINIX_UNKNOWN
};
#define TRAILING_ZEROS 4000
#define RUNTEST_START_CYCLES 100
#define RUNTEST_FINISH_CYCLES 100
struct efinix_device {
uint32_t idcode;
int num_user;
};
struct efinix_pld_device {
struct jtag_tap *tap;
enum efinix_family_e family;
};
static int efinix_read_bit_file(struct raw_bit_file *bit_file, const char *filename)
@ -188,23 +204,87 @@ static int efinix_load(struct pld_device *pld_device, const char *filename)
return retval;
}
PLD_DEVICE_COMMAND_HANDLER(efinix_pld_device_command)
static int efinix_get_ipdbg_hub(int user_num, struct pld_device *pld_device, struct pld_ipdbg_hub *hub)
{
if (CMD_ARGC != 2)
if (!pld_device)
return ERROR_FAIL;
struct efinix_pld_device *pld_device_info = pld_device->driver_priv;
if (!pld_device_info || !pld_device_info->tap)
return ERROR_FAIL;
hub->tap = pld_device_info->tap;
if (pld_device_info->family == EFINIX_UNKNOWN) {
LOG_ERROR("family unknown, please specify for 'pld create'");
return ERROR_FAIL;
}
int num_user = 2; /* trion */
if (pld_device_info->family == EFINIX_TITANIUM)
num_user = 4;
if (user_num > num_user) {
LOG_ERROR("Devices has only user register 1 to %d", num_user);
return ERROR_FAIL;
}
switch (user_num) {
case 1:
hub->user_ir_code = USER1;
break;
case 2:
hub->user_ir_code = USER2;
break;
case 3:
hub->user_ir_code = USER3;
break;
case 4:
hub->user_ir_code = USER4;
break;
default:
LOG_ERROR("efinix devices only have user register 1 to %d", num_user);
return ERROR_FAIL;
}
return ERROR_OK;
}
PLD_CREATE_COMMAND_HANDLER(efinix_pld_create_command)
{
if (CMD_ARGC != 4 && CMD_ARGC != 6)
return ERROR_COMMAND_SYNTAX_ERROR;
struct jtag_tap *tap = jtag_tap_by_string(CMD_ARGV[1]);
if (strcmp(CMD_ARGV[2], "-chain-position") != 0)
return ERROR_COMMAND_SYNTAX_ERROR;
struct jtag_tap *tap = jtag_tap_by_string(CMD_ARGV[3]);
if (!tap) {
command_print(CMD, "Tap: %s does not exist", CMD_ARGV[1]);
command_print(CMD, "Tap: %s does not exist", CMD_ARGV[3]);
return ERROR_FAIL;
}
enum efinix_family_e family = EFINIX_UNKNOWN;
if (CMD_ARGC == 6) {
if (strcmp(CMD_ARGV[4], "-family") != 0)
return ERROR_COMMAND_SYNTAX_ERROR;
if (strcmp(CMD_ARGV[5], "trion") == 0) {
family = EFINIX_TRION;
} else if (strcmp(CMD_ARGV[5], "titanium") == 0) {
family = EFINIX_TITANIUM;
} else {
command_print(CMD, "unknown family");
return ERROR_FAIL;
}
}
struct efinix_pld_device *efinix_info = malloc(sizeof(struct efinix_pld_device));
if (!efinix_info) {
LOG_ERROR("Out of memory");
return ERROR_FAIL;
}
efinix_info->tap = tap;
efinix_info->family = family;
pld->driver_priv = efinix_info;
@ -213,6 +293,7 @@ PLD_DEVICE_COMMAND_HANDLER(efinix_pld_device_command)
struct pld_driver efinix_pld = {
.name = "efinix",
.pld_device_command = &efinix_pld_device_command,
.pld_create_command = &efinix_pld_create_command,
.load = &efinix_load,
.get_ipdbg_hub = efinix_get_ipdbg_hub,
};

View File

@ -209,22 +209,21 @@ static int gatemate_load(struct pld_device *pld_device, const char *filename)
return retval;
}
PLD_DEVICE_COMMAND_HANDLER(gatemate_pld_device_command)
PLD_CREATE_COMMAND_HANDLER(gatemate_pld_create_command)
{
struct jtag_tap *tap;
struct gatemate_pld_device *gatemate_info;
if (CMD_ARGC != 2)
if (CMD_ARGC != 4)
return ERROR_COMMAND_SYNTAX_ERROR;
tap = jtag_tap_by_string(CMD_ARGV[1]);
if (strcmp(CMD_ARGV[2], "-chain-position") != 0)
return ERROR_COMMAND_SYNTAX_ERROR;
struct jtag_tap *tap = jtag_tap_by_string(CMD_ARGV[3]);
if (!tap) {
command_print(CMD, "Tap: %s does not exist", CMD_ARGV[1]);
command_print(CMD, "Tap: %s does not exist", CMD_ARGV[3]);
return ERROR_FAIL;
}
gatemate_info = malloc(sizeof(struct gatemate_pld_device));
struct gatemate_pld_device *gatemate_info = malloc(sizeof(struct gatemate_pld_device));
if (!gatemate_info) {
LOG_ERROR("Out of memory");
return ERROR_FAIL;
@ -238,6 +237,6 @@ PLD_DEVICE_COMMAND_HANDLER(gatemate_pld_device_command)
struct pld_driver gatemate_pld = {
.name = "gatemate",
.pld_device_command = &gatemate_pld_device_command,
.pld_create_command = &gatemate_pld_create_command,
.load = &gatemate_load,
};

View File

@ -29,6 +29,9 @@
#define ERASE_FLASH 0x75
#define ENABLE_2ND_FLASH 0x78
#define USER1 0x42
#define USER2 0x43
#define STAUS_MASK_MEMORY_ERASE BIT(5)
#define STAUS_MASK_SYSTEM_EDIT_MODE BIT(7)
@ -449,17 +452,37 @@ static int gowin_reload_command(struct pld_device *pld_device)
return gowin_reload(gowin_info->tap);
}
static int gowin_get_ipdbg_hub(int user_num, struct pld_device *pld_device, struct pld_ipdbg_hub *hub)
{
if (!pld_device)
return ERROR_FAIL;
struct gowin_pld_device *pld_device_info = pld_device->driver_priv;
if (!pld_device_info || !pld_device_info->tap)
return ERROR_FAIL;
hub->tap = pld_device_info->tap;
if (user_num == 1) {
hub->user_ir_code = USER1;
} else if (user_num == 2) {
hub->user_ir_code = USER2;
} else {
LOG_ERROR("gowin devices only have user register 1 & 2");
return ERROR_FAIL;
}
return ERROR_OK;
}
COMMAND_HANDLER(gowin_read_status_command_handler)
{
int dev_id;
if (CMD_ARGC != 1)
return ERROR_COMMAND_SYNTAX_ERROR;
COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], dev_id);
struct pld_device *device = get_pld_device_by_num(dev_id);
struct pld_device *device = get_pld_device_by_name_or_numstr(CMD_ARGV[0]);
if (!device) {
command_print(CMD, "pld device '#%s' is out of bounds", CMD_ARGV[0]);
command_print(CMD, "pld device '#%s' is out of bounds or unknown", CMD_ARGV[0]);
return ERROR_FAIL;
}
@ -474,15 +497,12 @@ COMMAND_HANDLER(gowin_read_status_command_handler)
COMMAND_HANDLER(gowin_read_user_register_command_handler)
{
int dev_id;
if (CMD_ARGC != 1)
return ERROR_COMMAND_SYNTAX_ERROR;
COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], dev_id);
struct pld_device *device = get_pld_device_by_num(dev_id);
struct pld_device *device = get_pld_device_by_name_or_numstr(CMD_ARGV[0]);
if (!device) {
command_print(CMD, "pld device '#%s' is out of bounds", CMD_ARGV[0]);
command_print(CMD, "pld device '#%s' is out of bounds or unknown", CMD_ARGV[0]);
return ERROR_FAIL;
}
@ -497,15 +517,12 @@ COMMAND_HANDLER(gowin_read_user_register_command_handler)
COMMAND_HANDLER(gowin_reload_command_handler)
{
int dev_id;
if (CMD_ARGC != 1)
return ERROR_COMMAND_SYNTAX_ERROR;
COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], dev_id);
struct pld_device *device = get_pld_device_by_num(dev_id);
struct pld_device *device = get_pld_device_by_name_or_numstr(CMD_ARGV[0]);
if (!device) {
command_print(CMD, "pld device '#%s' is out of bounds", CMD_ARGV[0]);
command_print(CMD, "pld device '#%s' is out of bounds or unknown", CMD_ARGV[0]);
return ERROR_FAIL;
}
@ -518,19 +535,19 @@ static const struct command_registration gowin_exec_command_handlers[] = {
.mode = COMMAND_EXEC,
.handler = gowin_read_status_command_handler,
.help = "reading status register from FPGA",
.usage = "num_pld",
.usage = "pld_name",
}, {
.name = "read_user",
.mode = COMMAND_EXEC,
.handler = gowin_read_user_register_command_handler,
.help = "reading user register from FPGA",
.usage = "num_pld",
.usage = "pld_name",
}, {
.name = "reload",
.mode = COMMAND_EXEC,
.handler = gowin_reload_command_handler,
.help = "reloading bitstream from flash to SRAM",
.usage = "num_pld",
.usage = "pld_name",
},
COMMAND_REGISTRATION_DONE
};
@ -546,22 +563,21 @@ static const struct command_registration gowin_command_handler[] = {
COMMAND_REGISTRATION_DONE
};
PLD_DEVICE_COMMAND_HANDLER(gowin_pld_device_command)
PLD_CREATE_COMMAND_HANDLER(gowin_pld_create_command)
{
struct jtag_tap *tap;
struct gowin_pld_device *gowin_info;
if (CMD_ARGC != 2)
if (CMD_ARGC != 4)
return ERROR_COMMAND_SYNTAX_ERROR;
tap = jtag_tap_by_string(CMD_ARGV[1]);
if (strcmp(CMD_ARGV[2], "-chain-position") != 0)
return ERROR_COMMAND_SYNTAX_ERROR;
struct jtag_tap *tap = jtag_tap_by_string(CMD_ARGV[3]);
if (!tap) {
command_print(CMD, "Tap: %s does not exist", CMD_ARGV[1]);
command_print(CMD, "Tap: %s does not exist", CMD_ARGV[3]);
return ERROR_FAIL;
}
gowin_info = malloc(sizeof(struct gowin_pld_device));
struct gowin_pld_device *gowin_info = malloc(sizeof(struct gowin_pld_device));
if (!gowin_info) {
LOG_ERROR("Out of memory");
return ERROR_FAIL;
@ -576,6 +592,7 @@ PLD_DEVICE_COMMAND_HANDLER(gowin_pld_device_command)
struct pld_driver gowin_pld = {
.name = "gowin",
.commands = gowin_command_handler,
.pld_device_command = &gowin_pld_device_command,
.pld_create_command = &gowin_pld_create_command,
.load = &gowin_load_to_sram,
.get_ipdbg_hub = gowin_get_ipdbg_hub,
};

View File

@ -18,6 +18,8 @@
#include "raw_bit.h"
#define BYPASS 0x3FF
#define USER0 0x00C
#define USER1 0x00E
enum intel_family_e {
INTEL_CYCLONEIII,
@ -337,18 +339,39 @@ static int intel_load(struct pld_device *pld_device, const char *filename)
return jtag_execute_queue();
}
static int intel_get_ipdbg_hub(int user_num, struct pld_device *pld_device, struct pld_ipdbg_hub *hub)
{
if (!pld_device)
return ERROR_FAIL;
struct intel_pld_device *pld_device_info = pld_device->driver_priv;
if (!pld_device_info || !pld_device_info->tap)
return ERROR_FAIL;
hub->tap = pld_device_info->tap;
if (user_num == 0) {
hub->user_ir_code = USER0;
} else if (user_num == 1) {
hub->user_ir_code = USER1;
} else {
LOG_ERROR("intel devices only have user register 0 & 1");
return ERROR_FAIL;
}
return ERROR_OK;
}
COMMAND_HANDLER(intel_set_bscan_command_handler)
{
int dev_id;
unsigned int boundary_scan_length;
if (CMD_ARGC != 2)
return ERROR_COMMAND_SYNTAX_ERROR;
COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], dev_id);
struct pld_device *pld_device = get_pld_device_by_num(dev_id);
struct pld_device *pld_device = get_pld_device_by_name_or_numstr(CMD_ARGV[0]);
if (!pld_device) {
command_print(CMD, "pld device '#%s' is out of bounds", CMD_ARGV[0]);
command_print(CMD, "pld device '#%s' is out of bounds or unknown", CMD_ARGV[0]);
return ERROR_FAIL;
}
@ -366,16 +389,14 @@ COMMAND_HANDLER(intel_set_bscan_command_handler)
COMMAND_HANDLER(intel_set_check_pos_command_handler)
{
int dev_id;
int checkpos;
if (CMD_ARGC != 2)
return ERROR_COMMAND_SYNTAX_ERROR;
COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], dev_id);
struct pld_device *pld_device = get_pld_device_by_num(dev_id);
struct pld_device *pld_device = get_pld_device_by_name_or_numstr(CMD_ARGV[0]);
if (!pld_device) {
command_print(CMD, "pld device '#%s' is out of bounds", CMD_ARGV[0]);
command_print(CMD, "pld device '#%s' is out of bounds or unknown", CMD_ARGV[0]);
return ERROR_FAIL;
}
@ -392,42 +413,47 @@ COMMAND_HANDLER(intel_set_check_pos_command_handler)
}
PLD_DEVICE_COMMAND_HANDLER(intel_pld_device_command)
PLD_CREATE_COMMAND_HANDLER(intel_pld_create_command)
{
if (CMD_ARGC < 2 || CMD_ARGC > 3)
if (CMD_ARGC != 4 && CMD_ARGC != 6)
return ERROR_COMMAND_SYNTAX_ERROR;
struct jtag_tap *tap = jtag_tap_by_string(CMD_ARGV[1]);
if (strcmp(CMD_ARGV[2], "-chain-position") != 0)
return ERROR_COMMAND_SYNTAX_ERROR;
struct jtag_tap *tap = jtag_tap_by_string(CMD_ARGV[3]);
if (!tap) {
command_print(CMD, "Tap: %s does not exist", CMD_ARGV[1]);
command_print(CMD, "Tap: %s does not exist", CMD_ARGV[3]);
return ERROR_FAIL;
}
enum intel_family_e family = INTEL_UNKNOWN;
if (CMD_ARGC == 6) {
if (strcmp(CMD_ARGV[4], "-family") != 0)
return ERROR_COMMAND_SYNTAX_ERROR;
if (strcmp(CMD_ARGV[5], "cycloneiii") == 0) {
family = INTEL_CYCLONEIII;
} else if (strcmp(CMD_ARGV[5], "cycloneiv") == 0) {
family = INTEL_CYCLONEIV;
} else if (strcmp(CMD_ARGV[5], "cyclonev") == 0) {
family = INTEL_CYCLONEV;
} else if (strcmp(CMD_ARGV[5], "cyclone10") == 0) {
family = INTEL_CYCLONE10;
} else if (strcmp(CMD_ARGV[5], "arriaii") == 0) {
family = INTEL_ARRIAII;
} else {
command_print(CMD, "unknown family");
return ERROR_FAIL;
}
}
struct intel_pld_device *intel_info = malloc(sizeof(struct intel_pld_device));
if (!intel_info) {
LOG_ERROR("Out of memory");
return ERROR_FAIL;
}
enum intel_family_e family = INTEL_UNKNOWN;
if (CMD_ARGC == 3) {
if (strcmp(CMD_ARGV[2], "cycloneiii") == 0) {
family = INTEL_CYCLONEIII;
} else if (strcmp(CMD_ARGV[2], "cycloneiv") == 0) {
family = INTEL_CYCLONEIV;
} else if (strcmp(CMD_ARGV[2], "cyclonev") == 0) {
family = INTEL_CYCLONEV;
} else if (strcmp(CMD_ARGV[2], "cyclone10") == 0) {
family = INTEL_CYCLONE10;
} else if (strcmp(CMD_ARGV[2], "arriaii") == 0) {
family = INTEL_ARRIAII;
} else {
command_print(CMD, "unknown family");
free(intel_info);
return ERROR_FAIL;
}
}
intel_info->tap = tap;
intel_info->boundary_scan_length = 0;
intel_info->checkpos = -1;
@ -441,16 +467,16 @@ PLD_DEVICE_COMMAND_HANDLER(intel_pld_device_command)
static const struct command_registration intel_exec_command_handlers[] = {
{
.name = "set_bscan",
.mode = COMMAND_EXEC,
.mode = COMMAND_ANY,
.handler = intel_set_bscan_command_handler,
.help = "set boundary scan register length of FPGA",
.usage = "num_pld len",
.usage = "pld_name len",
}, {
.name = "set_check_pos",
.mode = COMMAND_EXEC,
.mode = COMMAND_ANY,
.handler = intel_set_check_pos_command_handler,
.help = "set check_pos of FPGA",
.usage = "num_pld pos",
.usage = "pld_name pos",
},
COMMAND_REGISTRATION_DONE
};
@ -469,6 +495,7 @@ static const struct command_registration intel_command_handler[] = {
struct pld_driver intel_pld = {
.name = "intel",
.commands = intel_command_handler,
.pld_device_command = &intel_pld_device_command,
.pld_create_command = &intel_pld_create_command,
.load = &intel_load,
.get_ipdbg_hub = intel_get_ipdbg_hub,
};

View File

@ -18,6 +18,9 @@
#include "certus.h"
#define PRELOAD 0x1C
#define USER1 0x32
#define USER2 0x38
struct lattice_devices_elem {
uint32_t id;
@ -316,39 +319,69 @@ static int lattice_load_command(struct pld_device *pld_device, const char *filen
return retval;
}
PLD_DEVICE_COMMAND_HANDLER(lattice_pld_device_command)
static int lattice_get_ipdbg_hub(int user_num, struct pld_device *pld_device, struct pld_ipdbg_hub *hub)
{
if (CMD_ARGC < 2 || CMD_ARGC > 3)
if (!pld_device)
return ERROR_FAIL;
struct lattice_pld_device *pld_device_info = pld_device->driver_priv;
if (!pld_device_info || !pld_device_info->tap)
return ERROR_FAIL;
hub->tap = pld_device_info->tap;
if (user_num == 1) {
hub->user_ir_code = USER1;
} else if (user_num == 2) {
hub->user_ir_code = USER2;
} else {
LOG_ERROR("lattice devices only have user register 1 & 2");
return ERROR_FAIL;
}
return ERROR_OK;
}
PLD_CREATE_COMMAND_HANDLER(lattice_pld_create_command)
{
if (CMD_ARGC != 4 && CMD_ARGC != 6)
return ERROR_COMMAND_SYNTAX_ERROR;
struct jtag_tap *tap = jtag_tap_by_string(CMD_ARGV[1]);
if (strcmp(CMD_ARGV[2], "-chain-position") != 0)
return ERROR_COMMAND_SYNTAX_ERROR;
struct jtag_tap *tap = jtag_tap_by_string(CMD_ARGV[3]);
if (!tap) {
command_print(CMD, "Tap: %s does not exist", CMD_ARGV[1]);
command_print(CMD, "Tap: %s does not exist", CMD_ARGV[3]);
return ERROR_FAIL;
}
/* id is not known yet -> postpone lattice_check_device_family() */
enum lattice_family_e family = LATTICE_UNKNOWN;
if (CMD_ARGC == 6) {
if (strcmp(CMD_ARGV[4], "-family") != 0)
return ERROR_COMMAND_SYNTAX_ERROR;
if (strcasecmp(CMD_ARGV[5], "ecp2") == 0) {
family = LATTICE_ECP2;
} else if (strcasecmp(CMD_ARGV[5], "ecp3") == 0) {
family = LATTICE_ECP3;
} else if (strcasecmp(CMD_ARGV[5], "ecp5") == 0) {
family = LATTICE_ECP5;
} else if (strcasecmp(CMD_ARGV[5], "certus") == 0) {
family = LATTICE_CERTUS;
} else {
command_print(CMD, "unknown family");
return ERROR_FAIL;
}
}
struct lattice_pld_device *lattice_device = malloc(sizeof(struct lattice_pld_device));
if (!lattice_device) {
LOG_ERROR("Out of memory");
return ERROR_FAIL;
}
/* id is not known yet -> postpone lattice_check_device_family() */
enum lattice_family_e family = LATTICE_UNKNOWN;
if (CMD_ARGC == 3) {
if (strcasecmp(CMD_ARGV[2], "ecp2") == 0) {
family = LATTICE_ECP2;
} else if (strcasecmp(CMD_ARGV[2], "ecp3") == 0) {
family = LATTICE_ECP3;
} else if (strcasecmp(CMD_ARGV[2], "ecp5") == 0) {
family = LATTICE_ECP5;
} else if (strcasecmp(CMD_ARGV[2], "certus") == 0) {
family = LATTICE_CERTUS;
} else {
command_print(CMD, "unknown family");
free(lattice_device);
return ERROR_FAIL;
}
}
lattice_device->tap = tap;
lattice_device->family = family;
lattice_device->preload_length = 0;
@ -360,16 +393,14 @@ PLD_DEVICE_COMMAND_HANDLER(lattice_pld_device_command)
COMMAND_HANDLER(lattice_read_usercode_register_command_handler)
{
int dev_id;
uint32_t usercode;
if (CMD_ARGC != 1)
return ERROR_COMMAND_SYNTAX_ERROR;
COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], dev_id);
struct pld_device *device = get_pld_device_by_num(dev_id);
struct pld_device *device = get_pld_device_by_name_or_numstr(CMD_ARGV[0]);
if (!device) {
command_print(CMD, "pld device '#%s' is out of bounds", CMD_ARGV[0]);
command_print(CMD, "pld device '#%s' is out of bounds or unknown", CMD_ARGV[0]);
return ERROR_FAIL;
}
@ -390,16 +421,14 @@ COMMAND_HANDLER(lattice_read_usercode_register_command_handler)
COMMAND_HANDLER(lattice_set_preload_command_handler)
{
int dev_id;
unsigned int preload_length;
if (CMD_ARGC != 2)
return ERROR_COMMAND_SYNTAX_ERROR;
COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], dev_id);
struct pld_device *device = get_pld_device_by_num(dev_id);
struct pld_device *device = get_pld_device_by_name_or_numstr(CMD_ARGV[0]);
if (!device) {
command_print(CMD, "pld device '#%s' is out of bounds", CMD_ARGV[0]);
command_print(CMD, "pld device '#%s' is out of bounds or unknown", CMD_ARGV[0]);
return ERROR_FAIL;
}
@ -417,16 +446,14 @@ COMMAND_HANDLER(lattice_set_preload_command_handler)
COMMAND_HANDLER(lattice_write_usercode_register_command_handler)
{
int dev_id;
uint32_t usercode;
if (CMD_ARGC != 2)
return ERROR_COMMAND_SYNTAX_ERROR;
COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], dev_id);
struct pld_device *device = get_pld_device_by_num(dev_id);
struct pld_device *device = get_pld_device_by_name_or_numstr(CMD_ARGV[0]);
if (!device) {
command_print(CMD, "pld device '#%s' is out of bounds", CMD_ARGV[0]);
command_print(CMD, "pld device '#%s' is out of bounds or unknown", CMD_ARGV[0]);
return ERROR_FAIL;
}
@ -445,15 +472,12 @@ COMMAND_HANDLER(lattice_write_usercode_register_command_handler)
COMMAND_HANDLER(lattice_read_status_command_handler)
{
int dev_id;
if (CMD_ARGC != 1)
return ERROR_COMMAND_SYNTAX_ERROR;
COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], dev_id);
struct pld_device *device = get_pld_device_by_num(dev_id);
struct pld_device *device = get_pld_device_by_name_or_numstr(CMD_ARGV[0]);
if (!device) {
command_print(CMD, "pld device '#%s' is out of bounds", CMD_ARGV[0]);
command_print(CMD, "pld device '#%s' is out of bounds or unknown", CMD_ARGV[0]);
return ERROR_FAIL;
}
@ -487,25 +511,25 @@ static const struct command_registration lattice_exec_command_handlers[] = {
.mode = COMMAND_EXEC,
.handler = lattice_read_status_command_handler,
.help = "reading status register from FPGA",
.usage = "num_pld",
.usage = "pld_name",
}, {
.name = "read_user",
.mode = COMMAND_EXEC,
.handler = lattice_read_usercode_register_command_handler,
.help = "reading usercode register from FPGA",
.usage = "num_pld",
.usage = "pld_name",
}, {
.name = "write_user",
.mode = COMMAND_EXEC,
.handler = lattice_write_usercode_register_command_handler,
.help = "writing usercode register to FPGA",
.usage = "num_pld value",
.usage = "pld_name value",
}, {
.name = "set_preload",
.mode = COMMAND_EXEC,
.mode = COMMAND_ANY,
.handler = lattice_set_preload_command_handler,
.help = "set length for preload (device specific)",
.usage = "num_pld value",
.usage = "pld_name value",
},
COMMAND_REGISTRATION_DONE
};
@ -524,6 +548,7 @@ static const struct command_registration lattice_command_handler[] = {
struct pld_driver lattice_pld = {
.name = "lattice",
.commands = lattice_command_handler,
.pld_device_command = &lattice_pld_device_command,
.pld_create_command = &lattice_pld_create_command,
.load = &lattice_load_command,
.get_ipdbg_hub = lattice_get_ipdbg_hub,
};

View File

@ -34,68 +34,110 @@ struct pld_device *get_pld_device_by_num(int num)
int i = 0;
for (p = pld_devices; p; p = p->next) {
if (i++ == num)
if (i++ == num) {
LOG_WARNING("DEPRECATED: use pld name \"%s\" instead of number %d", p->name, num);
return p;
}
}
return NULL;
}
struct pld_device *get_pld_device_by_name(const char *name)
{
for (struct pld_device *p = pld_devices; p; p = p->next) {
if (strcmp(p->name, name) == 0)
return p;
}
return NULL;
}
/* pld device <driver> [driver_options ...]
*/
COMMAND_HANDLER(handle_pld_device_command)
struct pld_device *get_pld_device_by_name_or_numstr(const char *str)
{
int i;
int found = 0;
struct pld_device *dev = get_pld_device_by_name(str);
if (dev)
return dev;
if (CMD_ARGC < 1)
char *end;
unsigned long dev_num = strtoul(str, &end, 0);
if (*end || dev_num > INT_MAX) {
LOG_ERROR("Invalid argument");
return NULL;
}
return get_pld_device_by_num(dev_num);
}
/* @deffn {Config Command} {pld create} pld_name driver -chain-position tap_name [options]
*/
COMMAND_HANDLER(handle_pld_create_command)
{
if (CMD_ARGC < 2)
return ERROR_COMMAND_SYNTAX_ERROR;
for (i = 0; pld_drivers[i]; i++) {
if (strcmp(CMD_ARGV[0], pld_drivers[i]->name) == 0) {
struct pld_device *p, *c;
struct pld_driver *pld_driver = NULL;
/* register pld specific commands */
int retval;
if (pld_drivers[i]->commands) {
retval = register_commands(CMD_CTX, NULL, pld_drivers[i]->commands);
if (retval != ERROR_OK) {
LOG_ERROR("couldn't register '%s' commands", CMD_ARGV[0]);
return ERROR_FAIL;
}
}
c = malloc(sizeof(struct pld_device));
c->driver = pld_drivers[i];
c->next = NULL;
retval = CALL_COMMAND_HANDLER(
pld_drivers[i]->pld_device_command, c);
if (retval != ERROR_OK) {
LOG_ERROR("'%s' driver rejected pld device",
CMD_ARGV[0]);
free(c);
return ERROR_OK;
}
/* put pld device in linked list */
if (pld_devices) {
/* find last pld device */
for (p = pld_devices; p && p->next; p = p->next)
;
if (p)
p->next = c;
} else
pld_devices = c;
found = 1;
for (int i = 0; pld_drivers[i]; i++) {
if (strcmp(CMD_ARGV[1], pld_drivers[i]->name) == 0) {
pld_driver = pld_drivers[i];
break;
}
}
/* no matching pld driver found */
if (!found) {
LOG_ERROR("pld driver '%s' not found", CMD_ARGV[0]);
exit(-1);
if (!pld_driver) {
LOG_ERROR("pld driver '%s' not found", CMD_ARGV[1]);
return ERROR_FAIL; /* exit(-1); */
}
if (get_pld_device_by_name(CMD_ARGV[0])) {
LOG_ERROR("pld device with name '%s' already exists", CMD_ARGV[0]);
return ERROR_FAIL;
}
struct pld_device *pld_device = malloc(sizeof(struct pld_device));
if (!pld_device) {
LOG_ERROR("Out of memory");
return ERROR_FAIL;
}
pld_device->driver = pld_driver;
pld_device->next = NULL;
int retval = CALL_COMMAND_HANDLER(pld_driver->pld_create_command, pld_device);
if (retval != ERROR_OK) {
LOG_ERROR("'%s' driver rejected pld device",
CMD_ARGV[1]);
free(pld_device);
return ERROR_OK;
}
pld_device->name = strdup(CMD_ARGV[0]);
if (!pld_device->name) {
LOG_ERROR("Out of memory");
free(pld_device);
return ERROR_FAIL;
}
/* register pld specific commands */
if (pld_driver->commands) {
retval = register_commands(CMD_CTX, NULL, pld_driver->commands);
if (retval != ERROR_OK) {
LOG_ERROR("couldn't register '%s' commands", CMD_ARGV[1]);
free(pld_device->name);
free(pld_device);
return ERROR_FAIL;
}
}
if (pld_devices) {
/* find last pld device */
struct pld_device *p = pld_devices;
for (; p && p->next; p = p->next)
;
if (p)
p->next = pld_device;
} else {
pld_devices = pld_device;
}
return ERROR_OK;
@ -112,7 +154,7 @@ COMMAND_HANDLER(handle_pld_devices_command)
}
for (p = pld_devices; p; p = p->next)
command_print(CMD, "#%i: %s", i++, p->driver->name);
command_print(CMD, "#%i: %s (driver: %s)", i++, p->name, p->driver->name);
return ERROR_OK;
}
@ -128,11 +170,9 @@ COMMAND_HANDLER(handle_pld_load_command)
if (CMD_ARGC < 2)
return ERROR_COMMAND_SYNTAX_ERROR;
unsigned dev_id;
COMMAND_PARSE_NUMBER(uint, CMD_ARGV[0], dev_id);
p = get_pld_device_by_num(dev_id);
p = get_pld_device_by_name_or_numstr(CMD_ARGV[0]);
if (!p) {
command_print(CMD, "pld device '#%s' is out of bounds", CMD_ARGV[0]);
command_print(CMD, "pld device '#%s' is out of bounds or unknown", CMD_ARGV[0]);
return ERROR_OK;
}
@ -154,15 +194,15 @@ COMMAND_HANDLER(handle_pld_load_command)
retval = p->driver->load(p, CMD_ARGV[1]);
if (retval != ERROR_OK) {
command_print(CMD, "failed loading file %s to pld device %u",
CMD_ARGV[1], dev_id);
command_print(CMD, "failed loading file %s to pld device %s",
CMD_ARGV[1], CMD_ARGV[0]);
return retval;
} else {
gettimeofday(&end, NULL);
timeval_subtract(&duration, &end, &start);
command_print(CMD, "loaded file %s to pld device %u in %jis %jius",
CMD_ARGV[1], dev_id,
command_print(CMD, "loaded file %s to pld device %s in %jis %jius",
CMD_ARGV[1], CMD_ARGV[0],
(intmax_t)duration.tv_sec, (intmax_t)duration.tv_usec);
}
@ -182,7 +222,7 @@ static const struct command_registration pld_exec_command_handlers[] = {
.handler = handle_pld_load_command,
.mode = COMMAND_EXEC,
.help = "load configuration file into PLD",
.usage = "pld_num filename",
.usage = "pld_name filename",
},
COMMAND_REGISTRATION_DONE
};
@ -213,11 +253,11 @@ COMMAND_HANDLER(handle_pld_init_command)
static const struct command_registration pld_config_command_handlers[] = {
{
.name = "device",
.name = "create",
.mode = COMMAND_CONFIG,
.handler = handle_pld_device_command,
.help = "configure a PLD device",
.usage = "driver_name [driver_args ... ]",
.handler = handle_pld_create_command,
.help = "create a PLD device",
.usage = "name.pld driver_name [driver_args ... ]",
},
{
.name = "init",

View File

@ -12,28 +12,37 @@
struct pld_device;
#define __PLD_DEVICE_COMMAND(name) \
#define __PLD_CREATE_COMMAND(name) \
COMMAND_HELPER(name, struct pld_device *pld)
struct pld_ipdbg_hub {
struct jtag_tap *tap;
unsigned int user_ir_code;
};
struct pld_driver {
const char *name;
__PLD_DEVICE_COMMAND((*pld_device_command));
__PLD_CREATE_COMMAND((*pld_create_command));
const struct command_registration *commands;
int (*load)(struct pld_device *pld_device, const char *filename);
int (*get_ipdbg_hub)(int user_num, struct pld_device *pld_device, struct pld_ipdbg_hub *hub);
};
#define PLD_DEVICE_COMMAND_HANDLER(name) \
static __PLD_DEVICE_COMMAND(name)
#define PLD_CREATE_COMMAND_HANDLER(name) \
static __PLD_CREATE_COMMAND(name)
struct pld_device {
struct pld_driver *driver;
void *driver_priv;
struct pld_device *next;
char *name;
};
int pld_register_commands(struct command_context *cmd_ctx);
struct pld_device *get_pld_device_by_num(int num);
struct pld_device *get_pld_device_by_name(const char *name);
struct pld_device *get_pld_device_by_name_or_numstr(const char *str);
#define ERROR_PLD_DEVICE_INVALID (-1000)
#define ERROR_PLD_FILE_LOAD_FAILED (-1001)

View File

@ -13,12 +13,23 @@
#include "xilinx_bit.h"
#include "pld.h"
static int virtex2_set_instr(struct jtag_tap *tap, uint32_t new_instr)
static const struct virtex2_command_set virtex2_default_commands = {
.cfg_out = 0x04,
.cfg_in = 0x05,
.jprog_b = 0x0b,
.jstart = 0x0c,
.jshutdown = 0x0d,
.bypass = 0x3f,
.user = {0x02, 0x03},
.num_user = 2, /* virtex II has only 2 user instructions */
};
static int virtex2_set_instr(struct jtag_tap *tap, uint64_t new_instr)
{
if (!tap)
return ERROR_FAIL;
if (buf_get_u32(tap->cur_instr, 0, tap->ir_length) != new_instr) {
if (buf_get_u64(tap->cur_instr, 0, tap->ir_length) != new_instr) {
struct scan_field field;
field.num_bits = tap->ir_length;
@ -28,7 +39,7 @@ static int virtex2_set_instr(struct jtag_tap *tap, uint32_t new_instr)
return ERROR_FAIL;
}
field.out_value = t;
buf_set_u32(t, 0, field.num_bits, new_instr);
buf_set_u64(t, 0, field.num_bits, new_instr);
field.in_value = NULL;
jtag_add_ir_scan(tap, &field, TAP_IDLE);
@ -60,7 +71,7 @@ static int virtex2_send_32(struct pld_device *pld_device,
for (i = 0; i < num_words; i++)
buf_set_u32(values + 4 * i, 0, 32, flip_u32(*words++, 32));
int retval = virtex2_set_instr(virtex2_info->tap, 0x5); /* CFG_IN */
int retval = virtex2_set_instr(virtex2_info->tap, virtex2_info->command_set.cfg_in);
if (retval != ERROR_OK) {
free(values);
return retval;
@ -89,7 +100,7 @@ static int virtex2_receive_32(struct pld_device *pld_device,
scan_field.out_value = NULL;
scan_field.in_value = NULL;
int retval = virtex2_set_instr(virtex2_info->tap, 0x4); /* CFG_OUT */
int retval = virtex2_set_instr(virtex2_info->tap, virtex2_info->command_set.cfg_out);
if (retval != ERROR_OK)
return retval;
@ -132,12 +143,41 @@ static int virtex2_read_stat(struct pld_device *pld_device, uint32_t *status)
return retval;
}
static int virtex2_program(struct pld_device *pld_device)
{
struct virtex2_pld_device *virtex2_info = pld_device->driver_priv;
if (!virtex2_info)
return ERROR_FAIL;
int retval = virtex2_set_instr(virtex2_info->tap, virtex2_info->command_set.jshutdown);
if (retval != ERROR_OK)
return retval;
retval = virtex2_set_instr(virtex2_info->tap, virtex2_info->command_set.jprog_b);
if (retval != ERROR_OK)
return retval;
jtag_add_runtest(62000, TAP_IDLE);
if (!(virtex2_info->no_jstart)) {
retval = virtex2_set_instr(virtex2_info->tap, virtex2_info->command_set.jstart);
if (retval != ERROR_OK)
return retval;
}
retval = virtex2_set_instr(virtex2_info->tap, virtex2_info->command_set.bypass);
if (retval != ERROR_OK)
return retval;
jtag_add_runtest(2000, TAP_IDLE);
return jtag_execute_queue();
}
static int virtex2_load_prepare(struct pld_device *pld_device)
{
struct virtex2_pld_device *virtex2_info = pld_device->driver_priv;
int retval;
retval = virtex2_set_instr(virtex2_info->tap, 0xb); /* JPROG_B */
retval = virtex2_set_instr(virtex2_info->tap, virtex2_info->command_set.jprog_b);
if (retval != ERROR_OK)
return retval;
@ -146,7 +186,7 @@ static int virtex2_load_prepare(struct pld_device *pld_device)
return retval;
jtag_add_sleep(1000);
retval = virtex2_set_instr(virtex2_info->tap, 0x5); /* CFG_IN */
retval = virtex2_set_instr(virtex2_info->tap, virtex2_info->command_set.cfg_in);
if (retval != ERROR_OK)
return retval;
@ -161,24 +201,24 @@ static int virtex2_load_cleanup(struct pld_device *pld_device)
jtag_add_tlr();
if (!(virtex2_info->no_jstart)) {
retval = virtex2_set_instr(virtex2_info->tap, 0xc); /* JSTART */
retval = virtex2_set_instr(virtex2_info->tap, virtex2_info->command_set.jstart);
if (retval != ERROR_OK)
return retval;
}
jtag_add_runtest(13, TAP_IDLE);
retval = virtex2_set_instr(virtex2_info->tap, 0x3f); /* BYPASS */
retval = virtex2_set_instr(virtex2_info->tap, virtex2_info->command_set.bypass);
if (retval != ERROR_OK)
return retval;
retval = virtex2_set_instr(virtex2_info->tap, 0x3f); /* BYPASS */
retval = virtex2_set_instr(virtex2_info->tap, virtex2_info->command_set.bypass);
if (retval != ERROR_OK)
return retval;
if (!(virtex2_info->no_jstart)) {
retval = virtex2_set_instr(virtex2_info->tap, 0xc); /* JSTART */
retval = virtex2_set_instr(virtex2_info->tap, virtex2_info->command_set.jstart);
if (retval != ERROR_OK)
return retval;
}
jtag_add_runtest(13, TAP_IDLE);
retval = virtex2_set_instr(virtex2_info->tap, 0x3f); /* BYPASS */
retval = virtex2_set_instr(virtex2_info->tap, virtex2_info->command_set.bypass);
if (retval != ERROR_OK)
return retval;
@ -225,6 +265,22 @@ static int virtex2_load(struct pld_device *pld_device, const char *filename)
return retval;
}
COMMAND_HANDLER(virtex2_handle_program_command)
{
struct pld_device *device;
if (CMD_ARGC != 1)
return ERROR_COMMAND_SYNTAX_ERROR;
device = get_pld_device_by_name_or_numstr(CMD_ARGV[0]);
if (!device) {
command_print(CMD, "pld device '#%s' is out of bounds or unknown", CMD_ARGV[0]);
return ERROR_FAIL;
}
return virtex2_program(device);
}
COMMAND_HANDLER(virtex2_handle_read_stat_command)
{
struct pld_device *device;
@ -233,11 +289,9 @@ COMMAND_HANDLER(virtex2_handle_read_stat_command)
if (CMD_ARGC < 1)
return ERROR_COMMAND_SYNTAX_ERROR;
unsigned dev_id;
COMMAND_PARSE_NUMBER(uint, CMD_ARGV[0], dev_id);
device = get_pld_device_by_num(dev_id);
device = get_pld_device_by_name_or_numstr(CMD_ARGV[0]);
if (!device) {
command_print(CMD, "pld device '#%s' is out of bounds", CMD_ARGV[0]);
command_print(CMD, "pld device '#%s' is out of bounds or unknown", CMD_ARGV[0]);
return ERROR_FAIL;
}
@ -252,31 +306,107 @@ COMMAND_HANDLER(virtex2_handle_read_stat_command)
return ERROR_OK;
}
PLD_DEVICE_COMMAND_HANDLER(virtex2_pld_device_command)
static int xilinx_get_ipdbg_hub(int user_num, struct pld_device *pld_device, struct pld_ipdbg_hub *hub)
{
struct jtag_tap *tap;
if (!pld_device)
return ERROR_FAIL;
struct virtex2_pld_device *virtex2_info;
struct virtex2_pld_device *pld_device_info = pld_device->driver_priv;
if (CMD_ARGC < 2)
return ERROR_COMMAND_SYNTAX_ERROR;
if (!pld_device_info || !pld_device_info->tap)
return ERROR_FAIL;
tap = jtag_tap_by_string(CMD_ARGV[1]);
if (!tap) {
command_print(CMD, "Tap: %s does not exist", CMD_ARGV[1]);
hub->tap = pld_device_info->tap;
if (user_num < 1 || (unsigned int)user_num > pld_device_info->command_set.num_user) {
LOG_ERROR("device has only user register 1 to %d", pld_device_info->command_set.num_user);
return ERROR_FAIL;
}
virtex2_info = malloc(sizeof(struct virtex2_pld_device));
hub->user_ir_code = pld_device_info->command_set.user[user_num - 1];
return ERROR_OK;
}
COMMAND_HANDLER(virtex2_handle_set_instuction_codes_command)
{
if (CMD_ARGC < 6 || CMD_ARGC > (6 + VIRTEX2_MAX_USER_INSTRUCTIONS))
return ERROR_COMMAND_SYNTAX_ERROR;
struct pld_device *device = get_pld_device_by_name(CMD_ARGV[0]);
if (!device) {
command_print(CMD, "pld device '#%s' is unknown", CMD_ARGV[0]);
return ERROR_FAIL;
}
struct virtex2_pld_device *virtex2_info = device->driver_priv;
if (!virtex2_info)
return ERROR_FAIL;
struct virtex2_command_set instr_codes;
COMMAND_PARSE_NUMBER(u64, CMD_ARGV[1], instr_codes.cfg_out);
COMMAND_PARSE_NUMBER(u64, CMD_ARGV[2], instr_codes.cfg_in);
COMMAND_PARSE_NUMBER(u64, CMD_ARGV[3], instr_codes.jprog_b);
COMMAND_PARSE_NUMBER(u64, CMD_ARGV[4], instr_codes.jstart);
COMMAND_PARSE_NUMBER(u64, CMD_ARGV[5], instr_codes.jshutdown);
instr_codes.bypass = 0xffffffffffffffffULL;
unsigned int num_user = CMD_ARGC - 6;
for (unsigned int i = 0; i < num_user; ++i)
COMMAND_PARSE_NUMBER(u64, CMD_ARGV[6 + i], instr_codes.user[i]);
instr_codes.num_user = num_user;
virtex2_info->command_set = instr_codes;
return ERROR_OK;
}
COMMAND_HANDLER(virtex2_handle_set_user_codes_command)
{
if (CMD_ARGC < 2 || CMD_ARGC > (1 + VIRTEX2_MAX_USER_INSTRUCTIONS))
return ERROR_COMMAND_SYNTAX_ERROR;
struct pld_device *device = get_pld_device_by_name(CMD_ARGV[0]);
if (!device) {
command_print(CMD, "pld device '#%s' is unknown", CMD_ARGV[0]);
return ERROR_FAIL;
}
struct virtex2_pld_device *virtex2_info = device->driver_priv;
if (!virtex2_info)
return ERROR_FAIL;
uint64_t user[VIRTEX2_MAX_USER_INSTRUCTIONS];
unsigned int num_user = CMD_ARGC - 1;
for (unsigned int i = 0; i < num_user; ++i)
COMMAND_PARSE_NUMBER(u64, CMD_ARGV[1 + i], user[i]);
virtex2_info->command_set.num_user = num_user;
memcpy(virtex2_info->command_set.user, user, num_user * sizeof(uint64_t));
return ERROR_OK;
}
PLD_CREATE_COMMAND_HANDLER(virtex2_pld_create_command)
{
if (CMD_ARGC < 4)
return ERROR_COMMAND_SYNTAX_ERROR;
if (strcmp(CMD_ARGV[2], "-chain-position") != 0)
return ERROR_COMMAND_SYNTAX_ERROR;
struct jtag_tap *tap = jtag_tap_by_string(CMD_ARGV[3]);
if (!tap) {
command_print(CMD, "Tap: %s does not exist", CMD_ARGV[3]);
return ERROR_FAIL;
}
struct virtex2_pld_device *virtex2_info = malloc(sizeof(struct virtex2_pld_device));
if (!virtex2_info) {
LOG_ERROR("Out of memory");
return ERROR_FAIL;
}
virtex2_info->tap = tap;
virtex2_info->command_set = virtex2_default_commands;
virtex2_info->no_jstart = 0;
if (CMD_ARGC >= 3)
COMMAND_PARSE_NUMBER(int, CMD_ARGV[2], virtex2_info->no_jstart);
if (CMD_ARGC >= 5 && strcmp(CMD_ARGV[4], "-no_jstart") == 0)
virtex2_info->no_jstart = 1;
pld->driver_priv = virtex2_info;
@ -289,10 +419,30 @@ static const struct command_registration virtex2_exec_command_handlers[] = {
.mode = COMMAND_EXEC,
.handler = virtex2_handle_read_stat_command,
.help = "read status register",
.usage = "pld_num",
.usage = "pld_name",
}, {
.name = "set_instr_codes",
.mode = COMMAND_ANY,
.handler = virtex2_handle_set_instuction_codes_command,
.help = "set instructions codes used for loading the bitstream/refreshing/jtag-hub",
.usage = "pld_name cfg_out cfg_in jprogb jstart jshutdown"
" [user1 [user2 [user3 [user4]]]]",
}, {
.name = "set_user_codes",
.mode = COMMAND_ANY,
.handler = virtex2_handle_set_user_codes_command,
.help = "set instructions codes used for jtag-hub",
.usage = "pld_name user1 [user2 [user3 [user4]]]",
}, {
.name = "program",
.mode = COMMAND_EXEC,
.handler = virtex2_handle_program_command,
.help = "start loading of configuration (refresh)",
.usage = "pld_name",
},
COMMAND_REGISTRATION_DONE
};
static const struct command_registration virtex2_command_handler[] = {
{
.name = "virtex2",
@ -307,6 +457,7 @@ static const struct command_registration virtex2_command_handler[] = {
struct pld_driver virtex2_pld = {
.name = "virtex2",
.commands = virtex2_command_handler,
.pld_device_command = &virtex2_pld_device_command,
.pld_create_command = &virtex2_pld_create_command,
.load = &virtex2_load,
.get_ipdbg_hub = xilinx_get_ipdbg_hub,
};

View File

@ -10,9 +10,23 @@
#include <jtag/jtag.h>
#define VIRTEX2_MAX_USER_INSTRUCTIONS 4
struct virtex2_command_set {
uint64_t cfg_out;
uint64_t cfg_in;
uint64_t jprog_b;
uint64_t jstart;
uint64_t jshutdown;
uint64_t bypass;
uint64_t user[VIRTEX2_MAX_USER_INSTRUCTIONS];
unsigned int num_user;
};
struct virtex2_pld_device {
struct jtag_tap *tap;
int no_jstart;
struct virtex2_command_set command_set;
};
#endif /* OPENOCD_PLD_VIRTEX2_H */

View File

@ -1836,7 +1836,7 @@ static int gdb_breakpoint_watchpoint_packet(struct connection *connection,
case 4:
{
if (packet[0] == 'Z') {
retval = watchpoint_add(target, address, size, wp_type, 0, 0xffffffffu);
retval = watchpoint_add(target, address, size, wp_type, 0, WATCHPOINT_IGNORE_DATA_VALUE_MASK);
if (retval == ERROR_NOT_IMPLEMENTED) {
/* Send empty reply to report that watchpoints of this type are not supported */
gdb_put_packet(connection, "", 0);

View File

@ -10,11 +10,12 @@
#include <jtag/jtag.h>
#include <server/server.h>
#include <target/target.h>
#include <pld/pld.h>
#include "ipdbg.h"
#define IPDBG_BUFFER_SIZE 16384
#define IPDBG_MIN_NUM_OF_OPTIONS 4
#define IPDBG_MIN_NUM_OF_OPTIONS 2
#define IPDBG_MAX_NUM_OF_OPTIONS 14
#define IPDBG_MIN_DR_LENGTH 11
#define IPDBG_MAX_DR_LENGTH 13
@ -631,10 +632,8 @@ static int ipdbg_start(uint16_t port, struct jtag_tap *tap, uint32_t user_instru
}
} else {
int retval = ipdbg_create_hub(tap, user_instruction, data_register_length, virtual_ir, &hub);
if (retval != ERROR_OK) {
free(virtual_ir);
if (retval != ERROR_OK)
return retval;
}
}
struct ipdbg_service *service = NULL;
@ -716,6 +715,7 @@ COMMAND_HANDLER(handle_ipdbg_command)
uint32_t virtual_ir_length = 5;
uint32_t virtual_ir_value = 0x11;
struct ipdbg_virtual_ir_info *virtual_ir = NULL;
int user_num = 1;
if ((CMD_ARGC < IPDBG_MIN_NUM_OF_OPTIONS) || (CMD_ARGC > IPDBG_MAX_NUM_OF_OPTIONS))
return ERROR_COMMAND_SYNTAX_ERROR;
@ -742,6 +742,34 @@ COMMAND_HANDLER(handle_ipdbg_command)
IPDBG_MIN_DR_LENGTH, IPDBG_MAX_DR_LENGTH);
return ERROR_FAIL;
}
} else if (strcmp(CMD_ARGV[i], "-pld") == 0) {
++i;
if (i >= CMD_ARGC || CMD_ARGV[i][0] == '-')
return ERROR_COMMAND_SYNTAX_ERROR;
struct pld_device *device = get_pld_device_by_name_or_numstr(CMD_ARGV[i]);
if (!device || !device->driver) {
command_print(CMD, "pld device '#%s' is out of bounds or unknown", CMD_ARGV[i]);
return ERROR_FAIL;
}
COMMAND_PARSE_OPTIONAL_NUMBER(int, i, user_num);
struct pld_ipdbg_hub pld_hub;
struct pld_driver *driver = device->driver;
if (!driver->get_ipdbg_hub) {
command_print(CMD, "pld driver has no ipdbg support");
return ERROR_FAIL;
}
if (driver->get_ipdbg_hub(user_num, device, &pld_hub) != ERROR_OK) {
command_print(CMD, "unable to retrieve hub from pld driver");
return ERROR_FAIL;
}
if (!pld_hub.tap) {
command_print(CMD, "no tap received from pld driver");
return ERROR_FAIL;
}
hub_configured = true;
user_instruction = pld_hub.user_ir_code;
tap = pld_hub.tap;
} else if (strcmp(CMD_ARGV[i], "-vir") == 0) {
COMMAND_PARSE_OPTIONAL_NUMBER(u32, i, virtual_ir_value);
COMMAND_PARSE_OPTIONAL_NUMBER(u32, i, virtual_ir_length);

View File

@ -846,8 +846,10 @@ static int aarch64_resume(struct target *target, int current,
struct armv8_common *armv8 = target_to_armv8(target);
armv8->last_run_control_op = ARMV8_RUNCONTROL_RESUME;
if (target->state != TARGET_HALTED)
if (target->state != TARGET_HALTED) {
LOG_TARGET_ERROR(target, "not halted");
return ERROR_TARGET_NOT_HALTED;
}
/*
* If this target is part of a SMP group, prepare the others
@ -1089,13 +1091,14 @@ static int aarch64_step(struct target *target, int current, target_addr_t addres
struct armv8_common *armv8 = target_to_armv8(target);
struct aarch64_common *aarch64 = target_to_aarch64(target);
int saved_retval = ERROR_OK;
int poll_retval;
int retval;
uint32_t edecr;
armv8->last_run_control_op = ARMV8_RUNCONTROL_STEP;
if (target->state != TARGET_HALTED) {
LOG_WARNING("target not halted");
LOG_TARGET_ERROR(target, "not halted");
return ERROR_TARGET_NOT_HALTED;
}
@ -1171,6 +1174,8 @@ static int aarch64_step(struct target *target, int current, target_addr_t addres
if (retval == ERROR_TARGET_TIMEOUT)
saved_retval = aarch64_halt_one(target, HALT_SYNC);
poll_retval = aarch64_poll(target);
/* restore EDECR */
retval = mem_ap_write_atomic_u32(armv8->debug_ap,
armv8->debug_base + CPUV8_DBG_EDECR, edecr);
@ -1187,6 +1192,9 @@ static int aarch64_step(struct target *target, int current, target_addr_t addres
if (saved_retval != ERROR_OK)
return saved_retval;
if (poll_retval != ERROR_OK)
return poll_retval;
return ERROR_OK;
}
@ -2135,7 +2143,7 @@ static int aarch64_write_cpu_memory(struct target *target,
uint32_t dscr;
if (target->state != TARGET_HALTED) {
LOG_WARNING("target not halted");
LOG_TARGET_ERROR(target, "not halted");
return ERROR_TARGET_NOT_HALTED;
}
@ -2353,7 +2361,7 @@ static int aarch64_read_cpu_memory(struct target *target,
address, size, count);
if (target->state != TARGET_HALTED) {
LOG_WARNING("target not halted");
LOG_TARGET_ERROR(target, "not halted");
return ERROR_TARGET_NOT_HALTED;
}
@ -2693,6 +2701,9 @@ static int aarch64_examine(struct target *target)
if (retval == ERROR_OK)
retval = aarch64_init_debug_access(target);
if (retval == ERROR_OK)
retval = aarch64_poll(target);
return retval;
}
@ -2790,8 +2801,8 @@ static int aarch64_mmu(struct target *target, int *enabled)
struct aarch64_common *aarch64 = target_to_aarch64(target);
struct armv8_common *armv8 = &aarch64->armv8_common;
if (target->state != TARGET_HALTED) {
LOG_ERROR("%s: target %s not halted", __func__, target_name(target));
return ERROR_TARGET_INVALID;
LOG_TARGET_ERROR(target, "not halted");
return ERROR_TARGET_NOT_HALTED;
}
if (armv8->is_armv8r)
*enabled = 0;
@ -3010,8 +3021,10 @@ COMMAND_HANDLER(aarch64_mcrmrc_command)
return ERROR_FAIL;
}
if (target->state != TARGET_HALTED)
if (target->state != TARGET_HALTED) {
command_print(CMD, "Error: [%s] not halted", target_name(target));
return ERROR_TARGET_NOT_HALTED;
}
if (arm->core_state == ARM_STATE_AARCH64) {
command_print(CMD, "%s: not 32-bit arm target", target_name(target));

View File

@ -846,21 +846,17 @@ static int arc_save_context(struct target *target)
memset(aux_addrs, 0xff, aux_regs_size);
for (i = 0; i < MIN(arc->num_core_regs, regs_to_scan); i++) {
struct reg *reg = &(reg_list[i]);
struct reg *reg = reg_list + i;
struct arc_reg_desc *arc_reg = reg->arch_info;
if (!reg->valid && reg->exist) {
core_addrs[core_cnt] = arc_reg->arch_num;
core_cnt += 1;
}
if (!reg->valid && reg->exist)
core_addrs[core_cnt++] = arc_reg->arch_num;
}
for (i = arc->num_core_regs; i < regs_to_scan; i++) {
struct reg *reg = &(reg_list[i]);
struct reg *reg = reg_list + i;
struct arc_reg_desc *arc_reg = reg->arch_info;
if (!reg->valid && reg->exist) {
aux_addrs[aux_cnt] = arc_reg->arch_num;
aux_cnt += 1;
}
if (!reg->valid && reg->exist)
aux_addrs[aux_cnt++] = arc_reg->arch_num;
}
/* Read data from target. */
@ -884,30 +880,30 @@ static int arc_save_context(struct target *target)
/* Parse core regs */
core_cnt = 0;
for (i = 0; i < MIN(arc->num_core_regs, regs_to_scan); i++) {
struct reg *reg = &(reg_list[i]);
struct reg *reg = reg_list + i;
struct arc_reg_desc *arc_reg = reg->arch_info;
if (!reg->valid && reg->exist) {
target_buffer_set_u32(target, reg->value, core_values[core_cnt]);
core_cnt += 1;
reg->valid = true;
reg->dirty = false;
LOG_DEBUG("Get core register regnum=%u, name=%s, value=0x%08" PRIx32,
i, arc_reg->name, core_values[core_cnt]);
core_cnt++;
}
}
/* Parse aux regs */
aux_cnt = 0;
for (i = arc->num_core_regs; i < regs_to_scan; i++) {
struct reg *reg = &(reg_list[i]);
struct reg *reg = reg_list + i;
struct arc_reg_desc *arc_reg = reg->arch_info;
if (!reg->valid && reg->exist) {
target_buffer_set_u32(target, reg->value, aux_values[aux_cnt]);
aux_cnt += 1;
reg->valid = true;
reg->dirty = false;
LOG_DEBUG("Get aux register regnum=%u, name=%s, value=0x%08" PRIx32,
i, arc_reg->name, aux_values[aux_cnt]);
aux_cnt++;
}
}
@ -1262,7 +1258,7 @@ static int arc_resume(struct target *target, int current, target_addr_t address,
CHECK_RETVAL(arc_reset_caches_states(target));
if (target->state != TARGET_HALTED) {
LOG_WARNING("target not halted");
LOG_TARGET_ERROR(target, "not halted");
return ERROR_TARGET_NOT_HALTED;
}
@ -1675,7 +1671,7 @@ static int arc_add_breakpoint(struct target *target, struct breakpoint *breakpoi
return arc_set_breakpoint(target, breakpoint);
} else {
LOG_WARNING(" > core was not halted, please try again.");
LOG_TARGET_ERROR(target, "not halted (add breakpoint)");
return ERROR_TARGET_NOT_HALTED;
}
}
@ -1687,7 +1683,7 @@ static int arc_remove_breakpoint(struct target *target,
if (breakpoint->is_set)
CHECK_RETVAL(arc_unset_breakpoint(target, breakpoint));
} else {
LOG_WARNING("target not halted");
LOG_TARGET_ERROR(target, "not halted (remove breakpoint)");
return ERROR_TARGET_NOT_HALTED;
}
@ -1909,7 +1905,7 @@ static int arc_add_watchpoint(struct target *target,
struct watchpoint *watchpoint)
{
if (target->state != TARGET_HALTED) {
LOG_WARNING("target not halted");
LOG_TARGET_ERROR(target, "not halted");
return ERROR_TARGET_NOT_HALTED;
}
@ -1922,7 +1918,7 @@ static int arc_remove_watchpoint(struct target *target,
struct watchpoint *watchpoint)
{
if (target->state != TARGET_HALTED) {
LOG_WARNING("target not halted");
LOG_TARGET_ERROR(target, "not halted");
return ERROR_TARGET_NOT_HALTED;
}
@ -2010,7 +2006,7 @@ static int arc_step(struct target *target, int current, target_addr_t address,
struct reg *pc = &(arc->core_and_aux_cache->reg_list[arc->pc_index_in_cache]);
if (target->state != TARGET_HALTED) {
LOG_WARNING("target not halted");
LOG_TARGET_ERROR(target, "not halted");
return ERROR_TARGET_NOT_HALTED;
}

View File

@ -162,7 +162,7 @@ int arc_mem_write(struct target *target, target_addr_t address, uint32_t size,
address, size, count);
if (target->state != TARGET_HALTED) {
LOG_WARNING("target not halted");
LOG_TARGET_ERROR(target, "not halted");
return ERROR_TARGET_NOT_HALTED;
}

View File

@ -58,6 +58,11 @@ enum arm_arch {
ARM_ARCH_V8M,
};
/** Known ARM implementor IDs */
enum arm_implementor {
ARM_IMPLEMENTOR_ARM = 0x41,
};
/**
* Represent state of an ARM core.
*

View File

@ -449,7 +449,7 @@ static int arm11_resume(struct target *target, int current,
if (target->state != TARGET_HALTED) {
LOG_ERROR("Target not halted");
LOG_TARGET_ERROR(target, "not halted");
return ERROR_TARGET_NOT_HALTED;
}
@ -551,7 +551,7 @@ static int arm11_step(struct target *target, int current,
target_state_name(target));
if (target->state != TARGET_HALTED) {
LOG_WARNING("target was not halted");
LOG_TARGET_ERROR(target, "not halted");
return ERROR_TARGET_NOT_HALTED;
}
@ -798,7 +798,7 @@ static int arm11_read_memory_inner(struct target *target,
int retval;
if (target->state != TARGET_HALTED) {
LOG_WARNING("target was not halted");
LOG_TARGET_ERROR(target, "not halted");
return ERROR_TARGET_NOT_HALTED;
}
@ -896,7 +896,7 @@ static int arm11_write_memory_inner(struct target *target,
int retval;
if (target->state != TARGET_HALTED) {
LOG_WARNING("target was not halted");
LOG_TARGET_ERROR(target, "not halted");
return ERROR_TARGET_NOT_HALTED;
}

View File

@ -241,8 +241,8 @@ static int arm720t_arch_state(struct target *target)
static int arm720_mmu(struct target *target, int *enabled)
{
if (target->state != TARGET_HALTED) {
LOG_ERROR("%s: target not halted", __func__);
return ERROR_TARGET_INVALID;
LOG_TARGET_ERROR(target, "not halted");
return ERROR_TARGET_NOT_HALTED;
}
*enabled = target_to_arm720(target)->armv4_5_mmu.mmu_enabled;

View File

@ -184,7 +184,7 @@ static int arm7_9_set_breakpoint(struct target *target, struct breakpoint *break
breakpoint->type);
if (target->state != TARGET_HALTED) {
LOG_WARNING("target not halted");
LOG_TARGET_ERROR(target, "not halted");
return ERROR_TARGET_NOT_HALTED;
}
@ -451,11 +451,12 @@ static int arm7_9_set_watchpoint(struct target *target, struct watchpoint *watch
struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
int rw_mask = 1;
uint32_t mask;
const uint32_t wp_data_mask = watchpoint->mask;
mask = watchpoint->length - 1;
if (target->state != TARGET_HALTED) {
LOG_WARNING("target not halted");
LOG_TARGET_ERROR(target, "not halted");
return ERROR_TARGET_NOT_HALTED;
}
@ -469,8 +470,8 @@ static int arm7_9_set_watchpoint(struct target *target, struct watchpoint *watch
watchpoint->address);
embeddedice_set_reg(&arm7_9->eice_cache->reg_list[EICE_W0_ADDR_MASK], mask);
embeddedice_set_reg(&arm7_9->eice_cache->reg_list[EICE_W0_DATA_MASK],
watchpoint->mask);
if (watchpoint->mask != 0xffffffffu)
wp_data_mask);
if (wp_data_mask != (uint32_t)WATCHPOINT_IGNORE_DATA_VALUE_MASK)
embeddedice_set_reg(&arm7_9->eice_cache->reg_list[EICE_W0_DATA_VALUE],
watchpoint->value);
embeddedice_set_reg(&arm7_9->eice_cache->reg_list[EICE_W0_CONTROL_MASK],
@ -488,8 +489,8 @@ static int arm7_9_set_watchpoint(struct target *target, struct watchpoint *watch
watchpoint->address);
embeddedice_set_reg(&arm7_9->eice_cache->reg_list[EICE_W1_ADDR_MASK], mask);
embeddedice_set_reg(&arm7_9->eice_cache->reg_list[EICE_W1_DATA_MASK],
watchpoint->mask);
if (watchpoint->mask != 0xffffffffu)
wp_data_mask);
if (wp_data_mask != (uint32_t)WATCHPOINT_IGNORE_DATA_VALUE_MASK)
embeddedice_set_reg(&arm7_9->eice_cache->reg_list[EICE_W1_DATA_VALUE],
watchpoint->value);
embeddedice_set_reg(&arm7_9->eice_cache->reg_list[EICE_W1_CONTROL_MASK],
@ -524,7 +525,7 @@ static int arm7_9_unset_watchpoint(struct target *target, struct watchpoint *wat
struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
if (target->state != TARGET_HALTED) {
LOG_WARNING("target not halted");
LOG_TARGET_ERROR(target, "not halted");
return ERROR_TARGET_NOT_HALTED;
}
@ -1259,7 +1260,7 @@ static int arm7_9_debug_entry(struct target *target)
return retval;
if (target->state != TARGET_HALTED) {
LOG_WARNING("target not halted");
LOG_TARGET_ERROR(target, "not halted");
return ERROR_TARGET_NOT_HALTED;
}
@ -1390,7 +1391,7 @@ static int arm7_9_full_context(struct target *target)
LOG_DEBUG("-");
if (target->state != TARGET_HALTED) {
LOG_WARNING("target not halted");
LOG_TARGET_ERROR(target, "not halted");
return ERROR_TARGET_NOT_HALTED;
}
@ -1506,7 +1507,7 @@ static int arm7_9_restore_context(struct target *target)
LOG_DEBUG("-");
if (target->state != TARGET_HALTED) {
LOG_WARNING("target not halted");
LOG_TARGET_ERROR(target, "not halted");
return ERROR_TARGET_NOT_HALTED;
}
@ -1709,7 +1710,7 @@ int arm7_9_resume(struct target *target,
LOG_DEBUG("-");
if (target->state != TARGET_HALTED) {
LOG_WARNING("target not halted");
LOG_TARGET_ERROR(target, "not halted");
return ERROR_TARGET_NOT_HALTED;
}
@ -1907,7 +1908,7 @@ int arm7_9_step(struct target *target, int current, target_addr_t address, int h
int err, retval;
if (target->state != TARGET_HALTED) {
LOG_WARNING("target not halted");
LOG_TARGET_ERROR(target, "not halted");
return ERROR_TARGET_NOT_HALTED;
}
@ -2118,7 +2119,7 @@ int arm7_9_read_memory(struct target *target,
address, size, count);
if (target->state != TARGET_HALTED) {
LOG_WARNING("target not halted");
LOG_TARGET_ERROR(target, "not halted");
return ERROR_TARGET_NOT_HALTED;
}
@ -2291,7 +2292,7 @@ int arm7_9_write_memory(struct target *target,
#endif
if (target->state != TARGET_HALTED) {
LOG_WARNING("target not halted");
LOG_TARGET_ERROR(target, "not halted");
return ERROR_TARGET_NOT_HALTED;
}

View File

@ -533,8 +533,8 @@ int arm920t_arch_state(struct target *target)
static int arm920_mmu(struct target *target, int *enabled)
{
if (target->state != TARGET_HALTED) {
LOG_ERROR("%s: target not halted", __func__);
return ERROR_TARGET_INVALID;
LOG_TARGET_ERROR(target, "not halted");
return ERROR_TARGET_NOT_HALTED;
}
*enabled = target_to_arm920(target)->armv4_5_mmu.mmu_enabled;
@ -1455,9 +1455,9 @@ COMMAND_HANDLER(arm920t_handle_cp15_command)
return retval;
if (target->state != TARGET_HALTED) {
command_print(CMD, "target must be stopped for "
command_print(CMD, "Error: target must be stopped for "
"\"%s\" command", CMD_NAME);
return ERROR_OK;
return ERROR_TARGET_NOT_HALTED;
}
/* one argument, read a register.

View File

@ -754,8 +754,8 @@ static int arm926ejs_mmu(struct target *target, int *enabled)
struct arm926ejs_common *arm926ejs = target_to_arm926(target);
if (target->state != TARGET_HALTED) {
LOG_ERROR("Target not halted");
return ERROR_TARGET_INVALID;
LOG_TARGET_ERROR(target, "not halted");
return ERROR_TARGET_NOT_HALTED;
}
*enabled = arm926ejs->armv4_5_mmu.mmu_enabled;
return ERROR_OK;

View File

@ -574,7 +574,7 @@ COMMAND_HANDLER(arm946e_handle_cp15)
return retval;
if (target->state != TARGET_HALTED) {
command_print(CMD, "target must be stopped for \"%s\" command", CMD_NAME);
command_print(CMD, "Error: target must be stopped for \"%s\" command", CMD_NAME);
return ERROR_TARGET_NOT_HALTED;
}
@ -624,7 +624,7 @@ COMMAND_HANDLER(arm946e_handle_idcache)
return retval;
if (target->state != TARGET_HALTED) {
command_print(CMD, "target must be stopped for \"%s\" command", CMD_NAME);
command_print(CMD, "Error: target must be stopped for \"%s\" command", CMD_NAME);
return ERROR_TARGET_NOT_HALTED;
}

View File

@ -174,8 +174,8 @@ COMMAND_HANDLER(arm966e_handle_cp15_command)
return retval;
if (target->state != TARGET_HALTED) {
command_print(CMD, "target must be stopped for \"%s\" command", CMD_NAME);
return ERROR_OK;
command_print(CMD, "Error: target must be stopped for \"%s\" command", CMD_NAME);
return ERROR_TARGET_NOT_HALTED;
}
/* one or more argument, access a single register (write if second argument is given */

View File

@ -918,7 +918,7 @@ static int dpm_watchpoint_setup(struct arm_dpm *dpm, unsigned index_t,
uint32_t control;
/* this hardware doesn't support data value matching or masking */
if (wp->value || wp->mask != ~(uint32_t)0) {
if (wp->mask != WATCHPOINT_IGNORE_DATA_VALUE_MASK) {
LOG_DEBUG("watchpoint values and masking not supported");
return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
}

View File

@ -578,7 +578,7 @@ static int armv4_5_get_core_reg(struct reg *reg)
struct target *target = reg_arch_info->target;
if (target->state != TARGET_HALTED) {
LOG_ERROR("Target not halted");
LOG_TARGET_ERROR(target, "not halted");
return ERROR_TARGET_NOT_HALTED;
}
@ -600,7 +600,7 @@ static int armv4_5_set_core_reg(struct reg *reg, uint8_t *buf)
uint32_t value = buf_get_u32(buf, 0, 32);
if (target->state != TARGET_HALTED) {
LOG_ERROR("Target not halted");
LOG_TARGET_ERROR(target, "not halted");
return ERROR_TARGET_NOT_HALTED;
}
@ -817,8 +817,8 @@ COMMAND_HANDLER(handle_armv4_5_reg_command)
}
if (target->state != TARGET_HALTED) {
command_print(CMD, "error: target must be halted for register accesses");
return ERROR_FAIL;
command_print(CMD, "Error: target must be halted for register accesses");
return ERROR_TARGET_NOT_HALTED;
}
if (arm->core_type != ARM_CORE_TYPE_STD) {
@ -833,7 +833,7 @@ COMMAND_HANDLER(handle_armv4_5_reg_command)
}
if (!arm->full_context) {
command_print(CMD, "error: target doesn't support %s",
command_print(CMD, "Error: target doesn't support %s",
CMD_NAME);
return ERROR_FAIL;
}
@ -1018,8 +1018,10 @@ COMMAND_HANDLER(handle_armv4_5_mcrmrc)
return ERROR_FAIL;
}
if (target->state != TARGET_HALTED)
if (target->state != TARGET_HALTED) {
command_print(CMD, "Error: [%s] not halted", target_name(target));
return ERROR_TARGET_NOT_HALTED;
}
int cpnum;
uint32_t op1;
@ -1307,7 +1309,7 @@ int armv4_5_run_algorithm_inner(struct target *target,
}
if (target->state != TARGET_HALTED) {
LOG_WARNING("target not halted");
LOG_TARGET_ERROR(target, "not halted (run target algo)");
return ERROR_TARGET_NOT_HALTED;
}

View File

@ -107,8 +107,10 @@ int armv4_5_mmu_read_physical(struct target *target,
{
int retval;
if (target->state != TARGET_HALTED)
if (target->state != TARGET_HALTED) {
LOG_TARGET_ERROR(target, "not halted");
return ERROR_TARGET_NOT_HALTED;
}
/* disable MMU and data (or unified) cache */
retval = armv4_5_mmu->disable_mmu_caches(target, 1, 1, 0);
@ -135,8 +137,10 @@ int armv4_5_mmu_write_physical(struct target *target,
{
int retval;
if (target->state != TARGET_HALTED)
if (target->state != TARGET_HALTED) {
LOG_TARGET_ERROR(target, "not halted");
return ERROR_TARGET_NOT_HALTED;
}
/* disable MMU and data (or unified) cache */
retval = armv4_5_mmu->disable_mmu_caches(target, 1, 1, 0);

View File

@ -22,7 +22,7 @@ static int armv7a_l1_d_cache_sanity_check(struct target *target)
struct armv7a_common *armv7a = target_to_armv7a(target);
if (target->state != TARGET_HALTED) {
LOG_ERROR("%s: target not halted", __func__);
LOG_TARGET_ERROR(target, "not halted");
return ERROR_TARGET_NOT_HALTED;
}
@ -40,7 +40,7 @@ static int armv7a_l1_i_cache_sanity_check(struct target *target)
struct armv7a_common *armv7a = target_to_armv7a(target);
if (target->state != TARGET_HALTED) {
LOG_ERROR("%s: target not halted", __func__);
LOG_TARGET_ERROR(target, "not halted");
return ERROR_TARGET_NOT_HALTED;
}

View File

@ -525,7 +525,7 @@ int armv7m_start_algorithm(struct target *target,
}
if (target->state != TARGET_HALTED) {
LOG_WARNING("target not halted");
LOG_TARGET_ERROR(target, "not halted (start target algo)");
return ERROR_TARGET_NOT_HALTED;
}

View File

@ -964,7 +964,7 @@ int armv8_mmu_translate_va_pa(struct target *target, target_addr_t va,
};
if (target->state != TARGET_HALTED) {
LOG_WARNING("target %s not halted", target_name(target));
LOG_TARGET_ERROR(target, "not halted");
return ERROR_TARGET_NOT_HALTED;
}

View File

@ -1210,7 +1210,7 @@ static int dpmv8_watchpoint_setup(struct arm_dpm *dpm, unsigned index_t,
uint32_t control;
/* this hardware doesn't support data value matching or masking */
if (wp->value || wp->mask != ~(uint32_t)0) {
if (wp->mask != WATCHPOINT_IGNORE_DATA_VALUE_MASK) {
LOG_DEBUG("watchpoint values and masking not supported");
return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
}

View File

@ -309,7 +309,7 @@ static int avr32_ap7k_resume(struct target *target, int current,
int retval;
if (target->state != TARGET_HALTED) {
LOG_WARNING("target not halted");
LOG_TARGET_ERROR(target, "not halted");
return ERROR_TARGET_NOT_HALTED;
}
@ -431,7 +431,7 @@ static int avr32_ap7k_read_memory(struct target *target, target_addr_t address,
count);
if (target->state != TARGET_HALTED) {
LOG_WARNING("target not halted");
LOG_TARGET_ERROR(target, "not halted");
return ERROR_TARGET_NOT_HALTED;
}
@ -471,7 +471,7 @@ static int avr32_ap7k_write_memory(struct target *target, target_addr_t address,
count);
if (target->state != TARGET_HALTED) {
LOG_WARNING("target not halted");
LOG_TARGET_ERROR(target, "not halted");
return ERROR_TARGET_NOT_HALTED;
}

View File

@ -448,7 +448,7 @@ struct breakpoint *breakpoint_find(struct target *target, target_addr_t address)
}
static int watchpoint_add_internal(struct target *target, target_addr_t address,
uint32_t length, enum watchpoint_rw rw, uint32_t value, uint32_t mask)
uint32_t length, enum watchpoint_rw rw, uint64_t value, uint64_t mask)
{
struct watchpoint *watchpoint = target->watchpoints;
struct watchpoint **watchpoint_p = &target->watchpoints;
@ -515,7 +515,7 @@ bye:
}
int watchpoint_add(struct target *target, target_addr_t address,
uint32_t length, enum watchpoint_rw rw, uint32_t value, uint32_t mask)
uint32_t length, enum watchpoint_rw rw, uint64_t value, uint64_t mask)
{
if (target->smp) {
struct target_list *head;

View File

@ -36,11 +36,13 @@ struct breakpoint {
int linked_brp;
};
#define WATCHPOINT_IGNORE_DATA_VALUE_MASK (~(uint64_t)0)
struct watchpoint {
target_addr_t address;
uint32_t length;
uint32_t mask;
uint32_t value;
uint64_t mask;
uint64_t value;
enum watchpoint_rw rw;
bool is_set;
unsigned int number;
@ -69,7 +71,7 @@ static inline void breakpoint_hw_set(struct breakpoint *breakpoint, unsigned int
void watchpoint_clear_target(struct target *target);
int watchpoint_add(struct target *target,
target_addr_t address, uint32_t length,
enum watchpoint_rw rw, uint32_t value, uint32_t mask);
enum watchpoint_rw rw, uint64_t value, uint64_t mask);
void watchpoint_remove(struct target *target, target_addr_t address);
/* report type and address of just hit watchpoint */

View File

@ -1147,7 +1147,7 @@ static int cortex_a_step(struct target *target, int current, target_addr_t addre
int retval;
if (target->state != TARGET_HALTED) {
LOG_WARNING("target not halted");
LOG_TARGET_ERROR(target, "not halted");
return ERROR_TARGET_NOT_HALTED;
}
@ -2225,7 +2225,7 @@ static int cortex_a_write_cpu_memory(struct target *target,
LOG_DEBUG("Writing CPU memory address 0x%" PRIx32 " size %" PRIu32 " count %" PRIu32,
address, size, count);
if (target->state != TARGET_HALTED) {
LOG_WARNING("target not halted");
LOG_TARGET_ERROR(target, "not halted");
return ERROR_TARGET_NOT_HALTED;
}
@ -2542,7 +2542,7 @@ static int cortex_a_read_cpu_memory(struct target *target,
LOG_DEBUG("Reading CPU memory address 0x%" PRIx32 " size %" PRIu32 " count %" PRIu32,
address, size, count);
if (target->state != TARGET_HALTED) {
LOG_WARNING("target not halted");
LOG_TARGET_ERROR(target, "not halted");
return ERROR_TARGET_NOT_HALTED;
}
@ -3183,8 +3183,8 @@ static int cortex_a_mmu(struct target *target, int *enabled)
struct armv7a_common *armv7a = target_to_armv7a(target);
if (target->state != TARGET_HALTED) {
LOG_ERROR("%s: target not halted", __func__);
return ERROR_TARGET_INVALID;
LOG_TARGET_ERROR(target, "not halted");
return ERROR_TARGET_NOT_HALTED;
}
if (armv7a->is_armv7r)

View File

@ -50,63 +50,63 @@
/* Supported Cortex-M Cores */
static const struct cortex_m_part_info cortex_m_parts[] = {
{
.partno = CORTEX_M0_PARTNO,
.impl_part = CORTEX_M0_PARTNO,
.name = "Cortex-M0",
.arch = ARM_ARCH_V6M,
},
{
.partno = CORTEX_M0P_PARTNO,
.impl_part = CORTEX_M0P_PARTNO,
.name = "Cortex-M0+",
.arch = ARM_ARCH_V6M,
},
{
.partno = CORTEX_M1_PARTNO,
.impl_part = CORTEX_M1_PARTNO,
.name = "Cortex-M1",
.arch = ARM_ARCH_V6M,
},
{
.partno = CORTEX_M3_PARTNO,
.impl_part = CORTEX_M3_PARTNO,
.name = "Cortex-M3",
.arch = ARM_ARCH_V7M,
.flags = CORTEX_M_F_TAR_AUTOINCR_BLOCK_4K,
},
{
.partno = CORTEX_M4_PARTNO,
.impl_part = CORTEX_M4_PARTNO,
.name = "Cortex-M4",
.arch = ARM_ARCH_V7M,
.flags = CORTEX_M_F_HAS_FPV4 | CORTEX_M_F_TAR_AUTOINCR_BLOCK_4K,
},
{
.partno = CORTEX_M7_PARTNO,
.impl_part = CORTEX_M7_PARTNO,
.name = "Cortex-M7",
.arch = ARM_ARCH_V7M,
.flags = CORTEX_M_F_HAS_FPV5,
},
{
.partno = CORTEX_M23_PARTNO,
.impl_part = CORTEX_M23_PARTNO,
.name = "Cortex-M23",
.arch = ARM_ARCH_V8M,
},
{
.partno = CORTEX_M33_PARTNO,
.impl_part = CORTEX_M33_PARTNO,
.name = "Cortex-M33",
.arch = ARM_ARCH_V8M,
.flags = CORTEX_M_F_HAS_FPV5,
},
{
.partno = CORTEX_M35P_PARTNO,
.impl_part = CORTEX_M35P_PARTNO,
.name = "Cortex-M35P",
.arch = ARM_ARCH_V8M,
.flags = CORTEX_M_F_HAS_FPV5,
},
{
.partno = CORTEX_M55_PARTNO,
.impl_part = CORTEX_M55_PARTNO,
.name = "Cortex-M55",
.arch = ARM_ARCH_V8M,
.flags = CORTEX_M_F_HAS_FPV5,
},
{
.partno = STAR_MC1_PARTNO,
.impl_part = STAR_MC1_PARTNO,
.name = "STAR-MC1",
.arch = ARM_ARCH_V8M,
.flags = CORTEX_M_F_HAS_FPV5,
@ -1214,7 +1214,7 @@ static int cortex_m_restore_one(struct target *target, bool current,
struct reg *r;
if (target->state != TARGET_HALTED) {
LOG_TARGET_ERROR(target, "target not halted");
LOG_TARGET_ERROR(target, "not halted");
return ERROR_TARGET_NOT_HALTED;
}
@ -1391,7 +1391,7 @@ static int cortex_m_step(struct target *target, int current,
bool isr_timed_out = false;
if (target->state != TARGET_HALTED) {
LOG_TARGET_WARNING(target, "target not halted");
LOG_TARGET_ERROR(target, "not halted");
return ERROR_TARGET_NOT_HALTED;
}
@ -2046,8 +2046,14 @@ int cortex_m_add_watchpoint(struct target *target, struct watchpoint *watchpoint
return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
}
/* hardware doesn't support data value masking */
if (watchpoint->mask != ~(uint32_t)0) {
/* REVISIT This DWT may well be able to watch for specific data
* values. Requires comparator #1 to set DATAVMATCH and match
* the data, and another comparator (DATAVADDR0) matching addr.
*
* NOTE: hardware doesn't support data value masking, so we'll need
* to check that mask is zero
*/
if (watchpoint->mask != WATCHPOINT_IGNORE_DATA_VALUE_MASK) {
LOG_TARGET_DEBUG(target, "watchpoint value masks not supported");
return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
}
@ -2068,18 +2074,6 @@ int cortex_m_add_watchpoint(struct target *target, struct watchpoint *watchpoint
return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
}
/* Caller doesn't seem to be able to describe watching for data
* values of zero; that flags "no value".
*
* REVISIT This DWT may well be able to watch for specific data
* values. Requires comparator #1 to set DATAVMATCH and match
* the data, and another comparator (DATAVADDR0) matching addr.
*/
if (watchpoint->value) {
LOG_TARGET_DEBUG(target, "data value watchpoint not YET supported");
return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
}
cortex_m->dwt_comp_available--;
LOG_TARGET_DEBUG(target, "dwt_comp_available: %d", cortex_m->dwt_comp_available);
@ -2092,7 +2086,7 @@ int cortex_m_remove_watchpoint(struct target *target, struct watchpoint *watchpo
/* REVISIT why check? DWT can be updated with core running ... */
if (target->state != TARGET_HALTED) {
LOG_TARGET_WARNING(target, "target not halted");
LOG_TARGET_ERROR(target, "not halted");
return ERROR_TARGET_NOT_HALTED;
}
@ -2532,18 +2526,18 @@ int cortex_m_examine(struct target *target)
if (retval != ERROR_OK)
return retval;
/* Get ARCH and CPU types */
const enum cortex_m_partno core_partno = (cpuid & ARM_CPUID_PARTNO_MASK) >> ARM_CPUID_PARTNO_POS;
/* Inspect implementor/part to look for recognized cores */
unsigned int impl_part = cpuid & (ARM_CPUID_IMPLEMENTOR_MASK | ARM_CPUID_PARTNO_MASK);
for (unsigned int n = 0; n < ARRAY_SIZE(cortex_m_parts); n++) {
if (core_partno == cortex_m_parts[n].partno) {
if (impl_part == cortex_m_parts[n].impl_part) {
cortex_m->core_info = &cortex_m_parts[n];
break;
}
}
if (!cortex_m->core_info) {
LOG_TARGET_ERROR(target, "Cortex-M PARTNO 0x%x is unrecognized", core_partno);
LOG_TARGET_ERROR(target, "Cortex-M CPUID: 0x%x is unrecognized", cpuid);
return ERROR_FAIL;
}
@ -2555,7 +2549,7 @@ int cortex_m_examine(struct target *target)
(uint8_t)((cpuid >> 0) & 0xf));
cortex_m->maskints_erratum = false;
if (core_partno == CORTEX_M7_PARTNO) {
if (impl_part == CORTEX_M7_PARTNO) {
uint8_t rev, patch;
rev = (cpuid >> 20) & 0xf;
patch = (cpuid >> 0) & 0xf;
@ -2948,8 +2942,8 @@ COMMAND_HANDLER(handle_cortex_m_mask_interrupts_command)
return retval;
if (target->state != TARGET_HALTED) {
command_print(CMD, "target must be stopped for \"%s\" command", CMD_NAME);
return ERROR_OK;
command_print(CMD, "Error: target must be stopped for \"%s\" command", CMD_NAME);
return ERROR_TARGET_NOT_HALTED;
}
if (CMD_ARGC > 0) {

View File

@ -31,22 +31,31 @@
#define CPUID 0xE000ED00
#define ARM_CPUID_PARTNO_POS 4
#define ARM_CPUID_PARTNO_MASK (0xFFF << ARM_CPUID_PARTNO_POS)
#define ARM_CPUID_IMPLEMENTOR_POS 24
#define ARM_CPUID_IMPLEMENTOR_MASK (0xFF << ARM_CPUID_IMPLEMENTOR_POS)
#define ARM_CPUID_PARTNO_POS 4
#define ARM_CPUID_PARTNO_MASK (0xFFF << ARM_CPUID_PARTNO_POS)
enum cortex_m_partno {
#define ARM_MAKE_CPUID(impl, partno) ((((impl) << ARM_CPUID_IMPLEMENTOR_POS) & ARM_CPUID_IMPLEMENTOR_MASK) | \
(((partno) << ARM_CPUID_PARTNO_POS) & ARM_CPUID_PARTNO_MASK))
/** Known Arm Cortex masked CPU Ids
* This includes the implementor and part number, but _not_ the revision or
* patch fields.
*/
enum cortex_m_impl_part {
CORTEX_M_PARTNO_INVALID,
STAR_MC1_PARTNO = 0x132,
CORTEX_M0_PARTNO = 0xC20,
CORTEX_M1_PARTNO = 0xC21,
CORTEX_M3_PARTNO = 0xC23,
CORTEX_M4_PARTNO = 0xC24,
CORTEX_M7_PARTNO = 0xC27,
CORTEX_M0P_PARTNO = 0xC60,
CORTEX_M23_PARTNO = 0xD20,
CORTEX_M33_PARTNO = 0xD21,
CORTEX_M35P_PARTNO = 0xD31,
CORTEX_M55_PARTNO = 0xD22,
STAR_MC1_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTOR_ARM, 0x132), /* FIXME - confirm implementor! */
CORTEX_M0_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTOR_ARM, 0xC20),
CORTEX_M1_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTOR_ARM, 0xC21),
CORTEX_M3_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTOR_ARM, 0xC23),
CORTEX_M4_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTOR_ARM, 0xC24),
CORTEX_M7_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTOR_ARM, 0xC27),
CORTEX_M0P_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTOR_ARM, 0xC60),
CORTEX_M23_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTOR_ARM, 0xD20),
CORTEX_M33_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTOR_ARM, 0xD21),
CORTEX_M35P_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTOR_ARM, 0xD31),
CORTEX_M55_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTOR_ARM, 0xD22),
};
/* Relevant Cortex-M flags, used in struct cortex_m_part_info.flags */
@ -55,7 +64,7 @@ enum cortex_m_partno {
#define CORTEX_M_F_TAR_AUTOINCR_BLOCK_4K BIT(2)
struct cortex_m_part_info {
enum cortex_m_partno partno;
enum cortex_m_impl_part impl_part;
const char *name;
enum arm_arch arch;
uint32_t flags;
@ -292,11 +301,11 @@ target_to_cortex_m_safe(struct target *target)
}
/**
* @returns cached value of Cortex-M part number
* @returns cached value of the cpuid, masked for implementation and part.
* or CORTEX_M_PARTNO_INVALID if the magic number does not match
* or core_info is not initialised.
*/
static inline enum cortex_m_partno cortex_m_get_partno_safe(struct target *target)
static inline enum cortex_m_impl_part cortex_m_get_impl_part(struct target *target)
{
struct cortex_m_common *cortex_m = target_to_cortex_m_safe(target);
if (!cortex_m)
@ -305,7 +314,7 @@ static inline enum cortex_m_partno cortex_m_get_partno_safe(struct target *targe
if (!cortex_m->core_info)
return CORTEX_M_PARTNO_INVALID;
return cortex_m->core_info->partno;
return cortex_m->core_info->impl_part;
}
int cortex_m_examine(struct target *target);

View File

@ -1296,7 +1296,7 @@ static int dsp563xx_step(struct target *target,
struct dsp563xx_common *dsp563xx = target_to_dsp563xx(target);
if (target->state != TARGET_HALTED) {
LOG_WARNING("target not halted");
LOG_TARGET_ERROR(target, "not halted");
return ERROR_TARGET_NOT_HALTED;
}
@ -1381,7 +1381,7 @@ static int dsp563xx_run_algorithm(struct target *target,
struct dsp563xx_common *dsp563xx = target_to_dsp563xx(target);
if (target->state != TARGET_HALTED) {
LOG_WARNING("target not halted");
LOG_TARGET_ERROR(target, "not halted (run target algo)");
return ERROR_TARGET_NOT_HALTED;
}
@ -1705,7 +1705,7 @@ static int dsp563xx_write_memory_core(struct target *target,
count);
if (target->state != TARGET_HALTED) {
LOG_WARNING("target not halted");
LOG_TARGET_ERROR(target, "not halted");
return ERROR_TARGET_NOT_HALTED;
}

View File

@ -318,8 +318,10 @@ static int esirisc_flush_caches(struct target *target)
LOG_DEBUG("-");
if (target->state != TARGET_HALTED)
if (target->state != TARGET_HALTED) {
LOG_TARGET_ERROR(target, "not halted");
return ERROR_TARGET_NOT_HALTED;
}
int retval = esirisc_jtag_flush_caches(jtag_info);
if (retval != ERROR_OK) {
@ -855,8 +857,10 @@ static int esirisc_resume_or_step(struct target *target, int current, target_add
LOG_DEBUG("-");
if (target->state != TARGET_HALTED)
if (target->state != TARGET_HALTED) {
LOG_TARGET_ERROR(target, "not halted");
return ERROR_TARGET_NOT_HALTED;
}
if (!debug_execution) {
target_free_all_working_areas(target);

View File

@ -2,21 +2,23 @@
noinst_LTLIBRARIES += %D%/libespressif.la
%C%_libespressif_la_SOURCES = \
%D%/esp_xtensa.c \
%D%/esp_xtensa.h \
%D%/esp_xtensa_smp.c \
%D%/esp_xtensa_smp.h \
%D%/esp_xtensa_semihosting.c \
%D%/esp_xtensa_semihosting.h \
%D%/esp_xtensa_apptrace.c \
%D%/esp_xtensa_apptrace.h \
%D%/esp32_apptrace.c \
%D%/esp32_apptrace.h \
%D%/esp32.c \
%D%/esp32s2.c \
%D%/esp32s3.c \
%D%/esp32_sysview.c \
%D%/esp32_sysview.h \
%D%/segger_sysview.h \
%D%/esp_semihosting.c \
%D%/esp_semihosting.h
%D%/esp_xtensa.c \
%D%/esp_xtensa.h \
%D%/esp_xtensa_smp.c \
%D%/esp_xtensa_smp.h \
%D%/esp_xtensa_semihosting.c \
%D%/esp_xtensa_semihosting.h \
%D%/esp_xtensa_apptrace.c \
%D%/esp_xtensa_apptrace.h \
%D%/esp32_apptrace.c \
%D%/esp32_apptrace.h \
%D%/esp32.c \
%D%/esp32s2.c \
%D%/esp32s3.c \
%D%/esp.c \
%D%/esp.h \
%D%/esp32_sysview.c \
%D%/esp32_sysview.h \
%D%/segger_sysview.h \
%D%/esp_semihosting.c \
%D%/esp_semihosting.h

View File

@ -0,0 +1,77 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/***************************************************************************
* Espressif chips common target API for OpenOCD *
* Copyright (C) 2021 Espressif Systems Ltd. *
***************************************************************************/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <helper/log.h>
#include <helper/binarybuffer.h>
#include "target/target.h"
#include "esp.h"
int esp_dbgstubs_table_read(struct target *target, struct esp_dbg_stubs *dbg_stubs)
{
uint32_t table_size, table_start_id, desc_entry_id, gcov_entry_id;
uint32_t entries[ESP_DBG_STUB_ENTRY_MAX] = {0};
uint8_t entry_buff[sizeof(entries)] = {0}; /* to avoid endiannes issues */
LOG_TARGET_DEBUG(target, "Read debug stubs info %" PRIx32 " / %d", dbg_stubs->base, dbg_stubs->entries_count);
/* First of, read 2 entries to get magic num and table size */
int res = target_read_buffer(target, dbg_stubs->base, sizeof(uint32_t) * 2, entry_buff);
if (res != ERROR_OK) {
LOG_ERROR("%s: Failed to read first debug stub entry!", target_name(target));
return res;
}
entries[0] = target_buffer_get_u32(target, entry_buff);
entries[1] = target_buffer_get_u32(target, entry_buff + sizeof(uint32_t));
if (entries[0] != ESP_DBG_STUB_MAGIC_NUM_VAL) {
/* idf with the old table entry structure */
table_size = 2;
table_start_id = 0;
desc_entry_id = 0;
gcov_entry_id = 1;
} else {
table_size = entries[1];
table_start_id = ESP_DBG_STUB_TABLE_START;
desc_entry_id = ESP_DBG_STUB_TABLE_START;
gcov_entry_id = ESP_DBG_STUB_ENTRY_FIRST;
/* discard unsupported entries */
if (table_size > ESP_DBG_STUB_ENTRY_MAX)
table_size = ESP_DBG_STUB_ENTRY_MAX;
/* now read the remaining entries */
res = target_read_buffer(target, dbg_stubs->base + 2 * sizeof(uint32_t), sizeof(uint32_t) * table_size - 2,
entry_buff + sizeof(uint32_t) * 2);
if (res != ERROR_OK) {
LOG_TARGET_ERROR(target, "Failed to read debug stubs info!");
return res;
}
for (unsigned int i = 2; i < table_size; ++i)
entries[i] = target_buffer_get_u32(target, entry_buff + sizeof(uint32_t) * i);
dbg_stubs->entries[ESP_DBG_STUB_CAPABILITIES] = entries[ESP_DBG_STUB_CAPABILITIES];
}
dbg_stubs->entries[ESP_DBG_STUB_DESC] = entries[desc_entry_id];
dbg_stubs->entries[ESP_DBG_STUB_ENTRY_GCOV] = entries[gcov_entry_id];
for (enum esp_dbg_stub_id i = ESP_DBG_STUB_DESC; i < ESP_DBG_STUB_ENTRY_MAX; i++) {
LOG_DEBUG("Check dbg stub %d - %x", i, dbg_stubs->entries[i]);
if (dbg_stubs->entries[i]) {
LOG_DEBUG("New dbg stub %d at %x", dbg_stubs->entries_count, dbg_stubs->entries[i]);
dbg_stubs->entries_count++;
}
}
if (dbg_stubs->entries_count < table_size - table_start_id)
LOG_WARNING("Not full dbg stub table %d of %d", dbg_stubs->entries_count, table_size - table_start_id);
return ERROR_OK;
}

View File

@ -0,0 +1,85 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
/***************************************************************************
* Espressif chips common target API for OpenOCD *
* Copyright (C) 2021 Espressif Systems Ltd. *
***************************************************************************/
#ifndef OPENOCD_TARGET_ESP_H
#define OPENOCD_TARGET_ESP_H
#include <stdint.h>
#include <helper/bits.h>
/* must be in sync with ESP-IDF version */
/** Size of the pre-compiled target buffer for stub trampoline.
* @note Must be in sync with ESP-IDF version */
#define ESP_DBG_STUBS_CODE_BUF_SIZE 32 /* TODO: move this info to esp_dbg_stubs_desc */
/** Size of the pre-compiled target buffer for stack.
* @note Must be in sync with ESP-IDF version */
#define ESP_DBG_STUBS_STACK_MIN_SIZE 2048/* TODO: move this info to esp_dbg_stubs_desc */
/**
* Debug stubs table entries IDs
*
* @note Must be in sync with ESP-IDF version
*/
enum esp_dbg_stub_id {
ESP_DBG_STUB_ENTRY_MAGIC_NUM,
ESP_DBG_STUB_TABLE_SIZE,
ESP_DBG_STUB_TABLE_START,
ESP_DBG_STUB_DESC = ESP_DBG_STUB_TABLE_START, /*< Stubs descriptor ID */
ESP_DBG_STUB_ENTRY_FIRST,
ESP_DBG_STUB_ENTRY_GCOV = ESP_DBG_STUB_ENTRY_FIRST, /*< GCOV stub ID */
ESP_DBG_STUB_CAPABILITIES,
/* add new stub entries here */
ESP_DBG_STUB_ENTRY_MAX,
};
#define ESP_DBG_STUB_MAGIC_NUM_VAL 0xFEEDBEEF
#define ESP_DBG_STUB_CAP_GCOV_THREAD BIT(0)
/**
* Debug stubs descriptor. ID: ESP_DBG_STUB_DESC
*
* @note Must be in sync with ESP-IDF version
*/
struct esp_dbg_stubs_desc {
/** Address of pre-compiled target buffer for stub trampoline.
* Size of the buffer is ESP_DBG_STUBS_CODE_BUF_SIZE
*/
uint32_t tramp_addr;
/** Pre-compiled target buffer's addr for stack. The size of the buffer is ESP_DBG_STUBS_STACK_MIN_SIZE.
* Target has the buffer which is used for the stack of onboard algorithms.
* If stack size required by algorithm exceeds ESP_DBG_STUBS_STACK_MIN_SIZE,
* it should be allocated using onboard function pointed by 'data_alloc' and
* freed by 'data_free'. They fit to the minimal stack. See below.
*/
uint32_t min_stack_addr;
/** Address of malloc-like function to allocate buffer on target. */
uint32_t data_alloc;
/** Address of free-like function to free buffer allocated with data_alloc. */
uint32_t data_free;
};
/**
* Debug stubs info.
*/
struct esp_dbg_stubs {
/** Address. */
uint32_t base;
/** Table contents. */
uint32_t entries[ESP_DBG_STUB_ENTRY_MAX];
/** Number of table entries. */
uint32_t entries_count;
/** Debug stubs decsriptor. */
struct esp_dbg_stubs_desc desc;
};
struct esp_common {
struct esp_dbg_stubs dbg_stubs;
};
int esp_dbgstubs_table_read(struct target *target, struct esp_dbg_stubs *dbg_stubs);
#endif /* OPENOCD_TARGET_ESP_H */

View File

@ -24,20 +24,8 @@ implementation.
*/
/* ESP32 memory map */
#define ESP32_DRAM_LOW 0x3ffae000
#define ESP32_DRAM_HIGH 0x40000000
#define ESP32_IROM_MASK_LOW 0x40000000
#define ESP32_IROM_MASK_HIGH 0x40064f00
#define ESP32_IRAM_LOW 0x40070000
#define ESP32_IRAM_HIGH 0x400a0000
#define ESP32_RTC_IRAM_LOW 0x400c0000
#define ESP32_RTC_IRAM_HIGH 0x400c2000
#define ESP32_RTC_DRAM_LOW 0x3ff80000
#define ESP32_RTC_DRAM_HIGH 0x3ff82000
#define ESP32_RTC_DATA_LOW 0x50000000
#define ESP32_RTC_DATA_HIGH 0x50002000
#define ESP32_EXTRAM_DATA_LOW 0x3f800000
#define ESP32_EXTRAM_DATA_HIGH 0x3fc00000
#define ESP32_DR_REG_LOW 0x3ff00000
#define ESP32_DR_REG_HIGH 0x3ff71000
#define ESP32_SYS_RAM_LOW 0x60000000UL
@ -266,7 +254,10 @@ static int esp32_disable_wdts(struct target *target)
static int esp32_on_halt(struct target *target)
{
return esp32_disable_wdts(target);
int ret = esp32_disable_wdts(target);
if (ret == ERROR_OK)
ret = esp_xtensa_smp_on_halt(target);
return ret;
}
static int esp32_arch_state(struct target *target)

View File

@ -1252,7 +1252,7 @@ static int esp32_sysview_start(struct esp32_apptrace_cmd_ctx *ctx)
{
uint8_t cmds[] = { SEGGER_SYSVIEW_COMMAND_ID_START };
uint32_t fired_target_num = 0;
struct esp32_apptrace_target_state target_state[ESP32_APPTRACE_MAX_CORES_NUM] = {0};
struct esp32_apptrace_target_state target_state[ESP32_APPTRACE_MAX_CORES_NUM] = {{0}};
struct esp32_sysview_cmd_data *cmd_data = ctx->cmd_priv;
/* get current block id */

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