diff --git a/HACKING b/HACKING
index b1d224dbf6..34d5745716 100644
--- a/HACKING
+++ b/HACKING
@@ -195,7 +195,9 @@ git remote add review https://USERNAME:PASSWORD@review.openocd.org/p/openocd.git
Gerrit server, even if you plan to use several local branches for different
topics. It is possible because @c for/master is not a traditional Git
branch.
- -# You will need to install this hook, we will look into a better solution:
+ -# You will need to install this hook to automatically add the
+ field "Change-Id:" in the commit message, as required by Gerrit.
+ We will look into a better solution:
@code
wget https://review.openocd.org/tools/hooks/commit-msg
mv commit-msg .git/hooks
@@ -272,6 +274,12 @@ doc: fix typos
@code
git pull --rebase origin master
@endcode
+
+-# When you create a new version of an old patch, check that the new patch
+ keeps the same 'Change-Id:' field of the old patch.
+ This allows the Gerrit server to recognize the patch as a new version of
+ the older one and keeps track of the history and the review process.
+
-# Send the patches to the Gerrit server for review:
@code
git push review
diff --git a/LICENSES/dual/CC-BY-4.0 b/LICENSES/dual/CC-BY-4.0
new file mode 100644
index 0000000000..e20b7a455e
--- /dev/null
+++ b/LICENSES/dual/CC-BY-4.0
@@ -0,0 +1,409 @@
+Valid-License-Identifier: CC-BY-4.0
+SPDX-URL: https://spdx.org/licenses/CC-BY-4.0
+Usage-Guide:
+ Do NOT use on OpenOCD code. This license is not GPL2 compatible. It may only
+ be used for dual-licensed files where the other license is GPL2 compatible.
+ If you end up using this it MUST be used together with a GPL2 compatible
+ license using "OR".
+ To use the Creative Commons Attribution 4.0 International license put
+ the following SPDX tag/value pair into a comment according to the
+ placement guidelines in the licensing rules documentation:
+ SPDX-License-Identifier: CC-BY-4.0
+License-Text:
+
+Creative Commons Attribution 4.0 International
+
+=======================================================================
+
+Creative Commons Corporation ("Creative Commons") is not a law firm and
+does not provide legal services or legal advice. Distribution of
+Creative Commons public licenses does not create a lawyer-client or
+other relationship. Creative Commons makes its licenses and related
+information available on an "as-is" basis. Creative Commons gives no
+warranties regarding its licenses, any material licensed under their
+terms and conditions, or any related information. Creative Commons
+disclaims all liability for damages resulting from their use to the
+fullest extent possible.
+
+Using Creative Commons Public Licenses
+
+Creative Commons public licenses provide a standard set of terms and
+conditions that creators and other rights holders may use to share
+original works of authorship and other material subject to copyright
+and certain other rights specified in the public license below. The
+following considerations are for informational purposes only, are not
+exhaustive, and do not form part of our licenses.
+
+ Considerations for licensors: Our public licenses are
+ intended for use by those authorized to give the public
+ permission to use material in ways otherwise restricted by
+ copyright and certain other rights. Our licenses are
+ irrevocable. Licensors should read and understand the terms
+ and conditions of the license they choose before applying it.
+ Licensors should also secure all rights necessary before
+ applying our licenses so that the public can reuse the
+ material as expected. Licensors should clearly mark any
+ material not subject to the license. This includes other CC-
+ licensed material, or material used under an exception or
+ limitation to copyright. More considerations for licensors:
+ wiki.creativecommons.org/Considerations_for_licensors
+
+ Considerations for the public: By using one of our public
+ licenses, a licensor grants the public permission to use the
+ licensed material under specified terms and conditions. If
+ the licensor's permission is not necessary for any reason--for
+ example, because of any applicable exception or limitation to
+ copyright--then that use is not regulated by the license. Our
+ licenses grant only permissions under copyright and certain
+ other rights that a licensor has authority to grant. Use of
+ the licensed material may still be restricted for other
+ reasons, including because others have copyright or other
+ rights in the material. A licensor may make special requests,
+ such as asking that all changes be marked or described.
+ Although not required by our licenses, you are encouraged to
+ respect those requests where reasonable. More considerations
+ for the public:
+ wiki.creativecommons.org/Considerations_for_licensees
+
+=======================================================================
+
+Creative Commons Attribution 4.0 International Public License
+
+By exercising the Licensed Rights (defined below), You accept and agree
+to be bound by the terms and conditions of this Creative Commons
+Attribution 4.0 International Public License ("Public License"). To the
+extent this Public License may be interpreted as a contract, You are
+granted the Licensed Rights in consideration of Your acceptance of
+these terms and conditions, and the Licensor grants You such rights in
+consideration of benefits the Licensor receives from making the
+Licensed Material available under these terms and conditions.
+
+
+Section 1 -- Definitions.
+
+ a. Adapted Material means material subject to Copyright and Similar
+ Rights that is derived from or based upon the Licensed Material
+ and in which the Licensed Material is translated, altered,
+ arranged, transformed, or otherwise modified in a manner requiring
+ permission under the Copyright and Similar Rights held by the
+ Licensor. For purposes of this Public License, where the Licensed
+ Material is a musical work, performance, or sound recording,
+ Adapted Material is always produced where the Licensed Material is
+ synched in timed relation with a moving image.
+
+ b. Adapter's License means the license You apply to Your Copyright
+ and Similar Rights in Your contributions to Adapted Material in
+ accordance with the terms and conditions of this Public License.
+
+ c. Copyright and Similar Rights means copyright and/or similar rights
+ closely related to copyright including, without limitation,
+ performance, broadcast, sound recording, and Sui Generis Database
+ Rights, without regard to how the rights are labeled or
+ categorized. For purposes of this Public License, the rights
+ specified in Section 2(b)(1)-(2) are not Copyright and Similar
+ Rights.
+
+ d. Effective Technological Measures means those measures that, in the
+ absence of proper authority, may not be circumvented under laws
+ fulfilling obligations under Article 11 of the WIPO Copyright
+ Treaty adopted on December 20, 1996, and/or similar international
+ agreements.
+
+ e. Exceptions and Limitations means fair use, fair dealing, and/or
+ any other exception or limitation to Copyright and Similar Rights
+ that applies to Your use of the Licensed Material.
+
+ f. Licensed Material means the artistic or literary work, database,
+ or other material to which the Licensor applied this Public
+ License.
+
+ g. Licensed Rights means the rights granted to You subject to the
+ terms and conditions of this Public License, which are limited to
+ all Copyright and Similar Rights that apply to Your use of the
+ Licensed Material and that the Licensor has authority to license.
+
+ h. Licensor means the individual(s) or entity(ies) granting rights
+ under this Public License.
+
+ i. Share means to provide material to the public by any means or
+ process that requires permission under the Licensed Rights, such
+ as reproduction, public display, public performance, distribution,
+ dissemination, communication, or importation, and to make material
+ available to the public including in ways that members of the
+ public may access the material from a place and at a time
+ individually chosen by them.
+
+ j. Sui Generis Database Rights means rights other than copyright
+ resulting from Directive 96/9/EC of the European Parliament and of
+ the Council of 11 March 1996 on the legal protection of databases,
+ as amended and/or succeeded, as well as other essentially
+ equivalent rights anywhere in the world.
+
+ k. You means the individual or entity exercising the Licensed Rights
+ under this Public License. Your has a corresponding meaning.
+
+
+Section 2 -- Scope.
+
+ a. License grant.
+
+ 1. Subject to the terms and conditions of this Public License,
+ the Licensor hereby grants You a worldwide, royalty-free,
+ non-sublicensable, non-exclusive, irrevocable license to
+ exercise the Licensed Rights in the Licensed Material to:
+
+ a. reproduce and Share the Licensed Material, in whole or
+ in part; and
+
+ b. produce, reproduce, and Share Adapted Material.
+
+ 2. Exceptions and Limitations. For the avoidance of doubt, where
+ Exceptions and Limitations apply to Your use, this Public
+ License does not apply, and You do not need to comply with
+ its terms and conditions.
+
+ 3. Term. The term of this Public License is specified in Section
+ 6(a).
+
+ 4. Media and formats; technical modifications allowed. The
+ Licensor authorizes You to exercise the Licensed Rights in
+ all media and formats whether now known or hereafter created,
+ and to make technical modifications necessary to do so. The
+ Licensor waives and/or agrees not to assert any right or
+ authority to forbid You from making technical modifications
+ necessary to exercise the Licensed Rights, including
+ technical modifications necessary to circumvent Effective
+ Technological Measures. For purposes of this Public License,
+ simply making modifications authorized by this Section 2(a)
+ (4) never produces Adapted Material.
+
+ 5. Downstream recipients.
+
+ a. Offer from the Licensor -- Licensed Material. Every
+ recipient of the Licensed Material automatically
+ receives an offer from the Licensor to exercise the
+ Licensed Rights under the terms and conditions of this
+ Public License.
+
+ b. No downstream restrictions. You may not offer or impose
+ any additional or different terms or conditions on, or
+ apply any Effective Technological Measures to, the
+ Licensed Material if doing so restricts exercise of the
+ Licensed Rights by any recipient of the Licensed
+ Material.
+
+ 6. No endorsement. Nothing in this Public License constitutes or
+ may be construed as permission to assert or imply that You
+ are, or that Your use of the Licensed Material is, connected
+ with, or sponsored, endorsed, or granted official status by,
+ the Licensor or others designated to receive attribution as
+ provided in Section 3(a)(1)(A)(i).
+
+ b. Other rights.
+
+ 1. Moral rights, such as the right of integrity, are not
+ licensed under this Public License, nor are publicity,
+ privacy, and/or other similar personality rights; however, to
+ the extent possible, the Licensor waives and/or agrees not to
+ assert any such rights held by the Licensor to the limited
+ extent necessary to allow You to exercise the Licensed
+ Rights, but not otherwise.
+
+ 2. Patent and trademark rights are not licensed under this
+ Public License.
+
+ 3. To the extent possible, the Licensor waives any right to
+ collect royalties from You for the exercise of the Licensed
+ Rights, whether directly or through a collecting society
+ under any voluntary or waivable statutory or compulsory
+ licensing scheme. In all other cases the Licensor expressly
+ reserves any right to collect such royalties.
+
+
+Section 3 -- License Conditions.
+
+Your exercise of the Licensed Rights is expressly made subject to the
+following conditions.
+
+ a. Attribution.
+
+ 1. If You Share the Licensed Material (including in modified
+ form), You must:
+
+ a. retain the following if it is supplied by the Licensor
+ with the Licensed Material:
+
+ i. identification of the creator(s) of the Licensed
+ Material and any others designated to receive
+ attribution, in any reasonable manner requested by
+ the Licensor (including by pseudonym if
+ designated);
+
+ ii. a copyright notice;
+
+ iii. a notice that refers to this Public License;
+
+ iv. a notice that refers to the disclaimer of
+ warranties;
+
+ v. a URI or hyperlink to the Licensed Material to the
+ extent reasonably practicable;
+
+ b. indicate if You modified the Licensed Material and
+ retain an indication of any previous modifications; and
+
+ c. indicate the Licensed Material is licensed under this
+ Public License, and include the text of, or the URI or
+ hyperlink to, this Public License.
+
+ 2. You may satisfy the conditions in Section 3(a)(1) in any
+ reasonable manner based on the medium, means, and context in
+ which You Share the Licensed Material. For example, it may be
+ reasonable to satisfy the conditions by providing a URI or
+ hyperlink to a resource that includes the required
+ information.
+
+ 3. If requested by the Licensor, You must remove any of the
+ information required by Section 3(a)(1)(A) to the extent
+ reasonably practicable.
+
+ 4. If You Share Adapted Material You produce, the Adapter's
+ License You apply must not prevent recipients of the Adapted
+ Material from complying with this Public License.
+
+
+Section 4 -- Sui Generis Database Rights.
+
+Where the Licensed Rights include Sui Generis Database Rights that
+apply to Your use of the Licensed Material:
+
+ a. for the avoidance of doubt, Section 2(a)(1) grants You the right
+ to extract, reuse, reproduce, and Share all or a substantial
+ portion of the contents of the database;
+
+ b. if You include all or a substantial portion of the database
+ contents in a database in which You have Sui Generis Database
+ Rights, then the database in which You have Sui Generis Database
+ Rights (but not its individual contents) is Adapted Material; and
+
+ c. You must comply with the conditions in Section 3(a) if You Share
+ all or a substantial portion of the contents of the database.
+
+For the avoidance of doubt, this Section 4 supplements and does not
+replace Your obligations under this Public License where the Licensed
+Rights include other Copyright and Similar Rights.
+
+
+Section 5 -- Disclaimer of Warranties and Limitation of Liability.
+
+ a. UNLESS OTHERWISE SEPARATELY UNDERTAKEN BY THE LICENSOR, TO THE
+ EXTENT POSSIBLE, THE LICENSOR OFFERS THE LICENSED MATERIAL AS-IS
+ AND AS-AVAILABLE, AND MAKES NO REPRESENTATIONS OR WARRANTIES OF
+ ANY KIND CONCERNING THE LICENSED MATERIAL, WHETHER EXPRESS,
+ IMPLIED, STATUTORY, OR OTHER. THIS INCLUDES, WITHOUT LIMITATION,
+ WARRANTIES OF TITLE, MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ PURPOSE, NON-INFRINGEMENT, ABSENCE OF LATENT OR OTHER DEFECTS,
+ ACCURACY, OR THE PRESENCE OR ABSENCE OF ERRORS, WHETHER OR NOT
+ KNOWN OR DISCOVERABLE. WHERE DISCLAIMERS OF WARRANTIES ARE NOT
+ ALLOWED IN FULL OR IN PART, THIS DISCLAIMER MAY NOT APPLY TO YOU.
+
+ b. TO THE EXTENT POSSIBLE, IN NO EVENT WILL THE LICENSOR BE LIABLE
+ TO YOU ON ANY LEGAL THEORY (INCLUDING, WITHOUT LIMITATION,
+ NEGLIGENCE) OR OTHERWISE FOR ANY DIRECT, SPECIAL, INDIRECT,
+ INCIDENTAL, CONSEQUENTIAL, PUNITIVE, EXEMPLARY, OR OTHER LOSSES,
+ COSTS, EXPENSES, OR DAMAGES ARISING OUT OF THIS PUBLIC LICENSE OR
+ USE OF THE LICENSED MATERIAL, EVEN IF THE LICENSOR HAS BEEN
+ ADVISED OF THE POSSIBILITY OF SUCH LOSSES, COSTS, EXPENSES, OR
+ DAMAGES. WHERE A LIMITATION OF LIABILITY IS NOT ALLOWED IN FULL OR
+ IN PART, THIS LIMITATION MAY NOT APPLY TO YOU.
+
+ c. The disclaimer of warranties and limitation of liability provided
+ above shall be interpreted in a manner that, to the extent
+ possible, most closely approximates an absolute disclaimer and
+ waiver of all liability.
+
+
+Section 6 -- Term and Termination.
+
+ a. This Public License applies for the term of the Copyright and
+ Similar Rights licensed here. However, if You fail to comply with
+ this Public License, then Your rights under this Public License
+ terminate automatically.
+
+ b. Where Your right to use the Licensed Material has terminated under
+ Section 6(a), it reinstates:
+
+ 1. automatically as of the date the violation is cured, provided
+ it is cured within 30 days of Your discovery of the
+ violation; or
+
+ 2. upon express reinstatement by the Licensor.
+
+ For the avoidance of doubt, this Section 6(b) does not affect any
+ right the Licensor may have to seek remedies for Your violations
+ of this Public License.
+
+ c. For the avoidance of doubt, the Licensor may also offer the
+ Licensed Material under separate terms or conditions or stop
+ distributing the Licensed Material at any time; however, doing so
+ will not terminate this Public License.
+
+ d. Sections 1, 5, 6, 7, and 8 survive termination of this Public
+ License.
+
+
+Section 7 -- Other Terms and Conditions.
+
+ a. The Licensor shall not be bound by any additional or different
+ terms or conditions communicated by You unless expressly agreed.
+
+ b. Any arrangements, understandings, or agreements regarding the
+ Licensed Material not stated herein are separate from and
+ independent of the terms and conditions of this Public License.
+
+
+Section 8 -- Interpretation.
+
+ a. For the avoidance of doubt, this Public License does not, and
+ shall not be interpreted to, reduce, limit, restrict, or impose
+ conditions on any use of the Licensed Material that could lawfully
+ be made without permission under this Public License.
+
+ b. To the extent possible, if any provision of this Public License is
+ deemed unenforceable, it shall be automatically reformed to the
+ minimum extent necessary to make it enforceable. If the provision
+ cannot be reformed, it shall be severed from this Public License
+ without affecting the enforceability of the remaining terms and
+ conditions.
+
+ c. No term or condition of this Public License will be waived and no
+ failure to comply consented to unless expressly agreed to by the
+ Licensor.
+
+ d. Nothing in this Public License constitutes or may be interpreted
+ as a limitation upon, or waiver of, any privileges and immunities
+ that apply to the Licensor or You, including from the legal
+ processes of any jurisdiction or authority.
+
+
+=======================================================================
+
+Creative Commons is not a party to its public
+licenses. Notwithstanding, Creative Commons may elect to apply one of
+its public licenses to material it publishes and in those instances
+will be considered the "Licensor." The text of the Creative Commons
+public licenses is dedicated to the public domain under the CC0 Public
+Domain Dedication. Except for the limited purpose of indicating that
+material is shared under a Creative Commons public license or as
+otherwise permitted by the Creative Commons policies published at
+creativecommons.org/policies, Creative Commons does not authorize the
+use of the trademark "Creative Commons" or any other trademark or logo
+of Creative Commons without its prior written consent including,
+without limitation, in connection with any unauthorized modifications
+to any of its public licenses or any other arrangements,
+understandings, or agreements concerning use of licensed material. For
+the avoidance of doubt, this paragraph does not form part of the
+public licenses.
+
+Creative Commons may be contacted at creativecommons.org.
+
diff --git a/LICENSES/license-rules.txt b/LICENSES/license-rules.txt
index ecc8e4db16..66aaaa5b4d 100644
--- a/LICENSES/license-rules.txt
+++ b/LICENSES/license-rules.txt
@@ -187,7 +187,21 @@ OpenOCD, can be broken down into:
License-Text:
Full license text
-2. Exceptions:
+2. Dual Licensing Only:
+
+ These licenses should only be used to dual license code with another
+ license in addition to a preferred license. These licenses are available
+ from the directory::
+
+ LICENSES/dual/
+
+ in the OpenOCD source tree.
+
+ The files in this directory contain the full license text and
+ `Metatags`_. The file names are identical to the SPDX license
+ identifier which shall be used for the license in source files.
+
+3. Exceptions:
Some licenses can be amended with exceptions which grant certain rights
which the original license does not. These exceptions are available
@@ -244,7 +258,7 @@ OpenOCD, can be broken down into:
License-Text:
Full license text
-3. Stand-alone licenses:
+4. Stand-alone licenses:
These licenses should only be used for stand-alone applications that are
distributed with OpenOCD but are not included in the OpenOCD binary.
diff --git a/LICENSES/preferred/GFDL-1.2 b/LICENSES/preferred/GFDL-1.2
index 9217d9c8ec..ded6f4d453 100644
--- a/LICENSES/preferred/GFDL-1.2
+++ b/LICENSES/preferred/GFDL-1.2
@@ -18,7 +18,7 @@ License-Text:
Copyright (C) 2000,2001,2002 Free Software Foundation, Inc.
- 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
diff --git a/LICENSES/preferred/GPL-2.0 b/LICENSES/preferred/GPL-2.0
index 687bdddb11..25d8343cd0 100644
--- a/LICENSES/preferred/GPL-2.0
+++ b/LICENSES/preferred/GPL-2.0
@@ -15,7 +15,7 @@ License-Text:
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
- 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
@@ -317,8 +317,7 @@ the "copyright" line and a pointer to where the full notice is found.
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
- with this program; if not, write to the Free Software Foundation, Inc.,
- 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ with this program; if not, see .
Also add information on how to contact you by electronic and paper mail.
diff --git a/LICENSES/preferred/LGPL-2.1 b/LICENSES/preferred/LGPL-2.1
index 8738a8d578..b19c23d17c 100644
--- a/LICENSES/preferred/LGPL-2.1
+++ b/LICENSES/preferred/LGPL-2.1
@@ -16,7 +16,7 @@ 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.
@@ -486,9 +486,9 @@ 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.
+along with this library; if not, see .
+
+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
diff --git a/Makefile.am b/Makefile.am
index 271a2c1654..845543721d 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -1,8 +1,6 @@
# SPDX-License-Identifier: GPL-2.0-or-later
-# not a GNU package. You can remove this line, if
-# have all needed files, that a GNU package needs
-AUTOMAKE_OPTIONS = gnu 1.6
+AUTOMAKE_OPTIONS = gnu 1.14
.DELETE_ON_ERROR:
@@ -10,7 +8,7 @@ AUTOMAKE_OPTIONS = gnu 1.6
AM_DISTCHECK_CONFIGURE_FLAGS = --disable-install-jim
# do not run Jim Tcl tests (esp. during distcheck)
-check-recursive: SUBDIRS :=
+check-recursive: SUBDIRS := $(SUBDIRS:jimtcl=)
nobase_dist_pkgdata_DATA = \
contrib/libdcc/dcc_stdio.c \
@@ -36,6 +34,9 @@ EXTRA_DIST += jimtcl/configure.gnu
DISTCLEANFILES += jimtcl/jsmn/jsmn.o
endif
+SUBDIRS += testing
+DIST_SUBDIRS += testing
+
# common flags used in openocd build
AM_CFLAGS = $(GCC_WARNINGS)
AM_LDFLAGS =
@@ -67,6 +68,7 @@ EXTRA_DIST += \
$(EXTRA_DIST_NEWS) \
Doxyfile.in \
LICENSES/license-rules.txt \
+ LICENSES/dual/CC-BY-4.0 \
LICENSES/exceptions/eCos-exception-2.0 \
LICENSES/preferred/BSD-1-Clause \
LICENSES/preferred/BSD-2-Clause \
diff --git a/README b/README
index 875c85de3b..73aa3a6301 100644
--- a/README
+++ b/README
@@ -191,6 +191,11 @@ and compiling the OpenOCD source code. That file is provided by
default for all GNU autotools packages. If you are not familiar with
the GNU autotools, then you should read those instructions first.
+Note: if the INSTALL file is not present, it means you are using the
+source code from a development branch, not from an OpenOCD release.
+In this case, follow the instructions 'Compiling OpenOCD' below and
+the file will be created by the first command './bootstrap'.
+
The remainder of this document tries to provide some instructions for
those looking for a quick-install.
diff --git a/README.Windows b/README.Windows
index 64bf5c0c6f..293eed975c 100644
--- a/README.Windows
+++ b/README.Windows
@@ -10,18 +10,6 @@ host. See README for the generic instructions.
Also, the MSYS2 project provides both ready-made binaries and an easy
way to self-compile from their software repository out of the box.
-Native MinGW-w64/MSYS compilation
------------------------------
-
-As MSYS doesn't come with pkg-config pre-installed, you need to add it
-manually. The easiest way to do that is to download pkg-config-lite
-from:
-
- http://sourceforge.net/projects/pkgconfiglite/
-
-Then simply unzip the archive to the root directory of your MinGW-w64
-installation.
-
USB adapters
------------
diff --git a/configure.ac b/configure.ac
index c026e14a1c..d563f2b668 100644
--- a/configure.ac
+++ b/configure.ac
@@ -24,7 +24,6 @@ AC_LANG([C])
AC_PROG_CC
# autoconf 2.70 obsoletes AC_PROG_CC_C99 and includes it in AC_PROG_CC
m4_version_prereq([2.70],[],[AC_PROG_CC_C99])
-AM_PROG_CC_C_O
AC_PROG_RANLIB
# If macro PKG_PROG_PKG_CONFIG is not available, Autoconf generates a misleading error message,
@@ -63,11 +62,14 @@ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include ]], [[int v = __GLIBC_
AC_MSG_RESULT($have_glibc)
AC_CHECK_HEADERS([fcntl.h])
+AC_CHECK_HEADERS([linux/pci.h])
+AC_CHECK_HEADERS([linux/spi/spidev.h])
AC_CHECK_HEADERS([malloc.h])
AC_CHECK_HEADERS([netdb.h])
AC_CHECK_HEADERS([poll.h])
AC_CHECK_HEADERS([strings.h])
AC_CHECK_HEADERS([sys/ioctl.h])
+AC_CHECK_HEADERS([sys/mman.h])
AC_CHECK_HEADERS([sys/param.h])
AC_CHECK_HEADERS([sys/select.h])
AC_CHECK_HEADERS([sys/stat.h])
@@ -129,6 +131,7 @@ m4_define([ADAPTER_OPT], [m4_translit(ADAPTER_ARG($1), [_], [-])])
m4_define([USB1_ADAPTERS],
[[[ftdi], [MPSSE mode of FTDI based devices], [FTDI]],
[[ftdi_cjtag], [cJTAG (OScan1, JScan3) tunneled thru MPSSE], [FTDI_CJTAG]],
+ [[ch347], [CH347 based devices], [CH347]],
[[stlink], [ST-Link Programmer], [HLADAPTER_STLINK]],
[[ti_icdi], [TI ICDI JTAG Programmer], [HLADAPTER_ICDI]],
[[ulink], [Keil ULINK JTAG Programmer], [ULINK]],
@@ -165,6 +168,9 @@ m4_define([LIBFTDI_USB1_ADAPTERS],
m4_define([LIBGPIOD_ADAPTERS],
[[[linuxgpiod], [Linux GPIO bitbang through libgpiod], [LINUXGPIOD]]])
+m4_define([DMEM_ADAPTER],
+ [[[dmem], [CoreSight Direct Memory], [DMEM]]])
+
m4_define([SYSFSGPIO_ADAPTER],
[[[sysfsgpio], [Linux GPIO bitbang through sysfs], [SYSFSGPIO]]])
@@ -174,12 +180,15 @@ m4_define([REMOTE_BITBANG_ADAPTER],
m4_define([LIBJAYLINK_ADAPTERS],
[[[jlink], [SEGGER J-Link Programmer], [JLINK]]])
-m4_define([PCIE_ADAPTERS],
- [[[xlnx_pcie_xvc], [Xilinx XVC/PCIe], [XLNX_PCIE_XVC]]])
+m4_define([XVC_ADAPTERS],
+ [[[xlnx_xvc], [Xilinx XVC PCIe and AXI drives], [XLNX_XVC]]])
m4_define([SERIAL_PORT_ADAPTERS],
[[[buspirate], [Bus Pirate], [BUS_PIRATE]]])
+m4_define([PARALLEL_PORT_ADAPTER],
+ [[[parport], [PC Parallel Port], [PARPORT]]])
+
m4_define([LINUXSPIDEV_ADAPTER],
[[[linuxspidev], [Linux spidev driver], [LINUXSPIDEV]]])
m4_define([VDEBUG_ADAPTER],
@@ -197,8 +206,18 @@ m4_define([RSHIM_ADAPTER],
m4_define([AMTJTAGACCEL_ADAPTER],
[[[amtjtagaccel], [Amontec JTAG-Accelerator driver], [AMTJTAGACCEL]]])
-# The word 'Adapter' in "Dummy Adapter" below must begin with a capital letter
-# because there is an M4 macro called 'adapter'.
+m4_define([CMSIS_DAP_TCP_ADAPTER],
+ [[[cmsis_dap_tcp], [CMSIS-DAP v2 compliant dongle (TCP)], [CMSIS_DAP_TCP]]])
+
+m4_define([HOST_ARM_BITBANG_ADAPTERS],
+ [[[ep93xx], [Bitbanging on EP93xx-based SBCs], [EP93XX]],
+ [[at91rm9200], [Bitbanging on AT91RM9200-based SBCs], [AT91RM9200]]])
+
+m4_define([HOST_ARM_OR_AARCH64_BITBANG_ADAPTERS],
+ [[[bcm2835gpio], [Bitbanging on BCM2835 (as found in Raspberry Pi)], [BCM2835GPIO]],
+ [[imx_gpio], [Bitbanging on NXP IMX processors], [IMX_GPIO]],
+ [[am335xgpio], [Bitbanging on AM335x (as found in Beaglebones)], [AM335XGPIO]]])
+
m4_define([DUMMY_ADAPTER],
[[[dummy], [Dummy Adapter], [DUMMY]]])
@@ -249,34 +268,21 @@ AS_IF([test "x$enable_gcov" = "xyes"], [
AC_DEFINE([USE_GCOV], [0], [0 to leave coverage collection disabled.])
])
-# set default verbose options, overridden by following options
-debug_usb_io=no
+# set default for debug_usb_comms, overridden by following options
debug_usb_comms=no
AC_ARG_ENABLE([verbose],
AS_HELP_STRING([--enable-verbose],
[Enable verbose JTAG I/O messages (for debugging).]),
[
- debug_usb_io=$enableval
debug_usb_comms=$enableval
], [])
-AC_ARG_ENABLE([verbose_usb_io],
- AS_HELP_STRING([--enable-verbose-usb-io],
- [Enable verbose USB I/O messages (for debugging)]),
- [debug_usb_io=$enableval], [])
-
AC_ARG_ENABLE([verbose_usb_comms],
AS_HELP_STRING([--enable-verbose-usb-comms],
[Enable verbose USB communication messages (for debugging)]),
[debug_usb_comms=$enableval], [])
-AC_MSG_CHECKING([whether to enable verbose USB I/O messages]);
-AC_MSG_RESULT([$debug_usb_io])
-AS_IF([test "x$debug_usb_io" = "xyes"], [
- AC_DEFINE([_DEBUG_USB_IO_],[1], [Print verbose USB I/O messages])
-])
-
AC_MSG_CHECKING([whether to enable verbose USB communication messages]);
AC_MSG_RESULT([$debug_usb_comms])
AS_IF([test "x$debug_usb_comms" = "xyes"], [
@@ -295,20 +301,16 @@ AS_IF([test "x$debug_malloc" = "xyes" -a "x$have_glibc" = "xyes"], [
AC_DEFINE([_DEBUG_FREE_SPACE_],[1], [Include malloc free space in logging])
])
-AC_ARG_ENABLE([dmem],
- AS_HELP_STRING([--enable-dmem], [Enable building the dmem driver]),
- [build_dmem=$enableval], [build_dmem=no])
-
m4_define([AC_ARG_ADAPTERS], [
- m4_foreach([adapter], [$1],
- [AC_ARG_ENABLE(ADAPTER_OPT([adapter]),
- AS_HELP_STRING([--enable-ADAPTER_OPT([adapter])[[[=yes/no/auto]]]],
- [Enable building support for the ]ADAPTER_DESC([adapter])[ (default is $2)]),
+ m4_foreach([adapter_driver], [$1],
+ [AC_ARG_ENABLE(ADAPTER_OPT([adapter_driver]),
+ AS_HELP_STRING([--enable-ADAPTER_OPT([adapter_driver])[[[=yes/no/auto]]]],
+ [Enable building support for the ]ADAPTER_DESC([adapter_driver])[ (default is $2)]),
[case "${enableval}" in
yes|no|auto) ;;
- *) AC_MSG_ERROR([Option --enable-ADAPTER_OPT([adapter]) has invalid value "${enableval}".]) ;;
+ *) AC_MSG_ERROR([Option --enable-ADAPTER_OPT([adapter_driver]) has invalid value "${enableval}".]) ;;
esac],
- [ADAPTER_VAR([adapter])=$2])
+ [ADAPTER_VAR([adapter_driver])=$2])
])
])
@@ -319,6 +321,7 @@ AC_ARG_ADAPTERS([
LIBFTDI_ADAPTERS,
LIBFTDI_USB1_ADAPTERS,
LIBGPIOD_ADAPTERS,
+ DMEM_ADAPTER,
SYSFSGPIO_ADAPTER,
REMOTE_BITBANG_ADAPTER,
LINUXSPIDEV_ADAPTER,
@@ -328,14 +331,25 @@ AC_ARG_ADAPTERS([
JTAG_DPI_ADAPTER,
JTAG_VPI_ADAPTER,
RSHIM_ADAPTER,
- AMTJTAGACCEL_ADAPTER,
- PCIE_ADAPTERS,
- LIBJAYLINK_ADAPTERS
+ XVC_ADAPTERS,
+ LIBJAYLINK_ADAPTERS,
+ CMSIS_DAP_TCP_ADAPTER
],[auto])
-AC_ARG_ENABLE([parport],
- AS_HELP_STRING([--enable-parport], [Enable building the pc parallel port driver]),
- [build_parport=$enableval], [build_parport=no])
+AC_ARG_ADAPTERS([
+ PARALLEL_PORT_ADAPTER,
+ AMTJTAGACCEL_ADAPTER
+ ],[no])
+
+# The following adapters use bitbanging and can actually be built on all architectures,
+# which is useful to verify that they still build fine.
+# We could enable them automatically only on the architectures where they actually occur:
+# HOST_ARM_BITBANG_ADAPTERS: when ${host_cpu} matches arm*
+# HOST_ARM_OR_AARCH64_BITBANG_ADAPTERS: when ${host_cpu} matches arm*|aarch64
+# However, conditionally changing the meaning of 'auto' requires
+# a more flexible logic around.
+AC_ARG_ADAPTERS([HOST_ARM_BITBANG_ADAPTERS],[no])
+AC_ARG_ADAPTERS([HOST_ARM_OR_AARCH64_BITBANG_ADAPTERS],[no])
AC_ARG_ENABLE([parport_ppdev],
AS_HELP_STRING([--disable-parport-ppdev],
@@ -344,42 +358,9 @@ AC_ARG_ENABLE([parport_ppdev],
AC_ARG_ENABLE([parport_giveio],
AS_HELP_STRING([--enable-parport-giveio],
- [Enable use of giveio for parport (for CygWin only)]),
+ [Enable use of giveio for parport (deprecated, for CygWin only)]),
[parport_use_giveio=$enableval], [parport_use_giveio=])
-AS_CASE(["${host_cpu}"],
- [arm*|aarch64], [
- AC_ARG_ENABLE([bcm2835gpio],
- AS_HELP_STRING([--enable-bcm2835gpio], [Enable building support for bitbanging on BCM2835 (as found in Raspberry Pi)]),
- [build_bcm2835gpio=$enableval], [build_bcm2835gpio=no])
- AC_ARG_ENABLE([imx_gpio],
- AS_HELP_STRING([--enable-imx_gpio], [Enable building support for bitbanging on NXP IMX processors]),
- [build_imx_gpio=$enableval], [build_imx_gpio=no])
- AC_ARG_ENABLE([am335xgpio],
- AS_HELP_STRING([--enable-am335xgpio], [Enable building support for bitbanging on AM335x (as found in Beaglebones)]),
- [build_am335xgpio=$enableval], [build_am335xgpio=no])
- ],
- [
- build_bcm2835gpio=no
- build_imx_gpio=no
- build_am335xgpio=no
-])
-
-AS_CASE(["${host_cpu}"],
- [arm*], [
- AC_ARG_ENABLE([ep93xx],
- AS_HELP_STRING([--enable-ep93xx], [Enable building support for EP93xx based SBCs]),
- [build_ep93xx=$enableval], [build_ep93xx=no])
-
- AC_ARG_ENABLE([at91rm9200],
- AS_HELP_STRING([--enable-at91rm9200], [Enable building support for AT91RM9200 based SBCs]),
- [build_at91rm9200=$enableval], [build_at91rm9200=no])
- ],
- [
- build_ep93xx=no
- build_at91rm9200=no
-])
-
AC_ARG_ENABLE([gw16012],
AS_HELP_STRING([--enable-gw16012], [Enable building support for the Gateworks GW16012 JTAG Programmer]),
[build_gw16012=$enableval], [build_gw16012=no])
@@ -401,7 +382,7 @@ AS_CASE([$host_os],
])
])
- AS_IF([test "x$build_dmem" = "xyes"], [
+ AS_IF([test "x$enable_dmem" = "xyes"], [
AC_MSG_ERROR([dmem is only available on linux])
])
])
@@ -423,9 +404,8 @@ AS_CASE(["${host_cpu}"],
[i?86|x86*], [],
[
AS_IF([test "x$parport_use_ppdev" = "xno"], [
- AC_MSG_WARN([--disable-parport-ppdev is not supported by the host CPU])
+ AC_MSG_ERROR([--disable-parport-ppdev is not supported by the host CPU])
])
- parport_use_ppdev=yes
])
can_build_buspirate=yes
@@ -446,7 +426,7 @@ AS_CASE([$host_os],
], [
is_cygwin=yes
# sys/io.h needed under cygwin for parport access
- AS_IF([test "x$build_parport" = "xyes"], [
+ AS_IF([test "x$enable_parport" != "xno"], [
AC_CHECK_HEADERS([sys/io.h],[],AC_MSG_ERROR([Please install the cygwin ioperm package]))
])
])
@@ -509,58 +489,10 @@ AS_IF([test "x$is_darwin" = "xyes"], [
AC_DEFINE([IS_DARWIN], [0], [0 if not building for Darwin.])
])
-AS_IF([test "x$build_parport" = "xyes"], [
- build_bitbang=yes
- AC_DEFINE([BUILD_PARPORT], [1], [1 if you want parport.])
-], [
- AC_DEFINE([BUILD_PARPORT], [0], [0 if you don't want parport.])
-])
-
-AS_IF([test "x$build_dmem" = "xyes"], [
- AC_DEFINE([BUILD_DMEM], [1], [1 if you want to debug via Direct Mem.])
-], [
- AC_DEFINE([BUILD_DMEM], [0], [0 if you don't want to debug via Direct Mem.])
-])
-
AS_IF([test "x$ADAPTER_VAR([dummy])" != "xno"], [
build_bitbang=yes
])
-AS_IF([test "x$build_ep93xx" = "xyes"], [
- build_bitbang=yes
- AC_DEFINE([BUILD_EP93XX], [1], [1 if you want ep93xx.])
-], [
- AC_DEFINE([BUILD_EP93XX], [0], [0 if you don't want ep93xx.])
-])
-
-AS_IF([test "x$build_at91rm9200" = "xyes"], [
- build_bitbang=yes
- AC_DEFINE([BUILD_AT91RM9200], [1], [1 if you want at91rm9200.])
-], [
- AC_DEFINE([BUILD_AT91RM9200], [0], [0 if you don't want at91rm9200.])
-])
-
-AS_IF([test "x$build_bcm2835gpio" = "xyes"], [
- build_bitbang=yes
- AC_DEFINE([BUILD_BCM2835GPIO], [1], [1 if you want bcm2835gpio.])
-], [
- AC_DEFINE([BUILD_BCM2835GPIO], [0], [0 if you don't want bcm2835gpio.])
-])
-
-AS_IF([test "x$build_imx_gpio" = "xyes"], [
- build_bitbang=yes
- AC_DEFINE([BUILD_IMX_GPIO], [1], [1 if you want imx_gpio.])
-], [
- AC_DEFINE([BUILD_IMX_GPIO], [0], [0 if you don't want imx_gpio.])
-])
-
-AS_IF([test "x$build_am335xgpio" = "xyes"], [
- build_bitbang=yes
- AC_DEFINE([BUILD_AM335XGPIO], [1], [1 if you want am335xgpio.])
-], [
- AC_DEFINE([BUILD_AM335XGPIO], [0], [0 if you don't want am335xgpio.])
-])
-
AS_IF([test "x$parport_use_ppdev" = "xyes"], [
AC_DEFINE([PARPORT_USE_PPDEV], [1], [1 if you want parport to use ppdev.])
], [
@@ -653,11 +585,19 @@ PKG_CHECK_MODULES([LIBFTDI], [libftdi1], [
PKG_CHECK_MODULES([LIBFTDI], [libftdi], [use_libftdi=yes], [use_libftdi=no])
])
-PKG_CHECK_MODULES([LIBGPIOD], [libgpiod < 2.0], [
+PKG_CHECK_MODULES([LIBGPIOD], [libgpiod >= 2.0] , [
use_libgpiod=yes
- PKG_CHECK_EXISTS([libgpiod >= 1.5],
- [AC_DEFINE([HAVE_LIBGPIOD1_FLAGS_BIAS], [1], [define if libgpiod v1 has line request flags bias])])
-], [use_libgpiod=no])
+], [
+ PKG_CHECK_MODULES([LIBGPIOD], [libgpiod], [
+ use_libgpiod=yes
+ AC_DEFINE([HAVE_LIBGPIOD_V1], [1], [define if libgpiod is version v1.x])
+
+ PKG_CHECK_EXISTS([libgpiod >= 1.5],
+ [AC_DEFINE([HAVE_LIBGPIOD1_FLAGS_BIAS], [1], [define if libgpiod v1 has line request flags bias])])
+ ], [
+ use_libgpiod=no
+ ])
+])
PKG_CHECK_MODULES([LIBJAYLINK], [libjaylink >= 0.2],
[use_libjaylink=yes], [use_libjaylink=no])
@@ -668,21 +608,24 @@ PKG_CHECK_MODULES([LIBJAYLINK], [libjaylink >= 0.2],
# Arg $3: What prerequisites are missing, to be shown in an error message
# if an adapter was requested but cannot be enabled.
m4_define([PROCESS_ADAPTERS], [
- m4_foreach([adapter], [$1], [
+ m4_foreach([adapter_driver], [$1], [
AS_IF([test $2], [
- AS_IF([test "x$ADAPTER_VAR([adapter])" != "xno"], [
- AC_DEFINE([BUILD_]ADAPTER_SYM([adapter]), [1], [1 if you want the ]ADAPTER_DESC([adapter]).)
+ AS_IF([test "x$ADAPTER_VAR([adapter_driver])" != "xno"], [
+ AC_DEFINE([BUILD_]ADAPTER_SYM([adapter_driver]), [1],
+ [1 if you want the ]ADAPTER_DESC([adapter_driver]).)
], [
- AC_DEFINE([BUILD_]ADAPTER_SYM([adapter]), [0], [0 if you do not want the ]ADAPTER_DESC([adapter]).)
+ AC_DEFINE([BUILD_]ADAPTER_SYM([adapter_driver]), [0],
+ [0 if you do not want the ]ADAPTER_DESC([adapter_driver]).)
])
], [
- AS_IF([test "x$ADAPTER_VAR([adapter])" = "xyes"], [
- AC_MSG_ERROR([$3 is required for [adapter] "ADAPTER_DESC([adapter])".])
+ AS_IF([test "x$ADAPTER_VAR([adapter_driver])" = "xyes"], [
+ AC_MSG_ERROR([$3 is required for [adapter_driver] "ADAPTER_DESC([adapter_driver])".])
])
- ADAPTER_VAR([adapter])=no
- AC_DEFINE([BUILD_]ADAPTER_SYM([adapter]), [0], [0 if you do not want the ]ADAPTER_DESC([adapter]).)
+ ADAPTER_VAR([adapter_driver])=no
+ AC_DEFINE([BUILD_]ADAPTER_SYM([adapter_driver]), [0],
+ [0 if you do not want the ]ADAPTER_DESC([adapter_driver]).)
])
- AM_CONDITIONAL(ADAPTER_SYM([adapter]), [test "x$ADAPTER_VAR([adapter])" != "xno"])
+ AM_CONDITIONAL(ADAPTER_SYM([adapter_driver]), [test "x$ADAPTER_VAR([adapter_driver])" != "xno"])
])
])
@@ -692,19 +635,27 @@ PROCESS_ADAPTERS([HIDAPI_USB1_ADAPTERS], ["x$use_hidapi" = "xyes" -a "x$use_libu
PROCESS_ADAPTERS([LIBFTDI_ADAPTERS], ["x$use_libftdi" = "xyes"], [libftdi])
PROCESS_ADAPTERS([LIBFTDI_USB1_ADAPTERS], ["x$use_libftdi" = "xyes" -a "x$use_libusb1" = "xyes"], [libftdi and libusb-1.x])
PROCESS_ADAPTERS([LIBGPIOD_ADAPTERS], ["x$use_libgpiod" = "xyes"], [Linux libgpiod])
+PROCESS_ADAPTERS([DMEM_ADAPTER], ["x$is_linux" = "xyes" -a "x$ac_cv_header_sys_mman_h" = "xyes"], [Linux /dev/mem])
PROCESS_ADAPTERS([SYSFSGPIO_ADAPTER], ["x$is_linux" = "xyes"], [Linux sysfs])
PROCESS_ADAPTERS([REMOTE_BITBANG_ADAPTER], [true], [unused])
+PROCESS_ADAPTERS([CMSIS_DAP_TCP_ADAPTER], [true], [unused])
PROCESS_ADAPTERS([LIBJAYLINK_ADAPTERS], ["x$use_internal_libjaylink" = "xyes" -o "x$use_libjaylink" = "xyes"], [libjaylink-0.2])
-PROCESS_ADAPTERS([PCIE_ADAPTERS], ["x$is_linux" = "xyes"], [Linux build])
+PROCESS_ADAPTERS([XVC_ADAPTERS],
+ ["x$is_linux" = "xyes" -a "x$ac_cv_header_linux_pci_h" = "xyes" -a "x$ac_cv_header_sys_mman_h" = "xyes"],
+ [Linux build with headers linux/pci.h and sys/mman.h])
PROCESS_ADAPTERS([SERIAL_PORT_ADAPTERS], ["x$can_build_buspirate" = "xyes"],
[internal error: validation should happen beforehand])
-PROCESS_ADAPTERS([LINUXSPIDEV_ADAPTER], ["x$is_linux" = "xyes"], [Linux spidev])
+PROCESS_ADAPTERS([PARALLEL_PORT_ADAPTER], [true], [unused])
+PROCESS_ADAPTERS([LINUXSPIDEV_ADAPTER], ["x$is_linux" = "xyes" -a "x$ac_cv_header_linux_spi_spidev_h" = "xyes"],
+ [Linux spidev])
PROCESS_ADAPTERS([VDEBUG_ADAPTER], [true], [unused])
PROCESS_ADAPTERS([JTAG_DPI_ADAPTER], [true], [unused])
PROCESS_ADAPTERS([JTAG_VPI_ADAPTER], [true], [unused])
PROCESS_ADAPTERS([RSHIM_ADAPTER], ["x$can_build_rshim" = "xyes"],
[internal error: validation should happen beforehand])
PROCESS_ADAPTERS([AMTJTAGACCEL_ADAPTER], [true], [unused])
+PROCESS_ADAPTERS([HOST_ARM_BITBANG_ADAPTERS], ["x$ac_cv_header_sys_mman_h" = "xyes"], [header sys/mman.h])
+PROCESS_ADAPTERS([HOST_ARM_OR_AARCH64_BITBANG_ADAPTERS], ["x$ac_cv_header_sys_mman_h" = "xyes"], [header sys/mman.h])
PROCESS_ADAPTERS([DUMMY_ADAPTER], [true], [unused])
AS_IF([test "x$enable_linuxgpiod" != "xno"], [
@@ -719,6 +670,26 @@ AS_IF([test "x$enable_remote_bitbang" != "xno"], [
build_bitbang=yes
])
+AS_IF([test "x$enable_bcm2835gpio" != "xno"], [
+ build_bitbang=yes
+])
+
+AS_IF([test "x$enable_imx_gpio" != "xno"], [
+ build_bitbang=yes
+])
+
+AS_IF([test "x$enable_am335xgpio" != "xno"], [
+ build_bitbang=yes
+])
+
+AS_IF([test "x$enable_ep93xx" != "xno"], [
+ build_bitbang=yes
+])
+
+AS_IF([test "x$enable_at91rm9200" != "xno"], [
+ build_bitbang=yes
+])
+
AS_IF([test "x$enable_stlink" != "xno" -o "x$enable_ti_icdi" != "xno" -o "x$enable_nulink" != "xno"], [
AC_DEFINE([BUILD_HLADAPTER], [1], [1 if you want the High Level JTAG driver.])
AM_CONDITIONAL([HLADAPTER], [true])
@@ -729,6 +700,8 @@ AS_IF([test "x$enable_stlink" != "xno" -o "x$enable_ti_icdi" != "xno" -o "x$enab
AM_CONDITIONAL([HLADAPTER_STLINK], [test "x$enable_stlink" != "xno"])
AM_CONDITIONAL([HLADAPTER_ICDI], [test "x$enable_ti_icdi" != "xno"])
AM_CONDITIONAL([HLADAPTER_NULINK], [test "x$enable_nulink" != "xno"])
+AM_CONDITIONAL([CMSIS_DAP_CORE],
+ [test "x$enable_cmsis_dap" != "xno" -o "x$enable_cmsis_dap_v2" != "xno" -o "x$enable_cmsis_dap_tcp" != "xno"])
AS_IF([test "x$enable_jlink" != "xno"], [
AS_IF([test "x$use_internal_libjaylink" = "xyes"], [
@@ -752,13 +725,7 @@ AS_IF([test "x$enable_esp_usb_jtag" != "xno"], [
])
AM_CONDITIONAL([RELEASE], [test "x$build_release" = "xyes"])
-AM_CONDITIONAL([PARPORT], [test "x$build_parport" = "xyes"])
AM_CONDITIONAL([GIVEIO], [test "x$parport_use_giveio" = "xyes"])
-AM_CONDITIONAL([EP93XX], [test "x$build_ep93xx" = "xyes"])
-AM_CONDITIONAL([AT91RM9200], [test "x$build_at91rm9200" = "xyes"])
-AM_CONDITIONAL([BCM2835GPIO], [test "x$build_bcm2835gpio" = "xyes"])
-AM_CONDITIONAL([IMX_GPIO], [test "x$build_imx_gpio" = "xyes"])
-AM_CONDITIONAL([AM335XGPIO], [test "x$build_am335xgpio" = "xyes"])
AM_CONDITIONAL([BITBANG], [test "x$build_bitbang" = "xyes"])
AM_CONDITIONAL([USB_BLASTER_DRIVER], [test "x$enable_usb_blaster" != "xno" -o "x$enable_usb_blaster_2" != "xno"])
AM_CONDITIONAL([GW16012], [test "x$build_gw16012" = "xyes"])
@@ -772,13 +739,13 @@ AM_CONDITIONAL([USE_LIBFTDI], [test "x$use_libftdi" = "xyes"])
AM_CONDITIONAL([USE_LIBGPIOD], [test "x$use_libgpiod" = "xyes"])
AM_CONDITIONAL([USE_HIDAPI], [test "x$use_hidapi" = "xyes"])
AM_CONDITIONAL([USE_LIBJAYLINK], [test "x$use_libjaylink" = "xyes"])
-AM_CONDITIONAL([DMEM], [test "x$build_dmem" = "xyes"])
AM_CONDITIONAL([HAVE_CAPSTONE], [test "x$enable_capstone" != "xno"])
AM_CONDITIONAL([INTERNAL_JIMTCL], [test "x$use_internal_jimtcl" = "xyes"])
AM_CONDITIONAL([HAVE_JIMTCL_PKG_CONFIG], [test "x$have_jimtcl_pkg_config" = "xyes"])
AM_CONDITIONAL([INTERNAL_LIBJAYLINK], [test "x$use_internal_libjaylink" = "xyes"])
+
AM_CONDITIONAL([USE_GCOV], [test "x$enable_gcov" = "xyes"])
# Look for environ alternatives. Possibility #1: is environ in unistd.h or stdlib.h?
@@ -836,7 +803,9 @@ AS_IF([test "x$gcc_warnings" = "xyes"], [
AC_SUBST(EXTRA_DIST_NEWS, ["$(echo $srcdir/NEWS-*)"])
AC_CONFIG_FILES([
- Makefile
+ Makefile \
+ testing/Makefile \
+ testing/tcl_commands/Makefile
])
AC_OUTPUT
@@ -850,28 +819,51 @@ AS_IF([test "x$use_internal_jimtcl" = "xyes"], [
AC_MSG_WARN([Using the internal jimtcl is deprecated and will not be possible in the future.])
])
+AS_IF([test "x$enable_amtjtagaccel" != "xno"], [
+ echo
+ echo
+ AC_MSG_WARN([Amontec JTAG-Accelerator adapter is deprecated and support will be removed in the next release!])
+])
+AS_IF([test "x$build_gw16012" = "xyes"], [
+ echo
+ echo
+ AC_MSG_WARN([Gateworks GW16012 JTAG adapter is deprecated and support will be removed in the next release!])
+])
+
+AS_IF([test "x$parport_use_giveio" = "xyes" || test [ "x$enable_parport" != "xno" -a "x$parport_use_ppdev" = "xno"]], [
+ echo
+ echo
+ AC_MSG_WARN([Parallel port access with direct I/O is deprecated and support will be removed in the next release!])
+])
+
echo
echo
echo OpenOCD configuration summary
echo ---------------------------------------------------
-m4_foreach([adapter], [USB1_ADAPTERS,
+m4_foreach([adapter_driver], [USB1_ADAPTERS,
HIDAPI_ADAPTERS, HIDAPI_USB1_ADAPTERS, LIBFTDI_ADAPTERS,
LIBFTDI_USB1_ADAPTERS,
LIBGPIOD_ADAPTERS,
+ DMEM_ADAPTER,
SYSFSGPIO_ADAPTER,
REMOTE_BITBANG_ADAPTER,
- LIBJAYLINK_ADAPTERS, PCIE_ADAPTERS, SERIAL_PORT_ADAPTERS,
+ LIBJAYLINK_ADAPTERS, XVC_ADAPTERS,
+ SERIAL_PORT_ADAPTERS,
+ PARALLEL_PORT_ADAPTER,
LINUXSPIDEV_ADAPTER,
VDEBUG_ADAPTER,
JTAG_DPI_ADAPTER,
JTAG_VPI_ADAPTER,
RSHIM_ADAPTER,
AMTJTAGACCEL_ADAPTER,
+ HOST_ARM_BITBANG_ADAPTERS,
+ HOST_ARM_OR_AARCH64_BITBANG_ADAPTERS,
+ CMSIS_DAP_TCP_ADAPTER,
DUMMY_ADAPTER,
OPTIONAL_LIBRARIES,
COVERAGE],
- [s=m4_format(["%-41s"], ADAPTER_DESC([adapter]))
- AS_CASE([$ADAPTER_VAR([adapter])],
+ [s=m4_format(["%-49s"], ADAPTER_DESC([adapter_driver]))
+ AS_CASE([$ADAPTER_VAR([adapter_driver])],
[auto], [
echo "$s"yes '(auto)'
],
@@ -883,8 +875,8 @@ m4_foreach([adapter], [USB1_ADAPTERS,
],
[
AC_MSG_ERROR(m4_normalize([
- Error in [adapter] "ADAPTER_ARG([adapter])": Variable "ADAPTER_VAR([adapter])"
- has invalid value "$ADAPTER_VAR([adapter])".]))
+ Error in [adapter_driver] "ADAPTER_ARG([adapter_driver])": Variable "ADAPTER_VAR([adapter_driver])"
+ has invalid value "$ADAPTER_VAR([adapter_driver])".]))
])
])
echo
diff --git a/contrib/60-openocd.rules b/contrib/60-openocd.rules
index 29f8d7a6d4..151b4e2c06 100644
--- a/contrib/60-openocd.rules
+++ b/contrib/60-openocd.rules
@@ -190,6 +190,10 @@ ATTRS{idVendor}=="138e", ATTRS{idProduct}=="9000", MODE="660", GROUP="plugdev",
# Debug Board for Neo1973
ATTRS{idVendor}=="1457", ATTRS{idProduct}=="5118", MODE="660", GROUP="plugdev", TAG+="uaccess"
+# Microchip RISC-V Debug
+ATTRS{idVendor}=="1514", ATTRS{idProduct}=="2008", MODE="660", GROUP="plugdev", TAG+="uaccess"
+ATTRS{idVendor}=="1514", ATTRS{idProduct}=="200a", MODE="660", GROUP="plugdev", TAG+="uaccess"
+
# OSBDM
ATTRS{idVendor}=="15a2", ATTRS{idProduct}=="0042", MODE="660", GROUP="plugdev", TAG+="uaccess"
ATTRS{idVendor}=="15a2", ATTRS{idProduct}=="0058", MODE="660", GROUP="plugdev", TAG+="uaccess"
@@ -216,6 +220,11 @@ ATTRS{idVendor}=="16c0", ATTRS{idProduct}=="06ad", MODE="660", GROUP="plugdev",
# USBprog with OpenOCD firmware
ATTRS{idVendor}=="1781", ATTRS{idProduct}=="0c63", MODE="660", GROUP="plugdev", TAG+="uaccess"
+# WCH CH347T chip in mode 3
+ATTRS{idVendor}=="1a86", ATTRS{idProduct}=="55dd", MODE="660", GROUP="plugdev", TAG+="uaccess"
+# WCH CH347F chip
+ATTRS{idVendor}=="1a86", ATTRS{idProduct}=="55de", MODE="660", GROUP="plugdev", TAG+="uaccess"
+
# TI/Luminary Stellaris In-Circuit Debug Interface (ICDI) Board
ATTRS{idVendor}=="1cbe", ATTRS{idProduct}=="00fd", MODE="660", GROUP="plugdev", TAG+="uaccess"
@@ -248,8 +257,6 @@ ATTRS{idVendor}=="303a", ATTRS{idProduct}=="1002", MODE="660", GROUP="plugdev",
# ANGIE USB-JTAG Adapter
ATTRS{idVendor}=="584e", ATTRS{idProduct}=="414f", MODE="660", GROUP="plugdev", TAG+="uaccess"
ATTRS{idVendor}=="584e", ATTRS{idProduct}=="424e", MODE="660", GROUP="plugdev", TAG+="uaccess"
-ATTRS{idVendor}=="584e", ATTRS{idProduct}=="4255", MODE="660", GROUP="plugdev", TAG+="uaccess"
-ATTRS{idVendor}=="584e", ATTRS{idProduct}=="4355", MODE="660", GROUP="plugdev", TAG+="uaccess"
ATTRS{idVendor}=="584e", ATTRS{idProduct}=="4a55", MODE="660", GROUP="plugdev", TAG+="uaccess"
# Marvell Sheevaplug
diff --git a/contrib/firmware/angie/c/Makefile b/contrib/firmware/angie/c/Makefile
index 1bcc1f7d1e..21873da6bf 100644
--- a/contrib/firmware/angie/c/Makefile
+++ b/contrib/firmware/angie/c/Makefile
@@ -38,10 +38,8 @@ 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 i2c.rel
+OBJECTS = main.rel usb.rel delay.rel USBJmpTb.rel gpif.rel i2c.rel serial.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 \
diff --git a/contrib/firmware/angie/c/include/i2c.h b/contrib/firmware/angie/c/include/i2c.h
index d0404923b3..7a199c15a5 100644
--- a/contrib/firmware/angie/c/include/i2c.h
+++ b/contrib/firmware/angie/c/include/i2c.h
@@ -14,6 +14,7 @@
#include
#include
+bool get_status(void);
void start_cd(void);
void repeated_start(void);
void stop_cd(void);
diff --git a/contrib/firmware/angie/c/include/io.h b/contrib/firmware/angie/c/include/io.h
index 19289d11d8..447aec3b4c 100644
--- a/contrib/firmware/angie/c/include/io.h
+++ b/contrib/firmware/angie/c/include/io.h
@@ -14,44 +14,26 @@
#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 */
+#define PIN_SDA_DIR IOA0
/* PA1 Not Connected */
-#define PIN_RDWR_B IOA2
-#define PIN_CSI_B IOA3
-#define PIN_INIT_B IOA4
-#define PIN_PROGRAM_B IOA5
+#define PIN_RDWR_B IOA2
+#define PIN_SDA IOA3
+#define PIN_SCL 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
+/* PB0 Not Connected */
+/* PB1 Not Connected */
+/* PB2 Not Connected */
+/* PB3 Not Connected */
+/* PB4 Not Connected */
+/* PB5 Not Connected */
/* PB6 Not Connected */
/* PB7 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 */
#define PIN_T0 IOC0
#define PIN_T1 IOC1
@@ -63,10 +45,10 @@
/* PC7 Not Connected */
/* PORT D */
-#define PIN_SDA IOD0
-#define PIN_SCL IOD1
-#define PIN_SDA_DIR IOD2
-#define PIN_SCL_DIR IOD3
+/* PD0 Not Connected */
+/* PD1 Not Connected */
+/* PD2 Not Connected */
+/* PD3 Not Connected */
/* PD4 Not Connected */
/* PD5 Not Connected */
/* PD6 Not Connected */
diff --git a/contrib/firmware/angie/c/include/jtag.h b/contrib/firmware/angie/c/include/jtag.h
deleted file mode 100644
index 6d5df64805..0000000000
--- a/contrib/firmware/angie/c/include/jtag.h
+++ /dev/null
@@ -1,31 +0,0 @@
-/* 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. *
- *
- *
-*****************************************************************************/
-
-#ifndef __JTAG_H
-#define __JTAG_H
-
-#include
-
-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
diff --git a/contrib/firmware/angie/c/include/protocol.h b/contrib/firmware/angie/c/include/protocol.h
deleted file mode 100644
index a12644b27d..0000000000
--- a/contrib/firmware/angie/c/include/protocol.h
+++ /dev/null
@@ -1,20 +0,0 @@
-/* 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. *
- *
- *
-*****************************************************************************/
-
-#ifndef __PROTOCOL_H
-#define __PROTOCOL_H
-
-#include
-
-bool execute_command(void);
-void command_loop(void);
-
-#endif
diff --git a/contrib/firmware/angie/c/include/reg_ezusb.h b/contrib/firmware/angie/c/include/reg_ezusb.h
index c22476a1a6..735ccaa8a7 100644
--- a/contrib/firmware/angie/c/include/reg_ezusb.h
+++ b/contrib/firmware/angie/c/include/reg_ezusb.h
@@ -634,10 +634,10 @@ SFRX(CT4, 0xE6FE);
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);
+SFRX(EP2FIFOBUF[1024], 0xF000);
+SFRX(EP4FIFOBUF[1024], 0xF400);
+SFRX(EP6FIFOBUF[1024], 0xF800);
+SFRX(EP8FIFOBUF[1024], 0xFC00);
/* Error Correction Code (ECC) Registers (FX2LP/FX1 only) */
SFRX(ECCCFG, 0xE628);
diff --git a/contrib/firmware/angie/c/include/usb.h b/contrib/firmware/angie/c/include/usb.h
index ad8be787e4..dbf41fe8e5 100644
--- a/contrib/firmware/angie/c/include/usb.h
+++ b/contrib/firmware/angie/c/include/usb.h
@@ -104,7 +104,7 @@ struct usb_endpoint_descriptor {
struct usb_language_descriptor {
uint8_t blength; /**< Size of this descriptor in bytes. */
uint8_t bdescriptortype; /**< STRING descriptor type. */
- uint16_t wlangid[]; /**< LANGID codes. */
+ uint16_t wlangid; /**< LANGID codes. */
};
/** USB String Descriptor. See USB 2.0 Spec */
@@ -125,12 +125,6 @@ struct setup_data {
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 bool ep6_out;
-
extern volatile __xdata __at 0xE6B8 struct setup_data setup_data;
/*
@@ -278,8 +272,8 @@ 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 usb_handle_i2c_in(void);
-void usb_handle_i2c_out(void);
+bool usb_handle_vcommands(void);
+void set_gpif_cnt(uint32_t count);
void i2c_recieve(void);
void ep_init(void);
diff --git a/contrib/firmware/angie/c/src/gpif.c b/contrib/firmware/angie/c/src/gpif.c
index f4028be400..0e0d01300d 100644
--- a/contrib/firmware/angie/c/src/gpif.c
+++ b/contrib/firmware/angie/c/src/gpif.c
@@ -19,15 +19,15 @@ const char wavedata[128] = {
/* Output*/ 0x04, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
/* LFun */ 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F,
// Wave 1
-/* LenBr */ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x07,
-/* Opcode*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* Output*/ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
-/* LFun */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F,
+/* LenBr */ 0x01, 0x3F, 0x01, 0x01, 0x01, 0x01, 0x01, 0x07,
+/* Opcode*/ 0x02, 0x07, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00,
+/* Output*/ 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+/* LFun */ 0x00, 0x09, 0x00, 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*/ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
-/* LFun */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F,
+/* LenBr */ 0x01, 0xBF, 0x01, 0x01, 0x01, 0x01, 0x01, 0x07,
+/* Opcode*/ 0x06, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+/* Output*/ 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+/* LFun */ 0x00, 0x09, 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,
@@ -47,7 +47,7 @@ const char flowstates[36] = {
/* DO NOT EDIT ... */
const char initdata[7] = {
-/* Regs */ 0xE0, 0x00, 0x00, 0x07, 0xEE, 0xF2, 0x00
+/* Regs */ 0xE0, 0x00, 0x00, 0x03, 0xEE, 0xF1, 0x00
};
/* END DO NOT EDIT */
diff --git a/contrib/firmware/angie/c/src/i2c.c b/contrib/firmware/angie/c/src/i2c.c
index 10a463bf7d..4cf82955fc 100644
--- a/contrib/firmware/angie/c/src/i2c.c
+++ b/contrib/firmware/angie/c/src/i2c.c
@@ -12,14 +12,26 @@
#include "delay.h"
#include "reg_ezusb.h"
+bool get_status(void)
+{
+ PIN_SDA_DIR = 1;
+ OEA = 0xF7;
+ delay_us(1);
+ bool sda_state = PIN_SDA;
+ PIN_T0 = sda_state;
+ delay_us(1);
+ OEA = 0xFF;
+ delay_us(1);
+ return sda_state;
+}
+
void start_cd(void)
{
- PIN_SCL_DIR = 0;
- PIN_SDA_DIR = 0;
+ PIN_SDA_DIR = 0; // SP6 SDA: OUT
delay_us(10);
- PIN_SDA = 0; //SDA = 1;
+ PIN_SDA = 0;
delay_us(1);
- PIN_SCL = 0; //SCL = 1;
+ PIN_SCL = 0;
delay_us(1);
}
@@ -43,9 +55,7 @@ void stop_cd(void)
delay_us(1);
PIN_SDA = 1;
delay_us(1);
- PIN_SDA_DIR = 1;
- delay_us(1);
- PIN_SCL_DIR = 1;
+ PIN_SDA_DIR = 1; // SP6 SDA: IN
delay_us(1);
}
@@ -79,16 +89,16 @@ void send_nack(void)
bool get_ack(void)
{
- PIN_SDA_DIR = 1;
+ PIN_SDA_DIR = 1; // SP6 SDA: IN
delay_us(1);
- OED = 0xFE;
+ OEA = 0xF7; // FX2 SDA: IN
PIN_SCL = 1;
delay_us(1);
bool ack = PIN_SDA;
PIN_SCL = 0;
delay_us(1);
- OED = 0xFF;
- PIN_SDA_DIR = 0;
+ OEA = 0xFF; // FX2 SDA: OUT
+ PIN_SDA_DIR = 0; // SP6 SDA: OUT
delay_us(1);
return ack;
}
@@ -123,8 +133,8 @@ void send_byte(uint8_t input)
uint8_t receive_byte(void)
{
- PIN_SDA_DIR = 1; //FX2 <-- FPGA
- OED = 0xFE;
+ PIN_SDA_DIR = 1; // SP6 SDA: IN
+ OEA = 0xF7; // FX2 SDA: IN
uint8_t input = 0x00;
for (uint8_t i = 0; i < 8; i++) {
PIN_SCL = 1;
@@ -138,7 +148,7 @@ uint8_t receive_byte(void)
PIN_SCL = 0;
delay_us(1);
}
- OED = 0xFF;
- PIN_SDA_DIR = 0;
+ OEA = 0xFF; // FX2 SDA: OUT
+ PIN_SDA_DIR = 0; // SP6 SDA: OUT
return input;
}
diff --git a/contrib/firmware/angie/c/src/jtag.c b/contrib/firmware/angie/c/src/jtag.c
deleted file mode 100644
index 9a44cd0bfc..0000000000
--- a/contrib/firmware/angie/c/src/jtag.c
+++ /dev/null
@@ -1,674 +0,0 @@
-// 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. *
- *
- *
-*****************************************************************************/
-
-#include "jtag.h"
-#include "io.h"
-#include "msgtypes.h"
-#include "reg_ezusb.h"
-#include
-#include
-#include
-
-/** 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;
-}
diff --git a/contrib/firmware/angie/c/src/main.c b/contrib/firmware/angie/c/src/main.c
index 9290af2ab5..657694b6c1 100644
--- a/contrib/firmware/angie/c/src/main.c
+++ b/contrib/firmware/angie/c/src/main.c
@@ -11,10 +11,9 @@
*****************************************************************************/
#include "usb.h"
+#include "serial.h"
#include "delay.h"
-#include "protocol.h"
#include "reg_ezusb.h"
-#include
#include
extern void sudav_isr(void)__interrupt SUDAV_ISR;
@@ -65,7 +64,7 @@ void gpif_init(void);
int main(void)
{
CPUCS = ((CPUCS & ~bmclkspd) | (CLK_48M << 3) | CLKOE); /* required for sio0_init */
- sio0_init(57600); /* needed for printf */
+ sio0_init(115200); /* needed for printf */
ep_init();
gpif_init();
@@ -74,12 +73,10 @@ int main(void)
/* Perform ReNumeration */
USBCS |= (DISCON | RENUM);
- delay_ms(250);
+ delay_ms(50);
USBCS &= ~DISCON;
- /* Begin executing command(s). This function never returns. */
- command_loop();
-
- /* Never reached, but SDCC complains about missing return statement */
- return 0;
+ /* stay here */
+ while (1)
+ ;
}
diff --git a/contrib/firmware/angie/c/src/protocol.c b/contrib/firmware/angie/c/src/protocol.c
deleted file mode 100644
index e32808db8f..0000000000
--- a/contrib/firmware/angie/c/src/protocol.c
+++ /dev/null
@@ -1,192 +0,0 @@
-// 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. *
- *
- *
-*****************************************************************************/
-
-#include "usb.h"
-#include "protocol.h"
-#include "jtag.h"
-#include "delay.h"
-#include "io.h"
-#include "msgtypes.h"
-#include "reg_ezusb.h"
-#include
-#include
-
-/** 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;
-
- /* 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 Bulk-OUT packet */
- while ((!ep1_out) && (!ep6_out))
- ;
- if (ep6_out) {
- /* Execute I2C command */
- i2c_recieve();
- ep6_out = false;
- }
- if (ep1_out) {
- ep1_out = false;
- /* Execute the commands */
- last_command = false;
- while (!last_command)
- last_command = execute_command();
-
- /* Send back EP1 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);
- }
- }
-}
diff --git a/contrib/firmware/angie/c/src/usb.c b/contrib/firmware/angie/c/src/usb.c
index ed23dcfa5a..6a07cc5d32 100644
--- a/contrib/firmware/angie/c/src/usb.c
+++ b/contrib/firmware/angie/c/src/usb.c
@@ -11,133 +11,119 @@
*****************************************************************************/
#include "usb.h"
-#include "stdint.h"
#include "delay.h"
#include "io.h"
#include "reg_ezusb.h"
-#include
-#include
-#include
+#include "fx2macros.h"
+#include "serial.h"
#include "i2c.h"
+#include
+#include
+#include
-/* Also update external declarations in "include/usb.h" if making changes to
- * these variables!
- */
-volatile bool ep1_out;
-volatile bool ep1_in;
-volatile bool ep6_out;
+// #define PRINTF_DEBUG
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
+#define NUM_ENDPOINTS 2
__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 = 0xEF,
- .bdevicesubclass = 0x02,
- .bdeviceprotocol = 0x01,
- .bmaxpacketsize0 = 64,
- .idvendor = 0x584e,
- .idproduct = 0x414f,
- .bcddevice = 0x0000,
- .imanufacturer = 1,
- .iproduct = 2,
- .iserialnumber = 3,
+ .blength = sizeof(struct usb_device_descriptor),
+ .bdescriptortype = DESCRIPTOR_TYPE_DEVICE,
+ .bcdusb = 0x0200, /* BCD: 02.00 (Version 2.0 USB spec) */
+ .bdeviceclass = 0xEF,
+ .bdevicesubclass = 0x02,
+ .bdeviceprotocol = 0x01,
+ .bmaxpacketsize0 = 64,
+ .idvendor = 0x584e,
+ .idproduct = 0x414f,
+ .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) +
- 3 * sizeof(struct usb_interface_descriptor) +
- ((NUM_ENDPOINTS + 2) * sizeof(struct usb_endpoint_descriptor)),
- .bnuminterfaces = 2,
+ .blength = sizeof(struct usb_config_descriptor),
+ .bdescriptortype = DESCRIPTOR_TYPE_CONFIGURATION,
+ .wtotallength = sizeof(struct usb_config_descriptor) +
+ 2 * sizeof(struct usb_interface_descriptor) +
+ ((NUM_ENDPOINTS * 2) * sizeof(struct usb_endpoint_descriptor)),
+ .bnuminterfaces = 2,
.bconfigurationvalue = 1,
- .iconfiguration = 1, /* String describing this configuration */
- .bmattributes = 0x80, /* Only MSB set according to USB spec */
- .maxpower = 50 /* 100 mA */
+ .iconfiguration = 2, /* 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,
+ .blength = sizeof(struct usb_interface_descriptor),
+ .bdescriptortype = DESCRIPTOR_TYPE_INTERFACE,
+ .binterfacenumber = 0,
.balternatesetting = 0,
- .bnumendpoints = NUM_ENDPOINTS,
- .binterfaceclass = 0XFF,
+ .bnumendpoints = NUM_ENDPOINTS,
+ .binterfaceclass = 0XFF,
.binterfacesubclass = 0x00,
.binterfaceprotocol = 0x00,
- .iinterface = 4
+ .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_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_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_interface_descriptor interface_descriptor01 = {
- .blength = sizeof(struct usb_interface_descriptor),
- .bdescriptortype = DESCRIPTOR_TYPE_INTERFACE,
- .binterfacenumber = 1,
+ .blength = sizeof(struct usb_interface_descriptor),
+ .bdescriptortype = DESCRIPTOR_TYPE_INTERFACE,
+ .binterfacenumber = 1,
.balternatesetting = 0,
- .bnumendpoints = 2,
- .binterfaceclass = 0x0A,
+ .bnumendpoints = NUM_ENDPOINTS,
+ .binterfaceclass = 0x0A,
.binterfacesubclass = 0x00,
.binterfaceprotocol = 0x00,
- .iinterface = 0x00
+ .iinterface = 0
};
__code struct usb_endpoint_descriptor bulk_ep6_out_endpoint_descriptor = {
- .blength = sizeof(struct usb_endpoint_descriptor),
- .bdescriptortype = 0x05,
- .bendpointaddress = (6 | USB_DIR_OUT),
- .bmattributes = 0x02,
- .wmaxpacketsize = 512,
- .binterval = 0
+ .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_in_endpoint_descriptor = {
- .blength = sizeof(struct usb_endpoint_descriptor),
- .bdescriptortype = 0x05,
- .bendpointaddress = (8 | USB_DIR_IN),
- .bmattributes = 0x02,
- .wmaxpacketsize = 512,
- .binterval = 0
+ .blength = sizeof(struct usb_endpoint_descriptor),
+ .bdescriptortype = 0x05,
+ .bendpointaddress = (8 | USB_DIR_IN),
+ .bmattributes = 0x02,
+ .wmaxpacketsize = 512,
+ .binterval = 0
};
__code struct usb_language_descriptor language_descriptor = {
- .blength = 4,
- .bdescriptortype = DESCRIPTOR_TYPE_STRING,
- .wlangid = {0x0409} /* US English */
+ .blength = 4,
+ .bdescriptortype = DESCRIPTOR_TYPE_STRING,
+ .wlangid = 0x0409 /* US English */
};
__code struct usb_string_descriptor strmanufacturer =
@@ -149,15 +135,11 @@ __code struct usb_string_descriptor strproduct =
__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] = {
+__code struct usb_string_descriptor *__code en_string_descriptors[3] = {
&strmanufacturer,
&strproduct,
- &strserialnumber,
- &strconfigdescr
+ &strserialnumber
};
void sudav_isr(void)__interrupt SUDAV_ISR
{
@@ -195,15 +177,9 @@ 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
{
@@ -213,15 +189,15 @@ void ep4_isr(void)__interrupt EP4_ISR
}
void ep6_isr(void)__interrupt EP6_ISR
{
- ep6_out = true;
+ REVCTL = 0; /* REVCTL.0 and REVCTL.1 set to 0 */
+ i2c_recieve(); /* Execute I2C communication */
EXIF &= ~0x10; /* Clear USBINT: Main global interrupt */
EPIRQ = 0x40; /* Clear individual EP6OUT IRQ */
-
}
void ep8_isr(void)__interrupt EP8_ISR
{
- EXIF &= ~0x10; /* Clear USBINT: Main global interrupt */
- EPIRQ = 0x80; /* Clear individual EP8IN IRQ */
+ EXIF &= ~0x10; /* Clear USBINT: Main global interrupt */
+ EPIRQ = 0x80; /* Clear individual EP8IN IRQ */
}
void ibn_isr(void)__interrupt IBN_ISR
{
@@ -348,63 +324,6 @@ void usb_reset_data_toggle(uint8_t ep)
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.
*
@@ -500,12 +419,17 @@ bool usb_handle_get_descriptor(void)
case DESCRIPTOR_TYPE_STRING:
if (setup_data.windex == 0) {
/* Supply language descriptor */
- SUDPTRH = HI8(&language_descriptor);
- SUDPTRL = LO8(&language_descriptor);
+ __xdata struct usb_language_descriptor temp_descriptor;
+ memcpy(&temp_descriptor, &language_descriptor, sizeof(language_descriptor));
+ SUDPTRH = HI8(&temp_descriptor);
+ SUDPTRL = LO8(&temp_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]);
+ __xdata uint8_t temp_descriptors[3];
+ memcpy(temp_descriptors, en_string_descriptors[descriptor_index - 1],
+ ((struct usb_string_descriptor *)en_string_descriptors[descriptor_index - 1])->blength);
+ SUDPTRH = HI8(temp_descriptors);
+ SUDPTRL = LO8(temp_descriptors);
} else {
return false;
}
@@ -523,15 +447,28 @@ bool usb_handle_get_descriptor(void)
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;
+ usb_reset_data_toggle(USB_DIR_IN | 4);
+ usb_reset_data_toggle(USB_DIR_OUT | 6);
+ usb_reset_data_toggle(USB_DIR_IN | 8);
/* Unstall all valid OUT endpoints, reset bytecounts */
- EP1OUTCS = 0;
- EP1OUTBC = 0;
+ EP2CS = 0;
+ EP4CS = 0;
+ EP6CS = 0;
+ EP8CS = 0;
+ syncdelay(3);
+ EP2BCH = 0;
+ EP2BCL = 0x80;
+ syncdelay(3);
+ EP4BCH = 0;
+ EP4BCL = 0x80;
+ syncdelay(3);
+ EP6BCH = 0;
+ EP6BCL = 0x80;
+ syncdelay(3);
+ EP8BCH = 0;
+ EP8BCL = 0x80;
syncdelay(3);
}
@@ -551,14 +488,14 @@ void set_gpif_cnt(uint32_t count)
* Vendor commands handling:
*/
#define VR_CFGOPEN 0xB0
-#define VR_CFGCLOSE 0xB1
+#define VR_DATAOUTOPEN 0xB2
uint8_t ix;
uint8_t bcnt;
uint8_t __xdata *eptr;
uint16_t wcnt;
uint32_t __xdata gcnt;
-bool usb_handle_send_bitstream(void)
+bool usb_handle_vcommands(void)
{
eptr = EP0BUF; /* points to EP0BUF 64-byte register */
wcnt = setup_data.wlength; /* total transfer count */
@@ -582,43 +519,69 @@ bool usb_handle_send_bitstream(void)
/* 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 */
+ /* Apply RPGM- pulse */
+ PIN_PROGRAM_B = 0;
+ syncdelay(1);
+ /* Negate RPGM- pulse */
+ PIN_PROGRAM_B = 1;
+ /* FPGA init time < 10mS */
+ delay_ms(10);
+ /* Initialize GPIF interface transfer count */
+ set_gpif_cnt(gcnt);
PIN_RDWR_B = 0;
- PIN_CSI_B = 0;
- GPIFTRIG = GPIF_EP2; /* Trigger GPIF OUT transfer on EP2 */
- syncdelay(3);
+ PIN_SDA = 0;
+ /* Trigger GPIF OUT transfer on EP2 */
+ GPIFTRIG = GPIF_EP2;
+ while (!(GPIFTRIG & BMGPIFDONE)) // poll GPIFTRIG.7 GPIF Done bit
+ ;
+ PIN_SDA = 1;
+ PIN_RDWR_B = 1;
+ #ifdef PRINTF_DEBUG
+ printf("Program SP6 Done.\n");
+ #endif
+ /* Choose wich Waveform to use */
+ GPIFWFSELECT = 0xF6;
break;
default:
break;
}
break;
- case VR_CFGCLOSE:
- ix = 10;
- /* wait until GPIF transaction has been completed */
- while ((GPIFTRIG & BMGPIFDONE) == 0) {
- if (ix-- == 0) {
- 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;
- }
+ case VR_DATAOUTOPEN:
+ /* Clear bytecount / to allow new data in / to stops NAKing */
EP0BCH = 0;
- EP0BCL = (uint8_t)(setup_data.wlength); /* Signal buffer is filled */
+ 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]);
+ /* REVCTL.0 and REVCTL.1 set to 1 */
+ REVCTL = 0x3;
+ /* Angie board FPGA bitstream download */
+ PIN_RDWR_B = 0;
+ /* Initialize GPIF interface transfer count */
+ GPIFTCB3 = (uint8_t)(((uint32_t)(gcnt) >> 24) & 0x000000ff);
+ GPIFTCB2 = (uint8_t)(((uint32_t)(gcnt) >> 16) & 0x000000ff);
+ GPIFTCB1 = (uint8_t)(((uint32_t)(gcnt) >> 8) & 0x000000ff);
+ GPIFTCB0 = (uint8_t)((uint32_t)(gcnt) & 0x000000ff);
+ /* Trigger GPIF OUT transfer on EP2 */
+ GPIFTRIG = GPIF_EP2;
+ while (!(GPIFTRIG & BMGPIFDONE)) // poll GPIFTRIG.7 GPIF Done bit
+ ;
+ PIN_RDWR_B = 1;
+ /* Initialize GPIF interface transfer count */
+ GPIFTCB3 = (uint8_t)(((uint32_t)(gcnt) >> 24) & 0x000000ff);
+ GPIFTCB2 = (uint8_t)(((uint32_t)(gcnt) >> 16) & 0x000000ff);
+ GPIFTCB1 = (uint8_t)(((uint32_t)(gcnt) >> 8) & 0x000000ff);
+ GPIFTCB0 = (uint8_t)((uint32_t)(gcnt) & 0x000000ff);
+ /* Initialize AUTOIN transfer count */
+ EP4AUTOINLENH = (uint8_t)(((uint32_t)(gcnt) >> 8) & 0x000000ff);
+ EP4AUTOINLENL = (uint8_t)((uint32_t)(gcnt) & 0x000000ff);
+ /* Trigger GPIF IN transfer on EP4 */
+ GPIFTRIG = BMGPIFREAD | GPIF_EP4;
+ while (!(GPIFTRIG & BMGPIFDONE)) // poll GPIFTRIG.7 GPIF Done bit
+ ;
+ /* REVCTL.0 and REVCTL.1 set to 0 */
+ REVCTL = 0;
break;
default:
return true; /* Error: unknown VR command */
@@ -633,8 +596,12 @@ void usb_handle_setup_data(void)
{
switch (setup_data.brequest) {
case GET_STATUS:
- if (!usb_handle_get_status())
- STALL_EP0();
+ EP0BUF[0] = 0;
+ EP0BUF[1] = 0;
+ /* Send response */
+ EP0BCH = 0;
+ EP0BCL = 2;
+ syncdelay(3);
break;
case CLEAR_FEATURE:
if (!usb_handle_clear_feature())
@@ -672,8 +639,9 @@ void usb_handle_setup_data(void)
case GET_INTERFACE:
/* ANGIE only has one interface, return its number */
EP0BUF[0] = interface_descriptor00.binterfacenumber;
+ EP0BUF[1] = interface_descriptor01.binterfacenumber;
EP0BCH = 0;
- EP0BCL = 1;
+ EP0BCL = 2;
syncdelay(3);
break;
case SET_INTERFACE:
@@ -684,7 +652,7 @@ void usb_handle_setup_data(void)
break;
default:
/* if not Vendor command, Stall EndPoint 0 */
- if (usb_handle_send_bitstream())
+ if (usb_handle_vcommands())
STALL_EP0();
break;
}
@@ -695,29 +663,21 @@ void usb_handle_setup_data(void)
*/
void ep_init(void)
{
- EP1INCFG = 0xA0;
- syncdelay(3);
- EP1OUTCFG = 0xA0;
- syncdelay(3);
- EP2CFG = 0xA0;
- syncdelay(3);
- EP4CFG = 0x00;
+ EP1INCFG = 0x00; /* non VALID */
syncdelay(3);
- EP6CFG = 0xA2;
- syncdelay(3);
- EP8CFG = 0xE2;
+ EP1OUTCFG = 0x00; /* non VALID */
syncdelay(3);
- /* arm EP1-OUT */
- EP1OUTBC = 0;
+ /* JTAG */
+ EP2CFG = 0xA2; /* VALID | OUT | BULK | 512 Bytes | Double buffer */
syncdelay(3);
- EP1OUTBC = 0;
+ EP4CFG = 0xE2; /* VALID | IN | BULK | 512 Bytes | Double buffer */
syncdelay(3);
- /* arm EP1-IN */
- EP1INBC = 0;
+ /* I2C */
+ EP6CFG = 0xA2; /* VALID | OUT | BULK | 512 Bytes | Double buffer */
syncdelay(3);
- EP1INBC = 0;
+ EP8CFG = 0xE2; /* VALID | IN | BULK | 512 Bytes | Double buffer */
syncdelay(3);
/* arm EP6-OUT */
@@ -726,31 +686,45 @@ void ep_init(void)
EP6BCL = 0x80;
syncdelay(3);
+ /* REVCTL.0 and REVCTL.1 set to 1 */
+ REVCTL = 0x3;
+ /* Arm both EP2 buffers to “prime the pump” */
+ OUTPKTEND = 0x82;
+ syncdelay(3);
+ OUTPKTEND = 0x82;
+ syncdelay(3);
+
/* Standard procedure to reset FIFOs */
FIFORESET = BMNAKALL; /* NAK all transfers during the reset */
syncdelay(3);
- FIFORESET = 0x02; /* reset EP2 FIFO */
+ FIFORESET = BMNAKALL | 0x02; /* reset EP2 FIFO */
+ syncdelay(3);
+ FIFORESET = BMNAKALL | 0x04; /* reset EP4 FIFO */
syncdelay(3);
FIFORESET = 0x00; /* deactivate the NAK all */
syncdelay(3);
+
+ /* configure EP2 in AUTO mode with 8-bit interface */
EP2FIFOCFG = 0x00;
syncdelay(3);
- EP2FIFOCFG = BMAUTOOUT; /* Automatic 8-bit GPIF OUT mode */
+ EP2FIFOCFG = BMAUTOOUT; /* 8-bit Auto OUT mode */
+ syncdelay(3);
+ EP4FIFOCFG = BMAUTOIN | BMZEROLENIN; /* 8-bit Auto IN mode */
syncdelay(3);
}
void i2c_recieve(void)
{
- PIN_SDA_DIR = 0;
if (EP6FIFOBUF[0] == 1) {
- uint8_t rdwr = EP6FIFOBUF[0]; //read
- uint8_t data_count = EP6FIFOBUF[1]; //data sent count
+ uint8_t rdwr = EP6FIFOBUF[0]; //read: 1
+ uint8_t reg_byte_check = EP6FIFOBUF[1]; //register given: 1 else: 0
uint8_t count = EP6FIFOBUF[2]; //requested data count
uint8_t adr = EP6FIFOBUF[3]; //address
uint8_t address = get_address(adr, rdwr); //address byte (read command)
uint8_t address_2 = get_address(adr, 0); //address byte 2 (write command)
- printf("%d\n", address - 1);
+ /* i2c bus state byte */
+ EP8FIFOBUF[0] = get_status();
/* start: */
start_cd();
@@ -760,12 +734,10 @@ void i2c_recieve(void)
uint8_t ack = get_ack();
/* send data */
- if (data_count) { //if there is a byte reg
- for (uint8_t i = 0; i < data_count; i++) {
- send_byte(EP6FIFOBUF[i + 4]);
- /* ack(): */
- ack = get_ack();
- }
+ for (int i = 0; i < reg_byte_check; i++) {
+ send_byte(EP6FIFOBUF[i + 4]);
+ /* ack(): */
+ ack = get_ack();
}
/* repeated start: */
@@ -776,14 +748,14 @@ void i2c_recieve(void)
ack = get_ack();
/* receive data */
- for (uint8_t i = 0; i < count - 1; i++) {
+ for (int i = 1; i < count; i++) {
EP8FIFOBUF[i] = receive_byte();
/* send ack: */
send_ack();
}
- EP8FIFOBUF[count - 1] = receive_byte();
+ EP8FIFOBUF[count] = receive_byte();
/* send Nack: */
send_nack();
@@ -791,44 +763,46 @@ void i2c_recieve(void)
/* stop */
stop_cd();
- EP8BCH = 0; //EP8
+ EP8BCH = (count + 1) >> 8; //EP8
syncdelay(3);
- EP8BCL = count; //EP8
+ EP8BCL = count + 1; //EP8
EP6BCL = 0x80; //EP6
syncdelay(3);
EP6BCL = 0x80; //EP6
} else {
- uint8_t rdwr = EP6FIFOBUF[0]; //write
+ uint8_t rdwr = EP6FIFOBUF[0]; //write: 0
uint8_t count = EP6FIFOBUF[1]; //data count
uint8_t adr = EP6FIFOBUF[2]; //address
uint8_t address = get_address(adr, rdwr); //address byte (read command)
uint8_t ack_cnt = 0;
-/* start(): */
+ // i2c bus state byte
+ EP8FIFOBUF[0] = get_status();
+
+ /* start(): */
start_cd();
-/* address: */
+ /* address: */
send_byte(address); //write
-/* ack(): */
+ /* ack(): */
if (!get_ack())
ack_cnt++;
-/* send data */
- for (uint8_t i = 0; i < count; i++) {
+ /* send data */
+ for (int i = 0; i < count; i++) {
send_byte(EP6FIFOBUF[i + 3]);
-
/* get ack: */
if (!get_ack())
ack_cnt++;
}
-/* stop */
+ /* stop */
stop_cd();
- EP8FIFOBUF[0] = ack_cnt;
+ EP8FIFOBUF[1] = ack_cnt;
EP8BCH = 0; //EP8
syncdelay(3);
- EP8BCL = 1; //EP8
+ EP8BCL = 2; //EP8
EP6BCL = 0x80; //EP6
syncdelay(3);
@@ -841,9 +815,6 @@ void i2c_recieve(void)
**/
void interrupt_init(void)
{
- /* Enable Interrupts */
- EA = 1;
-
/* Enable USB interrupt (EIE register) */
EUSB = 1;
EICON |= 0x20;
@@ -851,17 +822,22 @@ void interrupt_init(void)
/* Enable INT 2 & 4 Autovectoring */
INTSETUP |= (AV2EN | AV4EN);
- /* Enable individual EP1OUT&IN & EP6&8 interrupts */
- EPIE |= 0xCC;
+ /* Enable individual EP6&8 interrupts */
+ EPIE |= 0xC0;
/* Clear individual USB interrupt IRQ */
- EPIRQ = 0xCC;
+ EPIRQ = 0xC0;
/* Enable SUDAV interrupt */
USBIEN |= SUDAVI;
/* Clear SUDAV interrupt */
USBIRQ = SUDAVI;
+
+ /* Enable Interrupts (Do not confuse this with
+ * EA External Access pin, see ANGIE Schematic)
+ */
+ EA = 1;
}
/**
@@ -870,25 +846,12 @@ void interrupt_init(void)
void io_init(void)
{
/* PORT A */
- PORTACFG = 0x01; /* 0: normal ou 1: alternate function (each bit) */
- OEA = 0xEF; /* all OUT exept INIT_B IN */
+ PORTACFG = 0x0; /* 0: normal ou 1: alternate function (each bit) */
+ OEA = 0xEF;
IOA = 0xFF;
- /* 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) */
+ PORTCCFG = 0x0; /* 0: normal ou 1: alternate function (each bit) */
OEC = 0xFF;
IOC = 0xFF;
-
- /* PORT D */
- OED = 0xFF;
- IOD = 0xFF;
}
diff --git a/contrib/firmware/angie/hdl/src/angie_bitstream.ucf b/contrib/firmware/angie/hdl/src/angie_bitstream.ucf
index 9eb0c85c39..48c5b94079 100644
--- a/contrib/firmware/angie/hdl/src/angie_bitstream.ucf
+++ b/contrib/firmware/angie/hdl/src/angie_bitstream.ucf
@@ -1,8 +1,8 @@
## 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
+## Project Context: nanoXplore USB to JTAG/I2C Adapter Board, Spartan6
+## Design Name: ANGIE USB to JTAG/I2C Adapter FPGA source code
+## Module Name: angie_bitstream.ucf
## Target Device: XC6SLX9-2 TQ144
## Tool versions: ISE Webpack 13.2 -> 14.2
## Author: Ahmed BOUDJELIDA nanoXplore SAS
@@ -10,41 +10,65 @@
# 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 SDA LOC = 'P50' ;
-net SCL LOC = 'P51' ;
-net SDA_DIR LOC = 'P56' ;
-net SCL_DIR LOC = 'P57' ;
-
-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 SO_SDA_OUT LOC = 'P140' ;
-net SO_SDA_IN LOC = 'P1' ;
-net SO_SCL LOC = 'P137';
-
-net ST_0 LOC = 'P29' ;
-net ST_1 LOC = 'P21' ;
-net ST_2 LOC = 'P11' ;
-
-net ST_4 LOC = 'P134' ;
-net ST_5 LOC = 'P139' ;
-
-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' ;
+CONFIG VCCAUX = "3.3";
+
+# Timing
+# net IH24 period = 40; # Constrain at 25MHz
+# net IH40 period = 25; # Constrain at 40MHz
+# DCMs placement on Spartan6
+# INST S6MOD_CKMUL.H48_DCM LOC = DCM0;
+
+# Clock 48MHz
+net IFCLK_I LOC = 'P123' ;
+
+net GD_IO<0> LOC = 'P48' ;
+net GD_IO<1> LOC = 'P43' ;
+net GD_IO<2> LOC = 'P44' ;
+net GD_IO<3> LOC = 'P45' ;
+net GD_IO<4> LOC = 'P46' ;
+net GD_IO<5> LOC = 'P61' ;
+net GD_IO<6> LOC = 'P62' ;
+net GD_IO<7> LOC = 'P65' ;
+
+net PA2_I LOC = 'P47' ;
+#net PA3_I LOC = 'P64' ;
+net JPW_I LOC = 'P14' ;
+
+net GCTL0_I LOC = 'P70' ;
+#net GCTL1_I LOC = 'P55' ;
+#net GCTL2_I LOC = 'P67' ;
+net GRDY1_I LOC = 'P118' ;
+
+#net SDA_IO LOC = 'P50' ;
+net SDA_IO LOC = 'P64' ; #PA3
+#net SCL_I LOC = 'P51' ;
+net SCL_I LOC = 'P39' ; #PA4 switch
+net SDA_DIR_I LOC = 'P66' ; #PA0 switch
+#net SCL_DIR_I LOC = 'P57' ;
+
+net SO_SDA_OUT_O LOC = 'P140' ;
+net SO_SDA_IN_I LOC = 'P1' ;
+net SO_SCL_O LOC = 'P137' ;
+
+net SO_TRST_O LOC = 'P32' ;
+net SO_TMS_O LOC = 'P27' ;
+net SO_TCK_O LOC = 'P30' ;
+net SO_TDI_O LOC = 'P26' ;
+net SO_SRST_O LOC = 'P12' ;
+net SI_TDO_I LOC = 'P16' ;
+
+net ST_0_O LOC = 'P29' ;
+net ST_1_O LOC = 'P21' ;
+net ST_2_O LOC = 'P11' ;
+net ST_3_O LOC = 'P7' ;
+net ST_4_O LOC = 'P134' ;
+net ST_5_O LOC = 'P139' ;
+
+net FTP_O<0> LOC = 'P121' ;
+net FTP_O<1> LOC = 'P120' ;
+net FTP_O<2> LOC = 'P119' ;
+net FTP_O<3> LOC = 'P116' ;
+net FTP_O<4> LOC = 'P111' ;
+net FTP_O<5> LOC = 'P112' ;
+net FTP_O<6> LOC = 'P115' ;
+net FTP_O<7> LOC = 'P114' ;
diff --git a/contrib/firmware/angie/hdl/src/angie_bitstream.vhd b/contrib/firmware/angie/hdl/src/angie_bitstream.vhd
index 6004bf2ff5..737a84ce58 100644
--- a/contrib/firmware/angie/hdl/src/angie_bitstream.vhd
+++ b/contrib/firmware/angie/hdl/src/angie_bitstream.vhd
@@ -1,103 +1,415 @@
-- 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
+-- Project Context: nanoXplore USB to JTAG/I2C Adapter Board, Spartan6
+-- Design Name: ANGIE USB to JTAG/I2C Adapter FPGA source code
+-- Module Name: angie_bitstream.vhd
-- Target Device: XC6SLX9-2 TQ144
-- Tool versions: ISE Webpack 13.2 -> 14.2
-- Author: Ahmed BOUDJELIDA nanoXplore SAS
----------------------------------------------------------------------------
-
+library work;
+use work.all;
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;
-
- SDA : inout std_logic;
- SDA_DIR : in std_logic;
- SCL : in std_logic;
- SCL_DIR : 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;
-
- ST_4 : out std_logic;
- ST_5 : out std_logic;
-
- SO_SDA_OUT : out std_logic;
- SO_SDA_IN : in std_logic;
- SO_SCL : 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
+
+entity angie_bitstream is port(
+ SDA_IO : inout std_logic;
+ SDA_DIR_I : in std_logic;
+ SCL_I : in std_logic;
+
+ JPW_I : in std_logic; --Devkit power
+
+ SO_SDA_OUT_O : out std_logic;
+ SO_SDA_IN_I : in std_logic;
+ SO_SCL_O : out std_logic;
+
+ ST_0_O : out std_logic;
+ ST_1_O : out std_logic;
+ ST_2_O : out std_logic;
+ ST_3_O : out std_logic;
+ ST_4_O : out std_logic;
+ ST_5_O : out std_logic;
+
+ SO_TRST_O : out std_logic;
+ SO_TMS_O : out std_logic;
+ SO_TCK_O : out std_logic;
+ SO_TDI_O : out std_logic;
+ SO_SRST_O : out std_logic;
+ SI_TDO_I : in std_logic;
+
+ PA2_I : in std_logic; -- GPIF IN
+
+ -- Clock 48MHz
+ IFCLK_I : in std_logic;
+
+ GCTL0_I : in std_logic;
+ GRDY1_I : out std_logic;
+ GD_IO : inout std_logic_vector(7 downto 0);
+ FTP_O : out std_logic_vector(15 downto 0)
+);
+end angie_bitstream;
+
+architecture A_angie_bitstream of angie_bitstream is
+----------------------------------------Fifo out (PC to devkit)
+signal rst_o, clk_wr_o, clk_rd_o : std_logic;
+signal write_en_o, read_en_o : std_logic;
+signal data_in_o, data_out_o : std_logic_vector(7 downto 0);
+signal empty_o, full_o : std_logic;
+
+----------------------------------------Fifo in (devkit to PC)
+signal rst_i, clk_wr_i, clk_rd_i : std_logic;
+signal write_en_i, read_en_i : std_logic;
+signal data_in_i, data_out_i : std_logic_vector(7 downto 0);
+signal empty_i, full_i : std_logic;
+
+signal wr_o, rd_i : std_logic;
+
+----------------------------------------MAE
+signal transit1, transit2 : std_logic;
+
+----------------------------------------DFF
+signal pa2_dff_clk, pa2_dff_rst, pa2_dff_d, pa2_dff_q : std_logic;
+signal trst_clk, trst_rst, trst_d, trst_q : std_logic;
+signal tms_clk, tms_rst, tms_d, tms_q : std_logic;
+signal tdi_clk, tdi_rst, tdi_d, tdi_q : std_logic;
+signal tdo_clk, tdo_rst, tdo_d, tdo_q : std_logic;
+
+----------------------------------------clk_div
+signal clk_div_in, clk_div_out, reset_clk_div : std_logic;
+signal clk_div2_in, clk_div2_out, reset_clk_div2 : std_logic;
+
+----------------------------------------MAE
+type State_Type is (IDLE, WRITE_OUT, WRITE_IN, DELAY, READ_IN);
+signal state, state2 : State_Type;
+signal reset_mae, reset_mae2 : std_logic;
+
+-- Add Component DFF
+component DFF
+ Port (
+ clk : in std_logic;
+ reset : in std_logic;
+ d : in std_logic;
+ q : out std_logic
+ );
+end component;
+
+-- Add Component Clk_div
+component clk_div
+Port (
+ clk_in : in std_logic;
+ reset : in std_logic;
+ clk_out : out std_logic
);
-end S609;
+end component;
+
+-- Add component FIFO 64B
+component fifo_generator_v9_3
+PORT (
+ rst : IN STD_LOGIC;
+ wr_clk : IN STD_LOGIC;
+ rd_clk : IN STD_LOGIC;
+ din : IN STD_LOGIC_VECTOR(7 DOWNTO 0);
+ wr_en : IN STD_LOGIC;
+ rd_en : IN STD_LOGIC;
+ dout : OUT STD_LOGIC_VECTOR(7 DOWNTO 0);
+ full : OUT STD_LOGIC;
+ empty : OUT STD_LOGIC
+ );
+end component;
+
+signal state1_debug, state2_debug : std_logic;
-architecture A_S609 of S609 is
begin
+-------------------------------------------------------------I2C :
+SDA_IO <= not(SO_SDA_IN_I) when (SDA_DIR_I = '1') else 'Z';
+SO_SDA_OUT_O <= SDA_IO;
+ST_5_O <= SDA_DIR_I;
---Directions:
-ST_0 <= '0';
-ST_1 <= '1';
+SO_SCL_O <= SCL_I when (JPW_I = '1') else '0';
+ST_4_O <= '0';
---TDO:
-TDO <= not SI_TDO;
+------------------------------------------------------------JTAG :
+-- Instantiate the Clk div by 10
+clk_div_inst : clk_div
+port map (
+ clk_in => clk_div_in,
+ reset => reset_clk_div,
+ clk_out => clk_div_out
+);
+-- Instantiate the Clk div by 10
+clk_div2_inst : clk_div
+port map (
+ clk_in => clk_div2_in,
+ reset => reset_clk_div2,
+ clk_out => clk_div2_out
+);
---TRST - TCK - TMS - TDI:
-SO_TRST <= TRST;
-SO_TMS <= TMS;
-SO_TCK <= TCK;
-SO_TDI <= TDI;
-ST_2 <= SRST;
-SO_SRST <= '0';
+-- Instantiate DFFs
+DFF_inst_PA2 : DFF
+port map (
+ clk => pa2_dff_clk,
+ reset => pa2_dff_rst,
+ d => pa2_dff_d,
+ q => pa2_dff_q
+);
+
+DFF_inst_TRST : DFF
+port map (
+ clk => trst_clk,
+ reset => trst_rst,
+ d => trst_d,
+ q => trst_q
+);
-SO_SCL <= SCL;
+DFF_inst_TMS : DFF
+port map (
+ clk => tms_clk,
+ reset => tms_rst,
+ d => tms_d,
+ q => tms_q
+);
-SDA <= not(SO_SDA_IN) when (SDA_DIR = '1') else 'Z';
-SO_SDA_OUT <= SDA;
+DFF_inst_TDI : DFF
+port map (
+ clk => tdi_clk,
+ reset => tdi_rst,
+ d => tdi_d,
+ q => tdi_q
+);
+
+DFF_inst_TDO : DFF
+port map (
+ clk => tdo_clk,
+ reset => tdo_rst,
+ d => tdo_d,
+ q => tdo_q
+);
-process(SDA_DIR)
+-- Instantiate the FIFO OUT
+U0 : fifo_generator_v9_3
+port map (
+ rst => rst_o,
+ wr_clk => clk_wr_o,
+ rd_clk => clk_rd_o,
+ din => data_in_o,
+ wr_en => write_en_o,
+ rd_en => read_en_o,
+ dout => data_out_o,
+ full => full_o,
+ empty => empty_o
+);
+-- Instantiate the FIFO IN
+U1 : fifo_generator_v9_3
+port map (
+ rst => rst_i,
+ wr_clk => clk_wr_i,
+ rd_clk => clk_rd_i,
+ din => data_in_i,
+ wr_en => write_en_i,
+ rd_en => read_en_i,
+ dout => data_out_i,
+ full => full_i,
+ empty => empty_i
+);
+
+--------------- clock dividers
+clk_div_in <= IFCLK_I; -- 48Mhz
+clk_div2_in <= clk_div_out; -- 24Mhz
+
+--------------- DFFs
+pa2_dff_clk <= IFCLK_I;
+trst_clk <= IFCLK_I;
+tms_clk <= IFCLK_I;
+tdi_clk <= IFCLK_I;
+tdo_clk <= IFCLK_I;
+
+--------------- FIFOs
+clk_wr_o <= IFCLK_I;
+clk_rd_o <= clk_div2_out;
+clk_wr_i <= clk_div2_out;
+clk_rd_i <= IFCLK_I;
+
+--------------------------- GPIF ready :
+GRDY1_I <= '1';
+
+-------------------------------PA2 DFF :
+pa2_dff_rst <= '0';
+pa2_dff_d <= PA2_I;
+
+-------------------- FX2<->Fifo Enable pins :
+write_en_o <= not(wr_o) and not(GCTL0_I);
+read_en_i <= not(rd_i) and not(GCTL0_I);
+
+---------------- FX2->Fifo Data :
+data_in_o <= GD_IO;
+
+------------ FIFO_OUT->Devkit :
+SO_TRST_O <= trst_q;
+trst_d <= data_out_o(4);
+SO_TMS_O <= tms_q;
+tms_d <= data_out_o(3);
+SO_TDI_O <= tdi_q;
+tdi_d <= data_out_o(1);
+------------
+SO_TCK_O <= data_out_o(0);
+
+-------------------- FIFO_OUT->FIFO_IN :
+--data_in_i <= data_out_o;
+
+-------------------- FIFO_IN<-Devkit :
+data_in_i(0) <= '0';
+data_in_i(1) <= '0';
+data_in_i(2) <= tdo_q;
+tdo_d <= not SI_TDO_I;
+data_in_i(3) <= '0';
+data_in_i(4) <= '0';
+data_in_i(5) <= '0';
+data_in_i(6) <= '0';
+data_in_i(7) <= '0';
+
+-------------------- FX2<-FIFO_IN :
+GD_IO <= data_out_i when (state = READ_IN) else "ZZZZZZZZ";
+
+state1_debug <= '1' when state = READ_IN else '0';
+state2_debug <= '1' when state2 = WRITE_IN else '0';
+
+--Points de test:
+FTP_O(0) <= IFCLK_I;
+FTP_O(1) <= GCTL0_I;
+FTP_O(2) <= GD_IO(0);
+FTP_O(3) <= GD_IO(1);
+FTP_O(4) <= JPW_I;
+FTP_O(5) <= PA2_I;
+FTP_O(6) <= empty_o;
+FTP_O(7) <= not SI_TDO_I;
+
+process(pa2_dff_d, pa2_dff_q)
begin
- if(SDA_DIR = '0') then
- ST_5 <= '0';
- else
- ST_5 <= '1';
- end if;
+ if pa2_dff_d = '0' and pa2_dff_q = '1' then
+ reset_mae <= '1'; -- Reset State Machine
+ reset_mae2 <= '1'; -- Reset State Machine
+ rst_o <= '1'; -- Reset OUT
+ rst_i <= '1'; -- Reset IN
+ reset_clk_div <= '1';
+ reset_clk_div2 <= '1';
+ trst_rst <= '1';
+ tms_rst <= '1';
+ tdi_rst <= '1';
+ tdo_rst <= '1';
+ else
+ reset_mae <= '0'; -- No Reset State Machine
+ reset_mae2 <= '0'; -- Reset State Machine
+ rst_o <= '0'; -- No Reset OUT
+ rst_i <= '0'; -- No Reset IN
+ reset_clk_div <= '0';
+ reset_clk_div2 <= '0';
+ trst_rst <= '0';
+ tms_rst <= '0';
+ tdi_rst <= '0';
+ tdo_rst <= '0';
+ end if;
end process;
-process(SCL_DIR)
+process(clk_div2_out, reset_mae2)
begin
- if(SCL_DIR = '0') then
- ST_4 <= '0';
- else
- ST_4 <= '1';
- end if;
+ if reset_mae2 = '1' then
+ state2 <= IDLE;
+ elsif rising_edge(clk_div2_out) then
+ case state2 is
+ when IDLE =>
+ read_en_o <= '0'; -- Disable read OUT
+ write_en_i <= '0'; -- Disable write IN
+ transit2 <= '1';
+ if transit1 = '0' and PA2_I = '0' then
+ state2 <= WRITE_IN;
+ else
+ state2 <= IDLE;
+ end if;
+
+ when WRITE_IN =>
+ read_en_o <= '1'; -- Enable read OUT
+ write_en_i <= '1'; -- Enable write IN
+ if PA2_I = '1' then
+ state2 <= DELAY; -- Change state to DELAY
+ else
+ state2 <= WRITE_IN; -- Stay in WRITE_IN state
+ end if;
+
+ when DELAY =>
+ transit2 <= '0'; -- Enable READ IN
+ if empty_o = '1' then
+ read_en_o <= '0'; -- Disable read OUT
+ write_en_i <= '0'; -- Disable write IN
+ state2 <= IDLE; -- Change state to IDLE
+ else
+ state2 <= DELAY; -- Stay in READ_IN state
+ end if;
+
+ when others =>
+ state2 <= IDLE;
+ end case;
+ end if;
end process;
---Points de test:
-FTP(0) <= SDA;
-FTP(1) <= SCL;
-FTP(2) <= not(SO_SDA_IN);
-FTP(3) <= SDA_DIR;
-FTP(5) <= SRST;
-FTP(4) <= SI_TDO;
-FTP(6) <= '1';
-FTP(7) <= '1';
-
-end A_S609;
+process(IFCLK_I, reset_mae)
+begin
+ if reset_mae = '1' then
+ state <= IDLE;
+ elsif rising_edge(IFCLK_I) then
+ case state is
+ when IDLE =>
+ wr_o <= '1'; -- Disable write OUT
+ rd_i <= '1'; -- Disable read IN
+ transit1 <= '1';
+ if PA2_I = '0' then
+ state <= WRITE_OUT; -- Change state to RESET
+ else
+ state <= IDLE; -- Stay in IDLE state
+ end if;
+
+ when WRITE_OUT =>
+ wr_o <= '0'; -- Enable write OUT
+ if empty_o = '0' then
+ transit1 <= '0'; -- Enable Rd OUT & Wr IN
+ state <= DELAY; -- Change state to DELAY
+ else
+ state <= WRITE_OUT; -- Stay in WRITE_OUT state
+ end if;
+
+ when DELAY =>
+ if transit2 = '0' then
+ wr_o <= '1'; -- Disable write OUT
+ state <= READ_IN;
+ else
+ state <= DELAY;
+ end if;
+
+ when READ_IN =>
+ rd_i <= '0'; -- Enable read IN
+ if empty_i = '1' then
+ rd_i <= '1'; -- Enable read IN
+ state <= IDLE; -- Change state to IDLE
+ else
+ state <= READ_IN; -- Stay in READ_IN state
+ end if;
+
+ when others =>
+ state <= IDLE;
+ end case;
+ end if;
+end process;
+
+-- OUT signals direction
+-- TRST, TMS, TCK and TDI : out
+ST_0_O <= '0';
+-- TDO : in
+ST_1_O <= '1';
+-- SRST : out
+ST_2_O <= '1';
+SO_SRST_O <= '0';
+-- MOD : in
+ST_3_O <= '1';
+
+end A_angie_bitstream;
diff --git a/contrib/firmware/angie/hdl/src/clk_div.vhd b/contrib/firmware/angie/hdl/src/clk_div.vhd
new file mode 100644
index 0000000000..e69850d572
--- /dev/null
+++ b/contrib/firmware/angie/hdl/src/clk_div.vhd
@@ -0,0 +1,33 @@
+library ieee;
+use ieee.std_logic_1164.ALL;
+use ieee.numeric_std.ALL;
+
+entity clk_div is
+ Port (
+ clk_in : in std_logic;
+ reset : in std_logic;
+ clk_out : out std_logic
+ );
+end clk_div;
+
+architecture behavioral of clk_div is
+ -- Division factor N = 4, so we need a 2-bit counter (2^2 = 4)
+-- signal counter : unsigned(1 downto 0) := (others => '0');
+ signal tmp : std_logic;
+begin
+ process(clk_in, reset)
+ begin
+ if reset = '1' then
+-- counter <= (others => '0');
+ tmp <= '0';
+ elsif rising_edge(clk_in) then
+-- if counter = (2**2 - 1) then
+-- counter <= (others => '0');
+ tmp <= NOT tmp; -- Toggle the output clock
+-- else
+-- counter <= counter + 1;
+-- end if;
+ end if;
+ end process;
+ clk_out <= tmp;
+end behavioral;
\ No newline at end of file
diff --git a/contrib/firmware/angie/hdl/src/dff.vhd b/contrib/firmware/angie/hdl/src/dff.vhd
new file mode 100644
index 0000000000..c5ccf06d33
--- /dev/null
+++ b/contrib/firmware/angie/hdl/src/dff.vhd
@@ -0,0 +1,23 @@
+library ieee;
+use ieee.std_logic_1164.ALL;
+use ieee.std_logic_arith.ALL;
+use ieee.std_logic_unsigned.ALL;
+
+entity DFF is
+port ( clk : in std_logic;
+ reset : in std_logic;
+ d : in std_logic;
+ q : out std_logic);
+end DFF;
+
+architecture Behavioral of DFF is
+begin
+ process(clk, reset)
+ begin
+ if reset = '1' then
+ q <= '1'; -- Reset output to 0
+ elsif rising_edge(clk) then
+ q <= d; -- Capture D at the rising edge of the clock
+ end if;
+ end process;
+end Behavioral;
\ No newline at end of file
diff --git a/contrib/loaders/flash/at91sam7x/main.c b/contrib/loaders/flash/at91sam7x/main.c
index a29c6e605b..e988e1848b 100644
--- a/contrib/loaders/flash/at91sam7x/main.c
+++ b/contrib/loaders/flash/at91sam7x/main.c
@@ -70,23 +70,23 @@ int main (void)
for (;;) {
cmd = dcc_rd();
switch (cmd&OCL_CMD_MASK) {
- case OCL_PROBE:
- dcc_wr(OCL_CMD_DONE | flash_init());
- dcc_wr(0x100000); /* base */
- dcc_wr(flash_page_count*flash_page_size); /* size */
- dcc_wr(1); /* num_sectors */
- dcc_wr(4096 | ((unsigned long) flash_page_size << 16)); /* buflen and bufalign */
- break;
- case OCL_ERASE_ALL:
- dcc_wr(OCL_CMD_DONE | flash_erase_all());
- break;
- case OCL_FLASH_BLOCK:
- cmd_flash(cmd);
- break;
- default:
- /* unknown command */
- dcc_wr(OCL_CMD_ERR);
- break;
+ case OCL_PROBE:
+ dcc_wr(OCL_CMD_DONE | flash_init());
+ dcc_wr(0x100000); /* base */
+ dcc_wr(flash_page_count * flash_page_size); /* size */
+ dcc_wr(1); /* num_sectors */
+ dcc_wr(4096 | ((unsigned long)flash_page_size << 16)); /* buflen and bufalign */
+ break;
+ case OCL_ERASE_ALL:
+ dcc_wr(OCL_CMD_DONE | flash_erase_all());
+ break;
+ case OCL_FLASH_BLOCK:
+ cmd_flash(cmd);
+ break;
+ default:
+ /* unknown command */
+ dcc_wr(OCL_CMD_ERR);
+ break;
}
}
diff --git a/contrib/loaders/flash/at91sam7x/samflash.c b/contrib/loaders/flash/at91sam7x/samflash.c
index fcb76fbf98..8be0bdbb84 100644
--- a/contrib/loaders/flash/at91sam7x/samflash.c
+++ b/contrib/loaders/flash/at91sam7x/samflash.c
@@ -22,38 +22,38 @@ int flash_init(void)
nvpsiz = (inr(DBGU_CIDR) >> 8)&0xf;
switch (nvpsiz) {
- case 3:
- /* AT91SAM7x32 */
- flash_page_count = 256;
- flash_page_size = 128;
- flash_lock_pages = 256/8;
- break;
- case 5:
- /* AT91SAM7x64 */
- flash_page_count = 512;
- flash_page_size = 128;
- flash_lock_pages = 512/16;
- break;
- case 7:
- /* AT91SAM7x128*/
- flash_page_count = 512;
- flash_page_size = 256;
- flash_lock_pages = 512/8;
- break;
- case 9:
- /* AT91SAM7x256 */
- flash_page_count = 1024;
- flash_page_size = 256;
- flash_lock_pages = 1024/16;
- break;
- case 10:
- /* AT91SAM7x512 */
- flash_page_count = 2048;
- flash_page_size = 256;
- flash_lock_pages = 2048/32;
- break;
- default:
- return FLASH_STAT_INITE;
+ case 3:
+ /* AT91SAM7x32 */
+ flash_page_count = 256;
+ flash_page_size = 128;
+ flash_lock_pages = 256 / 8;
+ break;
+ case 5:
+ /* AT91SAM7x64 */
+ flash_page_count = 512;
+ flash_page_size = 128;
+ flash_lock_pages = 512 / 16;
+ break;
+ case 7:
+ /* AT91SAM7x128*/
+ flash_page_count = 512;
+ flash_page_size = 256;
+ flash_lock_pages = 512 / 8;
+ break;
+ case 9:
+ /* AT91SAM7x256 */
+ flash_page_count = 1024;
+ flash_page_size = 256;
+ flash_lock_pages = 1024 / 16;
+ break;
+ case 10:
+ /* AT91SAM7x512 */
+ flash_page_count = 2048;
+ flash_page_size = 256;
+ flash_lock_pages = 2048 / 32;
+ break;
+ default:
+ return FLASH_STAT_INITE;
}
return FLASH_STAT_OK;
}
diff --git a/contrib/loaders/flash/bluenrg-x/bluenrg-x_write.c b/contrib/loaders/flash/bluenrg-x/bluenrg-x_write.c
index 1bc72d5921..3c1988f112 100644
--- a/contrib/loaders/flash/bluenrg-x/bluenrg-x_write.c
+++ b/contrib/loaders/flash/bluenrg-x/bluenrg-x_write.c
@@ -52,7 +52,7 @@ static inline __attribute__((always_inline)) uint32_t flashWrite(uint32_t addres
/* Clear the IRQ flags */
*((volatile uint32_t *)(flash_regs_base + FLASH_REG_IRQRAW)) = 0x0000003F;
/* Load the flash address to write */
- *((volatile uint32_t *)(flash_regs_base + FLASH_REG_ADDRESS)) = (uint16_t)((address + index - MFB_BOTTOM) >> 2);
+ *((volatile uint32_t *)(flash_regs_base + FLASH_REG_ADDRESS)) = (uint32_t)((address + index - MFB_BOTTOM) >> 2);
/* Prepare and load the data to flash */
*((volatile uint32_t *)(flash_regs_base + FLASH_REG_DATA0)) = flash_word[0];
*((volatile uint32_t *)(flash_regs_base + FLASH_REG_DATA1)) = flash_word[1];
diff --git a/contrib/loaders/flash/bluenrg-x/bluenrg-x_write.inc b/contrib/loaders/flash/bluenrg-x/bluenrg-x_write.inc
index ff05634bb2..146a6bedeb 100644
--- a/contrib/loaders/flash/bluenrg-x/bluenrg-x_write.inc
+++ b/contrib/loaders/flash/bluenrg-x/bluenrg-x_write.inc
@@ -1,17 +1,19 @@
/* Autogenerated with ../../../../src/helper/bin2char.sh */
-0x05,0x93,0x43,0x68,0x14,0x9e,0x09,0x93,0x05,0x9b,0x05,0x00,0x07,0x91,0x06,0x92,
-0x01,0x24,0xb1,0x46,0x00,0x2b,0x68,0xd0,0x6a,0x68,0x2b,0x68,0x9a,0x42,0xfb,0xd0,
-0x2b,0x68,0x00,0x2b,0x61,0xd0,0x6a,0x68,0x2b,0x68,0x9a,0x42,0x5e,0xd9,0x6b,0x68,
-0x07,0x9a,0xd3,0x1a,0x0f,0x2b,0xef,0xdd,0x4a,0x46,0x00,0x21,0x03,0x93,0xd1,0x60,
-0x00,0x2b,0x42,0xd0,0x40,0x22,0x4a,0x44,0x90,0x46,0x44,0x22,0x4a,0x44,0x00,0x92,
-0x48,0x22,0x4a,0x44,0x93,0x46,0x4c,0x22,0x27,0x4f,0x4a,0x44,0xbc,0x46,0x4e,0x46,
-0x92,0x46,0x06,0x99,0x4b,0x46,0x61,0x44,0x08,0x00,0x00,0x99,0x18,0x36,0x6a,0x68,
-0x08,0x95,0x8c,0x46,0x55,0x46,0xda,0x46,0xb3,0x46,0x10,0x33,0x04,0x92,0x11,0x68,
-0x5e,0x46,0x00,0x91,0x51,0x68,0x97,0x68,0x01,0x91,0xd1,0x68,0x02,0x91,0x3f,0x21,
-0x19,0x60,0x81,0x03,0x09,0x0c,0x31,0x60,0x46,0x46,0x00,0x99,0x31,0x60,0x66,0x46,
-0x01,0x99,0x31,0x60,0x56,0x46,0x02,0x99,0x37,0x60,0x29,0x60,0xcc,0x26,0x49,0x46,
-0x0e,0x60,0x19,0x68,0x0c,0x42,0xfc,0xd0,0x04,0x99,0x03,0x9e,0x10,0x32,0x10,0x30,
-0x51,0x1a,0x8e,0x42,0xdb,0xd8,0x08,0x9d,0x6a,0x60,0x03,0x9a,0x06,0x9b,0x94,0x46,
-0x63,0x44,0x06,0x93,0x07,0x9a,0x6b,0x68,0x9a,0x42,0x01,0xd8,0x09,0x9b,0x6b,0x60,
-0x05,0x9b,0x03,0x9a,0x9b,0x1a,0x05,0x93,0x96,0xd1,0x00,0xbe,0x2b,0x68,0x6a,0x68,
-0x9b,0x1a,0x9f,0xd5,0x90,0xe7,0xc0,0x46,0x00,0x00,0xfc,0xef,
+0x16,0x9e,0x05,0x00,0x01,0x24,0xb1,0x46,0x06,0x93,0x43,0x68,0x08,0x91,0x07,0x92,
+0x09,0x93,0x06,0x9b,0x00,0x2b,0x6f,0xd0,0x6a,0x68,0x2b,0x68,0x9a,0x42,0xfb,0xd0,
+0x2b,0x68,0x00,0x2b,0x68,0xd0,0x6a,0x68,0x2b,0x68,0x9a,0x42,0x65,0xd9,0x6b,0x68,
+0x08,0x9a,0xd3,0x1a,0x0b,0x93,0x0b,0x9b,0x0f,0x2b,0xea,0xdd,0x4a,0x46,0x00,0x21,
+0x0b,0x9b,0xd1,0x60,0x04,0x93,0x00,0x2b,0x43,0xd0,0x31,0x4a,0x07,0x9b,0x94,0x46,
+0x40,0x22,0x4a,0x44,0x90,0x46,0x44,0x22,0x4a,0x44,0x63,0x44,0x94,0x46,0x48,0x22,
+0x4a,0x44,0x93,0x46,0x05,0x93,0x4c,0x22,0x4b,0x46,0x4a,0x44,0x10,0x33,0x4e,0x46,
+0x92,0x46,0x00,0x93,0x2b,0x00,0x18,0x36,0x6a,0x68,0x55,0x46,0xb2,0x46,0x5e,0x46,
+0x9b,0x46,0x10,0x68,0x57,0x68,0x01,0x90,0x3f,0x20,0x00,0x9b,0x02,0x97,0x97,0x68,
+0x03,0x97,0xd7,0x68,0x18,0x60,0x53,0x46,0x05,0x98,0x40,0x18,0x80,0x08,0x18,0x60,
+0x43,0x46,0x01,0x98,0x18,0x60,0x63,0x46,0x02,0x98,0x18,0x60,0x03,0x98,0x4b,0x46,
+0x30,0x60,0xcc,0x20,0x2f,0x60,0x18,0x60,0x00,0x9b,0x18,0x68,0x04,0x42,0xfc,0xd0,
+0x58,0x46,0x10,0x32,0x42,0x60,0x04,0x98,0x10,0x31,0x00,0x93,0x88,0x42,0xd8,0xd8,
+0x5d,0x46,0x07,0x9a,0x0b,0x9b,0x94,0x46,0x9c,0x44,0x63,0x46,0x08,0x9a,0x07,0x93,
+0x6b,0x68,0x93,0x42,0x01,0xd3,0x09,0x9b,0x6b,0x60,0x06,0x9a,0x0b,0x9b,0xd3,0x1a,
+0x06,0x93,0x06,0x9b,0x00,0x2b,0x8f,0xd1,0x00,0xbe,0x2b,0x68,0x6a,0x68,0x9b,0x1a,
+0x0b,0x93,0x0b,0x9b,0x00,0x2b,0x00,0xdb,0x95,0xe7,0x00,0x23,0x0b,0x93,0x92,0xe7,
+0x00,0x00,0xfc,0xef,
diff --git a/contrib/loaders/flash/cc26xx/main.c b/contrib/loaders/flash/cc26xx/main.c
index 6b626a3b84..bd5eaf3354 100644
--- a/contrib/loaders/flash/cc26xx/main.c
+++ b/contrib/loaders/flash/cc26xx/main.c
@@ -98,35 +98,32 @@ int main(void)
/* Perform requested task */
switch (g_cfg[g_curr_buf].cmd) {
- case CMD_ERASE_ALL:
- status = flashloader_erase_all();
- break;
- case CMD_PROGRAM:
- status =
- flashloader_program(
- (uint8_t *)g_cfg[g_curr_buf].buf_addr,
- g_cfg[g_curr_buf].dest, g_cfg[g_curr_buf].len);
- break;
- case CMD_ERASE_AND_PROGRAM:
- status =
- flashloader_erase_and_program(
- (uint8_t *)g_cfg[g_curr_buf].buf_addr,
- g_cfg[g_curr_buf].dest, g_cfg[g_curr_buf].len);
- break;
- case CMD_ERASE_AND_PROGRAM_WITH_RETAIN:
- status =
- flashloader_program_with_retain(
- (uint8_t *)g_cfg[g_curr_buf].buf_addr,
- g_cfg[g_curr_buf].dest, g_cfg[g_curr_buf].len);
- break;
- case CMD_ERASE_SECTORS:
- status =
- flashloader_erase_sectors(g_cfg[g_curr_buf].dest,
- g_cfg[g_curr_buf].len);
- break;
- default:
- status = STATUS_FAILED_UNKNOWN_COMMAND;
- break;
+ case CMD_ERASE_ALL:
+ status = flashloader_erase_all();
+ break;
+ case CMD_PROGRAM:
+ status =
+ flashloader_program((uint8_t *)g_cfg[g_curr_buf].buf_addr,
+ g_cfg[g_curr_buf].dest, g_cfg[g_curr_buf].len);
+ break;
+ case CMD_ERASE_AND_PROGRAM:
+ status =
+ flashloader_erase_and_program((uint8_t *)g_cfg[g_curr_buf].buf_addr,
+ g_cfg[g_curr_buf].dest, g_cfg[g_curr_buf].len);
+ break;
+ case CMD_ERASE_AND_PROGRAM_WITH_RETAIN:
+ status =
+ flashloader_program_with_retain((uint8_t *)g_cfg[g_curr_buf].buf_addr,
+ g_cfg[g_curr_buf].dest, g_cfg[g_curr_buf].len);
+ break;
+ case CMD_ERASE_SECTORS:
+ status =
+ flashloader_erase_sectors(g_cfg[g_curr_buf].dest,
+ g_cfg[g_curr_buf].len);
+ break;
+ default:
+ status = STATUS_FAILED_UNKNOWN_COMMAND;
+ break;
}
restore_cache_state();
diff --git a/contrib/loaders/flash/max32xxx/Makefile b/contrib/loaders/flash/max32xxx/Makefile
index 1565c811c1..fe7666f840 100644
--- a/contrib/loaders/flash/max32xxx/Makefile
+++ b/contrib/loaders/flash/max32xxx/Makefile
@@ -1,21 +1,30 @@
# SPDX-License-Identifier: GPL-2.0-or-later
+TARGET=max32xxx_write
+ENTRY=algo_write
+
BIN2C = ../../../../src/helper/bin2char.sh
-CROSS_COMPILE ?= arm-none-eabi-
-AS = $(CROSS_COMPILE)as
-OBJCOPY = $(CROSS_COMPILE)objcopy
+PREFIX=arm-none-eabi
+CFLAGS=-mthumb -mcpu=cortex-m4 -Wa,-mimplicit-it=thumb
+
+all: $(TARGET).inc
-all: max32xxx.inc
+%.o: %.c
+ $(PREFIX)-gcc $(CFLAGS) -Os -Wall -c ${<} -o ${@}
-%.elf: %.s
- $(AS) $< -o $@
+%.elf: %.o
+ $(PREFIX)-ld -nostdlib --entry $(ENTRY) ${<} -o ${@}
+ $(PREFIX)-size ${@}
%.bin: %.elf
- $(OBJCOPY) -Obinary $< $@
+ $(PREFIX)-objcopy -O binary ${<} ${@}
%.inc: %.bin
$(BIN2C) < $< > $@
+%.dasm: %.o
+ $(PREFIX)-objdump -S ${<} > ${TARGET}.dasm
+
clean:
- -rm -f *.elf *.bin *.inc
+ rm -rf $(TARGET).bin $(TARGET).elf $(TARGET).o $(TARGET).dasm $(TARGET).inc
diff --git a/contrib/loaders/flash/max32xxx/algo_options.h b/contrib/loaders/flash/max32xxx/algo_options.h
new file mode 100644
index 0000000000..a4902e08a0
--- /dev/null
+++ b/contrib/loaders/flash/max32xxx/algo_options.h
@@ -0,0 +1,14 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
+/***************************************************************************
+ * Copyright (C) 2016 by Maxim Integrated *
+ * Copyright (C) 2025 Analog Devices, Inc. *
+ ***************************************************************************/
+
+#define OPTIONS_128 0x01 /* Perform 128 bit flash writes */
+#define OPTIONS_ENC 0x02 /* Encrypt the flash contents */
+#define OPTIONS_AUTH 0x04 /* Authenticate the flash contents */
+#define OPTIONS_COUNT 0x08 /* Add counter values to authentication */
+#define OPTIONS_INTER 0x10 /* Interleave the authentication and count values*/
+#define OPTIONS_RELATIVE_XOR 0x20 /* Only XOR the offset of the address when encrypting */
+#define OPTIONS_KEYSIZE 0x40 /* Use a 256 bit KEY */
diff --git a/contrib/loaders/flash/max32xxx/flc_regs.h b/contrib/loaders/flash/max32xxx/flc_regs.h
new file mode 100644
index 0000000000..9179589ddd
--- /dev/null
+++ b/contrib/loaders/flash/max32xxx/flc_regs.h
@@ -0,0 +1,238 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
+/***************************************************************************
+ * Copyright (C) 2016 by Maxim Integrated *
+ * Copyright (C) 2025 Analog Devices, Inc. *
+ ***************************************************************************/
+
+#ifndef _FLC_REGS_H_
+#define _FLC_REGS_H_
+
+/* **** Includes **** */
+#include
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if defined(__ICCARM__)
+#pragma system_include
+#endif
+
+/*/ @cond */
+/*
+ If types are not defined elsewhere (CMSIS) define them here
+*/
+#ifndef __IO
+#define __IO volatile
+#endif
+#ifndef __I
+#define __I volatile const
+#endif
+#ifndef __O
+#define __O volatile
+#endif
+#ifndef __R
+#define __R volatile const
+#endif
+/*/ @endcond */
+
+/* **** Definitions **** */
+
+/**
+ * @ingroup flc
+ * @defgroup flc_registers Registers
+ * @brief Registers, Bit Masks and Bit Positions for the FLC Peripheral Module.
+ * @description Flash Memory Control.
+ */
+
+/**
+ * @ingroup flc_registers
+ * Structure type to access the FLC Registers.
+ */
+struct mxc_flc_regs {
+ __IO uint32_t addr; /**< \b 0x00:<\tt> FLC ADDR Register */
+ __IO uint32_t clkdiv; /**< \b 0x04:<\tt> FLC CLKDIV Register */
+ __IO uint32_t cn; /**< \b 0x08:<\tt> FLC CN Register */
+ __R uint32_t rsv_0xc_0x23[6];
+ __IO uint32_t intr; /**< \b 0x024:<\tt> FLC INTR Register */
+ __R uint32_t rsv_0x28_0x2f[2];
+ __IO uint32_t data[4]; /**< \b 0x30:<\tt> FLC DATA Register */
+ __O uint32_t acntl; /**< \b 0x40:<\tt> FLC ACNTL Register */
+};
+
+/* Register offsets for module FLC */
+/**
+ * @ingroup flc_registers
+ * @defgroup FLC_Register_Offsets Register Offsets
+ * @brief FLC Peripheral Register Offsets from the FLC Base Peripheral Address.
+ * @{
+ */
+#define MXC_R_FLC_ADDR ((uint32_t)0x00000000UL) /**< Offset from FLC Base Address: 0x0x000 */
+#define MXC_R_FLC_CLKDIV ((uint32_t)0x00000004UL) /**< Offset from FLC Base Address: 0x0x004 */
+#define MXC_R_FLC_CN ((uint32_t)0x00000008UL) /**< Offset from FLC Base Address: 0x0x008 */
+#define MXC_R_FLC_INTR ((uint32_t)0x00000024UL) /**< Offset from FLC Base Address: 0x0x024 */
+#define MXC_R_FLC_DATA ((uint32_t)0x00000030UL) /**< Offset from FLC Base Address: 0x0x030 */
+#define MXC_R_FLC_ACNTL ((uint32_t)0x00000040UL) /**< Offset from FLC Base Address: 0x0x040 */
+/**@} end of group flc_registers */
+
+/**
+ * @ingroup flc_registers
+ * @defgroup ADDR_Register
+ * @brief Flash Write Address.
+ * @{
+ */
+#define MXC_F_FLC_ADDR_ADDR_POS 0 /**< ADDR_ADDR Position */
+#define MXC_F_FLC_ADDR_ADDR ((uint32_t)(0xFFFFFFFFUL << MXC_F_FLC_ADDR_ADDR_POS)) /**< ADDR_ADDR Mask */
+
+/**@} end of group ADDR_Register */
+
+/**
+ * @ingroup flc_registers
+ * @defgroup CLKDIV_Register
+ * @brief Flash Clock Divide. The clock (PLL0) is divided by this value to generate a 1
+ * MHz clock for Flash controller.
+ * @{
+ */
+#define MXC_F_FLC_CLKDIV_CLKDIV_POS 0 /**< CLKDIV_CLKDIV Position */
+#define MXC_F_FLC_CLKDIV_CLKDIV ((uint32_t)(0xFFUL << MXC_F_FLC_CLKDIV_CLKDIV_POS)) /**< CLKDIV_CLKDIV Mask */
+
+/**@} end of group CLKDIV_Register */
+
+/**
+ * @ingroup flc_registers
+ * @defgroup CN_Register
+ * @brief Flash Control Register.
+ * @{
+ */
+#define MXC_F_FLC_CN_WR_POS 0 /**< CN_WR Position */
+#define MXC_F_FLC_CN_WR ((uint32_t)(0x1UL << MXC_F_FLC_CN_WR_POS)) /**< CN_WR Mask */
+#define MXC_V_FLC_CN_WR_COMPLETE ((uint32_t)0x0UL) /**< CN_WR_COMPLETE Value */
+#define MXC_S_FLC_CN_WR_COMPLETE (MXC_V_FLC_CN_WR_COMPLETE << MXC_F_FLC_CN_WR_POS) /**< CN_WR_COMPLETE Setting */
+#define MXC_V_FLC_CN_WR_START ((uint32_t)0x1UL) /**< CN_WR_START Value */
+#define MXC_S_FLC_CN_WR_START (MXC_V_FLC_CN_WR_START << MXC_F_FLC_CN_WR_POS) /**< CN_WR_START Setting */
+
+#define MXC_F_FLC_CN_ME_POS 1 /**< CN_ME Position */
+#define MXC_F_FLC_CN_ME ((uint32_t)(0x1UL << MXC_F_FLC_CN_ME_POS)) /**< CN_ME Mask */
+
+#define MXC_F_FLC_CN_PGE_POS 2 /**< CN_PGE Position */
+#define MXC_F_FLC_CN_PGE ((uint32_t)(0x1UL << MXC_F_FLC_CN_PGE_POS)) /**< CN_PGE Mask */
+
+#define MXC_F_FLC_CN_WDTH_POS 4 /**< CN_WDTH Position */
+#define MXC_F_FLC_CN_WDTH ((uint32_t)(0x1UL << MXC_F_FLC_CN_WDTH_POS)) /**< CN_WDTH Mask */
+#define MXC_V_FLC_CN_WDTH_SIZE128 ((uint32_t)0x0UL) /**< CN_WDTH_SIZE128 Value */
+#define MXC_S_FLC_CN_WDTH_SIZE128 (MXC_V_FLC_CN_WDTH_SIZE128 << MXC_F_FLC_CN_WDTH_POS) /**< CN_WDTH_SIZE128 Setting */
+#define MXC_V_FLC_CN_WDTH_SIZE32 ((uint32_t)0x1UL) /**< CN_WDTH_SIZE32 Value */
+#define MXC_S_FLC_CN_WDTH_SIZE32 (MXC_V_FLC_CN_WDTH_SIZE32 << MXC_F_FLC_CN_WDTH_POS) /**< CN_WDTH_SIZE32 Setting */
+
+#define MXC_F_FLC_CN_ERASE_CODE_POS 8 /**< CN_ERASE_CODE Position */
+#define MXC_F_FLC_CN_ERASE_CODE ((uint32_t)(0xFFUL << MXC_F_FLC_CN_ERASE_CODE_POS)) /**< CN_ERASE_CODE Mask */
+#define MXC_V_FLC_CN_ERASE_CODE_NOP ((uint32_t)0x0UL) /**< CN_ERASE_CODE_NOP Value */
+#define MXC_S_FLC_CN_ERASE_CODE_NOP \
+ (MXC_V_FLC_CN_ERASE_CODE_NOP << MXC_F_FLC_CN_ERASE_CODE_POS) /**< CN_ERASE_CODE_NOP Setting */
+#define MXC_V_FLC_CN_ERASE_CODE_ERASEPAGE ((uint32_t)0x55UL) /**< CN_ERASE_CODE_ERASEPAGE Value */
+#define MXC_S_FLC_CN_ERASE_CODE_ERASEPAGE \
+ (MXC_V_FLC_CN_ERASE_CODE_ERASEPAGE << MXC_F_FLC_CN_ERASE_CODE_POS) /**< CN_ERASE_CODE_ERASEPAGE Setting */
+#define MXC_V_FLC_CN_ERASE_CODE_ERASEALL ((uint32_t)0xAAUL) /**< CN_ERASE_CODE_ERASEALL Value */
+#define MXC_S_FLC_CN_ERASE_CODE_ERASEALL \
+ (MXC_V_FLC_CN_ERASE_CODE_ERASEALL << MXC_F_FLC_CN_ERASE_CODE_POS) /**< CN_ERASE_CODE_ERASEALL Setting */
+
+#define MXC_F_FLC_CN_PEND_POS 24 /**< CN_PEND Position */
+#define MXC_F_FLC_CN_PEND ((uint32_t)(0x1UL << MXC_F_FLC_CN_PEND_POS)) /**< CN_PEND Mask */
+#define MXC_V_FLC_CN_PEND_IDLE ((uint32_t)0x0UL) /**< CN_PEND_IDLE Value */
+#define MXC_S_FLC_CN_PEND_IDLE (MXC_V_FLC_CN_PEND_IDLE << MXC_F_FLC_CN_PEND_POS) /**< CN_PEND_IDLE Setting */
+#define MXC_V_FLC_CN_PEND_BUSY ((uint32_t)0x1UL) /**< CN_PEND_BUSY Value */
+#define MXC_S_FLC_CN_PEND_BUSY (MXC_V_FLC_CN_PEND_BUSY << MXC_F_FLC_CN_PEND_POS) /**< CN_PEND_BUSY Setting */
+
+#define MXC_F_FLC_CN_LVE_POS 25 /**< CN_LVE Position */
+#define MXC_F_FLC_CN_LVE ((uint32_t)(0x1UL << MXC_F_FLC_CN_LVE_POS)) /**< CN_LVE Mask */
+#define MXC_V_FLC_CN_LVE_DIS ((uint32_t)0x0UL) /**< CN_LVE_DIS Value */
+#define MXC_S_FLC_CN_LVE_DIS (MXC_V_FLC_CN_LVE_DIS << MXC_F_FLC_CN_LVE_POS) /**< CN_LVE_DIS Setting */
+#define MXC_V_FLC_CN_LVE_EN ((uint32_t)0x1UL) /**< CN_LVE_EN Value */
+#define MXC_S_FLC_CN_LVE_EN (MXC_V_FLC_CN_LVE_EN << MXC_F_FLC_CN_LVE_POS) /**< CN_LVE_EN Setting */
+
+#define MXC_F_FLC_CN_BRST_POS 27 /**< CN_BRST Position */
+#define MXC_F_FLC_CN_BRST ((uint32_t)(0x1UL << MXC_F_FLC_CN_BRST_POS)) /**< CN_BRST Mask */
+#define MXC_V_FLC_CN_BRST_DISABLE ((uint32_t)0x0UL) /**< CN_BRST_DISABLE Value */
+#define MXC_S_FLC_CN_BRST_DISABLE (MXC_V_FLC_CN_BRST_DISABLE << MXC_F_FLC_CN_BRST_POS) /**< CN_BRST_DISABLE Setting */
+#define MXC_V_FLC_CN_BRST_ENABLE ((uint32_t)0x1UL) /**< CN_BRST_ENABLE Value */
+#define MXC_S_FLC_CN_BRST_ENABLE (MXC_V_FLC_CN_BRST_ENABLE << MXC_F_FLC_CN_BRST_POS) /**< CN_BRST_ENABLE Setting */
+
+#define MXC_F_FLC_CN_UNLOCK_POS 28 /**< CN_UNLOCK Position */
+#define MXC_F_FLC_CN_UNLOCK ((uint32_t)(0xFUL << MXC_F_FLC_CN_UNLOCK_POS)) /**< CN_UNLOCK Mask */
+#define MXC_V_FLC_CN_UNLOCK_UNLOCKED ((uint32_t)0x2UL) /**< CN_UNLOCK_UNLOCKED Value */
+#define MXC_S_FLC_CN_UNLOCK_UNLOCKED \
+ (MXC_V_FLC_CN_UNLOCK_UNLOCKED << MXC_F_FLC_CN_UNLOCK_POS) /**< CN_UNLOCK_UNLOCKED Setting */
+#define MXC_V_FLC_CN_UNLOCK_LOCKED ((uint32_t)0x3UL) /**< CN_UNLOCK_LOCKED Value */
+#define MXC_S_FLC_CN_UNLOCK_LOCKED \
+ (MXC_V_FLC_CN_UNLOCK_LOCKED << MXC_F_FLC_CN_UNLOCK_POS) /**< CN_UNLOCK_LOCKED Setting */
+
+/**@} end of group CN_Register */
+
+/**
+ * @ingroup flc_registers
+ * @defgroup INTR_Register
+ * @brief Flash Interrupt Register.
+ * @{
+ */
+#define MXC_F_FLC_INTR_DONE_POS 0 /**< INTR_DONE Position */
+#define MXC_F_FLC_INTR_DONE ((uint32_t)(0x1UL << MXC_F_FLC_INTR_DONE_POS)) /**< INTR_DONE Mask */
+#define MXC_V_FLC_INTR_DONE_INACTIVE ((uint32_t)0x0UL) /**< INTR_DONE_INACTIVE Value */
+#define MXC_S_FLC_INTR_DONE_INACTIVE \
+ (MXC_V_FLC_INTR_DONE_INACTIVE << MXC_F_FLC_INTR_DONE_POS) /**< INTR_DONE_INACTIVE Setting */
+#define MXC_V_FLC_INTR_DONE_PENDING ((uint32_t)0x1UL) /**< INTR_DONE_PENDING Value */
+#define MXC_S_FLC_INTR_DONE_PENDING \
+ (MXC_V_FLC_INTR_DONE_PENDING << MXC_F_FLC_INTR_DONE_POS) /**< INTR_DONE_PENDING Setting */
+
+#define MXC_F_FLC_INTR_AF_POS 1 /**< INTR_AF Position */
+#define MXC_F_FLC_INTR_AF ((uint32_t)(0x1UL << MXC_F_FLC_INTR_AF_POS)) /**< INTR_AF Mask */
+#define MXC_V_FLC_INTR_AF_NOERROR ((uint32_t)0x0UL) /**< INTR_AF_NOERROR Value */
+#define MXC_S_FLC_INTR_AF_NOERROR (MXC_V_FLC_INTR_AF_NOERROR << MXC_F_FLC_INTR_AF_POS) /**< INTR_AF_NOERROR Setting */
+#define MXC_V_FLC_INTR_AF_ERROR ((uint32_t)0x1UL) /**< INTR_AF_ERROR Value */
+#define MXC_S_FLC_INTR_AF_ERROR (MXC_V_FLC_INTR_AF_ERROR << MXC_F_FLC_INTR_AF_POS) /**< INTR_AF_ERROR Setting */
+
+#define MXC_F_FLC_INTR_DONEIE_POS 8 /**< INTR_DONEIE Position */
+#define MXC_F_FLC_INTR_DONEIE ((uint32_t)(0x1UL << MXC_F_FLC_INTR_DONEIE_POS)) /**< INTR_DONEIE Mask */
+#define MXC_V_FLC_INTR_DONEIE_DISABLE ((uint32_t)0x0UL) /**< INTR_DONEIE_DISABLE Value */
+#define MXC_S_FLC_INTR_DONEIE_DISABLE \
+ (MXC_V_FLC_INTR_DONEIE_DISABLE << MXC_F_FLC_INTR_DONEIE_POS) /**< INTR_DONEIE_DISABLE Setting */
+#define MXC_V_FLC_INTR_DONEIE_ENABLE ((uint32_t)0x1UL) /**< INTR_DONEIE_ENABLE Value */
+#define MXC_S_FLC_INTR_DONEIE_ENABLE \
+ (MXC_V_FLC_INTR_DONEIE_ENABLE << MXC_F_FLC_INTR_DONEIE_POS) /**< INTR_DONEIE_ENABLE Setting */
+
+#define MXC_F_FLC_INTR_AFIE_POS 9 /**< INTR_AFIE Position */
+#define MXC_F_FLC_INTR_AFIE ((uint32_t)(0x1UL << MXC_F_FLC_INTR_AFIE_POS)) /**< INTR_AFIE Mask */
+
+/**@} end of group INTR_Register */
+
+/**
+ * @ingroup flc_registers
+ * @defgroup DATA_Register
+ * @brief Flash Write Data.
+ * @{
+ */
+#define MXC_F_FLC_DATA_DATA_POS 0 /**< DATA_DATA Position */
+#define MXC_F_FLC_DATA_DATA ((uint32_t)(0xFFFFFFFFUL << MXC_F_FLC_DATA_DATA_POS)) /**< DATA_DATA Mask */
+
+/**@} end of group DATA_Register */
+
+/**
+ * @ingroup flc_registers
+ * @defgroup ACNTL_Register
+ * @brief Access Control Register. Writing the ACNTL register with the following values in
+ * the order shown, allows read and write access to the system and user Information
+ * block: pflc-acntl = 0x3a7f5ca3; pflc-acntl = 0xa1e34f20; pflc-acntl =
+ * 0x9608b2c1. When unlocked, a write of any word will disable access to system and
+ * user information block. Readback of this register is always zero.
+ * @{
+ */
+#define MXC_F_FLC_ACNTL_ACNTL_POS 0 /**< ACNTL_ACNTL Position */
+#define MXC_F_FLC_ACNTL_ACNTL ((uint32_t)(0xFFFFFFFFUL << MXC_F_FLC_ACNTL_ACNTL_POS)) /**< ACNTL_ACNTL Mask */
+
+/**@} end of group ACNTL_Register */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _FLC_REGS_H_ */
diff --git a/contrib/loaders/flash/max32xxx/gcr_regs.h b/contrib/loaders/flash/max32xxx/gcr_regs.h
new file mode 100644
index 0000000000..0c5ccdbf3e
--- /dev/null
+++ b/contrib/loaders/flash/max32xxx/gcr_regs.h
@@ -0,0 +1,777 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
+/***************************************************************************
+ * Copyright (C) 2016 by Maxim Integrated *
+ * Copyright (C) 2025 Analog Devices, Inc. *
+ ***************************************************************************/
+
+#ifndef _GCR_REGS_H_
+#define _GCR_REGS_H_
+
+/* **** Includes **** */
+#include
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if defined(__ICCARM__)
+#pragma system_include
+#endif
+
+#if defined(__CC_ARM)
+#pragma anon_unions
+#endif
+/*/ @cond */
+/*
+ If types are not defined elsewhere (CMSIS) define them here
+*/
+#ifndef __IO
+#define __IO volatile
+#endif
+#ifndef __I
+#define __I volatile const
+#endif
+#ifndef __O
+#define __O volatile
+#endif
+#ifndef __R
+#define __R volatile const
+#endif
+/*/ @endcond */
+
+/* **** Definitions **** */
+
+/**
+ * @ingroup gcr
+ * @defgroup gcr_registers GCR_Registers
+ * @brief Registers, Bit Masks and Bit Positions for the GCR Peripheral Module.
+ * @details Global Control Registers.
+ */
+
+/**
+ * @ingroup gcr_registers
+ * Structure type to access the GCR Registers.
+ */
+struct mxc_gcr_regs {
+ __IO uint32_t scon; /**< \b 0x00: GCR SCON Register */
+ __IO uint32_t rstr0; /**< \b 0x04: GCR RSTR0 Register */
+ __IO uint32_t clkcn; /**< \b 0x08: GCR CLKCN Register */
+ __IO uint32_t pm; /**< \b 0x0C: GCR PM Register */
+ __R uint32_t rsv_0x10_0x17[2];
+ __IO uint32_t pckdiv; /**< \b 0x18: GCR PCKDIV Register */
+ __R uint32_t rsv_0x1c_0x23[2];
+ __IO uint32_t perckcn0; /**< \b 0x24: GCR PERCKCN0 Register */
+ __IO uint32_t memckcn; /**< \b 0x28: GCR MEMCKCN Register */
+ __IO uint32_t memzcn; /**< \b 0x2C: GCR MEMZCN Register */
+ __R uint32_t rsv_0x30_0x3f[4];
+ __IO uint32_t sysst; /**< \b 0x40: GCR SYSST Register */
+ __IO uint32_t rstr1; /**< \b 0x44: GCR RSTR1 Register */
+ __IO uint32_t perckcn1; /**< \b 0x48: GCR PERCKCN1 Register */
+ __IO uint32_t evten; /**< \b 0x4C: GCR EVTEN Register */
+ __I uint32_t revision; /**< \b 0x50: GCR REVISION Register */
+ __IO uint32_t syssie; /**< \b 0x54: GCR SYSSIE Register */
+ __R uint32_t rsv_0x58_0x63[3];
+ __IO uint32_t eccerr; /**< \b 0x64: GCR ECCERR Register */
+ __IO uint32_t eccnded; /**< \b 0x68: GCR ECCNDED Register */
+ __IO uint32_t eccirqen; /**< \b 0x6C: GCR ECCIRQEN Register */
+ __IO uint32_t eccerrad; /**< \b 0x70: GCR ECCERRAD Register */
+};
+
+/* Register offsets for module GCR */
+/**
+ * @ingroup gcr_registers
+ * @defgroup GCR_Register_Offsets Register Offsets
+ * @brief GCR Peripheral Register Offsets from the GCR Base Peripheral Address.
+ * @{
+ */
+#define MXC_R_GCR_SCON ((uint32_t)0x00000000UL) /**< Offset from GCR Base Address: 0x0000 */
+#define MXC_R_GCR_RSTR0 ((uint32_t)0x00000004UL) /**< Offset from GCR Base Address: 0x0004 */
+#define MXC_R_GCR_CLKCN ((uint32_t)0x00000008UL) /**< Offset from GCR Base Address: 0x0008 */
+#define MXC_R_GCR_PM ((uint32_t)0x0000000CUL) /**< Offset from GCR Base Address: 0x000C */
+#define MXC_R_GCR_PCKDIV ((uint32_t)0x00000018UL) /**< Offset from GCR Base Address: 0x0018 */
+#define MXC_R_GCR_PERCKCN0 ((uint32_t)0x00000024UL) /**< Offset from GCR Base Address: 0x0024 */
+#define MXC_R_GCR_MEMCKCN ((uint32_t)0x00000028UL) /**< Offset from GCR Base Address: 0x0028 */
+#define MXC_R_GCR_MEMZCN ((uint32_t)0x0000002CUL) /**< Offset from GCR Base Address: 0x002C */
+#define MXC_R_GCR_SYSST ((uint32_t)0x00000040UL) /**< Offset from GCR Base Address: 0x0040 */
+#define MXC_R_GCR_RSTR1 ((uint32_t)0x00000044UL) /**< Offset from GCR Base Address: 0x0044 */
+#define MXC_R_GCR_PERCKCN1 ((uint32_t)0x00000048UL) /**< Offset from GCR Base Address: 0x0048 */
+#define MXC_R_GCR_EVTEN ((uint32_t)0x0000004CUL) /**< Offset from GCR Base Address: 0x004C */
+#define MXC_R_GCR_REVISION ((uint32_t)0x00000050UL) /**< Offset from GCR Base Address: 0x0050 */
+#define MXC_R_GCR_SYSSIE ((uint32_t)0x00000054UL) /**< Offset from GCR Base Address: 0x0054 */
+#define MXC_R_GCR_ECCERR ((uint32_t)0x00000064UL) /**< Offset from GCR Base Address: 0x0064 */
+#define MXC_R_GCR_ECCNDED ((uint32_t)0x00000068UL) /**< Offset from GCR Base Address: 0x0068 */
+#define MXC_R_GCR_ECCIRQEN ((uint32_t)0x0000006CUL) /**< Offset from GCR Base Address: 0x006C */
+#define MXC_R_GCR_ECCERRAD ((uint32_t)0x00000070UL) /**< Offset from GCR Base Address: 0x0070 */
+ /**@} end of group gcr_registers */
+
+/**
+ * @ingroup gcr_registers
+ * @defgroup GCR_SCON GCR_SCON
+ * @brief System Control.
+ * @{
+ */
+#define MXC_F_GCR_SCON_BSTAPEN_POS 0 /**< SCON_BSTAPEN Position */
+#define MXC_F_GCR_SCON_BSTAPEN ((uint32_t)(0x1UL << MXC_F_GCR_SCON_BSTAPEN_POS)) /**< SCON_BSTAPEN Mask */
+#define MXC_V_GCR_SCON_BSTAPEN_DIS ((uint32_t)0x0UL) /**< SCON_BSTAPEN_DIS Value */
+#define MXC_S_GCR_SCON_BSTAPEN_DIS \
+ (MXC_V_GCR_SCON_BSTAPEN_DIS << MXC_F_GCR_SCON_BSTAPEN_POS) /**< SCON_BSTAPEN_DIS Setting */
+#define MXC_V_GCR_SCON_BSTAPEN_EN ((uint32_t)0x1UL) /**< SCON_BSTAPEN_EN Value */
+#define MXC_S_GCR_SCON_BSTAPEN_EN \
+ (MXC_V_GCR_SCON_BSTAPEN_EN << MXC_F_GCR_SCON_BSTAPEN_POS) /**< SCON_BSTAPEN_EN Setting */
+
+#define MXC_F_GCR_SCON_SBUSARB_POS 1 /**< SCON_SBUSARB Position */
+#define MXC_F_GCR_SCON_SBUSARB ((uint32_t)(0x3UL << MXC_F_GCR_SCON_SBUSARB_POS)) /**< SCON_SBUSARB Mask */
+#define MXC_V_GCR_SCON_SBUSARB_FIX ((uint32_t)0x0UL) /**< SCON_SBUSARB_FIX Value */
+#define MXC_S_GCR_SCON_SBUSARB_FIX \
+ (MXC_V_GCR_SCON_SBUSARB_FIX << MXC_F_GCR_SCON_SBUSARB_POS) /**< SCON_SBUSARB_FIX Setting */
+#define MXC_V_GCR_SCON_SBUSARB_ROUND ((uint32_t)0x1UL) /**< SCON_SBUSARB_ROUND Value */
+#define MXC_S_GCR_SCON_SBUSARB_ROUND \
+ (MXC_V_GCR_SCON_SBUSARB_ROUND << MXC_F_GCR_SCON_SBUSARB_POS) /**< SCON_SBUSARB_ROUND Setting */
+
+#define MXC_F_GCR_SCON_FLASH_PAGE_FLIP_POS 4 /**< SCON_FLASH_PAGE_FLIP Position */
+#define MXC_F_GCR_SCON_FLASH_PAGE_FLIP \
+ ((uint32_t)(0x1UL << MXC_F_GCR_SCON_FLASH_PAGE_FLIP_POS)) /**< SCON_FLASH_PAGE_FLIP Mask */
+#define MXC_V_GCR_SCON_FLASH_PAGE_FLIP_NORMAL ((uint32_t)0x0UL) /**< SCON_FLASH_PAGE_FLIP_NORMAL Value */
+#define MXC_S_GCR_SCON_FLASH_PAGE_FLIP_NORMAL \
+ (MXC_V_GCR_SCON_FLASH_PAGE_FLIP_NORMAL \
+ << MXC_F_GCR_SCON_FLASH_PAGE_FLIP_POS) /**< SCON_FLASH_PAGE_FLIP_NORMAL Setting */
+#define MXC_V_GCR_SCON_FLASH_PAGE_FLIP_SWAPPED ((uint32_t)0x1UL) /**< SCON_FLASH_PAGE_FLIP_SWAPPED Value */
+#define MXC_S_GCR_SCON_FLASH_PAGE_FLIP_SWAPPED \
+ (MXC_V_GCR_SCON_FLASH_PAGE_FLIP_SWAPPED \
+ << MXC_F_GCR_SCON_FLASH_PAGE_FLIP_POS) /**< SCON_FLASH_PAGE_FLIP_SWAPPED Setting */
+
+#define MXC_F_GCR_SCON_CCACHE_FLUSH_POS 6 /**< SCON_CCACHE_FLUSH Position */
+#define MXC_F_GCR_SCON_CCACHE_FLUSH \
+ ((uint32_t)(0x1UL << MXC_F_GCR_SCON_CCACHE_FLUSH_POS)) /**< SCON_CCACHE_FLUSH Mask */
+#define MXC_V_GCR_SCON_CCACHE_FLUSH_NORMAL ((uint32_t)0x0UL) /**< SCON_CCACHE_FLUSH_NORMAL Value */
+#define MXC_S_GCR_SCON_CCACHE_FLUSH_NORMAL \
+ (MXC_V_GCR_SCON_CCACHE_FLUSH_NORMAL << MXC_F_GCR_SCON_CCACHE_FLUSH_POS) /**< SCON_CCACHE_FLUSH_NORMAL Setting */
+#define MXC_V_GCR_SCON_CCACHE_FLUSH_FLUSH ((uint32_t)0x1UL) /**< SCON_CCACHE_FLUSH_FLUSH Value */
+#define MXC_S_GCR_SCON_CCACHE_FLUSH_FLUSH \
+ (MXC_V_GCR_SCON_CCACHE_FLUSH_FLUSH << MXC_F_GCR_SCON_CCACHE_FLUSH_POS) /**< SCON_CCACHE_FLUSH_FLUSH Setting */
+
+#define MXC_F_GCR_SCON_CCHK_POS 13 /**< SCON_CCHK Position */
+#define MXC_F_GCR_SCON_CCHK ((uint32_t)(0x1UL << MXC_F_GCR_SCON_CCHK_POS)) /**< SCON_CCHK Mask */
+#define MXC_V_GCR_SCON_CCHK_COMPLETE ((uint32_t)0x0UL) /**< SCON_CCHK_COMPLETE Value */
+#define MXC_S_GCR_SCON_CCHK_COMPLETE \
+ (MXC_V_GCR_SCON_CCHK_COMPLETE << MXC_F_GCR_SCON_CCHK_POS) /**< SCON_CCHK_COMPLETE Setting */
+#define MXC_V_GCR_SCON_CCHK_START ((uint32_t)0x1UL) /**< SCON_CCHK_START Value */
+#define MXC_S_GCR_SCON_CCHK_START (MXC_V_GCR_SCON_CCHK_START << MXC_F_GCR_SCON_CCHK_POS) /**< SCON_CCHK_START Setting \
+ */
+
+#define MXC_F_GCR_SCON_CHKRES_POS 15 /**< SCON_CHKRES Position */
+#define MXC_F_GCR_SCON_CHKRES ((uint32_t)(0x1UL << MXC_F_GCR_SCON_CHKRES_POS)) /**< SCON_CHKRES Mask */
+#define MXC_V_GCR_SCON_CHKRES_PASS ((uint32_t)0x0UL) /**< SCON_CHKRES_PASS Value */
+#define MXC_S_GCR_SCON_CHKRES_PASS \
+ (MXC_V_GCR_SCON_CHKRES_PASS << MXC_F_GCR_SCON_CHKRES_POS) /**< SCON_CHKRES_PASS Setting */
+#define MXC_V_GCR_SCON_CHKRES_FAIL ((uint32_t)0x1UL) /**< SCON_CHKRES_FAIL Value */
+#define MXC_S_GCR_SCON_CHKRES_FAIL \
+ (MXC_V_GCR_SCON_CHKRES_FAIL << MXC_F_GCR_SCON_CHKRES_POS) /**< SCON_CHKRES_FAIL Setting */
+
+#define MXC_F_GCR_SCON_OVR_POS 16 /**< SCON_OVR Position */
+#define MXC_F_GCR_SCON_OVR ((uint32_t)(0x3UL << MXC_F_GCR_SCON_OVR_POS)) /**< SCON_OVR Mask */
+#define MXC_V_GCR_SCON_OVR_0_9V ((uint32_t)0x0UL) /**< SCON_OVR_0_9V Value */
+#define MXC_S_GCR_SCON_OVR_0_9V (MXC_V_GCR_SCON_OVR_0_9V << MXC_F_GCR_SCON_OVR_POS) /**< SCON_OVR_0_9V Setting */
+#define MXC_V_GCR_SCON_OVR_1_0V ((uint32_t)0x1UL) /**< SCON_OVR_1_0V Value */
+#define MXC_S_GCR_SCON_OVR_1_0V (MXC_V_GCR_SCON_OVR_1_0V << MXC_F_GCR_SCON_OVR_POS) /**< SCON_OVR_1_0V Setting */
+#define MXC_V_GCR_SCON_OVR_1_1V ((uint32_t)0x2UL) /**< SCON_OVR_1_1V Value */
+#define MXC_S_GCR_SCON_OVR_1_1V (MXC_V_GCR_SCON_OVR_1_1V << MXC_F_GCR_SCON_OVR_POS) /**< SCON_OVR_1_1V Setting */
+
+#define MXC_F_GCR_SCON_MEMPROT_EN_POS 20 /**< SCON_MEMPROT_EN Position */
+#define MXC_F_GCR_SCON_MEMPROT_EN ((uint32_t)(0x1UL << MXC_F_GCR_SCON_MEMPROT_EN_POS)) /**< SCON_MEMPROT_EN Mask */
+#define MXC_V_GCR_SCON_MEMPROT_EN_DIS ((uint32_t)0x0UL) /**< SCON_MEMPROT_EN_DIS Value */
+#define MXC_S_GCR_SCON_MEMPROT_EN_DIS \
+ (MXC_V_GCR_SCON_MEMPROT_EN_DIS << MXC_F_GCR_SCON_MEMPROT_EN_POS) /**< SCON_MEMPROT_EN_DIS Setting */
+#define MXC_V_GCR_SCON_MEMPROT_EN_EN ((uint32_t)0x1UL) /**< SCON_MEMPROT_EN_EN Value */
+#define MXC_S_GCR_SCON_MEMPROT_EN_EN \
+ (MXC_V_GCR_SCON_MEMPROT_EN_EN << MXC_F_GCR_SCON_MEMPROT_EN_POS) /**< SCON_MEMPROT_EN_EN Setting */
+
+#define MXC_F_GCR_SCON_MEMPROT_KEYSZ_POS 21 /**< SCON_MEMPROT_KEYSZ Position */
+#define MXC_F_GCR_SCON_MEMPROT_KEYSZ \
+ ((uint32_t)(0x1UL << MXC_F_GCR_SCON_MEMPROT_KEYSZ_POS)) /**< SCON_MEMPROT_KEYSZ Mask */
+#define MXC_V_GCR_SCON_MEMPROT_KEYSZ_128 ((uint32_t)0x0UL) /**< SCON_MEMPROT_KEYSZ_128 Value */
+#define MXC_S_GCR_SCON_MEMPROT_KEYSZ_128 \
+ (MXC_V_GCR_SCON_MEMPROT_KEYSZ_128 << MXC_F_GCR_SCON_MEMPROT_KEYSZ_POS) /**< SCON_MEMPROT_KEYSZ_128 Setting */
+#define MXC_V_GCR_SCON_MEMPROT_KEYSZ_256 ((uint32_t)0x1UL) /**< SCON_MEMPROT_KEYSZ_256 Value */
+#define MXC_S_GCR_SCON_MEMPROT_KEYSZ_256 \
+ (MXC_V_GCR_SCON_MEMPROT_KEYSZ_256 << MXC_F_GCR_SCON_MEMPROT_KEYSZ_POS) /**< SCON_MEMPROT_KEYSZ_256 Setting */
+
+/**@} end of group GCR_SCON_Register */
+
+/**
+ * @ingroup gcr_registers
+ * @defgroup GCR_RSTR0 GCR_RSTR0
+ * @brief Reset.
+ * @{
+ */
+#define MXC_F_GCR_RSTR0_DMA_POS 0 /**< RSTR0_DMA Position */
+#define MXC_F_GCR_RSTR0_DMA ((uint32_t)(0x1UL << MXC_F_GCR_RSTR0_DMA_POS)) /**< RSTR0_DMA Mask */
+#define MXC_V_GCR_RSTR0_DMA_RESET_DONE ((uint32_t)0x0UL) /**< RSTR0_DMA_RESET_DONE Value */
+#define MXC_S_GCR_RSTR0_DMA_RESET_DONE \
+ (MXC_V_GCR_RSTR0_DMA_RESET_DONE << MXC_F_GCR_RSTR0_DMA_POS) /**< RSTR0_DMA_RESET_DONE Setting */
+#define MXC_V_GCR_RSTR0_DMA_BUSY ((uint32_t)0x1UL) /**< RSTR0_DMA_BUSY Value */
+#define MXC_S_GCR_RSTR0_DMA_BUSY (MXC_V_GCR_RSTR0_DMA_BUSY << MXC_F_GCR_RSTR0_DMA_POS) /**< RSTR0_DMA_BUSY Setting */
+
+#define MXC_F_GCR_RSTR0_WDT_POS 1 /**< RSTR0_WDT Position */
+#define MXC_F_GCR_RSTR0_WDT ((uint32_t)(0x1UL << MXC_F_GCR_RSTR0_WDT_POS)) /**< RSTR0_WDT Mask */
+
+#define MXC_F_GCR_RSTR0_GPIO0_POS 2 /**< RSTR0_GPIO0 Position */
+#define MXC_F_GCR_RSTR0_GPIO0 ((uint32_t)(0x1UL << MXC_F_GCR_RSTR0_GPIO0_POS)) /**< RSTR0_GPIO0 Mask */
+
+#define MXC_F_GCR_RSTR0_GPIO1_POS 3 /**< RSTR0_GPIO1 Position */
+#define MXC_F_GCR_RSTR0_GPIO1 ((uint32_t)(0x1UL << MXC_F_GCR_RSTR0_GPIO1_POS)) /**< RSTR0_GPIO1 Mask */
+
+#define MXC_F_GCR_RSTR0_TIMER0_POS 5 /**< RSTR0_TIMER0 Position */
+#define MXC_F_GCR_RSTR0_TIMER0 ((uint32_t)(0x1UL << MXC_F_GCR_RSTR0_TIMER0_POS)) /**< RSTR0_TIMER0 Mask */
+
+#define MXC_F_GCR_RSTR0_TIMER1_POS 6 /**< RSTR0_TIMER1 Position */
+#define MXC_F_GCR_RSTR0_TIMER1 ((uint32_t)(0x1UL << MXC_F_GCR_RSTR0_TIMER1_POS)) /**< RSTR0_TIMER1 Mask */
+
+#define MXC_F_GCR_RSTR0_TIMER2_POS 7 /**< RSTR0_TIMER2 Position */
+#define MXC_F_GCR_RSTR0_TIMER2 ((uint32_t)(0x1UL << MXC_F_GCR_RSTR0_TIMER2_POS)) /**< RSTR0_TIMER2 Mask */
+
+#define MXC_F_GCR_RSTR0_TIMER3_POS 8 /**< RSTR0_TIMER3 Position */
+#define MXC_F_GCR_RSTR0_TIMER3 ((uint32_t)(0x1UL << MXC_F_GCR_RSTR0_TIMER3_POS)) /**< RSTR0_TIMER3 Mask */
+
+#define MXC_F_GCR_RSTR0_UART0_POS 11 /**< RSTR0_UART0 Position */
+#define MXC_F_GCR_RSTR0_UART0 ((uint32_t)(0x1UL << MXC_F_GCR_RSTR0_UART0_POS)) /**< RSTR0_UART0 Mask */
+
+#define MXC_F_GCR_RSTR0_SPI0_POS 13 /**< RSTR0_SPI0 Position */
+#define MXC_F_GCR_RSTR0_SPI0 ((uint32_t)(0x1UL << MXC_F_GCR_RSTR0_SPI0_POS)) /**< RSTR0_SPI0 Mask */
+
+#define MXC_F_GCR_RSTR0_SPI1_POS 14 /**< RSTR0_SPI1 Position */
+#define MXC_F_GCR_RSTR0_SPI1 ((uint32_t)(0x1UL << MXC_F_GCR_RSTR0_SPI1_POS)) /**< RSTR0_SPI1 Mask */
+
+#define MXC_F_GCR_RSTR0_I2C0_POS 16 /**< RSTR0_I2C0 Position */
+#define MXC_F_GCR_RSTR0_I2C0 ((uint32_t)(0x1UL << MXC_F_GCR_RSTR0_I2C0_POS)) /**< RSTR0_I2C0 Mask */
+
+#define MXC_F_GCR_RSTR0_CRYPTO_POS 18 /**< RSTR0_CRYPTO Position */
+#define MXC_F_GCR_RSTR0_CRYPTO ((uint32_t)(0x1UL << MXC_F_GCR_RSTR0_CRYPTO_POS)) /**< RSTR0_CRYPTO Mask */
+
+#define MXC_F_GCR_RSTR0_SMPHR_POS 22 /**< RSTR0_SMPHR Position */
+#define MXC_F_GCR_RSTR0_SMPHR ((uint32_t)(0x1UL << MXC_F_GCR_RSTR0_SMPHR_POS)) /**< RSTR0_SMPHR Mask */
+
+#define MXC_F_GCR_RSTR0_TRNG_POS 24 /**< RSTR0_TRNG Position */
+#define MXC_F_GCR_RSTR0_TRNG ((uint32_t)(0x1UL << MXC_F_GCR_RSTR0_TRNG_POS)) /**< RSTR0_TRNG Mask */
+
+#define MXC_F_GCR_RSTR0_SRST_POS 29 /**< RSTR0_SRST Position */
+#define MXC_F_GCR_RSTR0_SRST ((uint32_t)(0x1UL << MXC_F_GCR_RSTR0_SRST_POS)) /**< RSTR0_SRST Mask */
+
+#define MXC_F_GCR_RSTR0_PRST_POS 30 /**< RSTR0_PRST Position */
+#define MXC_F_GCR_RSTR0_PRST ((uint32_t)(0x1UL << MXC_F_GCR_RSTR0_PRST_POS)) /**< RSTR0_PRST Mask */
+
+#define MXC_F_GCR_RSTR0_SYSTEM_POS 31 /**< RSTR0_SYSTEM Position */
+#define MXC_F_GCR_RSTR0_SYSTEM ((uint32_t)(0x1UL << MXC_F_GCR_RSTR0_SYSTEM_POS)) /**< RSTR0_SYSTEM Mask */
+
+/**@} end of group GCR_RSTR0_Register */
+
+/**
+ * @ingroup gcr_registers
+ * @defgroup GCR_CLKCN GCR_CLKCN
+ * @brief Clock Control.
+ * @{
+ */
+#define MXC_F_GCR_CLKCN_PSC_POS 6 /**< CLKCN_PSC Position */
+#define MXC_F_GCR_CLKCN_PSC ((uint32_t)(0x7UL << MXC_F_GCR_CLKCN_PSC_POS)) /**< CLKCN_PSC Mask */
+#define MXC_V_GCR_CLKCN_PSC_DIV1 ((uint32_t)0x0UL) /**< CLKCN_PSC_DIV1 Value */
+#define MXC_S_GCR_CLKCN_PSC_DIV1 (MXC_V_GCR_CLKCN_PSC_DIV1 << MXC_F_GCR_CLKCN_PSC_POS) /**< CLKCN_PSC_DIV1 Setting */
+#define MXC_V_GCR_CLKCN_PSC_DIV2 ((uint32_t)0x1UL) /**< CLKCN_PSC_DIV2 Value */
+#define MXC_S_GCR_CLKCN_PSC_DIV2 (MXC_V_GCR_CLKCN_PSC_DIV2 << MXC_F_GCR_CLKCN_PSC_POS) /**< CLKCN_PSC_DIV2 Setting */
+#define MXC_V_GCR_CLKCN_PSC_DIV4 ((uint32_t)0x2UL) /**< CLKCN_PSC_DIV4 Value */
+#define MXC_S_GCR_CLKCN_PSC_DIV4 (MXC_V_GCR_CLKCN_PSC_DIV4 << MXC_F_GCR_CLKCN_PSC_POS) /**< CLKCN_PSC_DIV4 Setting */
+#define MXC_V_GCR_CLKCN_PSC_DIV8 ((uint32_t)0x3UL) /**< CLKCN_PSC_DIV8 Value */
+#define MXC_S_GCR_CLKCN_PSC_DIV8 (MXC_V_GCR_CLKCN_PSC_DIV8 << MXC_F_GCR_CLKCN_PSC_POS) /**< CLKCN_PSC_DIV8 Setting */
+#define MXC_V_GCR_CLKCN_PSC_DIV16 ((uint32_t)0x4UL) /**< CLKCN_PSC_DIV16 Value */
+#define MXC_S_GCR_CLKCN_PSC_DIV16 (MXC_V_GCR_CLKCN_PSC_DIV16 << MXC_F_GCR_CLKCN_PSC_POS) /**< CLKCN_PSC_DIV16 Setting \
+ */
+#define MXC_V_GCR_CLKCN_PSC_DIV32 ((uint32_t)0x5UL) /**< CLKCN_PSC_DIV32 Value */
+#define MXC_S_GCR_CLKCN_PSC_DIV32 (MXC_V_GCR_CLKCN_PSC_DIV32 << MXC_F_GCR_CLKCN_PSC_POS) /**< CLKCN_PSC_DIV32 Setting \
+ */
+#define MXC_V_GCR_CLKCN_PSC_DIV64 ((uint32_t)0x6UL) /**< CLKCN_PSC_DIV64 Value */
+#define MXC_S_GCR_CLKCN_PSC_DIV64 (MXC_V_GCR_CLKCN_PSC_DIV64 << MXC_F_GCR_CLKCN_PSC_POS) /**< CLKCN_PSC_DIV64 Setting \
+ */
+#define MXC_V_GCR_CLKCN_PSC_DIV128 ((uint32_t)0x7UL) /**< CLKCN_PSC_DIV128 Value */
+#define MXC_S_GCR_CLKCN_PSC_DIV128 \
+ (MXC_V_GCR_CLKCN_PSC_DIV128 << MXC_F_GCR_CLKCN_PSC_POS) /**< CLKCN_PSC_DIV128 Setting */
+
+#define MXC_F_GCR_CLKCN_CLKSEL_POS 9 /**< CLKCN_CLKSEL Position */
+#define MXC_F_GCR_CLKCN_CLKSEL ((uint32_t)(0x7UL << MXC_F_GCR_CLKCN_CLKSEL_POS)) /**< CLKCN_CLKSEL Mask */
+#define MXC_V_GCR_CLKCN_CLKSEL_HIRC ((uint32_t)0x0UL) /**< CLKCN_CLKSEL_HIRC Value */
+#define MXC_S_GCR_CLKCN_CLKSEL_HIRC \
+ (MXC_V_GCR_CLKCN_CLKSEL_HIRC << MXC_F_GCR_CLKCN_CLKSEL_POS) /**< CLKCN_CLKSEL_HIRC Setting */
+#define MXC_V_GCR_CLKCN_CLKSEL_LIRC8 ((uint32_t)0x3UL) /**< CLKCN_CLKSEL_LIRC8 Value */
+#define MXC_S_GCR_CLKCN_CLKSEL_LIRC8 \
+ (MXC_V_GCR_CLKCN_CLKSEL_LIRC8 << MXC_F_GCR_CLKCN_CLKSEL_POS) /**< CLKCN_CLKSEL_LIRC8 Setting */
+#define MXC_V_GCR_CLKCN_CLKSEL_HIRC8 ((uint32_t)0x5UL) /**< CLKCN_CLKSEL_HIRC8 Value */
+#define MXC_S_GCR_CLKCN_CLKSEL_HIRC8 \
+ (MXC_V_GCR_CLKCN_CLKSEL_HIRC8 << MXC_F_GCR_CLKCN_CLKSEL_POS) /**< CLKCN_CLKSEL_HIRC8 Setting */
+
+#define MXC_F_GCR_CLKCN_CKRDY_POS 13 /**< CLKCN_CKRDY Position */
+#define MXC_F_GCR_CLKCN_CKRDY ((uint32_t)(0x1UL << MXC_F_GCR_CLKCN_CKRDY_POS)) /**< CLKCN_CKRDY Mask */
+#define MXC_V_GCR_CLKCN_CKRDY_BUSY ((uint32_t)0x0UL) /**< CLKCN_CKRDY_BUSY Value */
+#define MXC_S_GCR_CLKCN_CKRDY_BUSY \
+ (MXC_V_GCR_CLKCN_CKRDY_BUSY << MXC_F_GCR_CLKCN_CKRDY_POS) /**< CLKCN_CKRDY_BUSY Setting */
+#define MXC_V_GCR_CLKCN_CKRDY_READY ((uint32_t)0x1UL) /**< CLKCN_CKRDY_READY Value */
+#define MXC_S_GCR_CLKCN_CKRDY_READY \
+ (MXC_V_GCR_CLKCN_CKRDY_READY << MXC_F_GCR_CLKCN_CKRDY_POS) /**< CLKCN_CKRDY_READY Setting */
+
+#define MXC_F_GCR_CLKCN_HIRC_EN_POS 18 /**< CLKCN_HIRC_EN Position */
+#define MXC_F_GCR_CLKCN_HIRC_EN ((uint32_t)(0x1UL << MXC_F_GCR_CLKCN_HIRC_EN_POS)) /**< CLKCN_HIRC_EN Mask */
+#define MXC_V_GCR_CLKCN_HIRC_EN_DIS ((uint32_t)0x0UL) /**< CLKCN_HIRC_EN_DIS Value */
+#define MXC_S_GCR_CLKCN_HIRC_EN_DIS \
+ (MXC_V_GCR_CLKCN_HIRC_EN_DIS << MXC_F_GCR_CLKCN_HIRC_EN_POS) /**< CLKCN_HIRC_EN_DIS Setting */
+#define MXC_V_GCR_CLKCN_HIRC_EN_EN ((uint32_t)0x1UL) /**< CLKCN_HIRC_EN_EN Value */
+#define MXC_S_GCR_CLKCN_HIRC_EN_EN \
+ (MXC_V_GCR_CLKCN_HIRC_EN_EN << MXC_F_GCR_CLKCN_HIRC_EN_POS) /**< CLKCN_HIRC_EN_EN Setting */
+
+#define MXC_F_GCR_CLKCN_HIRC8M_EN_POS 20 /**< CLKCN_HIRC8M_EN Position */
+#define MXC_F_GCR_CLKCN_HIRC8M_EN ((uint32_t)(0x1UL << MXC_F_GCR_CLKCN_HIRC8M_EN_POS)) /**< CLKCN_HIRC8M_EN Mask */
+
+#define MXC_F_GCR_CLKCN_HIRC8M_VS_POS 21 /**< CLKCN_HIRC8M_VS Position */
+#define MXC_F_GCR_CLKCN_HIRC8M_VS ((uint32_t)(0x1UL << MXC_F_GCR_CLKCN_HIRC8M_VS_POS)) /**< CLKCN_HIRC8M_VS Mask */
+#define MXC_V_GCR_CLKCN_HIRC8M_VS_VCOR ((uint32_t)0x0UL) /**< CLKCN_HIRC8M_VS_VCOR Value */
+#define MXC_S_GCR_CLKCN_HIRC8M_VS_VCOR \
+ (MXC_V_GCR_CLKCN_HIRC8M_VS_VCOR << MXC_F_GCR_CLKCN_HIRC8M_VS_POS) /**< CLKCN_HIRC8M_VS_VCOR Setting */
+#define MXC_V_GCR_CLKCN_HIRC8M_VS_1V ((uint32_t)0x1UL) /**< CLKCN_HIRC8M_VS_1V Value */
+#define MXC_S_GCR_CLKCN_HIRC8M_VS_1V \
+ (MXC_V_GCR_CLKCN_HIRC8M_VS_1V << MXC_F_GCR_CLKCN_HIRC8M_VS_POS) /**< CLKCN_HIRC8M_VS_1V Setting */
+
+#define MXC_F_GCR_CLKCN_HIRC_RDY_POS 26 /**< CLKCN_HIRC_RDY Position */
+#define MXC_F_GCR_CLKCN_HIRC_RDY ((uint32_t)(0x1UL << MXC_F_GCR_CLKCN_HIRC_RDY_POS)) /**< CLKCN_HIRC_RDY Mask */
+#define MXC_V_GCR_CLKCN_HIRC_RDY_NOT ((uint32_t)0x0UL) /**< CLKCN_HIRC_RDY_NOT Value */
+#define MXC_S_GCR_CLKCN_HIRC_RDY_NOT \
+ (MXC_V_GCR_CLKCN_HIRC_RDY_NOT << MXC_F_GCR_CLKCN_HIRC_RDY_POS) /**< CLKCN_HIRC_RDY_NOT Setting */
+#define MXC_V_GCR_CLKCN_HIRC_RDY_READY ((uint32_t)0x1UL) /**< CLKCN_HIRC_RDY_READY Value */
+#define MXC_S_GCR_CLKCN_HIRC_RDY_READY \
+ (MXC_V_GCR_CLKCN_HIRC_RDY_READY << MXC_F_GCR_CLKCN_HIRC_RDY_POS) /**< CLKCN_HIRC_RDY_READY Setting */
+
+#define MXC_F_GCR_CLKCN_HIRC8M_RDY_POS 28 /**< CLKCN_HIRC8M_RDY Position */
+#define MXC_F_GCR_CLKCN_HIRC8M_RDY ((uint32_t)(0x1UL << MXC_F_GCR_CLKCN_HIRC8M_RDY_POS)) /**< CLKCN_HIRC8M_RDY Mask */
+
+#define MXC_F_GCR_CLKCN_LIRC8K_RDY_POS 29 /**< CLKCN_LIRC8K_RDY Position */
+#define MXC_F_GCR_CLKCN_LIRC8K_RDY ((uint32_t)(0x1UL << MXC_F_GCR_CLKCN_LIRC8K_RDY_POS)) /**< CLKCN_LIRC8K_RDY Mask */
+
+/**@} end of group GCR_CLKCN_Register */
+
+/**
+ * @ingroup gcr_registers
+ * @defgroup GCR_PM GCR_PM
+ * @brief Power Management.
+ * @{
+ */
+#define MXC_F_GCR_PM_MODE_POS 0 /**< PM_MODE Position */
+#define MXC_F_GCR_PM_MODE ((uint32_t)(0x7UL << MXC_F_GCR_PM_MODE_POS)) /**< PM_MODE Mask */
+#define MXC_V_GCR_PM_MODE_ACTIVE ((uint32_t)0x0UL) /**< PM_MODE_ACTIVE Value */
+#define MXC_S_GCR_PM_MODE_ACTIVE (MXC_V_GCR_PM_MODE_ACTIVE << MXC_F_GCR_PM_MODE_POS) /**< PM_MODE_ACTIVE Setting */
+#define MXC_V_GCR_PM_MODE_DEEPSLEEP ((uint32_t)0x2UL) /**< PM_MODE_DEEPSLEEP Value */
+#define MXC_S_GCR_PM_MODE_DEEPSLEEP \
+ (MXC_V_GCR_PM_MODE_DEEPSLEEP << MXC_F_GCR_PM_MODE_POS) /**< PM_MODE_DEEPSLEEP Setting */
+#define MXC_V_GCR_PM_MODE_SHUTDOWN ((uint32_t)0x3UL) /**< PM_MODE_SHUTDOWN Value */
+#define MXC_S_GCR_PM_MODE_SHUTDOWN \
+ (MXC_V_GCR_PM_MODE_SHUTDOWN << MXC_F_GCR_PM_MODE_POS) /**< PM_MODE_SHUTDOWN Setting */
+#define MXC_V_GCR_PM_MODE_BACKUP ((uint32_t)0x4UL) /**< PM_MODE_BACKUP Value */
+#define MXC_S_GCR_PM_MODE_BACKUP (MXC_V_GCR_PM_MODE_BACKUP << MXC_F_GCR_PM_MODE_POS) /**< PM_MODE_BACKUP Setting */
+
+#define MXC_F_GCR_PM_GPIOWKEN_POS 4 /**< PM_GPIOWKEN Position */
+#define MXC_F_GCR_PM_GPIOWKEN ((uint32_t)(0x1UL << MXC_F_GCR_PM_GPIOWKEN_POS)) /**< PM_GPIOWKEN Mask */
+#define MXC_V_GCR_PM_GPIOWKEN_DIS ((uint32_t)0x0UL) /**< PM_GPIOWKEN_DIS Value */
+#define MXC_S_GCR_PM_GPIOWKEN_DIS \
+ (MXC_V_GCR_PM_GPIOWKEN_DIS << MXC_F_GCR_PM_GPIOWKEN_POS) /**< PM_GPIOWKEN_DIS Setting */
+#define MXC_V_GCR_PM_GPIOWKEN_EN ((uint32_t)0x1UL) /**< PM_GPIOWKEN_EN Value */
+#define MXC_S_GCR_PM_GPIOWKEN_EN (MXC_V_GCR_PM_GPIOWKEN_EN << MXC_F_GCR_PM_GPIOWKEN_POS) /**< PM_GPIOWKEN_EN Setting \
+ */
+
+#define MXC_F_GCR_PM_HIRCPD_POS 15 /**< PM_HIRCPD Position */
+#define MXC_F_GCR_PM_HIRCPD ((uint32_t)(0x1UL << MXC_F_GCR_PM_HIRCPD_POS)) /**< PM_HIRCPD Mask */
+#define MXC_V_GCR_PM_HIRCPD_ACTIVE ((uint32_t)0x0UL) /**< PM_HIRCPD_ACTIVE Value */
+#define MXC_S_GCR_PM_HIRCPD_ACTIVE \
+ (MXC_V_GCR_PM_HIRCPD_ACTIVE << MXC_F_GCR_PM_HIRCPD_POS) /**< PM_HIRCPD_ACTIVE Setting */
+#define MXC_V_GCR_PM_HIRCPD_DEEPSLEEP ((uint32_t)0x1UL) /**< PM_HIRCPD_DEEPSLEEP Value */
+#define MXC_S_GCR_PM_HIRCPD_DEEPSLEEP \
+ (MXC_V_GCR_PM_HIRCPD_DEEPSLEEP << MXC_F_GCR_PM_HIRCPD_POS) /**< PM_HIRCPD_DEEPSLEEP Setting */
+
+#define MXC_F_GCR_PM_HIRC8MPD_POS 17 /**< PM_HIRC8MPD Position */
+#define MXC_F_GCR_PM_HIRC8MPD ((uint32_t)(0x1UL << MXC_F_GCR_PM_HIRC8MPD_POS)) /**< PM_HIRC8MPD Mask */
+
+/**@} end of group GCR_PM_Register */
+
+/**
+ * @ingroup gcr_registers
+ * @defgroup GCR_PCKDIV GCR_PCKDIV
+ * @brief Peripheral Clock Divider.
+ * @{
+ */
+#define MXC_F_GCR_PCKDIV_PCF_POS 0 /**< PCKDIV_PCF Position */
+#define MXC_F_GCR_PCKDIV_PCF ((uint32_t)(0x7UL << MXC_F_GCR_PCKDIV_PCF_POS)) /**< PCKDIV_PCF Mask */
+#define MXC_V_GCR_PCKDIV_PCF_96MHZ ((uint32_t)0x2UL) /**< PCKDIV_PCF_96MHZ Value */
+#define MXC_S_GCR_PCKDIV_PCF_96MHZ \
+ (MXC_V_GCR_PCKDIV_PCF_96MHZ << MXC_F_GCR_PCKDIV_PCF_POS) /**< PCKDIV_PCF_96MHZ Setting */
+#define MXC_V_GCR_PCKDIV_PCF_48MHZ ((uint32_t)0x3UL) /**< PCKDIV_PCF_48MHZ Value */
+#define MXC_S_GCR_PCKDIV_PCF_48MHZ \
+ (MXC_V_GCR_PCKDIV_PCF_48MHZ << MXC_F_GCR_PCKDIV_PCF_POS) /**< PCKDIV_PCF_48MHZ Setting */
+#define MXC_V_GCR_PCKDIV_PCF_24MHZ ((uint32_t)0x4UL) /**< PCKDIV_PCF_24MHZ Value */
+#define MXC_S_GCR_PCKDIV_PCF_24MHZ \
+ (MXC_V_GCR_PCKDIV_PCF_24MHZ << MXC_F_GCR_PCKDIV_PCF_POS) /**< PCKDIV_PCF_24MHZ Setting */
+#define MXC_V_GCR_PCKDIV_PCF_12MHZ ((uint32_t)0x5UL) /**< PCKDIV_PCF_12MHZ Value */
+#define MXC_S_GCR_PCKDIV_PCF_12MHZ \
+ (MXC_V_GCR_PCKDIV_PCF_12MHZ << MXC_F_GCR_PCKDIV_PCF_POS) /**< PCKDIV_PCF_12MHZ Setting */
+#define MXC_V_GCR_PCKDIV_PCF_6MHZ ((uint32_t)0x6UL) /**< PCKDIV_PCF_6MHZ Value */
+#define MXC_S_GCR_PCKDIV_PCF_6MHZ \
+ (MXC_V_GCR_PCKDIV_PCF_6MHZ << MXC_F_GCR_PCKDIV_PCF_POS) /**< PCKDIV_PCF_6MHZ Setting */
+#define MXC_V_GCR_PCKDIV_PCF_3MHZ ((uint32_t)0x7UL) /**< PCKDIV_PCF_3MHZ Value */
+#define MXC_S_GCR_PCKDIV_PCF_3MHZ \
+ (MXC_V_GCR_PCKDIV_PCF_3MHZ << MXC_F_GCR_PCKDIV_PCF_POS) /**< PCKDIV_PCF_3MHZ Setting */
+
+#define MXC_F_GCR_PCKDIV_PCFWEN_POS 3 /**< PCKDIV_PCFWEN Position */
+#define MXC_F_GCR_PCKDIV_PCFWEN ((uint32_t)(0x1UL << MXC_F_GCR_PCKDIV_PCFWEN_POS)) /**< PCKDIV_PCFWEN Mask */
+#define MXC_V_GCR_PCKDIV_PCFWEN_DISABLED ((uint32_t)0x0UL) /**< PCKDIV_PCFWEN_DISABLED Value */
+#define MXC_S_GCR_PCKDIV_PCFWEN_DISABLED \
+ (MXC_V_GCR_PCKDIV_PCFWEN_DISABLED << MXC_F_GCR_PCKDIV_PCFWEN_POS) /**< PCKDIV_PCFWEN_DISABLED Setting */
+#define MXC_V_GCR_PCKDIV_PCFWEN_ENABLED ((uint32_t)0x1UL) /**< PCKDIV_PCFWEN_ENABLED Value */
+#define MXC_S_GCR_PCKDIV_PCFWEN_ENABLED \
+ (MXC_V_GCR_PCKDIV_PCFWEN_ENABLED << MXC_F_GCR_PCKDIV_PCFWEN_POS) /**< PCKDIV_PCFWEN_ENABLED Setting */
+
+#define MXC_F_GCR_PCKDIV_AONCD_POS 14 /**< PCKDIV_AONCD Position */
+#define MXC_F_GCR_PCKDIV_AONCD ((uint32_t)(0x3UL << MXC_F_GCR_PCKDIV_AONCD_POS)) /**< PCKDIV_AONCD Mask */
+#define MXC_V_GCR_PCKDIV_AONCD_DIV_4 ((uint32_t)0x0UL) /**< PCKDIV_AONCD_DIV_4 Value */
+#define MXC_S_GCR_PCKDIV_AONCD_DIV_4 \
+ (MXC_V_GCR_PCKDIV_AONCD_DIV_4 << MXC_F_GCR_PCKDIV_AONCD_POS) /**< PCKDIV_AONCD_DIV_4 Setting */
+#define MXC_V_GCR_PCKDIV_AONCD_DIV_8 ((uint32_t)0x1UL) /**< PCKDIV_AONCD_DIV_8 Value */
+#define MXC_S_GCR_PCKDIV_AONCD_DIV_8 \
+ (MXC_V_GCR_PCKDIV_AONCD_DIV_8 << MXC_F_GCR_PCKDIV_AONCD_POS) /**< PCKDIV_AONCD_DIV_8 Setting */
+#define MXC_V_GCR_PCKDIV_AONCD_DIV_16 ((uint32_t)0x2UL) /**< PCKDIV_AONCD_DIV_16 Value */
+#define MXC_S_GCR_PCKDIV_AONCD_DIV_16 \
+ (MXC_V_GCR_PCKDIV_AONCD_DIV_16 << MXC_F_GCR_PCKDIV_AONCD_POS) /**< PCKDIV_AONCD_DIV_16 Setting */
+#define MXC_V_GCR_PCKDIV_AONCD_DIV_32 ((uint32_t)0x3UL) /**< PCKDIV_AONCD_DIV_32 Value */
+#define MXC_S_GCR_PCKDIV_AONCD_DIV_32 \
+ (MXC_V_GCR_PCKDIV_AONCD_DIV_32 << MXC_F_GCR_PCKDIV_AONCD_POS) /**< PCKDIV_AONCD_DIV_32 Setting */
+
+/**@} end of group GCR_PCKDIV_Register */
+
+/**
+ * @ingroup gcr_registers
+ * @defgroup GCR_PERCKCN0 GCR_PERCKCN0
+ * @brief Peripheral Clock Disable.
+ * @{
+ */
+#define MXC_F_GCR_PERCKCN0_GPIO0D_POS 0 /**< PERCKCN0_GPIO0D Position */
+#define MXC_F_GCR_PERCKCN0_GPIO0D ((uint32_t)(0x1UL << MXC_F_GCR_PERCKCN0_GPIO0D_POS)) /**< PERCKCN0_GPIO0D Mask */
+#define MXC_V_GCR_PERCKCN0_GPIO0D_EN ((uint32_t)0x0UL) /**< PERCKCN0_GPIO0D_EN Value */
+#define MXC_S_GCR_PERCKCN0_GPIO0D_EN \
+ (MXC_V_GCR_PERCKCN0_GPIO0D_EN << MXC_F_GCR_PERCKCN0_GPIO0D_POS) /**< PERCKCN0_GPIO0D_EN Setting */
+#define MXC_V_GCR_PERCKCN0_GPIO0D_DIS ((uint32_t)0x1UL) /**< PERCKCN0_GPIO0D_DIS Value */
+#define MXC_S_GCR_PERCKCN0_GPIO0D_DIS \
+ (MXC_V_GCR_PERCKCN0_GPIO0D_DIS << MXC_F_GCR_PERCKCN0_GPIO0D_POS) /**< PERCKCN0_GPIO0D_DIS Setting */
+
+#define MXC_F_GCR_PERCKCN0_GPIO1D_POS 1 /**< PERCKCN0_GPIO1D Position */
+#define MXC_F_GCR_PERCKCN0_GPIO1D ((uint32_t)(0x1UL << MXC_F_GCR_PERCKCN0_GPIO1D_POS)) /**< PERCKCN0_GPIO1D Mask */
+
+#define MXC_F_GCR_PERCKCN0_DMAD_POS 5 /**< PERCKCN0_DMAD Position */
+#define MXC_F_GCR_PERCKCN0_DMAD ((uint32_t)(0x1UL << MXC_F_GCR_PERCKCN0_DMAD_POS)) /**< PERCKCN0_DMAD Mask */
+
+#define MXC_F_GCR_PERCKCN0_SPI0D_POS 6 /**< PERCKCN0_SPI0D Position */
+#define MXC_F_GCR_PERCKCN0_SPI0D ((uint32_t)(0x1UL << MXC_F_GCR_PERCKCN0_SPI0D_POS)) /**< PERCKCN0_SPI0D Mask */
+
+#define MXC_F_GCR_PERCKCN0_SPI1D_POS 7 /**< PERCKCN0_SPI1D Position */
+#define MXC_F_GCR_PERCKCN0_SPI1D ((uint32_t)(0x1UL << MXC_F_GCR_PERCKCN0_SPI1D_POS)) /**< PERCKCN0_SPI1D Mask */
+
+#define MXC_F_GCR_PERCKCN0_UART0D_POS 9 /**< PERCKCN0_UART0D Position */
+#define MXC_F_GCR_PERCKCN0_UART0D ((uint32_t)(0x1UL << MXC_F_GCR_PERCKCN0_UART0D_POS)) /**< PERCKCN0_UART0D Mask */
+
+#define MXC_F_GCR_PERCKCN0_I2C0D_POS 13 /**< PERCKCN0_I2C0D Position */
+#define MXC_F_GCR_PERCKCN0_I2C0D ((uint32_t)(0x1UL << MXC_F_GCR_PERCKCN0_I2C0D_POS)) /**< PERCKCN0_I2C0D Mask */
+
+#define MXC_F_GCR_PERCKCN0_CRYPTOD_POS 14 /**< PERCKCN0_CRYPTOD Position */
+#define MXC_F_GCR_PERCKCN0_CRYPTOD ((uint32_t)(0x1UL << MXC_F_GCR_PERCKCN0_CRYPTOD_POS)) /**< PERCKCN0_CRYPTOD Mask */
+
+#define MXC_F_GCR_PERCKCN0_T0D_POS 15 /**< PERCKCN0_T0D Position */
+#define MXC_F_GCR_PERCKCN0_T0D ((uint32_t)(0x1UL << MXC_F_GCR_PERCKCN0_T0D_POS)) /**< PERCKCN0_T0D Mask */
+
+#define MXC_F_GCR_PERCKCN0_T1D_POS 16 /**< PERCKCN0_T1D Position */
+#define MXC_F_GCR_PERCKCN0_T1D ((uint32_t)(0x1UL << MXC_F_GCR_PERCKCN0_T1D_POS)) /**< PERCKCN0_T1D Mask */
+
+#define MXC_F_GCR_PERCKCN0_T2D_POS 17 /**< PERCKCN0_T2D Position */
+#define MXC_F_GCR_PERCKCN0_T2D ((uint32_t)(0x1UL << MXC_F_GCR_PERCKCN0_T2D_POS)) /**< PERCKCN0_T2D Mask */
+
+#define MXC_F_GCR_PERCKCN0_T3D_POS 18 /**< PERCKCN0_T3D Position */
+#define MXC_F_GCR_PERCKCN0_T3D ((uint32_t)(0x1UL << MXC_F_GCR_PERCKCN0_T3D_POS)) /**< PERCKCN0_T3D Mask */
+
+/**@} end of group GCR_PERCKCN0_Register */
+
+/**
+ * @ingroup gcr_registers
+ * @defgroup GCR_MEMCKCN GCR_MEMCKCN
+ * @brief Memory Clock Control Register.
+ * @{
+ */
+#define MXC_F_GCR_MEMCKCN_FWS_POS 0 /**< MEMCKCN_FWS Position */
+#define MXC_F_GCR_MEMCKCN_FWS ((uint32_t)(0x7UL << MXC_F_GCR_MEMCKCN_FWS_POS)) /**< MEMCKCN_FWS Mask */
+
+#define MXC_F_GCR_MEMCKCN_SYSRAM0LS_POS 16 /**< MEMCKCN_SYSRAM0LS Position */
+#define MXC_F_GCR_MEMCKCN_SYSRAM0LS \
+ ((uint32_t)(0x1UL << MXC_F_GCR_MEMCKCN_SYSRAM0LS_POS)) /**< MEMCKCN_SYSRAM0LS Mask */
+#define MXC_V_GCR_MEMCKCN_SYSRAM0LS_ACTIVE ((uint32_t)0x0UL) /**< MEMCKCN_SYSRAM0LS_ACTIVE Value */
+#define MXC_S_GCR_MEMCKCN_SYSRAM0LS_ACTIVE \
+ (MXC_V_GCR_MEMCKCN_SYSRAM0LS_ACTIVE << MXC_F_GCR_MEMCKCN_SYSRAM0LS_POS) /**< MEMCKCN_SYSRAM0LS_ACTIVE Setting */
+#define MXC_V_GCR_MEMCKCN_SYSRAM0LS_LIGHT_SLEEP ((uint32_t)0x1UL) /**< MEMCKCN_SYSRAM0LS_LIGHT_SLEEP Value */
+#define MXC_S_GCR_MEMCKCN_SYSRAM0LS_LIGHT_SLEEP \
+ (MXC_V_GCR_MEMCKCN_SYSRAM0LS_LIGHT_SLEEP \
+ << MXC_F_GCR_MEMCKCN_SYSRAM0LS_POS) /**< MEMCKCN_SYSRAM0LS_LIGHT_SLEEP Setting */
+
+#define MXC_F_GCR_MEMCKCN_SYSRAM1LS_POS 17 /**< MEMCKCN_SYSRAM1LS Position */
+#define MXC_F_GCR_MEMCKCN_SYSRAM1LS \
+ ((uint32_t)(0x1UL << MXC_F_GCR_MEMCKCN_SYSRAM1LS_POS)) /**< MEMCKCN_SYSRAM1LS Mask */
+
+#define MXC_F_GCR_MEMCKCN_SYSRAM2LS_POS 18 /**< MEMCKCN_SYSRAM2LS Position */
+#define MXC_F_GCR_MEMCKCN_SYSRAM2LS \
+ ((uint32_t)(0x1UL << MXC_F_GCR_MEMCKCN_SYSRAM2LS_POS)) /**< MEMCKCN_SYSRAM2LS Mask */
+
+#define MXC_F_GCR_MEMCKCN_SYSRAM3LS_POS 19 /**< MEMCKCN_SYSRAM3LS Position */
+#define MXC_F_GCR_MEMCKCN_SYSRAM3LS \
+ ((uint32_t)(0x1UL << MXC_F_GCR_MEMCKCN_SYSRAM3LS_POS)) /**< MEMCKCN_SYSRAM3LS Mask */
+
+#define MXC_F_GCR_MEMCKCN_SYSRAM4LS_POS 20 /**< MEMCKCN_SYSRAM4LS Position */
+#define MXC_F_GCR_MEMCKCN_SYSRAM4LS \
+ ((uint32_t)(0x1UL << MXC_F_GCR_MEMCKCN_SYSRAM4LS_POS)) /**< MEMCKCN_SYSRAM4LS Mask */
+
+#define MXC_F_GCR_MEMCKCN_ICACHELS_POS 24 /**< MEMCKCN_ICACHELS Position */
+#define MXC_F_GCR_MEMCKCN_ICACHELS ((uint32_t)(0x1UL << MXC_F_GCR_MEMCKCN_ICACHELS_POS)) /**< MEMCKCN_ICACHELS Mask */
+
+#define MXC_F_GCR_MEMCKCN_ROMLS_POS 29 /**< MEMCKCN_ROMLS Position */
+#define MXC_F_GCR_MEMCKCN_ROMLS ((uint32_t)(0x1UL << MXC_F_GCR_MEMCKCN_ROMLS_POS)) /**< MEMCKCN_ROMLS Mask */
+
+/**@} end of group GCR_MEMCKCN_Register */
+
+/**
+ * @ingroup gcr_registers
+ * @defgroup GCR_MEMZCN GCR_MEMZCN
+ * @brief Memory Zeroize Control.
+ * @{
+ */
+#define MXC_F_GCR_MEMZCN_SRAM0Z_POS 0 /**< MEMZCN_SRAM0Z Position */
+#define MXC_F_GCR_MEMZCN_SRAM0Z ((uint32_t)(0x1UL << MXC_F_GCR_MEMZCN_SRAM0Z_POS)) /**< MEMZCN_SRAM0Z Mask */
+#define MXC_V_GCR_MEMZCN_SRAM0Z_NOP ((uint32_t)0x0UL) /**< MEMZCN_SRAM0Z_NOP Value */
+#define MXC_S_GCR_MEMZCN_SRAM0Z_NOP \
+ (MXC_V_GCR_MEMZCN_SRAM0Z_NOP << MXC_F_GCR_MEMZCN_SRAM0Z_POS) /**< MEMZCN_SRAM0Z_NOP Setting */
+#define MXC_V_GCR_MEMZCN_SRAM0Z_START ((uint32_t)0x1UL) /**< MEMZCN_SRAM0Z_START Value */
+#define MXC_S_GCR_MEMZCN_SRAM0Z_START \
+ (MXC_V_GCR_MEMZCN_SRAM0Z_START << MXC_F_GCR_MEMZCN_SRAM0Z_POS) /**< MEMZCN_SRAM0Z_START Setting */
+
+#define MXC_F_GCR_MEMZCN_SRAM1Z_POS 1 /**< MEMZCN_SRAM1Z Position */
+#define MXC_F_GCR_MEMZCN_SRAM1Z ((uint32_t)(0x1UL << MXC_F_GCR_MEMZCN_SRAM1Z_POS)) /**< MEMZCN_SRAM1Z Mask */
+
+#define MXC_F_GCR_MEMZCN_SRAM2Z_POS 2 /**< MEMZCN_SRAM2Z Position */
+#define MXC_F_GCR_MEMZCN_SRAM2Z ((uint32_t)(0x1UL << MXC_F_GCR_MEMZCN_SRAM2Z_POS)) /**< MEMZCN_SRAM2Z Mask */
+
+#define MXC_F_GCR_MEMZCN_SRAM3Z_POS 3 /**< MEMZCN_SRAM3Z Position */
+#define MXC_F_GCR_MEMZCN_SRAM3Z ((uint32_t)(0x1UL << MXC_F_GCR_MEMZCN_SRAM3Z_POS)) /**< MEMZCN_SRAM3Z Mask */
+
+#define MXC_F_GCR_MEMZCN_SRAM4Z_POS 4 /**< MEMZCN_SRAM4Z Position */
+#define MXC_F_GCR_MEMZCN_SRAM4Z ((uint32_t)(0x1UL << MXC_F_GCR_MEMZCN_SRAM4Z_POS)) /**< MEMZCN_SRAM4Z Mask */
+
+#define MXC_F_GCR_MEMZCN_ICACHEZ_POS 8 /**< MEMZCN_ICACHEZ Position */
+#define MXC_F_GCR_MEMZCN_ICACHEZ ((uint32_t)(0x1UL << MXC_F_GCR_MEMZCN_ICACHEZ_POS)) /**< MEMZCN_ICACHEZ Mask */
+
+/**@} end of group GCR_MEMZCN_Register */
+
+/**
+ * @ingroup gcr_registers
+ * @defgroup GCR_SYSST GCR_SYSST
+ * @brief System Status Register.
+ * @{
+ */
+#define MXC_F_GCR_SYSST_ICECLOCK_POS 0 /**< SYSST_ICECLOCK Position */
+#define MXC_F_GCR_SYSST_ICECLOCK ((uint32_t)(0x1UL << MXC_F_GCR_SYSST_ICECLOCK_POS)) /**< SYSST_ICECLOCK Mask */
+#define MXC_V_GCR_SYSST_ICECLOCK_UNLOCKED ((uint32_t)0x0UL) /**< SYSST_ICECLOCK_UNLOCKED Value */
+#define MXC_S_GCR_SYSST_ICECLOCK_UNLOCKED \
+ (MXC_V_GCR_SYSST_ICECLOCK_UNLOCKED << MXC_F_GCR_SYSST_ICECLOCK_POS) /**< SYSST_ICECLOCK_UNLOCKED Setting */
+#define MXC_V_GCR_SYSST_ICECLOCK_LOCKED ((uint32_t)0x1UL) /**< SYSST_ICECLOCK_LOCKED Value */
+#define MXC_S_GCR_SYSST_ICECLOCK_LOCKED \
+ (MXC_V_GCR_SYSST_ICECLOCK_LOCKED << MXC_F_GCR_SYSST_ICECLOCK_POS) /**< SYSST_ICECLOCK_LOCKED Setting */
+
+/**@} end of group GCR_SYSST_Register */
+
+/**
+ * @ingroup gcr_registers
+ * @defgroup GCR_RSTR1 GCR_RSTR1
+ * @brief Reset 1.
+ * @{
+ */
+#define MXC_F_GCR_RSTR1_WDT1_POS 8 /**< RSTR1_WDT1 Position */
+#define MXC_F_GCR_RSTR1_WDT1 ((uint32_t)(0x1UL << MXC_F_GCR_RSTR1_WDT1_POS)) /**< RSTR1_WDT1 Mask */
+#define MXC_V_GCR_RSTR1_WDT1_RESET_DONE ((uint32_t)0x0UL) /**< RSTR1_WDT1_RESET_DONE Value */
+#define MXC_S_GCR_RSTR1_WDT1_RESET_DONE \
+ (MXC_V_GCR_RSTR1_WDT1_RESET_DONE << MXC_F_GCR_RSTR1_WDT1_POS) /**< RSTR1_WDT1_RESET_DONE Setting */
+#define MXC_V_GCR_RSTR1_WDT1_BUSY ((uint32_t)0x1UL) /**< RSTR1_WDT1_BUSY Value */
+#define MXC_S_GCR_RSTR1_WDT1_BUSY \
+ (MXC_V_GCR_RSTR1_WDT1_BUSY << MXC_F_GCR_RSTR1_WDT1_POS) /**< RSTR1_WDT1_BUSY Setting */
+
+#define MXC_F_GCR_RSTR1_PUFC_POS 27 /**< RSTR1_PUFC Position */
+#define MXC_F_GCR_RSTR1_PUFC ((uint32_t)(0x1UL << MXC_F_GCR_RSTR1_PUFC_POS)) /**< RSTR1_PUFC Mask */
+
+#define MXC_F_GCR_RSTR1_CSPIS_POS 28 /**< RSTR1_CSPIS Position */
+#define MXC_F_GCR_RSTR1_CSPIS ((uint32_t)(0x1UL << MXC_F_GCR_RSTR1_CSPIS_POS)) /**< RSTR1_CSPIS Mask */
+
+/**@} end of group GCR_RSTR1_Register */
+
+/**
+ * @ingroup gcr_registers
+ * @defgroup GCR_PERCKCN1 GCR_PERCKCN1
+ * @brief Peripheral Clock Disable.
+ * @{
+ */
+#define MXC_F_GCR_PERCKCN1_TRNGD_POS 2 /**< PERCKCN1_TRNGD Position */
+#define MXC_F_GCR_PERCKCN1_TRNGD ((uint32_t)(0x1UL << MXC_F_GCR_PERCKCN1_TRNGD_POS)) /**< PERCKCN1_TRNGD Mask */
+#define MXC_V_GCR_PERCKCN1_TRNGD_EN ((uint32_t)0x0UL) /**< PERCKCN1_TRNGD_EN Value */
+#define MXC_S_GCR_PERCKCN1_TRNGD_EN \
+ (MXC_V_GCR_PERCKCN1_TRNGD_EN << MXC_F_GCR_PERCKCN1_TRNGD_POS) /**< PERCKCN1_TRNGD_EN Setting */
+#define MXC_V_GCR_PERCKCN1_TRNGD_DIS ((uint32_t)0x1UL) /**< PERCKCN1_TRNGD_DIS Value */
+#define MXC_S_GCR_PERCKCN1_TRNGD_DIS \
+ (MXC_V_GCR_PERCKCN1_TRNGD_DIS << MXC_F_GCR_PERCKCN1_TRNGD_POS) /**< PERCKCN1_TRNGD_DIS Setting */
+
+#define MXC_F_GCR_PERCKCN1_PUFCD_POS 3 /**< PERCKCN1_PUFCD Position */
+#define MXC_F_GCR_PERCKCN1_PUFCD ((uint32_t)(0x1UL << MXC_F_GCR_PERCKCN1_PUFCD_POS)) /**< PERCKCN1_PUFCD Mask */
+
+#define MXC_F_GCR_PERCKCN1_ICACHED_POS 11 /**< PERCKCN1_ICACHED Position */
+#define MXC_F_GCR_PERCKCN1_ICACHED ((uint32_t)(0x1UL << MXC_F_GCR_PERCKCN1_ICACHED_POS)) /**< PERCKCN1_ICACHED Mask */
+
+#define MXC_F_GCR_PERCKCN1_CSPISD_POS 30 /**< PERCKCN1_CSPISD Position */
+#define MXC_F_GCR_PERCKCN1_CSPISD ((uint32_t)(0x1UL << MXC_F_GCR_PERCKCN1_CSPISD_POS)) /**< PERCKCN1_CSPISD Mask */
+
+/**@} end of group GCR_PERCKCN1_Register */
+
+/**
+ * @ingroup gcr_registers
+ * @defgroup GCR_EVTEN GCR_EVTEN
+ * @brief Event Enable Register.
+ * @{
+ */
+#define MXC_F_GCR_EVTEN_CPU0DMAEVENT_POS 0 /**< EVTEN_CPU0DMAEVENT Position */
+#define MXC_F_GCR_EVTEN_CPU0DMAEVENT \
+ ((uint32_t)(0x1UL << MXC_F_GCR_EVTEN_CPU0DMAEVENT_POS)) /**< EVTEN_CPU0DMAEVENT Mask */
+
+#define MXC_F_GCR_EVTEN_CPU0RXEVENT_POS 1 /**< EVTEN_CPU0RXEVENT Position */
+#define MXC_F_GCR_EVTEN_CPU0RXEVENT \
+ ((uint32_t)(0x1UL << MXC_F_GCR_EVTEN_CPU0RXEVENT_POS)) /**< EVTEN_CPU0RXEVENT Mask */
+
+#define MXC_F_GCR_EVTEN_CPU0TXEVENT_POS 2 /**< EVTEN_CPU0TXEVENT Position */
+#define MXC_F_GCR_EVTEN_CPU0TXEVENT \
+ ((uint32_t)(0x1UL << MXC_F_GCR_EVTEN_CPU0TXEVENT_POS)) /**< EVTEN_CPU0TXEVENT Mask */
+
+/**@} end of group GCR_EVTEN_Register */
+
+/**
+ * @ingroup gcr_registers
+ * @defgroup GCR_REVISION GCR_REVISION
+ * @brief Revision Register.
+ * @{
+ */
+#define MXC_F_GCR_REVISION_REVISION_POS 0 /**< REVISION_REVISION Position */
+#define MXC_F_GCR_REVISION_REVISION \
+ ((uint32_t)(0xFFFFUL << MXC_F_GCR_REVISION_REVISION_POS)) /**< REVISION_REVISION Mask */
+
+/**@} end of group GCR_REVISION_Register */
+
+/**
+ * @ingroup gcr_registers
+ * @defgroup GCR_SYSSIE GCR_SYSSIE
+ * @brief System Status Interrupt Enable Register.
+ * @{
+ */
+#define MXC_F_GCR_SYSSIE_ICEULIE_POS 0 /**< SYSSIE_ICEULIE Position */
+#define MXC_F_GCR_SYSSIE_ICEULIE ((uint32_t)(0x1UL << MXC_F_GCR_SYSSIE_ICEULIE_POS)) /**< SYSSIE_ICEULIE Mask */
+#define MXC_V_GCR_SYSSIE_ICEULIE_DIS ((uint32_t)0x0UL) /**< SYSSIE_ICEULIE_DIS Value */
+#define MXC_S_GCR_SYSSIE_ICEULIE_DIS \
+ (MXC_V_GCR_SYSSIE_ICEULIE_DIS << MXC_F_GCR_SYSSIE_ICEULIE_POS) /**< SYSSIE_ICEULIE_DIS Setting */
+#define MXC_V_GCR_SYSSIE_ICEULIE_EN ((uint32_t)0x1UL) /**< SYSSIE_ICEULIE_EN Value */
+#define MXC_S_GCR_SYSSIE_ICEULIE_EN \
+ (MXC_V_GCR_SYSSIE_ICEULIE_EN << MXC_F_GCR_SYSSIE_ICEULIE_POS) /**< SYSSIE_ICEULIE_EN Setting */
+
+/**@} end of group GCR_SYSSIE_Register */
+
+/**
+ * @ingroup gcr_registers
+ * @defgroup GCR_ECCERR GCR_ECCERR
+ * @brief ECC Error Register
+ * @{
+ */
+#define MXC_F_GCR_ECCERR_SYSRAM0ECCERR_POS 0 /**< ECCERR_SYSRAM0ECCERR Position */
+#define MXC_F_GCR_ECCERR_SYSRAM0ECCERR \
+ ((uint32_t)(0x1UL << MXC_F_GCR_ECCERR_SYSRAM0ECCERR_POS)) /**< ECCERR_SYSRAM0ECCERR Mask */
+
+#define MXC_F_GCR_ECCERR_SYSRAM1ECCERR_POS 1 /**< ECCERR_SYSRAM1ECCERR Position */
+#define MXC_F_GCR_ECCERR_SYSRAM1ECCERR \
+ ((uint32_t)(0x1UL << MXC_F_GCR_ECCERR_SYSRAM1ECCERR_POS)) /**< ECCERR_SYSRAM1ECCERR Mask */
+
+#define MXC_F_GCR_ECCERR_SYSRAM2ECCERR_POS 2 /**< ECCERR_SYSRAM2ECCERR Position */
+#define MXC_F_GCR_ECCERR_SYSRAM2ECCERR \
+ ((uint32_t)(0x1UL << MXC_F_GCR_ECCERR_SYSRAM2ECCERR_POS)) /**< ECCERR_SYSRAM2ECCERR Mask */
+
+#define MXC_F_GCR_ECCERR_SYSRAM3ECCERR_POS 3 /**< ECCERR_SYSRAM3ECCERR Position */
+#define MXC_F_GCR_ECCERR_SYSRAM3ECCERR \
+ ((uint32_t)(0x1UL << MXC_F_GCR_ECCERR_SYSRAM3ECCERR_POS)) /**< ECCERR_SYSRAM3ECCERR Mask */
+
+#define MXC_F_GCR_ECCERR_SYSRAM4ECCERR_POS 4 /**< ECCERR_SYSRAM4ECCERR Position */
+#define MXC_F_GCR_ECCERR_SYSRAM4ECCERR \
+ ((uint32_t)(0x1UL << MXC_F_GCR_ECCERR_SYSRAM4ECCERR_POS)) /**< ECCERR_SYSRAM4ECCERR Mask */
+
+/**@} end of group GCR_ECCERR_Register */
+
+/**
+ * @ingroup gcr_registers
+ * @defgroup GCR_ECCNDED GCR_ECCNDED
+ * @brief ECC Not Double Error Detect Register
+ * @{
+ */
+#define MXC_F_GCR_ECCNDED_SYSRAM0ECCNDED_POS 0 /**< ECCNDED_SYSRAM0ECCNDED Position */
+#define MXC_F_GCR_ECCNDED_SYSRAM0ECCNDED \
+ ((uint32_t)(0x1UL << MXC_F_GCR_ECCNDED_SYSRAM0ECCNDED_POS)) /**< ECCNDED_SYSRAM0ECCNDED Mask */
+
+#define MXC_F_GCR_ECCNDED_SYSRAM1ECCNDED_POS 1 /**< ECCNDED_SYSRAM1ECCNDED Position */
+#define MXC_F_GCR_ECCNDED_SYSRAM1ECCNDED \
+ ((uint32_t)(0x1UL << MXC_F_GCR_ECCNDED_SYSRAM1ECCNDED_POS)) /**< ECCNDED_SYSRAM1ECCNDED Mask */
+
+#define MXC_F_GCR_ECCNDED_SYSRAM2ECCNDED_POS 2 /**< ECCNDED_SYSRAM2ECCNDED Position */
+#define MXC_F_GCR_ECCNDED_SYSRAM2ECCNDED \
+ ((uint32_t)(0x1UL << MXC_F_GCR_ECCNDED_SYSRAM2ECCNDED_POS)) /**< ECCNDED_SYSRAM2ECCNDED Mask */
+
+#define MXC_F_GCR_ECCNDED_SYSRAM3ECCNDED_POS 3 /**< ECCNDED_SYSRAM3ECCNDED Position */
+#define MXC_F_GCR_ECCNDED_SYSRAM3ECCNDED \
+ ((uint32_t)(0x1UL << MXC_F_GCR_ECCNDED_SYSRAM3ECCNDED_POS)) /**< ECCNDED_SYSRAM3ECCNDED Mask */
+
+#define MXC_F_GCR_ECCNDED_SYSRAM4ECCNDED_POS 4 /**< ECCNDED_SYSRAM4ECCNDED Position */
+#define MXC_F_GCR_ECCNDED_SYSRAM4ECCNDED \
+ ((uint32_t)(0x1UL << MXC_F_GCR_ECCNDED_SYSRAM4ECCNDED_POS)) /**< ECCNDED_SYSRAM4ECCNDED Mask */
+
+/**@} end of group GCR_ECCNDED_Register */
+
+/**
+ * @ingroup gcr_registers
+ * @defgroup GCR_ECCIRQEN GCR_ECCIRQEN
+ * @brief ECC IRQ Enable Register
+ * @{
+ */
+#define MXC_F_GCR_ECCIRQEN_ECCERAD_POS 0 /**< ECCIRQEN_ECCERAD Position */
+#define MXC_F_GCR_ECCIRQEN_ECCERAD \
+ ((uint32_t)(0x7FFFFFFFUL << MXC_F_GCR_ECCIRQEN_ECCERAD_POS)) /**< ECCIRQEN_ECCERAD Mask */
+
+/**@} end of group GCR_ECCIRQEN_Register */
+
+/**
+ * @ingroup gcr_registers
+ * @defgroup GCR_ECCERRAD GCR_ECCERRAD
+ * @brief ECC Error Address Register
+ * @{
+ */
+#define MXC_F_GCR_ECCERRAD_ECCERAD_POS 0 /**< ECCERRAD_ECCERAD Position */
+#define MXC_F_GCR_ECCERRAD_ECCERAD \
+ ((uint32_t)(0x7FFFFFFFUL << MXC_F_GCR_ECCERRAD_ECCERAD_POS)) /**< ECCERRAD_ECCERAD Mask */
+
+/**@} end of group GCR_ECCERRAD_Register */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _GCR_REGS_H_ */
diff --git a/contrib/loaders/flash/max32xxx/max32xxx.inc b/contrib/loaders/flash/max32xxx/max32xxx.inc
deleted file mode 100644
index 442165d0d1..0000000000
--- a/contrib/loaders/flash/max32xxx/max32xxx.inc
+++ /dev/null
@@ -1,6 +0,0 @@
-/* Autogenerated with ../../../../src/helper/bin2char.sh */
-0xdf,0xf8,0x44,0x40,0xd0,0xf8,0x00,0x80,0xb8,0xf1,0x00,0x0f,0x1a,0xd0,0x47,0x68,
-0x47,0x45,0xf7,0xd0,0x22,0x60,0x02,0xf1,0x04,0x02,0x57,0xf8,0x04,0x8b,0xc4,0xf8,
-0x30,0x80,0xa5,0x68,0x45,0xf0,0x01,0x05,0xa5,0x60,0xd4,0xf8,0x08,0x80,0x18,0xf0,
-0x01,0x0f,0xfa,0xd1,0x8f,0x42,0x28,0xbf,0x00,0xf1,0x08,0x07,0x47,0x60,0x01,0x3b,
-0x03,0xb1,0xdf,0xe7,0x00,0xbe,0x00,0xbf,0x00,0x00,0x00,0x40,
diff --git a/contrib/loaders/flash/max32xxx/max32xxx.s b/contrib/loaders/flash/max32xxx/max32xxx.s
deleted file mode 100644
index 38a4f12c32..0000000000
--- a/contrib/loaders/flash/max32xxx/max32xxx.s
+++ /dev/null
@@ -1,59 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-or-later */
-
-/***************************************************************************
- * Copyright (C) 2016 by Maxim Integrated *
- * Kevin Gillespie
+#else
+#define printf(...)
+#endif
+
+/***** Definitions *****/
+#define MXC_BASE_TPU ((uint32_t)0x40001000UL)
+#define MXC_TPU ((struct mxc_tpu_regs *)MXC_BASE_TPU)
+#define MXC_BASE_GCR ((uint32_t)0x40000000UL)
+#define MXC_GCR ((struct mxc_gcr_regs *)MXC_BASE_GCR)
+
+/******************************************************************************/
+#define getbyte(temp8) \
+/* Wait for the Read FIFO to not equal the Write FIFO */ \
+ do { while (*read_ptr == *write_ptr); \
+ temp8 = **read_ptr; \
+/* Increment and wrap around the read pointer */ \
+ if ((*read_ptr + 1) >= (uint8_t *)(work_end - 8 - 256)) { \
+ *read_ptr = (uint8_t *)(work_start + 8); \
+ } else { \
+ (*read_ptr)++; \
+ } \
+ len--; \
+ addr++; } while (0)
+
+/******************************************************************************/
+#ifndef ALGO_TEST
+__attribute__ ((naked, section(".algo")))
+#endif
+void algo_write(uint8_t *work_start, uint8_t *work_end, uint32_t len, uint32_t addr)
+{
+ printf(" > %s starting\n", __func__);
+
+ volatile uint8_t * (*write_ptr) = (volatile uint8_t **)work_start;
+ volatile uint8_t * (*read_ptr) = (volatile uint8_t **)(work_start + 4);
+ uint32_t *flc_base = (uint32_t *)(work_end - 4 - 128);
+ uint32_t *options = (uint32_t *)(work_end - 8 - 128);
+ uint32_t *enc_buffer = (uint32_t *)(work_end - 8 - 256);
+ uint8_t temp8;
+ uint32_t addr_save;
+ int i;
+ struct mxc_flc_regs *MXC_FLC = (struct mxc_flc_regs *)*flc_base;
+
+ printf(" > w%08x r%08x o%08x f%08x b%08x b%08x\n",
+ (uint32_t)write_ptr, (uint32_t)read_ptr, (uint32_t)*options, (uint32_t)*flc_base,
+ (uint32_t)enc_buffer, (uint32_t)(enc_buffer + 256));
+
+ if (*options & OPTIONS_ENC) {
+ /* Enable Memory Protection */
+ MXC_GCR->scon |= MXC_F_GCR_SCON_MEMPROT_EN;
+
+ /* Set the keysize */
+ if (*options & OPTIONS_KEYSIZE)
+ MXC_GCR->scon |= MXC_F_GCR_SCON_MEMPROT_KEYSZ;
+ else
+ MXC_GCR->scon &= ~(MXC_F_GCR_SCON_MEMPROT_KEYSZ);
+ } else {
+ /* Disable memory protection */
+ MXC_GCR->scon &= ~MXC_F_GCR_SCON_MEMPROT_EN;
+ }
+
+ if (*options & OPTIONS_ENC) {
+ /* Setup the AES */
+
+ /* Enable CRYPTO clock */
+ if ((MXC_GCR->clkcn & MXC_F_GCR_CLKCN_HIRC_EN) == 0)
+ MXC_GCR->clkcn |= MXC_F_GCR_CLKCN_HIRC_EN;
+
+ /* Disable CRYPTO clock gate */
+ if (MXC_GCR->perckcn0 & MXC_F_GCR_PERCKCN0_CRYPTOD)
+ MXC_GCR->perckcn0 &= ~(MXC_F_GCR_PERCKCN0_CRYPTOD);
+
+ /* Reset Crypto block and clear state */
+ MXC_TPU->ctrl = MXC_F_TPU_CTRL_RST;
+
+ /* Set the legacy bit */
+ MXC_TPU->ctrl |= MXC_F_TPU_CTRL_FLAG_MODE;
+
+ /* Byte swap the input and output */
+ MXC_TPU->ctrl |= MXC_F_TPU_CTRL_BSO;
+ MXC_TPU->ctrl |= MXC_F_TPU_CTRL_BSI;
+ }
+
+ while (len) {
+ if ((*options & OPTIONS_128) == 0) {
+ /* Save the current address before we read from the working area */
+ addr_save = addr;
+
+ /* 32-bit write */
+ MXC_FLC->cn |= MXC_F_FLC_CN_WDTH;
+
+ enc_buffer[0] = 0;
+ for (i = 0; i < 4; i++) {
+ /* Get data from the working area, pad with 0xFF */
+ if (len) {
+ getbyte(temp8);
+ __asm("nop\n");
+ } else {
+ temp8 = 0xFF;
+ __asm("nop\n");
+ }
+ enc_buffer[0] |= (temp8 << (i * 8));
+ }
+
+ /* 32-bit write */
+ MXC_FLC->cn |= MXC_F_FLC_CN_WDTH;
+
+ MXC_FLC->addr = addr_save;
+ MXC_FLC->data[0] = enc_buffer[0];
+
+ /* Enable the write */
+ MXC_FLC->cn |= MXC_F_FLC_CN_WR;
+
+ /* Wait for the operation to complete */
+ do {} while (MXC_FLC->cn & MXC_F_FLC_CN_WR);
+
+ /* Check access violations */
+ if (MXC_FLC->intr & MXC_F_FLC_INTR_AF) {
+ MXC_FLC->intr &= ~MXC_F_FLC_INTR_AF;
+ #ifndef ALGO_TEST
+ #ifdef __riscv
+ __asm("ebreak\n");
+ #else
+ __asm("bkpt\n");
+ #endif
+ #else
+ printf(" > Error writing to flash\n");
+ return;
+ #endif
+ }
+ } else {
+ /* Save the current address before we read from the working area */
+ addr_save = addr;
+
+ /* Fill the buffer with the plain text data from the working area */
+ for (i = 0; i < 4; i++) {
+ /* Get data from the working area, pad with 0xFF */
+ enc_buffer[i] = 0;
+ if (len) {
+ getbyte(temp8);
+ __asm("nop\n");
+ } else {
+ temp8 = 0xFF;
+ __asm("nop\n");
+ }
+ enc_buffer[i] |= (temp8 << (0));
+ /* Get data from the working area, pad with 0xFF */
+ if (len) {
+ getbyte(temp8);
+ __asm("nop\n");
+ } else {
+ temp8 = 0xFF;
+ __asm("nop\n");
+ }
+ enc_buffer[i] |= (temp8 << (8));
+ /* Get data from the working area, pad with 0xFF */
+ if (len) {
+ getbyte(temp8);
+ __asm("nop\n");
+ } else {
+ temp8 = 0xFF;
+ __asm("nop\n");
+ }
+ enc_buffer[i] |= (temp8 << (16));
+ /* Get data from the working area, pad with 0xFF */
+ if (len) {
+ getbyte(temp8);
+ __asm("nop\n");
+ } else {
+ temp8 = 0xFF;
+ __asm("nop\n");
+ }
+ enc_buffer[i] |= (temp8 << (24));
+ }
+
+ if (*options & OPTIONS_ENC) {
+ /* XOR data with the address */
+ for (i = 0; i < 4; i++) {
+ if (*options & OPTIONS_RELATIVE_XOR)
+ enc_buffer[i] ^= ((addr_save & 0x00FFFFFF) + i * 4);
+ else
+ enc_buffer[i] ^= (addr_save + i * 4);
+ }
+
+ /* Encrypt the plain text
+ * Clear interrupt flags*/
+ MXC_TPU->ctrl |= MXC_F_TPU_CTRL_CPH_DONE;
+
+ MXC_TPU->cipher_ctrl = ((0x0 << MXC_F_TPU_CIPHER_CTRL_MODE_POS) |
+ (0x0 << MXC_F_TPU_CIPHER_CTRL_ENC_POS));
+
+ if (*options & OPTIONS_KEYSIZE) {
+ /* ECB, AES-256, encrypt */
+ MXC_TPU->cipher_ctrl |=
+ (0x3 << MXC_F_TPU_CIPHER_CTRL_CIPHER_POS);
+ } else {
+ /* ECB, AES-128, encrypt */
+ MXC_TPU->cipher_ctrl |=
+ (0x1 << MXC_F_TPU_CIPHER_CTRL_CIPHER_POS);
+ }
+
+ /* Set the key source */
+ MXC_TPU->cipher_ctrl =
+ ((MXC_TPU->cipher_ctrl & ~MXC_F_TPU_CIPHER_CTRL_SRC) |
+ (0x3 << MXC_F_TPU_CIPHER_CTRL_SRC_POS));
+
+ /* Copy data to start the operation */
+ MXC_TPU->din[0] = enc_buffer[0];
+ MXC_TPU->din[1] = enc_buffer[1];
+ MXC_TPU->din[2] = enc_buffer[2];
+ MXC_TPU->din[3] = enc_buffer[3];
+
+ /* Wait until operation is complete */
+ do {} while (!(MXC_TPU->ctrl & MXC_F_TPU_CTRL_CPH_DONE));
+
+ /* Copy the data out */
+ enc_buffer[0] = MXC_TPU->dout[0];
+ enc_buffer[1] = MXC_TPU->dout[1];
+ enc_buffer[2] = MXC_TPU->dout[2];
+ enc_buffer[3] = MXC_TPU->dout[3];
+ }
+
+ /* 128-bit write */
+ MXC_FLC->cn &= ~MXC_F_FLC_CN_WDTH;
+
+ MXC_FLC->addr = addr_save;
+ MXC_FLC->data[0] = enc_buffer[0];
+ MXC_FLC->data[1] = enc_buffer[1];
+ MXC_FLC->data[2] = enc_buffer[2];
+ MXC_FLC->data[3] = enc_buffer[3];
+
+ /* Enable the write */
+ MXC_FLC->cn |= MXC_F_FLC_CN_WR;
+
+ /* Wait for the operation to complete */
+ do {} while (MXC_FLC->cn & MXC_F_FLC_CN_WR);
+
+ /* Check access violations */
+ if (MXC_FLC->intr & MXC_F_FLC_INTR_AF) {
+ MXC_FLC->intr &= ~MXC_F_FLC_INTR_AF;
+ #ifndef ALGO_TEST
+ #ifdef __riscv
+ __asm("ebreak\n");
+ #else
+ __asm("bkpt\n");
+ #endif
+ printf(" > Error writing to flash\n");
+ return;
+ #endif
+ }
+ }
+ }
+
+ #ifndef ALGO_TEST
+ #ifdef __riscv
+ __asm("ebreak\n");
+ #else
+ __asm("bkpt\n");
+ #endif
+ #else
+ printf(" > %s returning\n", __func__);
+ return;
+ #endif
+}
diff --git a/contrib/loaders/flash/max32xxx/max32xxx_write_arm.inc b/contrib/loaders/flash/max32xxx/max32xxx_write_arm.inc
new file mode 100644
index 0000000000..cdc373071a
--- /dev/null
+++ b/contrib/loaders/flash/max32xxx/max32xxx_write_arm.inc
@@ -0,0 +1,57 @@
+/* Autogenerated with ../../../../src/helper/bin2char.sh */
+0x51,0xe9,0x22,0x54,0x15,0xf0,0x02,0x0f,0x4f,0xf0,0x80,0x45,0x00,0x93,0xa1,0xf5,
+0x84,0x76,0x2f,0x68,0x00,0xf0,0x90,0x80,0x47,0xf4,0x80,0x17,0x2f,0x60,0x51,0xf8,
+0x88,0x7c,0x17,0xf0,0x40,0x0f,0x2f,0x68,0x14,0xbf,0x47,0xf4,0x00,0x17,0x27,0xf4,
+0x00,0x17,0x2f,0x60,0x51,0xf8,0x88,0x5c,0xad,0x07,0x1e,0xd5,0x4f,0xf0,0x80,0x45,
+0xaf,0x68,0x7b,0x03,0x5e,0xbf,0xaf,0x68,0x47,0xf4,0x80,0x27,0xaf,0x60,0x6f,0x6a,
+0x7f,0x04,0x42,0xbf,0x6f,0x6a,0x27,0xf4,0x80,0x47,0x6f,0x62,0xc0,0x4d,0x01,0x27,
+0x2f,0x60,0x2f,0x68,0x47,0xf4,0x80,0x47,0x2f,0x60,0x2f,0x68,0x47,0xf0,0x10,0x07,
+0x2f,0x60,0x2f,0x68,0x47,0xf0,0x20,0x07,0x2f,0x60,0xa1,0xf1,0xfc,0x05,0x03,0x95,
+0x00,0xf1,0x08,0x05,0x01,0x95,0xa1,0xf5,0x82,0x75,0x02,0x95,0xb4,0x4d,0xa1,0xf5,
+0x80,0x7c,0x00,0x2a,0x00,0xf0,0x63,0x81,0x51,0xf8,0x88,0x7c,0x17,0xf0,0x01,0x0e,
+0x50,0xd1,0xa7,0x68,0x47,0xf0,0x10,0x07,0xa7,0x60,0x00,0x9f,0xc6,0xf8,0x00,0xe0,
+0x00,0x2a,0x44,0xd0,0xd0,0xf8,0x04,0x90,0xd0,0xf8,0x00,0x80,0xc1,0x45,0xf9,0xd0,
+0xd0,0xf8,0x04,0x80,0xd0,0xf8,0x04,0x90,0x98,0xf8,0x00,0x80,0x09,0xf1,0x01,0x09,
+0x4e,0x45,0x8d,0xbf,0xd0,0xf8,0x04,0x90,0x01,0x9b,0x43,0x60,0x09,0xf1,0x01,0x09,
+0x88,0xbf,0xc0,0xf8,0x04,0x90,0x01,0x3a,0x01,0x37,0x33,0x68,0x08,0xfa,0x0e,0xf8,
+0x0e,0xf1,0x08,0x0e,0x43,0xea,0x08,0x08,0xbe,0xf1,0x20,0x0f,0xc6,0xf8,0x00,0x80,
+0xd6,0xd1,0xd4,0xf8,0x08,0xe0,0x00,0x9b,0x4e,0xf0,0x10,0x0e,0xc4,0xf8,0x08,0xe0,
+0x23,0x60,0x33,0x68,0x23,0x63,0xa3,0x68,0x43,0xf0,0x01,0x03,0xa3,0x60,0xa3,0x68,
+0xdb,0x07,0xfc,0xd4,0x63,0x6a,0x9b,0x07,0x04,0xd5,0x63,0x6a,0x23,0xf0,0x02,0x03,
+0x63,0x62,0x00,0xbe,0x00,0x97,0xac,0xe7,0x27,0xf4,0x80,0x17,0x79,0xe7,0x4f,0xf0,
+0xff,0x08,0xd2,0xe7,0xa1,0xf5,0x86,0x78,0x00,0x9f,0xc1,0x46,0x00,0x23,0x49,0xf8,
+0x04,0x3f,0x00,0x2a,0x00,0xf0,0x06,0x81,0xd0,0xf8,0x04,0xa0,0xd0,0xf8,0x00,0xe0,
+0xf2,0x45,0xf9,0xd0,0xd0,0xf8,0x04,0xe0,0xd0,0xf8,0x04,0xa0,0x9e,0xf8,0x00,0xe0,
+0x0a,0xf1,0x01,0x0a,0x56,0x45,0x8d,0xbf,0xd0,0xf8,0x04,0xa0,0x01,0x9b,0x43,0x60,
+0x0a,0xf1,0x01,0x0a,0x88,0xbf,0xc0,0xf8,0x04,0xa0,0x01,0x3a,0x01,0x37,0xc9,0xf8,
+0x00,0xe0,0x00,0x2a,0x00,0xf0,0xe9,0x80,0xd0,0xf8,0x04,0xb0,0xd0,0xf8,0x00,0xa0,
+0xd3,0x45,0xf9,0xd0,0xd0,0xf8,0x04,0xa0,0x9a,0xf8,0x00,0xb0,0xd0,0xf8,0x04,0xa0,
+0x0a,0xf1,0x01,0x0a,0x56,0x45,0x8d,0xbf,0xd0,0xf8,0x04,0xa0,0x01,0x9b,0x43,0x60,
+0x0a,0xf1,0x01,0x0a,0x88,0xbf,0xc0,0xf8,0x04,0xa0,0x01,0x3a,0x01,0x37,0x4e,0xea,
+0x0b,0x2e,0xc9,0xf8,0x00,0xe0,0x00,0x2a,0x00,0xf0,0xca,0x80,0xd0,0xf8,0x04,0xb0,
+0xd0,0xf8,0x00,0xa0,0xd3,0x45,0xf9,0xd0,0xd0,0xf8,0x04,0xa0,0x9a,0xf8,0x00,0xb0,
+0xd0,0xf8,0x04,0xa0,0x0a,0xf1,0x01,0x0a,0x56,0x45,0x8d,0xbf,0xd0,0xf8,0x04,0xa0,
+0x01,0x9b,0x43,0x60,0x0a,0xf1,0x01,0x0a,0x88,0xbf,0xc0,0xf8,0x04,0xa0,0x01,0x3a,
+0x01,0x37,0x4e,0xea,0x0b,0x4e,0xc9,0xf8,0x00,0xe0,0x00,0x2a,0x00,0xf0,0xab,0x80,
+0xd0,0xf8,0x04,0xb0,0xd0,0xf8,0x00,0xa0,0xd3,0x45,0xf9,0xd0,0xd0,0xf8,0x04,0xa0,
+0x9a,0xf8,0x00,0xb0,0xd0,0xf8,0x04,0xa0,0x0a,0xf1,0x01,0x0a,0x56,0x45,0x8d,0xbf,
+0xd0,0xf8,0x04,0xa0,0x01,0x9b,0x43,0x60,0x0a,0xf1,0x01,0x0a,0x88,0xbf,0xc0,0xf8,
+0x04,0xa0,0x01,0x3a,0x01,0x37,0x03,0x9b,0x4e,0xea,0x0b,0x6e,0x99,0x45,0xc9,0xf8,
+0x00,0xe0,0x7f,0xf4,0x73,0xaf,0x51,0xf8,0x88,0x3c,0x9b,0x07,0x55,0xd5,0x00,0x9b,
+0x4f,0xf0,0x00,0x0e,0x23,0xf0,0x7f,0x4a,0x51,0xf8,0x88,0x3c,0x58,0xf8,0x04,0x9f,
+0x9b,0x06,0x56,0xbf,0x00,0x9b,0x0a,0xeb,0x0e,0x0b,0x0e,0xeb,0x03,0x0b,0x0e,0xf1,
+0x04,0x0e,0x8b,0xea,0x09,0x09,0xbe,0xf1,0x10,0x0f,0xc8,0xf8,0x00,0x90,0xeb,0xd1,
+0xd5,0xf8,0x00,0xe0,0x4e,0xf0,0x00,0x6e,0xc5,0xf8,0x00,0xe0,0x4f,0xf0,0x00,0x0e,
+0xc5,0xf8,0x04,0xe0,0x51,0xf8,0x88,0x3c,0xd5,0xf8,0x04,0xe0,0x5b,0x06,0x4c,0xbf,
+0x4e,0xf0,0x30,0x0e,0x4e,0xf0,0x10,0x0e,0xc5,0xf8,0x04,0xe0,0xd5,0xf8,0x04,0xe0,
+0x4e,0xf0,0x0c,0x0e,0xc5,0xf8,0x04,0xe0,0x33,0x68,0x2b,0x62,0x02,0x9b,0x1b,0x68,
+0x6b,0x62,0xdc,0xf8,0x00,0x30,0xab,0x62,0x51,0xf8,0xfc,0x3c,0xeb,0x62,0xd5,0xf8,
+0x00,0xe0,0x1e,0xf0,0x00,0x6f,0xfa,0xd0,0xd5,0xf8,0x30,0xe0,0xc6,0xf8,0x00,0xe0,
+0x02,0x9b,0xd5,0xf8,0x34,0xe0,0xc3,0xf8,0x00,0xe0,0xd5,0xf8,0x38,0xe0,0xcc,0xf8,
+0x00,0xe0,0xd5,0xf8,0x3c,0xe0,0x41,0xf8,0xfc,0xec,0xd4,0xf8,0x08,0xe0,0x00,0x9b,
+0x2e,0xf0,0x10,0x0e,0xc4,0xf8,0x08,0xe0,0x23,0x60,0x33,0x68,0x23,0x63,0x02,0x9b,
+0x1b,0x68,0x63,0x63,0xdc,0xf8,0x00,0x30,0xa3,0x63,0x51,0xf8,0xfc,0x3c,0xe3,0x63,
+0xa3,0x68,0x43,0xf0,0x01,0x03,0xa3,0x60,0xa3,0x68,0xdb,0x07,0xfc,0xd4,0x63,0x6a,
+0x9b,0x07,0x7f,0xf5,0xef,0xae,0x63,0x6a,0x23,0xf0,0x02,0x03,0x63,0x62,0x00,0xbe,
+0x00,0x10,0x00,0x40,0x4f,0xf0,0xff,0x0e,0x11,0xe7,0x4f,0xf0,0xff,0x0b,0x2e,0xe7,
+0x4f,0xf0,0xff,0x0b,0x4d,0xe7,0x4f,0xf0,0xff,0x0b,0x6c,0xe7,
diff --git a/contrib/loaders/flash/max32xxx/tpu_regs.h b/contrib/loaders/flash/max32xxx/tpu_regs.h
new file mode 100644
index 0000000000..f750148af2
--- /dev/null
+++ b/contrib/loaders/flash/max32xxx/tpu_regs.h
@@ -0,0 +1,572 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
+/***************************************************************************
+ * Copyright (C) 2016 by Maxim Integrated *
+ * Copyright (C) 2025 Analog Devices, Inc. *
+ ***************************************************************************/
+
+#ifndef _TPU_REGS_H_
+#define _TPU_REGS_H_
+
+/* **** Includes **** */
+#include
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if defined(__ICCARM__)
+#pragma system_include
+#endif
+
+/*/ @cond */
+/*
+ If types are not defined elsewhere (CMSIS) define them here
+*/
+#ifndef __IO
+#define __IO volatile
+#endif
+#ifndef __I
+#define __I volatile const
+#endif
+#ifndef __O
+#define __O volatile
+#endif
+#ifndef __R
+#define __R volatile const
+#endif
+/*/ @endcond */
+
+/* **** Definitions **** */
+
+/**
+ * @ingroup tpu
+ * @defgroup tpu_registers Registers
+ * @brief Registers, Bit Masks and Bit Positions for the TPU Peripheral Module.
+ * @description The Trust Protection Unit used to assist the computationally intensive operations of several common
+ * cryptographic algorithms.
+ */
+
+/**
+ * @ingroup tpu_registers
+ * Structure type to access the TPU Registers.
+ */
+struct mxc_tpu_regs {
+ __IO uint32_t ctrl; /**< \b 0x00:<\tt> TPU CTRL Register */
+ __IO uint32_t cipher_ctrl; /**< \b 0x04:<\tt> TPU CIPHER_CTRL Register */
+ __IO uint32_t hash_ctrl; /**< \b 0x08:<\tt> TPU HASH_CTRL Register */
+ __IO uint32_t crc_ctrl; /**< \b 0x0C:<\tt> TPU CRC_CTRL Register */
+ __IO uint32_t dma_src; /**< \b 0x10:<\tt> TPU DMA_SRC Register */
+ __IO uint32_t dma_dest; /**< \b 0x14:<\tt> TPU DMA_DEST Register */
+ __IO uint32_t dma_cnt; /**< \b 0x18:<\tt> TPU DMA_CNT Register */
+ __IO uint32_t maa_ctrl; /**< \b 0x1C:<\tt> TPU MAA_CTRL Register */
+ __O uint32_t din[4]; /**< \b 0x20:<\tt> TPU DIN Register */
+ __I uint32_t dout[4]; /**< \b 0x30:<\tt> TPU DOUT Register */
+ __IO uint32_t crc_poly; /**< \b 0x40:<\tt> TPU CRC_POLY Register */
+ __IO uint32_t crc_val; /**< \b 0x44:<\tt> TPU CRC_VAL Register */
+ __I uint32_t crc_prng; /**< \b 0x48:<\tt> TPU CRC_PRNG Register */
+ __IO uint32_t ham_ecc; /**< \b 0x4C:<\tt> TPU HAM_ECC Register */
+ __IO uint32_t cipher_init[4]; /**< \b 0x50:<\tt> TPU CIPHER_INIT Register */
+ __O uint32_t cipher_key[8]; /**< \b 0x60:<\tt> TPU CIPHER_KEY Register */
+ __IO uint32_t hash_digest[16]; /**< \b 0x80:<\tt> TPU HASH_DIGEST Register */
+ __IO uint32_t hash_msg_sz[4]; /**< \b 0xC0:<\tt> TPU HASH_MSG_SZ Register */
+ __IO uint32_t maa_maws; /**< \b 0xD0:<\tt> TPU MAA_MAWS Register */
+};
+
+/* Register offsets for module TPU */
+/**
+ * @ingroup tpu_registers
+ * @defgroup TPU_Register_Offsets Register Offsets
+ * @brief TPU Peripheral Register Offsets from the TPU Base Peripheral Address.
+ * @{
+ */
+#define MXC_R_TPU_CTRL ((uint32_t)0x00000000UL) /**< Offset from TPU Base Address: 0x0x000 */
+#define MXC_R_TPU_CIPHER_CTRL ((uint32_t)0x00000004UL) /**< Offset from TPU Base Address: 0x0x004 */
+#define MXC_R_TPU_HASH_CTRL ((uint32_t)0x00000008UL) /**< Offset from TPU Base Address: 0x0x008 */
+#define MXC_R_TPU_CRC_CTRL ((uint32_t)0x0000000CUL) /**< Offset from TPU Base Address: 0x0x00C */
+#define MXC_R_TPU_DMA_SRC ((uint32_t)0x00000010UL) /**< Offset from TPU Base Address: 0x0x010 */
+#define MXC_R_TPU_DMA_DEST ((uint32_t)0x00000014UL) /**< Offset from TPU Base Address: 0x0x014 */
+#define MXC_R_TPU_DMA_CNT ((uint32_t)0x00000018UL) /**< Offset from TPU Base Address: 0x0x018 */
+#define MXC_R_TPU_MAA_CTRL ((uint32_t)0x0000001CUL) /**< Offset from TPU Base Address: 0x0x01C */
+#define MXC_R_TPU_DIN ((uint32_t)0x00000020UL) /**< Offset from TPU Base Address: 0x0x020 */
+#define MXC_R_TPU_DOUT ((uint32_t)0x00000030UL) /**< Offset from TPU Base Address: 0x0x030 */
+#define MXC_R_TPU_CRC_POLY ((uint32_t)0x00000040UL) /**< Offset from TPU Base Address: 0x0x040 */
+#define MXC_R_TPU_CRC_VAL ((uint32_t)0x00000044UL) /**< Offset from TPU Base Address: 0x0x044 */
+#define MXC_R_TPU_CRC_PRNG ((uint32_t)0x00000048UL) /**< Offset from TPU Base Address: 0x0x048 */
+#define MXC_R_TPU_HAM_ECC ((uint32_t)0x0000004CUL) /**< Offset from TPU Base Address: 0x0x04C */
+#define MXC_R_TPU_CIPHER_INIT ((uint32_t)0x00000050UL) /**< Offset from TPU Base Address: 0x0x050 */
+#define MXC_R_TPU_CIPHER_KEY ((uint32_t)0x00000060UL) /**< Offset from TPU Base Address: 0x0x060 */
+#define MXC_R_TPU_HASH_DIGEST ((uint32_t)0x00000080UL) /**< Offset from TPU Base Address: 0x0x080 */
+#define MXC_R_TPU_HASH_MSG_SZ ((uint32_t)0x000000C0UL) /**< Offset from TPU Base Address: 0x0x0C0 */
+#define MXC_R_TPU_MAA_MAWS ((uint32_t)0x000000D0UL) /**< Offset from TPU Base Address: 0x0x0D0 */
+ /**@} end of group tpu_registers */
+
+/**
+ * @ingroup tpu_registers
+ * @defgroup CTRL_Register
+ * @brief Crypto Control Register.
+ * @{
+ */
+#define MXC_F_TPU_CTRL_RST_POS 0 /**< CTRL_RST Position */
+#define MXC_F_TPU_CTRL_RST ((uint32_t)(0x1UL << MXC_F_TPU_CTRL_RST_POS)) /**< CTRL_RST Mask */
+
+#define MXC_F_TPU_CTRL_INTR_POS 1 /**< CTRL_INTR Position */
+#define MXC_F_TPU_CTRL_INTR ((uint32_t)(0x1UL << MXC_F_TPU_CTRL_INTR_POS)) /**< CTRL_INTR Mask */
+
+#define MXC_F_TPU_CTRL_SRC_POS 2 /**< CTRL_SRC Position */
+#define MXC_F_TPU_CTRL_SRC ((uint32_t)(0x1UL << MXC_F_TPU_CTRL_SRC_POS)) /**< CTRL_SRC Mask */
+
+#define MXC_F_TPU_CTRL_BSO_POS 4 /**< CTRL_BSO Position */
+#define MXC_F_TPU_CTRL_BSO ((uint32_t)(0x1UL << MXC_F_TPU_CTRL_BSO_POS)) /**< CTRL_BSO Mask */
+
+#define MXC_F_TPU_CTRL_BSI_POS 5 /**< CTRL_BSI Position */
+#define MXC_F_TPU_CTRL_BSI ((uint32_t)(0x1UL << MXC_F_TPU_CTRL_BSI_POS)) /**< CTRL_BSI Mask */
+
+#define MXC_F_TPU_CTRL_WAIT_EN_POS 6 /**< CTRL_WAIT_EN Position */
+#define MXC_F_TPU_CTRL_WAIT_EN ((uint32_t)(0x1UL << MXC_F_TPU_CTRL_WAIT_EN_POS)) /**< CTRL_WAIT_EN Mask */
+
+#define MXC_F_TPU_CTRL_WAIT_POL_POS 7 /**< CTRL_WAIT_POL Position */
+#define MXC_F_TPU_CTRL_WAIT_POL ((uint32_t)(0x1UL << MXC_F_TPU_CTRL_WAIT_POL_POS)) /**< CTRL_WAIT_POL Mask */
+
+#define MXC_F_TPU_CTRL_WRSRC_POS 8 /**< CTRL_WRSRC Position */
+#define MXC_F_TPU_CTRL_WRSRC ((uint32_t)(0x3UL << MXC_F_TPU_CTRL_WRSRC_POS)) /**< CTRL_WRSRC Mask */
+#define MXC_V_TPU_CTRL_WRSRC_NONE ((uint32_t)0x0UL) /**< CTRL_WRSRC_NONE Value */
+#define MXC_S_TPU_CTRL_WRSRC_NONE \
+ (MXC_V_TPU_CTRL_WRSRC_NONE << MXC_F_TPU_CTRL_WRSRC_POS) /**< CTRL_WRSRC_NONE Setting */
+#define MXC_V_TPU_CTRL_WRSRC_CIPHEROUTPUT ((uint32_t)0x1UL) /**< CTRL_WRSRC_CIPHEROUTPUT Value */
+#define MXC_S_TPU_CTRL_WRSRC_CIPHEROUTPUT \
+ (MXC_V_TPU_CTRL_WRSRC_CIPHEROUTPUT << MXC_F_TPU_CTRL_WRSRC_POS) /**< CTRL_WRSRC_CIPHEROUTPUT Setting */
+#define MXC_V_TPU_CTRL_WRSRC_READFIFO ((uint32_t)0x2UL) /**< CTRL_WRSRC_READFIFO Value */
+#define MXC_S_TPU_CTRL_WRSRC_READFIFO \
+ (MXC_V_TPU_CTRL_WRSRC_READFIFO << MXC_F_TPU_CTRL_WRSRC_POS) /**< CTRL_WRSRC_READFIFO Setting */
+#define MXC_V_TPU_CTRL_WRSRC_RFU ((uint32_t)0x3UL) /**< CTRL_WRSRC_RFU Value */
+#define MXC_S_TPU_CTRL_WRSRC_RFU (MXC_V_TPU_CTRL_WRSRC_RFU << MXC_F_TPU_CTRL_WRSRC_POS) /**< CTRL_WRSRC_RFU Setting */
+
+#define MXC_F_TPU_CTRL_RDSRC_POS 10 /**< CTRL_RDSRC Position */
+#define MXC_F_TPU_CTRL_RDSRC ((uint32_t)(0x3UL << MXC_F_TPU_CTRL_RDSRC_POS)) /**< CTRL_RDSRC Mask */
+#define MXC_V_TPU_CTRL_RDSRC_DMADISABLED ((uint32_t)0x0UL) /**< CTRL_RDSRC_DMADISABLED Value */
+#define MXC_S_TPU_CTRL_RDSRC_DMADISABLED \
+ (MXC_V_TPU_CTRL_RDSRC_DMADISABLED << MXC_F_TPU_CTRL_RDSRC_POS) /**< CTRL_RDSRC_DMADISABLED Setting */
+#define MXC_V_TPU_CTRL_RDSRC_DMAORAPB ((uint32_t)0x1UL) /**< CTRL_RDSRC_DMAORAPB Value */
+#define MXC_S_TPU_CTRL_RDSRC_DMAORAPB \
+ (MXC_V_TPU_CTRL_RDSRC_DMAORAPB << MXC_F_TPU_CTRL_RDSRC_POS) /**< CTRL_RDSRC_DMAORAPB Setting */
+#define MXC_V_TPU_CTRL_RDSRC_RNG ((uint32_t)0x2UL) /**< CTRL_RDSRC_RNG Value */
+#define MXC_S_TPU_CTRL_RDSRC_RNG (MXC_V_TPU_CTRL_RDSRC_RNG << MXC_F_TPU_CTRL_RDSRC_POS) /**< CTRL_RDSRC_RNG Setting */
+
+#define MXC_F_TPU_CTRL_FLAG_MODE_POS 14 /**< CTRL_FLAG_MODE Position */
+#define MXC_F_TPU_CTRL_FLAG_MODE ((uint32_t)(0x1UL << MXC_F_TPU_CTRL_FLAG_MODE_POS)) /**< CTRL_FLAG_MODE Mask */
+
+#define MXC_F_TPU_CTRL_DMADNEMSK_POS 15 /**< CTRL_DMADNEMSK Position */
+#define MXC_F_TPU_CTRL_DMADNEMSK ((uint32_t)(0x1UL << MXC_F_TPU_CTRL_DMADNEMSK_POS)) /**< CTRL_DMADNEMSK Mask */
+
+#define MXC_F_TPU_CTRL_DMA_DONE_POS 24 /**< CTRL_DMA_DONE Position */
+#define MXC_F_TPU_CTRL_DMA_DONE ((uint32_t)(0x1UL << MXC_F_TPU_CTRL_DMA_DONE_POS)) /**< CTRL_DMA_DONE Mask */
+
+#define MXC_F_TPU_CTRL_GLS_DONE_POS 25 /**< CTRL_GLS_DONE Position */
+#define MXC_F_TPU_CTRL_GLS_DONE ((uint32_t)(0x1UL << MXC_F_TPU_CTRL_GLS_DONE_POS)) /**< CTRL_GLS_DONE Mask */
+
+#define MXC_F_TPU_CTRL_HSH_DONE_POS 26 /**< CTRL_HSH_DONE Position */
+#define MXC_F_TPU_CTRL_HSH_DONE ((uint32_t)(0x1UL << MXC_F_TPU_CTRL_HSH_DONE_POS)) /**< CTRL_HSH_DONE Mask */
+
+#define MXC_F_TPU_CTRL_CPH_DONE_POS 27 /**< CTRL_CPH_DONE Position */
+#define MXC_F_TPU_CTRL_CPH_DONE ((uint32_t)(0x1UL << MXC_F_TPU_CTRL_CPH_DONE_POS)) /**< CTRL_CPH_DONE Mask */
+
+#define MXC_F_TPU_CTRL_MAA_DONE_POS 28 /**< CTRL_MAA_DONE Position */
+#define MXC_F_TPU_CTRL_MAA_DONE ((uint32_t)(0x1UL << MXC_F_TPU_CTRL_MAA_DONE_POS)) /**< CTRL_MAA_DONE Mask */
+
+#define MXC_F_TPU_CTRL_ERR_POS 29 /**< CTRL_ERR Position */
+#define MXC_F_TPU_CTRL_ERR ((uint32_t)(0x1UL << MXC_F_TPU_CTRL_ERR_POS)) /**< CTRL_ERR Mask */
+
+#define MXC_F_TPU_CTRL_RDY_POS 30 /**< CTRL_RDY Position */
+#define MXC_F_TPU_CTRL_RDY ((uint32_t)(0x1UL << MXC_F_TPU_CTRL_RDY_POS)) /**< CTRL_RDY Mask */
+
+#define MXC_F_TPU_CTRL_DONE_POS 31 /**< CTRL_DONE Position */
+#define MXC_F_TPU_CTRL_DONE ((uint32_t)(0x1UL << MXC_F_TPU_CTRL_DONE_POS)) /**< CTRL_DONE Mask */
+
+/**@} end of group CTRL_Register */
+
+/**
+ * @ingroup tpu_registers
+ * @defgroup CIPHER_CTRL_Register
+ * @brief Cipher Control Register.
+ * @{
+ */
+#define MXC_F_TPU_CIPHER_CTRL_ENC_POS 0 /**< CIPHER_CTRL_ENC Position */
+#define MXC_F_TPU_CIPHER_CTRL_ENC ((uint32_t)(0x1UL << MXC_F_TPU_CIPHER_CTRL_ENC_POS)) /**< CIPHER_CTRL_ENC Mask */
+
+#define MXC_F_TPU_CIPHER_CTRL_KEY_POS 1 /**< CIPHER_CTRL_KEY Position */
+#define MXC_F_TPU_CIPHER_CTRL_KEY ((uint32_t)(0x1UL << MXC_F_TPU_CIPHER_CTRL_KEY_POS)) /**< CIPHER_CTRL_KEY Mask */
+
+#define MXC_F_TPU_CIPHER_CTRL_SRC_POS 2 /**< CIPHER_CTRL_SRC Position */
+#define MXC_F_TPU_CIPHER_CTRL_SRC ((uint32_t)(0x3UL << MXC_F_TPU_CIPHER_CTRL_SRC_POS)) /**< CIPHER_CTRL_SRC Mask */
+#define MXC_V_TPU_CIPHER_CTRL_SRC_CIPHERKEY ((uint32_t)0x0UL) /**< CIPHER_CTRL_SRC_CIPHERKEY Value */
+#define MXC_S_TPU_CIPHER_CTRL_SRC_CIPHERKEY \
+ (MXC_V_TPU_CIPHER_CTRL_SRC_CIPHERKEY << MXC_F_TPU_CIPHER_CTRL_SRC_POS) /**< CIPHER_CTRL_SRC_CIPHERKEY Setting */
+#define MXC_V_TPU_CIPHER_CTRL_SRC_REGFILE ((uint32_t)0x2UL) /**< CIPHER_CTRL_SRC_REGFILE Value */
+#define MXC_S_TPU_CIPHER_CTRL_SRC_REGFILE \
+ (MXC_V_TPU_CIPHER_CTRL_SRC_REGFILE << MXC_F_TPU_CIPHER_CTRL_SRC_POS) /**< CIPHER_CTRL_SRC_REGFILE Setting */
+#define MXC_V_TPU_CIPHER_CTRL_SRC_QSPIKEY_REGFILE ((uint32_t)0x3UL) /**< CIPHER_CTRL_SRC_QSPIKEY_REGFILE Value */
+#define MXC_S_TPU_CIPHER_CTRL_SRC_QSPIKEY_REGFILE \
+ (MXC_V_TPU_CIPHER_CTRL_SRC_QSPIKEY_REGFILE \
+ << MXC_F_TPU_CIPHER_CTRL_SRC_POS) /**< CIPHER_CTRL_SRC_QSPIKEY_REGFILE Setting */
+
+#define MXC_F_TPU_CIPHER_CTRL_CIPHER_POS 4 /**< CIPHER_CTRL_CIPHER Position */
+#define MXC_F_TPU_CIPHER_CTRL_CIPHER \
+ ((uint32_t)(0x7UL << MXC_F_TPU_CIPHER_CTRL_CIPHER_POS)) /**< CIPHER_CTRL_CIPHER Mask */
+#define MXC_V_TPU_CIPHER_CTRL_CIPHER_DIS ((uint32_t)0x0UL) /**< CIPHER_CTRL_CIPHER_DIS Value */
+#define MXC_S_TPU_CIPHER_CTRL_CIPHER_DIS \
+ (MXC_V_TPU_CIPHER_CTRL_CIPHER_DIS << MXC_F_TPU_CIPHER_CTRL_CIPHER_POS) /**< CIPHER_CTRL_CIPHER_DIS Setting */
+#define MXC_V_TPU_CIPHER_CTRL_CIPHER_AES128 ((uint32_t)0x1UL) /**< CIPHER_CTRL_CIPHER_AES128 Value */
+#define MXC_S_TPU_CIPHER_CTRL_CIPHER_AES128 \
+ (MXC_V_TPU_CIPHER_CTRL_CIPHER_AES128 << MXC_F_TPU_CIPHER_CTRL_CIPHER_POS) /**< CIPHER_CTRL_CIPHER_AES128 Setting \
+ */
+#define MXC_V_TPU_CIPHER_CTRL_CIPHER_AES192 ((uint32_t)0x2UL) /**< CIPHER_CTRL_CIPHER_AES192 Value */
+#define MXC_S_TPU_CIPHER_CTRL_CIPHER_AES192 \
+ (MXC_V_TPU_CIPHER_CTRL_CIPHER_AES192 << MXC_F_TPU_CIPHER_CTRL_CIPHER_POS) /**< CIPHER_CTRL_CIPHER_AES192 Setting \
+ */
+#define MXC_V_TPU_CIPHER_CTRL_CIPHER_AES256 ((uint32_t)0x3UL) /**< CIPHER_CTRL_CIPHER_AES256 Value */
+#define MXC_S_TPU_CIPHER_CTRL_CIPHER_AES256 \
+ (MXC_V_TPU_CIPHER_CTRL_CIPHER_AES256 << MXC_F_TPU_CIPHER_CTRL_CIPHER_POS) /**< CIPHER_CTRL_CIPHER_AES256 Setting \
+ */
+#define MXC_V_TPU_CIPHER_CTRL_CIPHER_DES ((uint32_t)0x4UL) /**< CIPHER_CTRL_CIPHER_DES Value */
+#define MXC_S_TPU_CIPHER_CTRL_CIPHER_DES \
+ (MXC_V_TPU_CIPHER_CTRL_CIPHER_DES << MXC_F_TPU_CIPHER_CTRL_CIPHER_POS) /**< CIPHER_CTRL_CIPHER_DES Setting */
+#define MXC_V_TPU_CIPHER_CTRL_CIPHER_TDES ((uint32_t)0x5UL) /**< CIPHER_CTRL_CIPHER_TDES Value */
+#define MXC_S_TPU_CIPHER_CTRL_CIPHER_TDES \
+ (MXC_V_TPU_CIPHER_CTRL_CIPHER_TDES << MXC_F_TPU_CIPHER_CTRL_CIPHER_POS) /**< CIPHER_CTRL_CIPHER_TDES Setting */
+
+#define MXC_F_TPU_CIPHER_CTRL_MODE_POS 8 /**< CIPHER_CTRL_MODE Position */
+#define MXC_F_TPU_CIPHER_CTRL_MODE ((uint32_t)(0x7UL << MXC_F_TPU_CIPHER_CTRL_MODE_POS)) /**< CIPHER_CTRL_MODE Mask */
+#define MXC_V_TPU_CIPHER_CTRL_MODE_ECB ((uint32_t)0x0UL) /**< CIPHER_CTRL_MODE_ECB Value */
+#define MXC_S_TPU_CIPHER_CTRL_MODE_ECB \
+ (MXC_V_TPU_CIPHER_CTRL_MODE_ECB << MXC_F_TPU_CIPHER_CTRL_MODE_POS) /**< CIPHER_CTRL_MODE_ECB Setting */
+#define MXC_V_TPU_CIPHER_CTRL_MODE_CBC ((uint32_t)0x1UL) /**< CIPHER_CTRL_MODE_CBC Value */
+#define MXC_S_TPU_CIPHER_CTRL_MODE_CBC \
+ (MXC_V_TPU_CIPHER_CTRL_MODE_CBC << MXC_F_TPU_CIPHER_CTRL_MODE_POS) /**< CIPHER_CTRL_MODE_CBC Setting */
+#define MXC_V_TPU_CIPHER_CTRL_MODE_CFB ((uint32_t)0x2UL) /**< CIPHER_CTRL_MODE_CFB Value */
+#define MXC_S_TPU_CIPHER_CTRL_MODE_CFB \
+ (MXC_V_TPU_CIPHER_CTRL_MODE_CFB << MXC_F_TPU_CIPHER_CTRL_MODE_POS) /**< CIPHER_CTRL_MODE_CFB Setting */
+#define MXC_V_TPU_CIPHER_CTRL_MODE_OFB ((uint32_t)0x3UL) /**< CIPHER_CTRL_MODE_OFB Value */
+#define MXC_S_TPU_CIPHER_CTRL_MODE_OFB \
+ (MXC_V_TPU_CIPHER_CTRL_MODE_OFB << MXC_F_TPU_CIPHER_CTRL_MODE_POS) /**< CIPHER_CTRL_MODE_OFB Setting */
+#define MXC_V_TPU_CIPHER_CTRL_MODE_CTR ((uint32_t)0x4UL) /**< CIPHER_CTRL_MODE_CTR Value */
+#define MXC_S_TPU_CIPHER_CTRL_MODE_CTR \
+ (MXC_V_TPU_CIPHER_CTRL_MODE_CTR << MXC_F_TPU_CIPHER_CTRL_MODE_POS) /**< CIPHER_CTRL_MODE_CTR Setting */
+
+/**@} end of group CIPHER_CTRL_Register */
+
+/**
+ * @ingroup tpu_registers
+ * @defgroup HASH_CTRL_Register
+ * @brief HASH Control Register.
+ * @{
+ */
+#define MXC_F_TPU_HASH_CTRL_INIT_POS 0 /**< HASH_CTRL_INIT Position */
+#define MXC_F_TPU_HASH_CTRL_INIT ((uint32_t)(0x1UL << MXC_F_TPU_HASH_CTRL_INIT_POS)) /**< HASH_CTRL_INIT Mask */
+
+#define MXC_F_TPU_HASH_CTRL_XOR_POS 1 /**< HASH_CTRL_XOR Position */
+#define MXC_F_TPU_HASH_CTRL_XOR ((uint32_t)(0x1UL << MXC_F_TPU_HASH_CTRL_XOR_POS)) /**< HASH_CTRL_XOR Mask */
+
+#define MXC_F_TPU_HASH_CTRL_HASH_POS 2 /**< HASH_CTRL_HASH Position */
+#define MXC_F_TPU_HASH_CTRL_HASH ((uint32_t)(0x7UL << MXC_F_TPU_HASH_CTRL_HASH_POS)) /**< HASH_CTRL_HASH Mask */
+#define MXC_V_TPU_HASH_CTRL_HASH_DIS ((uint32_t)0x0UL) /**< HASH_CTRL_HASH_DIS Value */
+#define MXC_S_TPU_HASH_CTRL_HASH_DIS \
+ (MXC_V_TPU_HASH_CTRL_HASH_DIS << MXC_F_TPU_HASH_CTRL_HASH_POS) /**< HASH_CTRL_HASH_DIS Setting */
+#define MXC_V_TPU_HASH_CTRL_HASH_SHA1 ((uint32_t)0x1UL) /**< HASH_CTRL_HASH_SHA1 Value */
+#define MXC_S_TPU_HASH_CTRL_HASH_SHA1 \
+ (MXC_V_TPU_HASH_CTRL_HASH_SHA1 << MXC_F_TPU_HASH_CTRL_HASH_POS) /**< HASH_CTRL_HASH_SHA1 Setting */
+#define MXC_V_TPU_HASH_CTRL_HASH_SHA224 ((uint32_t)0x2UL) /**< HASH_CTRL_HASH_SHA224 Value */
+#define MXC_S_TPU_HASH_CTRL_HASH_SHA224 \
+ (MXC_V_TPU_HASH_CTRL_HASH_SHA224 << MXC_F_TPU_HASH_CTRL_HASH_POS) /**< HASH_CTRL_HASH_SHA224 Setting */
+#define MXC_V_TPU_HASH_CTRL_HASH_SHA256 ((uint32_t)0x3UL) /**< HASH_CTRL_HASH_SHA256 Value */
+#define MXC_S_TPU_HASH_CTRL_HASH_SHA256 \
+ (MXC_V_TPU_HASH_CTRL_HASH_SHA256 << MXC_F_TPU_HASH_CTRL_HASH_POS) /**< HASH_CTRL_HASH_SHA256 Setting */
+#define MXC_V_TPU_HASH_CTRL_HASH_SHA384 ((uint32_t)0x4UL) /**< HASH_CTRL_HASH_SHA384 Value */
+#define MXC_S_TPU_HASH_CTRL_HASH_SHA384 \
+ (MXC_V_TPU_HASH_CTRL_HASH_SHA384 << MXC_F_TPU_HASH_CTRL_HASH_POS) /**< HASH_CTRL_HASH_SHA384 Setting */
+#define MXC_V_TPU_HASH_CTRL_HASH_SHA512 ((uint32_t)0x5UL) /**< HASH_CTRL_HASH_SHA512 Value */
+#define MXC_S_TPU_HASH_CTRL_HASH_SHA512 \
+ (MXC_V_TPU_HASH_CTRL_HASH_SHA512 << MXC_F_TPU_HASH_CTRL_HASH_POS) /**< HASH_CTRL_HASH_SHA512 Setting */
+
+#define MXC_F_TPU_HASH_CTRL_LAST_POS 5 /**< HASH_CTRL_LAST Position */
+#define MXC_F_TPU_HASH_CTRL_LAST ((uint32_t)(0x1UL << MXC_F_TPU_HASH_CTRL_LAST_POS)) /**< HASH_CTRL_LAST Mask */
+
+/**@} end of group HASH_CTRL_Register */
+
+/**
+ * @ingroup tpu_registers
+ * @defgroup CRC_CTRL_Register
+ * @brief CRC Control Register.
+ * @{
+ */
+#define MXC_F_TPU_CRC_CTRL_CRC_POS 0 /**< CRC_CTRL_CRC Position */
+#define MXC_F_TPU_CRC_CTRL_CRC ((uint32_t)(0x1UL << MXC_F_TPU_CRC_CTRL_CRC_POS)) /**< CRC_CTRL_CRC Mask */
+
+#define MXC_F_TPU_CRC_CTRL_MSB_POS 1 /**< CRC_CTRL_MSB Position */
+#define MXC_F_TPU_CRC_CTRL_MSB ((uint32_t)(0x1UL << MXC_F_TPU_CRC_CTRL_MSB_POS)) /**< CRC_CTRL_MSB Mask */
+
+#define MXC_F_TPU_CRC_CTRL_PRNG_POS 2 /**< CRC_CTRL_PRNG Position */
+#define MXC_F_TPU_CRC_CTRL_PRNG ((uint32_t)(0x1UL << MXC_F_TPU_CRC_CTRL_PRNG_POS)) /**< CRC_CTRL_PRNG Mask */
+
+#define MXC_F_TPU_CRC_CTRL_ENT_POS 3 /**< CRC_CTRL_ENT Position */
+#define MXC_F_TPU_CRC_CTRL_ENT ((uint32_t)(0x1UL << MXC_F_TPU_CRC_CTRL_ENT_POS)) /**< CRC_CTRL_ENT Mask */
+
+#define MXC_F_TPU_CRC_CTRL_HAM_POS 4 /**< CRC_CTRL_HAM Position */
+#define MXC_F_TPU_CRC_CTRL_HAM ((uint32_t)(0x1UL << MXC_F_TPU_CRC_CTRL_HAM_POS)) /**< CRC_CTRL_HAM Mask */
+
+#define MXC_F_TPU_CRC_CTRL_HRST_POS 5 /**< CRC_CTRL_HRST Position */
+#define MXC_F_TPU_CRC_CTRL_HRST ((uint32_t)(0x1UL << MXC_F_TPU_CRC_CTRL_HRST_POS)) /**< CRC_CTRL_HRST Mask */
+
+/**@} end of group CRC_CTRL_Register */
+
+/**
+ * @ingroup tpu_registers
+ * @defgroup DMA_SRC_Register
+ * @brief Crypto DMA Source Address.
+ * @{
+ */
+#define MXC_F_TPU_DMA_SRC_ADDR_POS 0 /**< DMA_SRC_ADDR Position */
+#define MXC_F_TPU_DMA_SRC_ADDR ((uint32_t)(0xFFFFFFFFUL << MXC_F_TPU_DMA_SRC_ADDR_POS)) /**< DMA_SRC_ADDR Mask */
+
+/**@} end of group DMA_SRC_Register */
+
+/**
+ * @ingroup tpu_registers
+ * @defgroup DMA_DEST_Register
+ * @brief Crypto DMA Destination Address.
+ * @{
+ */
+#define MXC_F_TPU_DMA_DEST_ADDR_POS 0 /**< DMA_DEST_ADDR Position */
+#define MXC_F_TPU_DMA_DEST_ADDR ((uint32_t)(0xFFFFFFFFUL << MXC_F_TPU_DMA_DEST_ADDR_POS)) /**< DMA_DEST_ADDR Mask */
+
+/**@} end of group DMA_DEST_Register */
+
+/**
+ * @ingroup tpu_registers
+ * @defgroup DMA_CNT_Register
+ * @brief Crypto DMA Byte Count.
+ * @{
+ */
+#define MXC_F_TPU_DMA_CNT_ADDR_POS 0 /**< DMA_CNT_ADDR Position */
+#define MXC_F_TPU_DMA_CNT_ADDR ((uint32_t)(0xFFFFFFFFUL << MXC_F_TPU_DMA_CNT_ADDR_POS)) /**< DMA_CNT_ADDR Mask */
+
+/**@} end of group DMA_CNT_Register */
+
+/**
+ * @ingroup tpu_registers
+ * @defgroup MAA_CTRL_Register
+ * @brief MAA Control Register.
+ * @{
+ */
+#define MXC_F_TPU_MAA_CTRL_STC_POS 0 /**< MAA_CTRL_STC Position */
+#define MXC_F_TPU_MAA_CTRL_STC ((uint32_t)(0x1UL << MXC_F_TPU_MAA_CTRL_STC_POS)) /**< MAA_CTRL_STC Mask */
+
+#define MXC_F_TPU_MAA_CTRL_CLC_POS 1 /**< MAA_CTRL_CLC Position */
+#define MXC_F_TPU_MAA_CTRL_CLC ((uint32_t)(0x7UL << MXC_F_TPU_MAA_CTRL_CLC_POS)) /**< MAA_CTRL_CLC Mask */
+#define MXC_V_TPU_MAA_CTRL_CLC_EXP ((uint32_t)0x0UL) /**< MAA_CTRL_CLC_EXP Value */
+#define MXC_S_TPU_MAA_CTRL_CLC_EXP \
+ (MXC_V_TPU_MAA_CTRL_CLC_EXP << MXC_F_TPU_MAA_CTRL_CLC_POS) /**< MAA_CTRL_CLC_EXP Setting */
+#define MXC_V_TPU_MAA_CTRL_CLC_SQ ((uint32_t)0x1UL) /**< MAA_CTRL_CLC_SQ Value */
+#define MXC_S_TPU_MAA_CTRL_CLC_SQ \
+ (MXC_V_TPU_MAA_CTRL_CLC_SQ << MXC_F_TPU_MAA_CTRL_CLC_POS) /**< MAA_CTRL_CLC_SQ Setting */
+#define MXC_V_TPU_MAA_CTRL_CLC_MUL ((uint32_t)0x2UL) /**< MAA_CTRL_CLC_MUL Value */
+#define MXC_S_TPU_MAA_CTRL_CLC_MUL \
+ (MXC_V_TPU_MAA_CTRL_CLC_MUL << MXC_F_TPU_MAA_CTRL_CLC_POS) /**< MAA_CTRL_CLC_MUL Setting */
+#define MXC_V_TPU_MAA_CTRL_CLC_SQMUL ((uint32_t)0x3UL) /**< MAA_CTRL_CLC_SQMUL Value */
+#define MXC_S_TPU_MAA_CTRL_CLC_SQMUL \
+ (MXC_V_TPU_MAA_CTRL_CLC_SQMUL << MXC_F_TPU_MAA_CTRL_CLC_POS) /**< MAA_CTRL_CLC_SQMUL Setting */
+#define MXC_V_TPU_MAA_CTRL_CLC_ADD ((uint32_t)0x4UL) /**< MAA_CTRL_CLC_ADD Value */
+#define MXC_S_TPU_MAA_CTRL_CLC_ADD \
+ (MXC_V_TPU_MAA_CTRL_CLC_ADD << MXC_F_TPU_MAA_CTRL_CLC_POS) /**< MAA_CTRL_CLC_ADD Setting */
+#define MXC_V_TPU_MAA_CTRL_CLC_SUB ((uint32_t)0x5UL) /**< MAA_CTRL_CLC_SUB Value */
+#define MXC_S_TPU_MAA_CTRL_CLC_SUB \
+ (MXC_V_TPU_MAA_CTRL_CLC_SUB << MXC_F_TPU_MAA_CTRL_CLC_POS) /**< MAA_CTRL_CLC_SUB Setting */
+
+#define MXC_F_TPU_MAA_CTRL_OCALC_POS 4 /**< MAA_CTRL_OCALC Position */
+#define MXC_F_TPU_MAA_CTRL_OCALC ((uint32_t)(0x1UL << MXC_F_TPU_MAA_CTRL_OCALC_POS)) /**< MAA_CTRL_OCALC Mask */
+
+#define MXC_F_TPU_MAA_CTRL_MAAER_POS 7 /**< MAA_CTRL_MAAER Position */
+#define MXC_F_TPU_MAA_CTRL_MAAER ((uint32_t)(0x1UL << MXC_F_TPU_MAA_CTRL_MAAER_POS)) /**< MAA_CTRL_MAAER Mask */
+
+#define MXC_F_TPU_MAA_CTRL_AMS_POS 8 /**< MAA_CTRL_AMS Position */
+#define MXC_F_TPU_MAA_CTRL_AMS ((uint32_t)(0x3UL << MXC_F_TPU_MAA_CTRL_AMS_POS)) /**< MAA_CTRL_AMS Mask */
+
+#define MXC_F_TPU_MAA_CTRL_BMS_POS 10 /**< MAA_CTRL_BMS Position */
+#define MXC_F_TPU_MAA_CTRL_BMS ((uint32_t)(0x3UL << MXC_F_TPU_MAA_CTRL_BMS_POS)) /**< MAA_CTRL_BMS Mask */
+
+#define MXC_F_TPU_MAA_CTRL_EMS_POS 12 /**< MAA_CTRL_EMS Position */
+#define MXC_F_TPU_MAA_CTRL_EMS ((uint32_t)(0x3UL << MXC_F_TPU_MAA_CTRL_EMS_POS)) /**< MAA_CTRL_EMS Mask */
+
+#define MXC_F_TPU_MAA_CTRL_MMS_POS 14 /**< MAA_CTRL_MMS Position */
+#define MXC_F_TPU_MAA_CTRL_MMS ((uint32_t)(0x3UL << MXC_F_TPU_MAA_CTRL_MMS_POS)) /**< MAA_CTRL_MMS Mask */
+
+#define MXC_F_TPU_MAA_CTRL_AMA_POS 16 /**< MAA_CTRL_AMA Position */
+#define MXC_F_TPU_MAA_CTRL_AMA ((uint32_t)(0xFUL << MXC_F_TPU_MAA_CTRL_AMA_POS)) /**< MAA_CTRL_AMA Mask */
+
+#define MXC_F_TPU_MAA_CTRL_BMA_POS 20 /**< MAA_CTRL_BMA Position */
+#define MXC_F_TPU_MAA_CTRL_BMA ((uint32_t)(0xFUL << MXC_F_TPU_MAA_CTRL_BMA_POS)) /**< MAA_CTRL_BMA Mask */
+
+#define MXC_F_TPU_MAA_CTRL_RMA_POS 24 /**< MAA_CTRL_RMA Position */
+#define MXC_F_TPU_MAA_CTRL_RMA ((uint32_t)(0xFUL << MXC_F_TPU_MAA_CTRL_RMA_POS)) /**< MAA_CTRL_RMA Mask */
+
+#define MXC_F_TPU_MAA_CTRL_TMA_POS 28 /**< MAA_CTRL_TMA Position */
+#define MXC_F_TPU_MAA_CTRL_TMA ((uint32_t)(0xFUL << MXC_F_TPU_MAA_CTRL_TMA_POS)) /**< MAA_CTRL_TMA Mask */
+
+/**@} end of group MAA_CTRL_Register */
+
+/**
+ * @ingroup tpu_registers
+ * @defgroup DIN_Register
+ * @brief Crypto Data Input. Data input can be written to this register instead of using
+ * the DMA. This register writes to the FIFO. This register occupies four
+ * successive words to allow the use of multi-store instructions. Words can be
+ * written to any location, they will be placed in the FIFO in the order they are
+ * written. The endian swap input control bit affects this register.
+ * @{
+ */
+#define MXC_F_TPU_DIN_DATA_POS 0 /**< DIN_DATA Position */
+#define MXC_F_TPU_DIN_DATA ((uint32_t)(0xFFFFFFFFUL << MXC_F_TPU_DIN_DATA_POS)) /**< DIN_DATA Mask */
+
+/**@} end of group DIN_Register */
+
+/**
+ * @ingroup tpu_registers
+ * @defgroup DOUT_Register
+ * @brief Crypto Data Output. Resulting data from cipher calculation. Data is placed in
+ * the lower words of these four registers depending on the algorithm. For block
+ * cipher modes, this register holds the result of most recent encryption or
+ * decryption operation. These registers are affected by the endian swap bits.
+ * @{
+ */
+#define MXC_F_TPU_DOUT_DATA_POS 0 /**< DOUT_DATA Position */
+#define MXC_F_TPU_DOUT_DATA ((uint32_t)(0xFFFFFFFFUL << MXC_F_TPU_DOUT_DATA_POS)) /**< DOUT_DATA Mask */
+
+/**@} end of group DOUT_Register */
+
+/**
+ * @ingroup tpu_registers
+ * @defgroup CRC_POLY_Register
+ * @brief CRC Polynomial. The polynomial to be used for Galois Field calculations (CRC or
+ * LFSR) should be written to this register. This register is affected by the MSB
+ * control bit.
+ * @{
+ */
+#define MXC_F_TPU_CRC_POLY_POLY_POS 0 /**< CRC_POLY_POLY Position */
+#define MXC_F_TPU_CRC_POLY_POLY ((uint32_t)(0xFFFFFFFFUL << MXC_F_TPU_CRC_POLY_POLY_POS)) /**< CRC_POLY_POLY Mask */
+
+/**@} end of group CRC_POLY_Register */
+
+/**
+ * @ingroup tpu_registers
+ * @defgroup CRC_VAL_Register
+ * @brief CRC Value. This is the state for the Galois Field. This register holds the
+ * result of a CRC calculation or the current state of the LFSR. This register is
+ * affected by the MSB control bit.
+ * @{
+ */
+#define MXC_F_TPU_CRC_VAL_VAL_POS 0 /**< CRC_VAL_VAL Position */
+#define MXC_F_TPU_CRC_VAL_VAL ((uint32_t)(0xFFFFFFFFUL << MXC_F_TPU_CRC_VAL_VAL_POS)) /**< CRC_VAL_VAL Mask */
+
+/**@} end of group CRC_VAL_Register */
+
+/**
+ * @ingroup tpu_registers
+ * @defgroup CRC_PRNG_Register
+ * @brief Pseudo Random Value. Output of the Galois Field shift register. This holds the
+ * resulting pseudo-random number if entropy is disabled or true random number if
+ * entropy is enabled.
+ * @{
+ */
+#define MXC_F_TPU_CRC_PRNG_PRNG_POS 0 /**< CRC_PRNG_PRNG Position */
+#define MXC_F_TPU_CRC_PRNG_PRNG ((uint32_t)(0xFFFFFFFFUL << MXC_F_TPU_CRC_PRNG_PRNG_POS)) /**< CRC_PRNG_PRNG Mask */
+
+/**@} end of group CRC_PRNG_Register */
+
+/**
+ * @ingroup tpu_registers
+ * @defgroup HAM_ECC_Register
+ * @brief Hamming ECC Register.
+ * @{
+ */
+#define MXC_F_TPU_HAM_ECC_ECC_POS 0 /**< HAM_ECC_ECC Position */
+#define MXC_F_TPU_HAM_ECC_ECC ((uint32_t)(0xFFFFUL << MXC_F_TPU_HAM_ECC_ECC_POS)) /**< HAM_ECC_ECC Mask */
+
+#define MXC_F_TPU_HAM_ECC_PAR_POS 16 /**< HAM_ECC_PAR Position */
+#define MXC_F_TPU_HAM_ECC_PAR ((uint32_t)(0x1UL << MXC_F_TPU_HAM_ECC_PAR_POS)) /**< HAM_ECC_PAR Mask */
+
+/**@} end of group HAM_ECC_Register */
+
+/**
+ * @ingroup tpu_registers
+ * @defgroup CIPHER_INIT_Register
+ * @brief Initial Vector. For block cipher operations that use CBC, CFB, OFB, or CNTR
+ * modes, this register holds the initial value. This register is updated with each
+ * encryption or decryption operation. This register is affected by the endian swap
+ * bits.
+ * @{
+ */
+#define MXC_F_TPU_CIPHER_INIT_IVEC_POS 0 /**< CIPHER_INIT_IVEC Position */
+#define MXC_F_TPU_CIPHER_INIT_IVEC \
+ ((uint32_t)(0xFFFFFFFFUL << MXC_F_TPU_CIPHER_INIT_IVEC_POS)) /**< CIPHER_INIT_IVEC Mask */
+
+/**@} end of group CIPHER_INIT_Register */
+
+/**
+ * @ingroup tpu_registers
+ * @defgroup CIPHER_KEY_Register
+ * @brief Cipher Key. This register holds the key used for block cipher operations. The
+ * lower words are used for block ciphers that use shorter key lengths. This
+ * register is affected by the endian swap input control bits.
+ * @{
+ */
+#define MXC_F_TPU_CIPHER_KEY_KEY_POS 0 /**< CIPHER_KEY_KEY Position */
+#define MXC_F_TPU_CIPHER_KEY_KEY \
+ ((uint32_t)(0xFFFFFFFFUL << MXC_F_TPU_CIPHER_KEY_KEY_POS)) /**< CIPHER_KEY_KEY Mask \
+ */
+
+/**@} end of group CIPHER_KEY_Register */
+
+/**
+ * @ingroup tpu_registers
+ * @defgroup HASH_DIGEST_Register
+ * @brief This register holds the calculated hash value. This register is affected by the
+ * endian swap bits.
+ * @{
+ */
+#define MXC_F_TPU_HASH_DIGEST_HASH_POS 0 /**< HASH_DIGEST_HASH Position */
+#define MXC_F_TPU_HASH_DIGEST_HASH \
+ ((uint32_t)(0xFFFFFFFFUL << MXC_F_TPU_HASH_DIGEST_HASH_POS)) /**< HASH_DIGEST_HASH Mask */
+
+/**@} end of group HASH_DIGEST_Register */
+
+/**
+ * @ingroup tpu_registers
+ * @defgroup HASH_MSG_SZ_Register
+ * @brief Message Size. This register holds the lowest 32-bit of message size in bytes.
+ * @{
+ */
+#define MXC_F_TPU_HASH_MSG_SZ_MSGSZ_POS 0 /**< HASH_MSG_SZ_MSGSZ Position */
+#define MXC_F_TPU_HASH_MSG_SZ_MSGSZ \
+ ((uint32_t)(0xFFFFFFFFUL << MXC_F_TPU_HASH_MSG_SZ_MSGSZ_POS)) /**< HASH_MSG_SZ_MSGSZ Mask */
+
+/**@} end of group HASH_MSG_SZ_Register */
+
+/**
+ * @ingroup tpu_registers
+ * @defgroup MAA_MAWS_Register
+ * @brief MAA Word Size. This register defines the number of bits for a modular operation.
+ * This register must be set to a valid value prior to the MAA operation start.
+ * Valid values are from 1 to 2048. Invalid values are ignored and will not
+ * initiate a MAA operation.
+ * @{
+ */
+#define MXC_F_TPU_MAA_MAWS_MAWS_POS 0 /**< MAA_MAWS_MAWS Position */
+#define MXC_F_TPU_MAA_MAWS_MAWS ((uint32_t)(0xFFFUL << MXC_F_TPU_MAA_MAWS_MAWS_POS)) /**< MAA_MAWS_MAWS Mask */
+
+/**@} end of group MAA_MAWS_Register */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _TPU_REGS_H_ */
diff --git a/contrib/loaders/flash/msp432/driverlib.c b/contrib/loaders/flash/msp432/driverlib.c
index 6f483b83da..b897755d16 100644
--- a/contrib/loaders/flash/msp432/driverlib.c
+++ b/contrib/loaders/flash/msp432/driverlib.c
@@ -67,20 +67,20 @@ static bool __pcm_set_core_voltage_level_advanced(uint_fast8_t voltage_level,
reg_value = PCM->CTL0;
switch (pcm_get_power_state()) {
- case PCM_AM_LF_VCORE1:
- case PCM_AM_DCDC_VCORE1:
- case PCM_AM_LDO_VCORE0:
- PCM->CTL0 = (PCM_KEY | (PCM_AM_LDO_VCORE1)
- | (reg_value & ~(PCM_CTL0_KEY_MASK | PCM_CTL0_AMR_MASK)));
- break;
- case PCM_AM_LF_VCORE0:
- case PCM_AM_DCDC_VCORE0:
- case PCM_AM_LDO_VCORE1:
- PCM->CTL0 = (PCM_KEY | (PCM_AM_LDO_VCORE0)
- | (reg_value & ~(PCM_CTL0_KEY_MASK | PCM_CTL0_AMR_MASK)));
- break;
- default:
- break;
+ case PCM_AM_LF_VCORE1:
+ case PCM_AM_DCDC_VCORE1:
+ case PCM_AM_LDO_VCORE0:
+ PCM->CTL0 = (PCM_KEY | (PCM_AM_LDO_VCORE1)
+ | (reg_value & ~(PCM_CTL0_KEY_MASK | PCM_CTL0_AMR_MASK)));
+ break;
+ case PCM_AM_LF_VCORE0:
+ case PCM_AM_DCDC_VCORE0:
+ case PCM_AM_LDO_VCORE1:
+ PCM->CTL0 = (PCM_KEY | (PCM_AM_LDO_VCORE0)
+ | (reg_value & ~(PCM_CTL0_KEY_MASK | PCM_CTL0_AMR_MASK)));
+ break;
+ default:
+ break;
}
if (blocking) {
@@ -117,22 +117,22 @@ uint8_t pcm_get_power_mode(void)
current_power_state = pcm_get_power_state();
switch (current_power_state) {
- case PCM_AM_LDO_VCORE0:
- case PCM_AM_LDO_VCORE1:
- case PCM_LPM0_LDO_VCORE0:
- case PCM_LPM0_LDO_VCORE1:
- default:
- return PCM_LDO_MODE;
- case PCM_AM_DCDC_VCORE0:
- case PCM_AM_DCDC_VCORE1:
- case PCM_LPM0_DCDC_VCORE0:
- case PCM_LPM0_DCDC_VCORE1:
- return PCM_DCDC_MODE;
- case PCM_LPM0_LF_VCORE0:
- case PCM_LPM0_LF_VCORE1:
- case PCM_AM_LF_VCORE1:
- case PCM_AM_LF_VCORE0:
- return PCM_LF_MODE;
+ case PCM_AM_DCDC_VCORE0:
+ case PCM_AM_DCDC_VCORE1:
+ case PCM_LPM0_DCDC_VCORE0:
+ case PCM_LPM0_DCDC_VCORE1:
+ return PCM_DCDC_MODE;
+ case PCM_LPM0_LF_VCORE0:
+ case PCM_LPM0_LF_VCORE1:
+ case PCM_AM_LF_VCORE1:
+ case PCM_AM_LF_VCORE0:
+ return PCM_LF_MODE;
+ case PCM_AM_LDO_VCORE0:
+ case PCM_AM_LDO_VCORE1:
+ case PCM_LPM0_LDO_VCORE0:
+ case PCM_LPM0_LDO_VCORE1:
+ default:
+ return PCM_LDO_MODE;
}
}
@@ -141,23 +141,23 @@ uint8_t pcm_get_core_voltage_level(void)
uint8_t current_power_state = pcm_get_power_state();
switch (current_power_state) {
- case PCM_AM_LDO_VCORE0:
- case PCM_AM_DCDC_VCORE0:
- case PCM_AM_LF_VCORE0:
- case PCM_LPM0_LDO_VCORE0:
- case PCM_LPM0_DCDC_VCORE0:
- case PCM_LPM0_LF_VCORE0:
- default:
- return PCM_VCORE0;
- case PCM_AM_LDO_VCORE1:
- case PCM_AM_DCDC_VCORE1:
- case PCM_AM_LF_VCORE1:
- case PCM_LPM0_LDO_VCORE1:
- case PCM_LPM0_DCDC_VCORE1:
- case PCM_LPM0_LF_VCORE1:
- return PCM_VCORE1;
- case PCM_LPM3:
- return PCM_VCORELPM3;
+ case PCM_AM_LDO_VCORE1:
+ case PCM_AM_DCDC_VCORE1:
+ case PCM_AM_LF_VCORE1:
+ case PCM_LPM0_LDO_VCORE1:
+ case PCM_LPM0_DCDC_VCORE1:
+ case PCM_LPM0_LF_VCORE1:
+ return PCM_VCORE1;
+ case PCM_LPM3:
+ return PCM_VCORELPM3;
+ case PCM_AM_LDO_VCORE0:
+ case PCM_AM_DCDC_VCORE0:
+ case PCM_AM_LF_VCORE0:
+ case PCM_LPM0_LDO_VCORE0:
+ case PCM_LPM0_DCDC_VCORE0:
+ case PCM_LPM0_LF_VCORE0:
+ default:
+ return PCM_VCORE0;
}
}
@@ -186,44 +186,44 @@ static bool __pcm_set_power_mode_advanced(uint_fast8_t power_mode,
reg_value = PCM->CTL0;
switch (current_power_state) {
- case PCM_AM_DCDC_VCORE0:
- case PCM_AM_LF_VCORE0:
- PCM->CTL0 = (PCM_KEY | PCM_AM_LDO_VCORE0
- | (reg_value & ~(PCM_CTL0_KEY_MASK | PCM_CTL0_AMR_MASK)));
- break;
- case PCM_AM_LF_VCORE1:
- case PCM_AM_DCDC_VCORE1:
- PCM->CTL0 = (PCM_KEY | PCM_AM_LDO_VCORE1
- | (reg_value & ~(PCM_CTL0_KEY_MASK | PCM_CTL0_AMR_MASK)));
- break;
- case PCM_AM_LDO_VCORE1: {
- if (power_mode == PCM_DCDC_MODE) {
- PCM->CTL0 = (PCM_KEY | PCM_AM_DCDC_VCORE1
- | (reg_value & ~(PCM_CTL0_KEY_MASK
- | PCM_CTL0_AMR_MASK)));
- } else if (power_mode == PCM_LF_MODE) {
- PCM->CTL0 = (PCM_KEY | PCM_AM_LF_VCORE1
- | (reg_value & ~(PCM_CTL0_KEY_MASK
- | PCM_CTL0_AMR_MASK)));
- } else
- return false;
- break;
+ case PCM_AM_DCDC_VCORE0:
+ case PCM_AM_LF_VCORE0:
+ PCM->CTL0 = (PCM_KEY | PCM_AM_LDO_VCORE0
+ | (reg_value & ~(PCM_CTL0_KEY_MASK | PCM_CTL0_AMR_MASK)));
+ break;
+ case PCM_AM_LF_VCORE1:
+ case PCM_AM_DCDC_VCORE1:
+ PCM->CTL0 = (PCM_KEY | PCM_AM_LDO_VCORE1
+ | (reg_value & ~(PCM_CTL0_KEY_MASK | PCM_CTL0_AMR_MASK)));
+ break;
+ case PCM_AM_LDO_VCORE1:
+ if (power_mode == PCM_DCDC_MODE) {
+ PCM->CTL0 = (PCM_KEY | PCM_AM_DCDC_VCORE1
+ | (reg_value & ~(PCM_CTL0_KEY_MASK
+ | PCM_CTL0_AMR_MASK)));
+ } else if (power_mode == PCM_LF_MODE) {
+ PCM->CTL0 = (PCM_KEY | PCM_AM_LF_VCORE1
+ | (reg_value & ~(PCM_CTL0_KEY_MASK
+ | PCM_CTL0_AMR_MASK)));
+ } else {
+ return false;
}
- case PCM_AM_LDO_VCORE0: {
- if (power_mode == PCM_DCDC_MODE) {
- PCM->CTL0 = (PCM_KEY | PCM_AM_DCDC_VCORE0
- | (reg_value & ~(PCM_CTL0_KEY_MASK
- | PCM_CTL0_AMR_MASK)));
- } else if (power_mode == PCM_LF_MODE) {
- PCM->CTL0 = (PCM_KEY | PCM_AM_LF_VCORE0
- | (reg_value & ~(PCM_CTL0_KEY_MASK
- | PCM_CTL0_AMR_MASK)));
- } else
- return false;
- break;
+ break;
+ case PCM_AM_LDO_VCORE0:
+ if (power_mode == PCM_DCDC_MODE) {
+ PCM->CTL0 = (PCM_KEY | PCM_AM_DCDC_VCORE0
+ | (reg_value & ~(PCM_CTL0_KEY_MASK
+ | PCM_CTL0_AMR_MASK)));
+ } else if (power_mode == PCM_LF_MODE) {
+ PCM->CTL0 = (PCM_KEY | PCM_AM_LF_VCORE0
+ | (reg_value & ~(PCM_CTL0_KEY_MASK
+ | PCM_CTL0_AMR_MASK)));
+ } else {
+ return false;
}
- default:
- break;
+ break;
+ default:
+ break;
}
if (blocking) {
@@ -231,8 +231,9 @@ static bool __pcm_set_power_mode_advanced(uint_fast8_t power_mode,
if (bool_timeout && !(--time_out))
return false;
}
- } else
+ } else {
return true;
+ }
current_power_mode = pcm_get_power_mode();
current_power_state = pcm_get_power_state();
@@ -256,76 +257,76 @@ static bool __pcm_set_power_state_advanced(uint_fast8_t power_state,
return true;
switch (power_state) {
- case PCM_AM_LDO_VCORE0:
- return __pcm_set_core_voltage_level_advanced(PCM_VCORE0, timeout,
- blocking) && __pcm_set_power_mode_advanced(PCM_LDO_MODE,
- timeout, blocking);
- case PCM_AM_LDO_VCORE1:
- return __pcm_set_core_voltage_level_advanced(PCM_VCORE1, timeout,
- blocking) && __pcm_set_power_mode_advanced(PCM_LDO_MODE,
- timeout, blocking);
- case PCM_AM_DCDC_VCORE0:
- return __pcm_set_core_voltage_level_advanced(PCM_VCORE0, timeout,
- blocking) && __pcm_set_power_mode_advanced(PCM_DCDC_MODE,
- timeout, blocking);
- case PCM_AM_DCDC_VCORE1:
- return __pcm_set_core_voltage_level_advanced(PCM_VCORE1, timeout,
- blocking) && __pcm_set_power_mode_advanced(PCM_DCDC_MODE,
- timeout, blocking);
- case PCM_AM_LF_VCORE0:
- return __pcm_set_core_voltage_level_advanced(PCM_VCORE0, timeout,
- blocking) && __pcm_set_power_mode_advanced(PCM_LF_MODE,
- timeout, blocking);
- case PCM_AM_LF_VCORE1:
- return __pcm_set_core_voltage_level_advanced(PCM_VCORE1, timeout,
- blocking) && __pcm_set_power_mode_advanced(PCM_LF_MODE,
- timeout, blocking);
- case PCM_LPM0_LDO_VCORE0:
- if (!__pcm_set_core_voltage_level_advanced(PCM_VCORE0, timeout,
- blocking) || !__pcm_set_power_mode_advanced(PCM_LDO_MODE,
- timeout, blocking))
- break;
- return pcm_goto_lpm0();
- case PCM_LPM0_LDO_VCORE1:
- if (!__pcm_set_core_voltage_level_advanced(PCM_VCORE1, timeout,
- blocking) || !__pcm_set_power_mode_advanced(PCM_LDO_MODE,
- timeout, blocking))
- break;
- return pcm_goto_lpm0();
- case PCM_LPM0_DCDC_VCORE0:
- if (!__pcm_set_core_voltage_level_advanced(PCM_VCORE0, timeout,
- blocking) || !__pcm_set_power_mode_advanced(PCM_DCDC_MODE,
- timeout, blocking))
- break;
- return pcm_goto_lpm0();
- case PCM_LPM0_DCDC_VCORE1:
- if (!__pcm_set_core_voltage_level_advanced(PCM_VCORE1, timeout,
- blocking) || !__pcm_set_power_mode_advanced(PCM_DCDC_MODE,
- timeout, blocking))
- break;
- return pcm_goto_lpm0();
- case PCM_LPM0_LF_VCORE0:
- if (!__pcm_set_core_voltage_level_advanced(PCM_VCORE0, timeout,
- blocking) || !__pcm_set_power_mode_advanced(PCM_LF_MODE,
- timeout, blocking))
- break;
- return pcm_goto_lpm0();
- case PCM_LPM0_LF_VCORE1:
- if (!__pcm_set_core_voltage_level_advanced(PCM_VCORE1, timeout,
- blocking) || !__pcm_set_power_mode_advanced(PCM_LF_MODE,
- timeout, blocking))
- break;
- return pcm_goto_lpm0();
- case PCM_LPM3:
- return pcm_goto_lpm3();
- case PCM_LPM4:
- return pcm_goto_lpm4();
- case PCM_LPM45:
- return pcm_shutdown_device(PCM_LPM45);
- case PCM_LPM35_VCORE0:
- return pcm_shutdown_device(PCM_LPM35_VCORE0);
- default:
- return false;
+ case PCM_AM_LDO_VCORE0:
+ return __pcm_set_core_voltage_level_advanced(PCM_VCORE0, timeout,
+ blocking) && __pcm_set_power_mode_advanced(PCM_LDO_MODE,
+ timeout, blocking);
+ case PCM_AM_LDO_VCORE1:
+ return __pcm_set_core_voltage_level_advanced(PCM_VCORE1, timeout,
+ blocking) && __pcm_set_power_mode_advanced(PCM_LDO_MODE,
+ timeout, blocking);
+ case PCM_AM_DCDC_VCORE0:
+ return __pcm_set_core_voltage_level_advanced(PCM_VCORE0, timeout,
+ blocking) && __pcm_set_power_mode_advanced(PCM_DCDC_MODE,
+ timeout, blocking);
+ case PCM_AM_DCDC_VCORE1:
+ return __pcm_set_core_voltage_level_advanced(PCM_VCORE1, timeout,
+ blocking) && __pcm_set_power_mode_advanced(PCM_DCDC_MODE,
+ timeout, blocking);
+ case PCM_AM_LF_VCORE0:
+ return __pcm_set_core_voltage_level_advanced(PCM_VCORE0, timeout,
+ blocking) && __pcm_set_power_mode_advanced(PCM_LF_MODE,
+ timeout, blocking);
+ case PCM_AM_LF_VCORE1:
+ return __pcm_set_core_voltage_level_advanced(PCM_VCORE1, timeout,
+ blocking) && __pcm_set_power_mode_advanced(PCM_LF_MODE,
+ timeout, blocking);
+ case PCM_LPM0_LDO_VCORE0:
+ if (!__pcm_set_core_voltage_level_advanced(PCM_VCORE0, timeout,
+ blocking) || !__pcm_set_power_mode_advanced(PCM_LDO_MODE,
+ timeout, blocking))
+ break;
+ return pcm_goto_lpm0();
+ case PCM_LPM0_LDO_VCORE1:
+ if (!__pcm_set_core_voltage_level_advanced(PCM_VCORE1, timeout,
+ blocking) || !__pcm_set_power_mode_advanced(PCM_LDO_MODE,
+ timeout, blocking))
+ break;
+ return pcm_goto_lpm0();
+ case PCM_LPM0_DCDC_VCORE0:
+ if (!__pcm_set_core_voltage_level_advanced(PCM_VCORE0, timeout,
+ blocking) || !__pcm_set_power_mode_advanced(PCM_DCDC_MODE,
+ timeout, blocking))
+ break;
+ return pcm_goto_lpm0();
+ case PCM_LPM0_DCDC_VCORE1:
+ if (!__pcm_set_core_voltage_level_advanced(PCM_VCORE1, timeout,
+ blocking) || !__pcm_set_power_mode_advanced(PCM_DCDC_MODE,
+ timeout, blocking))
+ break;
+ return pcm_goto_lpm0();
+ case PCM_LPM0_LF_VCORE0:
+ if (!__pcm_set_core_voltage_level_advanced(PCM_VCORE0, timeout,
+ blocking) || !__pcm_set_power_mode_advanced(PCM_LF_MODE,
+ timeout, blocking))
+ break;
+ return pcm_goto_lpm0();
+ case PCM_LPM0_LF_VCORE1:
+ if (!__pcm_set_core_voltage_level_advanced(PCM_VCORE1, timeout,
+ blocking) || !__pcm_set_power_mode_advanced(PCM_LF_MODE,
+ timeout, blocking))
+ break;
+ return pcm_goto_lpm0();
+ case PCM_LPM3:
+ return pcm_goto_lpm3();
+ case PCM_LPM4:
+ return pcm_goto_lpm4();
+ case PCM_LPM45:
+ return pcm_shutdown_device(PCM_LPM45);
+ case PCM_LPM35_VCORE0:
+ return pcm_shutdown_device(PCM_LPM35_VCORE0);
+ default:
+ return false;
}
return false;
diff --git a/contrib/loaders/flash/msp432/main_msp432e4x.c b/contrib/loaders/flash/msp432/main_msp432e4x.c
index 7974f48c77..7c9cf468df 100644
--- a/contrib/loaders/flash/msp432/main_msp432e4x.c
+++ b/contrib/loaders/flash/msp432/main_msp432e4x.c
@@ -30,37 +30,37 @@ int main(void)
while (1) {
switch (FLASH_LOADER->FLASH_FUNCTION) {
- case FLASH_INIT:
- FLASH_LOADER->RETURN_CODE = FLASH_BUSY;
- msp432_flash_init();
- FLASH_LOADER->FLASH_FUNCTION = 0;
- break;
- case FLASH_MASS_ERASE:
- FLASH_LOADER->RETURN_CODE = FLASH_BUSY;
- msp432_flash_mass_erase();
- FLASH_LOADER->FLASH_FUNCTION = 0;
- break;
- case FLASH_SECTOR_ERASE:
- FLASH_LOADER->RETURN_CODE = FLASH_BUSY;
- msp432_flash_sector_erase();
- FLASH_LOADER->FLASH_FUNCTION = 0;
- break;
- case FLASH_PROGRAM:
- case FLASH_CONTINUOUS_PROGRAM:
- FLASH_LOADER->RETURN_CODE = FLASH_BUSY;
- msp432_flash_continous_write();
- FLASH_LOADER->FLASH_FUNCTION = 0;
- break;
- case FLASH_EXIT:
- FLASH_LOADER->RETURN_CODE = FLASH_BUSY;
- msp432_flash_exit();
- FLASH_LOADER->FLASH_FUNCTION = 0;
- break;
- case FLASH_NO_COMMAND:
- break;
- default:
- FLASH_LOADER->RETURN_CODE = FLASH_WRONG_COMMAND;
- break;
+ case FLASH_INIT:
+ FLASH_LOADER->RETURN_CODE = FLASH_BUSY;
+ msp432_flash_init();
+ FLASH_LOADER->FLASH_FUNCTION = 0;
+ break;
+ case FLASH_MASS_ERASE:
+ FLASH_LOADER->RETURN_CODE = FLASH_BUSY;
+ msp432_flash_mass_erase();
+ FLASH_LOADER->FLASH_FUNCTION = 0;
+ break;
+ case FLASH_SECTOR_ERASE:
+ FLASH_LOADER->RETURN_CODE = FLASH_BUSY;
+ msp432_flash_sector_erase();
+ FLASH_LOADER->FLASH_FUNCTION = 0;
+ break;
+ case FLASH_PROGRAM:
+ case FLASH_CONTINUOUS_PROGRAM:
+ FLASH_LOADER->RETURN_CODE = FLASH_BUSY;
+ msp432_flash_continous_write();
+ FLASH_LOADER->FLASH_FUNCTION = 0;
+ break;
+ case FLASH_EXIT:
+ FLASH_LOADER->RETURN_CODE = FLASH_BUSY;
+ msp432_flash_exit();
+ FLASH_LOADER->FLASH_FUNCTION = 0;
+ break;
+ case FLASH_NO_COMMAND:
+ break;
+ default:
+ FLASH_LOADER->RETURN_CODE = FLASH_WRONG_COMMAND;
+ break;
}
}
}
diff --git a/contrib/loaders/flash/msp432/main_msp432p401x.c b/contrib/loaders/flash/msp432/main_msp432p401x.c
index 47fb7fa476..024d047224 100644
--- a/contrib/loaders/flash/msp432/main_msp432p401x.c
+++ b/contrib/loaders/flash/msp432/main_msp432p401x.c
@@ -49,41 +49,41 @@ int main(void)
while (1) {
switch (FLASH_LOADER->FLASH_FUNCTION) {
- case FLASH_INIT:
- FLASH_LOADER->RETURN_CODE = FLASH_BUSY;
- msp432_flash_init();
- FLASH_LOADER->FLASH_FUNCTION = 0;
- break;
- case FLASH_MASS_ERASE:
- FLASH_LOADER->RETURN_CODE = FLASH_BUSY;
- msp432_flash_mass_erase();
- FLASH_LOADER->FLASH_FUNCTION = 0;
- break;
- case FLASH_SECTOR_ERASE:
- FLASH_LOADER->RETURN_CODE = FLASH_BUSY;
- msp432_flash_sector_erase();
- FLASH_LOADER->FLASH_FUNCTION = 0;
- break;
- case FLASH_PROGRAM:
- FLASH_LOADER->RETURN_CODE = FLASH_BUSY;
- msp432_flash_write();
- FLASH_LOADER->FLASH_FUNCTION = 0;
- break;
- case FLASH_CONTINUOUS_PROGRAM:
- FLASH_LOADER->RETURN_CODE = FLASH_BUSY;
- msp432_flash_continous_write();
- FLASH_LOADER->FLASH_FUNCTION = 0;
- break;
- case FLASH_EXIT:
- FLASH_LOADER->RETURN_CODE = FLASH_BUSY;
- msp432_flash_exit();
- FLASH_LOADER->FLASH_FUNCTION = 0;
- break;
- case FLASH_NO_COMMAND:
- break;
- default:
- FLASH_LOADER->RETURN_CODE = FLASH_WRONG_COMMAND;
- break;
+ case FLASH_INIT:
+ FLASH_LOADER->RETURN_CODE = FLASH_BUSY;
+ msp432_flash_init();
+ FLASH_LOADER->FLASH_FUNCTION = 0;
+ break;
+ case FLASH_MASS_ERASE:
+ FLASH_LOADER->RETURN_CODE = FLASH_BUSY;
+ msp432_flash_mass_erase();
+ FLASH_LOADER->FLASH_FUNCTION = 0;
+ break;
+ case FLASH_SECTOR_ERASE:
+ FLASH_LOADER->RETURN_CODE = FLASH_BUSY;
+ msp432_flash_sector_erase();
+ FLASH_LOADER->FLASH_FUNCTION = 0;
+ break;
+ case FLASH_PROGRAM:
+ FLASH_LOADER->RETURN_CODE = FLASH_BUSY;
+ msp432_flash_write();
+ FLASH_LOADER->FLASH_FUNCTION = 0;
+ break;
+ case FLASH_CONTINUOUS_PROGRAM:
+ FLASH_LOADER->RETURN_CODE = FLASH_BUSY;
+ msp432_flash_continous_write();
+ FLASH_LOADER->FLASH_FUNCTION = 0;
+ break;
+ case FLASH_EXIT:
+ FLASH_LOADER->RETURN_CODE = FLASH_BUSY;
+ msp432_flash_exit();
+ FLASH_LOADER->FLASH_FUNCTION = 0;
+ break;
+ case FLASH_NO_COMMAND:
+ break;
+ default:
+ FLASH_LOADER->RETURN_CODE = FLASH_WRONG_COMMAND;
+ break;
}
}
}
diff --git a/contrib/loaders/flash/msp432/main_msp432p411x.c b/contrib/loaders/flash/msp432/main_msp432p411x.c
index efc05a3b78..391057f2e5 100644
--- a/contrib/loaders/flash/msp432/main_msp432p411x.c
+++ b/contrib/loaders/flash/msp432/main_msp432p411x.c
@@ -52,41 +52,41 @@ int main(void)
while (1) {
switch (FLASH_LOADER->FLASH_FUNCTION) {
- case FLASH_INIT:
- FLASH_LOADER->RETURN_CODE = FLASH_BUSY;
- msp432_flash_init();
- FLASH_LOADER->FLASH_FUNCTION = 0;
- break;
- case FLASH_MASS_ERASE:
- FLASH_LOADER->RETURN_CODE = FLASH_BUSY;
- msp432_flash_mass_erase();
- FLASH_LOADER->FLASH_FUNCTION = 0;
- break;
- case FLASH_SECTOR_ERASE:
- FLASH_LOADER->RETURN_CODE = FLASH_BUSY;
- msp432_flash_sector_erase();
- FLASH_LOADER->FLASH_FUNCTION = 0;
- break;
- case FLASH_PROGRAM:
- FLASH_LOADER->RETURN_CODE = FLASH_BUSY;
- msp432_flash_write();
- FLASH_LOADER->FLASH_FUNCTION = 0;
- break;
- case FLASH_CONTINUOUS_PROGRAM:
- FLASH_LOADER->RETURN_CODE = FLASH_BUSY;
- msp432_flash_continous_write();
- FLASH_LOADER->FLASH_FUNCTION = 0;
- break;
- case FLASH_EXIT:
- FLASH_LOADER->RETURN_CODE = FLASH_BUSY;
- msp432_flash_exit();
- FLASH_LOADER->FLASH_FUNCTION = 0;
- break;
- case FLASH_NO_COMMAND:
- break;
- default:
- FLASH_LOADER->RETURN_CODE = FLASH_WRONG_COMMAND;
- break;
+ case FLASH_INIT:
+ FLASH_LOADER->RETURN_CODE = FLASH_BUSY;
+ msp432_flash_init();
+ FLASH_LOADER->FLASH_FUNCTION = 0;
+ break;
+ case FLASH_MASS_ERASE:
+ FLASH_LOADER->RETURN_CODE = FLASH_BUSY;
+ msp432_flash_mass_erase();
+ FLASH_LOADER->FLASH_FUNCTION = 0;
+ break;
+ case FLASH_SECTOR_ERASE:
+ FLASH_LOADER->RETURN_CODE = FLASH_BUSY;
+ msp432_flash_sector_erase();
+ FLASH_LOADER->FLASH_FUNCTION = 0;
+ break;
+ case FLASH_PROGRAM:
+ FLASH_LOADER->RETURN_CODE = FLASH_BUSY;
+ msp432_flash_write();
+ FLASH_LOADER->FLASH_FUNCTION = 0;
+ break;
+ case FLASH_CONTINUOUS_PROGRAM:
+ FLASH_LOADER->RETURN_CODE = FLASH_BUSY;
+ msp432_flash_continous_write();
+ FLASH_LOADER->FLASH_FUNCTION = 0;
+ break;
+ case FLASH_EXIT:
+ FLASH_LOADER->RETURN_CODE = FLASH_BUSY;
+ msp432_flash_exit();
+ FLASH_LOADER->FLASH_FUNCTION = 0;
+ break;
+ case FLASH_NO_COMMAND:
+ break;
+ default:
+ FLASH_LOADER->RETURN_CODE = FLASH_WRONG_COMMAND;
+ break;
}
}
}
diff --git a/doc/fdl.texi b/doc/fdl.texi
index 2189f80a66..72916a9fb7 100644
--- a/doc/fdl.texi
+++ b/doc/fdl.texi
@@ -7,7 +7,7 @@
@display
Copyright @copyright{} 2000,2001,2002 Free Software Foundation, Inc.
-51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
diff --git a/doc/manual/helper.txt b/doc/manual/helper.txt
index 6cf3c977bf..29e84e6f0b 100644
--- a/doc/manual/helper.txt
+++ b/doc/manual/helper.txt
@@ -97,18 +97,6 @@ registration, while the @c unregister_command() and
These may be called at any time, allowing the command set to change in
response to system actions.
-@subsection helpercmdjim Jim Command Registration
-
-The command_registration structure provides support for registering
-native Jim command handlers (@c jim_handler) too. For these handlers,
-the module can provide help and usage support; however, this mechanism
-allows Jim handlers to be called as sub-commands of other commands.
-These commands may be registered with a private data value (@c
-jim_handler_data) that will be available when called, as with low-level
-Jim command registration.
-
-A command may have a normal @c handler or a @c jim_handler, but not both.
-
@subsection helpercmdregisterchains Command Chaining
When using register_commands(), the array of commands may reference
diff --git a/doc/manual/primer/docs.txt b/doc/manual/primer/docs.txt
index 1aefa17e6d..ccf4550d51 100644
--- a/doc/manual/primer/docs.txt
+++ b/doc/manual/primer/docs.txt
@@ -16,7 +16,6 @@ OpenOCD presently produces several kinds of documentation:
- Provides overview, usage, reference, and FAQ for each device.
- Written using LaTeX language with custom macros.
- Created with 'make references'.
- - See @subpage primerlatex and @ref stylelatex.
- The Manual:
- Focuses on developing the OpenOCD software.
- Details the architecture, driver interfaces, and processes.
@@ -44,19 +43,6 @@ the Texinfo web site for the Texinfo manual and more information.
OpenOCD style guidelines for Texinfo documentation can be found on the
@ref styletexinfo page.
- */
-/** @page primerlatex LaTeX Primer
-
-The OpenOCD project provides a number of reference guides using the
-LaTeX typesetting language.
-
-- OpenOCD Quick Reference Sheets
-- OpenOCD Hardware Reference Guides
-
-These documents have not yet been produced, so this Primer serves as
-a placeholder to describe how they are created and can be extended.
-The same holds true for the @ref stylelatex page.
-
*/
/** @page primerdoxygen Doxygen Primer
@@ -118,7 +104,6 @@ This file contains the Doxygen source code for the @ref primerdocs.
The @ref primerdocs page also contains the following sections:
- @ref primertexinfo
-- @ref primerlatex
- @ref primerdoxygen
*/
diff --git a/doc/manual/server.txt b/doc/manual/server.txt
index 20e48c1f43..3c31e6fc62 100644
--- a/doc/manual/server.txt
+++ b/doc/manual/server.txt
@@ -190,7 +190,6 @@ Remember: OpenOCD runs on:
-# FreeBSD
-# Cygwin
-# MinGW32
--# Ecos
How can we get that to work?
diff --git a/doc/manual/style.txt b/doc/manual/style.txt
index f7a12988fc..fa08f4de96 100644
--- a/doc/manual/style.txt
+++ b/doc/manual/style.txt
@@ -22,7 +22,6 @@ providing documentation, either as part of the C code or stand-alone.
- @subpage styledoxygen
- @subpage styletexinfo
-- @subpage stylelatex
Feedback would be welcome to improve the OpenOCD guidelines.
@@ -449,13 +448,6 @@ be as productive as possible. Needing to look at OpenOCD source code,
to figure out how to use it is a bad sign, though it's OK to need to
look at the User's guide to figure out what a config script is doing.
- */
-/** @page stylelatex LaTeX Style Guide
-
-This page needs to provide style guidelines for using LaTeX, the
-typesetting language used by The References for OpenOCD Hardware.
-Likewise, the @ref primerlatex for using this guide needs to be completed.
-
*/
/** @page styleperl Perl Style Guide
@@ -510,7 +502,6 @@ documentation languages:
- @ref stylec
- @ref styledoxygen
- @ref styletexinfo
-- @ref stylelatex
- @ref styleperl
- @ref styleautotools
diff --git a/doc/openocd.texi b/doc/openocd.texi
index 6d9c198abc..e15188cf79 100644
--- a/doc/openocd.texi
+++ b/doc/openocd.texi
@@ -529,9 +529,8 @@ debuggers to ARM Cortex based targets @url{http://www.keil.com/support/man/docs/
@section IBM PC Parallel Printer Port Based
-The two well-known ``JTAG Parallel Ports'' cables are the Xilinx DLC5
-and the Macraigor Wiggler. There are many clones and variations of
-these on the market.
+The two well-known JTAG parallel port cables are the Xilinx DLC5 and the Macraigor Wiggler.
+There are many clones and variations of these on the market.
Note that parallel ports are becoming much less common, so if you
have the choice you should probably avoid these adapters in favor
@@ -553,7 +552,7 @@ produced, PDF schematics are easily found and it is easy to make.
@* Link: @url{http://www.ccac.rwth-aachen.de/~michaels/index.php/hardware/armjtag}
@item @b{Wiggler_ntrst_inverted}
-@* Yet another variation - See the source code, src/jtag/parport.c
+@* Yet another variation, see configuration in @file{interface/parport/wiggler-ntrst-inverted.cfg}
@item @b{old_amt_wiggler}
@* Unknown - probably not on the market today
@@ -613,6 +612,12 @@ emulation model of target hardware.
@item @b{xlnx_pcie_xvc}
@* A JTAG driver exposing Xilinx Virtual Cable over PCI Express to OpenOCD as JTAG/SWD interface.
+@* Link: @url{https://www.xilinx.com/products/intellectual-property/debug-bridge.html}
+
+@item @b{xlnx_axi_xvc}
+@* A JTAG driver exposing JTAG to OpenOCD over AXI-mapped registers.
+@* Link: @url{https://docs.amd.com/r/en-US/pg437-axi-jtag/Introduction}
+@* Link: @url{https://china.xilinx.com/support/documentation/application_notes/xapp1251-xvc-zynq-petalinux.pdf}
@item @b{linuxspidev}
@* A SPI based SWD driver using Linux SPI devices.
@@ -627,6 +632,10 @@ This is deprecated from Linux v5.3; prefer using @b{linuxgpiod}.
@item @b{esp_usb_jtag}
@* A JTAG driver to communicate with builtin debug modules of Espressif ESP32-C3 and ESP32-S3 chips using OpenOCD.
+@item @b{ch347}
+@* A JTAG driver that works with the WCH CH347F and CH347T chips.
+When using the CH347T, it must be configured to operate in mode 3 (UART + JTAG).
+
@end itemize
@node About Jim Tcl
@@ -804,8 +813,7 @@ itself), use the @option{-d} command line switch. This sets the
@option{debug_level} to "3", outputting the most information,
including debug messages. The default setting is "2", outputting only
informational messages, warnings and errors. You can also change this
-setting from within a telnet or gdb session using @command{debug_level}
-(@pxref{debuglevel,,debug_level}).
+setting from within a telnet or gdb session using @ref{debuglevel,,@command{debug_level}}.
You can redirect all output from the server to a file using the
@option{-l } switch.
@@ -1382,11 +1390,11 @@ Read the OpenOCD source code (and Developer's Guide)
if you have a new kind of hardware interface
and need to provide a driver for it.
-@deffn {Command} {find} 'filename'
+@deffn {Command} {find} filename
Prints full path to @var{filename} according to OpenOCD search rules.
@end deffn
-@deffn {Command} {ocd_find} 'filename'
+@deffn {Command} {ocd_find} filename
Prints full path to @var{filename} according to OpenOCD search rules. This
is a low level function used by the @command{find}. Usually you want
to use @command{find}, instead.
@@ -1432,7 +1440,6 @@ In addition to target-specific utility code, another way that
board and target config files communicate is by following a
convention on how to use certain variables.
-The full Tcl/Tk language supports ``namespaces'', but Jim Tcl does not.
Thus the rule we follow in OpenOCD is this: Variables that begin with
a leading underscore are temporary in nature, and can be modified and
used at will within a target configuration file.
@@ -2431,13 +2438,14 @@ dict get [adapter list] ftdi
@deffn {Config Command} {adapter gpio [ @
@option{tdo} | @option{tdi} | @option{tms} | @option{tck} | @option{trst} | @
@option{swdio} | @option{swdio_dir} | @option{swclk} | @option{srst} | @
- @option{led} @
+ @option{led} | @option{user0} @
[ @
gpio_number | @option{-chip} chip_number | @
@option{-active-high} | @option{-active-low} | @
@option{-push-pull} | @option{-open-drain} | @option{-open-source} | @
@option{-pull-none} | @option{-pull-up} | @option{-pull-down} | @
@option{-init-inactive} | @option{-init-active} | @option{-init-input} @
+ @option{-exit-inactive} | @option{-exit-active} | @option{-exit-input} | @option{-exit-no-change} @
] ]}
Define the GPIO mapping that the adapter will use. The following signals can be
@@ -2450,6 +2458,7 @@ JTAG transport signals
@item @option{swdio_dir}: optional swdio buffer control signal
@item @option{srst}: system reset signal
@item @option{led}: optional activity led
+@item @option{user0}: optional, user-specific signal
@end itemize
@@ -2472,11 +2481,14 @@ equivalent to issuing the single command @command{gpio led 7 -chip 1
signals which are inputs. The drive mode for the srst and trst signals must be
set with the @command{adapter reset_config} command. It is not permissible to
set the initial state of swdio_dir as it is derived from the initial state of
-swdio. The command @command{adapter gpio} prints the current configuration for
-all GPIOs while the command @command{adapter gpio gpio_name} prints the current
-configuration for gpio_name. Not all adapters support this generic GPIO mapping,
-some require their own commands to define the GPIOs used. Adapters that support
-the generic mapping may not support all of the listed options.
+swdio. Accordingly, the final state before the adapter terminates its operation,
+so-called “exit state”, can be set. By default the state and configuration of an
+output pin is not changed when the driver terminates its operation. The
+command @command{adapter gpio} prints the current configuration for all GPIOs
+while the command @command{adapter gpio gpio_name} prints the current configuration
+for gpio_name. Not all adapters support this generic GPIO mapping, some require
+their own commands to define the GPIOs used. Adapters that support the generic
+mapping may not support all of the listed options.
@end deffn
@deffn {Command} {adapter name}
@@ -2499,6 +2511,9 @@ If this command is not specified, serial strings are not checked.
Only the following adapter drivers use the serial string from this command:
arm-jtag-ew, cmsis_dap, esp_usb_jtag, ft232r, ftdi, hla (stlink, ti-icdi), jlink, kitprog, opendus,
openjtag, osbdm, presto, rlink, st-link, usb_blaster (ublast2), usbprog, vsllink, xds110.
+
+For jlink adapters, the @var{serial_string} is also compared
+against the adapter's nickname.
@end deffn
@section Interface Drivers
@@ -2508,6 +2523,8 @@ enabled when OpenOCD is configured, in order to be made
available at run time.
@deffn {Interface Driver} {amt_jtagaccel}
+@b{Note: This adapter is deprecated and support will be removed in the next release!}
+
Amontec Chameleon in its JTAG Accelerator configuration,
connected to a PC's EPP mode parallel port.
This defines some driver-specific commands:
@@ -2544,9 +2561,62 @@ and a specific set of GPIOs is used.
@c chooses among list of bit configs ... only one option
@end deffn
+@deffn {Interface Driver} {ch347}
+Driver for WCH CH347F and CH347T chips.
+When using the CH347T, it must be configured to operate in mode 3 (UART + JTAG).
+
+@b{WARNING:} WCH CH347T chips have rather poor performance
+with respect to the USB HS connection. Upgrade firmware to the latest version!
+@itemize @bullet
+@item Chip version 2.41:
+@itemize @minus
+@item JTAG timing is very weird, some clock pulses are
+much shorter then the requested clock frequency.
+@item SWD is not implemented.
+@end itemize
+@item Chip version 4.41:
+@itemize @minus
+@item SWD clock is limited to 1 MHz maximum.
+@item SWD reading AP reg CH347 erroneously drives
+SWDIO to H for 392 ns after the last ACK bit. Some devices get so upset
+that send wrong data with parity error. A resistor in the SWDIO circuit
+mitigates the problem.
+@item A long SWD operation causes that USB host disconnects the adapter.
+@end itemize
+@item Chip version 5.44:
+@itemize @minus
+@item Maximal SWD clock speed is 5 MHz
+@item A long SWD operation causes that USB host disconnects the adapter.
+@end itemize
+@end itemize
+
+The driver supports activity LED through the generic
+command @ref{adapter gpio, @command{adapter gpio led}}.
+
+This driver has these driver-specific command:
+
+@deffn {Config Command} {ch347 vid_pid} [vid pid]+
+The vendor ID and product ID of the CH347F or CH347T device in mode 3. If not specified
+the driver will use vendor ID 0x1a86 and product ID 0x55dd.
+Currently, up to four [@var{vid}, @var{pid}] pairs may be given, e.g.
+@example
+ch347 vid_pid 0x1a86 0x55dd 0x1a86 0x55de
+@end example
+@end deffn
+
+@deffn {Config Command} {ch347 device_desc} description
+If specified connect to a device which exactly has this product description
+string. If not specified the first found device with the correct vendor
+and product ID will be connected.
+@example
+ch347 device_desc "EasyDevKit"
+@end example
+@end deffn
+@end deffn
+
@deffn {Interface Driver} {cmsis-dap}
ARM CMSIS-DAP compliant based adapter v1 (USB HID based)
-or v2 (USB bulk).
+or v2 (USB bulk or TCP/IP).
@deffn {Config Command} {cmsis-dap vid_pid} [vid pid]+
The vendor ID and product ID of the CMSIS-DAP device. If not specified
@@ -2557,23 +2627,56 @@ cmsis-dap vid_pid 0xc251 0xf001 0x0d28 0x0204
@end example
@end deffn
-@deffn {Config Command} {cmsis-dap backend} [@option{auto}|@option{usb_bulk}|@option{hid}]
+@deffn {Config Command} {cmsis-dap backend} [@option{auto}|@option{usb_bulk}|@option{hid}|@option{tcp}]
Specifies how to communicate with the adapter:
@itemize @minus
-@item @option{hid} Use HID generic reports - CMSIS-DAP v1
+@item @option{hid} Use USB HID generic reports - CMSIS-DAP v1
@item @option{usb_bulk} Use USB bulk - CMSIS-DAP v2
-@item @option{auto} First try USB bulk CMSIS-DAP v2, if not found try HID CMSIS-DAP v1.
-This is the default if @command{cmsis-dap backend} is not specified.
+@item @option{tcp} Use TCP/IP instead of USB
+@item @option{auto} First try USB bulk CMSIS-DAP v2, if not found try USB HID
+CMSIS-DAP v1, if not found try TCP (if @command{cmsis-dap tcp host} is
+configured). This is the default if @command{cmsis-dap backend} is not
+specified.
@end itemize
@end deffn
-@deffn {Config Command} {cmsis-dap usb interface} [number]
+@deffn {Config Command} {cmsis-dap usb interface} number
Specifies the @var{number} of the USB interface to use in v2 mode (USB bulk).
In most cases need not to be specified and interfaces are searched by
interface string or for user class interface.
@end deffn
+@deffn {Config Command} {cmsis-dap tcp host} hostname
+Specifies the @var{hostname} or IP address of the remote programmer. For use
+with 'tcp' backend only.
+@example
+cmsis-dap backend tcp
+cmsis-dap tcp host 192.168.1.4
+@end example
+@end deffn
+
+@deffn {Config Command} {cmsis-dap tcp port} port
+Specifies the TCP @var{port} number used by the remote programmer for DAP
+commands. The default port is 4441. For use with 'tcp' backend only.
+@example
+cmsis-dap backend tcp
+cmsis-dap tcp host 192.168.1.4
+cmsis-dap tcp port 4441
+@end example
+@end deffn
+
+@deffn {Config Command} {cmsis-dap tcp min_timeout} milliseconds
+Sets a lower bound on the requested timeout in @var{milliseconds} to wait for
+response packets from the remote programmer when using the 'tcp' backend. The
+user may want to use a larger value on slower networks, to avoid getting
+command mismatch errors. Default value is 150 milliseconds. For use with 'tcp'
+backend only.
+@example
+cmsis-dap tcp min_timeout 200
+@end example
+@end deffn
+
@deffn {Command} {cmsis-dap quirk} [@option{enable}|@option{disable}]
Enables or disables the following workarounds of known CMSIS-DAP adapter
quirks:
@@ -2956,6 +3059,8 @@ image. To be used with USB-Blaster II only.
@end deffn
@deffn {Interface Driver} {gw16012}
+@b{Note: This adapter is deprecated and support will be removed in the next release!}
+
Gateworks GW16012 JTAG programmer.
This has one driver-specific command:
@@ -3107,61 +3212,66 @@ version, and target voltage.
@end deffn
@deffn {Interface Driver} {parport}
-Supports PC parallel port bit-banging cables:
-Wigglers, PLD download cable, and more.
-These interfaces have several commands, used to configure the driver
-before initializing the JTAG scan chain:
-
-@deffn {Config Command} {parport cable} name
-Set the layout of the parallel port cable used to connect to the target.
-This is a write-once setting.
-Currently valid cable @var{name} values include:
-@itemize @minus
-@item @b{altium} Altium Universal JTAG cable.
-@item @b{arm-jtag} Same as original wiggler except SRST and
-TRST connections reversed and TRST is also inverted.
-@item @b{chameleon} The Amontec Chameleon's CPLD when operated
-in configuration mode. This is only used to
-program the Chameleon itself, not a connected target.
-@item @b{dlc5} The Xilinx Parallel cable III.
-@item @b{flashlink} The ST Parallel cable.
-@item @b{lattice} Lattice ispDOWNLOAD Cable
-@item @b{old_amt_wiggler} The Wiggler configuration that comes with
-some versions of
-Amontec's Chameleon Programmer. The new version available from
-the website uses the original Wiggler layout ('@var{wiggler}')
-@item @b{triton} The parallel port adapter found on the
-``Karo Triton 1 Development Board''.
-This is also the layout used by the HollyGates design
-(see @uref{http://www.lartmaker.nl/projects/jtag/}).
-@item @b{wiggler} The original Wiggler layout, also supported by
-several clones, such as the Olimex ARM-JTAG
-@item @b{wiggler2} Same as original wiggler except an led is fitted on D5.
-@item @b{wiggler_ntrst_inverted} Same as original wiggler except TRST is inverted.
-@end itemize
+This driver supports PC parallel port bit-banging adapters.
+Only JTAG is supported as transport protocol.
+The driver supports Linux, FreeBSD, and Windows.
+However, the Windows support is untested and unmaintained.
+
+The pin configuration is handled by the generic command @ref{adapter gpio, @command{adapter gpio}}.
+In addition to the JTAG signals, the driver also supports the activity LED signal.
+
+The data and status pins of the parallel port are used as output and input pins, respectively.
+The pin direction is given in the following table.
+
+@multitable @columnfractions .2 .1 .1 .1 .1 .1 .1 .1 .1
+@headitem Pin direction
+@item Input
+@tab ~11
+@tab 10
+@tab 12
+@tab 13
+@tab 15
+@tab -
+@tab -
+@tab -
+@item Output
+@tab 9
+@tab 8
+@tab 7
+@tab 6
+@tab 5
+@tab 4
+@tab 3
+@tab 2
+@end multitable
+
+@deffn {Config Command} {parport port} file
+Specify the device file of the parallel port device.
+The parallel port device file is usually @file{/dev/parportX} on Linux and @file{/dev/ppiX} on FreeBSD.
+
+For legacy reason, the port number @var{X} can be specified instead of the device file.
+@b{Note:} Using the port number is a deprecated feature and will be removed in the future.
+
+When using direct I/O, the number is the I/O port number.
+The default port number is 0x378 (LTP1).
+@b{Note:} Direct I/O support is deprecated and will be removed in the future.
@end deffn
-@deffn {Config Command} {parport port} [port_number]
-Display either the address of the I/O port
-(default: 0x378 for LPT1) or the number of the @file{/dev/parport} device.
-If a parameter is provided, first switch to use that port.
-This is a write-once setting.
+@deffn {Config Command} {parport write_on_exit} (@option{on}|@option{off})
+@b{Note:} This command is deprecated and will be removed in the future.
+Use the command @command{adapter gpio} to configure the pin states before the adapter terminates its operation.
-When using PPDEV to access the parallel port, use the number of the parallel port:
-@option{parport port 0} (the default). If @option{parport port 0x378} is specified
-you may encounter a problem.
+Configure whether the driver sets the value specified by @command{adapter gpio} to the output pins on shutdown.
@end deffn
-@deffn {Config Command} {parport toggling_time} [nanoseconds]
-Displays how many nanoseconds the hardware needs to toggle TCK;
-the parport driver uses this value to obey the
-@command{adapter speed} configuration.
-When the optional @var{nanoseconds} parameter is given,
-that setting is changed before displaying the current value.
+@deffn {Config Command} {parport toggling_time} time
+Configure how many nanoseconds the hardware needs to toggle TCK.
+The driver uses this value to obey the @command{adapter speed} configuration.
The default setting should work reasonably well on commodity PC hardware.
However, you may want to calibrate for your specific hardware.
+
@quotation Tip
To measure the toggling time with a logic analyzer or a digital storage
oscilloscope, follow the procedure below:
@@ -3169,15 +3279,18 @@ oscilloscope, follow the procedure below:
> parport toggling_time 1000
> adapter speed 500
@end example
+
This sets the maximum JTAG clock speed of the hardware, but
the actual speed probably deviates from the requested 500 kHz.
Now, measure the time between the two closest spaced TCK transitions.
You can use @command{runtest 1000} or something similar to generate a
large set of samples.
Update the setting to match your measurement:
+
@example
> parport toggling_time
@end example
+
Now the clock speed will be a better match for @command{adapter speed}
command given in OpenOCD scripts and event handlers.
@@ -3189,20 +3302,6 @@ match with the rate you specified in the @command{adapter speed} command;
be conservative.
@end quotation
@end deffn
-
-@deffn {Config Command} {parport write_on_exit} (@option{on}|@option{off})
-This will configure the parallel driver to write a known
-cable-specific value to the parallel interface on exiting OpenOCD.
-@end deffn
-
-For example, the interface configuration file for a
-classic ``Wiggler'' cable on LPT2 might look something like this:
-
-@example
-adapter driver parport
-parport port 0x278
-parport cable wiggler
-@end example
@end deffn
@deffn {Interface Driver} {presto}
@@ -3374,9 +3473,26 @@ The string will be of the format "DDDD:BB:SS.F" such as "0000:65:00.1".
@end deffn
@end deffn
+@deffn {Interface Driver} {xlnx_axi_xvc}
+This driver supports the Xilinx JTAG mapping over AXI using the AXI to JTAG
+Converter or the AXI-to-JTAG mode of the debug bridge.
+It is commonly found in Xilinx MPSoC based designs. It allows debugging
+fabric based JTAG/SWD devices such as Cortex-M1/M3 or RISC-V softcores. Access to this
+is exposed via extended capability registers in the AXI-mapped configuration space.
+
+@deffn {Config Command} {xlnx_axi_xvc dev_addr} addr
+Specifies the address of the AXI-mapped registers via parameter @var{addr}.
+
+The correct value for @var{addr} is specified in the "Address Editor" tab
+in Vivado.
+@end deffn
+@end deffn
+
@deffn {Interface Driver} {bcm2835gpio}
-This SoC is present in Raspberry Pi which is a cheap single-board computer
-exposing some GPIOs on its expansion header.
+This GPIO interface is present in Raspberry Pi 0-4 which is a cheap
+single-board computer exposing some GPIOs on its expansion header.
+
+@emph{Note:} for Raspberry Pi 5, use @b{linuxgpiod} not this driver.
The driver accesses memory-mapped GPIO peripheral registers directly
for maximum performance, but the only possible race condition is for
@@ -3415,9 +3531,7 @@ and drive strength is reduced to 4 mA (2 mA on RPi 4).
@deffn {Config Command} {bcm2835gpio peripheral_base} @var{base}
Set the peripheral base register address to access GPIOs.
Ignored if @file{/dev/gpiomem} is used. For the RPi1, use
-0x20000000. For RPi2 and RPi3, use 0x3F000000. For RPi4, use 0xFE000000. A full
-list can be found in the
-@uref{https://www.raspberrypi.org/documentation/hardware/raspberrypi/peripheral_addresses.md, official guide}.
+0x20000000. For RPi2 and RPi3, use 0x3F000000. For RPi4, use 0xFE000000.
@end deffn
@end deffn
@@ -5468,7 +5582,8 @@ Displays the current target state:
@code{debug-running},
@code{halted},
@code{reset},
-@code{running}, or @code{unknown}.
+@code{running},
+@code{unavailable} or @code{unknown}.
(Also, @pxref{eventpolling,,Event Polling}.)
@end deffn
@@ -5898,6 +6013,24 @@ The flash bank to use is inferred from the @var{address} of
each block, and the specified length must stay within that bank.
@end deffn
+@deffn {Command} {flash read_memory} address width count
+This function provides an efficient way to read flash memory from a Tcl script.
+A Tcl list containing the requested memory elements is returned by this function.
+
+@itemize
+@item @var{address} ... flash memory address
+@item @var{width} ... memory access bit size, can be 8, 16, 32 or 64
+@item @var{count} ... number of elements to read
+@end itemize
+
+For example, the following command reads two 32 bit words from the flash
+memory at address 0x08000000:
+
+@example
+flash read_memory 0x08000000 32 2
+@end example
+@end deffn
+
@deffn {Command} {flash write_bank} num filename [offset]
Write the binary @file{filename} to flash bank @var{num},
starting at @var{offset} bytes from the beginning of the bank. If @var{offset}
@@ -6591,6 +6724,50 @@ the flash.
@end deffn
@end deffn
+@deffn {Flash Driver} {artery}
+@cindex artery
+This driver supports Artery Technology devices from the following series:
+
+@itemize
+@item AT32F403A / AT32F407
+@item AT32F413
+@item AT32F415
+@item AT32F421
+@item AT32F423
+@item AT32F425
+@item AT32F435 / AT32F437
+@item AT32WB415
+@end itemize
+
+Devices with dual-bank flash memory are currently not supported.
+Also, access to user data in the user system data (USD) area is not supported.
+
+The driver supports flash write protection and flash access protection (FAP).
+For the FAP, only the low-level protection is implemented.
+
+@b{Note:} a change of the flash write protection or FAP requires a device reset for the changes to take effect.
+
+The @var{artery} driver provides the following additional commands:
+
+@deffn {Command} {artery fap enable}
+Enable low-level flash access protection (FAP).
+@end deffn
+
+@deffn {Command} {artery fap disable}
+Disable flash access protection (FAP).
+@end deffn
+
+@deffn {Command} {artery fap state}
+Get the flash access protection (FAP) state.
+The state is a boolean value that indicates whether the FAP is configured in level 'low' or higher.
+@end deffn
+
+@deffn {Command} {artery mass_erase}
+Erase entire bank.
+@end deffn
+
+@end deffn
+
@deffn {Flash Driver} {at91samd}
@cindex at91samd
All members of the ATSAM D2x, D1x, D0x, ATSAMR, ATSAML and ATSAMC microcontroller
@@ -6839,6 +7016,18 @@ This driver uses the same command names/syntax as @xref{at91sam3}.
flash bank $_FLASHNAME atsamv 0x00400000 0 0 0 $_TARGETNAME
@end example
+These families also have a user signature area located at the beginning
+of an embedded flash. This is a 512 bytes large page whose data are not
+erased by assering ERASE pin or by software ERASE command. It can be
+used to store configuration, keys, trimming values and so on. The area
+overlaps with the beginning of standard flash and uses special commands
+to perform write/read operations. OpenOCD locates the signature area
+at fake address above 32 bit address space, specifically at 0x100000000.
+
+@example
+flash bank $_SIGNATURENAME atsamv 0x100000000 0 0 0 $_TARGETNAME
+@end example
+
@deffn {Command} {atsamv gpnvm} [@option{show} [@option{all}|number]]
@deffnx {Command} {atsamv gpnvm} (@option{clr}|@option{set}) number
With no parameters, @option{show} or @option{show all},
@@ -8319,10 +8508,8 @@ is the register offset of the Option byte to read.
For example to read the FLASH_OPTR register:
@example
-stm32l4x option_read 0 0x20
-# Option Register (for STM32L4x): <0x40022020> = 0xffeff8aa
-# Option Register (for STM32WBx): <0x58004020> = ...
-# The correct flash base address will be used automatically
+> stm32l4x option_read 0 0x20
+0xffeff8aa
@end example
The above example will read out the FLASH_OPTR register which contains the RDP
@@ -9311,10 +9498,10 @@ will proceed to quit.
@end deffn
@anchor{debuglevel}
-@deffn {Command} {debug_level} [n]
+@deffn {Command} {debug_level} [number]
@cindex message level
-Display debug level.
-If @var{n} (from 0..4) is provided, then set it to that level.
+Without arguments it displays the current debug level.
+If @var{number} (from 0..4) is provided, then set it to that level.
This affects the kind of messages sent to the server log.
Level 0 is error messages only;
level 1 adds warnings;
@@ -9341,7 +9528,7 @@ Redirect logging to @var{filename}. If used without an argument or
stderr.
@end deffn
-@deffn {Command} {add_script_search_dir} [directory]
+@deffn {Command} {add_script_search_dir} directory
Add @var{directory} to the file/script search path.
@end deffn
@@ -9734,12 +9921,14 @@ hardware support for a handful of code breakpoints and data
watchpoints.
In addition, CPUs almost always support software breakpoints.
-@deffn {Command} {bp} [address len [@option{hw}]]
+@deffn {Command} {bp} [address [asid] len [@option{hw} | @option{hw_ctx}]]
With no parameters, lists all active breakpoints.
Else sets a breakpoint on code execution starting
at @var{address} for @var{length} bytes.
-This is a software breakpoint, unless @option{hw} is specified
-in which case it will be a hardware breakpoint.
+This is a software breakpoint, unless @option{hw} or @option{hw_ctx}
+is specified in which case it will be a hardware, context or hybrid breakpoint.
+The context and hybrid breakpoints require an additional parameter @var{asid}:
+address space identifier.
(@xref{arm9vectorcatch,,arm9 vector_catch}, or @pxref{xscalevectorcatch,,xscale vector_catch},
for similar mechanisms that do not consume hardware breakpoints.)
@@ -9876,11 +10065,11 @@ Requests the current target to map the specified @var{virtual_address}
to its corresponding physical address, and displays the result.
@end deffn
-@deffn {Command} {add_help_text} 'command_name' 'help-string'
+@deffn {Command} {add_help_text} command_name help_string
Add or replace help text on the given @var{command_name}.
@end deffn
-@deffn {Command} {add_usage_text} 'command_name' 'help-string'
+@deffn {Command} {add_usage_text} command_name help_string
Add or replace usage text on the given @var{command_name}.
@end deffn
@@ -10739,10 +10928,6 @@ Display/set the current core displayed in GDB
Selects whether interrupts will be processed when single stepping
@end deffn
-@deffn {Command} {cache_config l2x} [base way]
-configure l2x cache
-@end deffn
-
@deffn {Command} {cortex_a mmu dump} [@option{0}|@option{1}|@option{addr} address [@option{num_entries}]]
Dump the MMU translation table from TTB0 or TTB1 register, or from physical
memory location @var{address}. When dumping the table from @var{address}, print at most
@@ -10958,6 +11143,10 @@ Enable or disable trace output for all ITM stimulus ports.
@subsection Cortex-M specific commands
@cindex Cortex-M
+@deffn {Command} {cortex_m cache_info}
+Report information about the type and size of the cache, if present.
+@end deffn
+
@deffn {Command} {cortex_m maskisr} (@option{auto}|@option{on}|@option{off}|@option{steponly})
Control masking (disabling) interrupts during target step/resume.
diff --git a/doc/usb_adapters/ch347/1a86_55dd_easydevkit.txt b/doc/usb_adapters/ch347/1a86_55dd_easydevkit.txt
new file mode 100644
index 0000000000..9a0ae71edf
--- /dev/null
+++ b/doc/usb_adapters/ch347/1a86_55dd_easydevkit.txt
@@ -0,0 +1,146 @@
+# SPDX-License-Identifier: GPL-2.0-or-later OR GFDL-1.2-no-invariants-or-later
+
+# Link: https://www.easydevkits.com
+# PCB: ESP32-WROVER-E WCH JTAG DevKit v0.1
+# Chip: CH347T in mode 3 (UART+JTAG mode)
+# Product id of 0x55dd is only valid if the chip is started in mode 3
+# These are the other product ids: mode 0 = 0x55da, mode 1 = 0x55db, mode 2 = 0x55dc
+# The similar chip CH347F has no modes and always product id 0x55de
+
+Bus 001 Device 013: ID 1a86:55dd QinHeng Electronics EasyDevKit
+Device Descriptor:
+ bLength 18
+ bDescriptorType 1
+ bcdUSB 2.00
+ bDeviceClass 0
+ bDeviceSubClass 0
+ bDeviceProtocol 0
+ bMaxPacketSize0 64
+ idVendor 0x1a86 QinHeng Electronics
+ idProduct 0x55dd
+ bcdDevice 4.41
+ iManufacturer 1 EasyDevKits
+ iProduct 2 EasyDevKit
+ iSerial 3 ACBACJGAAB
+ bNumConfigurations 1
+ Configuration Descriptor:
+ bLength 9
+ bDescriptorType 2
+ wTotalLength 0x0062
+ bNumInterfaces 3
+ bConfigurationValue 1
+ iConfiguration 0
+ bmAttributes 0x80
+ (Bus Powered)
+ MaxPower 500mA
+ Interface Association:
+ bLength 8
+ bDescriptorType 11
+ bFirstInterface 0
+ bInterfaceCount 2
+ bFunctionClass 2 Communications
+ bFunctionSubClass 2 Abstract (modem)
+ bFunctionProtocol 1 AT-commands (v.25ter)
+ iFunction 0
+ Interface Descriptor:
+ bLength 9
+ bDescriptorType 4
+ bInterfaceNumber 0
+ bAlternateSetting 0
+ bNumEndpoints 1
+ bInterfaceClass 2 Communications
+ bInterfaceSubClass 2 Abstract (modem)
+ bInterfaceProtocol 1 AT-commands (v.25ter)
+ iInterface 0
+ CDC Header:
+ bcdCDC 1.10
+ CDC Call Management:
+ bmCapabilities 0x00
+ bDataInterface 1
+ CDC ACM:
+ bmCapabilities 0x02
+ line coding and serial state
+ CDC Union:
+ bMasterInterface 0
+ bSlaveInterface 1
+ Endpoint Descriptor:
+ bLength 7
+ bDescriptorType 5
+ bEndpointAddress 0x83 EP 3 IN
+ bmAttributes 3
+ Transfer Type Interrupt
+ Synch Type None
+ Usage Type Data
+ wMaxPacketSize 0x0040 1x 64 bytes
+ bInterval 1
+ Interface Descriptor:
+ bLength 9
+ bDescriptorType 4
+ bInterfaceNumber 1
+ bAlternateSetting 0
+ bNumEndpoints 2
+ bInterfaceClass 10 CDC Data
+ bInterfaceSubClass 0
+ bInterfaceProtocol 0
+ iInterface 0
+ Endpoint Descriptor:
+ bLength 7
+ bDescriptorType 5
+ bEndpointAddress 0x04 EP 4 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 0x84 EP 4 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 2
+ bAlternateSetting 0
+ bNumEndpoints 2
+ bInterfaceClass 255 Vendor Specific Class
+ bInterfaceSubClass 0
+ bInterfaceProtocol 0
+ iInterface 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
+ 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
+Device Qualifier (for other device speed):
+ bLength 10
+ bDescriptorType 6
+ bcdUSB 2.00
+ bDeviceClass 255 Vendor Specific Class
+ bDeviceSubClass 0
+ bDeviceProtocol 255
+ bMaxPacketSize0 64
+ bNumConfigurations 1
+Device Status: 0x0000
+ (Bus Powered)
diff --git a/src/flash/nand/core.c b/src/flash/nand/core.c
index c5430aeb05..a79844eb5f 100644
--- a/src/flash/nand/core.c
+++ b/src/flash/nand/core.c
@@ -310,16 +310,15 @@ int nand_probe(struct nand_device *nand)
retval = nand->controller->init(nand);
if (retval != ERROR_OK) {
switch (retval) {
- case ERROR_NAND_OPERATION_FAILED:
- LOG_DEBUG("controller initialization failed");
- return ERROR_NAND_OPERATION_FAILED;
- case ERROR_NAND_OPERATION_NOT_SUPPORTED:
- LOG_ERROR(
- "BUG: controller reported that it doesn't support default parameters");
- return ERROR_NAND_OPERATION_FAILED;
- default:
- LOG_ERROR("BUG: unknown controller initialization failure");
- return ERROR_NAND_OPERATION_FAILED;
+ case ERROR_NAND_OPERATION_FAILED:
+ LOG_DEBUG("controller initialization failed");
+ return ERROR_NAND_OPERATION_FAILED;
+ case ERROR_NAND_OPERATION_NOT_SUPPORTED:
+ LOG_ERROR("BUG: controller reported that it doesn't support default parameters");
+ return ERROR_NAND_OPERATION_FAILED;
+ default:
+ LOG_ERROR("BUG: unknown controller initialization failure");
+ return ERROR_NAND_OPERATION_FAILED;
}
}
@@ -450,18 +449,18 @@ int nand_probe(struct nand_device *nand)
/* erase size */
if (nand->device->erase_size == 0) {
switch ((id_buff[4] >> 4) & 3) {
- case 0:
- nand->erase_size = 64 << 10;
- break;
- case 1:
- nand->erase_size = 128 << 10;
- break;
- case 2:
- nand->erase_size = 256 << 10;
- break;
- case 3:
- nand->erase_size = 512 << 10;
- break;
+ case 0:
+ nand->erase_size = 64 << 10;
+ break;
+ case 1:
+ nand->erase_size = 128 << 10;
+ break;
+ case 2:
+ nand->erase_size = 256 << 10;
+ break;
+ case 3:
+ nand->erase_size = 512 << 10;
+ break;
}
} else
nand->erase_size = nand->device->erase_size;
@@ -470,19 +469,18 @@ int nand_probe(struct nand_device *nand)
retval = nand->controller->init(nand);
if (retval != ERROR_OK) {
switch (retval) {
- case ERROR_NAND_OPERATION_FAILED:
- LOG_DEBUG("controller initialization failed");
- return ERROR_NAND_OPERATION_FAILED;
- case ERROR_NAND_OPERATION_NOT_SUPPORTED:
- LOG_ERROR(
- "controller doesn't support requested parameters (buswidth: %i, address cycles: %i, page size: %i)",
+ case ERROR_NAND_OPERATION_FAILED:
+ LOG_DEBUG("controller initialization failed");
+ return ERROR_NAND_OPERATION_FAILED;
+ case ERROR_NAND_OPERATION_NOT_SUPPORTED:
+ LOG_ERROR("controller doesn't support requested parameters (buswidth: %i, address cycles: %i, page size: %i)",
nand->bus_width,
nand->address_cycles,
nand->page_size);
- return ERROR_NAND_OPERATION_FAILED;
- default:
- LOG_ERROR("BUG: unknown controller initialization failure");
- return ERROR_NAND_OPERATION_FAILED;
+ return ERROR_NAND_OPERATION_FAILED;
+ default:
+ LOG_ERROR("BUG: unknown controller initialization failure");
+ return ERROR_NAND_OPERATION_FAILED;
}
}
diff --git a/src/flash/nand/davinci.c b/src/flash/nand/davinci.c
index 17040fe172..d27b4c748c 100644
--- a/src/flash/nand/davinci.c
+++ b/src/flash/nand/davinci.c
@@ -256,17 +256,17 @@ static int davinci_write_page(struct nand_device *nand, uint32_t page,
/* If we're not given OOB, write 0xff where we don't write ECC codes. */
switch (nand->page_size) {
- case 512:
- oob_size = 16;
- break;
- case 2048:
- oob_size = 64;
- break;
- case 4096:
- oob_size = 128;
- break;
- default:
- return ERROR_NAND_OPERATION_FAILED;
+ case 512:
+ oob_size = 16;
+ break;
+ case 2048:
+ oob_size = 64;
+ break;
+ case 4096:
+ oob_size = 128;
+ break;
+ default:
+ return ERROR_NAND_OPERATION_FAILED;
}
if (!oob) {
ooballoc = malloc(oob_size);
@@ -391,15 +391,15 @@ static int davinci_write_page_ecc1(struct nand_device *nand, uint32_t page,
* for 16-bit OOB, those extra bytes are discontiguous.
*/
switch (nand->page_size) {
- case 512:
- oob_offset = 0;
- break;
- case 2048:
- oob_offset = 40;
- break;
- default:
- oob_offset = 80;
- break;
+ case 512:
+ oob_offset = 0;
+ break;
+ case 2048:
+ oob_offset = 40;
+ break;
+ default:
+ oob_offset = 80;
+ break;
}
davinci_write_pagecmd(nand, NAND_CMD_SEQIN, page);
@@ -482,15 +482,15 @@ static int davinci_write_page_ecc4(struct nand_device *nand, uint32_t page,
* the standard ECC logic can't handle.
*/
switch (nand->page_size) {
- case 512:
- l = ecc512;
- break;
- case 2048:
- l = ecc2048;
- break;
- default:
- l = ecc4096;
- break;
+ case 512:
+ l = ecc512;
+ break;
+ case 2048:
+ l = ecc2048;
+ break;
+ default:
+ l = ecc4096;
+ break;
}
davinci_write_pagecmd(nand, NAND_CMD_SEQIN, page);
@@ -741,19 +741,19 @@ NAND_DEVICE_COMMAND_HANDLER(davinci_nand_device_command)
info->read_page = nand_read_page_raw;
switch (eccmode) {
- case HWECC1:
- /* ECC_HW, 1-bit corrections, 3 bytes ECC per 512 data bytes */
- info->write_page = davinci_write_page_ecc1;
- break;
- case HWECC4:
- /* ECC_HW, 4-bit corrections, 10 bytes ECC per 512 data bytes */
- info->write_page = davinci_write_page_ecc4;
- break;
- case HWECC4_INFIX:
- /* Same 4-bit ECC HW, with problematic page/ecc layout */
- info->read_page = davinci_read_page_ecc4infix;
- info->write_page = davinci_write_page_ecc4infix;
- break;
+ case HWECC1:
+ /* ECC_HW, 1-bit corrections, 3 bytes ECC per 512 data bytes */
+ info->write_page = davinci_write_page_ecc1;
+ break;
+ case HWECC4:
+ /* ECC_HW, 4-bit corrections, 10 bytes ECC per 512 data bytes */
+ info->write_page = davinci_write_page_ecc4;
+ break;
+ case HWECC4_INFIX:
+ /* Same 4-bit ECC HW, with problematic page/ecc layout */
+ info->read_page = davinci_read_page_ecc4infix;
+ info->write_page = davinci_write_page_ecc4infix;
+ break;
}
return ERROR_OK;
diff --git a/src/flash/nand/driver.c b/src/flash/nand/driver.c
index 5d99102c85..eda033b5b7 100644
--- a/src/flash/nand/driver.c
+++ b/src/flash/nand/driver.c
@@ -10,30 +10,32 @@
#ifdef HAVE_CONFIG_H
#include
#endif
+
+#include
#include "core.h"
#include "driver.h"
static struct nand_flash_controller *nand_flash_controllers[] = {
- &nonce_nand_controller,
+ // Keep in alphabetic order the list of drivers
+ &at91sam9_nand_controller,
&davinci_nand_controller,
+ &imx31_nand_flash_controller,
&lpc3180_nand_controller,
&lpc32xx_nand_controller,
+ &mxc_nand_flash_controller,
+ &nonce_nand_controller,
+ &nuc910_nand_controller,
&orion_nand_controller,
&s3c2410_nand_controller,
&s3c2412_nand_controller,
&s3c2440_nand_controller,
&s3c2443_nand_controller,
&s3c6400_nand_controller,
- &mxc_nand_flash_controller,
- &imx31_nand_flash_controller,
- &at91sam9_nand_controller,
- &nuc910_nand_controller,
- NULL
};
struct nand_flash_controller *nand_driver_find_by_name(const char *name)
{
- for (unsigned int i = 0; nand_flash_controllers[i]; i++) {
+ for (size_t i = 0; i < ARRAY_SIZE(nand_flash_controllers); i++) {
struct nand_flash_controller *controller = nand_flash_controllers[i];
if (strcmp(name, controller->name) == 0)
return controller;
@@ -42,7 +44,7 @@ struct nand_flash_controller *nand_driver_find_by_name(const char *name)
}
int nand_driver_walk(nand_driver_walker_t f, void *x)
{
- for (unsigned int i = 0; nand_flash_controllers[i]; i++) {
+ for (size_t i = 0; i < ARRAY_SIZE(nand_flash_controllers); i++) {
int retval = (*f)(nand_flash_controllers[i], x);
if (retval != ERROR_OK)
return retval;
diff --git a/src/flash/nand/driver.h b/src/flash/nand/driver.h
index 4e84f10fbd..d26e77c75b 100644
--- a/src/flash/nand/driver.h
+++ b/src/flash/nand/driver.h
@@ -89,6 +89,7 @@ typedef int (*nand_driver_walker_t)(struct nand_flash_controller *c, void *);
*/
int nand_driver_walk(nand_driver_walker_t f, void *x);
+// Keep in alphabetic order the list of drivers
extern struct nand_flash_controller at91sam9_nand_controller;
extern struct nand_flash_controller davinci_nand_controller;
extern struct nand_flash_controller imx31_nand_flash_controller;
diff --git a/src/flash/nand/mx3.c b/src/flash/nand/mx3.c
index 86e94685b7..23c18947ba 100644
--- a/src/flash/nand/mx3.c
+++ b/src/flash/nand/mx3.c
@@ -256,23 +256,23 @@ static int imx31_command(struct nand_device *nand, uint8_t command)
}
switch (command) {
- case NAND_CMD_READOOB:
- command = NAND_CMD_READ0;
- in_sram_address = MX3_NF_SPARE_BUFFER0; /* set read point for
- * data_read() and
- * read_block_data() to
- * spare area in SRAM
- * buffer */
- break;
- case NAND_CMD_READ1:
- command = NAND_CMD_READ0;
- /*
- * offset == one half of page size
- */
- in_sram_address = MX3_NF_MAIN_BUFFER0 + (nand->page_size >> 1);
- break;
- default:
- in_sram_address = MX3_NF_MAIN_BUFFER0;
+ case NAND_CMD_READOOB:
+ command = NAND_CMD_READ0;
+ in_sram_address = MX3_NF_SPARE_BUFFER0; /* set read point for
+ * data_read() and
+ * read_block_data() to
+ * spare area in SRAM
+ * buffer */
+ break;
+ case NAND_CMD_READ1:
+ command = NAND_CMD_READ0;
+ /*
+ * offset == one half of page size
+ */
+ in_sram_address = MX3_NF_MAIN_BUFFER0 + (nand->page_size >> 1);
+ break;
+ default:
+ in_sram_address = MX3_NF_MAIN_BUFFER0;
}
target_write_u16(target, MX3_NF_FCMD, command);
@@ -291,20 +291,20 @@ static int imx31_command(struct nand_device *nand, uint8_t command)
*/
sign_of_sequental_byte_read = 0;
switch (command) {
- case NAND_CMD_READID:
- mx3_nf_info->optype = MX3_NF_DATAOUT_NANDID;
- mx3_nf_info->fin = MX3_NF_FIN_DATAOUT;
- break;
- case NAND_CMD_STATUS:
- mx3_nf_info->optype = MX3_NF_DATAOUT_NANDSTATUS;
- mx3_nf_info->fin = MX3_NF_FIN_DATAOUT;
- break;
- case NAND_CMD_READ0:
- mx3_nf_info->fin = MX3_NF_FIN_DATAOUT;
- mx3_nf_info->optype = MX3_NF_DATAOUT_PAGE;
- break;
- default:
- mx3_nf_info->optype = MX3_NF_DATAOUT_PAGE;
+ case NAND_CMD_READID:
+ mx3_nf_info->optype = MX3_NF_DATAOUT_NANDID;
+ mx3_nf_info->fin = MX3_NF_FIN_DATAOUT;
+ break;
+ case NAND_CMD_STATUS:
+ mx3_nf_info->optype = MX3_NF_DATAOUT_NANDSTATUS;
+ mx3_nf_info->fin = MX3_NF_FIN_DATAOUT;
+ break;
+ case NAND_CMD_READ0:
+ mx3_nf_info->fin = MX3_NF_FIN_DATAOUT;
+ mx3_nf_info->optype = MX3_NF_DATAOUT_PAGE;
+ break;
+ default:
+ mx3_nf_info->optype = MX3_NF_DATAOUT_PAGE;
}
return ERROR_OK;
}
@@ -647,46 +647,46 @@ static int do_data_output(struct nand_device *nand)
struct mx3_nf_controller *mx3_nf_info = nand->controller_priv;
struct target *target = nand->target;
switch (mx3_nf_info->fin) {
- case MX3_NF_FIN_DATAOUT:
- /*
- * start data output operation (set MX3_NF_BIT_OP_DONE==0)
- */
- target_write_u16 (target, MX3_NF_CFG2,
- MX3_NF_BIT_DATAOUT_TYPE(mx3_nf_info->optype));
- {
- int poll_result;
- poll_result = poll_for_complete_op(target, "data output");
- if (poll_result != ERROR_OK)
- return poll_result;
+ case MX3_NF_FIN_DATAOUT:
+ /*
+ * start data output operation (set MX3_NF_BIT_OP_DONE==0)
+ */
+ target_write_u16 (target, MX3_NF_CFG2,
+ MX3_NF_BIT_DATAOUT_TYPE(mx3_nf_info->optype));
+ {
+ int poll_result;
+ poll_result = poll_for_complete_op(target, "data output");
+ if (poll_result != ERROR_OK)
+ return poll_result;
+ }
+ mx3_nf_info->fin = MX3_NF_FIN_NONE;
+ /*
+ * ECC stuff
+ */
+ if (mx3_nf_info->optype == MX3_NF_DATAOUT_PAGE
+ && mx3_nf_info->flags.hw_ecc_enabled) {
+ uint16_t ecc_status;
+ target_read_u16 (target, MX3_NF_ECCSTATUS, &ecc_status);
+ switch (ecc_status & 0x000c) {
+ case 1 << 2:
+ LOG_DEBUG("main area read with 1 (correctable) error");
+ break;
+ case 2 << 2:
+ LOG_DEBUG("main area read with more than 1 (incorrectable) error");
+ return ERROR_NAND_OPERATION_FAILED;
}
- mx3_nf_info->fin = MX3_NF_FIN_NONE;
- /*
- * ECC stuff
- */
- if ((mx3_nf_info->optype == MX3_NF_DATAOUT_PAGE)
- && mx3_nf_info->flags.hw_ecc_enabled) {
- uint16_t ecc_status;
- target_read_u16 (target, MX3_NF_ECCSTATUS, &ecc_status);
- switch (ecc_status & 0x000c) {
- case 1 << 2:
- LOG_DEBUG("main area read with 1 (correctable) error");
- break;
- case 2 << 2:
- LOG_DEBUG("main area read with more than 1 (incorrectable) error");
- return ERROR_NAND_OPERATION_FAILED;
- }
- switch (ecc_status & 0x0003) {
- case 1:
- LOG_DEBUG("spare area read with 1 (correctable) error");
- break;
- case 2:
- LOG_DEBUG("main area read with more than 1 (incorrectable) error");
- return ERROR_NAND_OPERATION_FAILED;
- }
+ switch (ecc_status & 0x0003) {
+ case 1:
+ LOG_DEBUG("spare area read with 1 (correctable) error");
+ break;
+ case 2:
+ LOG_DEBUG("main area read with more than 1 (incorrectable) error");
+ return ERROR_NAND_OPERATION_FAILED;
}
- break;
- case MX3_NF_FIN_NONE:
- break;
+ }
+ break;
+ case MX3_NF_FIN_NONE:
+ break;
}
return ERROR_OK;
}
diff --git a/src/flash/nand/mxc.c b/src/flash/nand/mxc.c
index 845a3bb9a6..f37468f8dc 100644
--- a/src/flash/nand/mxc.c
+++ b/src/flash/nand/mxc.c
@@ -338,26 +338,26 @@ static int mxc_command(struct nand_device *nand, uint8_t command)
return validate_target_result;
switch (command) {
- case NAND_CMD_READOOB:
- command = NAND_CMD_READ0;
- /* set read point for data_read() and read_block_data() to
- * spare area in SRAM buffer
- */
- if (nfc_is_v1())
- in_sram_address = MXC_NF_V1_SPARE_BUFFER0;
- else
- in_sram_address = MXC_NF_V2_SPARE_BUFFER0;
- break;
- case NAND_CMD_READ1:
- command = NAND_CMD_READ0;
- /*
- * offset == one half of page size
- */
- in_sram_address = MXC_NF_MAIN_BUFFER0 + (nand->page_size >> 1);
- break;
- default:
- in_sram_address = MXC_NF_MAIN_BUFFER0;
- break;
+ case NAND_CMD_READOOB:
+ command = NAND_CMD_READ0;
+ /* set read point for data_read() and read_block_data() to
+ * spare area in SRAM buffer
+ */
+ if (nfc_is_v1())
+ in_sram_address = MXC_NF_V1_SPARE_BUFFER0;
+ else
+ in_sram_address = MXC_NF_V2_SPARE_BUFFER0;
+ break;
+ case NAND_CMD_READ1:
+ command = NAND_CMD_READ0;
+ /*
+ * offset == one half of page size
+ */
+ in_sram_address = MXC_NF_MAIN_BUFFER0 + (nand->page_size >> 1);
+ break;
+ default:
+ in_sram_address = MXC_NF_MAIN_BUFFER0;
+ break;
}
target_write_u16(target, MXC_NF_FCMD, command);
@@ -374,24 +374,24 @@ static int mxc_command(struct nand_device *nand, uint8_t command)
sign_of_sequental_byte_read = 0;
/* Handle special read command and adjust NF_CFG2(FDO) */
switch (command) {
- case NAND_CMD_READID:
- mxc_nf_info->optype = MXC_NF_DATAOUT_NANDID;
- mxc_nf_info->fin = MXC_NF_FIN_DATAOUT;
- break;
- case NAND_CMD_STATUS:
- mxc_nf_info->optype = MXC_NF_DATAOUT_NANDSTATUS;
- mxc_nf_info->fin = MXC_NF_FIN_DATAOUT;
- target_write_u16 (target, MXC_NF_BUFADDR, 0);
- in_sram_address = 0;
- break;
- case NAND_CMD_READ0:
- mxc_nf_info->fin = MXC_NF_FIN_DATAOUT;
- mxc_nf_info->optype = MXC_NF_DATAOUT_PAGE;
- break;
- default:
- /* Other command use the default 'One page data out' FDO */
- mxc_nf_info->optype = MXC_NF_DATAOUT_PAGE;
- break;
+ case NAND_CMD_READID:
+ mxc_nf_info->optype = MXC_NF_DATAOUT_NANDID;
+ mxc_nf_info->fin = MXC_NF_FIN_DATAOUT;
+ break;
+ case NAND_CMD_STATUS:
+ mxc_nf_info->optype = MXC_NF_DATAOUT_NANDSTATUS;
+ mxc_nf_info->fin = MXC_NF_FIN_DATAOUT;
+ target_write_u16 (target, MXC_NF_BUFADDR, 0);
+ in_sram_address = 0;
+ break;
+ case NAND_CMD_READ0:
+ mxc_nf_info->fin = MXC_NF_FIN_DATAOUT;
+ mxc_nf_info->optype = MXC_NF_DATAOUT_PAGE;
+ break;
+ default:
+ /* Other command use the default 'One page data out' FDO */
+ mxc_nf_info->optype = MXC_NF_DATAOUT_PAGE;
+ break;
}
return ERROR_OK;
}
@@ -857,20 +857,20 @@ static int ecc_status_v1(struct nand_device *nand)
target_read_u16(target, MXC_NF_ECCSTATUS, &ecc_status);
switch (ecc_status & 0x000c) {
- case 1 << 2:
- LOG_INFO("main area read with 1 (correctable) error");
- break;
- case 2 << 2:
- LOG_INFO("main area read with more than 1 (incorrectable) error");
- return ERROR_NAND_OPERATION_FAILED;
+ case 1 << 2:
+ LOG_INFO("main area read with 1 (correctable) error");
+ break;
+ case 2 << 2:
+ LOG_INFO("main area read with more than 1 (incorrectable) error");
+ return ERROR_NAND_OPERATION_FAILED;
}
switch (ecc_status & 0x0003) {
- case 1:
- LOG_INFO("spare area read with 1 (correctable) error");
- break;
- case 2:
- LOG_INFO("main area read with more than 1 (incorrectable) error");
- return ERROR_NAND_OPERATION_FAILED;
+ case 1:
+ LOG_INFO("spare area read with 1 (correctable) error");
+ break;
+ case 2:
+ LOG_INFO("main area read with more than 1 (incorrectable) error");
+ return ERROR_NAND_OPERATION_FAILED;
}
return ERROR_OK;
}
@@ -904,31 +904,31 @@ static int do_data_output(struct nand_device *nand)
struct target *target = nand->target;
int poll_result;
switch (mxc_nf_info->fin) {
- case MXC_NF_FIN_DATAOUT:
- /*
- * start data output operation (set MXC_NF_BIT_OP_DONE==0)
- */
- target_write_u16(target, MXC_NF_CFG2, MXC_NF_BIT_DATAOUT_TYPE(mxc_nf_info->optype));
- poll_result = poll_for_complete_op(nand, "data output");
- if (poll_result != ERROR_OK)
- return poll_result;
+ case MXC_NF_FIN_DATAOUT:
+ /*
+ * start data output operation (set MXC_NF_BIT_OP_DONE==0)
+ */
+ target_write_u16(target, MXC_NF_CFG2, MXC_NF_BIT_DATAOUT_TYPE(mxc_nf_info->optype));
+ poll_result = poll_for_complete_op(nand, "data output");
+ if (poll_result != ERROR_OK)
+ return poll_result;
- mxc_nf_info->fin = MXC_NF_FIN_NONE;
- /*
- * ECC stuff
- */
- if (mxc_nf_info->optype == MXC_NF_DATAOUT_PAGE && mxc_nf_info->flags.hw_ecc_enabled) {
- int ecc_status;
- if (nfc_is_v1())
- ecc_status = ecc_status_v1(nand);
- else
- ecc_status = ecc_status_v2(nand);
- if (ecc_status != ERROR_OK)
- return ecc_status;
- }
- break;
- case MXC_NF_FIN_NONE:
- break;
+ mxc_nf_info->fin = MXC_NF_FIN_NONE;
+ /*
+ * ECC stuff
+ */
+ if (mxc_nf_info->optype == MXC_NF_DATAOUT_PAGE && mxc_nf_info->flags.hw_ecc_enabled) {
+ int ecc_status;
+ if (nfc_is_v1())
+ ecc_status = ecc_status_v1(nand);
+ else
+ ecc_status = ecc_status_v2(nand);
+ if (ecc_status != ERROR_OK)
+ return ecc_status;
+ }
+ break;
+ case MXC_NF_FIN_NONE:
+ break;
}
return ERROR_OK;
}
diff --git a/src/flash/nand/tcl.c b/src/flash/nand/tcl.c
index 67a62770fb..0d6686d007 100644
--- a/src/flash/nand/tcl.c
+++ b/src/flash/nand/tcl.c
@@ -50,21 +50,22 @@ COMMAND_HANDLER(handle_nand_info_command)
int last = -1;
switch (CMD_ARGC) {
- default:
- return ERROR_COMMAND_SYNTAX_ERROR;
- case 1:
- first = 0;
- last = INT32_MAX;
- break;
- case 2:
- COMMAND_PARSE_NUMBER(int, CMD_ARGV[1], i);
- first = last = i;
- i = 0;
- break;
- case 3:
- COMMAND_PARSE_NUMBER(int, CMD_ARGV[1], first);
- COMMAND_PARSE_NUMBER(int, CMD_ARGV[2], last);
- break;
+ case 1:
+ first = 0;
+ last = INT32_MAX;
+ break;
+ case 2:
+ COMMAND_PARSE_NUMBER(int, CMD_ARGV[1], i);
+ first = i;
+ last = i;
+ i = 0;
+ break;
+ case 3:
+ COMMAND_PARSE_NUMBER(int, CMD_ARGV[1], first);
+ COMMAND_PARSE_NUMBER(int, CMD_ARGV[2], last);
+ break;
+ default:
+ return ERROR_COMMAND_SYNTAX_ERROR;
}
struct nand_device *p;
diff --git a/src/flash/nor/Makefile.am b/src/flash/nor/Makefile.am
index 7a81b282b6..f408559004 100644
--- a/src/flash/nor/Makefile.am
+++ b/src/flash/nor/Makefile.am
@@ -12,6 +12,7 @@ NOR_DRIVERS = \
%D%/aduc702x.c \
%D%/aducm360.c \
%D%/ambiqmicro.c \
+ %D%/artery.c \
%D%/at91sam4.c \
%D%/at91sam4l.c \
%D%/at91samd.c \
@@ -85,6 +86,7 @@ NOR_DRIVERS = \
%D%/xmc4xxx.c
NORHEADERS = \
+ %D%/artery.h \
%D%/core.h \
%D%/cc3220sf.h \
%D%/bluenrg-x.h \
diff --git a/src/flash/nor/ambiqmicro.c b/src/flash/nor/ambiqmicro.c
index bb893778ce..cb9fa5ed77 100644
--- a/src/flash/nor/ambiqmicro.c
+++ b/src/flash/nor/ambiqmicro.c
@@ -190,37 +190,36 @@ static int ambiqmicro_read_part_info(struct flash_bank *bank)
ambiqmicro_info->target_class = (part_num & 0xFF000000) >> 24;
switch (ambiqmicro_info->target_class) {
- case 1: /* 1 - Apollo */
- case 5: /* 5 - Apollo Bootloader */
- bank->base = bank->bank_number * 0x40000;
- ambiqmicro_info->pagesize = 2048;
- ambiqmicro_info->flshsiz =
+ case 1: /* 1 - Apollo */
+ case 5: /* 5 - Apollo Bootloader */
+ bank->base = bank->bank_number * 0x40000;
+ ambiqmicro_info->pagesize = 2048;
+ ambiqmicro_info->flshsiz =
apollo_flash_size[(part_num & 0x00F00000) >> 20];
- ambiqmicro_info->sramsiz =
+ ambiqmicro_info->sramsiz =
apollo_sram_size[(part_num & 0x000F0000) >> 16];
- ambiqmicro_info->num_pages = ambiqmicro_info->flshsiz /
- ambiqmicro_info->pagesize;
- if (ambiqmicro_info->num_pages > 128) {
- ambiqmicro_info->num_pages = 128;
- ambiqmicro_info->flshsiz = 1024 * 256;
- }
- break;
+ ambiqmicro_info->num_pages = ambiqmicro_info->flshsiz /
+ ambiqmicro_info->pagesize;
+ if (ambiqmicro_info->num_pages > 128) {
+ ambiqmicro_info->num_pages = 128;
+ ambiqmicro_info->flshsiz = 1024 * 256;
+ }
+ break;
- default:
- LOG_INFO("Unknown Class. Using Apollo-64 as default.");
+ default:
+ LOG_INFO("Unknown Class. Using Apollo-64 as default.");
- bank->base = bank->bank_number * 0x40000;
- ambiqmicro_info->pagesize = 2048;
- ambiqmicro_info->flshsiz = apollo_flash_size[1];
- ambiqmicro_info->sramsiz = apollo_sram_size[0];
- ambiqmicro_info->num_pages = ambiqmicro_info->flshsiz /
+ bank->base = bank->bank_number * 0x40000;
+ ambiqmicro_info->pagesize = 2048;
+ ambiqmicro_info->flshsiz = apollo_flash_size[1];
+ ambiqmicro_info->sramsiz = apollo_sram_size[0];
+ ambiqmicro_info->num_pages = ambiqmicro_info->flshsiz /
ambiqmicro_info->pagesize;
- if (ambiqmicro_info->num_pages > 128) {
- ambiqmicro_info->num_pages = 128;
- ambiqmicro_info->flshsiz = 1024 * 256;
- }
- break;
-
+ if (ambiqmicro_info->num_pages > 128) {
+ ambiqmicro_info->num_pages = 128;
+ ambiqmicro_info->flshsiz = 1024 * 256;
+ }
+ break;
}
if (ambiqmicro_info->target_class < ARRAY_SIZE(ambiqmicro_parts))
@@ -309,9 +308,9 @@ static int ambiqmicro_exec_command(struct target *target,
*/
target_poll(target);
alive_sleep(100);
- LOG_DEBUG("state = %d", target->state);
} else {
- LOG_ERROR("Target not halted or running %d", target->state);
+ LOG_ERROR("Target not halted or running (state is %s)",
+ target_state_name(target));
break;
}
}
diff --git a/src/flash/nor/artery.c b/src/flash/nor/artery.c
new file mode 100644
index 0000000000..797d60de51
--- /dev/null
+++ b/src/flash/nor/artery.c
@@ -0,0 +1,2608 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+/*
+ * Copyright (C) 2023 by Marc Schink
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "imp.h"
+#include
+#include
+#include
+#include
+#include
+
+#include "artery.h"
+
+// Flash timeout values in milliseconds.
+#define FLASH_MASS_ERASE_TIMEOUT 2400
+#define FLASH_ERASE_TIMEOUT 500
+#define FLASH_WRITE_TIMEOUT 5
+#define HICK_STABLE_TIMEOUT 1000
+
+/*
+ * Flash memory register assignment for the following device series:
+ * - AT32F403A / AT32F407
+ * - AT32F413
+ * - AT32F415
+ * - AT32F421
+ * - AT32F423
+ * - AT32F425
+ * - AT32WB415
+ */
+static const uint32_t flash_regs_f4xx_wb415[ARTERY_FLASH_REG_INDEX_NUM] = {
+ [ARTERY_FLASH_REG_PSR] = 0x00,
+ [ARTERY_FLASH_REG_UNLOCK] = 0x04,
+ [ARTERY_FLASH_REG_USD_UNLOCK] = 0x08,
+ [ARTERY_FLASH_REG_STS] = 0x0c,
+ [ARTERY_FLASH_REG_CTRL] = 0x10,
+ [ARTERY_FLASH_REG_ADDR] = 0x14,
+ [ARTERY_FLASH_REG_USD] = 0x1c,
+ [ARTERY_FLASH_REG_EPPS0] = 0x20,
+ // [ARTERY_FLASH_REG_EPPS1] not available.
+};
+
+// Flash memory register assignment for the AT32F435 / AT32F437 series.
+static const uint32_t flash_regs_f435_f437[ARTERY_FLASH_REG_INDEX_NUM] = {
+ [ARTERY_FLASH_REG_PSR] = 0x00,
+ [ARTERY_FLASH_REG_UNLOCK] = 0x04,
+ [ARTERY_FLASH_REG_USD_UNLOCK] = 0x08,
+ [ARTERY_FLASH_REG_STS] = 0x0c,
+ [ARTERY_FLASH_REG_CTRL] = 0x10,
+ [ARTERY_FLASH_REG_ADDR] = 0x14,
+ [ARTERY_FLASH_REG_USD] = 0x1c,
+ [ARTERY_FLASH_REG_EPPS0] = 0x20,
+ [ARTERY_FLASH_REG_EPPS1] = 0x2c,
+};
+
+/*
+ * User system data (USD) offsets for the following device series:
+ * - AT32F415
+ * - AT32F421
+ * - AT32F423
+ * - AT32F425
+ * - AT32WB415
+ */
+static const uint32_t usd_offsets_f4xx_wb415[ARTERY_USD_INDEX_NUM] = {
+ [ARTERY_USD_FAP_INDEX] = 0x00,
+ [ARTERY_USD_SSB_INDEX] = 0x02,
+ [ARTERY_USD_DATA_INDEX] = 0x04,
+ [ARTERY_USD_EPP_INDEX] = 0x08,
+ // [ARTERY_USD_EPP_EXT_INDEX] not available.
+ [ARTERY_USD_DATA_EXT_INDEX] = 0x10,
+};
+
+// User system data (USD) offsets for the AT32F403A / AT32F407 / AT32F413 series.
+static const uint32_t usd_offsets_f403a_f407_f413[ARTERY_USD_INDEX_NUM] = {
+ [ARTERY_USD_FAP_INDEX] = 0x00,
+ [ARTERY_USD_SSB_INDEX] = 0x02,
+ [ARTERY_USD_DATA_INDEX] = 0x04,
+ [ARTERY_USD_EPP_INDEX] = 0x08,
+ // [ARTERY_USD_EPP_EXT_INDEX] not available.
+ [ARTERY_USD_DATA_EXT_INDEX] = 0x14,
+};
+
+// User system data (USD) offsets for the AT32F435 / AT32F437 series.
+static const uint32_t usd_offsets_f435_f437[ARTERY_USD_INDEX_NUM] = {
+ [ARTERY_USD_FAP_INDEX] = 0x00,
+ [ARTERY_USD_SSB_INDEX] = 0x02,
+ [ARTERY_USD_DATA_INDEX] = 0x04,
+ [ARTERY_USD_EPP_INDEX] = 0x08,
+ [ARTERY_USD_EPP_EXT_INDEX] = 0x14,
+ [ARTERY_USD_DATA_EXT_INDEX] = 0x4c,
+};
+
+static const struct artery_series_info artery_series[] = {
+ [ARTERY_SERIES_F403A_F407] = {
+ .has_fap_high_level = false,
+ .has_epp_ext = false,
+ .flash_regs_base = 0x40022000,
+ .flash_regs = flash_regs_f4xx_wb415,
+ .crm_base = 0x40021000,
+ .usd_base = 0x1FFFF800,
+ .usd_offsets = usd_offsets_f403a_f407_f413,
+ },
+ [ARTERY_SERIES_F413] = {
+ .has_fap_high_level = false,
+ .has_epp_ext = false,
+ .flash_regs_base = 0x40022000,
+ .flash_regs = flash_regs_f4xx_wb415,
+ .crm_base = 0x40021000,
+ .usd_base = 0x1FFFF800,
+ .usd_offsets = usd_offsets_f403a_f407_f413,
+ },
+ [ARTERY_SERIES_F415] = {
+ .has_fap_high_level = true,
+ .has_epp_ext = false,
+ .flash_regs_base = 0x40022000,
+ .flash_regs = flash_regs_f4xx_wb415,
+ .crm_base = 0x40021000,
+ .usd_base = 0x1FFFF800,
+ .usd_offsets = usd_offsets_f4xx_wb415,
+ },
+ [ARTERY_SERIES_F421] = {
+ .has_fap_high_level = true,
+ .has_epp_ext = false,
+ .flash_regs_base = 0x40022000,
+ .flash_regs = flash_regs_f4xx_wb415,
+ .crm_base = 0x40021000,
+ .usd_base = 0x1FFFF800,
+ .usd_offsets = usd_offsets_f4xx_wb415,
+ },
+ [ARTERY_SERIES_F423] = {
+ .has_fap_high_level = true,
+ .has_epp_ext = false,
+ .flash_regs_base = 0x40023C00,
+ .flash_regs = flash_regs_f4xx_wb415,
+ .crm_base = 0x40023800,
+ .usd_base = 0x1FFFF800,
+ .usd_offsets = usd_offsets_f4xx_wb415,
+ },
+ [ARTERY_SERIES_F425] = {
+ .has_fap_high_level = true,
+ .has_epp_ext = false,
+ .flash_regs_base = 0x40022000,
+ .flash_regs = flash_regs_f4xx_wb415,
+ .crm_base = 0x40021000,
+ .usd_base = 0x1FFFF800,
+ .usd_offsets = usd_offsets_f4xx_wb415,
+ },
+ [ARTERY_SERIES_F435_F437] = {
+ .has_fap_high_level = false,
+ .has_epp_ext = true,
+ .flash_regs_base = 0x40023C00,
+ .flash_regs = flash_regs_f435_f437,
+ .crm_base = 0x40023800,
+ .usd_base = 0x1FFFC000,
+ .usd_offsets = usd_offsets_f435_f437,
+ },
+ [ARTERY_SERIES_WB415] = {
+ .has_fap_high_level = true,
+ .has_epp_ext = false,
+ .flash_regs_base = 0x40022000,
+ .flash_regs = flash_regs_f4xx_wb415,
+ .crm_base = 0x40021000,
+ .usd_base = 0x1FFFF800,
+ .usd_offsets = usd_offsets_f4xx_wb415,
+ },
+};
+
+static const struct artery_part_info artery_parts[] = {
+ {
+ .pid = 0x70050240,
+ .name = "AT32F403AVCT7",
+ .series = ARTERY_SERIES_F403A_F407,
+ .flash_size = 256,
+ .page_size = 2048,
+ .usd_size = 48,
+ .usd_data_size = 8,
+ },
+ {
+ .pid = 0x70050241,
+ .name = "AT32F403ARCT7",
+ .series = ARTERY_SERIES_F403A_F407,
+ .flash_size = 256,
+ .page_size = 2048,
+ .usd_size = 48,
+ .usd_data_size = 8,
+ },
+ {
+ .pid = 0x70050242,
+ .name = "AT32F403ACCT7",
+ .series = ARTERY_SERIES_F403A_F407,
+ .flash_size = 256,
+ .page_size = 2048,
+ .usd_size = 48,
+ .usd_data_size = 8,
+ },
+ {
+ .pid = 0x70050243,
+ .name = "AT32F403ACCU7",
+ .series = ARTERY_SERIES_F403A_F407,
+ .flash_size = 256,
+ .page_size = 2048,
+ .usd_size = 48,
+ .usd_data_size = 8,
+ },
+ {
+ .pid = 0x70050249,
+ .name = "AT32F407VCT7",
+ .series = ARTERY_SERIES_F403A_F407,
+ .flash_size = 256,
+ .page_size = 2048,
+ .usd_size = 48,
+ .usd_data_size = 8,
+ },
+ {
+ .pid = 0x7005024a,
+ .name = "AT32F407RCT7",
+ .series = ARTERY_SERIES_F403A_F407,
+ .flash_size = 256,
+ .page_size = 2048,
+ .usd_size = 48,
+ .usd_data_size = 8,
+ },
+ {
+ .pid = 0x700502cd,
+ .name = "AT32F403AVET7",
+ .series = ARTERY_SERIES_F403A_F407,
+ .flash_size = 512,
+ .page_size = 2048,
+ .usd_size = 48,
+ .usd_data_size = 8,
+ },
+ {
+ .pid = 0x700502ce,
+ .name = "AT32F403ARET7",
+ .series = ARTERY_SERIES_F403A_F407,
+ .flash_size = 512,
+ .page_size = 2048,
+ .usd_size = 48,
+ .usd_data_size = 8,
+ },
+ {
+ .pid = 0x700502cf,
+ .name = "AT32F403ACET7",
+ .series = ARTERY_SERIES_F403A_F407,
+ .flash_size = 512,
+ .page_size = 2048,
+ .usd_size = 48,
+ .usd_data_size = 8,
+ },
+ {
+ .pid = 0x700502d0,
+ .name = "AT32F403ACEU7",
+ .series = ARTERY_SERIES_F403A_F407,
+ .flash_size = 512,
+ .page_size = 2048,
+ .usd_size = 48,
+ .usd_data_size = 8,
+ },
+ {
+ .pid = 0x700502d1,
+ .name = "AT32F407VET7",
+ .series = ARTERY_SERIES_F403A_F407,
+ .flash_size = 512,
+ .page_size = 2048,
+ .usd_size = 48,
+ .usd_data_size = 8,
+ },
+ {
+ .pid = 0x700502d2,
+ .name = "AT32F407RET7",
+ .series = ARTERY_SERIES_F403A_F407,
+ .flash_size = 512,
+ .page_size = 2048,
+ .usd_size = 48,
+ .usd_data_size = 8,
+ },
+ {
+ .pid = 0x70050254,
+ .name = "AT32F407AVCT7",
+ .series = ARTERY_SERIES_F403A_F407,
+ .flash_size = 256,
+ .page_size = 2048,
+ .usd_size = 48,
+ .usd_data_size = 8,
+ },
+ {
+ .pid = 0x70030240,
+ .name = "AT32F413RCT7",
+ .series = ARTERY_SERIES_F413,
+ .flash_size = 256,
+ .page_size = 2048,
+ .usd_size = 48,
+ .usd_data_size = 8,
+ },
+ {
+ .pid = 0x700301c1,
+ .name = "AT32F413RBT7",
+ .series = ARTERY_SERIES_F413,
+ .flash_size = 128,
+ .page_size = 1024,
+ .usd_size = 48,
+ .usd_data_size = 8,
+ },
+ {
+ .pid = 0x70030242,
+ .name = "AT32F413CCT7",
+ .series = ARTERY_SERIES_F413,
+ .flash_size = 256,
+ .page_size = 2048,
+ .usd_size = 48,
+ .usd_data_size = 8,
+ },
+ {
+ .pid = 0x700301c3,
+ .name = "AT32F413CBT7",
+ .series = ARTERY_SERIES_F413,
+ .flash_size = 128,
+ .page_size = 1024,
+ .usd_size = 48,
+ .usd_data_size = 8,
+ },
+ {
+ .pid = 0x70030244,
+ .name = "AT32F413KCU7-4",
+ .series = ARTERY_SERIES_F413,
+ .flash_size = 256,
+ .page_size = 2048,
+ .usd_size = 48,
+ .usd_data_size = 8,
+ },
+ {
+ .pid = 0x700301c5,
+ .name = "AT32F413KBU7-4",
+ .series = ARTERY_SERIES_F413,
+ .flash_size = 128,
+ .page_size = 1024,
+ .usd_size = 48,
+ .usd_data_size = 8,
+ },
+ {
+ .pid = 0x70030106,
+ .name = "AT32F413C8T7",
+ .series = ARTERY_SERIES_F413,
+ .flash_size = 64,
+ .page_size = 1024,
+ .usd_size = 48,
+ .usd_data_size = 8,
+ },
+ {
+ .pid = 0x70030247,
+ .name = "AT32F413CCU7",
+ .series = ARTERY_SERIES_F413,
+ .flash_size = 256,
+ .page_size = 2048,
+ .usd_size = 48,
+ .usd_data_size = 8,
+ },
+ {
+ .pid = 0x700301ca,
+ .name = "AT32F413CBU7",
+ .series = ARTERY_SERIES_F413,
+ .flash_size = 128,
+ .page_size = 1024,
+ .usd_size = 48,
+ .usd_data_size = 8,
+ },
+ {
+ .pid = 0x70030240,
+ .name = "AT32F415RCT7",
+ .series = ARTERY_SERIES_F415,
+ .flash_size = 256,
+ .page_size = 2048,
+ .usd_size = 1024,
+ .usd_data_size = 506,
+ },
+ {
+ .pid = 0x70030241,
+ .name = "AT32F415CCT7",
+ .series = ARTERY_SERIES_F415,
+ .flash_size = 256,
+ .page_size = 2048,
+ .usd_size = 1024,
+ .usd_data_size = 506,
+ },
+ {
+ .pid = 0x70030242,
+ .name = "AT32F415KCU7-4",
+ .series = ARTERY_SERIES_F415,
+ .flash_size = 256,
+ .page_size = 2048,
+ .usd_size = 1024,
+ .usd_data_size = 506,
+ },
+ {
+ .pid = 0x70030243,
+ .name = "AT32F415RCT7-7",
+ .series = ARTERY_SERIES_F415,
+ .flash_size = 256,
+ .page_size = 2048,
+ .usd_size = 1024,
+ .usd_data_size = 506,
+ },
+ {
+ .pid = 0x700301c4,
+ .name = "AT32F415RBT7",
+ .series = ARTERY_SERIES_F415,
+ .flash_size = 128,
+ .page_size = 1024,
+ .usd_size = 1024,
+ .usd_data_size = 506,
+ },
+ {
+ .pid = 0x700301c5,
+ .name = "AT32F415CBT7",
+ .series = ARTERY_SERIES_F415,
+ .flash_size = 128,
+ .page_size = 1024,
+ .usd_size = 1024,
+ .usd_data_size = 506,
+ },
+ {
+ .pid = 0x700301c6,
+ .name = "AT32F415KBU7-4",
+ .series = ARTERY_SERIES_F415,
+ .flash_size = 128,
+ .page_size = 1024,
+ .usd_size = 1024,
+ .usd_data_size = 506,
+ },
+ {
+ .pid = 0x700301c7,
+ .name = "AT32F415RBT7-7",
+ .series = ARTERY_SERIES_F415,
+ .flash_size = 128,
+ .page_size = 1024,
+ .usd_size = 1024,
+ .usd_data_size = 506,
+ },
+ {
+ .pid = 0x70030108,
+ .name = "AT32F415R8T7",
+ .series = ARTERY_SERIES_F415,
+ .flash_size = 64,
+ .page_size = 1024,
+ .usd_size = 1024,
+ .usd_data_size = 506,
+ },
+ {
+ .pid = 0x70030109,
+ .name = "AT32F415C8T7",
+ .series = ARTERY_SERIES_F415,
+ .flash_size = 64,
+ .page_size = 1024,
+ .usd_size = 1024,
+ .usd_data_size = 506,
+ },
+ {
+ .pid = 0x7003010a,
+ .name = "AT32F415K8U7-4",
+ .series = ARTERY_SERIES_F415,
+ .flash_size = 64,
+ .page_size = 1024,
+ .usd_size = 1024,
+ .usd_data_size = 506,
+ },
+ {
+ .pid = 0x7003024c,
+ .name = "AT32F415CCU7",
+ .series = ARTERY_SERIES_F415,
+ .flash_size = 256,
+ .page_size = 2048,
+ .usd_size = 1024,
+ .usd_data_size = 506,
+ },
+ {
+ .pid = 0x700301cd,
+ .name = "AT32F415CBU7",
+ .series = ARTERY_SERIES_F415,
+ .flash_size = 128,
+ .page_size = 1024,
+ .usd_size = 1024,
+ .usd_data_size = 506,
+ },
+ {
+ .pid = 0x50020100,
+ .name = "AT32F421C8T7",
+ .series = ARTERY_SERIES_F421,
+ .flash_size = 64,
+ .page_size = 1024,
+ .usd_size = 512,
+ .usd_data_size = 250,
+ },
+ {
+ .pid = 0x50020101,
+ .name = "AT32F421K8T7",
+ .series = ARTERY_SERIES_F421,
+ .flash_size = 64,
+ .page_size = 1024,
+ .usd_size = 512,
+ .usd_data_size = 250,
+ },
+ {
+ .pid = 0x50020102,
+ .name = "AT32F421K8U7",
+ .series = ARTERY_SERIES_F421,
+ .flash_size = 64,
+ .page_size = 1024,
+ .usd_size = 512,
+ .usd_data_size = 250,
+ },
+ {
+ .pid = 0x50020103,
+ .name = "AT32F421K8U7-4",
+ .series = ARTERY_SERIES_F421,
+ .flash_size = 64,
+ .page_size = 1024,
+ .usd_size = 512,
+ .usd_data_size = 250,
+ },
+ {
+ .pid = 0x50020104,
+ .name = "AT32F421F8U7",
+ .series = ARTERY_SERIES_F421,
+ .flash_size = 64,
+ .page_size = 1024,
+ .usd_size = 512,
+ .usd_data_size = 250,
+ },
+ {
+ .pid = 0x50020105,
+ .name = "AT32F421F8P7",
+ .series = ARTERY_SERIES_F421,
+ .flash_size = 64,
+ .page_size = 1024,
+ .usd_size = 512,
+ .usd_data_size = 250,
+ },
+ {
+ .pid = 0x50020086,
+ .name = "AT32F421C6T7",
+ .series = ARTERY_SERIES_F421,
+ .flash_size = 32,
+ .page_size = 1024,
+ .usd_size = 512,
+ .usd_data_size = 250,
+ },
+ {
+ .pid = 0x50020087,
+ .name = "AT32F421K6T7",
+ .series = ARTERY_SERIES_F421,
+ .flash_size = 32,
+ .page_size = 1024,
+ .usd_size = 512,
+ .usd_data_size = 250,
+ },
+ {
+ .pid = 0x50020088,
+ .name = "AT32F421K6U7",
+ .series = ARTERY_SERIES_F421,
+ .flash_size = 32,
+ .page_size = 1024,
+ .usd_size = 512,
+ .usd_data_size = 250,
+ },
+ {
+ .pid = 0x50020089,
+ .name = "AT32F421K6U7-4",
+ .series = ARTERY_SERIES_F421,
+ .flash_size = 32,
+ .page_size = 1024,
+ .usd_size = 512,
+ .usd_data_size = 250,
+ },
+ {
+ .pid = 0x5002008a,
+ .name = "AT32F421F6U7",
+ .series = ARTERY_SERIES_F421,
+ .flash_size = 32,
+ .page_size = 1024,
+ .usd_size = 512,
+ .usd_data_size = 250,
+ },
+ {
+ .pid = 0x5002008b,
+ .name = "AT32F421F6P7",
+ .series = ARTERY_SERIES_F421,
+ .flash_size = 32,
+ .page_size = 1024,
+ .usd_size = 512,
+ .usd_data_size = 250,
+ },
+ {
+ .pid = 0x5001000c,
+ .name = "AT32F421C4T7",
+ .series = ARTERY_SERIES_F421,
+ .flash_size = 16,
+ .page_size = 1024,
+ .usd_size = 512,
+ .usd_data_size = 250,
+ },
+ {
+ .pid = 0x5001000d,
+ .name = "AT32F421K4T7",
+ .series = ARTERY_SERIES_F421,
+ .flash_size = 16,
+ .page_size = 1024,
+ .usd_size = 512,
+ .usd_data_size = 250,
+ },
+ {
+ .pid = 0x5001000e,
+ .name = "AT32F421K4U7",
+ .series = ARTERY_SERIES_F421,
+ .flash_size = 16,
+ .page_size = 1024,
+ .usd_size = 512,
+ .usd_data_size = 250,
+ },
+ {
+ .pid = 0x5001000f,
+ .name = "AT32F421K4U7-4",
+ .series = ARTERY_SERIES_F421,
+ .flash_size = 16,
+ .page_size = 1024,
+ .usd_size = 512,
+ .usd_data_size = 250,
+ },
+ {
+ .pid = 0x50010010,
+ .name = "AT32F421F4U7",
+ .series = ARTERY_SERIES_F421,
+ .flash_size = 16,
+ .page_size = 1024,
+ .usd_size = 512,
+ .usd_data_size = 250,
+ },
+ {
+ .pid = 0x50010011,
+ .name = "AT32F421F4P7",
+ .series = ARTERY_SERIES_F421,
+ .flash_size = 16,
+ .page_size = 1024,
+ .usd_size = 512,
+ .usd_data_size = 250,
+ },
+ {
+ .pid = 0x50020112,
+ .name = "AT32F421G8U7",
+ .series = ARTERY_SERIES_F421,
+ .flash_size = 64,
+ .page_size = 1024,
+ .usd_size = 512,
+ .usd_data_size = 250,
+ },
+ {
+ .pid = 0x50020093,
+ .name = "AT32F421G6U7",
+ .series = ARTERY_SERIES_F421,
+ .flash_size = 32,
+ .page_size = 1024,
+ .usd_size = 512,
+ .usd_data_size = 250,
+ },
+ {
+ .pid = 0x50010014,
+ .name = "AT32F421G4U7",
+ .series = ARTERY_SERIES_F421,
+ .flash_size = 16,
+ .page_size = 1024,
+ .usd_size = 512,
+ .usd_data_size = 250,
+ },
+ {
+ .pid = 0x700a3240,
+ .name = "AT32F423VCT7",
+ .series = ARTERY_SERIES_F423,
+ .flash_size = 256,
+ .page_size = 2048,
+ .usd_size = 512,
+ .usd_data_size = 250,
+ },
+ {
+ .pid = 0x700a21c1,
+ .name = "AT32F423VBT7",
+ .series = ARTERY_SERIES_F423,
+ .flash_size = 128,
+ .page_size = 1024,
+ .usd_size = 512,
+ .usd_data_size = 250,
+ },
+ {
+ .pid = 0x70032102,
+ .name = "AT32F423V8T7",
+ .series = ARTERY_SERIES_F423,
+ .flash_size = 64,
+ .page_size = 1024,
+ .usd_size = 512,
+ .usd_data_size = 250,
+ },
+ {
+ .pid = 0x700a3243,
+ .name = "AT32F423RCT7",
+ .series = ARTERY_SERIES_F423,
+ .flash_size = 256,
+ .page_size = 2048,
+ .usd_size = 512,
+ .usd_data_size = 250,
+ },
+ {
+ .pid = 0x700a21c4,
+ .name = "AT32F423RBT7",
+ .series = ARTERY_SERIES_F423,
+ .flash_size = 128,
+ .page_size = 1024,
+ .usd_size = 512,
+ .usd_data_size = 250,
+ },
+ {
+ .pid = 0x70032105,
+ .name = "AT32F423R8T7",
+ .series = ARTERY_SERIES_F423,
+ .flash_size = 64,
+ .page_size = 1024,
+ .usd_size = 512,
+ .usd_data_size = 250,
+ },
+ {
+ .pid = 0x700a3246,
+ .name = "AT32F423RCT7-7",
+ .series = ARTERY_SERIES_F423,
+ .flash_size = 256,
+ .page_size = 2048,
+ .usd_size = 512,
+ .usd_data_size = 250,
+ },
+ {
+ .pid = 0x700a21c7,
+ .name = "AT32F423RBT7-7",
+ .series = ARTERY_SERIES_F423,
+ .flash_size = 128,
+ .page_size = 1024,
+ .usd_size = 512,
+ .usd_data_size = 250,
+ },
+ {
+ .pid = 0x70032108,
+ .name = "AT32F423R8T7-7",
+ .series = ARTERY_SERIES_F423,
+ .flash_size = 64,
+ .page_size = 1024,
+ .usd_size = 512,
+ .usd_data_size = 250,
+ },
+ {
+ .pid = 0x700a3249,
+ .name = "AT32F423CCT7",
+ .series = ARTERY_SERIES_F423,
+ .flash_size = 256,
+ .page_size = 2048,
+ .usd_size = 512,
+ .usd_data_size = 250,
+ },
+ {
+ .pid = 0x700a21ca,
+ .name = "AT32F423CBT7",
+ .series = ARTERY_SERIES_F423,
+ .flash_size = 128,
+ .page_size = 1024,
+ .usd_size = 512,
+ .usd_data_size = 250,
+ },
+ {
+ .pid = 0x7003210b,
+ .name = "AT32F423C8T7",
+ .series = ARTERY_SERIES_F423,
+ .flash_size = 64,
+ .page_size = 1024,
+ .usd_size = 512,
+ .usd_data_size = 250,
+ },
+ {
+ .pid = 0x700a324c,
+ .name = "AT32F423CCU7",
+ .series = ARTERY_SERIES_F423,
+ .flash_size = 256,
+ .page_size = 2048,
+ .usd_size = 512,
+ .usd_data_size = 250,
+ },
+ {
+ .pid = 0x700a21cd,
+ .name = "AT32F423CBU7",
+ .series = ARTERY_SERIES_F423,
+ .flash_size = 128,
+ .page_size = 1024,
+ .usd_size = 512,
+ .usd_data_size = 250,
+ },
+ {
+ .pid = 0x7003210e,
+ .name = "AT32F423C8U7",
+ .series = ARTERY_SERIES_F423,
+ .flash_size = 64,
+ .page_size = 1024,
+ .usd_size = 512,
+ .usd_data_size = 250,
+ },
+ {
+ .pid = 0x700a3250,
+ .name = "AT32F423TCU7",
+ .series = ARTERY_SERIES_F423,
+ .flash_size = 256,
+ .page_size = 2048,
+ .usd_size = 512,
+ .usd_data_size = 250,
+ },
+ {
+ .pid = 0x700a21d1,
+ .name = "AT32F423TBU7",
+ .series = ARTERY_SERIES_F423,
+ .flash_size = 128,
+ .page_size = 1024,
+ .usd_size = 512,
+ .usd_data_size = 250,
+ },
+ {
+ .pid = 0x70032112,
+ .name = "AT32F423T8U7",
+ .series = ARTERY_SERIES_F423,
+ .flash_size = 64,
+ .page_size = 1024,
+ .usd_size = 512,
+ .usd_data_size = 250,
+ },
+ {
+ .pid = 0x700a3253,
+ .name = "AT32F423KCU7-4",
+ .series = ARTERY_SERIES_F423,
+ .flash_size = 256,
+ .page_size = 2048,
+ .usd_size = 512,
+ .usd_data_size = 250,
+ },
+ {
+ .pid = 0x700a21d4,
+ .name = "AT32F423KBU7-4",
+ .series = ARTERY_SERIES_F423,
+ .flash_size = 128,
+ .page_size = 1024,
+ .usd_size = 512,
+ .usd_data_size = 250,
+ },
+ {
+ .pid = 0x70032115,
+ .name = "AT32F423K8U7-4",
+ .series = ARTERY_SERIES_F423,
+ .flash_size = 64,
+ .page_size = 1024,
+ .usd_size = 512,
+ .usd_data_size = 250,
+ },
+ {
+ .pid = 0x50092100,
+ .name = "AT32F425R8T7",
+ .series = ARTERY_SERIES_F425,
+ .flash_size = 64,
+ .page_size = 1024,
+ .usd_size = 512,
+ .usd_data_size = 250,
+ },
+ {
+ .pid = 0x50092081,
+ .name = "AT32F425R6T7",
+ .series = ARTERY_SERIES_F425,
+ .flash_size = 32,
+ .page_size = 1024,
+ .usd_size = 512,
+ .usd_data_size = 250,
+ },
+ {
+ .pid = 0x50092103,
+ .name = "AT32F425R8T7-7",
+ .series = ARTERY_SERIES_F425,
+ .flash_size = 64,
+ .page_size = 1024,
+ .usd_size = 512,
+ .usd_data_size = 250,
+ },
+ {
+ .pid = 0x50092084,
+ .name = "AT32F425R6T7-7",
+ .series = ARTERY_SERIES_F425,
+ .flash_size = 32,
+ .page_size = 1024,
+ .usd_size = 512,
+ .usd_data_size = 250,
+ },
+ {
+ .pid = 0x50092106,
+ .name = "AT32F425C8T7",
+ .series = ARTERY_SERIES_F425,
+ .flash_size = 64,
+ .page_size = 1024,
+ .usd_size = 512,
+ .usd_data_size = 250,
+ },
+ {
+ .pid = 0x50092087,
+ .name = "AT32F425C6T7",
+ .series = ARTERY_SERIES_F425,
+ .flash_size = 32,
+ .page_size = 1024,
+ .usd_size = 512,
+ .usd_data_size = 250,
+ },
+ {
+ .pid = 0x50092109,
+ .name = "AT32F425C8U7",
+ .series = ARTERY_SERIES_F425,
+ .flash_size = 64,
+ .page_size = 1024,
+ .usd_size = 512,
+ .usd_data_size = 250,
+ },
+ {
+ .pid = 0x5009208a,
+ .name = "AT32F425C6U7",
+ .series = ARTERY_SERIES_F425,
+ .flash_size = 32,
+ .page_size = 1024,
+ .usd_size = 512,
+ .usd_data_size = 250,
+ },
+ {
+ .pid = 0x5009210c,
+ .name = "AT32F425K8T7",
+ .series = ARTERY_SERIES_F425,
+ .flash_size = 64,
+ .page_size = 1024,
+ .usd_size = 512,
+ .usd_data_size = 250,
+ },
+ {
+ .pid = 0x5009208d,
+ .name = "AT32F425K6T7",
+ .series = ARTERY_SERIES_F425,
+ .flash_size = 32,
+ .page_size = 1024,
+ .usd_size = 512,
+ .usd_data_size = 250,
+ },
+ {
+ .pid = 0x5009210f,
+ .name = "AT32F425K8U7-4",
+ .series = ARTERY_SERIES_F425,
+ .flash_size = 64,
+ .page_size = 1024,
+ .usd_size = 512,
+ .usd_data_size = 250,
+ },
+ {
+ .pid = 0x50092090,
+ .name = "AT32F425K6U7-4",
+ .series = ARTERY_SERIES_F425,
+ .flash_size = 32,
+ .page_size = 1024,
+ .usd_size = 512,
+ .usd_data_size = 250,
+ },
+ {
+ .pid = 0x50092112,
+ .name = "AT32F425F8P7",
+ .series = ARTERY_SERIES_F425,
+ .flash_size = 64,
+ .page_size = 1024,
+ .usd_size = 512,
+ .usd_data_size = 250,
+ },
+ {
+ .pid = 0x50092093,
+ .name = "AT32F425F6P7",
+ .series = ARTERY_SERIES_F425,
+ .flash_size = 32,
+ .page_size = 1024,
+ .usd_size = 512,
+ .usd_data_size = 250,
+ },
+ {
+ .pid = 0x70084598,
+ .name = "AT32F435ZDT7",
+ .series = ARTERY_SERIES_F435_F437,
+ .flash_size = 448,
+ .page_size = 4096,
+ .usd_size = 4096,
+ .usd_data_size = 2012,
+ },
+ {
+ .pid = 0x70083242,
+ .name = "AT32F435ZCT7",
+ .series = ARTERY_SERIES_F435_F437,
+ .flash_size = 256,
+ .page_size = 2048,
+ .usd_size = 512,
+ .usd_data_size = 220,
+ },
+ {
+ .pid = 0x70084599,
+ .name = "AT32F435VDT7",
+ .series = ARTERY_SERIES_F435_F437,
+ .flash_size = 448,
+ .page_size = 4096,
+ .usd_size = 4096,
+ .usd_data_size = 2012,
+ },
+ {
+ .pid = 0x70083245,
+ .name = "AT32F435VCT7",
+ .series = ARTERY_SERIES_F435_F437,
+ .flash_size = 256,
+ .page_size = 2048,
+ .usd_size = 512,
+ .usd_data_size = 220,
+ },
+ {
+ .pid = 0x7008459a,
+ .name = "AT32F435RDT7",
+ .series = ARTERY_SERIES_F435_F437,
+ .flash_size = 448,
+ .page_size = 4096,
+ .usd_size = 4096,
+ .usd_data_size = 2012,
+ },
+ {
+ .pid = 0x70083248,
+ .name = "AT32F435RCT7",
+ .series = ARTERY_SERIES_F435_F437,
+ .flash_size = 256,
+ .page_size = 2048,
+ .usd_size = 512,
+ .usd_data_size = 220,
+ },
+ {
+ .pid = 0x7008459b,
+ .name = "AT32F435CDT7",
+ .series = ARTERY_SERIES_F435_F437,
+ .flash_size = 448,
+ .page_size = 4096,
+ .usd_size = 4096,
+ .usd_data_size = 2012,
+ },
+ {
+ .pid = 0x7008324b,
+ .name = "AT32F435CCT7",
+ .series = ARTERY_SERIES_F435_F437,
+ .flash_size = 256,
+ .page_size = 2048,
+ .usd_size = 512,
+ .usd_data_size = 220,
+ },
+ {
+ .pid = 0x7008459c,
+ .name = "AT32F435CDU7",
+ .series = ARTERY_SERIES_F435_F437,
+ .flash_size = 448,
+ .page_size = 4096,
+ .usd_size = 4096,
+ .usd_data_size = 2012,
+ },
+ {
+ .pid = 0x7008324e,
+ .name = "AT32F435CCU7",
+ .series = ARTERY_SERIES_F435_F437,
+ .flash_size = 256,
+ .page_size = 2048,
+ .usd_size = 512,
+ .usd_data_size = 220,
+ },
+ {
+ .pid = 0x7008459d,
+ .name = "AT32F437ZDT7",
+ .series = ARTERY_SERIES_F435_F437,
+ .flash_size = 448,
+ .page_size = 4096,
+ .usd_size = 4096,
+ .usd_data_size = 2012,
+ },
+ {
+ .pid = 0x70083251,
+ .name = "AT32F437ZCT7",
+ .series = ARTERY_SERIES_F435_F437,
+ .flash_size = 256,
+ .page_size = 2048,
+ .usd_size = 512,
+ .usd_data_size = 220,
+ },
+ {
+ .pid = 0x7008459e,
+ .name = "AT32F437VDT7",
+ .series = ARTERY_SERIES_F435_F437,
+ .flash_size = 448,
+ .page_size = 4096,
+ .usd_size = 4096,
+ .usd_data_size = 2012,
+ },
+ {
+ .pid = 0x70083254,
+ .name = "AT32F437VCT7",
+ .series = ARTERY_SERIES_F435_F437,
+ .flash_size = 256,
+ .page_size = 2048,
+ .usd_size = 512,
+ .usd_data_size = 220,
+ },
+ {
+ .pid = 0x7008459f,
+ .name = "AT32F437RDT7",
+ .series = ARTERY_SERIES_F435_F437,
+ .flash_size = 448,
+ .page_size = 4096,
+ .usd_size = 4096,
+ .usd_data_size = 2012,
+ },
+ {
+ .pid = 0x70083257,
+ .name = "AT32F437RCT7",
+ .series = ARTERY_SERIES_F435_F437,
+ .flash_size = 256,
+ .page_size = 2048,
+ .usd_size = 512,
+ .usd_data_size = 220,
+ },
+ {
+ .pid = 0x70030250,
+ .name = "AT32WB415CCU7-7",
+ .series = ARTERY_SERIES_WB415,
+ .flash_size = 256,
+ .page_size = 2048,
+ .usd_size = 1024,
+ .usd_data_size = 506,
+ },
+};
+
+/* flash bank artery 0 0 */
+FLASH_BANK_COMMAND_HANDLER(artery_flash_bank_command)
+{
+ if (CMD_ARGC < 6)
+ return ERROR_COMMAND_SYNTAX_ERROR;
+
+ struct artery_flash_bank *artery_info = calloc(1,
+ sizeof(struct artery_flash_bank));
+
+ if (!artery_info)
+ return ERROR_FAIL;
+
+ bank->driver_priv = artery_info;
+ artery_info->probed = false;
+
+ return ERROR_OK;
+}
+
+static int artery_read_flash_register(struct flash_bank *bank,
+ enum artery_flash_reg_index reg, uint32_t *value)
+{
+ const struct artery_flash_bank *artery_info = bank->driver_priv;
+ const struct artery_part_info *part_info = artery_info->part_info;
+ const struct artery_series_info *series_info = &artery_series[part_info->series];
+ uint32_t reg_addr = series_info->flash_regs_base + series_info->flash_regs[reg];
+
+ return target_read_u32(bank->target, reg_addr, value);
+}
+
+static int artery_write_flash_register(struct flash_bank *bank,
+ enum artery_flash_reg_index reg, uint32_t value)
+{
+ const struct artery_flash_bank *artery_info = bank->driver_priv;
+ const struct artery_part_info *part_info = artery_info->part_info;
+ const struct artery_series_info *series_info = &artery_series[part_info->series];
+ uint32_t reg_addr = series_info->flash_regs_base + series_info->flash_regs[reg];
+
+ return target_write_u32(bank->target, reg_addr, value);
+}
+
+static int artery_wait_flash_busy(struct flash_bank *bank, unsigned int timeout)
+{
+ const int64_t start_time = timeval_ms();
+
+ while (true) {
+ uint32_t status;
+ int retval = artery_read_flash_register(bank, ARTERY_FLASH_REG_STS,
+ &status);
+
+ if (retval != ERROR_OK)
+ return retval;
+
+ if (!(status & FLASH_STS_OBF))
+ break;
+
+ if ((timeval_ms() - start_time) > timeout) {
+ LOG_ERROR("Timed out waiting for flash");
+ return ERROR_FAIL;
+ }
+
+ keep_alive();
+ }
+
+ return ERROR_OK;
+}
+
+static int artery_enable_hiclk(struct flash_bank *bank)
+{
+ const struct artery_flash_bank *artery_info = bank->driver_priv;
+ const struct artery_part_info *part_info = artery_info->part_info;
+ const struct artery_series_info *series_info = &artery_series[part_info->series];
+ uint32_t crm_base = series_info->crm_base;
+ struct target *target = bank->target;
+
+ uint32_t crm_ctrl;
+ int ret = target_read_u32(target, crm_base + CRM_REG_CTRL, &crm_ctrl);
+
+ if (ret != ERROR_OK)
+ return ret;
+
+ // High speed internal clock (HICK) is already enabled and ready.
+ if (crm_ctrl & CRM_CTRL_HICKSTBL)
+ return ERROR_OK;
+
+ crm_ctrl |= CRM_CTRL_HICKEN;
+ ret = target_write_u32(target, crm_base + CRM_REG_CTRL, crm_ctrl);
+
+ if (ret != ERROR_OK)
+ return ret;
+
+ const int64_t start_time = timeval_ms();
+
+ while (true) {
+ ret = target_read_u32(target, crm_base + CRM_REG_CTRL, &crm_ctrl);
+
+ if (ret != ERROR_OK)
+ return ret;
+
+ if (crm_ctrl & CRM_CTRL_HICKSTBL)
+ break;
+
+ if ((timeval_ms() - start_time) > HICK_STABLE_TIMEOUT) {
+ LOG_ERROR("Timed out waiting for flash");
+ return ERROR_FAIL;
+ }
+
+ keep_alive();
+ }
+
+ return ERROR_OK;
+}
+
+static int artery_usd_unlock(struct flash_bank *bank)
+{
+ uint32_t ctrl;
+ int retval = artery_read_flash_register(bank, ARTERY_FLASH_REG_CTRL, &ctrl);
+
+ if (retval != ERROR_OK)
+ return retval;
+
+ if (ctrl & FLASH_CTRL_USDULKS)
+ return ERROR_OK;
+
+ retval = artery_write_flash_register(bank, ARTERY_FLASH_REG_USD_UNLOCK, KEY1);
+
+ if (retval != ERROR_OK)
+ return retval;
+
+ retval = artery_write_flash_register(bank, ARTERY_FLASH_REG_USD_UNLOCK, KEY2);
+
+ if (retval != ERROR_OK)
+ return retval;
+
+ retval = artery_read_flash_register(bank, ARTERY_FLASH_REG_CTRL, &ctrl);
+
+ if (retval != ERROR_OK)
+ return retval;
+
+ if (!(ctrl & FLASH_CTRL_USDULKS)) {
+ LOG_ERROR("Failed to unlock user system data");
+ return ERROR_FAIL;
+ }
+
+ return ERROR_OK;
+}
+
+static int artery_usd_lock(struct flash_bank *bank)
+{
+ uint32_t ctrl;
+
+ int retval = artery_read_flash_register(bank, ARTERY_FLASH_REG_CTRL, &ctrl);
+
+ if (retval != ERROR_OK)
+ return retval;
+
+ if (!(ctrl & FLASH_CTRL_USDULKS))
+ return ERROR_OK;
+
+ ctrl &= ~FLASH_CTRL_USDULKS;
+ retval = artery_write_flash_register(bank, ARTERY_FLASH_REG_CTRL, ctrl);
+
+ if (retval != ERROR_OK)
+ return retval;
+
+ retval = artery_read_flash_register(bank, ARTERY_FLASH_REG_CTRL, &ctrl);
+
+ if (retval != ERROR_OK)
+ return retval;
+
+ if (ctrl & FLASH_CTRL_USDULKS) {
+ LOG_ERROR("Failed to lock user system data");
+ return ERROR_FAIL;
+ }
+
+ return ERROR_OK;
+}
+
+// Initialize the device for flash memory operations.
+static int artery_init_flash(struct flash_bank *bank)
+{
+ /*
+ * The internal high speed clock (HICK) must be enabled before any flash
+ * operation is performed.
+ */
+ int retval = artery_enable_hiclk(bank);
+
+ if (retval != ERROR_OK) {
+ LOG_ERROR("Failed to enable HICLK");
+ return retval;
+ }
+
+ uint32_t ctrl;
+ retval = artery_read_flash_register(bank, ARTERY_FLASH_REG_CTRL, &ctrl);
+
+ if (retval != ERROR_OK)
+ return retval;
+
+ if (!(ctrl & FLASH_CTRL_OPLK))
+ return ERROR_OK;
+
+ retval = artery_write_flash_register(bank, ARTERY_FLASH_REG_UNLOCK, KEY1);
+
+ if (retval != ERROR_OK)
+ return retval;
+
+ retval = artery_write_flash_register(bank, ARTERY_FLASH_REG_UNLOCK, KEY2);
+
+ if (retval != ERROR_OK)
+ return retval;
+
+ retval = artery_read_flash_register(bank, ARTERY_FLASH_REG_CTRL, &ctrl);
+
+ if (retval != ERROR_OK)
+ return retval;
+
+ if (ctrl & FLASH_CTRL_OPLK) {
+ LOG_ERROR("Failed to initialize flash memory");
+ return ERROR_FAIL;
+ }
+
+ return artery_usd_unlock(bank);
+}
+
+// Deinitialize the flash memory controller.
+static int artery_deinit_flash(struct flash_bank *bank)
+{
+ int retval = artery_usd_lock(bank);
+
+ if (retval != ERROR_OK)
+ return retval;
+
+ uint32_t ctrl;
+ retval = artery_read_flash_register(bank, ARTERY_FLASH_REG_CTRL, &ctrl);
+
+ if (retval != ERROR_OK)
+ return retval;
+
+ if (ctrl & FLASH_CTRL_OPLK)
+ return ERROR_OK;
+
+ ctrl |= FLASH_CTRL_OPLK;
+ retval = artery_write_flash_register(bank, ARTERY_FLASH_REG_CTRL, ctrl);
+
+ if (retval != ERROR_OK)
+ return retval;
+
+ retval = artery_read_flash_register(bank, ARTERY_FLASH_REG_CTRL, &ctrl);
+
+ if (retval != ERROR_OK)
+ return retval;
+
+ if (!(ctrl & FLASH_CTRL_OPLK)) {
+ LOG_ERROR("Failed to lock flash");
+ return ERROR_FAIL;
+ }
+
+ return ERROR_OK;
+}
+
+static int artery_read_protection(struct flash_bank *bank, uint64_t *protection)
+{
+ uint32_t epps0;
+ int retval = artery_read_flash_register(bank, ARTERY_FLASH_REG_EPPS0,
+ &epps0);
+
+ if (retval != ERROR_OK)
+ return retval;
+
+ const struct artery_flash_bank *artery_info = bank->driver_priv;
+ const struct artery_part_info *part_info = artery_info->part_info;
+
+ uint64_t prot = epps0;
+
+ if (artery_series[part_info->series].has_epp_ext) {
+ uint32_t epps1;
+ retval = artery_read_flash_register(bank, ARTERY_FLASH_REG_EPPS1,
+ &epps1);
+
+ if (retval != ERROR_OK)
+ return retval;
+
+ prot |= (((uint64_t)epps1) << 32);
+ }
+
+ *protection = prot;
+
+ return ERROR_OK;
+}
+
+static int artery_protect_check(struct flash_bank *bank)
+{
+ uint64_t prot;
+ int retval = artery_read_protection(bank, &prot);
+
+ if (retval != ERROR_OK) {
+ LOG_ERROR("Failed to read flash protection settings");
+ return retval;
+ }
+
+ for (unsigned int i = 0; i < bank->num_prot_blocks; i++) {
+ const bool protected = !(prot & (UINT64_C(1) << i));
+ bank->prot_blocks[i].is_protected = protected ? 1 : 0;
+ }
+
+ return ERROR_OK;
+}
+
+static int artery_erase(struct flash_bank *bank, unsigned int first,
+ unsigned int last)
+{
+ struct target *target = bank->target;
+
+ if (target->state != TARGET_HALTED) {
+ LOG_ERROR("Target not halted");
+ return ERROR_TARGET_NOT_HALTED;
+ }
+
+ int retval = artery_init_flash(bank);
+
+ if (retval != ERROR_OK) {
+ LOG_ERROR("Failed to initialize flash controller");
+ return retval;
+ }
+
+ // Clear the EPPERR bit, otherwise we may read an invalid value later on.
+ retval = artery_write_flash_register(bank, ARTERY_FLASH_REG_STS,
+ FLASH_STS_EPPERR);
+
+ if (retval != ERROR_OK) {
+ LOG_ERROR("Failed to write FLASH_STS register");
+ goto flash_deinit;
+ }
+
+ retval = artery_wait_flash_busy(bank, FLASH_WRITE_TIMEOUT);
+
+ if (retval != ERROR_OK)
+ goto flash_deinit;
+
+ for (unsigned int i = first; i <= last; i++) {
+ retval = artery_write_flash_register(bank, ARTERY_FLASH_REG_ADDR,
+ bank->base + bank->sectors[i].offset);
+
+ if (retval != ERROR_OK) {
+ LOG_ERROR("Failed to write FLASH_ADDR register");
+ goto flash_deinit;
+ }
+
+ retval = artery_write_flash_register(bank, ARTERY_FLASH_REG_CTRL,
+ FLASH_CTRL_SECERS | FLASH_CTRL_ERSTR);
+
+ if (retval != ERROR_OK) {
+ LOG_ERROR("Failed to write FLASH_CTRL register");
+ goto flash_deinit;
+ }
+
+ retval = artery_wait_flash_busy(bank, FLASH_ERASE_TIMEOUT);
+
+ if (retval != ERROR_OK)
+ goto flash_deinit;
+
+ uint32_t sts;
+ retval = artery_read_flash_register(bank, ARTERY_FLASH_REG_STS, &sts);
+
+ if (retval != ERROR_OK) {
+ LOG_ERROR("Failed to read FLASH_STS register");
+ goto flash_deinit;
+ }
+
+ if (sts & FLASH_STS_EPPERR) {
+ LOG_ERROR("Sector %u is write protected", i);
+ retval = ERROR_FLASH_PROTECTED;
+ goto flash_deinit;
+ }
+ }
+
+ int retval_deinit;
+flash_deinit:
+ retval_deinit = artery_deinit_flash(bank);
+
+ if (retval_deinit != ERROR_OK)
+ return retval_deinit;
+
+ return retval;
+}
+
+static int artery_usd_init(struct flash_bank *bank, uint8_t **buffer)
+{
+ const struct artery_flash_bank *artery_info = bank->driver_priv;
+ const struct artery_part_info *part_info = artery_info->part_info;
+ uint32_t usd_size = part_info->usd_size;
+
+ *buffer = malloc(usd_size);
+
+ if (!*buffer) {
+ LOG_ERROR("Failed to allocate USD buffer");
+ return ERROR_FAIL;
+ }
+
+ memset(*buffer, 0xff, usd_size);
+
+ return ERROR_OK;
+}
+
+static int artery_usd_read(struct flash_bank *bank, uint8_t *buffer)
+{
+ const struct artery_flash_bank *artery_info = bank->driver_priv;
+ const struct artery_part_info *part_info = artery_info->part_info;
+ const struct artery_series_info *series_info = &artery_series[part_info->series];
+
+ return target_read_buffer(bank->target, series_info->usd_base,
+ part_info->usd_size, buffer);
+}
+
+static uint8_t artery_usd_read_buffer(const uint8_t *buffer, uint32_t base,
+ uint32_t offset)
+{
+ return buffer[base + (offset * 2)];
+}
+
+static int artery_usd_load(const struct artery_part_info *part_info,
+ const uint8_t *buffer, struct artery_usd *usd)
+{
+ const uint32_t *usd_regs = artery_series[part_info->series].usd_offsets;
+
+ uint8_t fap_level = artery_usd_read_buffer(buffer,
+ usd_regs[ARTERY_USD_FAP_INDEX], 0);
+
+ switch (fap_level) {
+ case ARTERY_FAP_LEVEL_DISABLED:
+ case ARTERY_FAP_LEVEL_HIGH:
+ usd->fap_level = fap_level;
+ break;
+ default:
+ usd->fap_level = ARTERY_FAP_LEVEL_LOW;
+ }
+
+ usd->ssb = artery_usd_read_buffer(buffer, usd_regs[ARTERY_USD_SSB_INDEX], 0);
+ usd->protection = 0;
+
+ for (unsigned int i = 0; i < 4; i++) {
+ const uint8_t prot = artery_usd_read_buffer(buffer,
+ usd_regs[ARTERY_USD_EPP_INDEX], i);
+ usd->protection |= (prot << (i * 8));
+ }
+
+ if (artery_series[part_info->series].has_epp_ext) {
+ usd->protection_ext = 0;
+
+ for (unsigned int i = 0; i < 4; i++) {
+ const uint8_t prot = artery_usd_read_buffer(buffer,
+ usd_regs[ARTERY_USD_EPP_INDEX], i);
+ usd->protection_ext |= (prot << (i * 8));
+ }
+ }
+
+ // All devices have at least two bytes of user data.
+ usd->data[0] = artery_usd_read_buffer(buffer,
+ usd_regs[ARTERY_USD_DATA_INDEX], 0);
+ usd->data[1] = artery_usd_read_buffer(buffer,
+ usd_regs[ARTERY_USD_DATA_INDEX], 1);
+
+ for (unsigned int i = 0; i < part_info->usd_data_size - 2; i++) {
+ usd->data[i + 2] = artery_usd_read_buffer(buffer,
+ usd_regs[ARTERY_USD_DATA_EXT_INDEX], i);
+ }
+
+ return ERROR_OK;
+}
+
+static void artery_usd_write_buffer(uint8_t *buffer, uint32_t base,
+ uint32_t offset, uint8_t data)
+{
+ buffer[base + (offset * 2)] = data;
+ buffer[base + (offset * 2) + 1] = ~data;
+}
+
+static void artery_usd_update(const struct artery_part_info *part_info,
+ uint8_t *buffer, const struct artery_usd *usd)
+{
+ const uint32_t *usd_regs = artery_series[part_info->series].usd_offsets;
+
+ artery_usd_write_buffer(buffer, usd_regs[ARTERY_USD_FAP_INDEX], 0,
+ usd->fap_level);
+ artery_usd_write_buffer(buffer, usd_regs[ARTERY_USD_SSB_INDEX], 0,
+ usd->ssb);
+
+ for (unsigned int i = 0; i < 4; i++) {
+ const uint8_t prot = usd->protection >> (i * 8);
+ artery_usd_write_buffer(buffer, usd_regs[ARTERY_USD_EPP_INDEX], i, prot);
+ }
+
+ if (artery_series[part_info->series].has_epp_ext) {
+ for (unsigned int i = 0; i < 4; i++) {
+ const uint8_t prot = usd->protection_ext >> (i * 8);
+ artery_usd_write_buffer(buffer, usd_regs[ARTERY_USD_EPP_EXT_INDEX],
+ i, prot);
+ }
+ }
+
+ artery_usd_write_buffer(buffer, usd_regs[ARTERY_USD_DATA_INDEX], 0,
+ usd->data[0]);
+ artery_usd_write_buffer(buffer, usd_regs[ARTERY_USD_DATA_INDEX], 1,
+ usd->data[1]);
+
+ for (unsigned int i = 0; i < part_info->usd_data_size - 2; i++) {
+ artery_usd_write_buffer(buffer, usd_regs[ARTERY_USD_DATA_EXT_INDEX], i,
+ usd->data[i + 2]);
+ }
+}
+
+static int artery_usd_write(struct flash_bank *bank, const uint8_t *buffer)
+{
+ struct target *target = bank->target;
+
+ int retval = artery_wait_flash_busy(bank, FLASH_WRITE_TIMEOUT);
+
+ if (retval != ERROR_OK)
+ return retval;
+
+ // Clear the PRGMERR bit, otherwise we may read an invalid value later on.
+ retval = artery_write_flash_register(bank, ARTERY_FLASH_REG_STS,
+ FLASH_STS_PRGMERR);
+
+ if (retval != ERROR_OK) {
+ LOG_ERROR("Failed to write FLASH_STS register");
+ return retval;
+ }
+
+ // Set the USDULKS bit to avoid locking the USD area.
+ uint32_t ctrl = FLASH_CTRL_USDULKS | FLASH_CTRL_USDPRGM;
+ retval = artery_write_flash_register(bank, ARTERY_FLASH_REG_CTRL, ctrl);
+
+ if (retval != ERROR_OK) {
+ LOG_ERROR("Failed to write FLASH_CTRL register");
+ return retval;
+ }
+
+ const struct artery_flash_bank *artery_info = bank->driver_priv;
+ const struct artery_part_info *part_info = artery_info->part_info;
+
+ const target_addr_t usd_base = artery_series[part_info->series].usd_base;
+ const uint32_t usd_size = part_info->usd_size;
+
+ unsigned int bytes_written = 0;
+
+ retval = artery_wait_flash_busy(bank, FLASH_WRITE_TIMEOUT);
+
+ if (retval != ERROR_OK)
+ return retval;
+
+ while (bytes_written < usd_size) {
+ uint32_t tmp;
+ memcpy(&tmp, buffer + bytes_written, sizeof(tmp));
+
+ if (tmp != 0xffffffff) {
+ retval = target_write_u32(target, usd_base + bytes_written, tmp);
+
+ if (retval != ERROR_OK) {
+ LOG_ERROR("Failed to write user system data");
+ return retval;
+ }
+
+ retval = artery_wait_flash_busy(bank, FLASH_WRITE_TIMEOUT);
+
+ if (retval != ERROR_OK)
+ return retval;
+ }
+
+ bytes_written += 4;
+ }
+
+ uint32_t sts;
+ retval = artery_read_flash_register(bank, ARTERY_FLASH_REG_STS, &sts);
+
+ if (retval != ERROR_OK) {
+ LOG_ERROR("Failed to read FLASH_STS register");
+ return retval;
+ }
+
+ if (sts & FLASH_STS_PRGMERR) {
+ LOG_ERROR("Failed to program user system data");
+ return ERROR_FLASH_OPERATION_FAILED;
+ }
+
+ return ERROR_OK;
+}
+
+static int artery_usd_erase(struct flash_bank *bank)
+{
+ int retval = artery_wait_flash_busy(bank, FLASH_WRITE_TIMEOUT);
+
+ if (retval != ERROR_OK)
+ return retval;
+
+ // Set the USDULKS bit to avoid locking the USD area.
+ uint32_t ctrl = FLASH_CTRL_USDULKS | FLASH_CTRL_USDERS | FLASH_CTRL_ERSTR;
+ retval = artery_write_flash_register(bank, ARTERY_FLASH_REG_CTRL, ctrl);
+
+ if (retval != ERROR_OK) {
+ LOG_ERROR("Failed to write FLASH_CTRL register");
+ return retval;
+ }
+
+ retval = artery_wait_flash_busy(bank, FLASH_WRITE_TIMEOUT);
+
+ if (retval != ERROR_OK)
+ return retval;
+
+ uint32_t sts;
+ retval = artery_read_flash_register(bank, ARTERY_FLASH_REG_STS, &sts);
+
+ if (retval != ERROR_OK) {
+ LOG_ERROR("Failed to read FLASH_STS register");
+ return retval;
+ }
+
+ retval = artery_read_flash_register(bank, ARTERY_FLASH_REG_CTRL, &ctrl);
+
+ if (retval != ERROR_OK) {
+ LOG_ERROR("Failed to read FLASH_CTRL register");
+ return retval;
+ }
+
+ return ERROR_OK;
+}
+
+static int artery_get_fap(struct flash_bank *bank,
+ enum artery_fap_level *fap_level)
+{
+ uint32_t usd;
+ int retval = artery_read_flash_register(bank, ARTERY_FLASH_REG_USD,
+ &usd);
+
+ if (retval != ERROR_OK)
+ return retval;
+
+ const struct artery_flash_bank *artery_info = bank->driver_priv;
+ const struct artery_part_info *part_info = artery_info->part_info;
+ const struct artery_series_info *series_info = &artery_series[part_info->series];
+
+ const bool fap_high = series_info->has_fap_high_level && (usd & FLASH_USD_FAP_HL);
+ const bool fap_low = usd & FLASH_USD_FAP;
+
+ if (fap_high && fap_low)
+ *fap_level = ARTERY_FAP_LEVEL_HIGH;
+ else if (fap_low)
+ *fap_level = ARTERY_FAP_LEVEL_LOW;
+ else
+ *fap_level = ARTERY_FAP_LEVEL_DISABLED;
+
+ return ERROR_OK;
+}
+
+static int artery_protect(struct flash_bank *bank, int set, unsigned int first,
+ unsigned int last)
+{
+ struct target *target = bank->target;
+
+ if (target->state != TARGET_HALTED) {
+ LOG_ERROR("Target not halted");
+ return ERROR_TARGET_NOT_HALTED;
+ }
+
+ enum artery_fap_level fap_level;
+ int retval = artery_get_fap(bank, &fap_level);
+
+ if (retval != ERROR_OK) {
+ LOG_ERROR("Failed to read FAP level");
+ return retval;
+ }
+
+ if (fap_level != ARTERY_FAP_LEVEL_DISABLED) {
+ LOG_ERROR("Protection cannot be modified when FAP is active");
+ return ERROR_FAIL;
+ }
+
+ uint8_t *usd_buffer;
+ retval = artery_usd_init(bank, &usd_buffer);
+
+ if (retval != ERROR_OK)
+ return retval;
+
+ retval = artery_usd_read(bank, usd_buffer);
+
+ if (retval != ERROR_OK) {
+ LOG_ERROR("Failed to read user system data");
+ return retval;
+ }
+
+ const struct artery_flash_bank *artery_info = bank->driver_priv;
+ const struct artery_part_info *part_info = artery_info->part_info;
+
+ struct artery_usd usd;
+ retval = artery_usd_load(part_info, usd_buffer, &usd);
+
+ if (retval != ERROR_OK) {
+ LOG_ERROR("Failed to load user system data");
+ free(usd_buffer);
+ return retval;
+ }
+
+ for (unsigned int i = first; i <= MIN(31, last); i++) {
+ if (bank->prot_blocks[i].is_protected == set)
+ continue;
+
+ if (set)
+ usd.protection &= ~BIT(i);
+ else
+ usd.protection |= BIT(i);
+ }
+
+ for (unsigned int i = 32; i <= last; i++) {
+ if (bank->prot_blocks[i].is_protected == set)
+ continue;
+
+ if (set)
+ usd.protection_ext &= ~BIT(i - 32);
+ else
+ usd.protection_ext |= BIT(i - 32);
+ }
+
+ artery_usd_update(part_info, usd_buffer, &usd);
+ retval = artery_init_flash(bank);
+
+ if (retval != ERROR_OK) {
+ LOG_ERROR("Failed to initialize flash controller");
+ free(usd_buffer);
+ return retval;
+ }
+
+ retval = artery_usd_erase(bank);
+
+ if (retval != ERROR_OK) {
+ LOG_ERROR("Failed to erase user system data");
+ free(usd_buffer);
+ goto flash_deinit;
+ }
+
+ retval = artery_usd_write(bank, usd_buffer);
+
+ free(usd_buffer);
+
+ if (retval != ERROR_OK) {
+ LOG_ERROR("Failed to write user system data");
+ goto flash_deinit;
+ }
+
+ int retval_deinit;
+flash_deinit:
+ retval_deinit = artery_deinit_flash(bank);
+
+ if (retval_deinit != ERROR_OK)
+ return retval_deinit;
+
+ return retval;
+}
+
+static int artery_write_without_loader(struct flash_bank *bank,
+ const uint8_t *buffer, uint32_t offset, uint32_t count)
+{
+ struct target *target = bank->target;
+
+ int retval = artery_wait_flash_busy(bank, FLASH_WRITE_TIMEOUT);
+
+ if (retval != ERROR_OK)
+ return retval;
+
+ retval = artery_write_flash_register(bank, ARTERY_FLASH_REG_CTRL,
+ FLASH_CTRL_FPRGM);
+
+ if (retval != ERROR_OK) {
+ LOG_ERROR("failed to write ctrl register");
+ return retval;
+ }
+
+ const uint32_t block_size = 4;
+
+ uint32_t bytes_written = 0;
+ target_addr_t address = bank->base + offset;
+
+ for (uint32_t i = 0; i < count / block_size; i++) {
+ retval = target_write_memory(target, address, block_size, 1,
+ buffer + bytes_written);
+
+ if (retval != ERROR_OK)
+ return retval;
+
+ retval = artery_wait_flash_busy(bank, FLASH_WRITE_TIMEOUT);
+
+ if (retval != ERROR_OK)
+ return retval;
+
+ address += block_size;
+ bytes_written += block_size;
+ }
+
+ return ERROR_OK;
+}
+
+static int artery_write(struct flash_bank *bank, const uint8_t *buffer,
+ uint32_t offset, uint32_t count)
+{
+ struct target *target = bank->target;
+
+ if (target->state != TARGET_HALTED) {
+ LOG_ERROR("Target not halted");
+ return ERROR_TARGET_NOT_HALTED;
+ }
+
+ int retval = artery_init_flash(bank);
+ if (retval != ERROR_OK) {
+ LOG_ERROR("Failed to initialize flash controller");
+ return retval;
+ }
+
+ retval = artery_write_without_loader(bank, buffer, offset, count);
+
+ if (retval != ERROR_OK) {
+ LOG_ERROR("Failed to write flash memory");
+ goto flash_deinit;
+ }
+
+ int retval_deinit;
+flash_deinit:
+ retval_deinit = artery_deinit_flash(bank);
+
+ if (retval != ERROR_OK)
+ return retval;
+
+ return retval_deinit;
+}
+
+static int artery_probe(struct flash_bank *bank)
+{
+ struct target *target = bank->target;
+
+ if (!target_was_examined(target)) {
+ LOG_ERROR("Target not examined yet");
+ return ERROR_TARGET_NOT_EXAMINED;
+ }
+
+ const struct cortex_m_common *cortex_m = target_to_cortex_m_safe(target);
+
+ if (!cortex_m) {
+ LOG_ERROR("Target is not a Cortex-M device");
+ return ERROR_TARGET_INVALID;
+ }
+
+ struct artery_flash_bank *artery_info = bank->driver_priv;
+
+ artery_info->probed = false;
+
+ int retval = target_read_u32(target, DEBUG_IDCODE, &artery_info->idcode);
+
+ if (retval != ERROR_OK)
+ return retval;
+
+ const uint32_t pid = artery_info->idcode;
+ const bool has_fpu = cortex_m->armv7m.fp_feature != FP_NONE;
+ bool check_device_series = false;
+ enum artery_series device_series;
+
+ /*
+ * The following PIDs are used for AT32F413 and AT32F415 devices. In order
+ * to distinguish between the series, we use the presence of the FPU. Note
+ * that we do not rely on the unqiue device ID (UID) which also encodes the
+ * device series. The reason is that the UID registers are not accessible
+ * when the flash access protection (FAP) is active.
+ */
+ switch (pid) {
+ case 0x700301C5:
+ case 0x70030240:
+ case 0x70030242:
+ check_device_series = true;
+ device_series = has_fpu ? ARTERY_SERIES_F413 : ARTERY_SERIES_F415;
+ break;
+ default:
+ break;
+ }
+
+ artery_info->part_info = NULL;
+
+ for (size_t i = 0; i < ARRAY_SIZE(artery_parts); i++) {
+ if (check_device_series && artery_parts[i].series != device_series)
+ continue;
+
+ if (artery_parts[i].pid == pid) {
+ artery_info->part_info = &artery_parts[i];
+ break;
+ }
+ }
+
+ if (!artery_info->part_info) {
+ LOG_ERROR("Cannot identify target as an Artery device");
+ return ERROR_FAIL;
+ }
+
+ const struct artery_part_info *part_info = artery_info->part_info;
+
+ LOG_INFO("Device ID = 0x%08" PRIx32 " (%s)", artery_info->idcode,
+ part_info->name);
+ LOG_INFO("Flash size = %d KiB", part_info->flash_size);
+
+ free(bank->sectors);
+
+ bank->base = FLASH_BASE;
+ bank->size = part_info->flash_size * 1024;
+
+ const unsigned int num_pages = (bank->size) / part_info->page_size;
+
+ // Ensure that the flash infrastructure uses an alignment of 4 bytes.
+ bank->write_start_alignment = 4;
+ bank->write_end_alignment = 4;
+
+ bank->num_sectors = num_pages;
+ bank->sectors = malloc(sizeof(struct flash_sector) * bank->num_sectors);
+
+ if (!bank->sectors) {
+ LOG_ERROR("Failed to allocate bank sectors");
+ return ERROR_FAIL;
+ }
+
+ for (unsigned int i = 0; i < bank->num_sectors; i++) {
+ bank->sectors[i].offset = i * part_info->page_size;
+ bank->sectors[i].size = part_info->page_size;
+ bank->sectors[i].is_erased = -1;
+ bank->sectors[i].is_protected = 0;
+ }
+
+ free(bank->prot_blocks);
+
+ /*
+ * Flash erase/program protection (EPPx) registers configuration for each
+ * device series.
+ *
+ * - AT32F403A / AT32F407
+ * - AT32F413
+ *
+ * Each bit represents a sector of 4 KiB. The last bit represents the
+ * entire remaining flash memory and extension area.
+ *
+ * - AT32F415
+ * - AT32WB415
+ *
+ * Each bit represents a sector of 2 KiB. The last bit represents the
+ * entire remaining flash memory and extension area.
+ *
+ * - AT32F421
+ * - AT32F423
+ * - AT32F425
+ *
+ * Each bit represents a sector of 4 KiB. Some bits may not used
+ * depending on the flash memory size. The last bit represents only the
+ * flash memory extension area.
+ *
+ * - AT32F435 / AT32F437
+ *
+ * This device series has an additional erase/program protection (EPP)
+ * register.
+ *
+ * The first 32 bits represent a flash sector of 4 KiB per bit.
+ *
+ * The additional 32 bits represent a sector of 128 KiB each. The
+ * second last bit covers the remaining flash memory. The last bit is
+ * always reserved.
+ *
+ */
+ if (part_info->series == ARTERY_SERIES_F435_F437) {
+ // See description above.
+ const unsigned int num_prot_blocks_1 = 32;
+ const unsigned int num_prot_blocks_2 = MIN(31, DIV_ROUND_UP(part_info->flash_size - 128, 128));
+ const unsigned int num_prot_blocks = num_prot_blocks_1 + num_prot_blocks_2;
+ bank->num_prot_blocks = num_prot_blocks;
+ bank->prot_blocks = malloc(sizeof(struct flash_sector) * num_prot_blocks);
+
+ if (!bank->prot_blocks) {
+ LOG_ERROR("Failed to allocate protection blocks");
+ return ERROR_FAIL;
+ }
+
+ const uint32_t prot_block_size = 4096;
+
+ unsigned int i;
+ uint32_t block_offset = 0;
+
+ for (i = 0; i < 32; i++) {
+ bank->prot_blocks[i].offset = block_offset;
+ bank->prot_blocks[i].size = prot_block_size;
+ bank->prot_blocks[i].is_erased = -1;
+ bank->prot_blocks[i].is_protected = -1;
+
+ block_offset += prot_block_size;
+ }
+
+ const uint32_t prot_block_size_2 = 128 * 1024;
+
+ for (; i < (num_prot_blocks - 1); i++) {
+ bank->prot_blocks[i].offset = block_offset;
+ bank->prot_blocks[i].size = prot_block_size_2;
+ bank->prot_blocks[i].is_erased = -1;
+ bank->prot_blocks[i].is_protected = -1;
+
+ block_offset += prot_block_size_2;
+ }
+
+ bank->prot_blocks[i].offset = block_offset;
+ bank->prot_blocks[i].size = bank->size - block_offset;
+ bank->prot_blocks[i].is_erased = -1;
+ bank->prot_blocks[i].is_protected = -1;
+ } else {
+ uint32_t prot_block_size;
+
+ switch (part_info->series) {
+ case ARTERY_SERIES_F403A_F407:
+ case ARTERY_SERIES_F413:
+ case ARTERY_SERIES_F421:
+ case ARTERY_SERIES_F423:
+ case ARTERY_SERIES_F425:
+ prot_block_size = 4096;
+ break;
+ case ARTERY_SERIES_F415:
+ case ARTERY_SERIES_WB415:
+ prot_block_size = 2048;
+ break;
+ default:
+ LOG_ERROR("Unknown Artery device series");
+ return ERROR_FAIL;
+ }
+
+ const unsigned int num_prot_blocks = MIN(bank->size / prot_block_size, 32);
+ bank->num_prot_blocks = num_prot_blocks;
+ bank->prot_blocks = malloc(sizeof(struct flash_sector) * num_prot_blocks);
+
+ if (!bank->prot_blocks) {
+ LOG_ERROR("Failed to allocate protection blocks");
+ return ERROR_FAIL;
+ }
+
+ unsigned int i;
+
+ for (i = 0; i < (num_prot_blocks - 1); i++) {
+ bank->prot_blocks[i].offset = i * prot_block_size;
+ bank->prot_blocks[i].size = prot_block_size;
+ bank->prot_blocks[i].is_erased = -1;
+ bank->prot_blocks[i].is_protected = -1;
+ }
+
+ bank->prot_blocks[i].offset = i * prot_block_size;
+ bank->prot_blocks[i].size = (bank->size - (i * prot_block_size));
+ bank->prot_blocks[i].is_erased = -1;
+ bank->prot_blocks[i].is_protected = -1;
+ }
+
+ artery_info->probed = true;
+
+ return ERROR_OK;
+}
+
+static int artery_auto_probe(struct flash_bank *bank)
+{
+ const struct artery_flash_bank *artery_info = bank->driver_priv;
+
+ if (artery_info->probed)
+ return ERROR_OK;
+
+ return artery_probe(bank);
+}
+
+static int artery_info(struct flash_bank *bank, struct command_invocation *cmd)
+{
+ const struct artery_flash_bank *artery_info = bank->driver_priv;
+ const struct artery_part_info *part_info = artery_info->part_info;
+
+ if (!part_info) {
+ command_print_sameline(cmd, "Cannot identify target device");
+ return ERROR_OK;
+ }
+
+ command_print_sameline(cmd, "%s - %u KiB flash", part_info->name,
+ part_info->flash_size);
+
+ return ERROR_OK;
+}
+
+static int artery_mass_erase(struct flash_bank *bank)
+{
+ int retval = artery_init_flash(bank);
+
+ if (retval != ERROR_OK) {
+ LOG_ERROR("Failed to initialize flash controller");
+ return retval;
+ }
+
+ retval = artery_wait_flash_busy(bank, FLASH_WRITE_TIMEOUT);
+
+ if (retval != ERROR_OK)
+ goto flash_deinit;
+
+ // Clear the EPPERR bit, otherwise we may read an invalid value later on.
+ retval = artery_write_flash_register(bank, ARTERY_FLASH_REG_STS,
+ FLASH_STS_EPPERR);
+
+ if (retval != ERROR_OK) {
+ LOG_ERROR("Failed to write FLASH_CTRL register");
+ goto flash_deinit;
+ }
+
+ uint32_t ctrl = FLASH_CTRL_BANKERS | FLASH_CTRL_ERSTR;
+ retval = artery_write_flash_register(bank, ARTERY_FLASH_REG_CTRL, ctrl);
+
+ if (retval != ERROR_OK) {
+ LOG_ERROR("Failed to write FLASH_CTRL register");
+ goto flash_deinit;
+ }
+
+ retval = artery_wait_flash_busy(bank, FLASH_MASS_ERASE_TIMEOUT);
+
+ if (retval != ERROR_OK)
+ goto flash_deinit;
+
+ uint32_t sts;
+ retval = artery_read_flash_register(bank, ARTERY_FLASH_REG_STS, &sts);
+
+ if (retval != ERROR_OK) {
+ LOG_ERROR("Failed to read FLASH_STS register");
+ goto flash_deinit;
+ }
+
+ if (sts & FLASH_STS_EPPERR) {
+ LOG_ERROR("Mass erase operation failed");
+ goto flash_deinit;
+ }
+
+ int retval_deinit;
+flash_deinit:
+ retval_deinit = artery_deinit_flash(bank);
+
+ if (retval != ERROR_OK)
+ return retval;
+
+ return retval_deinit;
+}
+
+COMMAND_HANDLER(artery_handle_fap_enable_command)
+{
+ if (CMD_ARGC != 1)
+ return ERROR_COMMAND_SYNTAX_ERROR;
+
+ struct flash_bank *bank;
+ int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
+
+ if (retval != ERROR_OK)
+ return retval;
+
+ enum artery_fap_level fap_level;
+ retval = artery_get_fap(bank, &fap_level);
+
+ if (retval != ERROR_OK) {
+ command_print(CMD, "failed to read FAP state");
+ return retval;
+ }
+
+ if (fap_level != ARTERY_FAP_LEVEL_DISABLED) {
+ command_print(CMD, "flash access protection is already enabled");
+ return ERROR_FAIL;
+ }
+
+ uint8_t *usd_buffer;
+ retval = artery_usd_init(bank, &usd_buffer);
+
+ if (retval != ERROR_OK)
+ return retval;
+
+ retval = artery_usd_read(bank, usd_buffer);
+
+ if (retval != ERROR_OK) {
+ command_print(CMD, "failed to read user system data");
+ return retval;
+ }
+
+ const struct artery_flash_bank *artery_info = bank->driver_priv;
+ const struct artery_part_info *part_info = artery_info->part_info;
+
+ struct artery_usd usd;
+ retval = artery_usd_load(part_info, usd_buffer, &usd);
+
+ if (retval != ERROR_OK) {
+ command_print(CMD, "failed to load user system data");
+ return retval;
+ }
+
+ usd.fap_level = ARTERY_FAP_LEVEL_LOW;
+ artery_usd_update(part_info, usd_buffer, &usd);
+
+ retval = artery_init_flash(bank);
+ if (retval != ERROR_OK) {
+ LOG_ERROR("Failed to initialize flash controller");
+ goto flash_deinit;
+ }
+
+ retval = artery_usd_erase(bank);
+
+ if (retval != ERROR_OK) {
+ free(usd_buffer);
+ command_print(CMD, "failed to erase user system data");
+ goto flash_deinit;
+ }
+
+ retval = artery_usd_write(bank, usd_buffer);
+ free(usd_buffer);
+
+ if (retval != ERROR_OK) {
+ command_print(CMD, "failed to write user system data");
+ goto flash_deinit;
+ }
+
+ int retval_deinit;
+flash_deinit:
+ retval_deinit = artery_deinit_flash(bank);
+
+ if (retval_deinit != ERROR_OK)
+ return retval_deinit;
+
+ return retval;
+}
+
+/*
+ * We use a dedicated operation to perform the FAP unlock operation that only
+ * writes the corresponding FAP byte(s) instead of the entire user system
+ * data (USD) area. The reason is that directly after the FAP byte(s) are
+ * written, a device reset is performed and all other writes to the USD area
+ * would fail and generate errors.
+*/
+static int artery_disable_fap(struct flash_bank *bank)
+{
+ int retval = artery_init_flash(bank);
+
+ if (retval != ERROR_OK) {
+ LOG_ERROR("Failed to initialize flash controller");
+ return retval;
+ }
+
+ retval = artery_usd_erase(bank);
+
+ if (retval != ERROR_OK) {
+ LOG_ERROR("Failed to erase user system data");
+ goto flash_deinit;
+ }
+
+ retval = artery_wait_flash_busy(bank, FLASH_WRITE_TIMEOUT);
+
+ if (retval != ERROR_OK)
+ goto flash_deinit;
+
+ // Clear the PRGMERR bit, otherwise we may read an invalid value later on.
+ retval = artery_write_flash_register(bank, ARTERY_FLASH_REG_STS,
+ FLASH_STS_PRGMERR);
+
+ if (retval != ERROR_OK) {
+ LOG_ERROR("Failed to write FLASH_STS register");
+ goto flash_deinit;
+ }
+
+ // Set the USDULKS bit to avoid locking the USD area.
+ uint32_t ctrl = FLASH_CTRL_USDULKS | FLASH_CTRL_USDPRGM;
+ retval = artery_write_flash_register(bank, ARTERY_FLASH_REG_CTRL, ctrl);
+
+ if (retval != ERROR_OK) {
+ LOG_ERROR("Failed to write FLASH_CTRL register");
+ goto flash_deinit;
+ }
+
+ retval = artery_wait_flash_busy(bank, FLASH_WRITE_TIMEOUT);
+
+ if (retval != ERROR_OK)
+ goto flash_deinit;
+
+ uint16_t buffer;
+
+ const struct artery_flash_bank *artery_info = bank->driver_priv;
+ const struct artery_part_info *part_info = artery_info->part_info;
+ const uint32_t *usd_regs = artery_series[part_info->series].usd_offsets;
+
+ artery_usd_write_buffer((uint8_t *)&buffer, usd_regs[ARTERY_USD_FAP_INDEX], 0,
+ ARTERY_FAP_LEVEL_DISABLED);
+
+ const target_addr_t usd_base = artery_series[part_info->series].usd_base;
+ retval = target_write_u16(bank->target, usd_base, buffer);
+
+ if (retval != ERROR_OK) {
+ LOG_ERROR("Failed to write FAP level");
+ goto flash_deinit;
+ }
+
+ /*
+ * Note that we do not need to deinitialize the flash memory because the
+ * device performed a reset anyway.
+ */
+
+ return ERROR_OK;
+
+ int retval_deinit;
+flash_deinit:
+ retval_deinit = artery_deinit_flash(bank);
+
+ if (retval_deinit != ERROR_OK)
+ return retval_deinit;
+
+ return retval;
+}
+
+COMMAND_HANDLER(artery_handle_fap_disable_command)
+{
+ if (CMD_ARGC != 1)
+ return ERROR_COMMAND_SYNTAX_ERROR;
+
+ struct flash_bank *bank;
+ int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
+
+ if (retval != ERROR_OK)
+ return retval;
+
+ enum artery_fap_level fap_level;
+ retval = artery_get_fap(bank, &fap_level);
+
+ if (retval != ERROR_OK) {
+ command_print(CMD, "failed to read FAP state");
+ return retval;
+ }
+
+ if (fap_level == ARTERY_FAP_LEVEL_DISABLED) {
+ command_print(CMD, "flash access protection is not enabled");
+ return ERROR_FAIL;
+ }
+
+ retval = artery_disable_fap(bank);
+
+ if (retval != ERROR_OK) {
+ command_print(CMD, "failed to disable flash access protection");
+ return retval;
+ }
+
+ return ERROR_OK;
+}
+
+COMMAND_HANDLER(artery_handle_fap_state_command)
+{
+ if (CMD_ARGC != 1)
+ return ERROR_COMMAND_SYNTAX_ERROR;
+
+ struct flash_bank *bank;
+ int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
+
+ if (retval != ERROR_OK)
+ return retval;
+
+ enum artery_fap_level fap_level;
+ retval = artery_get_fap(bank, &fap_level);
+
+ if (retval != ERROR_OK) {
+ command_print(CMD, "failed to read FAP level");
+ return retval;
+ }
+
+ const bool fap_enabled = fap_level != ARTERY_FAP_LEVEL_DISABLED;
+ command_print(CMD, "%u", fap_enabled);
+
+ return ERROR_OK;
+}
+
+COMMAND_HANDLER(artery_handle_mass_erase_command)
+{
+ if (CMD_ARGC != 1)
+ return ERROR_COMMAND_SYNTAX_ERROR;
+
+ struct flash_bank *bank;
+ int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
+
+ if (retval != ERROR_OK)
+ return retval;
+
+ retval = artery_mass_erase(bank);
+
+ if (retval != ERROR_OK) {
+ command_print(CMD, "Mass erase failed");
+ return retval;
+ }
+
+ return ERROR_OK;
+}
+
+static const struct command_registration artery_fap_command_handlers[] = {
+ {
+ .name = "enable",
+ .handler = artery_handle_fap_enable_command,
+ .mode = COMMAND_EXEC,
+ .usage = "",
+ .help = "Enable flash access protection (FAP)",
+ },
+ {
+ .name = "disable",
+ .handler = artery_handle_fap_disable_command,
+ .mode = COMMAND_EXEC,
+ .usage = "",
+ .help = "Disable flash access protection (FAP)",
+ },
+ {
+ .name = "state",
+ .handler = artery_handle_fap_state_command,
+ .mode = COMMAND_EXEC,
+ .usage = "",
+ .help = "Get the flash access protection (FAP) state",
+ },
+
+ COMMAND_REGISTRATION_DONE,
+};
+
+static const struct command_registration artery_exec_command_handlers[] = {
+ {
+ .name = "fap",
+ .mode = COMMAND_ANY,
+ .help = "flash access protection (FAP) command group",
+ .usage = "",
+ .chain = artery_fap_command_handlers,
+ },
+ {
+ .name = "mass_erase",
+ .handler = artery_handle_mass_erase_command,
+ .mode = COMMAND_EXEC,
+ .usage = "",
+ .help = "Erase entire flash memory",
+ },
+ COMMAND_REGISTRATION_DONE,
+};
+
+static const struct command_registration artery_command_handlers[] = {
+ {
+ .name = "artery",
+ .mode = COMMAND_ANY,
+ .help = "artery flash command group",
+ .usage = "",
+ .chain = artery_exec_command_handlers,
+ },
+ COMMAND_REGISTRATION_DONE,
+};
+
+const struct flash_driver artery_flash = {
+ .name = "artery",
+ .commands = artery_command_handlers,
+ .flash_bank_command = artery_flash_bank_command,
+ .erase = artery_erase,
+ .protect = artery_protect,
+ .write = artery_write,
+ .read = default_flash_read,
+ .probe = artery_probe,
+ .auto_probe = artery_auto_probe,
+ .erase_check = default_flash_blank_check,
+ .protect_check = artery_protect_check,
+ .info = artery_info,
+ .free_driver_priv = default_flash_free_driver_priv,
+};
diff --git a/src/flash/nor/artery.h b/src/flash/nor/artery.h
new file mode 100644
index 0000000000..dcfa70a6e3
--- /dev/null
+++ b/src/flash/nor/artery.h
@@ -0,0 +1,128 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
+/*
+ * Copyright (C) 2023 by Marc Schink
+ */
+
+#ifndef OPENOCD_FLASH_NOR_ARTERY
+#define OPENOCD_FLASH_NOR_ARTERY
+
+#define DEBUG_IDCODE 0xE0042000
+
+#define FLASH_BASE 0x08000000
+
+enum artery_series {
+ ARTERY_SERIES_F403A_F407 = 0,
+ ARTERY_SERIES_F413,
+ ARTERY_SERIES_F415,
+ ARTERY_SERIES_F421,
+ ARTERY_SERIES_F423,
+ ARTERY_SERIES_F425,
+ ARTERY_SERIES_F435_F437,
+ ARTERY_SERIES_WB415,
+};
+
+enum artery_flash_reg_index {
+ ARTERY_FLASH_REG_PSR = 0,
+ ARTERY_FLASH_REG_UNLOCK,
+ ARTERY_FLASH_REG_USD_UNLOCK,
+ ARTERY_FLASH_REG_STS,
+ ARTERY_FLASH_REG_CTRL,
+ ARTERY_FLASH_REG_ADDR,
+ ARTERY_FLASH_REG_USD,
+ ARTERY_FLASH_REG_EPPS0,
+ ARTERY_FLASH_REG_EPPS1,
+ ARTERY_FLASH_REG_INDEX_NUM,
+};
+
+enum artery_usd_reg_index {
+ ARTERY_USD_FAP_INDEX = 0,
+ ARTERY_USD_SSB_INDEX,
+ ARTERY_USD_DATA_INDEX,
+ ARTERY_USD_EPP_INDEX,
+ ARTERY_USD_EPP_EXT_INDEX,
+ ARTERY_USD_DATA_EXT_INDEX,
+ ARTERY_USD_INDEX_NUM,
+};
+
+enum artery_fap_level {
+ ARTERY_FAP_LEVEL_DISABLED = 0xa5,
+ ARTERY_FAP_LEVEL_LOW = 0xff,
+ ARTERY_FAP_LEVEL_HIGH = 0xcc,
+};
+
+struct artery_part_info {
+ uint32_t pid;
+ const char *name;
+ enum artery_series series;
+ // Flash size in bytes.
+ uint32_t flash_size;
+ // Page / sector size in bytes.
+ uint32_t page_size;
+ // User system data (USD) area size including the inverse bytes.
+ uint32_t usd_size;
+ // User data area (part of the USD) size excluding the inverse bytes.
+ uint32_t usd_data_size;
+};
+
+struct artery_flash_bank {
+ bool probed;
+ uint32_t idcode;
+ const struct artery_part_info *part_info;
+};
+
+struct artery_series_info {
+ bool has_fap_high_level;
+ bool has_epp_ext;
+ uint32_t flash_regs_base;
+ const uint32_t *flash_regs;
+ uint32_t crm_base;
+ uint32_t usd_base;
+ const uint32_t *usd_offsets;
+};
+
+#define ARTERY_USD_DATA_MAX_SIZE 2012
+
+struct artery_usd {
+ enum artery_fap_level fap_level;
+ uint8_t ssb;
+ uint32_t protection;
+ uint32_t protection_ext;
+ uint8_t data[ARTERY_USD_DATA_MAX_SIZE];
+};
+
+#define CRM_REG_CTRL 0x000
+
+/* CRM_CTRL register bits. */
+#define CRM_CTRL_HICKSTBL BIT(0)
+#define CRM_CTRL_HICKEN BIT(1)
+
+/* FLASH_CTRL register bits. */
+#define FLASH_CTRL_USDULKS BIT(9)
+#define FLASH_CTRL_OPLK BIT(7)
+#define FLASH_CTRL_ERSTR BIT(6)
+#define FLASH_CTRL_USDERS BIT(5)
+#define FLASH_CTRL_USDPRGM BIT(4)
+#define FLASH_CTRL_BANKERS BIT(2)
+#define FLASH_CTRL_SECERS BIT(1)
+#define FLASH_CTRL_FPRGM BIT(0)
+
+/* FLASH_STS register bits. */
+#define FLASH_STS_OBF BIT(0)
+#define FLASH_STS_PRGMERR BIT(2)
+#define FLASH_STS_EPPERR BIT(4)
+#define FLASH_STS_ODF BIT(5)
+
+/* FLASH_USD register bits. */
+#define FLASH_USD_FAP BIT(1)
+#define FLASH_USD_FAP_HL BIT(26)
+
+#define FLASH_USD_SSB_OFFSET 2
+#define FLASH_USD_USER_D0_OFFSET 10
+#define FLASH_USD_USER_D1_OFFSET 18
+
+/* Flash and USD unlock keys. */
+#define KEY1 0x45670123
+#define KEY2 0xCDEF89AB
+
+#endif /* OPENOCD_FLASH_NOR_ARTERY */
diff --git a/src/flash/nor/at91sam3.c b/src/flash/nor/at91sam3.c
index b86a18da75..5f551681d5 100644
--- a/src/flash/nor/at91sam3.c
+++ b/src/flash/nor/at91sam3.c
@@ -2040,40 +2040,39 @@ static int efc_start_command(struct sam3_bank_private *private,
/* Check command & argument */
switch (command) {
-
- case AT91C_EFC_FCMD_WP:
- case AT91C_EFC_FCMD_WPL:
- case AT91C_EFC_FCMD_EWP:
- case AT91C_EFC_FCMD_EWPL:
- /* case AT91C_EFC_FCMD_EPL: */
- /* case AT91C_EFC_FCMD_EPA: */
- case AT91C_EFC_FCMD_SLB:
- case AT91C_EFC_FCMD_CLB:
- n = (private->size_bytes / private->page_size);
- if (argument >= n)
- LOG_ERROR("*BUG*: Embedded flash has only %" PRIu32 " pages", n);
- break;
-
- case AT91C_EFC_FCMD_SFB:
- case AT91C_EFC_FCMD_CFB:
- if (argument >= private->chip->details.n_gpnvms) {
- LOG_ERROR("*BUG*: Embedded flash has only %d GPNVMs",
- private->chip->details.n_gpnvms);
- }
- break;
-
- case AT91C_EFC_FCMD_GETD:
- case AT91C_EFC_FCMD_EA:
- case AT91C_EFC_FCMD_GLB:
- case AT91C_EFC_FCMD_GFB:
- case AT91C_EFC_FCMD_STUI:
- case AT91C_EFC_FCMD_SPUI:
- if (argument != 0)
- LOG_ERROR("Argument is meaningless for cmd: %d", command);
- break;
- default:
- LOG_ERROR("Unknown command %d", command);
- break;
+ case AT91C_EFC_FCMD_WP:
+ case AT91C_EFC_FCMD_WPL:
+ case AT91C_EFC_FCMD_EWP:
+ case AT91C_EFC_FCMD_EWPL:
+ /* case AT91C_EFC_FCMD_EPL: */
+ /* case AT91C_EFC_FCMD_EPA: */
+ case AT91C_EFC_FCMD_SLB:
+ case AT91C_EFC_FCMD_CLB:
+ n = (private->size_bytes / private->page_size);
+ if (argument >= n)
+ LOG_ERROR("*BUG*: Embedded flash has only %" PRIu32 " pages", n);
+ break;
+
+ case AT91C_EFC_FCMD_SFB:
+ case AT91C_EFC_FCMD_CFB:
+ if (argument >= private->chip->details.n_gpnvms) {
+ LOG_ERROR("*BUG*: Embedded flash has only %d GPNVMs",
+ private->chip->details.n_gpnvms);
+ }
+ break;
+
+ case AT91C_EFC_FCMD_GETD:
+ case AT91C_EFC_FCMD_EA:
+ case AT91C_EFC_FCMD_GLB:
+ case AT91C_EFC_FCMD_GFB:
+ case AT91C_EFC_FCMD_STUI:
+ case AT91C_EFC_FCMD_SPUI:
+ if (argument != 0)
+ LOG_ERROR("Argument is meaningless for cmd: %d", command);
+ break;
+ default:
+ LOG_ERROR("Unknown command %d", command);
+ break;
}
if (command == AT91C_EFC_FCMD_SPUI) {
@@ -2571,18 +2570,18 @@ static void sam3_explain_ckgr_mor(struct sam3_chip *chip)
chip->cfg.rc_freq = 0;
if (rcen) {
switch (v) {
- default:
- chip->cfg.rc_freq = 0;
- break;
- case 0:
- chip->cfg.rc_freq = 4 * 1000 * 1000;
- break;
- case 1:
- chip->cfg.rc_freq = 8 * 1000 * 1000;
- break;
- case 2:
- chip->cfg.rc_freq = 12 * 1000 * 1000;
- break;
+ case 0:
+ chip->cfg.rc_freq = 4 * 1000 * 1000;
+ break;
+ case 1:
+ chip->cfg.rc_freq = 8 * 1000 * 1000;
+ break;
+ case 2:
+ chip->cfg.rc_freq = 12 * 1000 * 1000;
+ break;
+ default:
+ chip->cfg.rc_freq = 0;
+ break;
}
}
@@ -2683,30 +2682,30 @@ static void sam3_explain_mckr(struct sam3_chip *chip)
css = sam3_reg_fieldname(chip, "CSS", chip->cfg.PMC_MCKR, 0, 2);
switch (css & 3) {
- case 0:
- fin = chip->cfg.slow_freq;
- cp = "slowclk";
- break;
- case 1:
- fin = chip->cfg.mainosc_freq;
- cp = "mainosc";
- break;
- case 2:
- fin = chip->cfg.plla_freq;
- cp = "plla";
- break;
- case 3:
- if (chip->cfg.CKGR_UCKR & (1 << 16)) {
- fin = 480 * 1000 * 1000;
- cp = "upll";
- } else {
- fin = 0;
- cp = "upll (*ERROR* UPLL is disabled)";
- }
- break;
- default:
- assert(0);
- break;
+ case 0:
+ fin = chip->cfg.slow_freq;
+ cp = "slowclk";
+ break;
+ case 1:
+ fin = chip->cfg.mainosc_freq;
+ cp = "mainosc";
+ break;
+ case 2:
+ fin = chip->cfg.plla_freq;
+ cp = "plla";
+ break;
+ case 3:
+ if (chip->cfg.CKGR_UCKR & (1 << 16)) {
+ fin = 480 * 1000 * 1000;
+ cp = "upll";
+ } else {
+ fin = 0;
+ cp = "upll (*ERROR* UPLL is disabled)";
+ }
+ break;
+ default:
+ assert(0);
+ break;
}
LOG_USER("%s (%3.03f Mhz)",
@@ -2714,41 +2713,41 @@ static void sam3_explain_mckr(struct sam3_chip *chip)
_tomhz(fin));
pres = sam3_reg_fieldname(chip, "PRES", chip->cfg.PMC_MCKR, 4, 3);
switch (pres & 0x07) {
- case 0:
- pdiv = 1;
- cp = "selected clock";
- break;
- case 1:
- pdiv = 2;
- cp = "clock/2";
- break;
- case 2:
- pdiv = 4;
- cp = "clock/4";
- break;
- case 3:
- pdiv = 8;
- cp = "clock/8";
- break;
- case 4:
- pdiv = 16;
- cp = "clock/16";
- break;
- case 5:
- pdiv = 32;
- cp = "clock/32";
- break;
- case 6:
- pdiv = 64;
- cp = "clock/64";
- break;
- case 7:
- pdiv = 6;
- cp = "clock/6";
- break;
- default:
- assert(0);
- break;
+ case 0:
+ pdiv = 1;
+ cp = "selected clock";
+ break;
+ case 1:
+ pdiv = 2;
+ cp = "clock/2";
+ break;
+ case 2:
+ pdiv = 4;
+ cp = "clock/4";
+ break;
+ case 3:
+ pdiv = 8;
+ cp = "clock/8";
+ break;
+ case 4:
+ pdiv = 16;
+ cp = "clock/16";
+ break;
+ case 5:
+ pdiv = 32;
+ cp = "clock/32";
+ break;
+ case 6:
+ pdiv = 64;
+ cp = "clock/64";
+ break;
+ case 7:
+ pdiv = 6;
+ cp = "clock/6";
+ break;
+ default:
+ assert(0);
+ break;
}
LOG_USER("(%s)", cp);
fin = fin / pdiv;
@@ -3011,39 +3010,39 @@ FLASH_BANK_COMMAND_HANDLER(sam3_flash_bank_command)
}
switch (bank->base) {
- default:
- LOG_ERROR("Address 0x%08x invalid bank address (try 0x%08x or 0x%08x "
- "[at91sam3u series] or 0x%08x [at91sam3s series] or "
- "0x%08x [at91sam3n series] or 0x%08x or 0x%08x or 0x%08x[at91sam3ax series] )",
- ((unsigned int)(bank->base)),
- ((unsigned int)(FLASH_BANK0_BASE_U)),
- ((unsigned int)(FLASH_BANK1_BASE_U)),
- ((unsigned int)(FLASH_BANK_BASE_S)),
- ((unsigned int)(FLASH_BANK_BASE_N)),
- ((unsigned int)(FLASH_BANK0_BASE_AX)),
- ((unsigned int)(FLASH_BANK1_BASE_256K_AX)),
- ((unsigned int)(FLASH_BANK1_BASE_512K_AX)));
- return ERROR_FAIL;
-
- /* at91sam3s and at91sam3n series only has bank 0*/
- /* at91sam3u and at91sam3ax series has the same address for bank 0*/
- case FLASH_BANK_BASE_S:
- case FLASH_BANK0_BASE_U:
- bank->driver_priv = &(chip->details.bank[0]);
- bank->bank_number = 0;
- chip->details.bank[0].chip = chip;
- chip->details.bank[0].bank = bank;
- break;
-
- /* Bank 1 of at91sam3u or at91sam3ax series */
- case FLASH_BANK1_BASE_U:
- case FLASH_BANK1_BASE_256K_AX:
- case FLASH_BANK1_BASE_512K_AX:
- bank->driver_priv = &(chip->details.bank[1]);
- bank->bank_number = 1;
- chip->details.bank[1].chip = chip;
- chip->details.bank[1].bank = bank;
- break;
+ /* at91sam3s and at91sam3n series only has bank 0*/
+ /* at91sam3u and at91sam3ax series has the same address for bank 0*/
+ case FLASH_BANK_BASE_S:
+ case FLASH_BANK0_BASE_U:
+ bank->driver_priv = &chip->details.bank[0];
+ bank->bank_number = 0;
+ chip->details.bank[0].chip = chip;
+ chip->details.bank[0].bank = bank;
+ break;
+
+ /* Bank 1 of at91sam3u or at91sam3ax series */
+ case FLASH_BANK1_BASE_U:
+ case FLASH_BANK1_BASE_256K_AX:
+ case FLASH_BANK1_BASE_512K_AX:
+ bank->driver_priv = &chip->details.bank[1];
+ bank->bank_number = 1;
+ chip->details.bank[1].chip = chip;
+ chip->details.bank[1].bank = bank;
+ break;
+
+ default:
+ LOG_ERROR("Address " TARGET_ADDR_FMT " invalid bank address (try 0x%08x or 0x%08x "
+ "[at91sam3u series] or 0x%08x [at91sam3s series] or "
+ "0x%08x [at91sam3n series] or 0x%08x or 0x%08x or 0x%08x[at91sam3ax series] )",
+ bank->base,
+ FLASH_BANK0_BASE_U,
+ FLASH_BANK1_BASE_U,
+ FLASH_BANK_BASE_S,
+ FLASH_BANK_BASE_N,
+ FLASH_BANK0_BASE_AX,
+ FLASH_BANK1_BASE_256K_AX,
+ FLASH_BANK1_BASE_512K_AX);
+ return ERROR_FAIL;
}
/* we initialize after probing. */
@@ -3574,22 +3573,22 @@ COMMAND_HANDLER(sam3_handle_gpnvm_command)
}
switch (CMD_ARGC) {
- default:
- return ERROR_COMMAND_SYNTAX_ERROR;
- case 0:
- goto showall;
- case 1:
+ case 0:
+ goto showall;
+ case 1:
+ who = -1;
+ break;
+ case 2:
+ if ((strcmp(CMD_ARGV[0], "show") == 0) && (strcmp(CMD_ARGV[1], "all") == 0)) {
who = -1;
- break;
- case 2:
- if ((strcmp(CMD_ARGV[0], "show") == 0) && (strcmp(CMD_ARGV[1], "all") == 0))
- who = -1;
- else {
- uint32_t v32;
- COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], v32);
- who = v32;
- }
- break;
+ } else {
+ uint32_t v32;
+ COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], v32);
+ who = v32;
+ }
+ break;
+ default:
+ return ERROR_COMMAND_SYNTAX_ERROR;
}
if (strcmp("show", CMD_ARGV[0]) == 0) {
@@ -3641,26 +3640,26 @@ COMMAND_HANDLER(sam3_handle_slowclk_command)
return ERROR_OK;
switch (CMD_ARGC) {
- case 0:
- /* show */
- break;
- case 1:
- {
- /* set */
- uint32_t v;
- COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], v);
- if (v > 200000) {
- /* absurd slow clock of 200Khz? */
- command_print(CMD, "Absurd/illegal slow clock freq: %d\n", (int)(v));
- return ERROR_COMMAND_SYNTAX_ERROR;
- }
- chip->cfg.slow_freq = v;
- break;
- }
- default:
- /* error */
- command_print(CMD, "Too many parameters");
+ case 0:
+ /* show */
+ break;
+ case 1:
+ {
+ /* set */
+ uint32_t v;
+ COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], v);
+ if (v > 200000) {
+ /* absurd slow clock of 200Khz? */
+ command_print(CMD, "Absurd/illegal slow clock freq: %d\n", (int)(v));
return ERROR_COMMAND_SYNTAX_ERROR;
+ }
+ chip->cfg.slow_freq = v;
+ break;
+ }
+ default:
+ /* error */
+ command_print(CMD, "Too many parameters");
+ return ERROR_COMMAND_SYNTAX_ERROR;
}
command_print(CMD, "Slowclk freq: %d.%03dkhz",
(int)(chip->cfg.slow_freq / 1000),
diff --git a/src/flash/nor/at91sam4.c b/src/flash/nor/at91sam4.c
index 26a803784d..dd3a1ca3f0 100644
--- a/src/flash/nor/at91sam4.c
+++ b/src/flash/nor/at91sam4.c
@@ -1490,40 +1490,39 @@ static int efc_start_command(struct sam4_bank_private *private,
/* Check command & argument */
switch (command) {
-
- case AT91C_EFC_FCMD_WP:
- case AT91C_EFC_FCMD_WPL:
- case AT91C_EFC_FCMD_EWP:
- case AT91C_EFC_FCMD_EWPL:
- /* case AT91C_EFC_FCMD_EPL: */
- case AT91C_EFC_FCMD_EPA:
- case AT91C_EFC_FCMD_SLB:
- case AT91C_EFC_FCMD_CLB:
- n = (private->size_bytes / private->page_size);
- if (argument >= n)
- LOG_ERROR("*BUG*: Embedded flash has only %" PRIu32 " pages", n);
- break;
-
- case AT91C_EFC_FCMD_SFB:
- case AT91C_EFC_FCMD_CFB:
- if (argument >= private->chip->details.n_gpnvms) {
- LOG_ERROR("*BUG*: Embedded flash has only %d GPNVMs",
- private->chip->details.n_gpnvms);
- }
- break;
-
- case AT91C_EFC_FCMD_GETD:
- case AT91C_EFC_FCMD_EA:
- case AT91C_EFC_FCMD_GLB:
- case AT91C_EFC_FCMD_GFB:
- case AT91C_EFC_FCMD_STUI:
- case AT91C_EFC_FCMD_SPUI:
- if (argument != 0)
- LOG_ERROR("Argument is meaningless for cmd: %d", command);
- break;
- default:
- LOG_ERROR("Unknown command %d", command);
- break;
+ case AT91C_EFC_FCMD_WP:
+ case AT91C_EFC_FCMD_WPL:
+ case AT91C_EFC_FCMD_EWP:
+ case AT91C_EFC_FCMD_EWPL:
+ /* case AT91C_EFC_FCMD_EPL: */
+ case AT91C_EFC_FCMD_EPA:
+ case AT91C_EFC_FCMD_SLB:
+ case AT91C_EFC_FCMD_CLB:
+ n = (private->size_bytes / private->page_size);
+ if (argument >= n)
+ LOG_ERROR("*BUG*: Embedded flash has only %" PRIu32 " pages", n);
+ break;
+
+ case AT91C_EFC_FCMD_SFB:
+ case AT91C_EFC_FCMD_CFB:
+ if (argument >= private->chip->details.n_gpnvms) {
+ LOG_ERROR("*BUG*: Embedded flash has only %d GPNVMs",
+ private->chip->details.n_gpnvms);
+ }
+ break;
+
+ case AT91C_EFC_FCMD_GETD:
+ case AT91C_EFC_FCMD_EA:
+ case AT91C_EFC_FCMD_GLB:
+ case AT91C_EFC_FCMD_GFB:
+ case AT91C_EFC_FCMD_STUI:
+ case AT91C_EFC_FCMD_SPUI:
+ if (argument != 0)
+ LOG_ERROR("Argument is meaningless for cmd: %d", command);
+ break;
+ default:
+ LOG_ERROR("Unknown command %d", command);
+ break;
}
if (command == AT91C_EFC_FCMD_SPUI) {
@@ -1678,21 +1677,21 @@ static int flashd_erase_pages(struct sam4_bank_private *private,
LOG_DEBUG("Here");
uint8_t erase_pages;
switch (num_pages) {
- case 4:
- erase_pages = 0x00;
- break;
- case 8:
- erase_pages = 0x01;
- break;
- case 16:
- erase_pages = 0x02;
- break;
- case 32:
- erase_pages = 0x03;
- break;
- default:
- erase_pages = 0x00;
- break;
+ case 4:
+ erase_pages = 0x00;
+ break;
+ case 8:
+ erase_pages = 0x01;
+ break;
+ case 16:
+ erase_pages = 0x02;
+ break;
+ case 32:
+ erase_pages = 0x03;
+ break;
+ default:
+ erase_pages = 0x00;
+ break;
}
/* AT91C_EFC_FCMD_EPA
@@ -2080,18 +2079,18 @@ static void sam4_explain_ckgr_mor(struct sam4_chip *chip)
chip->cfg.rc_freq = 0;
if (rcen) {
switch (v) {
- default:
- chip->cfg.rc_freq = 0;
- break;
- case 0:
- chip->cfg.rc_freq = 4 * 1000 * 1000;
- break;
- case 1:
- chip->cfg.rc_freq = 8 * 1000 * 1000;
- break;
- case 2:
- chip->cfg.rc_freq = 12 * 1000 * 1000;
- break;
+ case 0:
+ chip->cfg.rc_freq = 4 * 1000 * 1000;
+ break;
+ case 1:
+ chip->cfg.rc_freq = 8 * 1000 * 1000;
+ break;
+ case 2:
+ chip->cfg.rc_freq = 12 * 1000 * 1000;
+ break;
+ default:
+ chip->cfg.rc_freq = 0;
+ break;
}
}
@@ -2192,30 +2191,30 @@ static void sam4_explain_mckr(struct sam4_chip *chip)
css = sam4_reg_fieldname(chip, "CSS", chip->cfg.PMC_MCKR, 0, 2);
switch (css & 3) {
- case 0:
- fin = chip->cfg.slow_freq;
- cp = "slowclk";
- break;
- case 1:
- fin = chip->cfg.mainosc_freq;
- cp = "mainosc";
- break;
- case 2:
- fin = chip->cfg.plla_freq;
- cp = "plla";
- break;
- case 3:
- if (chip->cfg.CKGR_UCKR & (1 << 16)) {
- fin = 480 * 1000 * 1000;
- cp = "upll";
- } else {
- fin = 0;
- cp = "upll (*ERROR* UPLL is disabled)";
- }
- break;
- default:
- assert(0);
- break;
+ case 0:
+ fin = chip->cfg.slow_freq;
+ cp = "slowclk";
+ break;
+ case 1:
+ fin = chip->cfg.mainosc_freq;
+ cp = "mainosc";
+ break;
+ case 2:
+ fin = chip->cfg.plla_freq;
+ cp = "plla";
+ break;
+ case 3:
+ if (chip->cfg.CKGR_UCKR & (1 << 16)) {
+ fin = 480 * 1000 * 1000;
+ cp = "upll";
+ } else {
+ fin = 0;
+ cp = "upll (*ERROR* UPLL is disabled)";
+ }
+ break;
+ default:
+ assert(0);
+ break;
}
LOG_USER("%s (%3.03f Mhz)",
@@ -2223,41 +2222,41 @@ static void sam4_explain_mckr(struct sam4_chip *chip)
_tomhz(fin));
pres = sam4_reg_fieldname(chip, "PRES", chip->cfg.PMC_MCKR, 4, 3);
switch (pres & 0x07) {
- case 0:
- pdiv = 1;
- cp = "selected clock";
- break;
- case 1:
- pdiv = 2;
- cp = "clock/2";
- break;
- case 2:
- pdiv = 4;
- cp = "clock/4";
- break;
- case 3:
- pdiv = 8;
- cp = "clock/8";
- break;
- case 4:
- pdiv = 16;
- cp = "clock/16";
- break;
- case 5:
- pdiv = 32;
- cp = "clock/32";
- break;
- case 6:
- pdiv = 64;
- cp = "clock/64";
- break;
- case 7:
- pdiv = 6;
- cp = "clock/6";
- break;
- default:
- assert(0);
- break;
+ case 0:
+ pdiv = 1;
+ cp = "selected clock";
+ break;
+ case 1:
+ pdiv = 2;
+ cp = "clock/2";
+ break;
+ case 2:
+ pdiv = 4;
+ cp = "clock/4";
+ break;
+ case 3:
+ pdiv = 8;
+ cp = "clock/8";
+ break;
+ case 4:
+ pdiv = 16;
+ cp = "clock/16";
+ break;
+ case 5:
+ pdiv = 32;
+ cp = "clock/32";
+ break;
+ case 6:
+ pdiv = 64;
+ cp = "clock/64";
+ break;
+ case 7:
+ pdiv = 6;
+ cp = "clock/6";
+ break;
+ default:
+ assert(0);
+ break;
}
LOG_USER("(%s)", cp);
fin = fin / pdiv;
@@ -2504,32 +2503,32 @@ FLASH_BANK_COMMAND_HANDLER(sam4_flash_bank_command)
}
switch (bank->base) {
- default:
- LOG_ERROR("Address 0x%08x invalid bank address (try 0x%08x"
- "[at91sam4s series] )",
- ((unsigned int)(bank->base)),
- ((unsigned int)(FLASH_BANK_BASE_S)));
- return ERROR_FAIL;
-
- /* at91sam4s series only has bank 0*/
- /* at91sam4sd series has the same address for bank 0 (FLASH_BANK0_BASE_SD)*/
- case FLASH_BANK_BASE_S:
- case FLASH_BANK_BASE_C:
- bank->driver_priv = &(chip->details.bank[0]);
- bank->bank_number = 0;
- chip->details.bank[0].chip = chip;
- chip->details.bank[0].bank = bank;
- break;
-
- /* Bank 1 of at91sam4sd/at91sam4c32 series */
- case FLASH_BANK1_BASE_1024K_SD:
- case FLASH_BANK1_BASE_2048K_SD:
- case FLASH_BANK1_BASE_C32:
- bank->driver_priv = &(chip->details.bank[1]);
- bank->bank_number = 1;
- chip->details.bank[1].chip = chip;
- chip->details.bank[1].bank = bank;
- break;
+ /* at91sam4s series only has bank 0*/
+ /* at91sam4sd series has the same address for bank 0 (FLASH_BANK0_BASE_SD)*/
+ case FLASH_BANK_BASE_S:
+ case FLASH_BANK_BASE_C:
+ bank->driver_priv = &chip->details.bank[0];
+ bank->bank_number = 0;
+ chip->details.bank[0].chip = chip;
+ chip->details.bank[0].bank = bank;
+ break;
+
+ /* Bank 1 of at91sam4sd/at91sam4c32 series */
+ case FLASH_BANK1_BASE_1024K_SD:
+ case FLASH_BANK1_BASE_2048K_SD:
+ case FLASH_BANK1_BASE_C32:
+ bank->driver_priv = &chip->details.bank[1];
+ bank->bank_number = 1;
+ chip->details.bank[1].chip = chip;
+ chip->details.bank[1].bank = bank;
+ break;
+
+ default:
+ LOG_ERROR("Address " TARGET_ADDR_FMT " invalid bank address (try 0x%08x"
+ "[at91sam4s series] )",
+ bank->base,
+ FLASH_BANK_BASE_S);
+ return ERROR_FAIL;
}
/* we initialize after probing. */
@@ -3122,22 +3121,22 @@ COMMAND_HANDLER(sam4_handle_gpnvm_command)
}
switch (CMD_ARGC) {
- default:
- return ERROR_COMMAND_SYNTAX_ERROR;
- case 0:
- goto showall;
- case 1:
+ case 0:
+ goto showall;
+ case 1:
+ who = -1;
+ break;
+ case 2:
+ if ((strcmp(CMD_ARGV[0], "show") == 0) && (strcmp(CMD_ARGV[1], "all") == 0)) {
who = -1;
- break;
- case 2:
- if ((strcmp(CMD_ARGV[0], "show") == 0) && (strcmp(CMD_ARGV[1], "all") == 0))
- who = -1;
- else {
- uint32_t v32;
- COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], v32);
- who = v32;
- }
- break;
+ } else {
+ uint32_t v32;
+ COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], v32);
+ who = v32;
+ }
+ break;
+ default:
+ return ERROR_COMMAND_SYNTAX_ERROR;
}
if (strcmp("show", CMD_ARGV[0]) == 0) {
@@ -3189,26 +3188,26 @@ COMMAND_HANDLER(sam4_handle_slowclk_command)
return ERROR_OK;
switch (CMD_ARGC) {
- case 0:
- /* show */
- break;
- case 1:
- {
- /* set */
- uint32_t v;
- COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], v);
- if (v > 200000) {
- /* absurd slow clock of 200Khz? */
- command_print(CMD, "Absurd/illegal slow clock freq: %d\n", (int)(v));
- return ERROR_COMMAND_SYNTAX_ERROR;
- }
- chip->cfg.slow_freq = v;
- break;
- }
- default:
- /* error */
- command_print(CMD, "Too many parameters");
+ case 0:
+ /* show */
+ break;
+ case 1:
+ {
+ /* set */
+ uint32_t v;
+ COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], v);
+ if (v > 200000) {
+ /* absurd slow clock of 200Khz? */
+ command_print(CMD, "Absurd/illegal slow clock freq: %d\n", (int)(v));
return ERROR_COMMAND_SYNTAX_ERROR;
+ }
+ chip->cfg.slow_freq = v;
+ break;
+ }
+ default:
+ /* error */
+ command_print(CMD, "Too many parameters");
+ return ERROR_COMMAND_SYNTAX_ERROR;
}
command_print(CMD, "Slowclk freq: %d.%03dkhz",
(int)(chip->cfg.slow_freq / 1000),
diff --git a/src/flash/nor/at91sam4l.c b/src/flash/nor/at91sam4l.c
index ddf42a8c5f..1db15377eb 100644
--- a/src/flash/nor/at91sam4l.c
+++ b/src/flash/nor/at91sam4l.c
@@ -282,19 +282,19 @@ static int sam4l_probe(struct flash_bank *bank)
chip->ram_kb = sam4l_ram_sizes[0xF & (id >> 16)];
switch (0xF & (id >> 8)) {
- case 0x07:
- chip->flash_kb = 128;
- break;
- case 0x09:
- chip->flash_kb = 256;
- break;
- case 0x0A:
- chip->flash_kb = 512;
- break;
- default:
- LOG_ERROR("Unknown flash size (chip ID is %08" PRIx32 "), assuming 128K", id);
- chip->flash_kb = 128;
- break;
+ case 0x07:
+ chip->flash_kb = 128;
+ break;
+ case 0x09:
+ chip->flash_kb = 256;
+ break;
+ case 0x0A:
+ chip->flash_kb = 512;
+ break;
+ default:
+ LOG_ERROR("Unknown flash size (chip ID is %08" PRIx32 "), assuming 128K", id);
+ chip->flash_kb = 128;
+ break;
}
/* Retrieve the Flash parameters */
diff --git a/src/flash/nor/at91sam7.c b/src/flash/nor/at91sam7.c
index 86c80765fc..a4c92a93c6 100644
--- a/src/flash/nor/at91sam7.c
+++ b/src/flash/nor/at91sam7.c
@@ -193,44 +193,41 @@ static void at91sam7_read_clock_info(struct flash_bank *bank)
at91sam7_info->mck_valid = 0;
at91sam7_info->mck_freq = 0;
switch (mckr & PMC_MCKR_CSS) {
- case 0: /* Slow Clock */
+ case 0: /* Slow Clock */
+ at91sam7_info->mck_valid = 1;
+ tmp = RC_FREQ;
+ break;
+
+ case 1: /* Main Clock */
+ if ((mcfr & CKGR_MCFR_MAINRDY) && at91sam7_info->ext_freq == 0) {
at91sam7_info->mck_valid = 1;
- tmp = RC_FREQ;
- break;
-
- case 1: /* Main Clock */
- if ((mcfr & CKGR_MCFR_MAINRDY) &&
- (at91sam7_info->ext_freq == 0)) {
- at91sam7_info->mck_valid = 1;
- tmp = RC_FREQ / 16ul * (mcfr & 0xffff);
- } else if (at91sam7_info->ext_freq != 0) {
- at91sam7_info->mck_valid = 1;
- tmp = at91sam7_info->ext_freq;
- }
- break;
-
- case 2: /* Reserved */
- break;
-
- case 3: /* PLL Clock */
- if ((mcfr & CKGR_MCFR_MAINRDY) &&
- (at91sam7_info->ext_freq == 0)) {
- target_read_u32(target, CKGR_PLLR, &pllr);
- if (!(pllr & CKGR_PLLR_DIV))
- break; /* 0 Hz */
- at91sam7_info->mck_valid = 1;
- mainfreq = RC_FREQ / 16ul * (mcfr & 0xffff);
- /* Integer arithmetic should have sufficient precision
- * as long as PLL is properly configured. */
- tmp = mainfreq / (pllr & CKGR_PLLR_DIV)*
- (((pllr & CKGR_PLLR_MUL) >> 16) + 1);
- } else if ((at91sam7_info->ext_freq != 0) &&
- ((pllr&CKGR_PLLR_DIV) != 0)) {
- at91sam7_info->mck_valid = 1;
- tmp = at91sam7_info->ext_freq / (pllr&CKGR_PLLR_DIV)*
- (((pllr & CKGR_PLLR_MUL) >> 16) + 1);
- }
- break;
+ tmp = RC_FREQ / 16ul * (mcfr & 0xffff);
+ } else if (at91sam7_info->ext_freq != 0) {
+ at91sam7_info->mck_valid = 1;
+ tmp = at91sam7_info->ext_freq;
+ }
+ break;
+
+ case 2: /* Reserved */
+ break;
+
+ case 3: /* PLL Clock */
+ if ((mcfr & CKGR_MCFR_MAINRDY) && at91sam7_info->ext_freq == 0) {
+ target_read_u32(target, CKGR_PLLR, &pllr);
+ if (!(pllr & CKGR_PLLR_DIV))
+ break; /* 0 Hz */
+ at91sam7_info->mck_valid = 1;
+ mainfreq = RC_FREQ / 16ul * (mcfr & 0xffff);
+ /* Integer arithmetic should have sufficient precision
+ * as long as PLL is properly configured. */
+ tmp = mainfreq / (pllr & CKGR_PLLR_DIV) *
+ (((pllr & CKGR_PLLR_MUL) >> 16) + 1);
+ } else if ((at91sam7_info->ext_freq != 0) && ((pllr & CKGR_PLLR_DIV) != 0)) {
+ at91sam7_info->mck_valid = 1;
+ tmp = at91sam7_info->ext_freq / (pllr & CKGR_PLLR_DIV) *
+ (((pllr & CKGR_PLLR_MUL) >> 16) + 1);
+ }
+ break;
}
/* Prescaler adjust */
@@ -277,7 +274,7 @@ static void at91sam7_set_flash_mode(struct flash_bank *bank, int mode)
if (at91sam7_info->mck_freq > 30000000ul)
fws = 1;
- LOG_DEBUG("fmcn[%i]: %i", bank->bank_number, (int)(fmcn));
+ LOG_DEBUG("fmcn[%u]: %" PRIu32, bank->bank_number, fmcn);
fmr = fmcn << 16 | fws << 8;
target_write_u32(target, mc_fmr[bank->bank_number], fmr);
}
@@ -291,14 +288,14 @@ static uint32_t at91sam7_wait_status_busy(struct flash_bank *bank, uint32_t wait
while ((!((status = at91sam7_get_flash_status(bank->target,
bank->bank_number)) & waitbits)) && (timeout-- > 0)) {
- LOG_DEBUG("status[%i]: 0x%" PRIx32 "", (int)bank->bank_number, status);
+ LOG_DEBUG("status[%u]: 0x%" PRIx32, bank->bank_number, status);
alive_sleep(1);
}
- LOG_DEBUG("status[%i]: 0x%" PRIx32 "", bank->bank_number, status);
+ LOG_DEBUG("status[%u]: 0x%" PRIx32, bank->bank_number, status);
if (status & 0x0C) {
- LOG_ERROR("status register: 0x%" PRIx32 "", status);
+ LOG_ERROR("status register: 0x%" PRIx32, status);
if (status & 0x4)
LOG_ERROR("Lock Error Bit Detected, Operation Abort");
if (status & 0x8)
@@ -319,7 +316,7 @@ static int at91sam7_flash_command(struct flash_bank *bank, uint8_t cmd, uint16_t
fcr = (0x5A << 24) | ((pagen&0x3FF) << 8) | cmd;
target_write_u32(target, mc_fcr[bank->bank_number], fcr);
- LOG_DEBUG("Flash command: 0x%" PRIx32 ", flash bank: %i, page number: %u",
+ LOG_DEBUG("Flash command: 0x%" PRIx32 ", flash bank: %u, page number: %" PRIu16,
fcr,
bank->bank_number + 1,
pagen);
@@ -418,130 +415,130 @@ static int at91sam7_read_part_info(struct flash_bank *bank)
/* check flash size */
switch ((cidr >> 8)&0x000F) {
- case FLASH_SIZE_8KB:
- break;
-
- case FLASH_SIZE_16KB:
- banks_num = 1;
- sectors_num = 8;
- pages_per_sector = 32;
- page_size = 64;
- base_address = 0x00100000;
- if (arch == 0x70) {
- num_nvmbits = 2;
- target_name_t = "AT91SAM7S161/16";
- }
- break;
-
- case FLASH_SIZE_32KB:
- banks_num = 1;
- sectors_num = 8;
- pages_per_sector = 32;
- page_size = 128;
- base_address = 0x00100000;
- if (arch == 0x70) {
- num_nvmbits = 2;
- target_name_t = "AT91SAM7S321/32";
- }
- if (arch == 0x72) {
- num_nvmbits = 3;
- target_name_t = "AT91SAM7SE32";
- }
- break;
-
- case FLASH_SIZE_64KB:
- banks_num = 1;
- sectors_num = 16;
- pages_per_sector = 32;
- page_size = 128;
- base_address = 0x00100000;
- if (arch == 0x70) {
- num_nvmbits = 2;
- target_name_t = "AT91SAM7S64";
- }
- break;
-
- case FLASH_SIZE_128KB:
- banks_num = 1;
- sectors_num = 8;
- pages_per_sector = 64;
- page_size = 256;
- base_address = 0x00100000;
- if (arch == 0x70) {
- num_nvmbits = 2;
- target_name_t = "AT91SAM7S128";
- }
- if (arch == 0x71) {
- num_nvmbits = 3;
- target_name_t = "AT91SAM7XC128";
- }
- if (arch == 0x72) {
- num_nvmbits = 3;
- target_name_t = "AT91SAM7SE128";
- }
- if (arch == 0x75) {
- num_nvmbits = 3;
- target_name_t = "AT91SAM7X128";
- }
- break;
-
- case FLASH_SIZE_256KB:
- banks_num = 1;
- sectors_num = 16;
- pages_per_sector = 64;
- page_size = 256;
- base_address = 0x00100000;
- if (arch == 0x60) {
- num_nvmbits = 3;
- target_name_t = "AT91SAM7A3";
- }
- if (arch == 0x70) {
- num_nvmbits = 2;
- target_name_t = "AT91SAM7S256";
- }
- if (arch == 0x71) {
- num_nvmbits = 3;
- target_name_t = "AT91SAM7XC256";
- }
- if (arch == 0x72) {
- num_nvmbits = 3;
- target_name_t = "AT91SAM7SE256";
- }
- if (arch == 0x75) {
- num_nvmbits = 3;
- target_name_t = "AT91SAM7X256";
- }
- break;
-
- case FLASH_SIZE_512KB:
- banks_num = 2;
- sectors_num = 16;
- pages_per_sector = 64;
- page_size = 256;
- base_address = 0x00100000;
- if (arch == 0x70) {
- num_nvmbits = 2;
- target_name_t = "AT91SAM7S512";
- }
- if (arch == 0x71) {
- num_nvmbits = 3;
- target_name_t = "AT91SAM7XC512";
- }
- if (arch == 0x72) {
- num_nvmbits = 3;
- target_name_t = "AT91SAM7SE512";
- }
- if (arch == 0x75) {
- num_nvmbits = 3;
- target_name_t = "AT91SAM7X512";
- }
- break;
+ case FLASH_SIZE_8KB:
+ break;
+
+ case FLASH_SIZE_16KB:
+ banks_num = 1;
+ sectors_num = 8;
+ pages_per_sector = 32;
+ page_size = 64;
+ base_address = 0x00100000;
+ if (arch == 0x70) {
+ num_nvmbits = 2;
+ target_name_t = "AT91SAM7S161/16";
+ }
+ break;
+
+ case FLASH_SIZE_32KB:
+ banks_num = 1;
+ sectors_num = 8;
+ pages_per_sector = 32;
+ page_size = 128;
+ base_address = 0x00100000;
+ if (arch == 0x70) {
+ num_nvmbits = 2;
+ target_name_t = "AT91SAM7S321/32";
+ }
+ if (arch == 0x72) {
+ num_nvmbits = 3;
+ target_name_t = "AT91SAM7SE32";
+ }
+ break;
+
+ case FLASH_SIZE_64KB:
+ banks_num = 1;
+ sectors_num = 16;
+ pages_per_sector = 32;
+ page_size = 128;
+ base_address = 0x00100000;
+ if (arch == 0x70) {
+ num_nvmbits = 2;
+ target_name_t = "AT91SAM7S64";
+ }
+ break;
+
+ case FLASH_SIZE_128KB:
+ banks_num = 1;
+ sectors_num = 8;
+ pages_per_sector = 64;
+ page_size = 256;
+ base_address = 0x00100000;
+ if (arch == 0x70) {
+ num_nvmbits = 2;
+ target_name_t = "AT91SAM7S128";
+ }
+ if (arch == 0x71) {
+ num_nvmbits = 3;
+ target_name_t = "AT91SAM7XC128";
+ }
+ if (arch == 0x72) {
+ num_nvmbits = 3;
+ target_name_t = "AT91SAM7SE128";
+ }
+ if (arch == 0x75) {
+ num_nvmbits = 3;
+ target_name_t = "AT91SAM7X128";
+ }
+ break;
+
+ case FLASH_SIZE_256KB:
+ banks_num = 1;
+ sectors_num = 16;
+ pages_per_sector = 64;
+ page_size = 256;
+ base_address = 0x00100000;
+ if (arch == 0x60) {
+ num_nvmbits = 3;
+ target_name_t = "AT91SAM7A3";
+ }
+ if (arch == 0x70) {
+ num_nvmbits = 2;
+ target_name_t = "AT91SAM7S256";
+ }
+ if (arch == 0x71) {
+ num_nvmbits = 3;
+ target_name_t = "AT91SAM7XC256";
+ }
+ if (arch == 0x72) {
+ num_nvmbits = 3;
+ target_name_t = "AT91SAM7SE256";
+ }
+ if (arch == 0x75) {
+ num_nvmbits = 3;
+ target_name_t = "AT91SAM7X256";
+ }
+ break;
+
+ case FLASH_SIZE_512KB:
+ banks_num = 2;
+ sectors_num = 16;
+ pages_per_sector = 64;
+ page_size = 256;
+ base_address = 0x00100000;
+ if (arch == 0x70) {
+ num_nvmbits = 2;
+ target_name_t = "AT91SAM7S512";
+ }
+ if (arch == 0x71) {
+ num_nvmbits = 3;
+ target_name_t = "AT91SAM7XC512";
+ }
+ if (arch == 0x72) {
+ num_nvmbits = 3;
+ target_name_t = "AT91SAM7SE512";
+ }
+ if (arch == 0x75) {
+ num_nvmbits = 3;
+ target_name_t = "AT91SAM7X512";
+ }
+ break;
- case FLASH_SIZE_1024KB:
- break;
+ case FLASH_SIZE_1024KB:
+ break;
- case FLASH_SIZE_2048KB:
- break;
+ case FLASH_SIZE_2048KB:
+ break;
}
if (strcmp(target_name_t, "Unknown") == 0) {
@@ -915,7 +912,7 @@ static int at91sam7_write(struct flash_bank *bank, const uint8_t *buffer, uint32
dst_min_alignment = at91sam7_info->pagesize;
if (offset % dst_min_alignment) {
- LOG_WARNING("offset 0x%" PRIx32 " breaks required alignment 0x%" PRIx32 "",
+ LOG_WARNING("offset 0x%" PRIx32 " breaks required alignment 0x%" PRIx32,
offset,
dst_min_alignment);
return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
diff --git a/src/flash/nor/atsamv.c b/src/flash/nor/atsamv.c
index d6d8938b67..de0b7dd1d2 100644
--- a/src/flash/nor/atsamv.c
+++ b/src/flash/nor/atsamv.c
@@ -12,6 +12,9 @@
* atsamv, atsams, and atsame support
* Copyright (C) 2015 Morgan Quigley
*
+ * atsamv extension of user signature area
+ * Copyright (C) 2024-2025 Elektroline Inc.
+ *
* Some of the lower level code was based on code supplied by
* ATMEL under BSD-Source-Code License and this copyright.
* ATMEL Microcontroller Software Support
@@ -24,6 +27,7 @@
#include "imp.h"
#include
+#include
#define REG_NAME_WIDTH (12)
@@ -40,18 +44,39 @@
#define SAMV_EFC_FCMD_SFB (0xB) /* (EFC) Set Fuse Bit */
#define SAMV_EFC_FCMD_CFB (0xC) /* (EFC) Clear Fuse Bit */
#define SAMV_EFC_FCMD_GFB (0xD) /* (EFC) Get Fuse Bit */
+#define SAMV_EFC_FCMD_WUS (0x12) /* (EFC) Write User Signature */
+#define SAMV_EFC_FCMD_EUS (0x13) /* (EFC) Erase User Signature */
+#define SAMV_EFC_FCMD_STUS (0x14) /* (EFC) Start Read User Signature */
+#define SAMV_EFC_FCMD_SPUS (0x15) /* (EFC) Stop Read User Signature */
+
+#define SAMV_EFC_FMR_SCOD BIT(16) /* Sequantial Code Optimalization Disable */
+
+#define SAMV_EFC_FSR_FRDY_SET 1
+#define SAMV_EFC_FRS_FRDY_CLR 0
#define OFFSET_EFC_FMR 0
#define OFFSET_EFC_FCR 4
#define OFFSET_EFC_FSR 8
#define OFFSET_EFC_FRR 12
+#define TIMEOUT_MS_FRS_CHANGE 10 /* Timeout for FRS ready bit change */
+#define TIMEOUT_MS_CMD_DEFAULT 50 /* Default timeout for command */
+#define TIMEOUT_MS_CMD_ERASE 24000 /* Timeout for erase commands */
+
#define SAMV_CHIPID_CIDR (0x400E0940)
#define SAMV_NUM_GPNVM_BITS 9
#define SAMV_CONTROLLER_ADDR (0x400e0c00)
#define SAMV_SECTOR_SIZE 16384
#define SAMV_PAGE_SIZE 512
#define SAMV_FLASH_BASE 0x00400000
+/* This is a workaround. Flash Signature area is actually located at the
+ * beginning of the flash memory at the address range overlapping the
+ * first page of program flash. Since OpenOCD does not support write to
+ * a bank outside of address range, we use address above maximum 32-bit
+ * address space.
+ */
+#define SAMV_FLASH_SIGNATURE_BASE 0x100000000
+#define SAMV_FLASH_SIGNATURE_SIZE SAMV_PAGE_SIZE
struct samv_flash_bank {
bool probed;
@@ -59,6 +84,7 @@ struct samv_flash_bank {
unsigned int gpnvm[SAMV_NUM_GPNVM_BITS];
};
+
/* The actual sector size of the SAMV7 flash memory is 128K bytes.
* 16 sectors for a 2048KB device. The lock regions are 16KB per lock
* region, with a 2048KB device having 128 lock regions.
@@ -72,6 +98,36 @@ static int samv_efc_get_status(struct target *target, uint32_t *v)
return r;
}
+static int samv_efc_wait_status(struct target *target, uint8_t desired,
+ int64_t timeout, uint32_t *status)
+{
+ uint32_t v;
+ int64_t ms_now, ms_end;
+ int r;
+
+ if (status)
+ *status = 0;
+
+ ms_end = timeout + timeval_ms();
+
+ do {
+ r = samv_efc_get_status(target, &v);
+ if (r != ERROR_OK)
+ return r;
+
+ if (status)
+ *status = v;
+ ms_now = timeval_ms();
+ if (ms_now > ms_end) {
+ /* error */
+ LOG_ERROR("Command timeout");
+ return ERROR_FLASH_BUSY;
+ }
+ } while ((v & 1) != desired);
+
+ return ERROR_OK;
+}
+
static int samv_efc_get_result(struct target *target, uint32_t *v)
{
uint32_t rv;
@@ -81,15 +137,20 @@ static int samv_efc_get_result(struct target *target, uint32_t *v)
return r;
}
+static inline int samv_efc_get_mode(struct target *target, uint32_t *v)
+{
+ return target_read_u32(target, SAMV_CONTROLLER_ADDR + OFFSET_EFC_FMR, v);
+}
+
+static inline int samv_efc_set_mode(struct target *target, uint32_t v)
+{
+ return target_write_u32(target, SAMV_CONTROLLER_ADDR + OFFSET_EFC_FMR, v);
+}
+
static int samv_efc_start_command(struct target *target,
- unsigned int command, unsigned int argument)
+ uint8_t command, unsigned int argument)
{
uint32_t v;
- samv_efc_get_status(target, &v);
- if (!(v & 1)) {
- LOG_ERROR("flash controller is not ready");
- return ERROR_FAIL;
- }
v = (0x5A << 24) | (argument << 8) | command;
LOG_DEBUG("starting flash command: 0x%08x", (unsigned int)(v));
@@ -100,32 +161,33 @@ static int samv_efc_start_command(struct target *target,
}
static int samv_efc_perform_command(struct target *target,
- unsigned int command, unsigned int argument, uint32_t *status)
+ uint8_t command, unsigned int argument, uint32_t *status)
{
int r;
uint32_t v;
- int64_t ms_now, ms_end;
+ int64_t timeout;
if (status)
*status = 0;
+ r = samv_efc_get_status(target, &v);
+ if (r != ERROR_OK)
+ return r;
+ if ((v & 1) != 0x1)
+ return ERROR_FAIL;
r = samv_efc_start_command(target, command, argument);
if (r != ERROR_OK)
return r;
- ms_end = 10000 + timeval_ms();
+ if (command == SAMV_EFC_FCMD_EA || command == SAMV_EFC_FCMD_EPA ||
+ command == SAMV_EFC_FCMD_EUS)
+ timeout = TIMEOUT_MS_CMD_ERASE;
+ else
+ timeout = TIMEOUT_MS_CMD_DEFAULT;
- do {
- r = samv_efc_get_status(target, &v);
- if (r != ERROR_OK)
- return r;
- ms_now = timeval_ms();
- if (ms_now > ms_end) {
- /* error */
- LOG_ERROR("Command timeout");
- return ERROR_FAIL;
- }
- } while ((v & 1) == 0);
+ r = samv_efc_wait_status(target, SAMV_EFC_FSR_FRDY_SET, timeout, &v);
+ if (r != ERROR_OK)
+ return r;
/* if requested, copy the flash controller error bits back to the caller */
if (status)
@@ -133,26 +195,71 @@ static int samv_efc_perform_command(struct target *target,
return ERROR_OK;
}
+static int samv_efc_read_sequence(struct target *target, uint8_t start_cmd,
+ uint8_t stop_cmd, uint8_t *buf, size_t read_size)
+{
+ uint32_t v;
+ uint32_t addr = SAMV_FLASH_BASE;
+ int r;
+
+ samv_efc_get_mode(target, &v);
+ v |= SAMV_EFC_FMR_SCOD;
+ samv_efc_set_mode(target, v);
+
+ r = samv_efc_start_command(target, start_cmd, 0);
+ if (r != ERROR_OK) {
+ samv_efc_start_command(target, stop_cmd, 0);
+ goto rs_finish;
+ }
+
+ r = samv_efc_wait_status(target, SAMV_EFC_FRS_FRDY_CLR,
+ TIMEOUT_MS_FRS_CHANGE, NULL);
+ if (r != ERROR_OK)
+ goto rs_finish;
+
+ r = target_read_memory(target, addr, sizeof(uint32_t),
+ read_size / sizeof(uint32_t), buf);
+ if (r != ERROR_OK) {
+ LOG_ERROR("flash program failed to read page @ 0x%" PRIx32 "", addr);
+ goto rs_finish;
+ }
+
+ r = samv_efc_start_command(target, stop_cmd, 0);
+ if (r != ERROR_OK)
+ goto rs_finish;
+
+ r = samv_efc_wait_status(target, SAMV_EFC_FSR_FRDY_SET,
+ TIMEOUT_MS_FRS_CHANGE, NULL);
+ if (r != ERROR_OK)
+ goto rs_finish;
+
+rs_finish:
+ v &= ~SAMV_EFC_FMR_SCOD;
+ samv_efc_set_mode(target, v);
+
+ return r;
+}
+
static int samv_erase_pages(struct target *target,
int first_page, int num_pages, uint32_t *status)
{
uint8_t erase_pages;
switch (num_pages) {
- case 4:
- erase_pages = 0x00;
- break;
- case 8:
- erase_pages = 0x01;
- break;
- case 16:
- erase_pages = 0x02;
- break;
- case 32:
- erase_pages = 0x03;
- break;
- default:
- erase_pages = 0x00;
- break;
+ case 4:
+ erase_pages = 0x00;
+ break;
+ case 8:
+ erase_pages = 0x01;
+ break;
+ case 16:
+ erase_pages = 0x02;
+ break;
+ case 32:
+ erase_pages = 0x03;
+ break;
+ default:
+ erase_pages = 0x00;
+ break;
}
/* SAMV_EFC_FCMD_EPA
@@ -230,6 +337,17 @@ static int samv_set_gpnvm(struct target *target, unsigned int gpnvm)
return r;
}
+static int samv_erase_user_signature(struct target *target)
+{
+ int r;
+
+ r = samv_efc_perform_command(target, SAMV_EFC_FCMD_EUS, 0, NULL);
+ if (r != ERROR_OK)
+ LOG_ERROR("error performing user signature write");
+
+ return r;
+}
+
static int samv_flash_unlock(struct target *target,
unsigned int start_sector, unsigned int end_sector)
{
@@ -292,7 +410,6 @@ static int samv_protect_check(struct flash_bank *bank)
FLASH_BANK_COMMAND_HANDLER(samv_flash_bank_command)
{
- LOG_INFO("flash bank command");
struct samv_flash_bank *samv_info;
samv_info = calloc(1, sizeof(struct samv_flash_bank));
bank->driver_priv = samv_info;
@@ -306,11 +423,19 @@ static int samv_get_device_id(struct flash_bank *bank, uint32_t *device_id)
static int samv_probe(struct flash_bank *bank)
{
+ if (bank->base == SAMV_FLASH_SIGNATURE_BASE) {
+ bank->size = SAMV_FLASH_SIGNATURE_SIZE;
+ bank->num_sectors = 1;
+ bank->sectors = calloc(bank->num_sectors, sizeof(struct flash_sector));
+ bank->sectors[0].size = SAMV_FLASH_SIGNATURE_SIZE;
+ return ERROR_OK;
+ }
+
uint32_t device_id;
int r = samv_get_device_id(bank, &device_id);
if (r != ERROR_OK)
return r;
- LOG_INFO("device id = 0x%08" PRIx32 "", device_id);
+ LOG_INFO("device id = 0x%08" PRIx32, device_id);
uint8_t eproc = (device_id >> 5) & 0x7;
if (eproc != 0) {
@@ -320,18 +445,18 @@ static int samv_probe(struct flash_bank *bank)
uint8_t nvm_size_code = (device_id >> 8) & 0xf;
switch (nvm_size_code) {
- case 10:
- bank->size = 512 * 1024;
- break;
- case 12:
- bank->size = 1024 * 1024;
- break;
- case 14:
- bank->size = 2048 * 1024;
- break;
- default:
- LOG_ERROR("unrecognized flash size code: %d", nvm_size_code);
- return ERROR_FAIL;
+ case 10:
+ bank->size = 512 * 1024;
+ break;
+ case 12:
+ bank->size = 1024 * 1024;
+ break;
+ case 14:
+ bank->size = 2048 * 1024;
+ break;
+ default:
+ LOG_ERROR("unrecognized flash size code: %d", nvm_size_code);
+ return ERROR_FAIL;
}
struct samv_flash_bank *samv_info = bank->driver_priv;
@@ -377,16 +502,19 @@ static int samv_erase(struct flash_bank *bank, unsigned int first,
if (r != ERROR_OK)
return r;
+ if (bank->base == SAMV_FLASH_SIGNATURE_BASE)
+ return samv_erase_user_signature(bank->target);
+
/* easy case: we've been requested to erase the entire flash */
if ((first == 0) && ((last + 1) == bank->num_sectors))
return samv_efc_perform_command(bank->target, SAMV_EFC_FCMD_EA, 0, NULL);
- LOG_INFO("erasing lock regions %u-%u...", first, last);
+ LOG_DEBUG("erasing lock regions %u-%u...", first, last);
for (unsigned int i = first; i <= last; i++) {
uint32_t status;
r = samv_erase_pages(bank->target, (i * page_count), page_count, &status);
- LOG_INFO("erasing lock region %u", i);
+ LOG_DEBUG("erasing lock region %u", i);
if (r != ERROR_OK)
LOG_ERROR("error performing erase page @ lock region number %u", i);
if (status & (1 << 2)) {
@@ -418,45 +546,134 @@ static int samv_protect(struct flash_bank *bank, int set, unsigned int first,
return r;
}
-static int samv_page_read(struct target *target,
+static int samv_read_standard_page(struct target *target,
unsigned int page_num, uint8_t *buf)
{
uint32_t addr = SAMV_FLASH_BASE + page_num * SAMV_PAGE_SIZE;
int r = target_read_memory(target, addr, 4, SAMV_PAGE_SIZE / 4, buf);
if (r != ERROR_OK)
- LOG_ERROR("flash program failed to read page @ 0x%08x",
- (unsigned int)(addr));
+ LOG_ERROR("flash program failed to read page @ 0x%08" PRIx32 "",
+ addr);
return r;
}
-static int samv_page_write(struct target *target,
+static int samv_read_user_signature(struct target *target, uint8_t *buf)
+{
+ int r;
+
+ r = samv_efc_read_sequence(target, SAMV_EFC_FCMD_STUS, SAMV_EFC_FCMD_SPUS,
+ buf, SAMV_PAGE_SIZE);
+
+ return r;
+}
+
+static int samv_page_read(struct target *target,
+ target_addr_t base, unsigned int page_num, uint8_t *buf)
+{
+ int r;
+ if (base == SAMV_FLASH_SIGNATURE_BASE)
+ r = samv_read_user_signature(target, buf);
+ else
+ r = samv_read_standard_page(target, page_num, buf);
+
+ return r;
+}
+
+static int samv_write_user_signature(struct target *target,
+ unsigned int pagenum, const uint8_t *buf)
+{
+ const uint32_t addr = SAMV_FLASH_BASE;
+ int r;
+
+ r = target_write_memory(target, addr, sizeof(uint32_t),
+ SAMV_PAGE_SIZE / sizeof(uint32_t), buf);
+ if (r != ERROR_OK) {
+ LOG_ERROR("failed to buffer page at 0x%08" PRIx32 "", addr);
+ return r;
+ }
+
+ r = samv_efc_perform_command(target, SAMV_EFC_FCMD_WUS, 0, NULL);
+ if (r != ERROR_OK)
+ LOG_ERROR("error performing user signature write");
+
+ return r;
+}
+
+static int samv_write_standard_page(struct target *target,
unsigned int pagenum, const uint8_t *buf)
{
uint32_t status;
const uint32_t addr = SAMV_FLASH_BASE + pagenum * SAMV_PAGE_SIZE;
int r;
- LOG_DEBUG("write page %u at address 0x%08x", pagenum, (unsigned int)addr);
+ LOG_DEBUG("write page %u at address 0x%08" PRIx32 "", pagenum, addr);
r = target_write_memory(target, addr, 4, SAMV_PAGE_SIZE / 4, buf);
if (r != ERROR_OK) {
- LOG_ERROR("failed to buffer page at 0x%08x", (unsigned int)addr);
+ LOG_ERROR("failed to buffer page at 0x%08" PRIx32 "", addr);
return r;
}
r = samv_efc_perform_command(target, SAMV_EFC_FCMD_WP, pagenum, &status);
if (r != ERROR_OK)
- LOG_ERROR("error performing write page at 0x%08x", (unsigned int)addr);
+ LOG_ERROR("error performing write page at 0x%08" PRIx32 "", addr);
if (status & (1 << 2)) {
- LOG_ERROR("page at 0x%08x is locked", (unsigned int)addr);
+ LOG_ERROR("page at 0x%08" PRIx32 " is locked", addr);
return ERROR_FAIL;
}
if (status & (1 << 1)) {
- LOG_ERROR("flash command error at 0x%08x", (unsigned int)addr);
+ LOG_ERROR("flash command error at 0x%08" PRIx32 "", addr);
return ERROR_FAIL;
}
return ERROR_OK;
}
+static int samv_page_write(struct target *target,
+ target_addr_t base, unsigned int pagenum, const uint8_t *buf)
+{
+ int r;
+ if (base == SAMV_FLASH_SIGNATURE_BASE)
+ r = samv_write_user_signature(target, pagenum, buf);
+ else
+ r = samv_write_standard_page(target, pagenum, buf);
+
+ return r;
+}
+
+static int samv_read(struct flash_bank *bank, uint8_t *buffer,
+ uint32_t offset, uint32_t count)
+{
+ int r;
+ uint8_t pagebuffer[SAMV_PAGE_SIZE] = {0};
+ struct target *target = bank->target;
+
+ LOG_DEBUG("offset=0x%08" PRIx32 " count=0x%08" PRIx32 "", offset, count);
+
+ if (target->state != TARGET_HALTED) {
+ LOG_ERROR("Target not halted");
+ return ERROR_TARGET_NOT_HALTED;
+ }
+
+ if (offset + count > bank->size) {
+ LOG_WARNING("Reads past end of flash. Extra data discarded.");
+ count = bank->size - offset;
+ }
+
+ LOG_DEBUG("offset: 0x%08" PRIx32 ", count: 0x%08" PRIx32 "", offset, count);
+
+ if (bank->base == SAMV_FLASH_SIGNATURE_BASE) {
+ r = samv_read_user_signature(target, pagebuffer);
+ if (r != ERROR_OK)
+ return r;
+ memcpy(buffer, pagebuffer + offset, count);
+ } else {
+ r = target_read_memory(target, offset, 1, count, buffer);
+ if (r != ERROR_OK)
+ return r;
+ }
+
+ return ERROR_OK;
+}
+
static int samv_write(struct flash_bank *bank, const uint8_t *buffer,
uint32_t offset, uint32_t count)
{
@@ -470,10 +687,10 @@ static int samv_write(struct flash_bank *bank, const uint8_t *buffer,
if ((offset + count) > bank->size) {
LOG_ERROR("flash write error - past end of bank");
- LOG_ERROR(" offset: 0x%08x, count 0x%08x, bank end: 0x%08x",
- (unsigned int)(offset),
- (unsigned int)(count),
- (unsigned int)(bank->size));
+ LOG_ERROR(" offset: 0x%08" PRIx32 ", count 0x%08" PRIx32 ", bank end: 0x%08" PRIx32 "",
+ offset,
+ count,
+ bank->size);
return ERROR_FAIL;
}
@@ -481,9 +698,8 @@ static int samv_write(struct flash_bank *bank, const uint8_t *buffer,
uint32_t page_cur = offset / SAMV_PAGE_SIZE;
uint32_t page_end = (offset + count - 1) / SAMV_PAGE_SIZE;
- LOG_DEBUG("offset: 0x%08x, count: 0x%08x",
- (unsigned int)(offset), (unsigned int)(count));
- LOG_DEBUG("page start: %d, page end: %d", (int)(page_cur), (int)(page_end));
+ LOG_DEBUG("offset: 0x%08" PRIx32 ", count: 0x%08" PRIx32 "", offset, count);
+ LOG_DEBUG("page start: %" PRIu32 ", page end: %" PRIu32 "", page_cur, page_end);
/* Special case: all one page */
/* Otherwise: */
@@ -497,14 +713,14 @@ static int samv_write(struct flash_bank *bank, const uint8_t *buffer,
/* handle special case - all one page. */
if (page_cur == page_end) {
LOG_DEBUG("special case, all in one page");
- r = samv_page_read(bank->target, page_cur, pagebuffer);
+ r = samv_page_read(bank->target, bank->base, page_cur, pagebuffer);
if (r != ERROR_OK)
return r;
- page_offset = offset & (SAMV_PAGE_SIZE-1);
+ page_offset = offset & (SAMV_PAGE_SIZE - 1);
memcpy(pagebuffer + page_offset, buffer, count);
- r = samv_page_write(bank->target, page_cur, pagebuffer);
+ r = samv_page_write(bank->target, bank->base, page_cur, pagebuffer);
if (r != ERROR_OK)
return r;
return ERROR_OK;
@@ -515,7 +731,7 @@ static int samv_write(struct flash_bank *bank, const uint8_t *buffer,
if (page_offset) {
LOG_DEBUG("non-aligned start");
/* read the partial page */
- r = samv_page_read(bank->target, page_cur, pagebuffer);
+ r = samv_page_read(bank->target, bank->base, page_cur, pagebuffer);
if (r != ERROR_OK)
return r;
@@ -523,11 +739,11 @@ static int samv_write(struct flash_bank *bank, const uint8_t *buffer,
uint32_t n = SAMV_PAGE_SIZE - page_offset;
memcpy(pagebuffer + page_offset, buffer, n);
- r = samv_page_write(bank->target, page_cur, pagebuffer);
+ r = samv_page_write(bank->target, bank->base, page_cur, pagebuffer);
if (r != ERROR_OK)
return r;
- count -= n;
+ count -= n;
offset += n;
buffer += n;
page_cur++;
@@ -537,11 +753,11 @@ static int samv_write(struct flash_bank *bank, const uint8_t *buffer,
assert(offset % SAMV_PAGE_SIZE == 0);
/* step 2) handle the full pages */
- LOG_DEBUG("full page loop: cur=%d, end=%d, count = 0x%08x",
- (int)page_cur, (int)page_end, (unsigned int)(count));
+ LOG_DEBUG("full page loop: cur=%" PRIu32 ", end=%" PRIu32 ", count = 0x%08" PRIx32 "",
+ page_cur, page_end, count);
while ((page_cur < page_end) && (count >= SAMV_PAGE_SIZE)) {
- r = samv_page_write(bank->target, page_cur, buffer);
+ r = samv_page_write(bank->target, bank->base, page_cur, buffer);
if (r != ERROR_OK)
return r;
count -= SAMV_PAGE_SIZE;
@@ -551,13 +767,13 @@ static int samv_write(struct flash_bank *bank, const uint8_t *buffer,
/* step 3) write final page, if it's partial (otherwise it's already done) */
if (count) {
- LOG_DEBUG("final partial page, count = 0x%08x", (unsigned int)(count));
+ LOG_DEBUG("final partial page, count = 0x%08" PRIx32 "", count);
/* we have a partial page */
- r = samv_page_read(bank->target, page_cur, pagebuffer);
+ r = samv_page_read(bank->target, bank->base, page_cur, pagebuffer);
if (r != ERROR_OK)
return r;
memcpy(pagebuffer, buffer, count); /* data goes at start of page */
- r = samv_page_write(bank->target, page_cur, pagebuffer);
+ r = samv_page_write(bank->target, bank->base, page_cur, pagebuffer);
if (r != ERROR_OK)
return r;
}
@@ -600,22 +816,22 @@ COMMAND_HANDLER(samv_handle_gpnvm_command)
int who = 0;
switch (CMD_ARGC) {
- case 0:
- goto showall;
- case 1:
+ case 0:
+ goto showall;
+ case 1:
+ who = -1;
+ break;
+ case 2:
+ if (!strcmp(CMD_ARGV[0], "show") && !strcmp(CMD_ARGV[1], "all")) {
who = -1;
- break;
- case 2:
- if (!strcmp(CMD_ARGV[0], "show") && !strcmp(CMD_ARGV[1], "all"))
- who = -1;
- else {
- uint32_t v32;
- COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], v32);
- who = v32;
- }
- break;
- default:
- return ERROR_COMMAND_SYNTAX_ERROR;
+ } else {
+ uint32_t v32;
+ COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], v32);
+ who = v32;
+ }
+ break;
+ default:
+ return ERROR_COMMAND_SYNTAX_ERROR;
}
unsigned int v = 0;
@@ -691,7 +907,7 @@ const struct flash_driver atsamv_flash = {
.erase = samv_erase,
.protect = samv_protect,
.write = samv_write,
- .read = default_flash_read,
+ .read = samv_read,
.probe = samv_probe,
.auto_probe = samv_auto_probe,
.erase_check = default_flash_blank_check,
diff --git a/src/flash/nor/avrf.c b/src/flash/nor/avrf.c
index 1d317a10c6..af83822490 100644
--- a/src/flash/nor/avrf.c
+++ b/src/flash/nor/avrf.c
@@ -126,7 +126,7 @@ static int avr_jtagprg_chiperase(struct avr_common *avr)
AVR_JTAG_REG_PROGRAMMING_COMMAND_LEN);
if (mcu_execute_queue() != ERROR_OK)
return ERROR_FAIL;
- LOG_DEBUG("poll_value = 0x%04" PRIx32 "", poll_value);
+ LOG_DEBUG("poll_value = 0x%04" PRIx32, poll_value);
} while (!(poll_value & 0x0200));
return ERROR_OK;
@@ -187,7 +187,7 @@ static int avr_jtagprg_writeflashpage(struct avr_common *avr,
AVR_JTAG_REG_PROGRAMMING_COMMAND_LEN);
if (mcu_execute_queue() != ERROR_OK)
return ERROR_FAIL;
- LOG_DEBUG("poll_value = 0x%04" PRIx32 "", poll_value);
+ LOG_DEBUG("poll_value = 0x%04" PRIx32, poll_value);
} while (!(poll_value & 0x0200));
return ERROR_OK;
@@ -253,8 +253,8 @@ static int avrf_write(struct flash_bank *bank, const uint8_t *buffer, uint32_t o
return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
}
- LOG_DEBUG("offset is 0x%08" PRIx32 "", offset);
- LOG_DEBUG("count is %" PRIu32 "", count);
+ LOG_DEBUG("offset is 0x%08" PRIx32, offset);
+ LOG_DEBUG("count is %" PRIu32, count);
if (avr_jtagprg_enterprogmode(avr) != ERROR_OK)
return ERROR_FAIL;
@@ -308,7 +308,7 @@ static int avrf_probe(struct flash_bank *bank)
if (mcu_execute_queue() != ERROR_OK)
return ERROR_FAIL;
- LOG_INFO("device id = 0x%08" PRIx32 "", device_id);
+ LOG_INFO("device id = 0x%08" PRIx32, device_id);
if (EXTRACT_MFG(device_id) != 0x1F)
LOG_ERROR("0x%" PRIx32 " is invalid Manufacturer for avr, 0x%X is expected",
EXTRACT_MFG(device_id),
@@ -373,7 +373,7 @@ static int avrf_info(struct flash_bank *bank, struct command_invocation *cmd)
if (mcu_execute_queue() != ERROR_OK)
return ERROR_FAIL;
- LOG_INFO("device id = 0x%08" PRIx32 "", device_id);
+ LOG_INFO("device id = 0x%08" PRIx32, device_id);
if (EXTRACT_MFG(device_id) != 0x1F)
LOG_ERROR("0x%" PRIx32 " is invalid Manufacturer for avr, 0x%X is expected",
EXTRACT_MFG(device_id),
@@ -390,7 +390,7 @@ static int avrf_info(struct flash_bank *bank, struct command_invocation *cmd)
if (avr_info) {
/* chip found */
- command_print_sameline(cmd, "%s - Rev: 0x%" PRIx32 "", avr_info->name,
+ command_print_sameline(cmd, "%s - Rev: 0x%" PRIx32, avr_info->name,
EXTRACT_VER(device_id));
return ERROR_OK;
} else {
diff --git a/src/flash/nor/bluenrg-x.c b/src/flash/nor/bluenrg-x.c
index 9ced2e9718..ccbbcc66eb 100644
--- a/src/flash/nor/bluenrg-x.c
+++ b/src/flash/nor/bluenrg-x.c
@@ -19,6 +19,7 @@
#define BLUENRG2_JTAG_REG (flash_priv_data_2.jtag_idcode_reg)
#define BLUENRGLP_JTAG_REG (flash_priv_data_lp.jtag_idcode_reg)
+#define BLUENRGLPF_JTAG_REG (flash_priv_data_lpf.jtag_idcode_reg)
#define DIE_ID_REG(bluenrgx_info) (bluenrgx_info->flash_ptr->die_id_reg)
#define JTAG_IDCODE_REG(bluenrgx_info) (bluenrgx_info->flash_ptr->jtag_idcode_reg)
@@ -63,7 +64,7 @@ static const struct flash_ctrl_priv_data flash_priv_data_lp = {
.flash_regs_base = 0x40001000,
.flash_page_size = 2048,
.jtag_idcode = 0x0201E041,
- .part_name = "BLUENRG-LP",
+ .part_name = "STM32WB07 (BLUENRG-LP)",
};
static const struct flash_ctrl_priv_data flash_priv_data_lps = {
@@ -73,7 +74,17 @@ static const struct flash_ctrl_priv_data flash_priv_data_lps = {
.flash_regs_base = 0x40001000,
.flash_page_size = 2048,
.jtag_idcode = 0x02028041,
- .part_name = "BLUENRG-LPS",
+ .part_name = "STM32WB05 (BLUENRG-LPS)",
+};
+
+static const struct flash_ctrl_priv_data flash_priv_data_lpf = {
+ .die_id_reg = 0x40000000,
+ .jtag_idcode_reg = 0x40000004,
+ .flash_base = 0x10040000,
+ .flash_regs_base = 0x40001000,
+ .flash_page_size = 2048,
+ .jtag_idcode = 0x02032041,
+ .part_name = "STM32WB09 (BLUENRG-LPF)",
};
struct bluenrgx_flash_bank {
@@ -86,7 +97,9 @@ static const struct flash_ctrl_priv_data *flash_ctrl[] = {
&flash_priv_data_1,
&flash_priv_data_2,
&flash_priv_data_lp,
- &flash_priv_data_lps};
+ &flash_priv_data_lps,
+ &flash_priv_data_lpf
+};
/* flash_bank bluenrg-x 0 0 0 0 */
FLASH_BANK_COMMAND_HANDLER(bluenrgx_flash_bank_command)
@@ -130,8 +143,45 @@ static inline int bluenrgx_write_flash_reg(struct flash_bank *bank, uint32_t reg
return target_write_u32(bank->target, bluenrgx_get_flash_reg(bank, reg_offset), value);
}
-static int bluenrgx_erase(struct flash_bank *bank, unsigned int first,
- unsigned int last)
+static int bluenrgx_wait_for_interrupt(struct flash_bank *bank, uint32_t interrupt_flag)
+{
+ bool flag_raised = false;
+ for (unsigned int j = 0; j < 100; j++) {
+ uint32_t value;
+ if (bluenrgx_read_flash_reg(bank, FLASH_REG_IRQRAW, &value) != ERROR_OK) {
+ LOG_ERROR("Register read failed");
+ return ERROR_FAIL;
+ }
+
+ if (value & interrupt_flag) {
+ flag_raised = true;
+ break;
+ }
+ }
+
+ /* clear the interrupt */
+ if (flag_raised) {
+ if (bluenrgx_write_flash_reg(bank, FLASH_REG_IRQRAW, interrupt_flag) != ERROR_OK) {
+ LOG_ERROR("Cannot clear interrupt flag");
+ return ERROR_FAIL;
+ }
+
+ return ERROR_OK;
+ }
+
+ LOG_ERROR("Erase command failed (timeout)");
+ return ERROR_TIMEOUT_REACHED;
+}
+
+static inline int bluenrgx_wait_for_command(struct flash_bank *bank)
+{
+ if (bluenrgx_wait_for_interrupt(bank, FLASH_INT_CMDSTART) == ERROR_OK)
+ return bluenrgx_wait_for_interrupt(bank, FLASH_INT_CMDDONE);
+
+ return ERROR_FAIL;
+}
+
+static int bluenrgx_erase(struct flash_bank *bank, unsigned int first, unsigned int last)
{
int retval = ERROR_OK;
struct bluenrgx_flash_bank *bluenrgx_info = bank->driver_priv;
@@ -173,19 +223,8 @@ static int bluenrgx_erase(struct flash_bank *bank, unsigned int first,
return ERROR_FAIL;
}
- for (unsigned int i = 0; i < 100; i++) {
- uint32_t value;
- if (bluenrgx_read_flash_reg(bank, FLASH_REG_IRQRAW, &value)) {
- LOG_ERROR("Register write failed");
- return ERROR_FAIL;
- }
- if (value & FLASH_INT_CMDDONE)
- break;
- if (i == 99) {
- LOG_ERROR("Mass erase command failed (timeout)");
- retval = ERROR_FAIL;
- }
- }
+ if (bluenrgx_wait_for_command(bank) != ERROR_OK)
+ return ERROR_FAIL;
} else {
command = FLASH_CMD_ERASE_PAGE;
@@ -209,19 +248,8 @@ static int bluenrgx_erase(struct flash_bank *bank, unsigned int first,
return ERROR_FAIL;
}
- for (unsigned int j = 0; j < 100; j++) {
- uint32_t value;
- if (bluenrgx_read_flash_reg(bank, FLASH_REG_IRQRAW, &value)) {
- LOG_ERROR("Register write failed");
- return ERROR_FAIL;
- }
- if (value & FLASH_INT_CMDDONE)
- break;
- if (j == 99) {
- LOG_ERROR("Erase command failed (timeout)");
- retval = ERROR_FAIL;
- }
- }
+ if (bluenrgx_wait_for_command(bank) != ERROR_OK)
+ return ERROR_FAIL;
}
}
@@ -229,7 +257,7 @@ static int bluenrgx_erase(struct flash_bank *bank, unsigned int first,
}
-static int bluenrgx_write(struct flash_bank *bank, const uint8_t *buffer,
+static int bluenrgx_write_with_loader(struct flash_bank *bank, const uint8_t *buffer,
uint32_t offset, uint32_t count)
{
struct bluenrgx_flash_bank *bluenrgx_info = bank->driver_priv;
@@ -251,22 +279,6 @@ static int bluenrgx_write(struct flash_bank *bank, const uint8_t *buffer,
#include "../../../contrib/loaders/flash/bluenrg-x/bluenrg-x_write.inc"
};
- /* check preconditions */
- if (!bluenrgx_info->probed)
- return ERROR_FLASH_BANK_NOT_PROBED;
-
- if ((offset + count) > bank->size) {
- LOG_ERROR("Requested write past beyond of flash size: (offset+count) = %" PRIu32 ", size=%" PRIu32,
- (offset + count),
- bank->size);
- return ERROR_FLASH_DST_OUT_OF_BANK;
- }
-
- if (bank->target->state != TARGET_HALTED) {
- LOG_ERROR("Target not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
if (target_alloc_working_area(target, sizeof(bluenrgx_flash_write_code),
&write_algorithm) != ERROR_OK) {
LOG_WARNING("no working area available, can't do block memory writes");
@@ -302,10 +314,10 @@ static int bluenrgx_write(struct flash_bank *bank, const uint8_t *buffer,
init_reg_param(®_params[4], "sp", 32, PARAM_OUT);
/* Put the 4th parameter at the location in the stack frame of target write() function.
* See contrib/loaders/flash/bluenrg-x/bluenrg-x_write.lst
- * 34 ldr r6, [sp, #80]
+ * 34 ldr r6, [sp, #88]
* ^^^ offset
*/
- init_mem_param(&mem_params[0], write_algorithm_stack->address + 80, 32, PARAM_OUT);
+ init_mem_param(&mem_params[0], write_algorithm_stack->address + 88, 32, PARAM_OUT);
/* Stack for target write algorithm - target write() function has
* __attribute__((naked)) so it does not setup the new stack frame.
* Therefore the stack frame uses the area from SP upwards!
@@ -353,6 +365,7 @@ static int bluenrgx_write(struct flash_bank *bank, const uint8_t *buffer,
if (error != 0)
LOG_ERROR("flash write failed = %08" PRIx32, error);
}
+
if (retval == ERROR_OK) {
uint32_t rp;
/* Read back rp and check that is valid */
@@ -364,6 +377,7 @@ static int bluenrgx_write(struct flash_bank *bank, const uint8_t *buffer,
}
}
}
+
target_free_working_area(target, source);
target_free_working_area(target, write_algorithm);
target_free_working_area(target, write_algorithm_stack);
@@ -378,6 +392,80 @@ static int bluenrgx_write(struct flash_bank *bank, const uint8_t *buffer,
return retval;
}
+static int bluenrgx_write_without_loader(struct flash_bank *bank, const uint8_t *buffer,
+ uint32_t offset, uint32_t count)
+{
+ struct target *target = bank->target;
+ unsigned int data_count = count / FLASH_DATA_WIDTH;
+
+ while (data_count--) {
+ /* clear flags */
+ if (bluenrgx_write_flash_reg(bank, FLASH_REG_IRQRAW, 0x3f) != ERROR_OK) {
+ LOG_ERROR("Register write failed");
+ return ERROR_FAIL;
+ }
+
+ if (bluenrgx_write_flash_reg(bank, FLASH_REG_ADDRESS, offset >> 2) != ERROR_OK) {
+ LOG_ERROR("Register write failed");
+ return ERROR_FAIL;
+ }
+
+ if (target_write_memory(target, bluenrgx_get_flash_reg(bank, FLASH_REG_DATA0),
+ FLASH_WORD_LEN, FLASH_DATA_WIDTH_W, buffer) != ERROR_OK) {
+ LOG_ERROR("Failed to write data");
+ return ERROR_FAIL;
+ }
+
+ if (bluenrgx_write_flash_reg(bank, FLASH_REG_COMMAND, FLASH_CMD_BURSTWRITE) != ERROR_OK) {
+ LOG_ERROR("Failed");
+ return ERROR_FAIL;
+ }
+
+ if (bluenrgx_wait_for_command(bank) != ERROR_OK)
+ return ERROR_FAIL;
+
+ /* increment offset, and buffer */
+ offset += FLASH_DATA_WIDTH;
+ buffer += FLASH_DATA_WIDTH;
+ }
+
+ return ERROR_OK;
+}
+
+static int bluenrgx_write(struct flash_bank *bank, const uint8_t *buffer,
+ uint32_t offset, uint32_t count)
+{
+ struct bluenrgx_flash_bank *bluenrgx_info = bank->driver_priv;
+ int retval = ERROR_OK;
+
+ /* check preconditions */
+ if (!bluenrgx_info->probed)
+ return ERROR_FLASH_BANK_NOT_PROBED;
+
+ if ((offset + count) > bank->size) {
+ LOG_ERROR("Requested write past beyond of flash size: (offset+count) = %" PRIu32 ", size=%" PRIu32,
+ (offset + count),
+ bank->size);
+ return ERROR_FLASH_DST_OUT_OF_BANK;
+ }
+
+ if (bank->target->state != TARGET_HALTED) {
+ LOG_ERROR("Target not halted");
+ return ERROR_TARGET_NOT_HALTED;
+ }
+
+ assert(offset % FLASH_WORD_LEN == 0);
+ assert(count % FLASH_WORD_LEN == 0);
+
+ retval = bluenrgx_write_with_loader(bank, buffer, offset, count);
+ /* if resources are not available write without a loader */
+ if (retval == ERROR_TARGET_RESOURCE_NOT_AVAILABLE) {
+ LOG_WARNING("falling back to programming without a flash loader (slower)");
+ retval = bluenrgx_write_without_loader(bank, buffer, offset, count);
+ }
+ return retval;
+}
+
static int bluenrgx_probe(struct flash_bank *bank)
{
struct bluenrgx_flash_bank *bluenrgx_info = bank->driver_priv;
@@ -387,7 +475,8 @@ static int bluenrgx_probe(struct flash_bank *bank)
if (retval != ERROR_OK)
return retval;
- if ((idcode != flash_priv_data_lp.jtag_idcode) && (idcode != flash_priv_data_lps.jtag_idcode)) {
+ if (idcode != flash_priv_data_lp.jtag_idcode && idcode != flash_priv_data_lps.jtag_idcode
+ && idcode != flash_priv_data_lpf.jtag_idcode) {
retval = target_read_u32(bank->target, BLUENRG2_JTAG_REG, &idcode);
if (retval != ERROR_OK)
return retval;
@@ -414,7 +503,7 @@ static int bluenrgx_probe(struct flash_bank *bank)
return retval;
bank->size = (size_info + 1) * FLASH_WORD_LEN;
- bank->num_sectors = bank->size/FLASH_PAGE_SIZE(bluenrgx_info);
+ bank->num_sectors = bank->size / FLASH_PAGE_SIZE(bluenrgx_info);
bank->sectors = realloc(bank->sectors, sizeof(struct flash_sector) * bank->num_sectors);
for (unsigned int i = 0; i < bank->num_sectors; i++) {
diff --git a/src/flash/nor/bluenrg-x.h b/src/flash/nor/bluenrg-x.h
index 720cb6e618..03c66cd81a 100644
--- a/src/flash/nor/bluenrg-x.h
+++ b/src/flash/nor/bluenrg-x.h
@@ -28,7 +28,12 @@
#define FLASH_CMD_WRITE 0x33
#define FLASH_CMD_BURSTWRITE 0xCC
#define FLASH_INT_CMDDONE 0x01
+#define FLASH_INT_CMDSTART 0x02
+/* Flash Controller constants */
#define FLASH_WORD_LEN 4
+#define FLASH_DATA_WIDTH_W 4
+#define FLASH_DATA_WIDTH 16
+
#endif /* OPENOCD_FLASH_NOR_BLUENRGX_H */
diff --git a/src/flash/nor/cc26xx.c b/src/flash/nor/cc26xx.c
index 54d61421ce..f7c2011beb 100644
--- a/src/flash/nor/cc26xx.c
+++ b/src/flash/nor/cc26xx.c
@@ -51,22 +51,22 @@ static uint32_t cc26xx_device_type(uint32_t icepick_id, uint32_t user_id)
uint32_t device_type = 0;
switch (icepick_id & ICEPICK_ID_MASK) {
- case CC26X0_ICEPICK_ID:
- device_type = CC26X0_TYPE;
- break;
- case CC26X1_ICEPICK_ID:
- device_type = CC26X1_TYPE;
- break;
- case CC13X0_ICEPICK_ID:
- device_type = CC13X0_TYPE;
- break;
- case CC13X2_CC26X2_ICEPICK_ID:
- default:
- if ((user_id & USER_ID_CC13_MASK) != 0)
- device_type = CC13X2_TYPE;
- else
- device_type = CC26X2_TYPE;
- break;
+ case CC26X0_ICEPICK_ID:
+ device_type = CC26X0_TYPE;
+ break;
+ case CC26X1_ICEPICK_ID:
+ device_type = CC26X1_TYPE;
+ break;
+ case CC13X0_ICEPICK_ID:
+ device_type = CC13X0_TYPE;
+ break;
+ case CC13X2_CC26X2_ICEPICK_ID:
+ default:
+ if ((user_id & USER_ID_CC13_MASK) != 0)
+ device_type = CC13X2_TYPE;
+ else
+ device_type = CC26X2_TYPE;
+ break;
}
return device_type;
@@ -77,17 +77,17 @@ static uint32_t cc26xx_sector_length(uint32_t icepick_id)
uint32_t sector_length;
switch (icepick_id & ICEPICK_ID_MASK) {
- case CC26X0_ICEPICK_ID:
- case CC26X1_ICEPICK_ID:
- case CC13X0_ICEPICK_ID:
- /* Chameleon family device */
- sector_length = CC26X0_SECTOR_LENGTH;
- break;
- case CC13X2_CC26X2_ICEPICK_ID:
- default:
- /* Agama family device */
- sector_length = CC26X2_SECTOR_LENGTH;
- break;
+ case CC26X0_ICEPICK_ID:
+ case CC26X1_ICEPICK_ID:
+ case CC13X0_ICEPICK_ID:
+ /* Chameleon family device */
+ sector_length = CC26X0_SECTOR_LENGTH;
+ break;
+ case CC13X2_CC26X2_ICEPICK_ID:
+ default:
+ /* Agama family device */
+ sector_length = CC26X2_SECTOR_LENGTH;
+ break;
}
return sector_length;
@@ -112,10 +112,10 @@ static int cc26xx_wait_algo_done(struct flash_bank *bank, uint32_t params_addr)
return retval;
elapsed_ms = timeval_ms() - start_ms;
- if (elapsed_ms > 500)
- keep_alive();
if (elapsed_ms > FLASH_TIMEOUT)
break;
+
+ keep_alive();
};
if (status != CC26XX_BUFFER_EMPTY) {
@@ -321,8 +321,6 @@ static int cc26xx_write(struct flash_bank *bank, const uint8_t *buffer,
struct cc26xx_bank *cc26xx_bank = bank->driver_priv;
struct cc26xx_algo_params algo_params[2];
uint32_t size = 0;
- long long start_ms;
- long long elapsed_ms;
uint32_t address;
uint32_t index;
@@ -343,7 +341,6 @@ static int cc26xx_write(struct flash_bank *bank, const uint8_t *buffer,
/* Write requested data, ping-ponging between two buffers */
index = 0;
- start_ms = timeval_ms();
address = bank->base + offset;
while (count > 0) {
@@ -381,9 +378,7 @@ static int cc26xx_write(struct flash_bank *bank, const uint8_t *buffer,
buffer += size;
address += size;
- elapsed_ms = timeval_ms() - start_ms;
- if (elapsed_ms > 500)
- keep_alive();
+ keep_alive();
}
/* If no error yet, wait for last buffer to finish */
@@ -427,31 +422,31 @@ static int cc26xx_probe(struct flash_bank *bank)
/* Set up appropriate flash helper algorithm */
switch (cc26xx_bank->icepick_id & ICEPICK_ID_MASK) {
- case CC26X0_ICEPICK_ID:
- case CC26X1_ICEPICK_ID:
- case CC13X0_ICEPICK_ID:
- /* Chameleon family device */
- cc26xx_bank->algo_code = cc26x0_algo;
- cc26xx_bank->algo_size = sizeof(cc26x0_algo);
- cc26xx_bank->algo_working_size = CC26X0_WORKING_SIZE;
- cc26xx_bank->buffer_addr[0] = CC26X0_ALGO_BUFFER_0;
- cc26xx_bank->buffer_addr[1] = CC26X0_ALGO_BUFFER_1;
- cc26xx_bank->params_addr[0] = CC26X0_ALGO_PARAMS_0;
- cc26xx_bank->params_addr[1] = CC26X0_ALGO_PARAMS_1;
- max_sectors = CC26X0_MAX_SECTORS;
- break;
- case CC13X2_CC26X2_ICEPICK_ID:
- default:
- /* Agama family device */
- cc26xx_bank->algo_code = cc26x2_algo;
- cc26xx_bank->algo_size = sizeof(cc26x2_algo);
- cc26xx_bank->algo_working_size = CC26X2_WORKING_SIZE;
- cc26xx_bank->buffer_addr[0] = CC26X2_ALGO_BUFFER_0;
- cc26xx_bank->buffer_addr[1] = CC26X2_ALGO_BUFFER_1;
- cc26xx_bank->params_addr[0] = CC26X2_ALGO_PARAMS_0;
- cc26xx_bank->params_addr[1] = CC26X2_ALGO_PARAMS_1;
- max_sectors = CC26X2_MAX_SECTORS;
- break;
+ case CC26X0_ICEPICK_ID:
+ case CC26X1_ICEPICK_ID:
+ case CC13X0_ICEPICK_ID:
+ /* Chameleon family device */
+ cc26xx_bank->algo_code = cc26x0_algo;
+ cc26xx_bank->algo_size = sizeof(cc26x0_algo);
+ cc26xx_bank->algo_working_size = CC26X0_WORKING_SIZE;
+ cc26xx_bank->buffer_addr[0] = CC26X0_ALGO_BUFFER_0;
+ cc26xx_bank->buffer_addr[1] = CC26X0_ALGO_BUFFER_1;
+ cc26xx_bank->params_addr[0] = CC26X0_ALGO_PARAMS_0;
+ cc26xx_bank->params_addr[1] = CC26X0_ALGO_PARAMS_1;
+ max_sectors = CC26X0_MAX_SECTORS;
+ break;
+ case CC13X2_CC26X2_ICEPICK_ID:
+ default:
+ /* Agama family device */
+ cc26xx_bank->algo_code = cc26x2_algo;
+ cc26xx_bank->algo_size = sizeof(cc26x2_algo);
+ cc26xx_bank->algo_working_size = CC26X2_WORKING_SIZE;
+ cc26xx_bank->buffer_addr[0] = CC26X2_ALGO_BUFFER_0;
+ cc26xx_bank->buffer_addr[1] = CC26X2_ALGO_BUFFER_1;
+ cc26xx_bank->params_addr[0] = CC26X2_ALGO_PARAMS_0;
+ cc26xx_bank->params_addr[1] = CC26X2_ALGO_PARAMS_1;
+ max_sectors = CC26X2_MAX_SECTORS;
+ break;
}
retval = target_read_u32(target, CC26XX_FLASH_SIZE_INFO, &value);
@@ -505,25 +500,25 @@ static int cc26xx_info(struct flash_bank *bank, struct command_invocation *cmd)
const char *device;
switch (cc26xx_bank->device_type) {
- case CC26X0_TYPE:
- device = "CC26x0";
- break;
- case CC26X1_TYPE:
- device = "CC26x1";
- break;
- case CC13X0_TYPE:
- device = "CC13x0";
- break;
- case CC13X2_TYPE:
- device = "CC13x2";
- break;
- case CC26X2_TYPE:
- device = "CC26x2";
- break;
- case CC26XX_NO_TYPE:
- default:
- device = "Unrecognized";
- break;
+ case CC26X0_TYPE:
+ device = "CC26x0";
+ break;
+ case CC26X1_TYPE:
+ device = "CC26x1";
+ break;
+ case CC13X0_TYPE:
+ device = "CC13x0";
+ break;
+ case CC13X2_TYPE:
+ device = "CC13x2";
+ break;
+ case CC26X2_TYPE:
+ device = "CC26x2";
+ break;
+ case CC26XX_NO_TYPE:
+ default:
+ device = "Unrecognized";
+ break;
}
command_print_sameline(cmd,
diff --git a/src/flash/nor/cc3220sf.c b/src/flash/nor/cc3220sf.c
index 74cb7aea57..0418aeac2b 100644
--- a/src/flash/nor/cc3220sf.c
+++ b/src/flash/nor/cc3220sf.c
@@ -65,10 +65,10 @@ static int cc3220sf_mass_erase(struct flash_bank *bank)
done = true;
} else {
elapsed_ms = timeval_ms() - start_ms;
- if (elapsed_ms > 500)
- keep_alive();
if (elapsed_ms > FLASH_TIMEOUT)
break;
+
+ keep_alive();
}
}
@@ -152,10 +152,10 @@ static int cc3220sf_erase(struct flash_bank *bank, unsigned int first,
done = true;
} else {
elapsed_ms = timeval_ms() - start_ms;
- if (elapsed_ms > 500)
- keep_alive();
if (elapsed_ms > FLASH_TIMEOUT)
break;
+
+ keep_alive();
}
}
diff --git a/src/flash/nor/cfi.c b/src/flash/nor/cfi.c
index 2a15e49132..108b66750c 100644
--- a/src/flash/nor/cfi.c
+++ b/src/flash/nor/cfi.c
@@ -945,14 +945,14 @@ int cfi_erase(struct flash_bank *bank, unsigned int first,
return ERROR_FLASH_BANK_NOT_PROBED;
switch (cfi_info->pri_id) {
- case 1:
- case 3:
- return cfi_intel_erase(bank, first, last);
- case 2:
- return cfi_spansion_erase(bank, first, last);
- default:
- LOG_ERROR("cfi primary command set %i unsupported", cfi_info->pri_id);
- break;
+ case 1:
+ case 3:
+ return cfi_intel_erase(bank, first, last);
+ case 2:
+ return cfi_spansion_erase(bank, first, last);
+ default:
+ LOG_ERROR("cfi primary command set %i unsupported", cfi_info->pri_id);
+ break;
}
return ERROR_OK;
@@ -1084,12 +1084,12 @@ int cfi_protect(struct flash_bank *bank, int set, unsigned int first,
return ERROR_FLASH_BANK_NOT_PROBED;
switch (cfi_info->pri_id) {
- case 1:
- case 3:
- return cfi_intel_protect(bank, set, first, last);
- default:
- LOG_WARNING("protect: cfi primary command set %i unsupported", cfi_info->pri_id);
- return ERROR_OK;
+ case 1:
+ case 3:
+ return cfi_intel_protect(bank, set, first, last);
+ default:
+ LOG_WARNING("protect: cfi primary command set %i unsupported", cfi_info->pri_id);
+ return ERROR_OK;
}
}
@@ -1100,16 +1100,16 @@ static uint32_t cfi_command_val(struct flash_bank *bank, uint8_t cmd)
uint8_t buf[CFI_MAX_BUS_WIDTH];
cfi_command(bank, cmd, buf);
switch (bank->bus_width) {
- case 1:
- return buf[0];
- case 2:
- return target_buffer_get_u16(target, buf);
- case 4:
- return target_buffer_get_u32(target, buf);
- default:
- LOG_ERROR("Unsupported bank buswidth %u, can't do block memory writes",
- bank->bus_width);
- return 0;
+ case 1:
+ return buf[0];
+ case 2:
+ return target_buffer_get_u16(target, buf);
+ case 4:
+ return target_buffer_get_u32(target, buf);
+ default:
+ LOG_ERROR("Unsupported bank buswidth %u, can't do block memory writes",
+ bank->bus_width);
+ return 0;
}
}
@@ -1214,22 +1214,22 @@ static int cfi_intel_write_block(struct flash_bank *bank, const uint8_t *buffer,
/* prepare algorithm code for target endian */
switch (bank->bus_width) {
- case 1:
- target_code_src = word_8_code;
- target_code_size = sizeof(word_8_code);
- break;
- case 2:
- target_code_src = word_16_code;
- target_code_size = sizeof(word_16_code);
- break;
- case 4:
- target_code_src = word_32_code;
- target_code_size = sizeof(word_32_code);
- break;
- default:
- LOG_ERROR("Unsupported bank buswidth %u, can't do block memory writes",
- bank->bus_width);
- return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
+ case 1:
+ target_code_src = word_8_code;
+ target_code_size = sizeof(word_8_code);
+ break;
+ case 2:
+ target_code_src = word_16_code;
+ target_code_size = sizeof(word_16_code);
+ break;
+ case 4:
+ target_code_src = word_32_code;
+ target_code_size = sizeof(word_32_code);
+ break;
+ default:
+ LOG_ERROR("Unsupported bank buswidth %u, can't do block memory writes",
+ bank->bus_width);
+ return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
}
/* flash write code */
@@ -1448,22 +1448,22 @@ static int cfi_spansion_write_block_mips(struct flash_bank *bank, const uint8_t
const uint32_t *target_code_src = NULL;
switch (bank->bus_width) {
- case 2:
- /* Check for DQ5 support */
- if (cfi_info->status_poll_mask & (1 << 5)) {
- target_code_src = mips_word_16_code;
- target_code_size = sizeof(mips_word_16_code);
- } else {
- LOG_ERROR("Need DQ5 support");
- return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
- /* target_code_src = mips_word_16_code_dq7only; */
- /* target_code_size = sizeof(mips_word_16_code_dq7only); */
- }
- break;
- default:
- LOG_ERROR("Unsupported bank buswidth %u, can't do block memory writes",
- bank->bus_width);
+ case 2:
+ /* Check for DQ5 support */
+ if (cfi_info->status_poll_mask & (1 << 5)) {
+ target_code_src = mips_word_16_code;
+ target_code_size = sizeof(mips_word_16_code);
+ } else {
+ LOG_ERROR("Need DQ5 support");
return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
+ /* target_code_src = mips_word_16_code_dq7only; */
+ /* target_code_size = sizeof(mips_word_16_code_dq7only); */
+ }
+ break;
+ default:
+ LOG_ERROR("Unsupported bank buswidth %u, can't do block memory writes",
+ bank->bus_width);
+ return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
}
/* flash write code */
@@ -1800,49 +1800,49 @@ static int cfi_spansion_write_block(struct flash_bank *bank, const uint8_t *buff
const uint32_t *target_code_src = NULL;
switch (bank->bus_width) {
- case 1:
+ case 1:
+ if (is_armv7m(target_to_armv7m(target))) {
+ LOG_ERROR("Unknown ARM architecture");
+ return ERROR_FAIL;
+ }
+ target_code_src = armv4_5_word_8_code;
+ target_code_size = sizeof(armv4_5_word_8_code);
+ break;
+ case 2:
+ /* Check for DQ5 support */
+ if (cfi_info->status_poll_mask & (1 << 5)) {
if (is_armv7m(target_to_armv7m(target))) {
- LOG_ERROR("Unknown ARM architecture");
- return ERROR_FAIL;
+ /* armv7m target */
+ target_code_src = armv7m_word_16_code;
+ target_code_size = sizeof(armv7m_word_16_code);
+ } else { /* armv4_5 target */
+ target_code_src = armv4_5_word_16_code;
+ target_code_size = sizeof(armv4_5_word_16_code);
}
- target_code_src = armv4_5_word_8_code;
- target_code_size = sizeof(armv4_5_word_8_code);
- break;
- case 2:
- /* Check for DQ5 support */
- if (cfi_info->status_poll_mask & (1 << 5)) {
- if (is_armv7m(target_to_armv7m(target))) {
- /* armv7m target */
- target_code_src = armv7m_word_16_code;
- target_code_size = sizeof(armv7m_word_16_code);
- } else { /* armv4_5 target */
- target_code_src = armv4_5_word_16_code;
- target_code_size = sizeof(armv4_5_word_16_code);
- }
- } else {
- /* No DQ5 support. Use DQ7 DATA# polling only. */
- if (is_armv7m(target_to_armv7m(target))) {
- /* armv7m target */
- target_code_src = armv7m_word_16_code_dq7only;
- target_code_size = sizeof(armv7m_word_16_code_dq7only);
- } else { /* armv4_5 target */
- target_code_src = armv4_5_word_16_code_dq7only;
- target_code_size = sizeof(armv4_5_word_16_code_dq7only);
- }
- }
- break;
- case 4:
+ } else {
+ /* No DQ5 support. Use DQ7 DATA# polling only. */
if (is_armv7m(target_to_armv7m(target))) {
- LOG_ERROR("Unknown ARM architecture");
- return ERROR_FAIL;
+ /* armv7m target */
+ target_code_src = armv7m_word_16_code_dq7only;
+ target_code_size = sizeof(armv7m_word_16_code_dq7only);
+ } else { /* armv4_5 target */
+ target_code_src = armv4_5_word_16_code_dq7only;
+ target_code_size = sizeof(armv4_5_word_16_code_dq7only);
}
- target_code_src = armv4_5_word_32_code;
- target_code_size = sizeof(armv4_5_word_32_code);
- break;
- default:
- LOG_ERROR("Unsupported bank buswidth %u, can't do block memory writes",
- bank->bus_width);
- return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
+ }
+ break;
+ case 4:
+ if (is_armv7m(target_to_armv7m(target))) {
+ LOG_ERROR("Unknown ARM architecture");
+ return ERROR_FAIL;
+ }
+ target_code_src = armv4_5_word_32_code;
+ target_code_size = sizeof(armv4_5_word_32_code);
+ break;
+ default:
+ LOG_ERROR("Unsupported bank buswidth %u, can't do block memory writes",
+ bank->bus_width);
+ return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
}
/* flash write code */
@@ -2172,14 +2172,14 @@ int cfi_write_word(struct flash_bank *bank, uint8_t *word, uint32_t address)
struct cfi_flash_bank *cfi_info = bank->driver_priv;
switch (cfi_info->pri_id) {
- case 1:
- case 3:
- return cfi_intel_write_word(bank, word, address);
- case 2:
- return cfi_spansion_write_word(bank, word, address);
- default:
- LOG_ERROR("cfi primary command set %i unsupported", cfi_info->pri_id);
- break;
+ case 1:
+ case 3:
+ return cfi_intel_write_word(bank, word, address);
+ case 2:
+ return cfi_spansion_write_word(bank, word, address);
+ default:
+ LOG_ERROR("cfi primary command set %i unsupported", cfi_info->pri_id);
+ break;
}
return ERROR_FLASH_OPERATION_FAILED;
@@ -2197,14 +2197,14 @@ static int cfi_write_words(struct flash_bank *bank, const uint8_t *word,
}
switch (cfi_info->pri_id) {
- case 1:
- case 3:
- return cfi_intel_write_words(bank, word, wordcount, address);
- case 2:
- return cfi_spansion_write_words(bank, word, wordcount, address);
- default:
- LOG_ERROR("cfi primary command set %i unsupported", cfi_info->pri_id);
- break;
+ case 1:
+ case 3:
+ return cfi_intel_write_words(bank, word, wordcount, address);
+ case 2:
+ return cfi_spansion_write_words(bank, word, wordcount, address);
+ default:
+ LOG_ERROR("cfi primary command set %i unsupported", cfi_info->pri_id);
+ break;
}
return ERROR_FLASH_OPERATION_FAILED;
@@ -2345,18 +2345,18 @@ static int cfi_write(struct flash_bank *bank, const uint8_t *buffer, uint32_t of
/* handle blocks of bus_size aligned bytes */
blk_count = count & ~(bank->bus_width - 1); /* round down, leave tail bytes */
switch (cfi_info->pri_id) {
- /* try block writes (fails without working area) */
- case 1:
- case 3:
- retval = cfi_intel_write_block(bank, buffer, write_p, blk_count);
- break;
- case 2:
- retval = cfi_spansion_write_block(bank, buffer, write_p, blk_count);
- break;
- default:
- LOG_ERROR("cfi primary command set %i unsupported", cfi_info->pri_id);
- retval = ERROR_FLASH_OPERATION_FAILED;
- break;
+ /* try block writes (fails without working area) */
+ case 1:
+ case 3:
+ retval = cfi_intel_write_block(bank, buffer, write_p, blk_count);
+ break;
+ case 2:
+ retval = cfi_spansion_write_block(bank, buffer, write_p, blk_count);
+ break;
+ default:
+ LOG_ERROR("cfi primary command set %i unsupported", cfi_info->pri_id);
+ retval = ERROR_FLASH_OPERATION_FAILED;
+ break;
}
if (retval == ERROR_OK) {
/* Increment pointers and decrease count on successful block write */
@@ -2581,22 +2581,22 @@ int cfi_probe(struct flash_bank *bank)
if (retval != ERROR_OK)
return retval;
switch (bank->chip_width) {
- case 1:
- cfi_info->manufacturer = *value_buf0;
- cfi_info->device_id = *value_buf1;
- break;
- case 2:
- cfi_info->manufacturer = target_buffer_get_u16(target, value_buf0);
- cfi_info->device_id = target_buffer_get_u16(target, value_buf1);
- break;
- case 4:
- cfi_info->manufacturer = target_buffer_get_u32(target, value_buf0);
- cfi_info->device_id = target_buffer_get_u32(target, value_buf1);
- break;
- default:
- LOG_ERROR("Unsupported bank chipwidth %u, can't probe memory",
- bank->chip_width);
- return ERROR_FLASH_OPERATION_FAILED;
+ case 1:
+ cfi_info->manufacturer = *value_buf0;
+ cfi_info->device_id = *value_buf1;
+ break;
+ case 2:
+ cfi_info->manufacturer = target_buffer_get_u16(target, value_buf0);
+ cfi_info->device_id = target_buffer_get_u16(target, value_buf1);
+ break;
+ case 4:
+ cfi_info->manufacturer = target_buffer_get_u32(target, value_buf0);
+ cfi_info->device_id = target_buffer_get_u32(target, value_buf1);
+ break;
+ default:
+ LOG_ERROR("Unsupported bank chipwidth %u, can't probe memory",
+ bank->chip_width);
+ return ERROR_FLASH_OPERATION_FAILED;
}
LOG_INFO("Flash Manufacturer/Device: 0x%04x 0x%04x",
@@ -2722,7 +2722,7 @@ int cfi_probe(struct flash_bank *bank)
if (retval != ERROR_OK)
return retval;
LOG_DEBUG(
- "erase region[%i]: %" PRIu32 " blocks of size 0x%" PRIx32 "",
+ "erase region[%i]: %" PRIu32 " blocks of size 0x%" PRIx32,
i,
(cfi_info->erase_region_info[i] & 0xffff) + 1,
(cfi_info->erase_region_info[i] >> 16) * 256);
@@ -2734,25 +2734,25 @@ int cfi_probe(struct flash_bank *bank)
* the sector layout to be able to apply fixups
*/
switch (cfi_info->pri_id) {
- /* Intel command set (standard and extended) */
- case 0x0001:
- case 0x0003:
- cfi_read_intel_pri_ext(bank);
- break;
- /* AMD/Spansion, Atmel, ... command set */
- case 0x0002:
- cfi_info->status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7; /*
- *default
- *for
- *all
- *CFI
- *flashes
- **/
- cfi_read_0002_pri_ext(bank);
- break;
- default:
- LOG_ERROR("cfi primary command set %i unsupported", cfi_info->pri_id);
- break;
+ /* Intel command set (standard and extended) */
+ case 0x0001:
+ case 0x0003:
+ cfi_read_intel_pri_ext(bank);
+ break;
+ /* AMD/Spansion, Atmel, ... command set */
+ case 0x0002:
+ cfi_info->status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7; /*
+ *default
+ *for
+ *all
+ *CFI
+ *flashes
+ **/
+ cfi_read_0002_pri_ext(bank);
+ break;
+ default:
+ LOG_ERROR("cfi primary command set %i unsupported", cfi_info->pri_id);
+ break;
}
/* return to read array mode
@@ -2798,18 +2798,18 @@ int cfi_probe(struct flash_bank *bank)
/* apply fixups depending on the primary command set */
switch (cfi_info->pri_id) {
- /* Intel command set (standard and extended) */
- case 0x0001:
- case 0x0003:
- cfi_fixup(bank, cfi_0001_fixups);
- break;
- /* AMD/Spansion, Atmel, ... command set */
- case 0x0002:
- cfi_fixup(bank, cfi_0002_fixups);
- break;
- default:
- LOG_ERROR("cfi primary command set %i unsupported", cfi_info->pri_id);
- break;
+ /* Intel command set (standard and extended) */
+ case 0x0001:
+ case 0x0003:
+ cfi_fixup(bank, cfi_0001_fixups);
+ break;
+ /* AMD/Spansion, Atmel, ... command set */
+ case 0x0002:
+ cfi_fixup(bank, cfi_0002_fixups);
+ break;
+ default:
+ LOG_ERROR("cfi primary command set %i unsupported", cfi_info->pri_id);
+ break;
}
if ((cfi_info->dev_size * bank->bus_width / bank->chip_width) != bank->size) {
@@ -2849,7 +2849,7 @@ int cfi_probe(struct flash_bank *bank)
}
if (offset != (cfi_info->dev_size * bank->bus_width / bank->chip_width)) {
LOG_WARNING(
- "CFI size is 0x%" PRIx32 ", but total sector size is 0x%" PRIx32 "",
+ "CFI size is 0x%" PRIx32 ", but total sector size is 0x%" PRIx32,
(cfi_info->dev_size * bank->bus_width / bank->chip_width),
offset);
}
@@ -2939,14 +2939,14 @@ int cfi_protect_check(struct flash_bank *bank)
return ERROR_FLASH_BANK_NOT_PROBED;
switch (cfi_info->pri_id) {
- case 1:
- case 3:
- return cfi_intel_protect_check(bank);
- case 2:
- return cfi_spansion_protect_check(bank);
- default:
- LOG_ERROR("cfi primary command set %i unsupported", cfi_info->pri_id);
- break;
+ case 1:
+ case 3:
+ return cfi_intel_protect_check(bank);
+ case 2:
+ return cfi_spansion_protect_check(bank);
+ default:
+ LOG_ERROR("cfi primary command set %i unsupported", cfi_info->pri_id);
+ break;
}
return ERROR_OK;
@@ -3011,16 +3011,16 @@ int cfi_get_info(struct flash_bank *bank, struct command_invocation *cmd)
1 << cfi_info->max_buf_write_size);
switch (cfi_info->pri_id) {
- case 1:
- case 3:
- cfi_intel_info(bank, cmd);
- break;
- case 2:
- cfi_spansion_info(bank, cmd);
- break;
- default:
- LOG_ERROR("cfi primary command set %i unsupported", cfi_info->pri_id);
- break;
+ case 1:
+ case 3:
+ cfi_intel_info(bank, cmd);
+ break;
+ case 2:
+ cfi_spansion_info(bank, cmd);
+ break;
+ default:
+ LOG_ERROR("cfi primary command set %i unsupported", cfi_info->pri_id);
+ break;
}
return ERROR_OK;
diff --git a/src/flash/nor/driver.h b/src/flash/nor/driver.h
index 3b57ef9ff0..2bd2043633 100644
--- a/src/flash/nor/driver.h
+++ b/src/flash/nor/driver.h
@@ -237,9 +237,11 @@ struct flash_driver {
*/
const struct flash_driver *flash_driver_find_by_name(const char *name);
+// Keep in alphabetic order this list of drivers
extern const struct flash_driver aduc702x_flash;
extern const struct flash_driver aducm360_flash;
extern const struct flash_driver ambiqmicro_flash;
+extern const struct flash_driver artery_flash;
extern const struct flash_driver at91sam3_flash;
extern const struct flash_driver at91sam4_flash;
extern const struct flash_driver at91sam4l_flash;
diff --git a/src/flash/nor/drivers.c b/src/flash/nor/drivers.c
index 3770bfbd3c..6b0def6810 100644
--- a/src/flash/nor/drivers.c
+++ b/src/flash/nor/drivers.c
@@ -7,6 +7,8 @@
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
+
+#include
#include "imp.h"
/**
@@ -14,9 +16,11 @@
* @todo Make this dynamically extendable with loadable modules.
*/
static const struct flash_driver * const flash_drivers[] = {
+ // Keep in alphabetic order the list of drivers
&aduc702x_flash,
&aducm360_flash,
&ambiqmicro_flash,
+ &artery_flash,
&at91sam3_flash,
&at91sam4_flash,
&at91sam4l_flash,
@@ -27,8 +31,8 @@ static const struct flash_driver * const flash_drivers[] = {
&atsamv_flash,
&avr_flash,
&bluenrgx_flash,
- &cc3220sf_flash,
&cc26xx_flash,
+ &cc3220sf_flash,
&cfi_flash,
&dsp5680xx_flash,
&dw_spi_flash,
@@ -37,9 +41,9 @@ static const struct flash_driver * const flash_drivers[] = {
&eneispif_flash,
&esirisc_flash,
&faux_flash,
+ &fespi_flash,
&fm3_flash,
&fm4_flash,
- &fespi_flash,
&jtagspi_flash,
&kinetis_flash,
&kinetis_ke_flash,
@@ -54,46 +58,45 @@ static const struct flash_driver * const flash_drivers[] = {
&mspm0_flash,
&niietcm4_flash,
&npcx_flash,
- &nrf5_flash,
&nrf51_flash,
+ &nrf5_flash,
&numicro_flash,
&ocl_flash,
&pic32mx_flash,
&psoc4_flash,
- &psoc5lp_flash,
&psoc5lp_eeprom_flash,
+ &psoc5lp_flash,
&psoc5lp_nvl_flash,
&psoc6_flash,
&qn908x_flash,
&renesas_rpchf_flash,
&rp2xxx_flash,
+ &rsl10_flash,
&sh_qspi_flash,
&sim3x_flash,
&stellaris_flash,
&stm32f1x_flash,
&stm32f2x_flash,
- &stm32lx_flash,
- &stm32l4x_flash,
&stm32h7x_flash,
- &stmsmi_flash,
+ &stm32l4x_flash,
+ &stm32lx_flash,
&stmqspi_flash,
+ &stmsmi_flash,
&str7x_flash,
&str9x_flash,
&str9xpec_flash,
&swm050_flash,
&tms470_flash,
&virtual_flash,
+ &w600_flash,
&xcf_flash,
&xmc1xxx_flash,
&xmc4xxx_flash,
- &w600_flash,
- &rsl10_flash,
- NULL,
};
const struct flash_driver *flash_driver_find_by_name(const char *name)
{
- for (unsigned int i = 0; flash_drivers[i]; i++) {
+ for (size_t i = 0; i < ARRAY_SIZE(flash_drivers); i++) {
if (strcmp(name, flash_drivers[i]->name) == 0)
return flash_drivers[i];
}
diff --git a/src/flash/nor/efm32.c b/src/flash/nor/efm32.c
index f8e0886570..e402867912 100644
--- a/src/flash/nor/efm32.c
+++ b/src/flash/nor/efm32.c
@@ -88,14 +88,14 @@ enum efm32_bank_index {
static int efm32x_get_bank_index(target_addr_t base)
{
switch (base) {
- case EFM32_FLASH_BASE:
- return EFM32_BANK_INDEX_MAIN;
- case EFM32_MSC_USER_DATA:
- return EFM32_BANK_INDEX_USER_DATA;
- case EFM32_MSC_LOCK_BITS:
- return EFM32_BANK_INDEX_LOCK_BITS;
- default:
- return ERROR_FAIL;
+ case EFM32_FLASH_BASE:
+ return EFM32_BANK_INDEX_MAIN;
+ case EFM32_MSC_USER_DATA:
+ return EFM32_BANK_INDEX_USER_DATA;
+ case EFM32_MSC_LOCK_BITS:
+ return EFM32_BANK_INDEX_LOCK_BITS;
+ default:
+ return ERROR_FAIL;
}
}
@@ -282,14 +282,14 @@ static int efm32x_read_info(struct flash_bank *bank)
}
switch (efm32_info->family_data->series) {
- case 0:
- efm32x_info->reg_base = EFM32_MSC_REGBASE;
- efm32x_info->reg_lock = EFM32_MSC_REG_LOCK;
- break;
- case 1:
- efm32x_info->reg_base = EFM32_MSC_REGBASE_SERIES1;
- efm32x_info->reg_lock = EFM32_MSC_REG_LOCK_SERIES1;
- break;
+ case 0:
+ efm32x_info->reg_base = EFM32_MSC_REGBASE;
+ efm32x_info->reg_lock = EFM32_MSC_REG_LOCK;
+ break;
+ case 1:
+ efm32x_info->reg_base = EFM32_MSC_REGBASE_SERIES1;
+ efm32x_info->reg_lock = EFM32_MSC_REG_LOCK_SERIES1;
+ break;
}
if (efm32_info->family_data->msc_regbase != 0)
@@ -430,7 +430,7 @@ static int efm32x_wait_status(struct flash_bank *bank, int timeout,
if (ret != ERROR_OK)
break;
- LOG_DEBUG("status: 0x%" PRIx32 "", status);
+ LOG_DEBUG("status: 0x%" PRIx32, status);
if (((status & wait_mask) == 0) && (wait_for_set == 0))
break;
@@ -662,18 +662,18 @@ static int efm32x_get_page_lock(struct flash_bank *bank, size_t page)
uint32_t mask = 0;
switch (bank->base) {
- case EFM32_FLASH_BASE:
- dw = efm32x_info->lb_page[page >> 5];
- mask = 1 << (page & 0x1f);
- break;
- case EFM32_MSC_USER_DATA:
- dw = efm32x_info->lb_page[126];
- mask = 0x1;
- break;
- case EFM32_MSC_LOCK_BITS:
- dw = efm32x_info->lb_page[126];
- mask = 0x2;
- break;
+ case EFM32_FLASH_BASE:
+ dw = efm32x_info->lb_page[page >> 5];
+ mask = 1 << (page & 0x1f);
+ break;
+ case EFM32_MSC_USER_DATA:
+ dw = efm32x_info->lb_page[126];
+ mask = 0x1;
+ break;
+ case EFM32_MSC_LOCK_BITS:
+ dw = efm32x_info->lb_page[126];
+ mask = 0x2;
+ break;
}
return (dw & mask) ? 0 : 1;
diff --git a/src/flash/nor/em357.c b/src/flash/nor/em357.c
index 207346f10d..cf005ca22d 100644
--- a/src/flash/nor/em357.c
+++ b/src/flash/nor/em357.c
@@ -115,7 +115,7 @@ static int em357_wait_status_busy(struct flash_bank *bank, int timeout)
retval = em357_get_flash_status(bank, &status);
if (retval != ERROR_OK)
return retval;
- LOG_DEBUG("status: 0x%" PRIx32 "", status);
+ LOG_DEBUG("status: 0x%" PRIx32, status);
if ((status & FLASH_BSY) == 0)
break;
if (timeout-- <= 0) {
@@ -670,36 +670,36 @@ static int em357_probe(struct flash_bank *bank)
em357_info->probed = false;
switch (bank->size) {
- case 0x10000:
- /* 64k -- 64 1k pages */
- num_pages = 64;
- page_size = 1024;
- break;
- case 0x20000:
- /* 128k -- 128 1k pages */
- num_pages = 128;
- page_size = 1024;
- break;
- case 0x30000:
- /* 192k -- 96 2k pages */
- num_pages = 96;
- page_size = 2048;
- break;
- case 0x40000:
- /* 256k -- 128 2k pages */
- num_pages = 128;
- page_size = 2048;
- break;
- case 0x80000:
- /* 512k -- 256 2k pages */
- num_pages = 256;
- page_size = 2048;
- break;
- default:
- LOG_WARNING("No size specified for em357 flash driver, assuming 192k!");
- num_pages = 96;
- page_size = 2048;
- break;
+ case 0x10000:
+ /* 64k -- 64 1k pages */
+ num_pages = 64;
+ page_size = 1024;
+ break;
+ case 0x20000:
+ /* 128k -- 128 1k pages */
+ num_pages = 128;
+ page_size = 1024;
+ break;
+ case 0x30000:
+ /* 192k -- 96 2k pages */
+ num_pages = 96;
+ page_size = 2048;
+ break;
+ case 0x40000:
+ /* 256k -- 128 2k pages */
+ num_pages = 128;
+ page_size = 2048;
+ break;
+ case 0x80000:
+ /* 512k -- 256 2k pages */
+ num_pages = 256;
+ page_size = 2048;
+ break;
+ default:
+ LOG_WARNING("No size specified for em357 flash driver, assuming 192k!");
+ num_pages = 96;
+ page_size = 2048;
+ break;
}
/* Enable FPEC CLK */
diff --git a/src/flash/nor/jtagspi.c b/src/flash/nor/jtagspi.c
index 4b975390be..e1bb17ab1f 100644
--- a/src/flash/nor/jtagspi.c
+++ b/src/flash/nor/jtagspi.c
@@ -230,7 +230,7 @@ COMMAND_HANDLER(jtagspi_handle_set)
*/
retval = CALL_COMMAND_HANDLER(flash_command_get_bank_probe_optional, 0,
&bank, false);
- if (ERROR_OK != retval)
+ if (retval != ERROR_OK)
return retval;
info = bank->driver_priv;
@@ -420,7 +420,7 @@ COMMAND_HANDLER(jtagspi_handle_always_4byte)
return ERROR_COMMAND_SYNTAX_ERROR;
retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
- if (ERROR_OK != retval)
+ if (retval != ERROR_OK)
return retval;
jtagspi_info = bank->driver_priv;
diff --git a/src/flash/nor/kinetis.c b/src/flash/nor/kinetis.c
index 85c306bd44..82e68de3fb 100644
--- a/src/flash/nor/kinetis.c
+++ b/src/flash/nor/kinetis.c
@@ -2145,24 +2145,24 @@ static int kinetis_probe_chip_s32k(struct kinetis_chip *k_chip)
k_chip->max_flash_prog_size = 512;
switch (k_chip->sim_sdid & KINETIS_SDID_S32K_DERIVATE_MASK) {
- case KINETIS_SDID_S32K_DERIVATE_KXX6:
- /* S32K116 CPU 48Mhz Flash 128KB RAM 17KB+2KB */
- /* Non-Interleaved */
- k_chip->pflash_size = 128 << 10;
- k_chip->pflash_sector_size = 2 << 10;
- /* Non-Interleaved */
- k_chip->nvm_size = 32 << 10;
- k_chip->nvm_sector_size = 2 << 10;
- break;
- case KINETIS_SDID_S32K_DERIVATE_KXX8:
- /* S32K118 CPU 80Mhz Flash 256KB+32KB RAM 32KB+4KB */
- /* Non-Interleaved */
- k_chip->pflash_size = 256 << 10;
- k_chip->pflash_sector_size = 2 << 10;
- /* Non-Interleaved */
- k_chip->nvm_size = 32 << 10;
- k_chip->nvm_sector_size = 2 << 10;
- break;
+ case KINETIS_SDID_S32K_DERIVATE_KXX6:
+ /* S32K116 CPU 48Mhz Flash 128KB RAM 17KB+2KB */
+ /* Non-Interleaved */
+ k_chip->pflash_size = 128 << 10;
+ k_chip->pflash_sector_size = 2 << 10;
+ /* Non-Interleaved */
+ k_chip->nvm_size = 32 << 10;
+ k_chip->nvm_sector_size = 2 << 10;
+ break;
+ case KINETIS_SDID_S32K_DERIVATE_KXX8:
+ /* S32K118 CPU 80Mhz Flash 256KB+32KB RAM 32KB+4KB */
+ /* Non-Interleaved */
+ k_chip->pflash_size = 256 << 10;
+ k_chip->pflash_sector_size = 2 << 10;
+ /* Non-Interleaved */
+ k_chip->nvm_size = 32 << 10;
+ k_chip->nvm_sector_size = 2 << 10;
+ break;
}
break;
diff --git a/src/flash/nor/kinetis_ke.c b/src/flash/nor/kinetis_ke.c
index 8207504b5f..51d5cb504b 100644
--- a/src/flash/nor/kinetis_ke.c
+++ b/src/flash/nor/kinetis_ke.c
@@ -238,19 +238,18 @@ static int kinetis_ke_prepare_flash(struct flash_bank *bank)
* Trim internal clock
*/
switch (KINETIS_KE_SRSID_SUBFAMID(kinfo->sim_srsid)) {
-
- case KINETIS_KE_SRSID_KEX2:
- /* Both KE02_20 and KE02_40 should get the same trim value */
- trim_value = 0x4C;
- break;
-
- case KINETIS_KE_SRSID_KEX4:
- trim_value = 0x54;
- break;
-
- case KINETIS_KE_SRSID_KEX6:
- trim_value = 0x58;
- break;
+ case KINETIS_KE_SRSID_KEX2:
+ /* Both KE02_20 and KE02_40 should get the same trim value */
+ trim_value = 0x4C;
+ break;
+
+ case KINETIS_KE_SRSID_KEX4:
+ trim_value = 0x54;
+ break;
+
+ case KINETIS_KE_SRSID_KEX6:
+ trim_value = 0x58;
+ break;
}
result = target_read_u8(target, ICS_C4, &c4);
@@ -293,54 +292,52 @@ static int kinetis_ke_prepare_flash(struct flash_bank *bank)
* Configure SIM (bus clock)
*/
switch (KINETIS_KE_SRSID_SUBFAMID(kinfo->sim_srsid)) {
+ /* KE02 sub-family operates on SIM_BUSDIV */
+ case KINETIS_KE_SRSID_KEX2:
+ bus_reg_val = 0;
+ bus_reg_addr = SIM_BUSDIV;
+ bus_clock = 20000000;
+ break;
+
+ /* KE04 and KE06 sub-family operates on SIM_CLKDIV
+ * Clocks are divided by:
+ * DIV1 = core clock = 48MHz
+ * DIV2 = bus clock = 24Mhz
+ * DIV3 = timer clocks
+ * So we need to configure SIM_CLKDIV, DIV1 and DIV2 value
+ */
+ case KINETIS_KE_SRSID_KEX4:
+ /* KE04 devices have the SIM_CLKDIV register at a different offset
+ * depending on the pin count. */
+ switch (KINETIS_KE_SRSID_PINCOUNT(kinfo->sim_srsid)) {
+ /* 16, 20 and 24 pins */
+ case 1:
+ case 2:
+ case 3:
+ bus_reg_addr = SIM_CLKDIV_KE04_16_20_24;
+ break;
- /* KE02 sub-family operates on SIM_BUSDIV */
- case KINETIS_KE_SRSID_KEX2:
- bus_reg_val = 0;
- bus_reg_addr = SIM_BUSDIV;
- bus_clock = 20000000;
+ /* 44, 64 and 80 pins */
+ case 5:
+ case 7:
+ case 8:
+ bus_reg_addr = SIM_CLKDIV_KE04_44_64_80;
break;
- /* KE04 and KE06 sub-family operates on SIM_CLKDIV
- * Clocks are divided by:
- * DIV1 = core clock = 48MHz
- * DIV2 = bus clock = 24Mhz
- * DIV3 = timer clocks
- * So we need to configure SIM_CLKDIV, DIV1 and DIV2 value
- */
- case KINETIS_KE_SRSID_KEX4:
- /* KE04 devices have the SIM_CLKDIV register at a different offset
- * depending on the pin count. */
- switch (KINETIS_KE_SRSID_PINCOUNT(kinfo->sim_srsid)) {
-
- /* 16, 20 and 24 pins */
- case 1:
- case 2:
- case 3:
- bus_reg_addr = SIM_CLKDIV_KE04_16_20_24;
- break;
-
- /* 44, 64 and 80 pins */
- case 5:
- case 7:
- case 8:
- bus_reg_addr = SIM_CLKDIV_KE04_44_64_80;
- break;
-
- default:
- LOG_ERROR("KE04 - Unknown pin count");
- return ERROR_FAIL;
- }
+ default:
+ LOG_ERROR("KE04 - Unknown pin count");
+ return ERROR_FAIL;
+ }
- bus_reg_val = SIM_CLKDIV_OUTDIV2_MASK;
- bus_clock = 24000000;
- break;
+ bus_reg_val = SIM_CLKDIV_OUTDIV2_MASK;
+ bus_clock = 24000000;
+ break;
- case KINETIS_KE_SRSID_KEX6:
- bus_reg_val = SIM_CLKDIV_OUTDIV2_MASK;
- bus_reg_addr = SIM_CLKDIV_KE06;
- bus_clock = 24000000;
- break;
+ case KINETIS_KE_SRSID_KEX6:
+ bus_reg_val = SIM_CLKDIV_OUTDIV2_MASK;
+ bus_reg_addr = SIM_CLKDIV_KE06;
+ bus_clock = 24000000;
+ break;
}
result = target_write_u32(target, bus_reg_addr, bus_reg_val);
@@ -357,20 +354,19 @@ static int kinetis_ke_prepare_flash(struct flash_bank *bank)
c2 &= ~ICS_C2_BDIV_MASK;
switch (KINETIS_KE_SRSID_SUBFAMID(kinfo->sim_srsid)) {
-
- case KINETIS_KE_SRSID_KEX2:
- /* Note: since there are two KE02 types, the KE02_40 @ 40MHz and the
- * KE02_20 @ 20MHz, we divide here the ~40MHz ICSFLLCLK down to 20MHz,
- * for compatibility.
- */
- c2 |= ICS_C2_BDIV(1);
- break;
-
- case KINETIS_KE_SRSID_KEX4:
- case KINETIS_KE_SRSID_KEX6:
- /* For KE04 and KE06, the ICSFLLCLK can be 48MHz. */
- c2 |= ICS_C2_BDIV(0);
- break;
+ case KINETIS_KE_SRSID_KEX2:
+ /* Note: since there are two KE02 types, the KE02_40 @ 40MHz and the
+ * KE02_20 @ 20MHz, we divide here the ~40MHz ICSFLLCLK down to 20MHz,
+ * for compatibility.
+ */
+ c2 |= ICS_C2_BDIV(1);
+ break;
+
+ case KINETIS_KE_SRSID_KEX4:
+ case KINETIS_KE_SRSID_KEX6:
+ /* For KE04 and KE06, the ICSFLLCLK can be 48MHz. */
+ c2 |= ICS_C2_BDIV(0);
+ break;
}
result = target_write_u8(target, ICS_C2, c2);
@@ -1052,21 +1048,21 @@ static int kinetis_ke_probe(struct flash_bank *bank)
}
switch (KINETIS_KE_SRSID_SUBFAMID(kinfo->sim_srsid)) {
- case KINETIS_KE_SRSID_KEX2:
- LOG_INFO("KE02 sub-family");
- break;
+ case KINETIS_KE_SRSID_KEX2:
+ LOG_INFO("KE02 sub-family");
+ break;
- case KINETIS_KE_SRSID_KEX4:
- LOG_INFO("KE04 sub-family");
- break;
+ case KINETIS_KE_SRSID_KEX4:
+ LOG_INFO("KE04 sub-family");
+ break;
- case KINETIS_KE_SRSID_KEX6:
- LOG_INFO("KE06 sub-family");
- break;
+ case KINETIS_KE_SRSID_KEX6:
+ LOG_INFO("KE06 sub-family");
+ break;
- default:
- LOG_ERROR("Unsupported KE sub-family");
- return ERROR_FLASH_OPER_UNSUPPORTED;
+ default:
+ LOG_ERROR("Unsupported KE sub-family");
+ return ERROR_FLASH_OPER_UNSUPPORTED;
}
/* We can only retrieve the ke0x part, but there is no way to know
@@ -1077,41 +1073,40 @@ static int kinetis_ke_probe(struct flash_bank *bank)
kinfo->sector_size = 512;
switch (KINETIS_KE_SRSID_SUBFAMID(kinfo->sim_srsid)) {
-
- case KINETIS_KE_SRSID_KEX2:
- /* Max. 64KB */
- bank->size = 0x00010000;
- bank->num_sectors = 128;
-
- /* KE02 uses the FTMRH flash controller,
- * and registers have a different offset from the
- * FTMRE flash controller. Sort this out here.
- */
- kinfo->ftmrx_fclkdiv_addr = 0x40020000;
- kinfo->ftmrx_fccobix_addr = 0x40020002;
- kinfo->ftmrx_fstat_addr = 0x40020006;
- kinfo->ftmrx_fprot_addr = 0x40020008;
- kinfo->ftmrx_fccobhi_addr = 0x4002000A;
- kinfo->ftmrx_fccoblo_addr = 0x4002000B;
- break;
-
- case KINETIS_KE_SRSID_KEX6:
- case KINETIS_KE_SRSID_KEX4:
- /* Max. 128KB */
- bank->size = 0x00020000;
- bank->num_sectors = 256;
-
- /* KE04 and KE06 use the FTMRE flash controller,
- * and registers have a different offset from the
- * FTMRH flash controller. Sort this out here.
- */
- kinfo->ftmrx_fclkdiv_addr = 0x40020003;
- kinfo->ftmrx_fccobix_addr = 0x40020001;
- kinfo->ftmrx_fstat_addr = 0x40020005;
- kinfo->ftmrx_fprot_addr = 0x4002000B;
- kinfo->ftmrx_fccobhi_addr = 0x40020009;
- kinfo->ftmrx_fccoblo_addr = 0x40020008;
- break;
+ case KINETIS_KE_SRSID_KEX2:
+ /* Max. 64KB */
+ bank->size = 0x00010000;
+ bank->num_sectors = 128;
+
+ /* KE02 uses the FTMRH flash controller,
+ * and registers have a different offset from the
+ * FTMRE flash controller. Sort this out here.
+ */
+ kinfo->ftmrx_fclkdiv_addr = 0x40020000;
+ kinfo->ftmrx_fccobix_addr = 0x40020002;
+ kinfo->ftmrx_fstat_addr = 0x40020006;
+ kinfo->ftmrx_fprot_addr = 0x40020008;
+ kinfo->ftmrx_fccobhi_addr = 0x4002000A;
+ kinfo->ftmrx_fccoblo_addr = 0x4002000B;
+ break;
+
+ case KINETIS_KE_SRSID_KEX6:
+ case KINETIS_KE_SRSID_KEX4:
+ /* Max. 128KB */
+ bank->size = 0x00020000;
+ bank->num_sectors = 256;
+
+ /* KE04 and KE06 use the FTMRE flash controller,
+ * and registers have a different offset from the
+ * FTMRH flash controller. Sort this out here.
+ */
+ kinfo->ftmrx_fclkdiv_addr = 0x40020003;
+ kinfo->ftmrx_fccobix_addr = 0x40020001;
+ kinfo->ftmrx_fstat_addr = 0x40020005;
+ kinfo->ftmrx_fprot_addr = 0x4002000B;
+ kinfo->ftmrx_fccobhi_addr = 0x40020009;
+ kinfo->ftmrx_fccoblo_addr = 0x40020008;
+ break;
}
free(bank->sectors);
diff --git a/src/flash/nor/lpc2000.c b/src/flash/nor/lpc2000.c
index 09d35f604a..1b338ee2e6 100644
--- a/src/flash/nor/lpc2000.c
+++ b/src/flash/nor/lpc2000.c
@@ -383,40 +383,40 @@ static int lpc2000_build_sector_list(struct flash_bank *bank)
/* variant 2 has a uniform layout, only number of sectors differs */
switch (bank->size) {
- case 4 * 1024:
- lpc2000_info->cmd51_max_buffer = 1024;
- bank->num_sectors = 1;
- break;
- case 8 * 1024:
- lpc2000_info->cmd51_max_buffer = 1024;
- bank->num_sectors = 2;
- break;
- case 16 * 1024:
- bank->num_sectors = 4;
- break;
- case 32 * 1024:
- bank->num_sectors = 8;
- break;
- case 64 * 1024:
- bank->num_sectors = 9;
- break;
- case 128 * 1024:
- bank->num_sectors = 11;
- break;
- case 256 * 1024:
- bank->num_sectors = 15;
- break;
- case 500 * 1024:
- bank->num_sectors = 27;
- break;
- case 512 * 1024:
- case 504 * 1024:
- bank->num_sectors = 28;
- break;
- default:
- LOG_ERROR("BUG: unknown bank->size encountered");
- exit(-1);
- break;
+ case 4 * 1024:
+ lpc2000_info->cmd51_max_buffer = 1024;
+ bank->num_sectors = 1;
+ break;
+ case 8 * 1024:
+ lpc2000_info->cmd51_max_buffer = 1024;
+ bank->num_sectors = 2;
+ break;
+ case 16 * 1024:
+ bank->num_sectors = 4;
+ break;
+ case 32 * 1024:
+ bank->num_sectors = 8;
+ break;
+ case 64 * 1024:
+ bank->num_sectors = 9;
+ break;
+ case 128 * 1024:
+ bank->num_sectors = 11;
+ break;
+ case 256 * 1024:
+ bank->num_sectors = 15;
+ break;
+ case 500 * 1024:
+ bank->num_sectors = 27;
+ break;
+ case 512 * 1024:
+ case 504 * 1024:
+ bank->num_sectors = 28;
+ break;
+ default:
+ LOG_ERROR("BUG: unknown bank->size encountered");
+ exit(-1);
+ break;
}
bank->sectors = malloc(sizeof(struct flash_sector) * bank->num_sectors);
@@ -448,37 +448,37 @@ static int lpc2000_build_sector_list(struct flash_bank *bank)
lpc2000_info->iap_max_stack = 128;
switch (bank->size) {
- case 4 * 1024:
- lpc2000_info->cmd51_max_buffer = 256;
- bank->num_sectors = 1;
- break;
- case 8 * 1024:
- lpc2000_info->cmd51_max_buffer = 512;
- bank->num_sectors = 2;
- break;
- case 16 * 1024:
- lpc2000_info->cmd51_max_buffer = 512;
- bank->num_sectors = 4;
- break;
- case 32 * 1024:
- lpc2000_info->cmd51_max_buffer = 1024;
- bank->num_sectors = 8;
- break;
- case 64 * 1024:
- bank->num_sectors = 16;
- break;
- case 128 * 1024:
- bank->num_sectors = 18;
+ case 4 * 1024:
+ lpc2000_info->cmd51_max_buffer = 256;
+ bank->num_sectors = 1;
break;
- case 256 * 1024:
- bank->num_sectors = 22;
- break;
- case 512 * 1024:
- bank->num_sectors = 30;
- break;
- default:
- LOG_ERROR("BUG: unknown bank->size encountered");
- exit(-1);
+ case 8 * 1024:
+ lpc2000_info->cmd51_max_buffer = 512;
+ bank->num_sectors = 2;
+ break;
+ case 16 * 1024:
+ lpc2000_info->cmd51_max_buffer = 512;
+ bank->num_sectors = 4;
+ break;
+ case 32 * 1024:
+ lpc2000_info->cmd51_max_buffer = 1024;
+ bank->num_sectors = 8;
+ break;
+ case 64 * 1024:
+ bank->num_sectors = 16;
+ break;
+ case 128 * 1024:
+ bank->num_sectors = 18;
+ break;
+ case 256 * 1024:
+ bank->num_sectors = 22;
+ break;
+ case 512 * 1024:
+ bank->num_sectors = 30;
+ break;
+ default:
+ LOG_ERROR("BUG: unknown bank->size encountered");
+ exit(-1);
}
bank->sectors = malloc(sizeof(struct flash_sector) * bank->num_sectors);
@@ -497,18 +497,18 @@ static int lpc2000_build_sector_list(struct flash_bank *bank)
lpc2000_info->iap_max_stack = 208;
switch (bank->size) {
- case 256 * 1024:
- bank->num_sectors = 11;
- break;
- case 384 * 1024:
- bank->num_sectors = 13;
- break;
- case 512 * 1024:
- bank->num_sectors = 15;
- break;
- default:
- LOG_ERROR("BUG: unknown bank->size encountered");
- exit(-1);
+ case 256 * 1024:
+ bank->num_sectors = 11;
+ break;
+ case 384 * 1024:
+ bank->num_sectors = 13;
+ break;
+ case 512 * 1024:
+ bank->num_sectors = 15;
+ break;
+ default:
+ LOG_ERROR("BUG: unknown bank->size encountered");
+ exit(-1);
}
bank->sectors = malloc(sizeof(struct flash_sector) * bank->num_sectors);
@@ -529,30 +529,30 @@ static int lpc2000_build_sector_list(struct flash_bank *bank)
lpc2000_info->cmd51_max_buffer = 256; /* smallest MCU in the series, LPC810, has 1 kB of SRAM */
switch (bank->size) {
- case 4 * 1024:
- bank->num_sectors = 4;
- break;
- case 8 * 1024:
- bank->num_sectors = 8;
- break;
- case 16 * 1024:
- bank->num_sectors = 16;
- break;
- case 30 * 1024:
- lpc2000_info->cmd51_max_buffer = 1024; /* For LPC8N04 and NHS31xx, have 8kB of SRAM */
- bank->num_sectors = 30; /* There have only 30kB of writable Flash out of 32kB */
- break;
- case 32 * 1024:
- lpc2000_info->cmd51_max_buffer = 1024; /* For LPC824, has 8kB of SRAM */
- bank->num_sectors = 32;
- break;
- case 64 * 1024:
- lpc2000_info->cmd51_max_buffer = 1024; /* For LPC844, has 8kB of SRAM */
- bank->num_sectors = 64;
- break;
- default:
- LOG_ERROR("BUG: unknown bank->size encountered");
- exit(-1);
+ case 4 * 1024:
+ bank->num_sectors = 4;
+ break;
+ case 8 * 1024:
+ bank->num_sectors = 8;
+ break;
+ case 16 * 1024:
+ bank->num_sectors = 16;
+ break;
+ case 30 * 1024:
+ lpc2000_info->cmd51_max_buffer = 1024; /* For LPC8N04 and NHS31xx, have 8kB of SRAM */
+ bank->num_sectors = 30; /* There have only 30kB of writable Flash out of 32kB */
+ break;
+ case 32 * 1024:
+ lpc2000_info->cmd51_max_buffer = 1024; /* For LPC824, has 8kB of SRAM */
+ bank->num_sectors = 32;
+ break;
+ case 64 * 1024:
+ lpc2000_info->cmd51_max_buffer = 1024; /* For LPC844, has 8kB of SRAM */
+ bank->num_sectors = 64;
+ break;
+ default:
+ LOG_ERROR("BUG: unknown bank->size encountered");
+ exit(-1);
}
bank->sectors = malloc(sizeof(struct flash_sector) * bank->num_sectors);
@@ -602,18 +602,18 @@ static int lpc2000_build_sector_list(struct flash_bank *bank)
lpc2000_info->iap_max_stack = 128;
switch (bank->size) {
- case 64 * 1024:
- bank->num_sectors = 16;
- break;
- case 128 * 1024:
- bank->num_sectors = 32;
- break;
- case 256 * 1024:
- bank->num_sectors = 64;
- break;
- default:
- LOG_ERROR("BUG: unknown bank->size encountered");
- exit(-1);
+ case 64 * 1024:
+ bank->num_sectors = 16;
+ break;
+ case 128 * 1024:
+ bank->num_sectors = 32;
+ break;
+ case 256 * 1024:
+ bank->num_sectors = 64;
+ break;
+ default:
+ LOG_ERROR("BUG: unknown bank->size encountered");
+ exit(-1);
}
bank->sectors = malloc(sizeof(struct flash_sector) * bank->num_sectors);
@@ -633,15 +633,15 @@ static int lpc2000_build_sector_list(struct flash_bank *bank)
lpc2000_info->iap_max_stack = 128;
switch (bank->size) {
- case 256 * 1024:
- bank->num_sectors = 8;
- break;
- case 512 * 1024:
- bank->num_sectors = 16;
- break;
- default:
- LOG_ERROR("BUG: unknown bank->size encountered");
- exit(-1);
+ case 256 * 1024:
+ bank->num_sectors = 8;
+ break;
+ case 512 * 1024:
+ bank->num_sectors = 16;
+ break;
+ default:
+ LOG_ERROR("BUG: unknown bank->size encountered");
+ exit(-1);
}
bank->sectors = malloc(sizeof(struct flash_sector) * bank->num_sectors);
@@ -686,24 +686,24 @@ static int lpc2000_iap_working_area_init(struct flash_bank *bank, struct working
/* write IAP code to working area */
switch (lpc2000_info->variant) {
- case LPC800:
- case LPC1100:
- case LPC1500:
- case LPC1700:
- case LPC4300:
- case LPC54100:
- case LPC_AUTO:
- target_buffer_set_u32(target, jump_gate, ARMV4_5_T_BX(12));
- target_buffer_set_u32(target, jump_gate + 4, ARMV5_T_BKPT(0));
- break;
- case LPC2000_V1:
- case LPC2000_V2:
- target_buffer_set_u32(target, jump_gate, ARMV4_5_BX(12));
- target_buffer_set_u32(target, jump_gate + 4, ARMV4_5_B(0xfffffe, 0));
- break;
- default:
- LOG_ERROR("BUG: unknown lpc2000_info->variant encountered");
- exit(-1);
+ case LPC800:
+ case LPC1100:
+ case LPC1500:
+ case LPC1700:
+ case LPC4300:
+ case LPC54100:
+ case LPC_AUTO:
+ target_buffer_set_u32(target, jump_gate, ARMV4_5_T_BX(12));
+ target_buffer_set_u32(target, jump_gate + 4, ARMV5_T_BKPT(0));
+ break;
+ case LPC2000_V1:
+ case LPC2000_V2:
+ target_buffer_set_u32(target, jump_gate, ARMV4_5_BX(12));
+ target_buffer_set_u32(target, jump_gate + 4, ARMV4_5_B(0xfffffe, 0));
+ break;
+ default:
+ LOG_ERROR("BUG: unknown lpc2000_info->variant encountered");
+ exit(-1);
}
int retval = target_write_memory(target, (*iap_working_area)->address, 4, 2, jump_gate);
@@ -729,36 +729,36 @@ static int lpc2000_iap_call(struct flash_bank *bank, struct working_area *iap_wo
uint32_t iap_entry_point = 0; /* to make compiler happier */
switch (lpc2000_info->variant) {
- case LPC800:
- case LPC1100:
- case LPC1700:
- case LPC_AUTO:
- armv7m_info.common_magic = ARMV7M_COMMON_MAGIC;
- armv7m_info.core_mode = ARM_MODE_THREAD;
- iap_entry_point = 0x1fff1ff1;
- break;
- case LPC1500:
- case LPC54100:
- armv7m_info.common_magic = ARMV7M_COMMON_MAGIC;
- armv7m_info.core_mode = ARM_MODE_THREAD;
- iap_entry_point = 0x03000205;
- break;
- case LPC2000_V1:
- case LPC2000_V2:
- arm_algo.common_magic = ARM_COMMON_MAGIC;
- arm_algo.core_mode = ARM_MODE_SVC;
- arm_algo.core_state = ARM_STATE_ARM;
- iap_entry_point = 0x7ffffff1;
- break;
- case LPC4300:
- armv7m_info.common_magic = ARMV7M_COMMON_MAGIC;
- armv7m_info.core_mode = ARM_MODE_THREAD;
- /* read out IAP entry point from ROM driver table at 0x10400100 */
- target_read_u32(target, 0x10400100, &iap_entry_point);
- break;
- default:
- LOG_ERROR("BUG: unknown lpc2000->variant encountered");
- exit(-1);
+ case LPC800:
+ case LPC1100:
+ case LPC1700:
+ case LPC_AUTO:
+ armv7m_info.common_magic = ARMV7M_COMMON_MAGIC;
+ armv7m_info.core_mode = ARM_MODE_THREAD;
+ iap_entry_point = 0x1fff1ff1;
+ break;
+ case LPC1500:
+ case LPC54100:
+ armv7m_info.common_magic = ARMV7M_COMMON_MAGIC;
+ armv7m_info.core_mode = ARM_MODE_THREAD;
+ iap_entry_point = 0x03000205;
+ break;
+ case LPC2000_V1:
+ case LPC2000_V2:
+ arm_algo.common_magic = ARM_COMMON_MAGIC;
+ arm_algo.core_mode = ARM_MODE_SVC;
+ arm_algo.core_state = ARM_STATE_ARM;
+ iap_entry_point = 0x7ffffff1;
+ break;
+ case LPC4300:
+ armv7m_info.common_magic = ARMV7M_COMMON_MAGIC;
+ armv7m_info.core_mode = ARM_MODE_THREAD;
+ /* read out IAP entry point from ROM driver table at 0x10400100 */
+ target_read_u32(target, 0x10400100, &iap_entry_point);
+ break;
+ default:
+ LOG_ERROR("BUG: unknown lpc2000->variant encountered");
+ exit(-1);
}
if (lpc2000_info->iap_entry_alternative != 0x0)
@@ -791,43 +791,43 @@ static int lpc2000_iap_call(struct flash_bank *bank, struct working_area *iap_wo
buf_set_u32(reg_params[2].value, 0, 32, iap_entry_point);
switch (lpc2000_info->variant) {
- case LPC800:
- case LPC1100:
- case LPC1500:
- case LPC1700:
- case LPC4300:
- case LPC54100:
- case LPC_AUTO:
- /* IAP stack */
- init_reg_param(®_params[3], "sp", 32, PARAM_OUT);
- buf_set_u32(reg_params[3].value, 0, 32,
- iap_working_area->address + IAP_CODE_LEN + lpc2000_info->iap_max_stack);
-
- /* return address */
- init_reg_param(®_params[4], "lr", 32, PARAM_OUT);
- buf_set_u32(reg_params[4].value, 0, 32, (iap_working_area->address + 0x04) | 1);
- /* bit0 of LR = 1 to return in Thumb mode */
-
- target_run_algorithm(target, 2, mem_params, 5, reg_params, iap_working_area->address, 0, 10000,
- &armv7m_info);
- break;
- case LPC2000_V1:
- case LPC2000_V2:
- /* IAP stack */
- init_reg_param(®_params[3], "sp_svc", 32, PARAM_OUT);
- buf_set_u32(reg_params[3].value, 0, 32,
- iap_working_area->address + IAP_CODE_LEN + lpc2000_info->iap_max_stack);
-
- /* return address */
- init_reg_param(®_params[4], "lr_svc", 32, PARAM_OUT);
- buf_set_u32(reg_params[4].value, 0, 32, iap_working_area->address + 0x04);
-
- target_run_algorithm(target, 2, mem_params, 5, reg_params, iap_working_area->address,
- iap_working_area->address + 0x4, 10000, &arm_algo);
- break;
- default:
- LOG_ERROR("BUG: unknown lpc2000->variant encountered");
- exit(-1);
+ case LPC800:
+ case LPC1100:
+ case LPC1500:
+ case LPC1700:
+ case LPC4300:
+ case LPC54100:
+ case LPC_AUTO:
+ /* IAP stack */
+ init_reg_param(®_params[3], "sp", 32, PARAM_OUT);
+ buf_set_u32(reg_params[3].value, 0, 32,
+ iap_working_area->address + IAP_CODE_LEN + lpc2000_info->iap_max_stack);
+
+ /* return address */
+ init_reg_param(®_params[4], "lr", 32, PARAM_OUT);
+ buf_set_u32(reg_params[4].value, 0, 32, (iap_working_area->address + 0x04) | 1);
+ /* bit0 of LR = 1 to return in Thumb mode */
+
+ target_run_algorithm(target, 2, mem_params, 5, reg_params, iap_working_area->address, 0, 10000,
+ &armv7m_info);
+ break;
+ case LPC2000_V1:
+ case LPC2000_V2:
+ /* IAP stack */
+ init_reg_param(®_params[3], "sp_svc", 32, PARAM_OUT);
+ buf_set_u32(reg_params[3].value, 0, 32,
+ iap_working_area->address + IAP_CODE_LEN + lpc2000_info->iap_max_stack);
+
+ /* return address */
+ init_reg_param(®_params[4], "lr_svc", 32, PARAM_OUT);
+ buf_set_u32(reg_params[4].value, 0, 32, iap_working_area->address + 0x04);
+
+ target_run_algorithm(target, 2, mem_params, 5, reg_params, iap_working_area->address,
+ iap_working_area->address + 0x4, 10000, &arm_algo);
+ break;
+ default:
+ LOG_ERROR("BUG: unknown lpc2000->variant encountered");
+ exit(-1);
}
int status_code = target_buffer_get_u32(target, mem_params[1].value);
@@ -877,24 +877,24 @@ static int lpc2000_iap_blank_check(struct flash_bank *bank, unsigned int first,
int status_code = lpc2000_iap_call(bank, iap_working_area, 53, param_table, result_table);
switch (status_code) {
- case ERROR_FLASH_OPERATION_FAILED:
- retval = ERROR_FLASH_OPERATION_FAILED;
- break;
- case LPC2000_CMD_SUCCESS:
- bank->sectors[i].is_erased = 1;
- break;
- case LPC2000_SECTOR_NOT_BLANK:
- bank->sectors[i].is_erased = 0;
- break;
- case LPC2000_INVALID_SECTOR:
- bank->sectors[i].is_erased = 0;
- break;
- case LPC2000_BUSY:
- retval = ERROR_FLASH_BUSY;
- break;
- default:
- LOG_ERROR("BUG: unknown LPC2000 status code %i", status_code);
- exit(-1);
+ case ERROR_FLASH_OPERATION_FAILED:
+ retval = ERROR_FLASH_OPERATION_FAILED;
+ break;
+ case LPC2000_CMD_SUCCESS:
+ bank->sectors[i].is_erased = 1;
+ break;
+ case LPC2000_SECTOR_NOT_BLANK:
+ bank->sectors[i].is_erased = 0;
+ break;
+ case LPC2000_INVALID_SECTOR:
+ bank->sectors[i].is_erased = 0;
+ break;
+ case LPC2000_BUSY:
+ retval = ERROR_FLASH_BUSY;
+ break;
+ default:
+ LOG_ERROR("BUG: unknown LPC2000 status code %i", status_code);
+ exit(-1);
}
}
@@ -1002,6 +1002,28 @@ static int lpc2000_erase(struct flash_bank *bank, unsigned int first,
/* Prepare sectors */
int status_code = lpc2000_iap_call(bank, iap_working_area, 50, param_table, result_table);
switch (status_code) {
+ case ERROR_FLASH_OPERATION_FAILED:
+ retval = ERROR_FLASH_OPERATION_FAILED;
+ break;
+ case LPC2000_CMD_SUCCESS:
+ break;
+ case LPC2000_INVALID_SECTOR:
+ retval = ERROR_FLASH_SECTOR_INVALID;
+ break;
+ default:
+ LOG_WARNING("lpc2000 prepare sectors returned %i", status_code);
+ retval = ERROR_FLASH_OPERATION_FAILED;
+ break;
+ }
+
+ if (retval == ERROR_OK) {
+ /* Erase sectors */
+ param_table[2] = lpc2000_info->cclk;
+ if (lpc2000_info->variant == LPC4300)
+ param_table[3] = lpc2000_info->lpc4300_bank;
+
+ status_code = lpc2000_iap_call(bank, iap_working_area, 52, param_table, result_table);
+ switch (status_code) {
case ERROR_FLASH_OPERATION_FAILED:
retval = ERROR_FLASH_OPERATION_FAILED;
break;
@@ -1011,31 +1033,9 @@ static int lpc2000_erase(struct flash_bank *bank, unsigned int first,
retval = ERROR_FLASH_SECTOR_INVALID;
break;
default:
- LOG_WARNING("lpc2000 prepare sectors returned %i", status_code);
+ LOG_WARNING("lpc2000 erase sectors returned %i", status_code);
retval = ERROR_FLASH_OPERATION_FAILED;
break;
- }
-
- if (retval == ERROR_OK) {
- /* Erase sectors */
- param_table[2] = lpc2000_info->cclk;
- if (lpc2000_info->variant == LPC4300)
- param_table[3] = lpc2000_info->lpc4300_bank;
-
- status_code = lpc2000_iap_call(bank, iap_working_area, 52, param_table, result_table);
- switch (status_code) {
- case ERROR_FLASH_OPERATION_FAILED:
- retval = ERROR_FLASH_OPERATION_FAILED;
- break;
- case LPC2000_CMD_SUCCESS:
- break;
- case LPC2000_INVALID_SECTOR:
- retval = ERROR_FLASH_SECTOR_INVALID;
- break;
- default:
- LOG_WARNING("lpc2000 erase sectors returned %i", status_code);
- retval = ERROR_FLASH_OPERATION_FAILED;
- break;
}
}
@@ -1145,18 +1145,18 @@ static int lpc2000_write(struct flash_bank *bank, const uint8_t *buffer, uint32_
int status_code = lpc2000_iap_call(bank, iap_working_area, 50, param_table, result_table);
switch (status_code) {
- case ERROR_FLASH_OPERATION_FAILED:
- retval = ERROR_FLASH_OPERATION_FAILED;
- break;
- case LPC2000_CMD_SUCCESS:
- break;
- case LPC2000_INVALID_SECTOR:
- retval = ERROR_FLASH_SECTOR_INVALID;
- break;
- default:
- LOG_WARNING("lpc2000 prepare sectors returned %i", status_code);
- retval = ERROR_FLASH_OPERATION_FAILED;
- break;
+ case ERROR_FLASH_OPERATION_FAILED:
+ retval = ERROR_FLASH_OPERATION_FAILED;
+ break;
+ case LPC2000_CMD_SUCCESS:
+ break;
+ case LPC2000_INVALID_SECTOR:
+ retval = ERROR_FLASH_SECTOR_INVALID;
+ break;
+ default:
+ LOG_WARNING("lpc2000 prepare sectors returned %i", status_code);
+ retval = ERROR_FLASH_OPERATION_FAILED;
+ break;
}
/* Exit if error occurred */
@@ -1187,18 +1187,18 @@ static int lpc2000_write(struct flash_bank *bank, const uint8_t *buffer, uint32_
param_table[3] = lpc2000_info->cclk;
status_code = lpc2000_iap_call(bank, iap_working_area, 51, param_table, result_table);
switch (status_code) {
- case ERROR_FLASH_OPERATION_FAILED:
- retval = ERROR_FLASH_OPERATION_FAILED;
- break;
- case LPC2000_CMD_SUCCESS:
- break;
- case LPC2000_INVALID_SECTOR:
- retval = ERROR_FLASH_SECTOR_INVALID;
- break;
- default:
- LOG_WARNING("lpc2000 returned %i", status_code);
- retval = ERROR_FLASH_OPERATION_FAILED;
- break;
+ case ERROR_FLASH_OPERATION_FAILED:
+ retval = ERROR_FLASH_OPERATION_FAILED;
+ break;
+ case LPC2000_CMD_SUCCESS:
+ break;
+ case LPC2000_INVALID_SECTOR:
+ retval = ERROR_FLASH_SECTOR_INVALID;
+ break;
+ default:
+ LOG_WARNING("lpc2000 returned %i", status_code);
+ retval = ERROR_FLASH_OPERATION_FAILED;
+ break;
}
/* Exit if error occurred */
@@ -1267,240 +1267,240 @@ static int lpc2000_auto_probe_flash(struct flash_bank *bank)
}
switch (part_id) {
- case LPC1110_1:
- case LPC1110_2:
- lpc2000_info->variant = LPC1100;
- bank->size = 4 * 1024;
- break;
-
- case LPC1111_002_1:
- case LPC1111_002_2:
- case LPC1111_101_1:
- case LPC1111_101_2:
- case LPC1111_103_1:
- case LPC1111_201_1:
- case LPC1111_201_2:
- case LPC1111_203_1:
- case LPC11A11_001_1:
- case LPC11E11_101:
- case LPC1311:
- case LPC1311_1:
- lpc2000_info->variant = LPC1100;
- bank->size = 8 * 1024;
- break;
-
- case LPC1112_101_1:
- case LPC1112_101_2:
- case LPC1112_102_1:
- case LPC1112_102_2:
- case LPC1112_103_1:
- case LPC1112_201_1:
- case LPC1112_201_2:
- case LPC1112_203_1:
- case LPC11A02_1:
- case LPC11C12_301_1:
- case LPC11C22_301_1:
- case LPC11A12_101_1:
- case LPC11E12_201:
- case LPC11U12_201_1:
- case LPC11U12_201_2:
- case LPC1342:
- lpc2000_info->variant = LPC1100;
- bank->size = 16 * 1024;
- break;
-
- case LPC1113_201_1:
- case LPC1113_201_2:
- case LPC1113_203_1:
- case LPC1113_301_1:
- case LPC1113_301_2:
- case LPC1113_303_1:
- case LPC11A13_201_1:
- case LPC11E13_301:
- case LPC11U13_201_1:
- case LPC11U13_201_2:
- case LPC11U23_301:
- lpc2000_info->variant = LPC1100;
- bank->size = 24 * 1024;
- break;
-
- case LPC1114_102_1:
- case LPC1114_102_2:
- case LPC1114_201_1:
- case LPC1114_201_2:
- case LPC1114_203_1:
- case LPC1114_301_1:
- case LPC1114_301_2:
- case LPC1114_303_1:
- case LPC11A04_1:
- case LPC11A14_301_1:
- case LPC11A14_301_2:
- case LPC11C14_301_1:
- case LPC11C24_301_1:
- case LPC11E14_401:
- case LPC11U14_201_1:
- case LPC11U14_201_2:
- case LPC11U24_301:
- case LPC11U24_401:
- case LPC1313:
- case LPC1313_1:
- case LPC1315:
- case LPC1343:
- case LPC1343_1:
- case LPC1345:
- lpc2000_info->variant = LPC1100;
- bank->size = 32 * 1024;
- break;
-
- case LPC1751_1:
- case LPC1751_2:
- lpc2000_info->variant = LPC1700;
- bank->size = 32 * 1024;
- break;
-
- case LPC11U34_311:
- lpc2000_info->variant = LPC1100;
- bank->size = 40 * 1024;
- break;
-
- case LPC1114_323_1:
- case LPC11U34_421:
- case LPC1316:
- case LPC1346:
- lpc2000_info->variant = LPC1100;
- bank->size = 48 * 1024;
- break;
-
- case LPC1114_333_1:
- lpc2000_info->variant = LPC1100;
- bank->size = 56 * 1024;
- break;
-
- case LPC1115_303_1:
- case LPC11U35_401:
- case LPC11U35_501:
- case LPC11E66:
- case LPC11U66:
- case LPC1317:
- case LPC1347:
- lpc2000_info->variant = LPC1100;
- bank->size = 64 * 1024;
- break;
-
- case LPC1752:
- case LPC4072:
- lpc2000_info->variant = LPC1700;
- bank->size = 64 * 1024;
- break;
+ case LPC1110_1:
+ case LPC1110_2:
+ lpc2000_info->variant = LPC1100;
+ bank->size = 4 * 1024;
+ break;
+
+ case LPC1111_002_1:
+ case LPC1111_002_2:
+ case LPC1111_101_1:
+ case LPC1111_101_2:
+ case LPC1111_103_1:
+ case LPC1111_201_1:
+ case LPC1111_201_2:
+ case LPC1111_203_1:
+ case LPC11A11_001_1:
+ case LPC11E11_101:
+ case LPC1311:
+ case LPC1311_1:
+ lpc2000_info->variant = LPC1100;
+ bank->size = 8 * 1024;
+ break;
+
+ case LPC1112_101_1:
+ case LPC1112_101_2:
+ case LPC1112_102_1:
+ case LPC1112_102_2:
+ case LPC1112_103_1:
+ case LPC1112_201_1:
+ case LPC1112_201_2:
+ case LPC1112_203_1:
+ case LPC11A02_1:
+ case LPC11C12_301_1:
+ case LPC11C22_301_1:
+ case LPC11A12_101_1:
+ case LPC11E12_201:
+ case LPC11U12_201_1:
+ case LPC11U12_201_2:
+ case LPC1342:
+ lpc2000_info->variant = LPC1100;
+ bank->size = 16 * 1024;
+ break;
+
+ case LPC1113_201_1:
+ case LPC1113_201_2:
+ case LPC1113_203_1:
+ case LPC1113_301_1:
+ case LPC1113_301_2:
+ case LPC1113_303_1:
+ case LPC11A13_201_1:
+ case LPC11E13_301:
+ case LPC11U13_201_1:
+ case LPC11U13_201_2:
+ case LPC11U23_301:
+ lpc2000_info->variant = LPC1100;
+ bank->size = 24 * 1024;
+ break;
+
+ case LPC1114_102_1:
+ case LPC1114_102_2:
+ case LPC1114_201_1:
+ case LPC1114_201_2:
+ case LPC1114_203_1:
+ case LPC1114_301_1:
+ case LPC1114_301_2:
+ case LPC1114_303_1:
+ case LPC11A04_1:
+ case LPC11A14_301_1:
+ case LPC11A14_301_2:
+ case LPC11C14_301_1:
+ case LPC11C24_301_1:
+ case LPC11E14_401:
+ case LPC11U14_201_1:
+ case LPC11U14_201_2:
+ case LPC11U24_301:
+ case LPC11U24_401:
+ case LPC1313:
+ case LPC1313_1:
+ case LPC1315:
+ case LPC1343:
+ case LPC1343_1:
+ case LPC1345:
+ lpc2000_info->variant = LPC1100;
+ bank->size = 32 * 1024;
+ break;
- case LPC11E36_501:
- case LPC11U36_401:
- lpc2000_info->variant = LPC1100;
- bank->size = 96 * 1024;
- break;
+ case LPC1751_1:
+ case LPC1751_2:
+ lpc2000_info->variant = LPC1700;
+ bank->size = 32 * 1024;
+ break;
- case LPC11E37_401:
- case LPC11E37_501:
- case LPC11U37_401:
- case LPC11U37H_401:
- case LPC11U37_501:
- case LPC11E67:
- case LPC11E68:
- case LPC11U67_1:
- case LPC11U67_2:
- lpc2000_info->variant = LPC1100;
- bank->size = 128 * 1024;
- break;
+ case LPC11U34_311:
+ lpc2000_info->variant = LPC1100;
+ bank->size = 40 * 1024;
+ break;
- case LPC1754:
- case LPC1764:
- case LPC1774:
- case LPC4074:
- lpc2000_info->variant = LPC1700;
- bank->size = 128 * 1024;
- break;
+ case LPC1114_323_1:
+ case LPC11U34_421:
+ case LPC1316:
+ case LPC1346:
+ lpc2000_info->variant = LPC1100;
+ bank->size = 48 * 1024;
+ break;
- case LPC11U68_1:
- case LPC11U68_2:
- lpc2000_info->variant = LPC1100;
- bank->size = 256 * 1024;
- break;
+ case LPC1114_333_1:
+ lpc2000_info->variant = LPC1100;
+ bank->size = 56 * 1024;
+ break;
+
+ case LPC1115_303_1:
+ case LPC11U35_401:
+ case LPC11U35_501:
+ case LPC11E66:
+ case LPC11U66:
+ case LPC1317:
+ case LPC1347:
+ lpc2000_info->variant = LPC1100;
+ bank->size = 64 * 1024;
+ break;
- case LPC1756:
- case LPC1763:
- case LPC1765:
- case LPC1766:
- case LPC1776:
- case LPC1785:
- case LPC1786:
- case LPC4076:
- lpc2000_info->variant = LPC1700;
- bank->size = 256 * 1024;
- break;
+ case LPC1752:
+ case LPC4072:
+ lpc2000_info->variant = LPC1700;
+ bank->size = 64 * 1024;
+ break;
- case LPC1758:
- case LPC1759:
- case LPC1767:
- case LPC1768:
- case LPC1769:
- case LPC1777:
- case LPC1778:
- case LPC1787:
- case LPC1788:
- case LPC4078:
- case LPC4088:
- lpc2000_info->variant = LPC1700;
- bank->size = 512 * 1024;
- break;
+ case LPC11E36_501:
+ case LPC11U36_401:
+ lpc2000_info->variant = LPC1100;
+ bank->size = 96 * 1024;
+ break;
+
+ case LPC11E37_401:
+ case LPC11E37_501:
+ case LPC11U37_401:
+ case LPC11U37H_401:
+ case LPC11U37_501:
+ case LPC11E67:
+ case LPC11E68:
+ case LPC11U67_1:
+ case LPC11U67_2:
+ lpc2000_info->variant = LPC1100;
+ bank->size = 128 * 1024;
+ break;
- case LPC810_021:
- lpc2000_info->variant = LPC800;
- bank->size = 4 * 1024;
- break;
+ case LPC1754:
+ case LPC1764:
+ case LPC1774:
+ case LPC4074:
+ lpc2000_info->variant = LPC1700;
+ bank->size = 128 * 1024;
+ break;
- case LPC811_001:
- lpc2000_info->variant = LPC800;
- bank->size = 8 * 1024;
- break;
+ case LPC11U68_1:
+ case LPC11U68_2:
+ lpc2000_info->variant = LPC1100;
+ bank->size = 256 * 1024;
+ break;
+
+ case LPC1756:
+ case LPC1763:
+ case LPC1765:
+ case LPC1766:
+ case LPC1776:
+ case LPC1785:
+ case LPC1786:
+ case LPC4076:
+ lpc2000_info->variant = LPC1700;
+ bank->size = 256 * 1024;
+ break;
+
+ case LPC1758:
+ case LPC1759:
+ case LPC1767:
+ case LPC1768:
+ case LPC1769:
+ case LPC1777:
+ case LPC1778:
+ case LPC1787:
+ case LPC1788:
+ case LPC4078:
+ case LPC4088:
+ lpc2000_info->variant = LPC1700;
+ bank->size = 512 * 1024;
+ break;
- case LPC812_101:
- case LPC812_101_1:
- case LPC812_101_2:
- case LPC812_101_3:
- case LPC822_101:
- case LPC822_101_1:
- lpc2000_info->variant = LPC800;
- bank->size = 16 * 1024;
- break;
+ case LPC810_021:
+ lpc2000_info->variant = LPC800;
+ bank->size = 4 * 1024;
+ break;
- case LPC824_201:
- case LPC824_201_1:
- lpc2000_info->variant = LPC800;
- bank->size = 32 * 1024;
- break;
+ case LPC811_001:
+ lpc2000_info->variant = LPC800;
+ bank->size = 8 * 1024;
+ break;
+
+ case LPC812_101:
+ case LPC812_101_1:
+ case LPC812_101_2:
+ case LPC812_101_3:
+ case LPC822_101:
+ case LPC822_101_1:
+ lpc2000_info->variant = LPC800;
+ bank->size = 16 * 1024;
+ break;
- case LPC8N04:
- case NHS3100:
- case NHS3152:
- case NHS3153:
- lpc2000_info->variant = LPC800;
- bank->size = 30 * 1024;
- break;
+ case LPC824_201:
+ case LPC824_201_1:
+ lpc2000_info->variant = LPC800;
+ bank->size = 32 * 1024;
+ break;
- case LPC844_201:
- case LPC844_201_1:
- case LPC844_201_2:
- case LPC845_301:
- case LPC845_301_1:
- case LPC845_301_2:
- case LPC845_301_3:
- lpc2000_info->variant = LPC800;
- bank->size = 64 * 1024;
- break;
+ case LPC8N04:
+ case NHS3100:
+ case NHS3152:
+ case NHS3153:
+ lpc2000_info->variant = LPC800;
+ bank->size = 30 * 1024;
+ break;
+
+ case LPC844_201:
+ case LPC844_201_1:
+ case LPC844_201_2:
+ case LPC845_301:
+ case LPC845_301_1:
+ case LPC845_301_2:
+ case LPC845_301_3:
+ lpc2000_info->variant = LPC800;
+ bank->size = 64 * 1024;
+ break;
- default:
- LOG_ERROR("BUG: unknown Part ID encountered: 0x%" PRIx32, part_id);
- exit(-1);
+ default:
+ LOG_ERROR("BUG: unknown Part ID encountered: 0x%" PRIx32, part_id);
+ exit(-1);
}
return ERROR_OK;
diff --git a/src/flash/nor/lpc288x.c b/src/flash/nor/lpc288x.c
index 3006db1cbf..d7a4fdf24f 100644
--- a/src/flash/nor/lpc288x.c
+++ b/src/flash/nor/lpc288x.c
@@ -279,7 +279,7 @@ static int lpc288x_write(struct flash_bank *bank, const uint8_t *buffer, uint32_
/* all writes must start on a sector boundary... */
if (offset % bank->sectors[i].size) {
LOG_INFO(
- "offset 0x%" PRIx32 " breaks required alignment 0x%" PRIx32 "",
+ "offset 0x%" PRIx32 " breaks required alignment 0x%" PRIx32,
offset,
bank->sectors[i].size);
return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
@@ -293,7 +293,7 @@ static int lpc288x_write(struct flash_bank *bank, const uint8_t *buffer, uint32_
/* Range check... */
if (first_sector == 0xffffffff || last_sector == 0xffffffff) {
- LOG_INFO("Range check failed %" PRIx32 " %" PRIx32 "", offset, count);
+ LOG_INFO("Range check failed %" PRIx32 " %" PRIx32, offset, count);
return ERROR_FLASH_DST_OUT_OF_BANK;
}
diff --git a/src/flash/nor/max32xxx.c b/src/flash/nor/max32xxx.c
index 267fd43120..e91b9b67d5 100644
--- a/src/flash/nor/max32xxx.c
+++ b/src/flash/nor/max32xxx.c
@@ -2,7 +2,7 @@
/***************************************************************************
* Copyright (C) 2016 by Maxim Integrated *
- * Kevin Gillespie *
+ * Copyright (C) 2025 Analog Devices, Inc. *
***************************************************************************/
#ifdef HAVE_CONFIG_H
@@ -13,90 +13,112 @@
#include
#include
#include
-
-/* Register Addresses */
-#define FLSH_ADDR 0x000
-#define FLSH_CLKDIV 0x004
-#define FLSH_CN 0x008
-#define PR1E_ADDR 0x00C
-#define PR2S_ADDR 0x010
-#define PR2E_ADDR 0x014
-#define PR3S_ADDR 0x018
-#define PR3E_ADDR 0x01C
-#define FLSH_MD 0x020
-#define FLSH_INT 0x024
-#define FLSH_DATA0 0x030
-#define FLSH_DATA1 0x034
-#define FLSH_DATA2 0x038
-#define FLSH_DATA3 0x03C
-#define FLSH_BL_CTRL 0x170
-#define FLSH_PROT 0x300
-
-#define ARM_PID_REG 0xE00FFFE0
-#define MAX326XX_ID_REG 0x40000838
-
-/* Register settings */
-#define FLSH_INT_AF 0x00000002
-
-#define FLSH_CN_UNLOCK_MASK 0xF0000000
-#define FLSH_CN_UNLOCK_VALUE 0x20000000
-
-#define FLSH_CN_PEND 0x01000000
-
-#define FLSH_CN_ERASE_CODE_MASK 0x0000FF00
-#define FLSH_CN_ERASE_CODE_PGE 0x00005500
-#define FLSH_CN_ERASE_CODE_ME 0x0000AA00
-
-#define FLSH_CN_PGE 0x00000004
-#define FLSH_CN_ME 0x00000002
-#define FLSH_CN_WR 0x00000001
-#define FLASH_BL_CTRL_23 0x00020000
-#define FLASH_BL_CTRL_IFREN 0x00000001
-
-#define ARM_PID_DEFAULT_CM3 0xB4C3
-#define ARM_PID_DEFAULT_CM4 0xB4C4
-#define MAX326XX_ID 0x4D
+#include
+#include
+
+// Register addresses
+#define FLC_ADDR 0x00000000
+#define FLC_CLKDIV 0x00000004
+#define FLC_CN 0x00000008
+#define FLC_PR1E_ADDR 0x0000000C
+#define FLC_PR2S_ADDR 0x00000010
+#define FLC_PR2E_ADDR 0x00000014
+#define FLC_PR3S_ADDR 0x00000018
+#define FLC_PR3E_ADDR 0x0000001C
+#define FLC_MD 0x00000020
+#define FLC_INT 0x00000024
+#define FLC_DATA0 0x00000030
+#define FLC_DATA1 0x00000034
+#define FLC_DATA2 0x00000038
+#define FLC_DATA3 0x0000003C
+#define FLC_BL_CTRL 0x00000170
+#define FLC_PROT 0x00000300
+
+#define ARM_PID_REG 0xE00FFFE0
+#define MAX326XX_ID_REG 0x40000838
+
+// Register settings
+#define FLC_INT_AF 0x00000002
+
+#define FLC_CN_UNLOCK_MASK 0xF0000000
+#define FLC_CN_UNLOCK_VALUE 0x20000000
+
+#define FLC_CN_PEND 0x01000000
+#define FLC_CN_ERASE_CODE_MASK 0x0000FF00
+#define FLC_CN_ERASE_CODE_PGE 0x00005500
+#define FLC_CN_ERASE_CODE_ME 0x0000AA00
+#define FLC_CN_32BIT 0x00000010
+#define FLC_CN_PGE 0x00000004
+#define FLC_CN_ME 0x00000002
+#define FLC_CN_WR 0x00000001
+#define FLC_CN_PGE 0x00000004
+#define FLC_CN_ME 0x00000002
+#define FLC_CN_WR 0x00000001
+
+#define FLC_BL_CTRL_23 0x00020000
+#define FLC_BL_CTRL_IFREN 0x00000001
+
+#define MASK_FLASH_BUSY (0x048800E0 & ~0x04000000)
+#define MASK_DISABLE_INTS (0xFFFFFCFC)
+#define MASK_FLASH_UNLOCKED (0xF588FFEF & ~0x04000000)
+#define MASK_FLASH_LOCK (0xF588FFEF & ~0x04000000)
+#define MASK_FLASH_ERASE (0xF588FFEF & ~0x04000000)
+#define MASK_FLASH_ERASED (0xF48800EB & ~0x04000000)
+#define MASK_ACCESS_VIOLATIONS (0xFFFFFCFC)
+#define MASK_FLASH_WRITE (0xF588FFEF & ~0x04000000)
+#define MASK_WRITE_ALIGNED (0xF588FFEF & ~0x04000000)
+#define MASK_WRITE_COMPLETE (0xF488FFEE & ~0x04000000)
+#define MASK_WRITE_BURST (0xF588FFEF & ~0x04000000)
+#define MASK_BURST_COMPLETE (0xF488FFEE & ~0x04000000)
+#define MASK_WRITE_REMAINING (0xF588FFEF & ~0x04000000)
+#define MASK_REMAINING_COMPLETE (0xF488FFEE & ~0x04000000)
+#define MASK_MASS_ERASE (0xF588FFEF & ~0x04000000)
+#define MASK_ERASE_COMPLETE (0xF48800ED & ~0x04000000)
+
+#define ARM_PID_DEFAULT_CM3 0x0000B4C3
+#define ARM_PID_DEFAULT_CM4 0x0000B4C4
+#define MAX326XX_ID 0x0000004D
+
+#define OPTIONS_128 0x01 // Perform 128 bit flash writes
+#define OPTIONS_ENC 0x02 // Encrypt the flash contents
+#define OPTIONS_AUTH 0x04 // Authenticate the flash contents
+#define OPTIONS_COUNT 0x08 // Add counter values to authentication
+#define OPTIONS_INTER 0x10 // Interleave the authentication and count values
+#define OPTIONS_RELATIVE_XOR 0x20 // Only XOR the offset of the address when encrypting
+#define OPTIONS_KEYSIZE 0x40 // Use a 256 bit KEY
static int max32xxx_mass_erase(struct flash_bank *bank);
struct max32xxx_flash_bank {
bool probed;
- int max326xx;
+ bool max326xx;
unsigned int flash_size;
unsigned int flc_base;
unsigned int sector_size;
unsigned int clkdiv_value;
- uint32_t int_state;
- unsigned int burst_size_bits;
+ unsigned int int_state;
+ unsigned int options;
};
-/* see contrib/loaders/flash/max32xxx/max32xxx.s for src */
-static const uint8_t write_code[] = {
-#include "../../../contrib/loaders/flash/max32xxx/max32xxx.inc"
+static const uint8_t write_code_arm[] = {
+#include "../../../contrib/loaders/flash/max32xxx/max32xxx_write_arm.inc"
};
-/* Config Command: flash bank name driver base size chip_width bus_width target [driver_option]
- flash bank max32xxx 0 0 [burst_bits]
- */
FLASH_BANK_COMMAND_HANDLER(max32xxx_flash_bank_command)
{
struct max32xxx_flash_bank *info;
- if (CMD_ARGC < 9) {
- LOG_WARNING("incomplete flash bank max32xxx configuration: 0 0 [burst_bits]");
+ if (CMD_ARGC != 10) {
+ LOG_ERROR("incorrect flash bank max32xxx configuration: 0 0 ");
return ERROR_FLASH_BANK_INVALID;
}
info = calloc(1, sizeof(struct max32xxx_flash_bank));
- COMMAND_PARSE_NUMBER(uint, CMD_ARGV[2], info->flash_size);
- COMMAND_PARSE_NUMBER(uint, CMD_ARGV[6], info->flc_base);
- COMMAND_PARSE_NUMBER(uint, CMD_ARGV[7], info->sector_size);
- COMMAND_PARSE_NUMBER(uint, CMD_ARGV[8], info->clkdiv_value);
-
- if (CMD_ARGC > 9)
- COMMAND_PARSE_NUMBER(uint, CMD_ARGV[9], info->burst_size_bits);
- else
- info->burst_size_bits = 32;
+ COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], info->flash_size);
+ COMMAND_PARSE_NUMBER(u32, CMD_ARGV[6], info->flc_base);
+ COMMAND_PARSE_NUMBER(u32, CMD_ARGV[7], info->sector_size);
+ COMMAND_PARSE_NUMBER(u32, CMD_ARGV[8], info->clkdiv_value);
+ COMMAND_PARSE_NUMBER(u32, CMD_ARGV[9], info->options);
info->int_state = 0;
bank->driver_priv = info;
@@ -114,63 +136,67 @@ static int get_info(struct flash_bank *bank, struct command_invocation *cmd)
return ERROR_OK;
}
-/***************************************************************************
-* flash operations
-***************************************************************************/
+static bool max32xxx_flash_busy(uint32_t flash_cn)
+{
+ if (flash_cn & (FLC_CN_PGE | FLC_CN_ME | FLC_CN_WR))
+ return true;
+
+ return false;
+}
static int max32xxx_flash_op_pre(struct flash_bank *bank)
{
struct target *target = bank->target;
struct max32xxx_flash_bank *info = bank->driver_priv;
- uint32_t flsh_cn;
+ uint32_t flash_cn;
uint32_t bootloader;
- /* Check if the flash controller is busy */
- target_read_u32(target, info->flc_base + FLSH_CN, &flsh_cn);
- if (flsh_cn & (FLSH_CN_PEND | FLSH_CN_ERASE_CODE_MASK | FLSH_CN_PGE |
- FLSH_CN_ME | FLSH_CN_WR))
+ // Check if the flash controller is busy
+ target_read_u32(target, info->flc_base + FLC_CN, &flash_cn);
+ if (max32xxx_flash_busy(flash_cn))
return ERROR_FLASH_BUSY;
- /* Refresh flash controller timing */
- target_write_u32(target, info->flc_base + FLSH_CLKDIV, info->clkdiv_value);
+ // Refresh flash controller timing
+ target_write_u32(target, info->flc_base + FLC_CLKDIV, info->clkdiv_value);
- /* Clear and disable flash programming interrupts */
- target_read_u32(target, info->flc_base + FLSH_INT, &info->int_state);
- target_write_u32(target, info->flc_base + FLSH_INT, 0x00000000);
+ // Clear and disable flash programming interrupts
+ target_read_u32(target, info->flc_base + FLC_INT, &info->int_state);
+ target_write_u32(target, info->flc_base + FLC_INT, 0);
- /* Clear the lower bit in the bootloader configuration register in case flash page 0 has been replaced */
- if (target_read_u32(target, info->flc_base + FLSH_BL_CTRL, &bootloader) != ERROR_OK) {
- LOG_ERROR("Read failure on FLSH_BL_CTRL");
+ /* Clear the lower bit in the bootloader configuration register in case flash page 0 has
+ * been replaced */
+ if (target_read_u32(target, info->flc_base + FLC_BL_CTRL, &bootloader) != ERROR_OK) {
+ LOG_ERROR("Read failure on FLC_BL_CTRL");
return ERROR_FAIL;
}
- if (bootloader & FLASH_BL_CTRL_23) {
- LOG_WARNING("FLSH_BL_CTRL indicates BL mode 2 or mode 3.");
- if (bootloader & FLASH_BL_CTRL_IFREN) {
+ if (bootloader & FLC_BL_CTRL_23) {
+ LOG_WARNING("FLC_BL_CTRL indicates BL mode 2 or mode 3.");
+ if (bootloader & FLC_BL_CTRL_IFREN) {
LOG_WARNING("Flash page 0 swapped out, attempting to swap back in for programming");
- bootloader &= ~(FLASH_BL_CTRL_IFREN);
- if (target_write_u32(target, info->flc_base + FLSH_BL_CTRL, bootloader) != ERROR_OK) {
- LOG_ERROR("Write failure on FLSH_BL_CTRL");
+ bootloader &= ~(FLC_BL_CTRL_IFREN);
+ if (target_write_u32(target, info->flc_base + FLC_BL_CTRL,
+ bootloader) != ERROR_OK) {
+ LOG_ERROR("Write failure on FLC_BL_CTRL");
return ERROR_FAIL;
}
- if (target_read_u32(target, info->flc_base + FLSH_BL_CTRL, &bootloader) != ERROR_OK) {
- LOG_ERROR("Read failure on FLSH_BL_CTRL");
+ if (target_read_u32(target, info->flc_base + FLC_BL_CTRL,
+ &bootloader) != ERROR_OK) {
+ LOG_ERROR("Read failure on FLC_BL_CTRL");
return ERROR_FAIL;
}
- if (bootloader & FLASH_BL_CTRL_IFREN) {
- /* Bummer */
+ if (bootloader & FLC_BL_CTRL_IFREN)
LOG_ERROR("Unable to swap flash page 0 back in. Writes to page 0 will fail.");
- }
}
}
- /* Unlock flash */
- flsh_cn &= ~FLSH_CN_UNLOCK_MASK;
- flsh_cn |= FLSH_CN_UNLOCK_VALUE;
- target_write_u32(target, info->flc_base + FLSH_CN, flsh_cn);
+ // Unlock flash
+ flash_cn &= ~(FLC_CN_UNLOCK_MASK);
+ flash_cn |= FLC_CN_UNLOCK_VALUE;
+ target_write_u32(target, info->flc_base + FLC_CN, flash_cn);
- /* Confirm flash is unlocked */
- target_read_u32(target, info->flc_base + FLSH_CN, &flsh_cn);
- if ((flsh_cn & FLSH_CN_UNLOCK_VALUE) != FLSH_CN_UNLOCK_VALUE)
+ // Confirm flash is unlocked
+ target_read_u32(target, info->flc_base + FLC_CN, &flash_cn);
+ if ((flash_cn & FLC_CN_UNLOCK_VALUE) != FLC_CN_UNLOCK_VALUE)
return ERROR_FAIL;
return ERROR_OK;
@@ -180,15 +206,15 @@ static int max32xxx_flash_op_post(struct flash_bank *bank)
{
struct target *target = bank->target;
struct max32xxx_flash_bank *info = bank->driver_priv;
- uint32_t flsh_cn;
+ uint32_t flash_cn;
- /* Restore flash programming interrupts */
- target_write_u32(target, info->flc_base + FLSH_INT, info->int_state);
+ // Restore flash programming interrupts
+ target_write_u32(target, info->flc_base + FLC_INT, info->int_state);
- /* Lock flash */
- target_read_u32(target, info->flc_base + FLSH_CN, &flsh_cn);
- flsh_cn &= ~FLSH_CN_UNLOCK_MASK;
- target_write_u32(target, info->flc_base + FLSH_CN, flsh_cn);
+ // Lock flash
+ target_read_u32(target, info->flc_base + FLC_CN, &flash_cn);
+ flash_cn &= ~(FLC_CN_UNLOCK_MASK);
+ target_write_u32(target, info->flc_base + FLC_CN, flash_cn);
return ERROR_OK;
}
@@ -208,12 +234,12 @@ static int max32xxx_protect_check(struct flash_bank *bank)
return ERROR_FLASH_OPER_UNSUPPORTED;
}
- /* Check the protection */
+ // Check the protection
for (unsigned int i = 0; i < bank->num_sectors; i++) {
- if (i%32 == 0)
- target_read_u32(target, info->flc_base + FLSH_PROT + ((i/32)*4), &temp_reg);
+ if (i % 32 == 0)
+ target_read_u32(target, info->flc_base + FLC_PROT + ((i / 32) * 4), &temp_reg);
- if (temp_reg & (0x1 << i%32))
+ if (temp_reg & (0x1 << i % 32))
bank->sectors[i].is_protected = 1;
else
bank->sectors[i].is_protected = 0;
@@ -222,9 +248,9 @@ static int max32xxx_protect_check(struct flash_bank *bank)
}
static int max32xxx_erase(struct flash_bank *bank, unsigned int first,
- unsigned int last)
+ unsigned int last)
{
- uint32_t flsh_cn, flsh_int;
+ uint32_t flash_cn, flash_int;
struct max32xxx_flash_bank *info = bank->driver_priv;
struct target *target = bank->target;
int retval;
@@ -238,13 +264,13 @@ static int max32xxx_erase(struct flash_bank *bank, unsigned int first,
if (!info->probed)
return ERROR_FLASH_BANK_NOT_PROBED;
- if ((last < first) || (last >= bank->num_sectors))
+ if (last < first || last >= bank->num_sectors)
return ERROR_FLASH_SECTOR_INVALID;
- if ((first == 0) && (last == (bank->num_sectors - 1)))
+ if (first == 0 && last == (bank->num_sectors - 1))
return max32xxx_mass_erase(bank);
- /* Prepare to issue flash operation */
+ // Prepare to issue flash operation
retval = max32xxx_flash_op_pre(bank);
if (retval != ERROR_OK)
@@ -252,43 +278,43 @@ static int max32xxx_erase(struct flash_bank *bank, unsigned int first,
int erased = 0;
for (unsigned int banknr = first; banknr <= last; banknr++) {
-
- /* Check the protection */
+ // Check the protection
if (bank->sectors[banknr].is_protected == 1) {
LOG_WARNING("Flash sector %u is protected", banknr);
continue;
- } else
+ } else {
erased = 1;
+ }
- /* Address is first word in page */
- target_write_u32(target, info->flc_base + FLSH_ADDR, banknr * info->sector_size);
+ // Address is first word in page
+ target_write_u32(target, info->flc_base + FLC_ADDR, banknr * info->sector_size);
- /* Write page erase code */
- target_read_u32(target, info->flc_base + FLSH_CN, &flsh_cn);
- flsh_cn |= FLSH_CN_ERASE_CODE_PGE;
- target_write_u32(target, info->flc_base + FLSH_CN, flsh_cn);
+ // Write page erase code
+ target_read_u32(target, info->flc_base + FLC_CN, &flash_cn);
+ flash_cn |= FLC_CN_ERASE_CODE_PGE;
+ target_write_u32(target, info->flc_base + FLC_CN, flash_cn);
- /* Issue page erase command */
- flsh_cn |= 0x4;
- target_write_u32(target, info->flc_base + FLSH_CN, flsh_cn);
+ // Issue page erase command
+ flash_cn |= FLC_CN_PGE;
+ target_write_u32(target, info->flc_base + FLC_CN, flash_cn);
- /* Wait until erase complete */
+ // Wait until erase complete
retry = 1000;
do {
- target_read_u32(target, info->flc_base + FLSH_CN, &flsh_cn);
- } while ((--retry > 0) && (flsh_cn & FLSH_CN_PEND));
+ target_read_u32(target, info->flc_base + FLC_CN, &flash_cn);
+ } while ((--retry > 0) && max32xxx_flash_busy(flash_cn));
if (retry <= 0) {
- LOG_ERROR("Timed out waiting for flash page erase @ 0x%08x",
- banknr * info->sector_size);
+ LOG_ERROR("Timed out waiting for flash page erase @ 0x%08" PRIx32,
+ (banknr * info->sector_size));
return ERROR_FLASH_OPERATION_FAILED;
}
- /* Check access violations */
- target_read_u32(target, info->flc_base + FLSH_INT, &flsh_int);
- if (flsh_int & FLSH_INT_AF) {
+ // Check access violations
+ target_read_u32(target, info->flc_base + FLC_INT, &flash_int);
+ if (flash_int & FLC_INT_AF) {
LOG_ERROR("Error erasing flash page %i", banknr);
- target_write_u32(target, info->flc_base + FLSH_INT, 0);
+ target_write_u32(target, info->flc_base + FLC_INT, 0);
max32xxx_flash_op_post(bank);
return ERROR_FLASH_OPERATION_FAILED;
}
@@ -307,7 +333,7 @@ static int max32xxx_erase(struct flash_bank *bank, unsigned int first,
}
static int max32xxx_protect(struct flash_bank *bank, int set,
- unsigned int first, unsigned int last)
+ unsigned int first, unsigned int last)
{
struct max32xxx_flash_bank *info = bank->driver_priv;
struct target *target = bank->target;
@@ -324,22 +350,22 @@ static int max32xxx_protect(struct flash_bank *bank, int set,
if (!info->max326xx)
return ERROR_FLASH_OPER_UNSUPPORTED;
- if ((last < first) || (last >= bank->num_sectors))
+ if (last < first || last >= bank->num_sectors)
return ERROR_FLASH_SECTOR_INVALID;
- /* Setup the protection on the pages given */
+ // Setup the protection on the pages given
for (unsigned int page = first; page <= last; page++) {
if (set) {
- /* Set the write/erase bit for this page */
- target_read_u32(target, info->flc_base + FLSH_PROT + (page/32), &temp_reg);
- temp_reg |= (0x1 << page%32);
- target_write_u32(target, info->flc_base + FLSH_PROT + (page/32), temp_reg);
+ // Set the write/erase bit for this page
+ target_read_u32(target, info->flc_base + FLC_PROT + (page / 32), &temp_reg);
+ temp_reg |= (0x1 << page % 32);
+ target_write_u32(target, info->flc_base + FLC_PROT + (page / 32), temp_reg);
bank->sectors[page].is_protected = 1;
} else {
- /* Clear the write/erase bit for this page */
- target_read_u32(target, info->flc_base + FLSH_PROT + (page/32), &temp_reg);
- temp_reg &= ~(0x1 << page%32);
- target_write_u32(target, info->flc_base + FLSH_PROT + (page/32), temp_reg);
+ // Clear the write/erase bit for this page
+ target_read_u32(target, info->flc_base + FLC_PROT + (page / 32), &temp_reg);
+ temp_reg &= ~(0x1 << page % 32);
+ target_write_u32(target, info->flc_base + FLC_PROT + (page / 32), temp_reg);
bank->sectors[page].is_protected = 0;
}
}
@@ -348,38 +374,41 @@ static int max32xxx_protect(struct flash_bank *bank, int set,
}
static int max32xxx_write_block(struct flash_bank *bank, const uint8_t *buffer,
- uint32_t offset, uint32_t wcount)
+ uint32_t offset, uint32_t len)
{
struct max32xxx_flash_bank *info = bank->driver_priv;
struct target *target = bank->target;
+ const char *target_type_name = (const char *)target->type->name;
uint32_t buffer_size = 16384;
struct working_area *source;
struct working_area *write_algorithm;
- uint32_t address = bank->base + offset;
struct reg_param reg_params[5];
+ struct mem_param mem_param[2];
struct armv7m_algorithm armv7m_info;
int retval = ERROR_OK;
- /* power of two, and multiple of word size */
+ // power of two, and multiple of word size
static const unsigned int buf_min = 128;
+ uint8_t *write_code;
+ int write_code_size;
+
- /* for small buffers it's faster not to download an algorithm */
- if (wcount * 4 < buf_min)
+ if (strcmp(target_type_name, "cortex_m") == 0) {
+ write_code = (uint8_t *)write_code_arm;
+ write_code_size = sizeof(write_code_arm);
+ } else {
return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
+ }
- LOG_DEBUG("(bank=%p buffer=%p offset=%08" PRIx32 " wcount=%08" PRIx32 "",
- bank, buffer, offset, wcount);
+ LOG_DEBUG("bank=%p buffer=%p offset=%08" PRIx32 " len=%08" PRIx32 "",
+ bank, buffer, offset, len);
- /* flash write code */
- if (target_alloc_working_area(target, sizeof(write_code), &write_algorithm) != ERROR_OK) {
+ // flash write code
+ if (target_alloc_working_area(target, write_code_size, &write_algorithm) != ERROR_OK) {
LOG_DEBUG("no working area for block memory writes");
return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
}
- /* plus a buffer big enough for this data */
- if (wcount * 4 < buffer_size)
- buffer_size = wcount * 4;
-
- /* memory buffer */
+ // memory buffer
while (target_alloc_working_area_try(target, buffer_size, &source) != ERROR_OK) {
buffer_size /= 2;
@@ -392,24 +421,53 @@ static int max32xxx_write_block(struct flash_bank *bank, const uint8_t *buffer,
target_name(target), buffer_size);
}
- target_write_buffer(target, write_algorithm->address, sizeof(write_code),
+ target_write_buffer(target, write_algorithm->address, write_code_size,
write_code);
armv7m_info.common_magic = ARMV7M_COMMON_MAGIC;
armv7m_info.core_mode = ARM_MODE_THREAD;
- init_reg_param(®_params[0], "r0", 32, PARAM_OUT);
- init_reg_param(®_params[1], "r1", 32, PARAM_OUT);
- init_reg_param(®_params[2], "r2", 32, PARAM_OUT);
- init_reg_param(®_params[3], "r3", 32, PARAM_OUT);
- init_reg_param(®_params[4], "r4", 32, PARAM_OUT);
+
+ // TODO: a0-a3 for RISCV
+
+ if (strcmp(target_type_name, "cortex_m") == 0) {
+ init_reg_param(®_params[0], "r0", 32, PARAM_OUT);
+ init_reg_param(®_params[1], "r1", 32, PARAM_OUT);
+ init_reg_param(®_params[2], "r2", 32, PARAM_OUT);
+ init_reg_param(®_params[3], "r3", 32, PARAM_OUT);
+ } else {
+ init_reg_param(®_params[0], "a0", 32, PARAM_OUT);
+ init_reg_param(®_params[1], "a1", 32, PARAM_OUT);
+ init_reg_param(®_params[2], "a2", 32, PARAM_OUT);
+ init_reg_param(®_params[3], "a3", 32, PARAM_OUT);
+ }
+ init_reg_param(®_params[4], "sp", 32, PARAM_OUT);
buf_set_u32(reg_params[0].value, 0, 32, source->address);
buf_set_u32(reg_params[1].value, 0, 32, source->address + source->size);
- buf_set_u32(reg_params[2].value, 0, 32, address);
- buf_set_u32(reg_params[3].value, 0, 32, wcount);
- buf_set_u32(reg_params[4].value, 0, 32, info->flc_base);
- retval = target_run_flash_async_algorithm(target, buffer, wcount, 4, 0, NULL,
- 5, reg_params, source->address, source->size, write_algorithm->address, 0, &armv7m_info);
+ buf_set_u32(reg_params[2].value, 0, 32, len);
+ buf_set_u32(reg_params[3].value, 0, 32, offset);
+ buf_set_u32(reg_params[4].value, 0, 32, source->address + source->size);
+
+ // mem_params for options
+ init_mem_param(&mem_param[0], source->address + (source->size - 8 - 128), 4, PARAM_OUT);
+ init_mem_param(&mem_param[1], source->address + (source->size - 4 - 128), 4, PARAM_OUT);
+ buf_set_u32(mem_param[0].value, 0, 32, info->options);
+ buf_set_u32(mem_param[1].value, 0, 32, info->flc_base);
+
+ // leave room for stack, 32-bit options and encryption buffer
+ retval = target_run_flash_async_algorithm(target,
+ buffer,
+ len,
+ 1,
+ 2,
+ mem_param,
+ 5,
+ reg_params,
+ source->address,
+ (source->size - 8 - 256),
+ write_algorithm->address,
+ 0,
+ &armv7m_info);
if (retval == ERROR_FLASH_OPERATION_FAILED)
LOG_ERROR("error %d executing max32xxx flash write algorithm", retval);
@@ -429,10 +487,9 @@ static int max32xxx_write(struct flash_bank *bank, const uint8_t *buffer,
{
struct max32xxx_flash_bank *info = bank->driver_priv;
struct target *target = bank->target;
- uint32_t flsh_cn, flsh_int;
+ uint32_t flash_cn, flash_int;
uint32_t address = offset;
uint32_t remaining = count;
- uint32_t words_remaining;
int retval;
int retry;
@@ -447,67 +504,74 @@ static int max32xxx_write(struct flash_bank *bank, const uint8_t *buffer,
if (!info->probed)
return ERROR_FLASH_BANK_NOT_PROBED;
- if (offset & 0x3) {
- LOG_WARNING("offset size must be word aligned");
- return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
+ if ((info->options & OPTIONS_128) == 0) {
+ if (offset & 0x3) {
+ LOG_ERROR("offset size must be 32-bit aligned");
+ return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
+ }
+ } else {
+ if (offset & 0xF) {
+ LOG_ERROR("offset size must be 128-bit aligned");
+ return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
+ }
}
if (offset + count > bank->size)
return ERROR_FLASH_DST_OUT_OF_BANK;
- /* Prepare to issue flash operation */
+ // Prepare to issue flash operation
retval = max32xxx_flash_op_pre(bank);
- if (retval != ERROR_OK)
+ if (retval != ERROR_OK) {
+ max32xxx_flash_op_post(bank);
return retval;
+ }
- if (remaining >= 4) {
- /* write in 32-bit units */
- target_read_u32(target, info->flc_base + FLSH_CN, &flsh_cn);
- flsh_cn &= 0xF7FFFFFF;
- flsh_cn |= 0x00000010;
- target_write_u32(target, info->flc_base + FLSH_CN, flsh_cn);
-
- /* try using a block write */
- words_remaining = remaining / 4;
- retval = max32xxx_write_block(bank, buffer, offset, words_remaining);
+ if (remaining >= 16) {
+ // try using a block write
+ retval = max32xxx_write_block(bank, buffer, offset, remaining);
if (retval != ERROR_OK) {
- if (retval == ERROR_TARGET_RESOURCE_NOT_AVAILABLE)
+ if (retval == ERROR_TARGET_RESOURCE_NOT_AVAILABLE) {
+ if (info->options & OPTIONS_ENC) {
+ LOG_ERROR("Must use algorithm in working area for encryption");
+ return ERROR_FLASH_OPERATION_FAILED;
+ }
LOG_DEBUG("writing flash word-at-a-time");
- else {
+ } else {
max32xxx_flash_op_post(bank);
return ERROR_FLASH_OPERATION_FAILED;
}
} else {
- /* all 32-bit words have been written */
- buffer += words_remaining * 4;
- address += words_remaining * 4;
- remaining -= words_remaining * 4;
+ // all words_remaining have been written
+ buffer += remaining;
+ address += remaining;
+ remaining -= remaining;
}
}
- if ((remaining >= 4) && ((address & 0x1F) != 0)) {
- /* write in 32-bit units until we are 128-bit aligned */
- target_read_u32(target, info->flc_base + FLSH_CN, &flsh_cn);
- flsh_cn &= 0xF7FFFFFF;
- flsh_cn |= 0x00000010;
- target_write_u32(target, info->flc_base + FLSH_CN, flsh_cn);
+ if (((info->options & OPTIONS_128) == 0) && remaining >= 4) {
+ // write in 32-bit units
+ target_read_u32(target, info->flc_base + FLC_CN, &flash_cn);
+ flash_cn |= FLC_CN_32BIT;
+ target_write_u32(target, info->flc_base + FLC_CN, flash_cn);
- while ((remaining >= 4) && ((address & 0x1F) != 0)) {
- target_write_u32(target, info->flc_base + FLSH_ADDR, address);
- target_write_buffer(target, info->flc_base + FLSH_DATA0, 4, buffer);
- flsh_cn |= 0x00000001;
- target_write_u32(target, info->flc_base + FLSH_CN, flsh_cn);
- /* Wait until flash operation is complete */
+ while (remaining >= 4) {
+ target_write_u32(target, info->flc_base + FLC_ADDR, address);
+ target_write_buffer(target, info->flc_base + FLC_DATA0, 4, buffer);
+ flash_cn |= FLC_CN_WR;
+ target_write_u32(target, info->flc_base + FLC_CN, flash_cn);
+ // Wait until flash operation is complete
retry = 10;
do {
- target_read_u32(target, info->flc_base + FLSH_CN, &flsh_cn);
- } while ((--retry > 0) && (flsh_cn & FLSH_CN_PEND));
+ target_read_u32(target, info->flc_base + FLC_CN, &flash_cn);
+ } while ((--retry > 0) && max32xxx_flash_busy(flash_cn));
if (retry <= 0) {
- LOG_ERROR("Timed out waiting for flash write @ 0x%08" PRIx32, address);
+ LOG_ERROR("Timed out waiting for flash write @ 0x%08" PRIx32,
+ address);
+ max32xxx_flash_op_post(bank);
return ERROR_FLASH_OPERATION_FAILED;
}
@@ -517,31 +581,32 @@ static int max32xxx_write(struct flash_bank *bank, const uint8_t *buffer,
}
}
- if ((info->burst_size_bits == 128) && (remaining >= 16)) {
- /* write in 128-bit bursts while we can */
- target_read_u32(target, info->flc_base + FLSH_CN, &flsh_cn);
-
- flsh_cn &= 0xFFFFFFEF;
- flsh_cn |= 0x08000000;
- target_write_u32(target, info->flc_base + FLSH_CN, flsh_cn);
- target_write_u32(target, info->flc_base + FLSH_ADDR, address);
+ if ((info->options & OPTIONS_128) && remaining >= 16) {
+ // write in 128-bit units
+ target_read_u32(target, info->flc_base + FLC_CN, &flash_cn);
+ flash_cn &= ~(FLC_CN_32BIT);
+ target_write_u32(target, info->flc_base + FLC_CN, flash_cn);
while (remaining >= 16) {
+ target_write_u32(target, info->flc_base + FLC_ADDR, address);
+
if ((address & 0xFFF) == 0)
LOG_DEBUG("Writing @ 0x%08" PRIx32, address);
- target_write_buffer(target, info->flc_base + FLSH_DATA0, 16, buffer);
- flsh_cn |= 0x00000001;
- target_write_u32(target, info->flc_base + FLSH_CN, flsh_cn);
- /* Wait until flash operation is complete */
+ target_write_buffer(target, info->flc_base + FLC_DATA0, 16, buffer);
+ flash_cn |= FLC_CN_WR;
+ target_write_u32(target, info->flc_base + FLC_CN, flash_cn);
+ // Wait until flash operation is complete
retry = 10;
do {
- target_read_u32(target, info->flc_base + FLSH_CN, &flsh_cn);
- } while ((--retry > 0) && (flsh_cn & FLSH_CN_PEND));
+ target_read_u32(target, info->flc_base + FLC_CN, &flash_cn);
+ } while ((--retry > 0) && max32xxx_flash_busy(flash_cn));
if (retry <= 0) {
- LOG_ERROR("Timed out waiting for flash write @ 0x%08" PRIx32, address);
+ LOG_ERROR("Timed out waiting for flash write @ 0x%08" PRIx32,
+ address);
+ max32xxx_flash_op_post(bank);
return ERROR_FLASH_OPERATION_FAILED;
}
@@ -551,73 +616,92 @@ static int max32xxx_write(struct flash_bank *bank, const uint8_t *buffer,
}
}
- if (remaining >= 4) {
+ if (((info->options & OPTIONS_128) == 0) && remaining > 0) {
+ // write remaining bytes in a 32-bit unit
+ target_read_u32(target, info->flc_base + FLC_CN, &flash_cn);
+ flash_cn |= FLC_CN_32BIT;
+ target_write_u32(target, info->flc_base + FLC_CN, flash_cn);
- /* write in 32-bit units while we can */
- target_read_u32(target, info->flc_base + FLSH_CN, &flsh_cn);
- flsh_cn &= 0xF7FFFFFF;
- flsh_cn |= 0x00000010;
- target_write_u32(target, info->flc_base + FLSH_CN, flsh_cn);
+ uint8_t last_word[4] = {0xFF, 0xFF, 0xFF, 0xFF};
+ uint32_t i = 0;
- while (remaining >= 4) {
- target_write_u32(target, info->flc_base + FLSH_ADDR, address);
- target_write_buffer(target, info->flc_base + FLSH_DATA0, 4, buffer);
- flsh_cn |= 0x00000001;
- target_write_u32(target, info->flc_base + FLSH_CN, flsh_cn);
- /* Wait until flash operation is complete */
- retry = 10;
+ while (remaining > 0) {
+ last_word[i++] = *buffer;
+ buffer++;
+ remaining--;
+ }
- do {
- target_read_u32(target, info->flc_base + FLSH_CN, &flsh_cn);
- } while ((--retry > 0) && (flsh_cn & FLSH_CN_PEND));
+ target_write_u32(target, info->flc_base + FLC_ADDR, address);
+ target_write_buffer(target, info->flc_base + FLC_DATA0, 4, last_word);
+ flash_cn |= FLC_CN_WR;
+ target_write_u32(target, info->flc_base + FLC_CN, flash_cn);
- if (retry <= 0) {
- LOG_ERROR("Timed out waiting for flash write @ 0x%08" PRIx32, address);
- return ERROR_FLASH_OPERATION_FAILED;
- }
+ // Wait until flash operation is complete
+ retry = 10;
- buffer += 4;
- address += 4;
- remaining -= 4;
+ do {
+ target_read_u32(target, info->flc_base + FLC_CN, &flash_cn);
+ } while ((--retry > 0) && max32xxx_flash_busy(flash_cn));
+
+ if (retry <= 0) {
+ LOG_ERROR("Timed out waiting for flash write @ 0x%08" PRIx32, address);
+ max32xxx_flash_op_post(bank);
+ return ERROR_FLASH_OPERATION_FAILED;
}
}
- if (remaining > 0) {
- /* write remaining bytes in a 32-bit unit */
- target_read_u32(target, info->flc_base + FLSH_CN, &flsh_cn);
- flsh_cn &= 0xF7FFFFFF;
- flsh_cn |= 0x00000010;
- target_write_u32(target, info->flc_base + FLSH_CN, flsh_cn);
+ if ((info->options & OPTIONS_128) && remaining > 0) {
+ // write remaining bytes in a 128-bit unit
+ if (target_read_u32(target, info->flc_base + FLC_CN, &flash_cn) != ERROR_OK) {
+ max32xxx_flash_op_post(bank);
+ return ERROR_FAIL;
+ }
+
+ target_read_u32(target, info->flc_base + FLC_CN, &flash_cn);
+ flash_cn &= ~(FLC_CN_32BIT);
+ target_write_u32(target, info->flc_base + FLC_CN, flash_cn);
+
+ uint8_t last_words[16] = {0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF};
- uint8_t last_word[4] = {0xff, 0xff, 0xff, 0xff};
- int i = 0;
+ uint32_t i = 0;
while (remaining > 0) {
- last_word[i++] = *buffer;
+ last_words[i++] = *buffer;
buffer++;
remaining--;
}
- target_write_u32(target, info->flc_base + FLSH_ADDR, address);
- target_write_buffer(target, info->flc_base + FLSH_DATA0, 4, last_word);
- flsh_cn |= 0x00000001;
- target_write_u32(target, info->flc_base + FLSH_CN, flsh_cn);
- /* Wait until flash operation is complete */
- retry = 10;
+ target_write_u32(target, info->flc_base + FLC_ADDR, address);
+ target_write_buffer(target, info->flc_base + FLC_DATA0, 4, last_words);
+ target_write_buffer(target, info->flc_base + FLC_DATA0 + 4, 4, last_words + 4);
+ target_write_buffer(target, info->flc_base + FLC_DATA0 + 8, 4, last_words + 8);
+ target_write_buffer(target, info->flc_base + FLC_DATA0 + 12, 4, last_words + 12);
+ flash_cn |= FLC_CN_WR;
+ target_write_u32(target, info->flc_base + FLC_CN, flash_cn);
+ // Wait until flash operation is complete
+ retry = 10;
do {
- target_read_u32(target, info->flc_base + FLSH_CN, &flsh_cn);
- } while ((--retry > 0) && (flsh_cn & FLSH_CN_PEND));
+ if (target_read_u32(target, info->flc_base + FLC_CN,
+ &flash_cn) != ERROR_OK) {
+ max32xxx_flash_op_post(bank);
+ return ERROR_FAIL;
+ }
+ } while ((--retry > 0) && (flash_cn & FLC_CN_PEND));
if (retry <= 0) {
LOG_ERROR("Timed out waiting for flash write @ 0x%08" PRIx32, address);
+ max32xxx_flash_op_post(bank);
return ERROR_FLASH_OPERATION_FAILED;
}
}
- /* Check access violations */
- target_read_u32(target, info->flc_base + FLSH_INT, &flsh_int);
- if (flsh_int & FLSH_INT_AF) {
+ // Check access violations
+ target_read_u32(target, info->flc_base + FLC_INT, &flash_int);
+ if (flash_int & FLC_INT_AF) {
LOG_ERROR("Flash Error writing 0x%" PRIx32 " bytes at 0x%08" PRIx32, count, offset);
max32xxx_flash_op_post(bank);
return ERROR_FLASH_OPERATION_FAILED;
@@ -638,7 +722,7 @@ static int max32xxx_probe(struct flash_bank *bank)
free(bank->sectors);
- /* provide this for the benefit of the NOR flash framework */
+ // provide this for the benefit of the NOR flash framework
bank->size = info->flash_size;
bank->num_sectors = info->flash_size / info->sector_size;
bank->sectors = calloc(bank->num_sectors, sizeof(struct flash_sector));
@@ -650,24 +734,24 @@ static int max32xxx_probe(struct flash_bank *bank)
bank->sectors[i].is_protected = -1;
}
- /* Probe to determine if this part is in the max326xx family */
- info->max326xx = 0;
+ // Probe to determine if this part is in the max326xx family
+ info->max326xx = false;
target_read_u32(target, ARM_PID_REG, &arm_id[0]);
- target_read_u32(target, ARM_PID_REG+4, &arm_id[1]);
+ target_read_u32(target, ARM_PID_REG + 4, &arm_id[1]);
arm_pid = (arm_id[1] << 8) + arm_id[0];
LOG_DEBUG("arm_pid = 0x%x", arm_pid);
- if ((arm_pid == ARM_PID_DEFAULT_CM3) || arm_pid == ARM_PID_DEFAULT_CM4) {
+ if (arm_pid == ARM_PID_DEFAULT_CM3 || arm_pid == ARM_PID_DEFAULT_CM4) {
uint32_t max326xx_id;
target_read_u32(target, MAX326XX_ID_REG, &max326xx_id);
LOG_DEBUG("max326xx_id = 0x%" PRIx32, max326xx_id);
max326xx_id = ((max326xx_id & 0xFF000000) >> 24);
if (max326xx_id == MAX326XX_ID)
- info->max326xx = 1;
+ info->max326xx = true;
}
LOG_DEBUG("info->max326xx = %d", info->max326xx);
- /* Initialize the protection bits for each flash page */
+ // Initialize the protection bits for each flash page
if (max32xxx_protect_check(bank) == ERROR_FLASH_OPER_UNSUPPORTED)
LOG_WARNING("Flash protection not supported on this device");
@@ -679,7 +763,7 @@ static int max32xxx_mass_erase(struct flash_bank *bank)
{
struct target *target = NULL;
struct max32xxx_flash_bank *info = NULL;
- uint32_t flsh_cn, flsh_int;
+ uint32_t flash_cn, flash_int;
int retval;
int retry;
info = bank->driver_priv;
@@ -693,50 +777,50 @@ static int max32xxx_mass_erase(struct flash_bank *bank)
if (!info->probed)
return ERROR_FLASH_BANK_NOT_PROBED;
- int not_protected = 0;
+ bool protected = true;
for (unsigned int i = 0; i < bank->num_sectors; i++) {
if (bank->sectors[i].is_protected == 1)
LOG_WARNING("Flash sector %u is protected", i);
else
- not_protected = 1;
+ protected = false;
}
- if (!not_protected) {
+ if (protected) {
LOG_ERROR("All pages protected");
return ERROR_FAIL;
}
- /* Prepare to issue flash operation */
+ // Prepare to issue flash operation
retval = max32xxx_flash_op_pre(bank);
if (retval != ERROR_OK)
return retval;
- /* Write mass erase code */
- target_read_u32(target, info->flc_base + FLSH_CN, &flsh_cn);
- flsh_cn |= FLSH_CN_ERASE_CODE_ME;
- target_write_u32(target, info->flc_base + FLSH_CN, flsh_cn);
+ // Write mass erase code
+ target_read_u32(target, info->flc_base + FLC_CN, &flash_cn);
+ flash_cn |= FLC_CN_ERASE_CODE_ME;
+ target_write_u32(target, info->flc_base + FLC_CN, flash_cn);
- /* Issue mass erase command */
- flsh_cn |= 0x2;
- target_write_u32(target, info->flc_base + FLSH_CN, flsh_cn);
+ // Issue mass erase command
+ flash_cn |= FLC_CN_ME;
+ target_write_u32(target, info->flc_base + FLC_CN, flash_cn);
- /* Wait until erase complete */
+ // Wait until erase complete
retry = 1000;
do {
- target_read_u32(target, info->flc_base + FLSH_CN, &flsh_cn);
- } while ((--retry > 0) && (flsh_cn & FLSH_CN_PEND));
+ target_read_u32(target, info->flc_base + FLC_CN, &flash_cn);
+ } while ((--retry > 0) && max32xxx_flash_busy(flash_cn));
if (retry <= 0) {
LOG_ERROR("Timed out waiting for flash mass erase");
return ERROR_FLASH_OPERATION_FAILED;
}
- /* Check access violations */
- target_read_u32(target, info->flc_base + FLSH_INT, &flsh_int);
- if (flsh_int & FLSH_INT_AF) {
+ // Check access violations
+ target_read_u32(target, info->flc_base + FLC_INT, &flash_int);
+ if (flash_int & FLC_INT_AF) {
LOG_ERROR("Error mass erasing");
- target_write_u32(target, info->flc_base + FLSH_INT, 0);
+ target_write_u32(target, info->flc_base + FLC_INT, 0);
return ERROR_FLASH_OPERATION_FAILED;
}
@@ -784,34 +868,34 @@ COMMAND_HANDLER(max32xxx_handle_protection_set_command)
return retval;
info = bank->driver_priv;
- /* Convert the range to the page numbers */
- if (sscanf(CMD_ARGV[1], "0x%"SCNx32, &addr) != 1) {
+ // Convert the range to the page numbers
+ if (sscanf(CMD_ARGV[1], "0x%" SCNx32, &addr) != 1) {
LOG_WARNING("Error parsing address");
command_print(CMD, "max32xxx protection_set ");
return ERROR_FAIL;
}
- /* Mask off the top portion on the address */
+ // Mask off the top portion on the address
addr = (addr & 0x0FFFFFFF);
- if (sscanf(CMD_ARGV[2], "0x%"SCNx32, &len) != 1) {
+ if (sscanf(CMD_ARGV[2], "0x%" SCNx32, &len) != 1) {
LOG_WARNING("Error parsing length");
command_print(CMD, "max32xxx protection_set ");
return ERROR_FAIL;
}
- /* Check the address is in the range of the flash */
- if ((addr+len) >= info->flash_size)
+ // Check the address is in the range of the flash
+ if ((addr + len) >= info->flash_size)
return ERROR_FLASH_SECTOR_INVALID;
if (len == 0)
return ERROR_OK;
- /* Convert the address and length to the page boundaries */
+ // Convert the address and length to the page boundaries
addr = addr - (addr % info->sector_size);
if (len % info->sector_size)
len = len + info->sector_size - (len % info->sector_size);
- /* Convert the address and length to page numbers */
+ // Convert the address and length to page numbers
addr = (addr / info->sector_size);
len = addr + (len / info->sector_size) - 1;
@@ -840,34 +924,34 @@ COMMAND_HANDLER(max32xxx_handle_protection_clr_command)
return retval;
info = bank->driver_priv;
- /* Convert the range to the page numbers */
- if (sscanf(CMD_ARGV[1], "0x%"SCNx32, &addr) != 1) {
+ // Convert the range to the page numbers
+ if (sscanf(CMD_ARGV[1], "0x%" SCNx32, &addr) != 1) {
LOG_WARNING("Error parsing address");
command_print(CMD, "max32xxx protection_clr ");
return ERROR_FAIL;
}
- /* Mask off the top portion on the address */
+ // Mask off the top portion on the address
addr = (addr & 0x0FFFFFFF);
- if (sscanf(CMD_ARGV[2], "0x%"SCNx32, &len) != 1) {
+ if (sscanf(CMD_ARGV[2], "0x%" SCNx32, &len) != 1) {
LOG_WARNING("Error parsing length");
command_print(CMD, "max32xxx protection_clr ");
return ERROR_FAIL;
}
- /* Check the address is in the range of the flash */
- if ((addr+len) >= info->flash_size)
+ // Check the address is in the range of the flash
+ if ((addr + len) >= info->flash_size)
return ERROR_FLASH_SECTOR_INVALID;
if (len == 0)
return ERROR_OK;
- /* Convert the address and length to the page boundaries */
+ // Convert the address and length to the page boundaries
addr = addr - (addr % info->sector_size);
if (len % info->sector_size)
len = len + info->sector_size - (len % info->sector_size);
- /* Convert the address and length to page numbers */
+ // Convert the address and length to page numbers
addr = (addr / info->sector_size);
len = addr + (len / info->sector_size) - 1;
@@ -895,7 +979,7 @@ COMMAND_HANDLER(max32xxx_handle_protection_check_command)
return retval;
info = bank->driver_priv;
- /* Update the protection array */
+ // Update the protection array
retval = max32xxx_protect_check(bank);
if (retval != ERROR_OK) {
LOG_WARNING("Error updating the protection array");
@@ -905,10 +989,10 @@ COMMAND_HANDLER(max32xxx_handle_protection_check_command)
LOG_WARNING("s: a: p:");
for (unsigned int i = 0; i < bank->num_sectors; i += 4) {
LOG_WARNING("s:%03d a:0x%06x p:%d | s:%03d a:0x%06x p:%d | s:%03d a:0x%06x p:%d | s:%03d a:0x%06x p:%d",
- (i+0), (i+0)*info->sector_size, bank->sectors[(i+0)].is_protected,
- (i+1), (i+1)*info->sector_size, bank->sectors[(i+1)].is_protected,
- (i+2), (i+2)*info->sector_size, bank->sectors[(i+2)].is_protected,
- (i+3), (i+3)*info->sector_size, bank->sectors[(i+3)].is_protected);
+ (i + 0), (i + 0) * info->sector_size, bank->sectors[(i + 0)].is_protected,
+ (i + 1), (i + 1) * info->sector_size, bank->sectors[(i + 1)].is_protected,
+ (i + 2), (i + 2) * info->sector_size, bank->sectors[(i + 2)].is_protected,
+ (i + 3), (i + 3) * info->sector_size, bank->sectors[(i + 3)].is_protected);
}
return ERROR_OK;
@@ -970,4 +1054,5 @@ const struct flash_driver max32xxx_flash = {
.erase_check = default_flash_blank_check,
.protect_check = max32xxx_protect_check,
.info = get_info,
+ .free_driver_priv = default_flash_free_driver_priv,
};
diff --git a/src/flash/nor/msp432.c b/src/flash/nor/msp432.c
index b5e2b0bf86..d7cc253ae5 100644
--- a/src/flash/nor/msp432.c
+++ b/src/flash/nor/msp432.c
@@ -90,56 +90,56 @@ static int msp432_device_type(uint32_t family_type, uint32_t device_id,
/* Examine the device ID and hardware revision to get the device type */
switch (device_id) {
- case 0xA000:
- case 0xA001:
- case 0xA002:
- case 0xA003:
- case 0xA004:
- case 0xA005:
- /* Device is definitely MSP432P401x, check hardware revision */
- if (hardware_rev == 0x41 || hardware_rev == 0x42) {
- /* Rev A or B of the silicon has been deprecated */
- device_type = MSP432P401X_DEPR;
- } else if (hardware_rev >= 0x43 && hardware_rev <= 0x49) {
- /* Current and future revisions of the MSP432P401x device */
- device_type = MSP432P401X;
- } else {
- /* Unknown or unanticipated hardware revision */
- device_type = MSP432P401X_GUESS;
- }
- break;
- case 0xA010:
- case 0xA012:
- case 0xA016:
- case 0xA019:
- case 0xA01F:
- case 0xA020:
- case 0xA022:
- case 0xA026:
- case 0xA029:
- case 0xA02F:
- /* Device is definitely MSP432P411x, check hardware revision */
- if (hardware_rev >= 0x41 && hardware_rev <= 0x49) {
- /* Current and future revisions of the MSP432P411x device */
- device_type = MSP432P411X;
- } else {
- /* Unknown or unanticipated hardware revision */
- device_type = MSP432P411X_GUESS;
- }
- break;
- case 0xFFFF:
- /* Device is very early silicon that has been deprecated */
+ case 0xA000:
+ case 0xA001:
+ case 0xA002:
+ case 0xA003:
+ case 0xA004:
+ case 0xA005:
+ /* Device is definitely MSP432P401x, check hardware revision */
+ if (hardware_rev == 0x41 || hardware_rev == 0x42) {
+ /* Rev A or B of the silicon has been deprecated */
device_type = MSP432P401X_DEPR;
- break;
- default:
- if (device_id < 0xA010) {
- /* Wild guess that this is an MSP432P401x */
- device_type = MSP432P401X_GUESS;
- } else {
- /* Reasonable guess that this is a new variant */
- device_type = MSP432P411X_GUESS;
- }
- break;
+ } else if (hardware_rev >= 0x43 && hardware_rev <= 0x49) {
+ /* Current and future revisions of the MSP432P401x device */
+ device_type = MSP432P401X;
+ } else {
+ /* Unknown or unanticipated hardware revision */
+ device_type = MSP432P401X_GUESS;
+ }
+ break;
+ case 0xA010:
+ case 0xA012:
+ case 0xA016:
+ case 0xA019:
+ case 0xA01F:
+ case 0xA020:
+ case 0xA022:
+ case 0xA026:
+ case 0xA029:
+ case 0xA02F:
+ /* Device is definitely MSP432P411x, check hardware revision */
+ if (hardware_rev >= 0x41 && hardware_rev <= 0x49) {
+ /* Current and future revisions of the MSP432P411x device */
+ device_type = MSP432P411X;
+ } else {
+ /* Unknown or unanticipated hardware revision */
+ device_type = MSP432P411X_GUESS;
+ }
+ break;
+ case 0xFFFF:
+ /* Device is very early silicon that has been deprecated */
+ device_type = MSP432P401X_DEPR;
+ break;
+ default:
+ if (device_id < 0xA010) {
+ /* Wild guess that this is an MSP432P401x */
+ device_type = MSP432P401X_GUESS;
+ } else {
+ /* Reasonable guess that this is a new variant */
+ device_type = MSP432P411X_GUESS;
+ }
+ break;
}
}
@@ -149,22 +149,22 @@ static int msp432_device_type(uint32_t family_type, uint32_t device_id,
static const char *msp432_return_text(uint32_t return_code)
{
switch (return_code) {
- case FLASH_BUSY:
- return "FLASH_BUSY";
- case FLASH_SUCCESS:
- return "FLASH_SUCCESS";
- case FLASH_ERROR:
- return "FLASH_ERROR";
- case FLASH_TIMEOUT_ERROR:
- return "FLASH_TIMEOUT_ERROR";
- case FLASH_VERIFY_ERROR:
- return "FLASH_VERIFY_WRONG";
- case FLASH_WRONG_COMMAND:
- return "FLASH_WRONG_COMMAND";
- case FLASH_POWER_ERROR:
- return "FLASH_POWER_ERROR";
- default:
- return "UNDEFINED_RETURN_CODE";
+ case FLASH_BUSY:
+ return "FLASH_BUSY";
+ case FLASH_SUCCESS:
+ return "FLASH_SUCCESS";
+ case FLASH_ERROR:
+ return "FLASH_ERROR";
+ case FLASH_TIMEOUT_ERROR:
+ return "FLASH_TIMEOUT_ERROR";
+ case FLASH_VERIFY_ERROR:
+ return "FLASH_VERIFY_WRONG";
+ case FLASH_WRONG_COMMAND:
+ return "FLASH_WRONG_COMMAND";
+ case FLASH_POWER_ERROR:
+ return "FLASH_POWER_ERROR";
+ default:
+ return "UNDEFINED_RETURN_CODE";
}
}
@@ -219,10 +219,10 @@ static int msp432_wait_return_code(struct target *target)
return retval;
elapsed_ms = timeval_ms() - start_ms;
- if (elapsed_ms > 500)
- keep_alive();
if (elapsed_ms > FLASH_TIMEOUT)
break;
+
+ keep_alive();
};
if (return_code != FLASH_SUCCESS) {
@@ -244,14 +244,14 @@ static int msp432_wait_inactive(struct target *target, uint32_t buffer)
int retval;
switch (buffer) {
- case 1: /* Buffer 1 */
- status_addr = ALGO_BUFFER1_STATUS_ADDR;
- break;
- case 2: /* Buffer 2 */
- status_addr = ALGO_BUFFER2_STATUS_ADDR;
- break;
- default:
- return ERROR_FAIL;
+ case 1: /* Buffer 1 */
+ status_addr = ALGO_BUFFER1_STATUS_ADDR;
+ break;
+ case 2: /* Buffer 2 */
+ status_addr = ALGO_BUFFER2_STATUS_ADDR;
+ break;
+ default:
+ return ERROR_FAIL;
}
start_ms = timeval_ms();
@@ -261,10 +261,10 @@ static int msp432_wait_inactive(struct target *target, uint32_t buffer)
return retval;
elapsed_ms = timeval_ms() - start_ms;
- if (elapsed_ms > 500)
- keep_alive();
if (elapsed_ms > FLASH_TIMEOUT)
break;
+
+ keep_alive();
};
if (status_code != BUFFER_INACTIVE) {
@@ -295,27 +295,27 @@ static int msp432_init(struct flash_bank *bank)
/* Choose appropriate flash helper algorithm */
switch (msp432_bank->device_type) {
- case MSP432P401X:
- case MSP432P401X_DEPR:
- case MSP432P401X_GUESS:
- default:
- loader_code = msp432p401x_algo;
- loader_size = sizeof(msp432p401x_algo);
- algo_entry_addr = P4_ALGO_ENTRY_ADDR;
- break;
- case MSP432P411X:
- case MSP432P411X_GUESS:
- loader_code = msp432p411x_algo;
- loader_size = sizeof(msp432p411x_algo);
- algo_entry_addr = P4_ALGO_ENTRY_ADDR;
- break;
- case MSP432E401Y:
- case MSP432E411Y:
- case MSP432E4X_GUESS:
- loader_code = msp432e4x_algo;
- loader_size = sizeof(msp432e4x_algo);
- algo_entry_addr = E4_ALGO_ENTRY_ADDR;
- break;
+ case MSP432P401X:
+ case MSP432P401X_DEPR:
+ case MSP432P401X_GUESS:
+ default:
+ loader_code = msp432p401x_algo;
+ loader_size = sizeof(msp432p401x_algo);
+ algo_entry_addr = P4_ALGO_ENTRY_ADDR;
+ break;
+ case MSP432P411X:
+ case MSP432P411X_GUESS:
+ loader_code = msp432p411x_algo;
+ loader_size = sizeof(msp432p411x_algo);
+ algo_entry_addr = P4_ALGO_ENTRY_ADDR;
+ break;
+ case MSP432E401Y:
+ case MSP432E411Y:
+ case MSP432E4X_GUESS:
+ loader_code = msp432e4x_algo;
+ loader_size = sizeof(msp432e4x_algo);
+ algo_entry_addr = E4_ALGO_ENTRY_ADDR;
+ break;
}
/* Issue warnings if this is a device we may not be able to flash */
@@ -678,8 +678,6 @@ static int msp432_write(struct flash_bank *bank, const uint8_t *buffer,
struct msp432_algo_params algo_params;
uint32_t size;
uint32_t data_ready = BUFFER_DATA_READY;
- long long start_ms;
- long long elapsed_ms;
bool is_info = bank->base == P4_FLASH_INFO_BASE;
@@ -753,7 +751,6 @@ static int msp432_write(struct flash_bank *bank, const uint8_t *buffer,
}
/* Write requested data, one buffer at a time */
- start_ms = timeval_ms();
while (count > 0) {
if (count > ALGO_BUFFER_SIZE)
@@ -786,9 +783,7 @@ static int msp432_write(struct flash_bank *bank, const uint8_t *buffer,
count -= size;
buffer += size;
- elapsed_ms = timeval_ms() - start_ms;
- if (elapsed_ms > 500)
- keep_alive();
+ keep_alive();
}
/* Confirm that the flash helper algorithm is finished */
@@ -985,43 +980,43 @@ static int msp432_info(struct flash_bank *bank, struct command_invocation *cmd)
struct msp432_bank *msp432_bank = bank->driver_priv;
switch (msp432_bank->device_type) {
- case MSP432P401X_DEPR:
- if (msp432_bank->device_id == 0xFFFF) {
- /* Very early pre-production silicon currently deprecated */
- command_print_sameline(cmd, "MSP432P401x pre-production device (deprecated silicon)\n"
- SUPPORT_MESSAGE);
- } else {
- /* Revision A or B silicon, also deprecated */
- command_print_sameline(cmd, "MSP432P401x Device Rev %c (deprecated silicon)\n"
- SUPPORT_MESSAGE, (char)msp432_bank->hardware_rev);
- }
- break;
- case MSP432P401X:
- command_print_sameline(cmd, "MSP432P401x Device Rev %c\n",
- (char)msp432_bank->hardware_rev);
- break;
- case MSP432P411X:
- command_print_sameline(cmd, "MSP432P411x Device Rev %c\n",
- (char)msp432_bank->hardware_rev);
- break;
- case MSP432E401Y:
- command_print_sameline(cmd, "MSP432E401Y Device\n");
- break;
- case MSP432E411Y:
- command_print_sameline(cmd, "MSP432E411Y Device\n");
- break;
- case MSP432E4X_GUESS:
- command_print_sameline(cmd,
- "Unrecognized MSP432E4 DID0 and DID1 IDs (%08" PRIX32 ", %08" PRIX32 ")",
- msp432_bank->device_id, msp432_bank->hardware_rev);
- break;
- case MSP432P401X_GUESS:
- case MSP432P411X_GUESS:
- default:
- command_print_sameline(cmd,
- "Unrecognized MSP432P4 Device ID and Hardware Rev (%04" PRIX32 ", %02" PRIX32 ")",
- msp432_bank->device_id, msp432_bank->hardware_rev);
- break;
+ case MSP432P401X_DEPR:
+ if (msp432_bank->device_id == 0xFFFF) {
+ /* Very early pre-production silicon currently deprecated */
+ command_print_sameline(cmd, "MSP432P401x pre-production device (deprecated silicon)\n"
+ SUPPORT_MESSAGE);
+ } else {
+ /* Revision A or B silicon, also deprecated */
+ command_print_sameline(cmd, "MSP432P401x Device Rev %c (deprecated silicon)\n"
+ SUPPORT_MESSAGE, (char)msp432_bank->hardware_rev);
+ }
+ break;
+ case MSP432P401X:
+ command_print_sameline(cmd, "MSP432P401x Device Rev %c\n",
+ (char)msp432_bank->hardware_rev);
+ break;
+ case MSP432P411X:
+ command_print_sameline(cmd, "MSP432P411x Device Rev %c\n",
+ (char)msp432_bank->hardware_rev);
+ break;
+ case MSP432E401Y:
+ command_print_sameline(cmd, "MSP432E401Y Device\n");
+ break;
+ case MSP432E411Y:
+ command_print_sameline(cmd, "MSP432E411Y Device\n");
+ break;
+ case MSP432E4X_GUESS:
+ command_print_sameline(cmd,
+ "Unrecognized MSP432E4 DID0 and DID1 IDs (%08" PRIX32 ", %08" PRIX32 ")",
+ msp432_bank->device_id, msp432_bank->hardware_rev);
+ break;
+ case MSP432P401X_GUESS:
+ case MSP432P411X_GUESS:
+ default:
+ command_print_sameline(cmd,
+ "Unrecognized MSP432P4 Device ID and Hardware Rev (%04" PRIX32 ", %02" PRIX32 ")",
+ msp432_bank->device_id, msp432_bank->hardware_rev);
+ break;
}
return ERROR_OK;
diff --git a/src/flash/nor/mspm0.c b/src/flash/nor/mspm0.c
index 4731c89ccf..62fd5e8c40 100644
--- a/src/flash/nor/mspm0.c
+++ b/src/flash/nor/mspm0.c
@@ -429,7 +429,7 @@ static int mspm0_read_part_info(struct flash_bank *bank)
LOG_WARNING("Unknown Device ID[0x%" PRIx32 "], cannot identify target",
did);
LOG_DEBUG("did 0x%" PRIx32 ", traceid 0x%" PRIx32 ", userid 0x%" PRIx32
- ", flashram 0x%" PRIx32 "", did, mspm0_info->traceid, userid,
+ ", flashram 0x%" PRIx32, did, mspm0_info->traceid, userid,
flashram);
return ERROR_FLASH_OPERATION_FAILED;
}
@@ -737,10 +737,10 @@ static int mspm0_fctl_wait_cmd_ok(struct flash_bank *bank)
return retval;
elapsed_ms = timeval_ms() - start_ms;
- if (elapsed_ms > 500)
- keep_alive();
if (elapsed_ms > MSPM0_FLASH_TIMEOUT_MS)
break;
+
+ keep_alive();
}
if ((return_code & FCTL_STATCMD_CMDPASS_MASK) != FCTL_STATCMD_CMDPASS_STATPASS) {
diff --git a/src/flash/nor/numicro.c b/src/flash/nor/numicro.c
index a0c6e0c815..5809494df0 100644
--- a/src/flash/nor/numicro.c
+++ b/src/flash/nor/numicro.c
@@ -567,7 +567,7 @@ static int numicro_reg_unlock(struct target *target)
if (retval != ERROR_OK)
return retval;
- LOG_DEBUG("protected = 0x%08" PRIx32 "", is_protected);
+ LOG_DEBUG("protected = 0x%08" PRIx32, is_protected);
if (is_protected == 0) { /* means protected - so unlock it */
/* unlock flash registers */
retval = target_write_u32(target, NUMICRO_SYS_WRPROT - m_address_bias_offset, REG_KEY1);
@@ -828,7 +828,7 @@ static int numicro_protect_check(struct flash_bank *bank)
numicro_fmc_cmd(target, ISPCMD_READ, NUMICRO_CONFIG0 - m_address_bias_offset, 0, &config[0]);
numicro_fmc_cmd(target, ISPCMD_READ, NUMICRO_CONFIG1 - m_address_bias_offset, 0, &config[1]);
- LOG_DEBUG("CONFIG0: 0x%" PRIx32 ",CONFIG1: 0x%" PRIx32 "", config[0], config[1]);
+ LOG_DEBUG("CONFIG0: 0x%" PRIx32 ",CONFIG1: 0x%" PRIx32, config[0], config[1]);
if ((config[0] & (1<<7)) == 0)
LOG_INFO("CBS=0: Boot From LPROM");
@@ -908,7 +908,7 @@ static int numicro_erase(struct flash_bank *bank, unsigned int first,
if (retval != ERROR_OK)
return retval;
if ((status & ISPCON_ISPFF) != 0) {
- LOG_DEBUG("failure: 0x%" PRIx32 "", status);
+ LOG_DEBUG("failure: 0x%" PRIx32, status);
/* if bit is set, then must write to it to clear it. */
retval = target_write_u32(target, NUMICRO_FLASH_ISPCON - m_address_bias_offset, (status | ISPCON_ISPFF));
if (retval != ERROR_OK)
@@ -1007,7 +1007,7 @@ static int numicro_write(struct flash_bank *bank, const uint8_t *buffer,
if (retval != ERROR_OK)
return retval;
if ((status & ISPCON_ISPFF) != 0) {
- LOG_DEBUG("failure: 0x%" PRIx32 "", status);
+ LOG_DEBUG("failure: 0x%" PRIx32, status);
/* if bit is set, then must write to it to clear it. */
retval = target_write_u32(target,
NUMICRO_FLASH_ISPCON - m_address_bias_offset,
@@ -1037,7 +1037,7 @@ static int numicro_get_cpu_type(struct target *target, const struct numicro_cpu_
return ERROR_FLASH_OPERATION_FAILED;
}
- LOG_INFO("Device ID: 0x%08" PRIx32 "", part_id);
+ LOG_INFO("Device ID: 0x%08" PRIx32, part_id);
/* search part numbers */
for (size_t i = 0; i < ARRAY_SIZE(numicro_parts); i++) {
if (part_id == numicro_parts[i].partid) {
diff --git a/src/flash/nor/ocl.c b/src/flash/nor/ocl.c
index 61af908f58..6db7368f94 100644
--- a/src/flash/nor/ocl.c
+++ b/src/flash/nor/ocl.c
@@ -82,9 +82,9 @@ static int ocl_erase(struct flash_bank *bank, unsigned int first,
if (dcc_buffer[1] != OCL_CMD_DONE) {
if (dcc_buffer[0] == OCL_ERASE_ALL)
- LOG_ERROR("loader response to OCL_ERASE_ALL 0x%08" PRIx32 "", dcc_buffer[1]);
+ LOG_ERROR("loader response to OCL_ERASE_ALL 0x%08" PRIx32, dcc_buffer[1]);
else
- LOG_ERROR("loader response to OCL_ERASE_BLOCK 0x%08" PRIx32 "", dcc_buffer[1]);
+ LOG_ERROR("loader response to OCL_ERASE_BLOCK 0x%08" PRIx32, dcc_buffer[1]);
return ERROR_FLASH_OPERATION_FAILED;
}
@@ -132,21 +132,21 @@ static int ocl_write(struct flash_bank *bank, const uint8_t *buffer, uint32_t of
/* copy data to DCC buffer in proper byte order and properly aligned */
for (i = 0; i < runlen; i++) {
switch (byteofs++) {
- case 0:
- *dcc_bufptr &= *(buffer++) | 0xffffff00;
- break;
- case 1:
- *dcc_bufptr &= ((*(buffer++)) << 8) | 0xffff00ff;
- break;
- case 2:
- *dcc_bufptr &= ((*(buffer++)) << 16) | 0xff00ffff;
- break;
- case 3:
- *dcc_bufptr &= ((*(buffer++)) << 24) | 0x00ffffff;
- chksum ^= *(dcc_bufptr++);
- *dcc_bufptr = 0xffffffff;
- byteofs = 0;
- break;
+ case 0:
+ *dcc_bufptr &= *(buffer++) | 0xffffff00;
+ break;
+ case 1:
+ *dcc_bufptr &= ((*(buffer++)) << 8) | 0xffff00ff;
+ break;
+ case 2:
+ *dcc_bufptr &= ((*(buffer++)) << 16) | 0xff00ffff;
+ break;
+ case 3:
+ *dcc_bufptr &= ((*(buffer++)) << 24) | 0x00ffffff;
+ chksum ^= *(dcc_bufptr++);
+ *dcc_bufptr = 0xffffffff;
+ byteofs = 0;
+ break;
}
}
@@ -178,7 +178,7 @@ static int ocl_write(struct flash_bank *bank, const uint8_t *buffer, uint32_t of
}
if (dcc_buffer[0] != OCL_CMD_DONE) {
- LOG_ERROR("loader response to OCL_FLASH_BLOCK 0x%08" PRIx32 "", dcc_buffer[0]);
+ LOG_ERROR("loader response to OCL_FLASH_BLOCK 0x%08" PRIx32, dcc_buffer[0]);
free(dcc_buffer);
return ERROR_FLASH_OPERATION_FAILED;
}
@@ -217,7 +217,7 @@ static int ocl_probe(struct flash_bank *bank)
return retval;
if (dcc_buffer[0] != OCL_CMD_DONE) {
- LOG_ERROR("loader response to OCL_PROBE 0x%08" PRIx32 "", dcc_buffer[0]);
+ LOG_ERROR("loader response to OCL_PROBE 0x%08" PRIx32, dcc_buffer[0]);
return ERROR_FLASH_OPERATION_FAILED;
}
diff --git a/src/flash/nor/pic32mx.c b/src/flash/nor/pic32mx.c
index 982c9610a4..59e67cfe22 100644
--- a/src/flash/nor/pic32mx.c
+++ b/src/flash/nor/pic32mx.c
@@ -608,7 +608,7 @@ static int pic32mx_write(struct flash_bank *bank, const uint8_t *buffer, uint32_
}
LOG_DEBUG("writing to flash at address " TARGET_ADDR_FMT " at offset 0x%8.8" PRIx32
- " count: 0x%8.8" PRIx32 "", bank->base, offset, count);
+ " count: 0x%8.8" PRIx32, bank->base, offset, count);
if (offset & 0x3) {
LOG_WARNING("offset 0x%" PRIx32 "breaks required 4-byte alignment", offset);
@@ -900,7 +900,7 @@ COMMAND_HANDLER(pic32mx_handle_unlock_command)
mchip_cmd = MCHP_STATUS;
mips_ejtag_drscan_8(ejtag_info, &mchip_cmd);
if (timeout-- == 0) {
- LOG_DEBUG("timeout waiting for unlock: 0x%" PRIx8 "", mchip_cmd);
+ LOG_DEBUG("timeout waiting for unlock: 0x%" PRIx8, mchip_cmd);
break;
}
alive_sleep(1);
diff --git a/src/flash/nor/psoc4.c b/src/flash/nor/psoc4.c
index 72cf0ee05b..88f9b1310e 100644
--- a/src/flash/nor/psoc4.c
+++ b/src/flash/nor/psoc4.c
@@ -178,7 +178,7 @@ static const char *psoc4_decode_chip_protection(uint8_t protection)
case PSOC4_CHIP_PROT_KILL:
return "protection KILL";
default:
- LOG_WARNING("Unknown protection state 0x%02" PRIx8 "", protection);
+ LOG_WARNING("Unknown protection state 0x%02" PRIx8, protection);
return "";
}
}
@@ -658,7 +658,7 @@ static int psoc4_write(struct flash_bank *bank, const uint8_t *buffer,
memset(row_buffer + chunk_size, bank->default_padded_value, psoc4_info->row_size - chunk_size);
}
memcpy(row_buffer + row_offset, buffer, chunk_size);
- LOG_DEBUG("offset / row: 0x%08" PRIx32 " / %" PRIu32 ", size %" PRIu32 "",
+ LOG_DEBUG("offset / row: 0x%08" PRIx32 " / %" PRIu32 ", size %" PRIu32,
offset, row_offset, chunk_size);
uint32_t macro_idx = row_num / PSOC4_ROWS_PER_MACRO;
@@ -858,7 +858,7 @@ static int get_psoc4_info(struct flash_bank *bank, struct command_invocation *cm
"/0x%02" PRIx16 ", silicon id 0x%08" PRIx32,
psoc4_info->family_id, family_id, silicon_id);
else {
- command_print_sameline(cmd, "%s silicon id 0x%08" PRIx32 "",
+ command_print_sameline(cmd, "%s silicon id 0x%08" PRIx32,
family->name, silicon_id);
}
diff --git a/src/flash/nor/psoc6.c b/src/flash/nor/psoc6.c
index 662910aa04..3c7b06666b 100644
--- a/src/flash/nor/psoc6.c
+++ b/src/flash/nor/psoc6.c
@@ -420,17 +420,17 @@ static int psoc6_protect_check(struct flash_bank *bank)
return hr;
switch (psoc6_info->protection) {
- case PROTECTION_VIRGIN:
- case PROTECTION_NORMAL:
- is_protected = 0;
- break;
-
- case PROTECTION_UNKNOWN:
- case PROTECTION_SECURE:
- case PROTECTION_DEAD:
- default:
- is_protected = 1;
- break;
+ case PROTECTION_VIRGIN:
+ case PROTECTION_NORMAL:
+ is_protected = 0;
+ break;
+
+ case PROTECTION_UNKNOWN:
+ case PROTECTION_SECURE:
+ case PROTECTION_DEAD:
+ default:
+ is_protected = 1;
+ break;
}
for (unsigned int i = 0; i < bank->num_sectors; i++)
@@ -463,17 +463,17 @@ static int psoc6_protect(struct flash_bank *bank, int set, unsigned int first,
static const char *protection_to_str(uint8_t protection)
{
switch (protection) {
- case PROTECTION_VIRGIN:
- return "VIRGIN";
- case PROTECTION_NORMAL:
- return "NORMAL";
- case PROTECTION_SECURE:
- return "SECURE";
- case PROTECTION_DEAD:
- return "DEAD";
- case PROTECTION_UNKNOWN:
- default:
- return "UNKNOWN";
+ case PROTECTION_VIRGIN:
+ return "VIRGIN";
+ case PROTECTION_NORMAL:
+ return "NORMAL";
+ case PROTECTION_SECURE:
+ return "SECURE";
+ case PROTECTION_DEAD:
+ return "DEAD";
+ case PROTECTION_UNKNOWN:
+ default:
+ return "UNKNOWN";
}
}
diff --git a/src/flash/nor/qn908x.c b/src/flash/nor/qn908x.c
index 8cd7a2f04a..a881d549b1 100644
--- a/src/flash/nor/qn908x.c
+++ b/src/flash/nor/qn908x.c
@@ -257,7 +257,7 @@ static int qn908x_update_reg(struct target *target, target_addr_t reg,
}
if (mask == 0xffffffff) {
LOG_DEBUG("Updated reg at " TARGET_ADDR_FMT ": ?? -> 0x%.08"
- PRIx32 "", reg, new_value);
+ PRIx32, reg, new_value);
} else {
LOG_DEBUG("Updated reg at " TARGET_ADDR_FMT ": 0x%.08" PRIx32
" -> 0x%.08" PRIx32, reg, orig_value, new_value);
diff --git a/src/flash/nor/rp2xxx.c b/src/flash/nor/rp2xxx.c
index 85c5911041..30c6e99141 100644
--- a/src/flash/nor/rp2xxx.c
+++ b/src/flash/nor/rp2xxx.c
@@ -41,10 +41,18 @@
#define BOOTROM_STATE_RESET_OTHER_CORE 0x02
#define BOOTROM_STATE_RESET_GLOBAL_STATE 0x04
-#define ACCESSCTRL_LOCK_OFFSET 0x40060000u
-#define ACCESSCTRL_LOCK_DEBUG_BITS 0x00000008u
-#define ACCESSCTRL_CFGRESET_OFFSET 0x40060008u
-#define ACCESSCTRL_WRITE_PASSWORD 0xacce0000u
+#define ACCESSCTRL_LOCK_OFFSET 0x40060000u
+#define ACCESSCTRL_CFGRESET_OFFSET 0x40060008u
+#define ACCESSCTRL_GPIO_NSMASK0_OFFSET 0x4006000cu
+#define ACCESSCTRL_GPIO_ROM_OFFSET 0x40060014u
+#define ACCESSCTRL_GPIO_XIP_AUX_OFFSET 0x400600e8u
+
+#define ACCESSCTRL_SAVE_BASE ACCESSCTRL_GPIO_NSMASK0_OFFSET
+#define ACCESSCTRL_SAVE_SIZE \
+ (ACCESSCTRL_GPIO_XIP_AUX_OFFSET + 4 - ACCESSCTRL_SAVE_BASE)
+
+#define ACCESSCTRL_LOCK_DEBUG_BITS 0x00000008u
+#define ACCESSCTRL_WRITE_PASSWORD 0xacce0000u
#define RP2040_SSI_DR0 0x18000060
#define RP2040_QSPI_CTRL 0x4001800c
@@ -209,6 +217,10 @@ struct rp2xxx_flash_bank {
bool size_override;
struct flash_device spi_dev; /* detected model of SPI flash */
unsigned int sfdp_dummy, sfdp_dummy_detect;
+
+ struct cortex_m_saved_security saved_security;
+ bool accessctrl_dirty;
+ uint8_t saved_accessctrl[ACCESSCTRL_SAVE_SIZE]; /* in target byte order */
};
#ifndef LOG_ROM_SYMBOL_DEBUG
@@ -599,8 +611,28 @@ static int rp2xxx_call_rom_func(struct target *target, struct rp2xxx_flash_bank
return rp2xxx_call_rom_func_batch(target, priv, &call, 1);
}
-static int rp2350_init_accessctrl(struct target *target)
+static int rp2350_save_accessctrl(struct target *target, struct rp2xxx_flash_bank *priv)
+{
+ return target_read_memory(target, ACCESSCTRL_SAVE_BASE, 4, ACCESSCTRL_SAVE_SIZE / 4,
+ priv->saved_accessctrl);
+}
+
+static int rp2350_restore_accessctrl(struct target *target, struct rp2xxx_flash_bank *priv)
{
+ // Add write passwords to all ACCESSCTRL regs from ACCESSCTRL_GPIO_ROM to the end
+ // (exclude not keyed ACCESSCTRL_GPIO_NSMASK0 and ACCESSCTRL_GPIO_NSMASK1
+ for (unsigned int i = ACCESSCTRL_GPIO_ROM_OFFSET - ACCESSCTRL_SAVE_BASE;
+ i < ACCESSCTRL_SAVE_SIZE; i += 4)
+ target_buffer_set_u32(target, priv->saved_accessctrl + i,
+ target_buffer_get_u32(target, priv->saved_accessctrl + i) | ACCESSCTRL_WRITE_PASSWORD);
+
+ return target_write_memory(target, ACCESSCTRL_SAVE_BASE, 4, ACCESSCTRL_SAVE_SIZE / 4,
+ priv->saved_accessctrl);
+}
+
+static int rp2350_init_accessctrl(struct target *target, struct rp2xxx_flash_bank *priv)
+{
+ priv->accessctrl_dirty = false;
// Attempt to reset ACCESSCTRL, in case Secure access to SRAM has been
// blocked, which will stop us from loading/running algorithms such as RCP
// init. (Also ROM, QMI regs are needed later)
@@ -618,6 +650,13 @@ static int rp2350_init_accessctrl(struct target *target)
if (accessctrl_lock_reg & ACCESSCTRL_LOCK_DEBUG_BITS) {
LOG_ERROR("ACCESSCTRL is locked, so can't reset permissions. Following steps might fail");
} else {
+ int retval = rp2350_save_accessctrl(target, priv);
+ if (retval == ERROR_OK)
+ priv->accessctrl_dirty = true;
+ // If the ACCESSCTRL backup copy is valid, mark it dirty
+ // as we immediately proceed to ACCESSCTRL config reset.
+ // Don't fail on save ACCESSCTRL error, not vital for ROM API call
+
LOG_DEBUG("Reset ACCESSCTRL permissions via CFGRESET");
return target_write_u32(target, ACCESSCTRL_CFGRESET_OFFSET, ACCESSCTRL_WRITE_PASSWORD | 1u);
}
@@ -630,23 +669,12 @@ static int rp2350_init_arm_core0(struct target *target, struct rp2xxx_flash_bank
// run in the Secure state, so flip the state now before attempting to
// execute any code on the core.
int retval;
- uint32_t dscsr;
- retval = target_read_u32(target, DCB_DSCSR, &dscsr);
+ retval = cortex_m_set_secure(target, &priv->saved_security);
if (retval != ERROR_OK) {
- LOG_ERROR("RP2350 init ARM core: DSCSR read failed");
+ LOG_ERROR("RP2350 init ARM core: set secure mode failed");
return retval;
}
- LOG_DEBUG("DSCSR: 0x%08" PRIx32, dscsr);
- if (!(dscsr & DSCSR_CDS)) {
- LOG_DEBUG("Setting Current Domain Secure in DSCSR");
- retval = target_write_u32(target, DCB_DSCSR, (dscsr & ~DSCSR_CDSKEY) | DSCSR_CDS);
- if (retval != ERROR_OK) {
- LOG_ERROR("RP2350 init ARM core: DSCSR read failed");
- return retval;
- }
- }
-
if (!priv->stack) {
LOG_ERROR("No stack for flash programming code");
return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
@@ -713,7 +741,7 @@ static int setup_for_raw_flash_cmd(struct target *target, struct rp2xxx_flash_ba
}
if (IS_RP2350(priv->id)) {
- err = rp2350_init_accessctrl(target);
+ err = rp2350_init_accessctrl(target, priv);
if (err != ERROR_OK) {
LOG_ERROR("Failed to init ACCESSCTRL before ROM call");
return err;
@@ -840,6 +868,22 @@ static void cleanup_after_raw_flash_cmd(struct target *target, struct rp2xxx_fla
driver state. Best to clean up our allocations manually after
completing each flash call, so we know to make fresh ones next time. */
LOG_DEBUG("Cleaning up after flash operations");
+
+ if (IS_RP2350(priv->id)) {
+ int retval1 = ERROR_OK;
+ if (priv->accessctrl_dirty) {
+ retval1 = rp2350_restore_accessctrl(target, priv);
+ priv->accessctrl_dirty = false;
+ }
+
+ int retval2 = ERROR_OK;
+ if (is_arm(target_to_arm(target)))
+ retval2 = cortex_m_security_restore(target, &priv->saved_security);
+
+ if (retval1 != ERROR_OK || retval2 != ERROR_OK)
+ LOG_WARNING("RP2xxx: security state was not restored properly. Debug 'resume' will probably fail, use 'reset' instead");
+ /* Don't fail on security restore error, not vital for flash operation */
+ }
if (priv->stack) {
target_free_working_area(target, priv->stack);
priv->stack = 0;
diff --git a/src/flash/nor/spi.c b/src/flash/nor/spi.c
index bf654f9f6b..7f03f1fead 100644
--- a/src/flash/nor/spi.c
+++ b/src/flash/nor/spi.c
@@ -184,6 +184,16 @@ const struct flash_device flash_devices[] = {
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),
+ FLASH_ID("puya p25q05", 0x03, 0x6b, 0x02, 0x20, 0xc7, 0x00106085, 0x100, 0x1000, 0x10000),
+ FLASH_ID("puya p25q10", 0x03, 0x6b, 0x02, 0x20, 0xc7, 0x00116085, 0x100, 0x1000, 0x20000),
+ FLASH_ID("puya p25q20", 0x03, 0x6b, 0x02, 0x20, 0xc7, 0x00126085, 0x100, 0x1000, 0x40000),
+ FLASH_ID("puya p25q40", 0x03, 0x6b, 0x02, 0x20, 0xc7, 0x00136085, 0x100, 0x1000, 0x80000),
+ FLASH_ID("puya p25q80", 0x03, 0x6b, 0x02, 0x52, 0xc7, 0x00146085, 0x100, 0x8000, 0x100000),
+ FLASH_ID("puya p25q16", 0x03, 0x6b, 0x02, 0xd8, 0xc7, 0x00156085, 0x100, 0x10000, 0x200000),
+ FLASH_ID("puya p25q32", 0x03, 0x6b, 0x02, 0xd8, 0xc7, 0x00166085, 0x100, 0x10000, 0x400000),
+ FLASH_ID("puya p25q64", 0x03, 0x6b, 0x02, 0xd8, 0xc7, 0x00176085, 0x100, 0x10000, 0x800000),
+ FLASH_ID("puya p25q128", 0x03, 0x6b, 0x02, 0xd8, 0xc7, 0x00186085, 0x100, 0x10000, 0x1000000),
+
/* FRAM, no erase commands, no write page or sectors */
diff --git a/src/flash/nor/stellaris.c b/src/flash/nor/stellaris.c
index f7dcc6f0e3..bf598b1179 100644
--- a/src/flash/nor/stellaris.c
+++ b/src/flash/nor/stellaris.c
@@ -573,13 +573,13 @@ static void stellaris_read_clock_info(struct flash_bank *bank)
unsigned long mainfreq;
target_read_u32(target, SCB_BASE | RCC, &rcc);
- LOG_DEBUG("Stellaris RCC %" PRIx32 "", rcc);
+ LOG_DEBUG("Stellaris RCC %" PRIx32, rcc);
target_read_u32(target, SCB_BASE | RCC2, &rcc2);
- LOG_DEBUG("Stellaris RCC2 %" PRIx32 "", rcc);
+ LOG_DEBUG("Stellaris RCC2 %" PRIx32, rcc);
target_read_u32(target, SCB_BASE | PLLCFG, &pllcfg);
- LOG_DEBUG("Stellaris PLLCFG %" PRIx32 "", pllcfg);
+ LOG_DEBUG("Stellaris PLLCFG %" PRIx32, pllcfg);
stellaris_info->rcc = rcc;
stellaris_info->rcc2 = rcc2;
@@ -608,30 +608,30 @@ static void stellaris_read_clock_info(struct flash_bank *bank)
stellaris_info->mck_desc = "";
switch (oscsrc) {
- case 0: /* MOSC */
- mainfreq = rcc_xtal[xtal];
- break;
- case 1: /* IOSC */
- mainfreq = stellaris_info->iosc_freq;
- stellaris_info->mck_desc = stellaris_info->iosc_desc;
- break;
- case 2: /* IOSC/4 */
- mainfreq = stellaris_info->iosc_freq / 4;
- stellaris_info->mck_desc = stellaris_info->iosc_desc;
- break;
- case 3: /* lowspeed */
- /* Sandstorm doesn't have this 30K +/- 30% osc */
- mainfreq = 30000;
- stellaris_info->mck_desc = " (±30%)";
- break;
- case 8: /* hibernation osc */
- /* not all parts support hibernation */
- mainfreq = 32768;
- break;
-
- default: /* NOTREACHED */
- mainfreq = 0;
- break;
+ case 0: /* MOSC */
+ mainfreq = rcc_xtal[xtal];
+ break;
+ case 1: /* IOSC */
+ mainfreq = stellaris_info->iosc_freq;
+ stellaris_info->mck_desc = stellaris_info->iosc_desc;
+ break;
+ case 2: /* IOSC/4 */
+ mainfreq = stellaris_info->iosc_freq / 4;
+ stellaris_info->mck_desc = stellaris_info->iosc_desc;
+ break;
+ case 3: /* lowspeed */
+ /* Sandstorm doesn't have this 30K +/- 30% osc */
+ mainfreq = 30000;
+ stellaris_info->mck_desc = " (±30%)";
+ break;
+ case 8: /* hibernation osc */
+ /* not all parts support hibernation */
+ mainfreq = 32768;
+ break;
+
+ default: /* NOTREACHED */
+ mainfreq = 0;
+ break;
}
/* PLL is used if it's not bypassed; its output is 200 MHz
@@ -659,7 +659,7 @@ static int stellaris_read_part_info(struct flash_bank *bank)
target_read_u32(target, SCB_BASE | DID1, &did1);
target_read_u32(target, SCB_BASE | DC0, &stellaris_info->dc0);
target_read_u32(target, SCB_BASE | DC1, &stellaris_info->dc1);
- LOG_DEBUG("did0 0x%" PRIx32 ", did1 0x%" PRIx32 ", dc0 0x%" PRIx32 ", dc1 0x%" PRIx32 "",
+ LOG_DEBUG("did0 0x%" PRIx32 ", did1 0x%" PRIx32 ", dc0 0x%" PRIx32 ", dc1 0x%" PRIx32,
did0, did1, stellaris_info->dc0, stellaris_info->dc1);
ver = DID0_VER(did0);
@@ -702,35 +702,35 @@ static int stellaris_read_part_info(struct flash_bank *bank)
}
switch (stellaris_info->target_class) {
- case 0: /* Sandstorm */
- /*
- * Current (2009-August) parts seem to be rev C2 and use 12 MHz.
- * Parts before rev C0 used 15 MHz; some C0 parts use 15 MHz
- * (LM3S618), but some other C0 parts are 12 MHz (LM3S811).
- */
- if (((did0 >> 8) & 0xff) < 2) {
- stellaris_info->iosc_freq = 15000000;
- stellaris_info->iosc_desc = " (±50%)";
- }
- break;
+ case 0: /* Sandstorm */
+ /*
+ * Current (2009-August) parts seem to be rev C2 and use 12 MHz.
+ * Parts before rev C0 used 15 MHz; some C0 parts use 15 MHz
+ * (LM3S618), but some other C0 parts are 12 MHz (LM3S811).
+ */
+ if (((did0 >> 8) & 0xff) < 2) {
+ stellaris_info->iosc_freq = 15000000;
+ stellaris_info->iosc_desc = " (±50%)";
+ }
+ break;
- case 1: /* Fury */
- break;
+ case 1: /* Fury */
+ break;
- case 4: /* Tempest */
- case 5: /* Blizzard */
- case 6: /* Firestorm */
- case 0xa: /* Snowflake */
- stellaris_info->iosc_freq = 16000000; /* +/- 1% */
- stellaris_info->iosc_desc = " (±1%)";
- /* FALL THROUGH */
+ case 4: /* Tempest */
+ case 5: /* Blizzard */
+ case 6: /* Firestorm */
+ case 0xa: /* Snowflake */
+ stellaris_info->iosc_freq = 16000000; /* +/- 1% */
+ stellaris_info->iosc_desc = " (±1%)";
+ /* FALL THROUGH */
- case 3: /* DustDevil */
- stellaris_info->xtal_mask = 0x1f;
- break;
+ case 3: /* DustDevil */
+ stellaris_info->xtal_mask = 0x1f;
+ break;
- default:
- LOG_WARNING("Unknown did0 class");
+ default:
+ LOG_WARNING("Unknown did0 class");
}
for (i = 0; stellaris_parts[i].partno; i++) {
@@ -871,7 +871,7 @@ static int stellaris_erase(struct flash_bank *bank, unsigned int first,
/* Check access violations */
target_read_u32(target, FLASH_CRIS, &flash_cris);
if (flash_cris & (AMASK)) {
- LOG_WARNING("Error erasing flash page %i, flash_cris 0x%" PRIx32 "",
+ LOG_WARNING("Error erasing flash page %i, flash_cris 0x%" PRIx32,
banknr, flash_cris);
target_write_u32(target, FLASH_CRIS, 0);
return ERROR_FLASH_OPERATION_FAILED;
@@ -967,7 +967,7 @@ static int stellaris_protect(struct flash_bank *bank, int set,
/* Check access violations */
target_read_u32(target, FLASH_CRIS, &flash_cris);
if (flash_cris & (AMASK)) {
- LOG_WARNING("Error setting flash page protection, flash_cris 0x%" PRIx32 "", flash_cris);
+ LOG_WARNING("Error setting flash page protection, flash_cris 0x%" PRIx32, flash_cris);
target_write_u32(target, FLASH_CRIS, 0);
return ERROR_FLASH_OPERATION_FAILED;
}
@@ -1035,7 +1035,7 @@ static int stellaris_write_block(struct flash_bank *bank,
if (wcount * 4 < buf_min)
return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
- LOG_DEBUG("(bank=%p buffer=%p offset=%08" PRIx32 " wcount=%08" PRIx32 "",
+ LOG_DEBUG("(bank=%p buffer=%p offset=%08" PRIx32 " wcount=%08" PRIx32,
bank, buffer, offset, wcount);
/* flash write code */
@@ -1115,7 +1115,7 @@ static int stellaris_write(struct flash_bank *bank, const uint8_t *buffer,
return ERROR_TARGET_NOT_HALTED;
}
- LOG_DEBUG("(bank=%p buffer=%p offset=%08" PRIx32 " count=%08" PRIx32 "",
+ LOG_DEBUG("(bank=%p buffer=%p offset=%08" PRIx32 " count=%08" PRIx32,
bank, buffer, offset, count);
if (stellaris_info->did1 == 0)
@@ -1153,7 +1153,7 @@ static int stellaris_write(struct flash_bank *bank, const uint8_t *buffer,
/* if an error occurred, we examine the reason, and quit */
target_read_u32(target, FLASH_CRIS, &flash_cris);
- LOG_ERROR("flash writing failed with CRIS: 0x%" PRIx32 "", flash_cris);
+ LOG_ERROR("flash writing failed with CRIS: 0x%" PRIx32, flash_cris);
return ERROR_FLASH_OPERATION_FAILED;
}
} else {
@@ -1165,7 +1165,7 @@ static int stellaris_write(struct flash_bank *bank, const uint8_t *buffer,
while (words_remaining > 0) {
if (!(address & 0xff))
- LOG_DEBUG("0x%" PRIx32 "", address);
+ LOG_DEBUG("0x%" PRIx32, address);
/* Program one word */
target_write_u32(target, FLASH_FMA, address);
@@ -1189,7 +1189,7 @@ static int stellaris_write(struct flash_bank *bank, const uint8_t *buffer,
memcpy(last_word, buffer+bytes_written, bytes_remaining);
if (!(address & 0xff))
- LOG_DEBUG("0x%" PRIx32 "", address);
+ LOG_DEBUG("0x%" PRIx32, address);
/* Program one word */
target_write_u32(target, FLASH_FMA, address);
@@ -1205,7 +1205,7 @@ static int stellaris_write(struct flash_bank *bank, const uint8_t *buffer,
/* Check access violations */
target_read_u32(target, FLASH_CRIS, &flash_cris);
if (flash_cris & (AMASK)) {
- LOG_DEBUG("flash_cris 0x%" PRIx32 "", flash_cris);
+ LOG_DEBUG("flash_cris 0x%" PRIx32, flash_cris);
return ERROR_FLASH_OPERATION_FAILED;
}
return ERROR_OK;
diff --git a/src/flash/nor/stm32f1x.c b/src/flash/nor/stm32f1x.c
index 5a3c2da663..f512a26e9c 100644
--- a/src/flash/nor/stm32f1x.c
+++ b/src/flash/nor/stm32f1x.c
@@ -170,7 +170,7 @@ static int stm32x_wait_status_busy(struct flash_bank *bank, int timeout)
retval = stm32x_get_flash_status(bank, &status);
if (retval != ERROR_OK)
return retval;
- LOG_DEBUG("status: 0x%" PRIx32 "", status);
+ LOG_DEBUG("status: 0x%" PRIx32, status);
if ((status & FLASH_BSY) == 0)
break;
if (timeout-- <= 0) {
@@ -825,7 +825,7 @@ static int stm32x_probe(struct flash_bank *bank)
if (retval != ERROR_OK)
return retval;
- LOG_INFO("device id = 0x%08" PRIx32 "", dbgmcu_idcode);
+ LOG_INFO("device id = 0x%08" PRIx32, dbgmcu_idcode);
uint16_t device_id = dbgmcu_idcode & 0xfff;
uint16_t rev_id = dbgmcu_idcode >> 16;
@@ -1444,8 +1444,8 @@ COMMAND_HANDLER(stm32x_handle_options_read_command)
if (optionbyte & (1 << OPT_ERROR))
command_print(CMD, "option byte complement error");
- command_print(CMD, "option byte register = 0x%" PRIx32 "", optionbyte);
- command_print(CMD, "write protection register = 0x%" PRIx32 "", protection);
+ command_print(CMD, "option byte register = 0x%" PRIx32, optionbyte);
+ command_print(CMD, "write protection register = 0x%" PRIx32, protection);
command_print(CMD, "read protection: %s",
(optionbyte & (1 << OPT_READOUT)) ? "on" : "off");
@@ -1465,7 +1465,7 @@ COMMAND_HANDLER(stm32x_handle_options_read_command)
if (stm32x_info->has_dual_banks)
command_print(CMD, "boot: bank %d", (optionbyte & (1 << OPT_BFB2)) ? 0 : 1);
- command_print(CMD, "user data = 0x%02" PRIx16 "", user_data);
+ command_print(CMD, "user data = 0x%02" PRIx16, user_data);
return ERROR_OK;
}
diff --git a/src/flash/nor/stm32l4x.c b/src/flash/nor/stm32l4x.c
index f16333201b..4c25875ab0 100644
--- a/src/flash/nor/stm32l4x.c
+++ b/src/flash/nor/stm32l4x.c
@@ -152,6 +152,9 @@
/* this flag indicates that programming should be done in quad-word
* the default programming word size is double-word */
#define F_QUAD_WORD_PROG BIT(4)
+/* the registers WRPxyR have UNLOCK bit - writing zero locks the write
+ * protection region permanently! */
+#define F_WRP_HAS_LOCK BIT(5)
/* end of STM32L4 flags ******************************************************/
@@ -284,7 +287,7 @@ struct stm32l4_wrp {
};
/* human readable list of families this drivers supports (sorted alphabetically) */
-static const char *device_families = "STM32C0/G0/G4/L4/L4+/L5/U0/U5/WB/WL";
+static const char *device_families = "STM32C0/G0/G4/L4/L4+/L5/U0/U3/U5/WB/WL";
static const struct stm32l4_rev stm32l47_l48xx_revs[] = {
{ 0x1000, "1" }, { 0x1001, "2" }, { 0x1003, "3" }, { 0x1007, "4" }
@@ -347,6 +350,10 @@ static const struct stm32l4_rev stm32u0xx_revs[] = {
{ 0x1000, "A" },
};
+static const struct stm32l4_rev stm32u37_u38xx_revs[] = {
+ { 0x1000, "A" }, { 0x1001, "Z" },
+};
+
static const struct stm32l4_rev stm32g43_g44xx_revs[] = {
{ 0x1000, "A" }, { 0x2000, "B" }, { 0x2001, "Z" },
};
@@ -500,7 +507,8 @@ static const struct stm32l4_part_info stm32l4_parts[] = {
.num_revs = ARRAY_SIZE(stm32u53_u54xx_revs),
.device_str = "STM32U535/U545",
.max_flash_size_kb = 512,
- .flags = F_HAS_DUAL_BANK | F_QUAD_WORD_PROG | F_HAS_TZ | F_HAS_L5_FLASH_REGS,
+ .flags = F_HAS_DUAL_BANK | F_QUAD_WORD_PROG | F_HAS_TZ
+ | F_HAS_L5_FLASH_REGS | F_WRP_HAS_LOCK,
.flash_regs_base = 0x40022000,
.fsize_addr = 0x0BFA07A0,
.otp_base = 0x0BFA0000,
@@ -686,13 +694,26 @@ static const struct stm32l4_part_info stm32l4_parts[] = {
.otp_base = 0x1FFF6800,
.otp_size = 1024,
},
+ {
+ .id = DEVID_STM32U37_U38XX,
+ .revs = stm32u37_u38xx_revs,
+ .num_revs = ARRAY_SIZE(stm32u37_u38xx_revs),
+ .device_str = "STM32U37/U38xx",
+ .max_flash_size_kb = 1024,
+ .flags = F_HAS_DUAL_BANK | F_HAS_TZ | F_HAS_L5_FLASH_REGS | F_WRP_HAS_LOCK,
+ .flash_regs_base = 0x40022000,
+ .fsize_addr = 0x0BFA07A0,
+ .otp_base = 0x0BFA0000,
+ .otp_size = 512,
+ },
{
.id = DEVID_STM32U59_U5AXX,
.revs = stm32u59_u5axx_revs,
.num_revs = ARRAY_SIZE(stm32u59_u5axx_revs),
.device_str = "STM32U59/U5Axx",
.max_flash_size_kb = 4096,
- .flags = F_HAS_DUAL_BANK | F_QUAD_WORD_PROG | F_HAS_TZ | F_HAS_L5_FLASH_REGS,
+ .flags = F_HAS_DUAL_BANK | F_QUAD_WORD_PROG | F_HAS_TZ
+ | F_HAS_L5_FLASH_REGS | F_WRP_HAS_LOCK,
.flash_regs_base = 0x40022000,
.fsize_addr = 0x0BFA07A0,
.otp_base = 0x0BFA0000,
@@ -704,7 +725,8 @@ static const struct stm32l4_part_info stm32l4_parts[] = {
.num_revs = ARRAY_SIZE(stm32u57_u58xx_revs),
.device_str = "STM32U57/U58xx",
.max_flash_size_kb = 2048,
- .flags = F_HAS_DUAL_BANK | F_QUAD_WORD_PROG | F_HAS_TZ | F_HAS_L5_FLASH_REGS,
+ .flags = F_HAS_DUAL_BANK | F_QUAD_WORD_PROG | F_HAS_TZ
+ | F_HAS_L5_FLASH_REGS | F_WRP_HAS_LOCK,
.flash_regs_base = 0x40022000,
.fsize_addr = 0x0BFA07A0,
.otp_base = 0x0BFA0000,
@@ -716,7 +738,8 @@ static const struct stm32l4_part_info stm32l4_parts[] = {
.num_revs = ARRAY_SIZE(stm32u5f_u5gxx_revs),
.device_str = "STM32U5F/U5Gxx",
.max_flash_size_kb = 4096,
- .flags = F_HAS_DUAL_BANK | F_QUAD_WORD_PROG | F_HAS_TZ | F_HAS_L5_FLASH_REGS,
+ .flags = F_HAS_DUAL_BANK | F_QUAD_WORD_PROG | F_HAS_TZ
+ | F_HAS_L5_FLASH_REGS | F_WRP_HAS_LOCK,
.flash_regs_base = 0x40022000,
.fsize_addr = 0x0BFA07A0,
.otp_base = 0x0BFA0000,
@@ -974,7 +997,7 @@ static int stm32l4_wait_status_busy(struct flash_bank *bank, int timeout)
retval = stm32l4_read_flash_reg_by_index(bank, STM32_FLASH_SR_INDEX, &status);
if (retval != ERROR_OK)
return retval;
- LOG_DEBUG("status: 0x%" PRIx32 "", status);
+ LOG_DEBUG("status: 0x%" PRIx32, status);
if ((status & stm32l4_info->sr_bsy_mask) == 0)
break;
if (timeout-- <= 0) {
@@ -1287,6 +1310,8 @@ static int stm32l4_write_one_wrpxy(struct flash_bank *bank, struct stm32l4_wrp *
int wrp_end = wrpxy->last - wrpxy->offset;
uint32_t wrp_value = (wrp_start & stm32l4_info->wrpxxr_mask) | ((wrp_end & stm32l4_info->wrpxxr_mask) << 16);
+ if (stm32l4_info->part_info->flags & F_WRP_HAS_LOCK)
+ wrp_value |= FLASH_WRPXYR_UNLOCK;
return stm32l4_write_option(bank, stm32l4_info->flash_regs[wrpxy->reg_idx], wrp_value, 0xffffffff);
}
@@ -1371,6 +1396,10 @@ static int stm32l4_erase(struct flash_bank *bank, unsigned int first,
4. Wait for the BSY bit to be cleared
*/
+ retval = stm32l4_wait_status_busy(bank, FLASH_ERASE_TIMEOUT);
+ if (retval != ERROR_OK)
+ goto err_lock;
+
for (unsigned int i = first; i <= last; i++) {
uint32_t erase_flags;
erase_flags = FLASH_PER | FLASH_STRT;
@@ -1776,6 +1805,9 @@ static int stm32l4_write(struct flash_bank *bank, const uint8_t *buffer,
if (retval != ERROR_OK)
goto err_lock;
+ retval = stm32l4_wait_status_busy(bank, FLASH_WRITE_TIMEOUT);
+ if (retval != ERROR_OK)
+ goto err_lock;
/* For TrustZone enabled devices, when TZEN is set and RDP level is 0.5,
* the debug is possible only in non-secure state.
@@ -2142,6 +2174,15 @@ static int stm32l4_probe(struct flash_bank *bank)
stm32l4_info->bank1_sectors = num_pages / 2;
}
break;
+ case DEVID_STM32U37_U38XX:
+ page_size_kb = 4;
+ num_pages = flash_size_kb / page_size_kb;
+ stm32l4_info->bank1_sectors = num_pages;
+ if (is_max_flash_size || (stm32l4_info->optr & FLASH_U5_DUALBANK)) {
+ stm32l4_info->dual_bank_mode = true;
+ stm32l4_info->bank1_sectors = num_pages / 2;
+ }
+ break;
case DEVID_STM32U53_U54XX:
case DEVID_STM32U57_U58XX:
case DEVID_STM32U59_U5AXX:
@@ -2400,19 +2441,18 @@ COMMAND_HANDLER(stm32l4_handle_option_read_command)
if (retval != ERROR_OK)
return retval;
- uint32_t reg_offset, reg_addr;
+ uint32_t reg_offset;
uint32_t value = 0;
COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], reg_offset);
- reg_addr = stm32l4_get_flash_reg(bank, reg_offset);
retval = stm32l4_read_flash_reg(bank, reg_offset, &value);
if (retval != ERROR_OK)
return retval;
- command_print(CMD, "Option Register: <0x%" PRIx32 "> = 0x%" PRIx32 "", reg_addr, value);
+ command_print(CMD, "0x%" PRIx32, value);
- return retval;
+ return ERROR_OK;
}
COMMAND_HANDLER(stm32l4_handle_option_write_command)
diff --git a/src/flash/nor/stm32l4x.h b/src/flash/nor/stm32l4x.h
index 07b3615a24..8e6cb4309f 100644
--- a/src/flash/nor/stm32l4x.h
+++ b/src/flash/nor/stm32l4x.h
@@ -69,6 +69,9 @@
#define FLASH_U5_DUALBANK BIT(21)
#define FLASH_TZEN BIT(31)
+/* FLASH_WRPxyR register bits */
+#define FLASH_WRPXYR_UNLOCK BIT(31)
+
/* FLASH secure block based bank 1/2 register offsets */
#define FLASH_SECBB1(X) (0x80 + 4 * (X - 1))
#define FLASH_SECBB2(X) (0xA0 + 4 * (X - 1))
@@ -91,6 +94,7 @@
#define DEVID_STM32C05XX 0x44C
#define DEVID_STM32C09XX 0x44D
#define DEVID_STM32C03XX 0x453
+#define DEVID_STM32U37_U38XX 0x454
#define DEVID_STM32U53_U54XX 0x455
#define DEVID_STM32G05_G06XX 0x456
#define DEVID_STM32U031XX 0x459
diff --git a/src/flash/nor/stm32lx.c b/src/flash/nor/stm32lx.c
index 1459e942d1..2c7563e95a 100644
--- a/src/flash/nor/stm32lx.c
+++ b/src/flash/nor/stm32lx.c
@@ -745,7 +745,7 @@ static int stm32lx_probe(struct flash_bank *bank)
stm32lx_info->idcode = device_id;
- LOG_DEBUG("device id = 0x%08" PRIx32 "", device_id);
+ LOG_DEBUG("device id = 0x%08" PRIx32, device_id);
for (n = 0; n < ARRAY_SIZE(stm32lx_parts); n++) {
if ((device_id & 0xfff) == stm32lx_parts[n].id) {
@@ -1204,7 +1204,7 @@ static int stm32lx_wait_until_bsy_clear_timeout(struct flash_bank *bank, int tim
if (retval != ERROR_OK)
return retval;
- LOG_DEBUG("status: 0x%" PRIx32 "", status);
+ LOG_DEBUG("status: 0x%" PRIx32, status);
if ((status & FLASH_SR__BSY) == 0)
break;
diff --git a/src/flash/nor/stmqspi.c b/src/flash/nor/stmqspi.c
index df58f6c55d..bd72fe050e 100644
--- a/src/flash/nor/stmqspi.c
+++ b/src/flash/nor/stmqspi.c
@@ -1978,24 +1978,24 @@ static int read_flash_id(struct flash_bank *bank, uint32_t *id1, uint32_t *id2)
/* Read id: one particular flash chip (N25Q128) switches back to SPI mode when receiving
* SPI_FLASH_READ_ID in QPI mode, hence try SPIFLASH_READ_MID first */
switch (type) {
- case 0:
- if (IS_OCTOSPI)
- retval = octospi_cmd(bank, OCTOSPI_READ_MODE,
- OCTOSPI_CCR_READ_MID, SPIFLASH_READ_MID);
- else
- retval = target_write_u32(target, io_base + QSPI_CCR, QSPI_CCR_READ_MID);
- break;
-
- case 1:
- if (IS_OCTOSPI)
- retval = octospi_cmd(bank, OCTOSPI_READ_MODE,
- OCTOSPI_CCR_READ_ID, SPIFLASH_READ_ID);
- else
- retval = target_write_u32(target, io_base + QSPI_CCR, QSPI_CCR_READ_ID);
- break;
-
- default:
- return ERROR_FAIL;
+ case 0:
+ if (IS_OCTOSPI)
+ retval = octospi_cmd(bank, OCTOSPI_READ_MODE,
+ OCTOSPI_CCR_READ_MID, SPIFLASH_READ_MID);
+ else
+ retval = target_write_u32(target, io_base + QSPI_CCR, QSPI_CCR_READ_MID);
+ break;
+
+ case 1:
+ if (IS_OCTOSPI)
+ retval = octospi_cmd(bank, OCTOSPI_READ_MODE,
+ OCTOSPI_CCR_READ_ID, SPIFLASH_READ_ID);
+ else
+ retval = target_write_u32(target, io_base + QSPI_CCR, QSPI_CCR_READ_ID);
+ break;
+
+ default:
+ return ERROR_FAIL;
}
if (retval != ERROR_OK)
diff --git a/src/flash/nor/stmsmi.c b/src/flash/nor/stmsmi.c
index 1aa244728f..85f3580788 100644
--- a/src/flash/nor/stmsmi.c
+++ b/src/flash/nor/stmsmi.c
@@ -531,21 +531,21 @@ static int stmsmi_probe(struct flash_bank *bank)
}
switch (bank->base - target_device->smi_base) {
- case 0:
- stmsmi_info->bank_num = SMI_SEL_BANK0;
- break;
- case SMI_BANK_SIZE:
- stmsmi_info->bank_num = SMI_SEL_BANK1;
- break;
- case 2*SMI_BANK_SIZE:
- stmsmi_info->bank_num = SMI_SEL_BANK2;
- break;
- case 3*SMI_BANK_SIZE:
- stmsmi_info->bank_num = SMI_SEL_BANK3;
- break;
- default:
- LOG_ERROR("Invalid SMI base address " TARGET_ADDR_FMT, bank->base);
- return ERROR_FAIL;
+ case 0:
+ stmsmi_info->bank_num = SMI_SEL_BANK0;
+ break;
+ case SMI_BANK_SIZE:
+ stmsmi_info->bank_num = SMI_SEL_BANK1;
+ break;
+ case 2 * SMI_BANK_SIZE:
+ stmsmi_info->bank_num = SMI_SEL_BANK2;
+ break;
+ case 3 * SMI_BANK_SIZE:
+ stmsmi_info->bank_num = SMI_SEL_BANK3;
+ break;
+ default:
+ LOG_ERROR("Invalid SMI base address " TARGET_ADDR_FMT, bank->base);
+ return ERROR_FAIL;
}
io_base = target_device->io_base;
stmsmi_info->io_base = io_base;
diff --git a/src/flash/nor/str7x.c b/src/flash/nor/str7x.c
index b91e22e044..0177095cb9 100644
--- a/src/flash/nor/str7x.c
+++ b/src/flash/nor/str7x.c
@@ -131,21 +131,21 @@ static int str7x_build_block_list(struct flash_bank *bank)
int b0_sectors = 0, b1_sectors = 0;
switch (bank->size) {
- case 16 * 1024:
- b1_sectors = 2;
- break;
- case 64 * 1024:
- b0_sectors = 5;
- break;
- case 128 * 1024:
- b0_sectors = 6;
- break;
- case 256 * 1024:
- b0_sectors = 8;
- break;
- default:
- LOG_ERROR("BUG: unknown bank->size encountered");
- exit(-1);
+ case 16 * 1024:
+ b1_sectors = 2;
+ break;
+ case 64 * 1024:
+ b0_sectors = 5;
+ break;
+ case 128 * 1024:
+ b0_sectors = 6;
+ break;
+ case 256 * 1024:
+ b0_sectors = 8;
+ break;
+ default:
+ LOG_ERROR("BUG: unknown bank->size encountered");
+ exit(-1);
}
num_sectors = b0_sectors + b1_sectors;
@@ -335,7 +335,7 @@ static int str7x_erase(struct flash_bank *bank, unsigned int first,
for (unsigned int i = first; i <= last; i++)
sectors |= str7x_info->sector_bits[i];
- LOG_DEBUG("sectors: 0x%" PRIx32 "", sectors);
+ LOG_DEBUG("sectors: 0x%" PRIx32, sectors);
/* clear FLASH_ER register */
err = target_write_u32(target, str7x_get_flash_adr(bank, FLASH_ER), 0x0);
diff --git a/src/flash/nor/str9x.c b/src/flash/nor/str9x.c
index 1a26b839e9..9efac241a0 100644
--- a/src/flash/nor/str9x.c
+++ b/src/flash/nor/str9x.c
@@ -66,36 +66,36 @@ static int str9x_build_block_list(struct flash_bank *bank)
str9x_info->bank1 = 0;
switch (bank->size) {
- case (256 * 1024):
- b0_sectors = 4;
- break;
- case (512 * 1024):
- b0_sectors = 8;
- break;
- case (1024 * 1024):
- bank1start = 0x00100000;
- str9x_info->variant = 1;
- b0_sectors = 16;
- break;
- case (2048 * 1024):
- bank1start = 0x00200000;
- str9x_info->variant = 1;
- b0_sectors = 32;
- break;
- case (128 * 1024):
- str9x_info->variant = 1;
- str9x_info->bank1 = 1;
- b1_sectors = 8;
- bank1start = bank->base;
- break;
- case (32 * 1024):
- str9x_info->bank1 = 1;
- b1_sectors = 4;
- bank1start = bank->base;
- break;
- default:
- LOG_ERROR("BUG: unknown bank->size encountered");
- exit(-1);
+ case (256 * 1024):
+ b0_sectors = 4;
+ break;
+ case (512 * 1024):
+ b0_sectors = 8;
+ break;
+ case (1024 * 1024):
+ bank1start = 0x00100000;
+ str9x_info->variant = 1;
+ b0_sectors = 16;
+ break;
+ case (2048 * 1024):
+ bank1start = 0x00200000;
+ str9x_info->variant = 1;
+ b0_sectors = 32;
+ break;
+ case (128 * 1024):
+ str9x_info->variant = 1;
+ str9x_info->bank1 = 1;
+ b1_sectors = 8;
+ bank1start = bank->base;
+ break;
+ case (32 * 1024):
+ str9x_info->bank1 = 1;
+ b1_sectors = 4;
+ bank1start = bank->base;
+ break;
+ default:
+ LOG_ERROR("BUG: unknown bank->size encountered");
+ exit(-1);
}
num_sectors = b0_sectors + b1_sectors;
diff --git a/src/flash/nor/str9xpec.c b/src/flash/nor/str9xpec.c
index eff7df5a11..be0089879a 100644
--- a/src/flash/nor/str9xpec.c
+++ b/src/flash/nor/str9xpec.c
@@ -206,28 +206,28 @@ static int str9xpec_build_block_list(struct flash_bank *bank)
int b1_size = 0x2000;
switch (bank->size) {
- case (256 * 1024):
- b0_sectors = 4;
- break;
- case (512 * 1024):
- b0_sectors = 8;
- break;
- case (1024 * 1024):
- b0_sectors = 16;
- break;
- case (2048 * 1024):
- b0_sectors = 32;
- break;
- case (128 * 1024):
- b1_size = 0x4000;
- b1_sectors = 8;
- break;
- case (32 * 1024):
- b1_sectors = 4;
- break;
- default:
- LOG_ERROR("BUG: unknown bank->size encountered");
- exit(-1);
+ case (256 * 1024):
+ b0_sectors = 4;
+ break;
+ case (512 * 1024):
+ b0_sectors = 8;
+ break;
+ case (1024 * 1024):
+ b0_sectors = 16;
+ break;
+ case (2048 * 1024):
+ b0_sectors = 32;
+ break;
+ case (128 * 1024):
+ b1_size = 0x4000;
+ b1_sectors = 8;
+ break;
+ case (32 * 1024):
+ b1_sectors = 4;
+ break;
+ default:
+ LOG_ERROR("BUG: unknown bank->size encountered");
+ exit(-1);
}
num_sectors = b0_sectors + b1_sectors;
@@ -735,7 +735,7 @@ COMMAND_HANDLER(str9xpec_handle_part_id_command)
idcode = buf_get_u32(buffer, 0, 32);
- command_print(CMD, "str9xpec part id: 0x%8.8" PRIx32 "", idcode);
+ command_print(CMD, "str9xpec part id: 0x%8.8" PRIx32, idcode);
free(buffer);
diff --git a/src/flash/nor/tcl.c b/src/flash/nor/tcl.c
index a19b1a6833..517d9aca1d 100644
--- a/src/flash/nor/tcl.c
+++ b/src/flash/nor/tcl.c
@@ -535,20 +535,20 @@ COMMAND_HANDLER(handle_flash_fill_command)
return retval;
switch (CMD_NAME[4]) {
- case 'd':
- wordsize = 8;
- break;
- case 'w':
- wordsize = 4;
- break;
- case 'h':
- wordsize = 2;
- break;
- case 'b':
- wordsize = 1;
- break;
- default:
- return ERROR_COMMAND_SYNTAX_ERROR;
+ case 'd':
+ wordsize = 8;
+ break;
+ case 'w':
+ wordsize = 4;
+ break;
+ case 'h':
+ wordsize = 2;
+ break;
+ case 'b':
+ wordsize = 1;
+ break;
+ default:
+ return ERROR_COMMAND_SYNTAX_ERROR;
}
if ((wordsize < sizeof(pattern)) && (pattern >> (8 * wordsize) != 0)) {
@@ -588,25 +588,25 @@ COMMAND_HANDLER(handle_flash_fill_command)
uint8_t *ptr = buffer + padding_at_start;
switch (wordsize) {
- case 8:
- for (i = 0; i < count; i++, ptr += wordsize)
- target_buffer_set_u64(target, ptr, pattern);
- break;
- case 4:
- for (i = 0; i < count; i++, ptr += wordsize)
- target_buffer_set_u32(target, ptr, pattern);
- break;
- case 2:
- for (i = 0; i < count; i++, ptr += wordsize)
- target_buffer_set_u16(target, ptr, pattern);
- break;
- case 1:
- memset(ptr, pattern, count);
- ptr += count;
- break;
- default:
- LOG_ERROR("BUG: can't happen");
- exit(-1);
+ case 8:
+ for (i = 0; i < count; i++, ptr += wordsize)
+ target_buffer_set_u64(target, ptr, pattern);
+ break;
+ case 4:
+ for (i = 0; i < count; i++, ptr += wordsize)
+ target_buffer_set_u32(target, ptr, pattern);
+ break;
+ case 2:
+ for (i = 0; i < count; i++, ptr += wordsize)
+ target_buffer_set_u16(target, ptr, pattern);
+ break;
+ case 1:
+ memset(ptr, pattern, count);
+ ptr += count;
+ break;
+ default:
+ LOG_ERROR("BUG: can't happen");
+ exit(-1);
}
if (padding_at_end) {
@@ -631,18 +631,18 @@ COMMAND_HANDLER(handle_flash_fill_command)
uint64_t readback = 0;
switch (wordsize) {
- case 8:
- readback = target_buffer_get_u64(target, ptr);
- break;
- case 4:
- readback = target_buffer_get_u32(target, ptr);
- break;
- case 2:
- readback = target_buffer_get_u16(target, ptr);
- break;
- case 1:
- readback = *ptr;
- break;
+ case 8:
+ readback = target_buffer_get_u64(target, ptr);
+ break;
+ case 4:
+ readback = target_buffer_get_u32(target, ptr);
+ break;
+ case 2:
+ readback = target_buffer_get_u16(target, ptr);
+ break;
+ case 1:
+ readback = *ptr;
+ break;
}
if (readback != pattern) {
LOG_ERROR(
@@ -683,17 +683,17 @@ COMMAND_HANDLER(handle_flash_md_command)
unsigned int wordsize;
switch (CMD_NAME[2]) {
- case 'w':
- wordsize = 4;
- break;
- case 'h':
- wordsize = 2;
- break;
- case 'b':
- wordsize = 1;
- break;
- default:
- return ERROR_COMMAND_SYNTAX_ERROR;
+ case 'w':
+ wordsize = 4;
+ break;
+ case 'h':
+ wordsize = 2;
+ break;
+ case 'b':
+ wordsize = 1;
+ break;
+ default:
+ return ERROR_COMMAND_SYNTAX_ERROR;
}
if (count == 0)
@@ -728,6 +728,124 @@ COMMAND_HANDLER(handle_flash_md_command)
return retval;
}
+COMMAND_HANDLER(handle_flash_read_memory_command)
+{
+ /*
+ * CMD_ARGV[0] = memory address
+ * CMD_ARGV[1] = desired element width in bits
+ * CMD_ARGV[2] = number of elements to read
+ */
+
+ if (CMD_ARGC != 3)
+ return ERROR_COMMAND_SYNTAX_ERROR;
+
+ /* Arg 1: Memory address. */
+ target_addr_t addr;
+ COMMAND_PARSE_NUMBER(u64, CMD_ARGV[0], addr);
+
+ /* Arg 2: Bit width of one element. */
+ unsigned int width_bits;
+ COMMAND_PARSE_NUMBER(uint, CMD_ARGV[1], width_bits);
+
+ /* Arg 3: Number of elements to read. */
+ unsigned int count;
+ COMMAND_PARSE_NUMBER(uint, CMD_ARGV[2], count);
+
+ switch (width_bits) {
+ case 8:
+ case 16:
+ case 32:
+ case 64:
+ break;
+ default:
+ command_print(CMD, "invalid width, must be 8, 16, 32 or 64");
+ return ERROR_COMMAND_ARGUMENT_INVALID;
+ }
+
+ if (count > 65536) {
+ command_print(CMD, "too large read request, exceeds 64K elements");
+ return ERROR_COMMAND_ARGUMENT_INVALID;
+ }
+
+ const unsigned int width = width_bits / 8;
+ /* -1 is needed to handle cases when (addr + count * width) results in zero
+ * due to overflow.
+ */
+ if ((addr + count * width - 1) < addr) {
+ command_print(CMD, "memory region wraps over address zero");
+ return ERROR_COMMAND_ARGUMENT_INVALID;
+ }
+
+ struct target *target = get_current_target(CMD_CTX);
+ struct flash_bank *bank;
+ int retval = get_flash_bank_by_addr(target, addr, true, &bank);
+ if (retval != ERROR_OK)
+ return retval;
+
+ uint32_t offset = addr - bank->base;
+ uint32_t sizebytes = count * width_bits;
+ if (offset + sizebytes > bank->size) {
+ command_print(CMD, "cannot cross flash bank borders");
+ return ERROR_FAIL;
+ }
+
+ const size_t buffer_size = 4096;
+ uint8_t *buffer = malloc(buffer_size);
+
+ if (!buffer) {
+ command_print(CMD, "failed to allocate memory");
+ return ERROR_FAIL;
+ }
+
+ char *separator = "";
+ while (count > 0) {
+ const unsigned int max_chunk_len = buffer_size / width;
+ const size_t chunk_len = MIN(count, max_chunk_len);
+
+ retval = flash_driver_read(bank, buffer, offset, chunk_len * width);
+
+ if (retval != ERROR_OK) {
+ LOG_DEBUG("read at " TARGET_ADDR_FMT " with width=%u and count=%zu failed",
+ addr, width_bits, chunk_len);
+ /*
+ * FIXME: we append the errmsg to the list of value already read.
+ * Add a way to flush and replace old output, but LOG_DEBUG() it
+ */
+ command_print(CMD, "failed to read memory");
+ free(buffer);
+ return retval;
+ }
+
+ for (size_t i = 0; i < chunk_len ; i++) {
+ uint64_t v = 0;
+
+ switch (width) {
+ case 8:
+ v = target_buffer_get_u64(target, &buffer[i * width]);
+ break;
+ case 4:
+ v = target_buffer_get_u32(target, &buffer[i * width]);
+ break;
+ case 2:
+ v = target_buffer_get_u16(target, &buffer[i * width]);
+ break;
+ case 1:
+ v = buffer[i];
+ break;
+ }
+
+ command_print_sameline(CMD, "%s0x%" PRIx64, separator, v);
+ separator = " ";
+ }
+
+ count -= chunk_len;
+ offset += chunk_len * width;
+ }
+
+ free(buffer);
+
+ return ERROR_OK;
+}
COMMAND_HANDLER(handle_flash_write_bank_command)
{
@@ -1171,6 +1289,13 @@ static const struct command_registration flash_exec_command_handlers[] = {
.usage = "address [count]",
.help = "Display words from flash.",
},
+ {
+ .name = "read_memory",
+ .mode = COMMAND_EXEC,
+ .handler = handle_flash_read_memory_command,
+ .help = "Read Tcl list of 8/16/32/64 bit numbers from flash memory",
+ .usage = "address width count",
+ },
{
.name = "write_bank",
.handler = handle_flash_write_bank_command,
diff --git a/src/flash/nor/tms470.c b/src/flash/nor/tms470.c
index 00ee77bb80..fa0b5b68ec 100644
--- a/src/flash/nor/tms470.c
+++ b/src/flash/nor/tms470.c
@@ -125,7 +125,7 @@ static int tms470_read_part_info(struct flash_bank *bank)
/* read and parse the device identification register */
target_read_u32(target, 0xFFFFFFF0, &device_ident_reg);
- LOG_INFO("device_ident_reg = 0x%08" PRIx32 "", device_ident_reg);
+ LOG_INFO("device_ident_reg = 0x%08" PRIx32, device_ident_reg);
if ((device_ident_reg & 7) == 0) {
LOG_WARNING("Cannot identify target as a TMS470 family.");
@@ -148,100 +148,100 @@ static int tms470_read_part_info(struct flash_bank *bank)
* bank structure.
*/
switch (part_number) {
- case 0x0a:
- part_name = "TMS470R1A256";
-
- if (bank->base >= 0x00040000) {
- LOG_ERROR("No %s flash bank contains base address "
- TARGET_ADDR_FMT ".",
- part_name,
- bank->base);
- return ERROR_FLASH_OPERATION_FAILED;
- }
+ case 0x0a:
+ part_name = "TMS470R1A256";
+
+ if (bank->base >= 0x00040000) {
+ LOG_ERROR("No %s flash bank contains base address "
+ TARGET_ADDR_FMT ".",
+ part_name,
+ bank->base);
+ return ERROR_FLASH_OPERATION_FAILED;
+ }
+ tms470_info->ordinal = 0;
+ bank->base = 0x00000000;
+ bank->size = 256 * 1024;
+ bank->num_sectors = TMS470R1A256_NUM_SECTORS;
+ bank->sectors = malloc(sizeof(tms470r1a256_sectors));
+ if (!bank->sectors)
+ return ERROR_FLASH_OPERATION_FAILED;
+ (void)memcpy(bank->sectors, tms470r1a256_sectors, sizeof(tms470r1a256_sectors));
+ break;
+
+ case 0x2b:
+ part_name = "TMS470R1A288";
+
+ if (bank->base < 0x00008000) {
tms470_info->ordinal = 0;
bank->base = 0x00000000;
+ bank->size = 32 * 1024;
+ bank->num_sectors = TMS470R1A288_BANK0_NUM_SECTORS;
+ bank->sectors = malloc(sizeof(tms470r1a288_bank0_sectors));
+ if (!bank->sectors)
+ return ERROR_FLASH_OPERATION_FAILED;
+ (void)memcpy(bank->sectors, tms470r1a288_bank0_sectors,
+ sizeof(tms470r1a288_bank0_sectors));
+ } else if ((bank->base >= 0x00040000) && (bank->base < 0x00080000)) {
+ tms470_info->ordinal = 1;
+ bank->base = 0x00040000;
bank->size = 256 * 1024;
- bank->num_sectors = TMS470R1A256_NUM_SECTORS;
- bank->sectors = malloc(sizeof(tms470r1a256_sectors));
+ bank->num_sectors = TMS470R1A288_BANK1_NUM_SECTORS;
+ bank->sectors = malloc(sizeof(tms470r1a288_bank1_sectors));
if (!bank->sectors)
return ERROR_FLASH_OPERATION_FAILED;
- (void)memcpy(bank->sectors, tms470r1a256_sectors, sizeof(tms470r1a256_sectors));
- break;
+ (void)memcpy(bank->sectors, tms470r1a288_bank1_sectors,
+ sizeof(tms470r1a288_bank1_sectors));
+ } else {
+ LOG_ERROR("No %s flash bank contains base address " TARGET_ADDR_FMT ".",
+ part_name, bank->base);
+ return ERROR_FLASH_OPERATION_FAILED;
+ }
+ break;
- case 0x2b:
- part_name = "TMS470R1A288";
-
- if (bank->base < 0x00008000) {
- tms470_info->ordinal = 0;
- bank->base = 0x00000000;
- bank->size = 32 * 1024;
- bank->num_sectors = TMS470R1A288_BANK0_NUM_SECTORS;
- bank->sectors = malloc(sizeof(tms470r1a288_bank0_sectors));
- if (!bank->sectors)
- return ERROR_FLASH_OPERATION_FAILED;
- (void)memcpy(bank->sectors, tms470r1a288_bank0_sectors,
- sizeof(tms470r1a288_bank0_sectors));
- } else if ((bank->base >= 0x00040000) && (bank->base < 0x00080000)) {
- tms470_info->ordinal = 1;
- bank->base = 0x00040000;
- bank->size = 256 * 1024;
- bank->num_sectors = TMS470R1A288_BANK1_NUM_SECTORS;
- bank->sectors = malloc(sizeof(tms470r1a288_bank1_sectors));
- if (!bank->sectors)
- return ERROR_FLASH_OPERATION_FAILED;
- (void)memcpy(bank->sectors, tms470r1a288_bank1_sectors,
- sizeof(tms470r1a288_bank1_sectors));
- } else {
- LOG_ERROR("No %s flash bank contains base address " TARGET_ADDR_FMT ".",
- part_name, bank->base);
- return ERROR_FLASH_OPERATION_FAILED;
- }
- break;
+ case 0x2d:
+ part_name = "TMS470R1A384";
- case 0x2d:
- part_name = "TMS470R1A384";
-
- if (bank->base < 0x00020000) {
- tms470_info->ordinal = 0;
- bank->base = 0x00000000;
- bank->size = 128 * 1024;
- bank->num_sectors = TMS470R1A384_BANK0_NUM_SECTORS;
- bank->sectors = malloc(sizeof(tms470r1a384_bank0_sectors));
- if (!bank->sectors)
- return ERROR_FLASH_OPERATION_FAILED;
- (void)memcpy(bank->sectors, tms470r1a384_bank0_sectors,
- sizeof(tms470r1a384_bank0_sectors));
- } else if ((bank->base >= 0x00020000) && (bank->base < 0x00040000)) {
- tms470_info->ordinal = 1;
- bank->base = 0x00020000;
- bank->size = 128 * 1024;
- bank->num_sectors = TMS470R1A384_BANK1_NUM_SECTORS;
- bank->sectors = malloc(sizeof(tms470r1a384_bank1_sectors));
- if (!bank->sectors)
- return ERROR_FLASH_OPERATION_FAILED;
- (void)memcpy(bank->sectors, tms470r1a384_bank1_sectors,
- sizeof(tms470r1a384_bank1_sectors));
- } else if ((bank->base >= 0x00040000) && (bank->base < 0x00060000)) {
- tms470_info->ordinal = 2;
- bank->base = 0x00040000;
- bank->size = 128 * 1024;
- bank->num_sectors = TMS470R1A384_BANK2_NUM_SECTORS;
- bank->sectors = malloc(sizeof(tms470r1a384_bank2_sectors));
- if (!bank->sectors)
- return ERROR_FLASH_OPERATION_FAILED;
- (void)memcpy(bank->sectors, tms470r1a384_bank2_sectors,
- sizeof(tms470r1a384_bank2_sectors));
- } else {
- LOG_ERROR("No %s flash bank contains base address " TARGET_ADDR_FMT ".",
- part_name, bank->base);
+ if (bank->base < 0x00020000) {
+ tms470_info->ordinal = 0;
+ bank->base = 0x00000000;
+ bank->size = 128 * 1024;
+ bank->num_sectors = TMS470R1A384_BANK0_NUM_SECTORS;
+ bank->sectors = malloc(sizeof(tms470r1a384_bank0_sectors));
+ if (!bank->sectors)
return ERROR_FLASH_OPERATION_FAILED;
- }
- break;
-
- default:
- LOG_WARNING("Could not identify part 0x%02" PRIx32 " as a member of the TMS470 family.",
- part_number);
+ (void)memcpy(bank->sectors, tms470r1a384_bank0_sectors,
+ sizeof(tms470r1a384_bank0_sectors));
+ } else if ((bank->base >= 0x00020000) && (bank->base < 0x00040000)) {
+ tms470_info->ordinal = 1;
+ bank->base = 0x00020000;
+ bank->size = 128 * 1024;
+ bank->num_sectors = TMS470R1A384_BANK1_NUM_SECTORS;
+ bank->sectors = malloc(sizeof(tms470r1a384_bank1_sectors));
+ if (!bank->sectors)
+ return ERROR_FLASH_OPERATION_FAILED;
+ (void)memcpy(bank->sectors, tms470r1a384_bank1_sectors,
+ sizeof(tms470r1a384_bank1_sectors));
+ } else if ((bank->base >= 0x00040000) && (bank->base < 0x00060000)) {
+ tms470_info->ordinal = 2;
+ bank->base = 0x00040000;
+ bank->size = 128 * 1024;
+ bank->num_sectors = TMS470R1A384_BANK2_NUM_SECTORS;
+ bank->sectors = malloc(sizeof(tms470r1a384_bank2_sectors));
+ if (!bank->sectors)
+ return ERROR_FLASH_OPERATION_FAILED;
+ (void)memcpy(bank->sectors, tms470r1a384_bank2_sectors,
+ sizeof(tms470r1a384_bank2_sectors));
+ } else {
+ LOG_ERROR("No %s flash bank contains base address " TARGET_ADDR_FMT ".",
+ part_name, bank->base);
return ERROR_FLASH_OPERATION_FAILED;
+ }
+ break;
+
+ default:
+ LOG_WARNING("Could not identify part 0x%02" PRIx32 " as a member of the TMS470 family.",
+ part_number);
+ return ERROR_FLASH_OPERATION_FAILED;
}
/* turn off memory selects */
@@ -300,7 +300,7 @@ COMMAND_HANDLER(tms470_handle_flash_keyset_command)
if (keys_set) {
command_print(CMD,
- "using flash keys 0x%08" PRIx32 ", 0x%08" PRIx32 ", 0x%08" PRIx32 ", 0x%08" PRIx32 "",
+ "using flash keys 0x%08" PRIx32 ", 0x%08" PRIx32 ", 0x%08" PRIx32 ", 0x%08" PRIx32,
flash_keys[0],
flash_keys[1],
flash_keys[2],
@@ -419,7 +419,7 @@ static int tms470_try_flash_keys(struct target *target, const uint32_t *key_set)
*/
target_read_u32(target, 0x00001FF0 + 4 * i, &tmp);
- LOG_INFO("tms470 writing fmpkey = 0x%08" PRIx32 "", key_set[i]);
+ LOG_INFO("tms470 writing fmpkey = 0x%08" PRIx32, key_set[i]);
target_write_u32(target, 0xFFE89C0C, key_set[i]);
}
@@ -500,7 +500,7 @@ static int tms470_flash_initialize_internal_state_machine(struct flash_bank *ban
fmmac2 &= ~0x0007;
fmmac2 |= (tms470_info->ordinal & 7);
target_write_u32(target, 0xFFE8BC04, fmmac2);
- LOG_DEBUG("set fmmac2 = 0x%04" PRIx32 "", fmmac2);
+ LOG_DEBUG("set fmmac2 = 0x%04" PRIx32, fmmac2);
/*
* Disable level 1 sector protection by setting bit 15 of FMMAC1.
@@ -508,7 +508,7 @@ static int tms470_flash_initialize_internal_state_machine(struct flash_bank *ban
target_read_u32(target, 0xFFE8BC00, &fmmac1);
fmmac1 |= 0x8000;
target_write_u32(target, 0xFFE8BC00, fmmac1);
- LOG_DEBUG("set fmmac1 = 0x%04" PRIx32 "", fmmac1);
+ LOG_DEBUG("set fmmac1 = 0x%04" PRIx32, fmmac1);
/*
* FMTCREG = 0x2fc0;
@@ -542,7 +542,7 @@ static int tms470_flash_initialize_internal_state_machine(struct flash_bank *ban
LOG_DEBUG("set fmptr3 = 0x9b64");
}
target_write_u32(target, 0xFFE8A080, fmmaxep);
- LOG_DEBUG("set fmmaxep = 0x%04" PRIx32 "", fmmaxep);
+ LOG_DEBUG("set fmmaxep = 0x%04" PRIx32, fmmaxep);
/*
* FMPTR4 = 0xa000
@@ -562,56 +562,56 @@ static int tms470_flash_initialize_internal_state_machine(struct flash_bank *ban
sysclk = (plldis ? 1 : (glbctrl & 0x08) ? 4 : 8) * osc_mhz / (1 + (glbctrl & 7));
delay = (sysclk > 10) ? (sysclk + 1) / 2 : 5;
target_write_u32(target, 0xFFE8A018, (delay << 4) | (delay << 8));
- LOG_DEBUG("set fmpsetup = 0x%04" PRIx32 "", (delay << 4) | (delay << 8));
+ LOG_DEBUG("set fmpsetup = 0x%04" PRIx32, (delay << 4) | (delay << 8));
/*
* FMPVEVACCESS, based on delay.
*/
k = delay | (delay << 8);
target_write_u32(target, 0xFFE8A05C, k);
- LOG_DEBUG("set fmpvevaccess = 0x%04" PRIx32 "", k);
+ LOG_DEBUG("set fmpvevaccess = 0x%04" PRIx32, k);
/*
* FMPCHOLD, FMPVEVHOLD, FMPVEVSETUP, based on delay.
*/
k <<= 1;
target_write_u32(target, 0xFFE8A034, k);
- LOG_DEBUG("set fmpchold = 0x%04" PRIx32 "", k);
+ LOG_DEBUG("set fmpchold = 0x%04" PRIx32, k);
target_write_u32(target, 0xFFE8A040, k);
- LOG_DEBUG("set fmpvevhold = 0x%04" PRIx32 "", k);
+ LOG_DEBUG("set fmpvevhold = 0x%04" PRIx32, k);
target_write_u32(target, 0xFFE8A024, k);
- LOG_DEBUG("set fmpvevsetup = 0x%04" PRIx32 "", k);
+ LOG_DEBUG("set fmpvevsetup = 0x%04" PRIx32, k);
/*
* FMCVACCESS, based on delay.
*/
k = delay * 16;
target_write_u32(target, 0xFFE8A060, k);
- LOG_DEBUG("set fmcvaccess = 0x%04" PRIx32 "", k);
+ LOG_DEBUG("set fmcvaccess = 0x%04" PRIx32, k);
/*
* FMCSETUP, based on delay.
*/
k = 0x3000 | delay * 20;
target_write_u32(target, 0xFFE8A020, k);
- LOG_DEBUG("set fmcsetup = 0x%04" PRIx32 "", k);
+ LOG_DEBUG("set fmcsetup = 0x%04" PRIx32, k);
/*
* FMEHOLD, based on delay.
*/
k = (delay * 20) << 2;
target_write_u32(target, 0xFFE8A038, k);
- LOG_DEBUG("set fmehold = 0x%04" PRIx32 "", k);
+ LOG_DEBUG("set fmehold = 0x%04" PRIx32, k);
/*
* PWIDTH, CWIDTH, EWIDTH, based on delay.
*/
target_write_u32(target, 0xFFE8A050, delay * 8);
- LOG_DEBUG("set fmpwidth = 0x%04" PRIx32 "", delay * 8);
+ LOG_DEBUG("set fmpwidth = 0x%04" PRIx32, delay * 8);
target_write_u32(target, 0xFFE8A058, delay * 1000);
- LOG_DEBUG("set fmcwidth = 0x%04" PRIx32 "", delay * 1000);
+ LOG_DEBUG("set fmcwidth = 0x%04" PRIx32, delay * 1000);
target_write_u32(target, 0xFFE8A054, delay * 5400);
- LOG_DEBUG("set fmewidth = 0x%04" PRIx32 "", delay * 5400);
+ LOG_DEBUG("set fmewidth = 0x%04" PRIx32, delay * 5400);
return result;
}
@@ -625,7 +625,7 @@ static int tms470_flash_status(struct flash_bank *bank)
uint32_t fmmstat;
target_read_u32(target, 0xFFE8BC0C, &fmmstat);
- LOG_DEBUG("set fmmstat = 0x%04" PRIx32 "", fmmstat);
+ LOG_DEBUG("set fmmstat = 0x%04" PRIx32, fmmstat);
if (fmmstat & 0x0080) {
LOG_WARNING("tms470 flash command: erase still active after busy clear.");
@@ -680,7 +680,7 @@ static int tms470_erase_sector(struct flash_bank *bank, int sector)
*/
target_read_u32(target, 0xFFFFFFDC, &glbctrl);
target_write_u32(target, 0xFFFFFFDC, glbctrl | 0x10);
- LOG_DEBUG("set glbctrl = 0x%08" PRIx32 "", glbctrl | 0x10);
+ LOG_DEBUG("set glbctrl = 0x%08" PRIx32, glbctrl | 0x10);
/* Force normal read mode. */
target_read_u32(target, 0xFFE89C00, &orig_fmregopt);
@@ -697,11 +697,11 @@ static int tms470_erase_sector(struct flash_bank *bank, int sector)
if (sector < 16) {
target_read_u32(target, 0xFFE88008, &fmbsea);
target_write_u32(target, 0xFFE88008, fmbsea | (1 << sector));
- LOG_DEBUG("set fmbsea = 0x%04" PRIx32 "", fmbsea | (1 << sector));
+ LOG_DEBUG("set fmbsea = 0x%04" PRIx32, fmbsea | (1 << sector));
} else {
target_read_u32(target, 0xFFE8800C, &fmbseb);
target_write_u32(target, 0xFFE8800C, fmbseb | (1 << (sector - 16)));
- LOG_DEBUG("set fmbseb = 0x%04" PRIx32 "", fmbseb | (1 << (sector - 16)));
+ LOG_DEBUG("set fmbseb = 0x%04" PRIx32, fmbseb | (1 << (sector - 16)));
}
bank->sectors[sector].is_protected = 0;
@@ -729,17 +729,17 @@ static int tms470_erase_sector(struct flash_bank *bank, int sector)
if (sector < 16) {
target_write_u32(target, 0xFFE88008, fmbsea);
- LOG_DEBUG("set fmbsea = 0x%04" PRIx32 "", fmbsea);
+ LOG_DEBUG("set fmbsea = 0x%04" PRIx32, fmbsea);
bank->sectors[sector].is_protected = fmbsea & (1 << sector) ? 0 : 1;
} else {
target_write_u32(target, 0xFFE8800C, fmbseb);
- LOG_DEBUG("set fmbseb = 0x%04" PRIx32 "", fmbseb);
+ LOG_DEBUG("set fmbseb = 0x%04" PRIx32, fmbseb);
bank->sectors[sector].is_protected = fmbseb & (1 << (sector - 16)) ? 0 : 1;
}
target_write_u32(target, 0xFFE89C00, orig_fmregopt);
- LOG_DEBUG("set fmregopt = 0x%08" PRIx32 "", orig_fmregopt);
+ LOG_DEBUG("set fmregopt = 0x%08" PRIx32, orig_fmregopt);
target_write_u32(target, 0xFFFFFFDC, glbctrl);
- LOG_DEBUG("set glbctrl = 0x%08" PRIx32 "", glbctrl);
+ LOG_DEBUG("set glbctrl = 0x%08" PRIx32, glbctrl);
return result;
}
@@ -920,7 +920,7 @@ static int tms470_write(struct flash_bank *bank, const uint8_t *buffer, uint32_t
uint16_t word = (((uint16_t) buffer[i]) << 8) | (uint16_t) buffer[i + 1];
if (word != 0xffff) {
- LOG_INFO("writing 0x%04x at 0x%08" PRIx32 "", word, addr);
+ LOG_INFO("writing 0x%04x at 0x%08" PRIx32, word, addr);
/* clear status register */
target_write_u16(target, addr, 0x0040);
@@ -940,7 +940,7 @@ static int tms470_write(struct flash_bank *bank, const uint8_t *buffer, uint32_t
} while (fmmstat & 0x0100);
if (fmmstat & 0x3ff) {
- LOG_ERROR("fmstat = 0x%04" PRIx32 "", fmmstat);
+ LOG_ERROR("fmstat = 0x%04" PRIx32, fmmstat);
LOG_ERROR(
"Could not program word 0x%04x at address 0x%08" PRIx32 ".",
word,
@@ -949,7 +949,7 @@ static int tms470_write(struct flash_bank *bank, const uint8_t *buffer, uint32_t
break;
}
} else
- LOG_INFO("skipping 0xffff at 0x%08" PRIx32 "", addr);
+ LOG_INFO("skipping 0xffff at 0x%08" PRIx32, addr);
}
/* restore */
diff --git a/src/flash/nor/w600.c b/src/flash/nor/w600.c
index 20968dcaaa..ba4a42969b 100644
--- a/src/flash/nor/w600.c
+++ b/src/flash/nor/w600.c
@@ -128,13 +128,13 @@ static int w600_start_do(struct flash_bank *bank, uint32_t cmd, uint32_t addr,
if (len > 0)
cmd |= QFLASH_CMD_DATALEN(len - 1) | QFLASH_CMD_DATA;
- LOG_DEBUG("WRITE CMD: 0x%08" PRIx32 "", cmd);
+ LOG_DEBUG("WRITE CMD: 0x%08" PRIx32, cmd);
int retval = target_write_u32(target, QFLASH_CMD_INFO, cmd);
if (retval != ERROR_OK)
return retval;
addr |= QFLASH_START;
- LOG_DEBUG("WRITE START: 0x%08" PRIx32 "", addr);
+ LOG_DEBUG("WRITE START: 0x%08" PRIx32, addr);
retval = target_write_u32(target, QFLASH_CMD_START, addr);
if (retval != ERROR_OK)
return retval;
@@ -148,7 +148,7 @@ static int w600_start_do(struct flash_bank *bank, uint32_t cmd, uint32_t addr,
LOG_DEBUG("READ START...");
retval = target_read_u32(target, QFLASH_CMD_START, &status);
if (retval == ERROR_OK)
- LOG_DEBUG("READ START: 0x%08" PRIx32 "", status);
+ LOG_DEBUG("READ START: 0x%08" PRIx32, status);
else
LOG_DEBUG("READ START FAILED");
@@ -283,7 +283,7 @@ static int w600_probe(struct flash_bank *bank)
if (retval != ERROR_OK)
return retval;
- LOG_INFO("flash_id id = 0x%08" PRIx32 "", flash_id);
+ LOG_INFO("flash_id id = 0x%08" PRIx32, flash_id);
w600_info->id = flash_id;
w600_info->param = NULL;
for (i = 0; i < ARRAY_SIZE(w600_param); i++) {
@@ -360,7 +360,7 @@ static int get_w600_info(struct flash_bank *bank, struct command_invocation *cmd
if (retval != ERROR_OK)
return retval;
- command_print_sameline(cmd, "w600 : 0x%08" PRIx32 "", flash_id);
+ command_print_sameline(cmd, "w600 : 0x%08" PRIx32, flash_id);
return ERROR_OK;
}
diff --git a/src/flash/nor/xcf.c b/src/flash/nor/xcf.c
index 4011fa42be..04ee0d34a3 100644
--- a/src/flash/nor/xcf.c
+++ b/src/flash/nor/xcf.c
@@ -87,14 +87,14 @@ static const char *product_name(const struct flash_bank *bank)
{
switch (bank->target->tap->idcode & ID_MEANINGFUL_MASK) {
- case ID_XCF08P:
- return xcf_name_list[0];
- case ID_XCF16P:
- return xcf_name_list[1];
- case ID_XCF32P:
- return xcf_name_list[2];
- default:
- return xcf_name_list[3];
+ case ID_XCF08P:
+ return xcf_name_list[0];
+ case ID_XCF16P:
+ return xcf_name_list[1];
+ case ID_XCF32P:
+ return xcf_name_list[2];
+ default:
+ return xcf_name_list[3];
}
}
@@ -601,18 +601,18 @@ static int xcf_probe(struct flash_bank *bank)
/* guess number of blocks using chip ID */
id = bank->target->tap->idcode;
switch (id & ID_MEANINGFUL_MASK) {
- case ID_XCF08P:
- bank->num_sectors = 1;
- break;
- case ID_XCF16P:
- bank->num_sectors = 2;
- break;
- case ID_XCF32P:
- bank->num_sectors = 4;
- break;
- default:
- LOG_ERROR("Unknown flash device ID 0x%" PRIX32, id);
- return ERROR_FAIL;
+ case ID_XCF08P:
+ bank->num_sectors = 1;
+ break;
+ case ID_XCF16P:
+ bank->num_sectors = 2;
+ break;
+ case ID_XCF32P:
+ bank->num_sectors = 4;
+ break;
+ default:
+ LOG_ERROR("Unknown flash device ID 0x%" PRIX32, id);
+ return ERROR_FAIL;
}
bank->sectors = malloc(bank->num_sectors * sizeof(struct flash_sector));
diff --git a/src/helper/Makefile.am b/src/helper/Makefile.am
index 39d93d66ac..1b51ce056a 100644
--- a/src/helper/Makefile.am
+++ b/src/helper/Makefile.am
@@ -3,6 +3,7 @@
noinst_LTLIBRARIES += %D%/libhelper.la
%C%_libhelper_la_SOURCES = \
+ %D%/base64.c \
%D%/binarybuffer.c \
%D%/options.c \
%D%/time_support_common.c \
@@ -18,7 +19,9 @@ noinst_LTLIBRARIES += %D%/libhelper.la
%D%/jim-nvp.c \
%D%/nvp.c \
%D%/align.h \
+ %D%/base64.h \
%D%/binarybuffer.h \
+ %D%/bitfield.h \
%D%/bits.h \
%D%/configuration.h \
%D%/list.h \
@@ -29,6 +32,7 @@ noinst_LTLIBRARIES += %D%/libhelper.la
%D%/crc32.h \
%D%/time_support.h \
%D%/replacements.h \
+ %D%/string_choices.h \
%D%/fileio.h \
%D%/system.h \
%D%/jep106.h \
diff --git a/src/helper/base64.c b/src/helper/base64.c
index effa8acda0..5e0ee0846e 100644
--- a/src/helper/base64.c
+++ b/src/helper/base64.c
@@ -1,9 +1,11 @@
+// SPDX-License-Identifier: BSD-3-Clause
+
/*
* Base64 encoding/decoding (RFC1341)
* Copyright (c) 2005-2011, Jouni Malinen
*
- * This software may be distributed under the terms of the BSD license.
- * See README for more details.
+ * Original file from FreeBSD code
+ * https://cgit.freebsd.org/src/tree/contrib/wpa/src/utils/base64.c?id=f05cddf940db
*/
@@ -42,7 +44,7 @@ unsigned char *base64_encode(const unsigned char *src, size_t len,
if (olen < len)
return NULL; /* integer overflow */
out = malloc(olen);
- if (out == NULL)
+ if (!out)
return NULL;
end = src + len;
@@ -105,7 +107,7 @@ unsigned char *base64_decode(const unsigned char *src, size_t len,
memset(dtable, 0x80, 256);
for (i = 0; i < sizeof(base64_table) - 1; i++)
- dtable[base64_table[i]] = (unsigned char) i;
+ dtable[base64_table[i]] = (unsigned char)i;
dtable['='] = 0;
count = 0;
@@ -118,9 +120,10 @@ unsigned char *base64_decode(const unsigned char *src, size_t len,
return NULL;
olen = count / 4 * 3;
- pos = out = malloc(olen);
- if (out == NULL)
+ out = malloc(olen);
+ if (!out)
return NULL;
+ pos = out;
count = 0;
for (i = 0; i < len; i++) {
@@ -138,11 +141,11 @@ unsigned char *base64_decode(const unsigned char *src, size_t len,
*pos++ = (block[2] << 6) | block[3];
count = 0;
if (pad) {
- if (pad == 1)
+ if (pad == 1) {
pos--;
- else if (pad == 2)
+ } else if (pad == 2) {
pos -= 2;
- else {
+ } else {
/* Invalid padding */
free(out);
return NULL;
diff --git a/src/helper/base64.h b/src/helper/base64.h
index dbabb606ab..d3e0462131 100644
--- a/src/helper/base64.h
+++ b/src/helper/base64.h
@@ -1,9 +1,11 @@
+/* SPDX-License-Identifier: BSD-3-Clause */
+
/*
* Base64 encoding/decoding (RFC1341)
* Copyright (c) 2005, Jouni Malinen
*
- * This software may be distributed under the terms of the BSD license.
- * See README for more details.
+ * Original file from FreeBSD code
+ * https://cgit.freebsd.org/src/tree/contrib/wpa/src/utils/base64.h?id=f05cddf940db
*/
#ifndef BASE64_H
diff --git a/src/helper/bitfield.h b/src/helper/bitfield.h
new file mode 100644
index 0000000000..9f397282cf
--- /dev/null
+++ b/src/helper/bitfield.h
@@ -0,0 +1,60 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+
+/*
+* Copyright (c) 2020-2024 The FreeBSD Foundation
+*
+* This software was developed by Björn Zeeb under sponsorship from
+* the FreeBSD Foundation.
+*/
+
+#ifndef OPENOCD_HELPER_BITFIELD_H
+#define OPENOCD_HELPER_BITFIELD_H
+
+/**
+ * These macros come from FreeBSD, check source on
+ * https://cgit.freebsd.org/src/tree/sys/compat/linuxkpi/common/include/linux/bitfield.h
+ * Which does not include example usages of them.
+ */
+
+#define __bf_shf(x) (__builtin_ffsll(x) - 1)
+
+/**
+ * FIELD_FIT(_mask, _value) - Check if a value fits in the specified bitfield mask
+ * @_mask: Bitfield mask
+ * @_value: Value to check
+ *
+ * This macro checks whether a given value fits within the range defined by the
+ * specified bitfield mask. It ensures that no bits outside the mask are set.
+ *
+ * Return: true if the value fits, false otherwise.
+ */
+#define FIELD_FIT(_mask, _value) \
+ (!(((typeof(_mask))(_value) << __bf_shf(_mask)) & ~(_mask)))
+
+/**
+ * FIELD_PREP(_mask, _value) - Prepare a value for insertion into a bitfield
+ * @_mask: Bitfield mask
+ * @_value: Value to insert
+ *
+ * This macro prepares a value for insertion into a bitfield by shifting the
+ * value into the position defined by the mask and applying the mask.
+ *
+ * Return: The prepared bitfield value.
+ */
+#define FIELD_PREP(_mask, _value) \
+ (((typeof(_mask))(_value) << __bf_shf(_mask)) & (_mask))
+
+/**
+ * FIELD_GET(_mask, _value) - Extract a value from a bitfield
+ * @_mask: Bitfield mask
+ * @_value: Bitfield value to extract from
+ *
+ * This macro extracts a value from a bitfield by masking and shifting the
+ * relevant bits down to the least significant position.
+ *
+ * Return: The extracted value.
+ */
+#define FIELD_GET(_mask, _value) \
+ ((typeof(_mask))(((_value) & (_mask)) >> __bf_shf(_mask)))
+
+#endif /* OPENOCD_HELPER_BITFIELD_H */
diff --git a/src/helper/command.c b/src/helper/command.c
index 218f0581ef..4cce57f756 100644
--- a/src/helper/command.c
+++ b/src/helper/command.c
@@ -45,26 +45,22 @@ static enum command_mode get_command_mode(Jim_Interp *interp, const char *cmd_na
/* set of functions to wrap jimtcl internal data */
static inline bool jimcmd_is_proc(Jim_Cmd *cmd)
{
+#if defined(JIM_CMD_ISPROC)
+ // JIM_VERSION >= 84
+ return cmd->flags & JIM_CMD_ISPROC;
+#else
return cmd->isproc;
+#endif
}
bool jimcmd_is_oocd_command(Jim_Cmd *cmd)
{
- return !cmd->isproc && cmd->u.native.cmdProc == jim_command_dispatch;
+ return !jimcmd_is_proc(cmd) && cmd->u.native.cmdProc == jim_command_dispatch;
}
void *jimcmd_privdata(Jim_Cmd *cmd)
{
- return cmd->isproc ? NULL : cmd->u.native.privData;
-}
-
-static int command_retval_set(Jim_Interp *interp, int retval)
-{
- int *return_retval = Jim_GetAssocData(interp, "retval");
- if (return_retval)
- *return_retval = retval;
-
- return (retval == ERROR_OK) ? JIM_OK : retval;
+ return jimcmd_is_proc(cmd) ? NULL : cmd->u.native.privData;
}
extern struct command_context *global_cmd_ctx;
@@ -73,7 +69,7 @@ extern struct command_context *global_cmd_ctx;
* Do nothing in case we are not at debug level 3 */
static void script_debug(Jim_Interp *interp, unsigned int argc, Jim_Obj * const *argv)
{
- if (debug_level < LOG_LVL_DEBUG)
+ if (!LOG_LEVEL_IS(LOG_LVL_DEBUG))
return;
char *dbg = alloc_printf("command -");
@@ -130,13 +126,13 @@ static struct command *command_new(struct command_context *cmd_ctx,
assert(cr->name);
/*
- * If it is a non-jim command with no .usage specified,
+ * If it is a command with no .usage specified,
* log an error.
*
* strlen(.usage) == 0 means that the command takes no
* arguments.
*/
- if (!cr->jim_handler && !cr->usage)
+ if (!cr->usage)
LOG_ERROR("BUG: command '%s' does not have the "
"'.usage' field filled out",
full_name);
@@ -152,7 +148,6 @@ static struct command *command_new(struct command_context *cmd_ctx,
}
c->handler = cr->handler;
- c->jim_handler = cr->jim_handler;
c->mode = cr->mode;
if (cr->help || cr->usage)
@@ -406,28 +401,25 @@ static bool command_can_run(struct command_context *cmd_ctx, struct command *c,
/* Many commands may be run only before/after 'init' */
const char *when;
switch (c->mode) {
- case COMMAND_CONFIG:
- when = "before";
- break;
- case COMMAND_EXEC:
- when = "after";
- break;
- /* handle the impossible with humor; it guarantees a bug report! */
- default:
- when = "if Cthulhu is summoned by";
- break;
+ case COMMAND_CONFIG:
+ when = "before";
+ break;
+ case COMMAND_EXEC:
+ when = "after";
+ break;
+ /* handle the impossible with humor; it guarantees a bug report! */
+ default:
+ when = "if Cthulhu is summoned by";
+ break;
}
LOG_ERROR("The '%s' command must be used %s 'init'.",
full_name ? full_name : c->name, when);
return false;
}
-static int exec_command(Jim_Interp *interp, struct command_context *context,
+static int jim_exec_command(Jim_Interp *interp, struct command_context *context,
struct command *c, int argc, Jim_Obj * const *argv)
{
- if (c->jim_handler)
- return c->jim_handler(interp, argc, argv);
-
/* use c->handler */
const char **words = malloc(argc * sizeof(char *));
if (!words) {
@@ -474,7 +466,15 @@ static int exec_command(Jim_Interp *interp, struct command_context *context,
Jim_DecrRefCount(context->interp, cmd.output);
free(words);
- return command_retval_set(interp, retval);
+
+ if (retval == ERROR_OK)
+ return JIM_OK;
+
+ // used by telnet server to close one connection
+ if (retval == ERROR_COMMAND_CLOSE_CONNECTION)
+ return JIM_EXIT;
+
+ return JIM_ERR;
}
int command_run_line(struct command_context *context, char *line)
@@ -484,7 +484,6 @@ int command_run_line(struct command_context *context, char *line)
* results
*/
/* run the line thru a script engine */
- int retval = ERROR_FAIL;
int retcode;
/* Beware! This code needs to be reentrant. It is also possible
* for OpenOCD commands to be invoked directly from Tcl. This would
@@ -499,20 +498,17 @@ int command_run_line(struct command_context *context, char *line)
Jim_DeleteAssocData(interp, "context");
retcode = Jim_SetAssocData(interp, "context", NULL, context);
if (retcode == JIM_OK) {
- /* associated the return value */
- Jim_DeleteAssocData(interp, "retval");
- retcode = Jim_SetAssocData(interp, "retval", NULL, &retval);
- if (retcode == JIM_OK) {
- retcode = Jim_Eval_Named(interp, line, NULL, 0);
-
- Jim_DeleteAssocData(interp, "retval");
- }
+ retcode = Jim_Eval_Named(interp, line, NULL, 0);
Jim_DeleteAssocData(interp, "context");
int inner_retcode = Jim_SetAssocData(interp, "context", NULL, old_context);
if (retcode == JIM_OK)
retcode = inner_retcode;
}
context->current_target_override = saved_target_override;
+
+ if (retcode == JIM_RETURN)
+ retcode = interp->returnCode;
+
if (retcode == JIM_OK) {
const char *result;
int reslen;
@@ -522,25 +518,19 @@ int command_run_line(struct command_context *context, char *line)
command_output_text(context, result);
command_output_text(context, "\n");
}
- retval = ERROR_OK;
- } else if (retcode == JIM_EXIT) {
- /* ignore.
- * exit(Jim_GetExitCode(interp)); */
- } else if (retcode == ERROR_COMMAND_CLOSE_CONNECTION) {
- return retcode;
- } else {
- Jim_MakeErrorMessage(interp);
- /* error is broadcast */
- LOG_USER("%s", Jim_GetString(Jim_GetResult(interp), NULL));
+ return ERROR_OK;
+ }
- if (retval == ERROR_OK) {
- /* It wasn't a low level OpenOCD command that failed */
- return ERROR_FAIL;
- }
- return retval;
+ if (retcode == JIM_EXIT) {
+ // used by telnet server to close one connection
+ return ERROR_COMMAND_CLOSE_CONNECTION;
}
- return retval;
+ Jim_MakeErrorMessage(interp);
+ /* error is broadcast */
+ LOG_USER("%s", Jim_GetString(Jim_GetResult(interp), NULL));
+
+ return ERROR_FAIL;
}
int command_run_linef(struct command_context *context, const char *format, ...)
@@ -742,16 +732,16 @@ static COMMAND_HELPER(command_help_show, struct help_entry *c,
const char *stage_msg = "";
switch (mode) {
- case COMMAND_CONFIG:
- stage_msg = " (configuration command)";
- break;
- case COMMAND_ANY:
- stage_msg = " (command valid any time)";
- break;
- case COMMAND_UNKNOWN:
- default:
- stage_msg = " (?mode error?)";
- break;
+ case COMMAND_CONFIG:
+ stage_msg = " (configuration command)";
+ break;
+ case COMMAND_ANY:
+ stage_msg = " (command valid any time)";
+ break;
+ case COMMAND_UNKNOWN:
+ default:
+ stage_msg = " (?mode error?)";
+ break;
}
msg = alloc_printf("%s%s", c->help ? c->help : "", stage_msg);
} else
@@ -841,7 +831,7 @@ static int jim_command_dispatch(Jim_Interp *interp, int argc, Jim_Obj * const *a
script_debug(interp, argc, argv);
struct command *c = jim_to_command(interp);
- if (!c->jim_handler && !c->handler) {
+ if (!c->handler) {
Jim_EvalObjPrefix(interp, Jim_NewStringObj(interp, "usage", -1), 1, argv);
return JIM_ERR;
}
@@ -867,7 +857,7 @@ static int jim_command_dispatch(Jim_Interp *interp, int argc, Jim_Obj * const *a
if (c->jim_override_target)
cmd_ctx->current_target_override = c->jim_override_target;
- int retval = exec_command(interp, cmd_ctx, c, argc, argv);
+ int retval = jim_exec_command(interp, cmd_ctx, c, argc, argv);
if (c->jim_override_target)
cmd_ctx->current_target_override = saved_target_override;
@@ -912,19 +902,19 @@ COMMAND_HANDLER(handle_command_mode)
const char *mode_str;
switch (mode) {
- case COMMAND_ANY:
- mode_str = "any";
- break;
- case COMMAND_CONFIG:
- mode_str = "config";
- break;
- case COMMAND_EXEC:
- mode_str = "exec";
- break;
- case COMMAND_UNKNOWN:
- default:
- mode_str = "unknown";
- break;
+ case COMMAND_ANY:
+ mode_str = "any";
+ break;
+ case COMMAND_CONFIG:
+ mode_str = "config";
+ break;
+ case COMMAND_EXEC:
+ mode_str = "exec";
+ break;
+ case COMMAND_UNKNOWN:
+ default:
+ mode_str = "unknown";
+ break;
}
command_print(CMD, "%s", mode_str);
return ERROR_OK;
@@ -1329,19 +1319,19 @@ COMMAND_HELPER(command_parse_str_to_buf, const char *str, void *buf, unsigned in
COMMAND_HELPER(handle_command_parse_bool, bool *out, const char *label)
{
switch (CMD_ARGC) {
- case 1: {
- const char *in = CMD_ARGV[0];
- if (command_parse_bool_arg(in, out) != ERROR_OK) {
- LOG_ERROR("%s: argument '%s' is not valid", CMD_NAME, in);
- return ERROR_COMMAND_SYNTAX_ERROR;
- }
- }
- /* fallthrough */
- case 0:
- LOG_INFO("%s is %s", label, *out ? "enabled" : "disabled");
- break;
- default:
+ case 1: {
+ const char *in = CMD_ARGV[0];
+ if (command_parse_bool_arg(in, out) != ERROR_OK) {
+ LOG_ERROR("%s: argument '%s' is not valid", CMD_NAME, in);
return ERROR_COMMAND_SYNTAX_ERROR;
+ }
+ }
+ /* fallthrough */
+ case 0:
+ LOG_INFO("%s is %s", label, *out ? "enabled" : "disabled");
+ break;
+ default:
+ return ERROR_COMMAND_SYNTAX_ERROR;
}
return ERROR_OK;
}
diff --git a/src/helper/command.h b/src/helper/command.h
index 18fe561782..8bd2430e0b 100644
--- a/src/helper/command.h
+++ b/src/helper/command.h
@@ -197,7 +197,6 @@ typedef __COMMAND_HANDLER((*command_handler_t));
struct command {
char *name;
command_handler_t handler;
- Jim_CmdProc *jim_handler;
void *jim_handler_data;
/* Command handlers can use it for any handler specific data */
struct target *jim_override_target;
@@ -234,7 +233,6 @@ static inline struct command *jim_to_command(Jim_Interp *interp)
struct command_registration {
const char *name;
command_handler_t handler;
- Jim_CmdProc *jim_handler;
enum command_mode mode;
const char *help;
/** a string listing the options and arguments, required or optional */
diff --git a/src/helper/configuration.c b/src/helper/configuration.c
index 16732eb3dd..447b0dfefa 100644
--- a/src/helper/configuration.c
+++ b/src/helper/configuration.c
@@ -71,17 +71,18 @@ char *find_file(const char *file)
full_path = alloc_printf("%s", file);
fp = fopen(full_path, mode);
- while (!fp) {
- free(full_path);
- full_path = NULL;
- dir = *search_dirs++;
+ if (script_search_dirs)
+ while (!fp) {
+ free(full_path);
+ full_path = NULL;
+ dir = *search_dirs++;
- if (!dir)
- break;
+ if (!dir)
+ break;
- full_path = alloc_printf("%s/%s", dir, file);
- fp = fopen(full_path, mode);
- }
+ full_path = alloc_printf("%s/%s", dir, file);
+ fp = fopen(full_path, mode);
+ }
if (fp) {
fclose(fp);
diff --git a/src/helper/fileio.c b/src/helper/fileio.c
index a290a5d2ff..1059c67060 100644
--- a/src/helper/fileio.c
+++ b/src/helper/fileio.c
@@ -49,24 +49,24 @@ static inline int fileio_open_local(struct fileio *fileio)
ssize_t file_size;
switch (fileio->access) {
- case FILEIO_READ:
- strcpy(file_access, "r");
- break;
- case FILEIO_WRITE:
- strcpy(file_access, "w");
- break;
- case FILEIO_READWRITE:
- strcpy(file_access, "w+");
- break;
- case FILEIO_APPEND:
- strcpy(file_access, "a");
- break;
- case FILEIO_APPENDREAD:
- strcpy(file_access, "a+");
- break;
- default:
- LOG_ERROR("BUG: access neither read, write nor readwrite");
- return ERROR_COMMAND_SYNTAX_ERROR;
+ case FILEIO_READ:
+ strcpy(file_access, "r");
+ break;
+ case FILEIO_WRITE:
+ strcpy(file_access, "w");
+ break;
+ case FILEIO_READWRITE:
+ strcpy(file_access, "w+");
+ break;
+ case FILEIO_APPEND:
+ strcpy(file_access, "a");
+ break;
+ case FILEIO_APPENDREAD:
+ strcpy(file_access, "a+");
+ break;
+ default:
+ LOG_ERROR("BUG: access neither read, write nor readwrite");
+ return ERROR_COMMAND_SYNTAX_ERROR;
}
/* win32 always opens in binary mode */
diff --git a/src/helper/jep106.inc b/src/helper/jep106.inc
index 8bbaf4ca5c..5e50e19550 100644
--- a/src/helper/jep106.inc
+++ b/src/helper/jep106.inc
@@ -8,7 +8,7 @@
* identification code list, please visit the JEDEC website at www.jedec.org .
*/
-/* This file is aligned to revision JEP106BL February 2025. */
+/* This file is aligned to revision JEP106BM June 2025. */
[0][0x01 - 1] = "AMD",
[0][0x02 - 1] = "AMI",
@@ -78,7 +78,7 @@
[0][0x42 - 1] = "Macronix",
[0][0x43 - 1] = "Xerox",
[0][0x44 - 1] = "Plus Logic",
-[0][0x45 - 1] = "Western Digital Technologies Inc",
+[0][0x45 - 1] = "SanDisk Technologies Inc",
[0][0x46 - 1] = "Elan Circuit Tech.",
[0][0x47 - 1] = "European Silicon Str.",
[0][0x48 - 1] = "Apple Computer",
@@ -1798,7 +1798,7 @@
[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][0x19 - 1] = "Guangdong LeapFive Technology Limited",
[14][0x1a - 1] = "Jin JuQuan",
[14][0x1b - 1] = "Huaxuan Technology (Shenzhen) Co Ltd",
[14][0x1c - 1] = "Gigastone Corporation",
@@ -2049,4 +2049,39 @@
[16][0x15 - 1] = "Hangzhou Lishu Technology Co Ltd",
[16][0x16 - 1] = "Tier IV Inc",
[16][0x17 - 1] = "Wuhan Xuanluzhe Network Technology Co",
+[16][0x18 - 1] = "EA Semi (Shanghai) Limited",
+[16][0x19 - 1] = "Tech Vision Information Technology Co",
+[16][0x1a - 1] = "Zhihe Computing Technology",
+[16][0x1b - 1] = "Beijing Apexichips Tech",
+[16][0x1c - 1] = "Yemas Holdingsl Limited",
+[16][0x1d - 1] = "Eluktronics",
+[16][0x1e - 1] = "Walton Digi-Tech Industries Ltd",
+[16][0x1f - 1] = "Beijing Qixin Gongli Technology Co Ltd",
+[16][0x20 - 1] = "M.RED",
+[16][0x21 - 1] = "Shenzhen Damay Semiconductor Co Ltd",
+[16][0x22 - 1] = "Corelab Tech Singapore Holding PTE LTD",
+[16][0x23 - 1] = "EmBestor Technology Inc",
+[16][0x24 - 1] = "XConn Technologies",
+[16][0x25 - 1] = "Flagchip",
+[16][0x26 - 1] = "CUNNUC",
+[16][0x27 - 1] = "SGMicro",
+[16][0x28 - 1] = "Lanxin Computing (Shenzhen) Technology",
+[16][0x29 - 1] = "FuturePlus Systems LLC",
+[16][0x2a - 1] = "Shenzhen Jielong Storage Technology Co",
+[16][0x2b - 1] = "Precision Planting LLC",
+[16][0x2c - 1] = "Sichuan ZeroneStor Microelectronics Tech",
+[16][0x2d - 1] = "The University of Tokyo",
+[16][0x2e - 1] = "Aodu (Fujian) Information Technology Co",
+[16][0x2f - 1] = "Bytera Memory Inc",
+[16][0x30 - 1] = "XSemitron Technology Inc",
+[16][0x31 - 1] = "Cloud Ridge Ltd",
+[16][0x32 - 1] = "Shenzhen XinChiTai Technology Co Ltd",
+[16][0x33 - 1] = "Shenzhen Xinxin Semiconductor Co Ltd",
+[16][0x34 - 1] = "Shenzhen ShineKing Electronics Co Ltd.",
+[16][0x35 - 1] = "Shenzhen Shande Semiconductor Co. Ltd.",
+[16][0x36 - 1] = "AheadComputing",
+[16][0x37 - 1] = "Beijing Ronghua Kangweiye Technology",
+[16][0x38 - 1] = "Shanghai Yunsilicon Technology Co Ltd",
+[16][0x39 - 1] = "Shenzhen Wolongtai Technology Co Ltd.",
+[16][0x3a - 1] = "Vervesemi Microelectronics",
/* EOF */
diff --git a/src/helper/log.c b/src/helper/log.c
index 8f7ab00397..7acb154c62 100644
--- a/src/helper/log.c
+++ b/src/helper/log.c
@@ -113,7 +113,7 @@ static void log_puts(enum log_levels level,
if (f)
file = f + 1;
- if (debug_level >= LOG_LVL_DEBUG) {
+ if (LOG_LEVEL_IS(LOG_LVL_DEBUG)) {
/* print with count and time information */
int64_t t = timeval_ms() - start;
#ifdef _DEBUG_FREE_SPACE_
@@ -207,18 +207,19 @@ void log_printf_lf(enum log_levels level,
COMMAND_HANDLER(handle_debug_level_command)
{
- if (CMD_ARGC == 1) {
+ if (!CMD_ARGC) {
+ command_print(CMD, "%i", debug_level);
+ } else if (CMD_ARGC == 1) {
int new_level;
COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], new_level);
if ((new_level > LOG_LVL_DEBUG_IO) || (new_level < LOG_LVL_SILENT)) {
- LOG_ERROR("level must be between %d and %d", LOG_LVL_SILENT, LOG_LVL_DEBUG_IO);
- return ERROR_COMMAND_SYNTAX_ERROR;
+ command_print(CMD, "level must be between %d and %d", LOG_LVL_SILENT, LOG_LVL_DEBUG_IO);
+ return ERROR_COMMAND_ARGUMENT_INVALID;
}
debug_level = new_level;
- } else if (CMD_ARGC > 1)
+ } else {
return ERROR_COMMAND_SYNTAX_ERROR;
-
- command_print(CMD, "debug_level: %i", debug_level);
+ }
return ERROR_OK;
}
@@ -261,11 +262,11 @@ static const struct command_registration log_command_handlers[] = {
.name = "debug_level",
.handler = handle_debug_level_command,
.mode = COMMAND_ANY,
- .help = "Sets the verbosity level of debugging output. "
+ .help = "Sets or display the verbosity level of debugging output. "
"0 shows errors only; 1 adds warnings; "
"2 (default) adds other info; 3 adds debugging; "
"4 adds extra verbose debugging.",
- .usage = "number",
+ .usage = "[number]",
},
COMMAND_REGISTRATION_DONE
};
@@ -353,6 +354,8 @@ char *alloc_vprintf(const char *fmt, va_list ap)
int len;
char *string;
+ assert(fmt);
+
/* determine the length of the buffer needed */
va_copy(ap_copy, ap);
len = vsnprintf(NULL, 0, fmt, ap_copy);
diff --git a/src/helper/log.h b/src/helper/log.h
index ac24f8e833..b8e3e339ae 100644
--- a/src/helper/log.h
+++ b/src/helper/log.h
@@ -15,6 +15,7 @@
#define OPENOCD_HELPER_LOG_H
#include
+#include
/* To achieve C99 printf compatibility in MinGW, gnu_printf should be
* used for __attribute__((format( ... ))), with GCC v4.4 or later
@@ -86,9 +87,9 @@ int log_add_callback(log_callback_fn fn, void *priv);
int log_remove_callback(log_callback_fn fn, void *priv);
char *alloc_vprintf(const char *fmt, va_list ap)
- __attribute__ ((format (PRINTF_ATTRIBUTE_FORMAT, 1, 0)));
+ __attribute__ ((format (PRINTF_ATTRIBUTE_FORMAT, 1, 0))) __nonnull((1));
char *alloc_printf(const char *fmt, ...)
- __attribute__ ((format (PRINTF_ATTRIBUTE_FORMAT, 1, 2)));
+ __attribute__ ((format (PRINTF_ATTRIBUTE_FORMAT, 1, 2))) __nonnull((1));
const char *find_nonprint_char(const char *buf, unsigned int buf_len);
@@ -101,7 +102,7 @@ extern int debug_level;
#define LOG_DEBUG_IO(expr ...) \
do { \
- if (debug_level >= LOG_LVL_DEBUG_IO) \
+ if (LOG_LEVEL_IS(LOG_LVL_DEBUG_IO)) \
log_printf_lf(LOG_LVL_DEBUG, \
__FILE__, __LINE__, __func__, \
expr); \
@@ -109,7 +110,7 @@ extern int debug_level;
#define LOG_DEBUG(expr ...) \
do { \
- if (debug_level >= LOG_LVL_DEBUG) \
+ if (LOG_LEVEL_IS(LOG_LVL_DEBUG)) \
log_printf_lf(LOG_LVL_DEBUG, \
__FILE__, __LINE__, __func__, \
expr); \
@@ -118,7 +119,7 @@ extern int debug_level;
#define LOG_CUSTOM_LEVEL(level, expr ...) \
do { \
enum log_levels _level = level; \
- if (debug_level >= _level) \
+ if (LOG_LEVEL_IS(_level)) \
log_printf_lf(_level, \
__FILE__, __LINE__, __func__, \
expr); \
diff --git a/src/helper/options.c b/src/helper/options.c
index 735b8af5f6..28e2221717 100644
--- a/src/helper/options.c
+++ b/src/helper/options.c
@@ -277,44 +277,44 @@ int parse_cmdline_args(struct command_context *cmd_ctx, int argc, char *argv[])
break;
switch (c) {
- case 0:
- break;
- case 'h': /* --help | -h */
- help_flag = 1;
- break;
- case 'v': /* --version | -v */
- version_flag = 1;
- break;
- case 'f': /* --file | -f */
- {
- char *command = alloc_printf("script {%s}", optarg);
- add_config_command(command);
- free(command);
- break;
- }
- case 's': /* --search | -s */
- add_script_search_dir(optarg);
- break;
- case 'd': /* --debug | -d */
- {
- int retval = command_run_linef(cmd_ctx, "debug_level %s", optarg ? optarg : "3");
- if (retval != ERROR_OK)
- return retval;
- break;
- }
- case 'l': /* --log_output | -l */
- {
- int retval = command_run_linef(cmd_ctx, "log_output %s", optarg);
- if (retval != ERROR_OK)
- return retval;
- break;
- }
- case 'c': /* --command | -c */
- add_config_command(optarg);
- break;
- default: /* '?' */
- /* getopt will emit an error message, all we have to do is bail. */
- return ERROR_FAIL;
+ case 0:
+ break;
+ case 'h': /* --help | -h */
+ help_flag = 1;
+ break;
+ case 'v': /* --version | -v */
+ version_flag = 1;
+ break;
+ case 'f': /* --file | -f */
+ {
+ char *command = alloc_printf("script {%s}", optarg);
+ add_config_command(command);
+ free(command);
+ break;
+ }
+ case 's': /* --search | -s */
+ add_script_search_dir(optarg);
+ break;
+ case 'd': /* --debug | -d */
+ {
+ int retval = command_run_linef(cmd_ctx, "debug_level %s", optarg ? optarg : "3");
+ if (retval != ERROR_OK)
+ return retval;
+ break;
+ }
+ case 'l': /* --log_output | -l */
+ {
+ int retval = command_run_linef(cmd_ctx, "log_output %s", optarg);
+ if (retval != ERROR_OK)
+ return retval;
+ break;
+ }
+ case 'c': /* --command | -c */
+ add_config_command(optarg);
+ break;
+ default: /* '?' */
+ /* getopt will emit an error message, all we have to do is bail. */
+ return ERROR_FAIL;
}
}
diff --git a/src/helper/replacements.c b/src/helper/replacements.c
index 782d975184..9fb7b4a35b 100644
--- a/src/helper/replacements.c
+++ b/src/helper/replacements.c
@@ -152,6 +152,21 @@ int win_select(int max_fd, fd_set *rfds, fd_set *wfds, fd_set *efds, struct time
FD_ZERO(&sock_write);
FD_ZERO(&sock_except);
+ /* On Windows, if all provided sets are empty/NULL an error code of -1 is returned
+ * and WSAGetLastError() returns WSAEINVAL instead of delaying.
+ * We check for this case, delay and return 0 instead of calling select(). */
+ if (rfds && rfds->fd_count == 0)
+ rfds = NULL;
+ if (wfds && wfds->fd_count == 0)
+ wfds = NULL;
+ if (efds && efds->fd_count == 0)
+ efds = NULL;
+ if (!rfds && !wfds && !efds && tv) {
+ sleep(tv->tv_sec);
+ usleep(tv->tv_usec);
+ return 0;
+ }
+
/* build an array of handles for non-sockets */
for (i = 0; i < max_fd; i++) {
if (SAFE_FD_ISSET(i, rfds) || SAFE_FD_ISSET(i, wfds) || SAFE_FD_ISSET(i, efds)) {
diff --git a/src/helper/replacements.h b/src/helper/replacements.h
index ecc0e5e955..747c2ae09a 100644
--- a/src/helper/replacements.h
+++ b/src/helper/replacements.h
@@ -225,6 +225,20 @@ static inline int socket_select(int max_fd,
#endif
}
+static inline int socket_recv_timeout(int fd, unsigned long timeout_msec)
+{
+#ifdef _WIN32
+ DWORD timeout = timeout_msec;
+ return setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, (const char *)&timeout,
+ sizeof(timeout));
+#else
+ struct timeval tv;
+ tv.tv_sec = timeout_msec / 1000;
+ tv.tv_usec = (timeout_msec % 1000) * 1000;
+ return setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, (const char *)&tv, sizeof(tv));
+#endif
+}
+
#ifndef HAVE_ELF_H
typedef uint32_t Elf32_Addr;
diff --git a/src/helper/startup.tcl b/src/helper/startup.tcl
index e6e76e68fd..89ed71b900 100644
--- a/src/helper/startup.tcl
+++ b/src/helper/startup.tcl
@@ -7,7 +7,8 @@
# Try flipping / and \ to find file if the filename does not
# match the precise spelling
-proc find {filename} {
+# lappend _telnet_autocomplete_skip _find_internal
+proc _find_internal {filename} {
if {[catch {ocd_find $filename} t]==0} {
return $t
}
@@ -20,6 +21,49 @@ proc find {filename} {
# make sure error message matches original input string
return -code error "Can't find $filename"
}
+
+proc find {filename} {
+ if {[catch {_find_internal $filename} t]==0} {
+ return $t
+ }
+
+ # Check in vendor specific folder:
+
+ # - path/to/a/certain/vendor_config_file
+ # - path/to/a/certain/vendor-config_file
+ # replaced with
+ # - path/to/a/certain/vendor/config_file
+ regsub {([/\\])([^/\\_-]*)[_-]([^/\\]*$)} $filename "\\1\\2\\1\\3" f
+ if {[catch {_find_internal $f} t]==0} {
+ echo "WARNING: '$filename' is deprecated, use '$f' instead"
+ return $t
+ }
+
+ foreach vendor {nordic ti sifive st} {
+ # - path/to/a/certain/config_file
+ # replaced with
+ # - path/to/a/certain/${vendor}/config_file
+ regsub {([/\\])([^/\\]*$)} $filename "\\1$vendor\\1\\2" f
+ if {[catch {_find_internal $f} t]==0} {
+ echo "WARNING: '$filename' is deprecated, use '$f' instead"
+ return $t
+ }
+ }
+
+ # at last, check for explicit renaming
+ if {[catch {
+ source [_find_internal file_renaming.cfg]
+ set unixname [string map {\\ /} $filename]
+ regsub {^(.*/|)((board|chip|cpld|cpu|fpga|interface|target|test|tools)/.*.cfg$)} $unixname {{\1} {\2}} split
+ set newname [lindex $split 0][dict get $_file_renaming [lindex $split 1]]
+ _find_internal $newname
+ } t]==0} {
+ echo "WARNING: '$filename' is deprecated, use '$newname' instead"
+ return $t
+ }
+
+ return -code error "Can't find $filename"
+}
add_usage_text find ""
add_help_text find "print full path to file according to OpenOCD search rules"
diff --git a/src/helper/string_choices.h b/src/helper/string_choices.h
new file mode 100644
index 0000000000..7e535845da
--- /dev/null
+++ b/src/helper/string_choices.h
@@ -0,0 +1,22 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
+#ifndef OPENOCD_HELPER_STRING_CHOICES_H
+#define OPENOCD_HELPER_STRING_CHOICES_H
+
+#include
+
+/*
+ * This file contains helper functions that return one of two strings depending
+ * on a boolean value. The format of these functions is 'str_$true_$false' where
+ * $true and $false are the two corresponding strings.
+ *
+ * These helper functions are beneficial because they improve code consistency
+ * and reduce the number of hardcoded strings.
+ */
+
+static inline const char *str_enabled_disabled(bool value)
+{
+ return value ? "enabled" : "disabled";
+}
+
+#endif /* OPENOCD_HELPER_STRING_CHOICES_H */
diff --git a/src/helper/system.h b/src/helper/system.h
index bd96d626ab..60308abcd6 100644
--- a/src/helper/system.h
+++ b/src/helper/system.h
@@ -39,13 +39,6 @@
#include
#endif
-#ifdef __ECOS
-/* missing from eCos */
-#ifndef EFAULT
-#define EFAULT 14 /* Bad address */
-#endif
-#endif
-
#ifdef HAVE_NETINET_IN_H
#include
#endif
diff --git a/src/helper/types.h b/src/helper/types.h
index 53249e5b79..8b02d213b1 100644
--- a/src/helper/types.h
+++ b/src/helper/types.h
@@ -51,7 +51,7 @@
* Compute the number of elements of a variable length array.
*
* const char *strs[] = { "a", "b", "c" };
- * unsigned num_strs = ARRAY_SIZE(strs);
+ * size_t num_strs = ARRAY_SIZE(strs);
*
*/
#define ARRAY_SIZE(x) (sizeof(x) / sizeof(*(x)))
@@ -276,62 +276,6 @@ static inline int parity_u32(uint32_t x)
#endif
}
-#if defined(__ECOS)
-
-/* eCos plain lacks these definition... A series of upstream patches
- * could probably repair it, but it seems like too much work to be
- * worth it.
- */
-
-#if !defined(_STDINT_H)
-#define PRId32 "d"
-#define PRIi32 "i"
-#define PRIo32 "o"
-#define PRIu32 "u"
-#define PRIx32 "x"
-#define PRIX32 "X"
-#define SCNx32 "x"
-#define PRId8 PRId32
-#define SCNx64 "llx"
-#define PRId64 "lld"
-#define PRIi64 "lli"
-#define PRIo64 "llo"
-#define PRIu64 "llu"
-#define PRIx64 "llx"
-#define PRIX64 "llX"
-
-typedef CYG_ADDRWORD intptr_t;
-typedef int64_t intmax_t;
-typedef uint64_t uintmax_t;
-#define INT8_MAX 0x7f
-#define INT8_MIN (-INT8_MAX - 1)
-# define UINT8_MAX (255)
-#define INT16_MAX 0x7fff
-#define INT16_MIN (-INT16_MAX - 1)
-# define UINT16_MAX (65535)
-#define INT32_MAX 0x7fffffffL
-#define INT32_MIN (-INT32_MAX - 1L)
-# define UINT32_MAX (4294967295U)
-#define INT64_MAX 0x7fffffffffffffffLL
-#define INT64_MIN (-INT64_MAX - 1LL)
-#define UINT64_MAX (__CONCAT(INT64_MAX, U) * 2ULL + 1ULL)
-#endif
-
- #ifndef LLONG_MAX
- #define ULLONG_MAX UINT64_C(0xFFFFFFFFFFFFFFFF)
- #define LLONG_MAX INT64_C(0x7FFFFFFFFFFFFFFF)
- #define LLONG_MIN ULLONG_MAX
- #endif
-
-
-#define ULLONG_MAX 18446744073709551615
-
-/* C99, eCos is C90 compliant (with bits of C99) */
-#define isblank(c) ((c) == ' ' || (c) == '\t')
-
-
-#endif
-
typedef uint64_t target_addr_t;
#define TARGET_ADDR_MAX UINT64_MAX
#define TARGET_PRIdADDR PRId64
diff --git a/src/jtag/adapter.c b/src/jtag/adapter.c
index 6785a74ef1..c30a26c87b 100644
--- a/src/jtag/adapter.c
+++ b/src/jtag/adapter.c
@@ -53,17 +53,19 @@ static const struct gpio_map {
enum adapter_gpio_direction direction;
bool permit_drive_option;
bool permit_init_state_option;
+ bool permit_exit_state_option;
} gpio_map[ADAPTER_GPIO_IDX_NUM] = {
- [ADAPTER_GPIO_IDX_TDO] = { "tdo", ADAPTER_GPIO_DIRECTION_INPUT, false, true, },
- [ADAPTER_GPIO_IDX_TDI] = { "tdi", ADAPTER_GPIO_DIRECTION_OUTPUT, true, true, },
- [ADAPTER_GPIO_IDX_TMS] = { "tms", ADAPTER_GPIO_DIRECTION_OUTPUT, true, true, },
- [ADAPTER_GPIO_IDX_TCK] = { "tck", ADAPTER_GPIO_DIRECTION_OUTPUT, true, true, },
- [ADAPTER_GPIO_IDX_SWDIO] = { "swdio", ADAPTER_GPIO_DIRECTION_BIDIRECTIONAL, true, true, },
- [ADAPTER_GPIO_IDX_SWDIO_DIR] = { "swdio_dir", ADAPTER_GPIO_DIRECTION_OUTPUT, true, false, },
- [ADAPTER_GPIO_IDX_SWCLK] = { "swclk", ADAPTER_GPIO_DIRECTION_OUTPUT, true, true, },
- [ADAPTER_GPIO_IDX_TRST] = { "trst", ADAPTER_GPIO_DIRECTION_OUTPUT, false, true, },
- [ADAPTER_GPIO_IDX_SRST] = { "srst", ADAPTER_GPIO_DIRECTION_OUTPUT, false, true, },
- [ADAPTER_GPIO_IDX_LED] = { "led", ADAPTER_GPIO_DIRECTION_OUTPUT, true, true, },
+ [ADAPTER_GPIO_IDX_TDO] = { "tdo", ADAPTER_GPIO_DIRECTION_INPUT, false, true, true },
+ [ADAPTER_GPIO_IDX_TDI] = { "tdi", ADAPTER_GPIO_DIRECTION_OUTPUT, true, true, true },
+ [ADAPTER_GPIO_IDX_TMS] = { "tms", ADAPTER_GPIO_DIRECTION_OUTPUT, true, true, true },
+ [ADAPTER_GPIO_IDX_TCK] = { "tck", ADAPTER_GPIO_DIRECTION_OUTPUT, true, true, true },
+ [ADAPTER_GPIO_IDX_SWDIO] = { "swdio", ADAPTER_GPIO_DIRECTION_BIDIRECTIONAL, true, true, true },
+ [ADAPTER_GPIO_IDX_SWDIO_DIR] = { "swdio_dir", ADAPTER_GPIO_DIRECTION_OUTPUT, true, false, false },
+ [ADAPTER_GPIO_IDX_SWCLK] = { "swclk", ADAPTER_GPIO_DIRECTION_OUTPUT, true, true, true },
+ [ADAPTER_GPIO_IDX_TRST] = { "trst", ADAPTER_GPIO_DIRECTION_OUTPUT, false, true, true },
+ [ADAPTER_GPIO_IDX_SRST] = { "srst", ADAPTER_GPIO_DIRECTION_OUTPUT, false, true, true },
+ [ADAPTER_GPIO_IDX_LED] = { "led", ADAPTER_GPIO_DIRECTION_OUTPUT, true, true, true },
+ [ADAPTER_GPIO_IDX_USER0] = { "user0", ADAPTER_GPIO_DIRECTION_BIDIRECTIONAL, true, true, true },
};
static int adapter_config_khz(unsigned int khz);
@@ -269,15 +271,15 @@ int adapter_config_rclk(unsigned int fallback_speed_khz)
int adapter_get_speed(int *speed)
{
switch (adapter_config.clock_mode) {
- case CLOCK_MODE_KHZ:
- adapter_khz_to_speed(adapter_get_speed_khz(), speed);
- break;
- case CLOCK_MODE_RCLK:
- adapter_rclk_to_speed(adapter_config.rclk_fallback_speed_khz, speed);
- break;
- default:
- LOG_ERROR("BUG: unknown adapter clock mode");
- return ERROR_FAIL;
+ case CLOCK_MODE_KHZ:
+ adapter_khz_to_speed(adapter_get_speed_khz(), speed);
+ break;
+ case CLOCK_MODE_RCLK:
+ adapter_rclk_to_speed(adapter_config.rclk_fallback_speed_khz, speed);
+ break;
+ default:
+ LOG_ERROR("BUG: unknown adapter clock mode");
+ return ERROR_FAIL;
}
return ERROR_OK;
}
@@ -613,34 +615,34 @@ COMMAND_HANDLER(handle_reset_config_command)
/* minimal JTAG has neither SRST nor TRST (so that's the default) */
switch (new_cfg & (RESET_HAS_TRST | RESET_HAS_SRST)) {
- case RESET_HAS_SRST:
- modes[0] = "srst_only";
- break;
- case RESET_HAS_TRST:
- modes[0] = "trst_only";
- break;
- case RESET_TRST_AND_SRST:
- modes[0] = "trst_and_srst";
- break;
- default:
- modes[0] = "none";
- break;
+ case RESET_HAS_SRST:
+ modes[0] = "srst_only";
+ break;
+ case RESET_HAS_TRST:
+ modes[0] = "trst_only";
+ break;
+ case RESET_TRST_AND_SRST:
+ modes[0] = "trst_and_srst";
+ break;
+ default:
+ modes[0] = "none";
+ break;
}
/* normally SRST and TRST are decoupled; but bugs happen ... */
switch (new_cfg & (RESET_SRST_PULLS_TRST | RESET_TRST_PULLS_SRST)) {
- case RESET_SRST_PULLS_TRST:
- modes[1] = "srst_pulls_trst";
- break;
- case RESET_TRST_PULLS_SRST:
- modes[1] = "trst_pulls_srst";
- break;
- case RESET_SRST_PULLS_TRST | RESET_TRST_PULLS_SRST:
- modes[1] = "combined";
- break;
- default:
- modes[1] = "separate";
- break;
+ case RESET_SRST_PULLS_TRST:
+ modes[1] = "srst_pulls_trst";
+ break;
+ case RESET_TRST_PULLS_SRST:
+ modes[1] = "trst_pulls_srst";
+ break;
+ case RESET_SRST_PULLS_TRST | RESET_TRST_PULLS_SRST:
+ modes[1] = "combined";
+ break;
+ default:
+ modes[1] = "separate";
+ break;
}
/* TRST-less connectors include Altera, Xilinx, and minimal JTAG */
@@ -850,6 +852,7 @@ static COMMAND_HELPER(helper_adapter_gpio_print_config, enum adapter_gpio_config
const char *drive = "";
const char *pull = "";
const char *init_state = "";
+ const char *exit_state = "";
if (gpio_config->gpio_num == ADAPTER_GPIO_NOT_SET) {
command_print(CMD, "adapter gpio %s: not configured", gpio_map[gpio_idx].name);
@@ -908,9 +911,27 @@ static COMMAND_HELPER(helper_adapter_gpio_print_config, enum adapter_gpio_config
}
}
- command_print(CMD, "adapter gpio %s (%s): num %u, chip %d, active-%s%s%s%s",
+ if (gpio_map[gpio_idx].permit_exit_state_option) {
+ switch (gpio_config->exit_state) {
+ case ADAPTER_GPIO_EXIT_STATE_NO_CHANGE:
+ exit_state = ", exit-state no-change";
+ break;
+ case ADAPTER_GPIO_EXIT_STATE_INACTIVE:
+ exit_state = ", exit-state inactive";
+ break;
+ case ADAPTER_GPIO_EXIT_STATE_ACTIVE:
+ exit_state = ", exit-state active";
+ break;
+ case ADAPTER_GPIO_EXIT_STATE_INPUT:
+ exit_state = ", exit-state input";
+ break;
+ }
+ }
+
+
+ command_print(CMD, "adapter gpio %s (%s): num %u, chip %d, active-%s%s%s%s%s",
gpio_map[gpio_idx].name, dir, gpio_config->gpio_num, (int)gpio_config->chip_num, active_state,
- drive, pull, init_state);
+ drive, pull, init_state, exit_state);
return ERROR_OK;
}
@@ -1031,6 +1052,31 @@ COMMAND_HANDLER(adapter_gpio_config_handler)
}
}
+ if (gpio_map[gpio_idx].permit_exit_state_option) {
+ if (strcmp(CMD_ARGV[i], "-exit-no-change") == 0) {
+ ++i;
+ gpio_config->exit_state = ADAPTER_GPIO_EXIT_STATE_NO_CHANGE;
+ continue;
+ }
+ if (strcmp(CMD_ARGV[i], "-exit-inactive") == 0) {
+ ++i;
+ gpio_config->exit_state = ADAPTER_GPIO_EXIT_STATE_INACTIVE;
+ continue;
+ }
+ if (strcmp(CMD_ARGV[i], "-exit-active") == 0) {
+ ++i;
+ gpio_config->exit_state = ADAPTER_GPIO_EXIT_STATE_ACTIVE;
+ continue;
+ }
+
+ if (gpio_map[gpio_idx].direction == ADAPTER_GPIO_DIRECTION_BIDIRECTIONAL &&
+ strcmp(CMD_ARGV[i], "-exit-input") == 0) {
+ ++i;
+ gpio_config->exit_state = ADAPTER_GPIO_EXIT_STATE_INPUT;
+ continue;
+ }
+ }
+
LOG_ERROR("illegal option for adapter %s %s: %s",
CMD_NAME, gpio_map[gpio_idx].name, CMD_ARGV[i]);
return ERROR_COMMAND_SYNTAX_ERROR;
@@ -1168,7 +1214,8 @@ static const struct command_registration adapter_command_handlers[] = {
"[-active-high|-active-low] "
"[-push-pull|-open-drain|-open-source] "
"[-pull-none|-pull-up|-pull-down]"
- "[-init-inactive|-init-active|-init-input] ]",
+ "[-init-inactive|-init-active|-init-input] ]"
+ "[-exit-no-change|-exit-inactive|-exit-active|-exit-input] ]",
},
COMMAND_REGISTRATION_DONE
};
diff --git a/src/jtag/adapter.h b/src/jtag/adapter.h
index 556952f8d7..d76ea5e327 100644
--- a/src/jtag/adapter.h
+++ b/src/jtag/adapter.h
@@ -33,6 +33,14 @@ enum adapter_gpio_init_state {
ADAPTER_GPIO_INIT_STATE_INPUT,
};
+/** Supported exit states for GPIO */
+enum adapter_gpio_exit_state {
+ ADAPTER_GPIO_EXIT_STATE_NO_CHANGE, /* Should be zero so it is the default state */
+ ADAPTER_GPIO_EXIT_STATE_INACTIVE,
+ ADAPTER_GPIO_EXIT_STATE_ACTIVE,
+ ADAPTER_GPIO_EXIT_STATE_INPUT,
+};
+
/** Supported pull directions for GPIO */
enum adapter_gpio_pull {
ADAPTER_GPIO_PULL_NONE,
@@ -52,6 +60,7 @@ enum adapter_gpio_config_index {
ADAPTER_GPIO_IDX_SWCLK,
ADAPTER_GPIO_IDX_SRST,
ADAPTER_GPIO_IDX_LED,
+ ADAPTER_GPIO_IDX_USER0,
ADAPTER_GPIO_IDX_NUM, /* must be the last item */
};
@@ -61,6 +70,7 @@ struct adapter_gpio_config {
unsigned int chip_num;
enum adapter_gpio_drive_mode drive; /* For outputs only */
enum adapter_gpio_init_state init_state;
+ enum adapter_gpio_exit_state exit_state;
bool active_low;
enum adapter_gpio_pull pull;
};
diff --git a/src/jtag/core.c b/src/jtag/core.c
index 6dd2144c63..3261e60796 100644
--- a/src/jtag/core.c
+++ b/src/jtag/core.c
@@ -967,60 +967,60 @@ int default_interface_jtag_execute_queue(void)
struct jtag_command *cmd = jtag_command_queue_get();
int result = adapter_driver->jtag_ops->execute_queue(cmd);
- while (debug_level >= LOG_LVL_DEBUG_IO && cmd) {
+ while (LOG_LEVEL_IS(LOG_LVL_DEBUG_IO) && cmd) {
switch (cmd->type) {
- case JTAG_SCAN:
- LOG_DEBUG_IO("JTAG %s SCAN to %s",
- cmd->cmd.scan->ir_scan ? "IR" : "DR",
- tap_state_name(cmd->cmd.scan->end_state));
- for (unsigned int i = 0; i < cmd->cmd.scan->num_fields; i++) {
- struct scan_field *field = cmd->cmd.scan->fields + i;
- if (field->out_value) {
- char *str = buf_to_hex_str(field->out_value, field->num_bits);
- LOG_DEBUG_IO(" %ub out: %s", field->num_bits, str);
- free(str);
- }
- if (field->in_value) {
- char *str = buf_to_hex_str(field->in_value, field->num_bits);
- LOG_DEBUG_IO(" %ub in: %s", field->num_bits, str);
- free(str);
- }
+ case JTAG_SCAN:
+ LOG_DEBUG_IO("JTAG %s SCAN to %s",
+ cmd->cmd.scan->ir_scan ? "IR" : "DR",
+ tap_state_name(cmd->cmd.scan->end_state));
+ for (unsigned int i = 0; i < cmd->cmd.scan->num_fields; i++) {
+ struct scan_field *field = cmd->cmd.scan->fields + i;
+ if (field->out_value) {
+ char *str = buf_to_hex_str(field->out_value, field->num_bits);
+ LOG_DEBUG_IO(" %ub out: %s", field->num_bits, str);
+ free(str);
}
- break;
- case JTAG_TLR_RESET:
- LOG_DEBUG_IO("JTAG TLR RESET to %s",
- tap_state_name(cmd->cmd.statemove->end_state));
- break;
- case JTAG_RUNTEST:
- LOG_DEBUG_IO("JTAG RUNTEST %d cycles to %s",
- cmd->cmd.runtest->num_cycles,
- tap_state_name(cmd->cmd.runtest->end_state));
- break;
- case JTAG_RESET:
- {
- const char *reset_str[3] = {
- "leave", "deassert", "assert"
- };
- LOG_DEBUG_IO("JTAG RESET %s TRST, %s SRST",
- reset_str[cmd->cmd.reset->trst + 1],
- reset_str[cmd->cmd.reset->srst + 1]);
+ if (field->in_value) {
+ char *str = buf_to_hex_str(field->in_value, field->num_bits);
+ LOG_DEBUG_IO(" %ub in: %s", field->num_bits, str);
+ free(str);
}
- break;
- case JTAG_PATHMOVE:
- LOG_DEBUG_IO("JTAG PATHMOVE (TODO)");
- break;
- case JTAG_SLEEP:
- LOG_DEBUG_IO("JTAG SLEEP (TODO)");
- break;
- case JTAG_STABLECLOCKS:
- LOG_DEBUG_IO("JTAG STABLECLOCKS (TODO)");
- break;
- case JTAG_TMS:
- LOG_DEBUG_IO("JTAG TMS (TODO)");
- break;
- default:
- LOG_ERROR("Unknown JTAG command: %d", cmd->type);
- break;
+ }
+ break;
+ case JTAG_TLR_RESET:
+ LOG_DEBUG_IO("JTAG TLR RESET to %s",
+ tap_state_name(cmd->cmd.statemove->end_state));
+ break;
+ case JTAG_RUNTEST:
+ LOG_DEBUG_IO("JTAG RUNTEST %d cycles to %s",
+ cmd->cmd.runtest->num_cycles,
+ tap_state_name(cmd->cmd.runtest->end_state));
+ break;
+ case JTAG_RESET:
+ {
+ const char *reset_str[3] = {
+ "leave", "deassert", "assert"
+ };
+ LOG_DEBUG_IO("JTAG RESET %s TRST, %s SRST",
+ reset_str[cmd->cmd.reset->trst + 1],
+ reset_str[cmd->cmd.reset->srst + 1]);
+ }
+ break;
+ case JTAG_PATHMOVE:
+ LOG_DEBUG_IO("JTAG PATHMOVE (TODO)");
+ break;
+ case JTAG_SLEEP:
+ LOG_DEBUG_IO("JTAG SLEEP (TODO)");
+ break;
+ case JTAG_STABLECLOCKS:
+ LOG_DEBUG_IO("JTAG STABLECLOCKS (TODO)");
+ break;
+ case JTAG_TMS:
+ LOG_DEBUG_IO("JTAG TMS (TODO)");
+ break;
+ default:
+ LOG_ERROR("Unknown JTAG command: %d", cmd->type);
+ break;
}
cmd = cmd->next;
}
@@ -1551,22 +1551,22 @@ int jtag_init_inner(struct command_context *cmd_ctx)
*/
retval = jtag_examine_chain();
switch (retval) {
- case ERROR_OK:
- /* complete success */
- break;
- default:
- /* For backward compatibility reasons, try coping with
- * configuration errors involving only ID mismatches.
- * We might be able to talk to the devices.
- *
- * Also the device might be powered down during startup.
- *
- * After OpenOCD starts, we can try to power on the device
- * and run a reset.
- */
- LOG_ERROR("Trying to use configured scan chain anyway...");
- issue_setup = false;
- break;
+ case ERROR_OK:
+ /* complete success */
+ break;
+ default:
+ /* For backward compatibility reasons, try coping with
+ * configuration errors involving only ID mismatches.
+ * We might be able to talk to the devices.
+ *
+ * Also the device might be powered down during startup.
+ *
+ * After OpenOCD starts, we can try to power on the device
+ * and run a reset.
+ */
+ LOG_ERROR("Trying to use configured scan chain anyway...");
+ issue_setup = false;
+ break;
}
/* Now look at IR values. Problems here will prevent real
diff --git a/src/jtag/drivers/Makefile.am b/src/jtag/drivers/Makefile.am
index b0dd8e3ad1..5216e5d774 100644
--- a/src/jtag/drivers/Makefile.am
+++ b/src/jtag/drivers/Makefile.am
@@ -127,8 +127,6 @@ endif
if ANGIE
angiedir = $(pkgdatadir)/angie
DRIVERFILES += %D%/angie.c
- DRIVERFILES += %D%/angie/include/msgtypes.h
- EXTRA_DIST += %D%/angie/README
dist_angie_DATA = %D%/angie/angie_firmware.bin
dist_angie_DATA += %D%/angie/angie_bitstream.bit
%C%_libocdjtagdrivers_la_LIBADD += -lm
@@ -179,8 +177,8 @@ endif
if LINUXSPIDEV
DRIVERFILES += %D%/linuxspidev.c
endif
-if XLNX_PCIE_XVC
-DRIVERFILES += %D%/xlnx-pcie-xvc.c
+if XLNX_XVC
+DRIVERFILES += %D%/xlnx-xvc.c
endif
if BCM2835GPIO
DRIVERFILES += %D%/bcm2835gpio.c
@@ -188,15 +186,17 @@ endif
if OPENJTAG
DRIVERFILES += %D%/openjtag.c
endif
+if CMSIS_DAP_CORE
+DRIVERFILES += %D%/cmsis_dap.c
+endif
if CMSIS_DAP_HID
DRIVERFILES += %D%/cmsis_dap_usb_hid.c
-DRIVERFILES += %D%/cmsis_dap.c
endif
if CMSIS_DAP_USB
DRIVERFILES += %D%/cmsis_dap_usb_bulk.c
-if !CMSIS_DAP_HID
-DRIVERFILES += %D%/cmsis_dap.c
endif
+if CMSIS_DAP_TCP
+DRIVERFILES += %D%/cmsis_dap_tcp.c
endif
if IMX_GPIO
DRIVERFILES += %D%/imx_gpio.c
@@ -210,6 +210,9 @@ endif
if AM335XGPIO
DRIVERFILES += %D%/am335xgpio.c
endif
+if CH347
+DRIVERFILES += %D%/ch347.c
+endif
DRIVERHEADERS = \
%D%/bitbang.h \
diff --git a/src/jtag/drivers/amt_jtagaccel.c b/src/jtag/drivers/amt_jtagaccel.c
index 633c20413a..6f1718896e 100644
--- a/src/jtag/drivers/amt_jtagaccel.c
+++ b/src/jtag/drivers/amt_jtagaccel.c
@@ -332,43 +332,43 @@ static int amt_jtagaccel_execute_queue(struct jtag_command *cmd_queue)
while (cmd) {
switch (cmd->type) {
- case JTAG_RESET:
- LOG_DEBUG_IO("reset trst: %i srst %i",
- cmd->cmd.reset->trst,
- cmd->cmd.reset->srst);
- if (cmd->cmd.reset->trst == 1)
- tap_set_state(TAP_RESET);
- amt_jtagaccel_reset(cmd->cmd.reset->trst, cmd->cmd.reset->srst);
- break;
- case JTAG_RUNTEST:
- LOG_DEBUG_IO("runtest %i cycles, end in %i",
- cmd->cmd.runtest->num_cycles,
- cmd->cmd.runtest->end_state);
- amt_jtagaccel_end_state(cmd->cmd.runtest->end_state);
- amt_jtagaccel_runtest(cmd->cmd.runtest->num_cycles);
- break;
- case JTAG_TLR_RESET:
- LOG_DEBUG_IO("statemove end in %i", cmd->cmd.statemove->end_state);
- amt_jtagaccel_end_state(cmd->cmd.statemove->end_state);
- amt_jtagaccel_state_move();
- break;
- case JTAG_SCAN:
- LOG_DEBUG_IO("scan end in %i", cmd->cmd.scan->end_state);
- amt_jtagaccel_end_state(cmd->cmd.scan->end_state);
- scan_size = jtag_build_buffer(cmd->cmd.scan, &buffer);
- type = jtag_scan_type(cmd->cmd.scan);
- amt_jtagaccel_scan(cmd->cmd.scan->ir_scan, type, buffer, scan_size);
- if (jtag_read_buffer(buffer, cmd->cmd.scan) != ERROR_OK)
- retval = ERROR_JTAG_QUEUE_FAILED;
- free(buffer);
- break;
- case JTAG_SLEEP:
- LOG_DEBUG_IO("sleep %" PRIu32, cmd->cmd.sleep->us);
- jtag_sleep(cmd->cmd.sleep->us);
- break;
- default:
- LOG_ERROR("BUG: unknown JTAG command type encountered");
- exit(-1);
+ case JTAG_RESET:
+ LOG_DEBUG_IO("reset trst: %i srst %i",
+ cmd->cmd.reset->trst,
+ cmd->cmd.reset->srst);
+ if (cmd->cmd.reset->trst == 1)
+ tap_set_state(TAP_RESET);
+ amt_jtagaccel_reset(cmd->cmd.reset->trst, cmd->cmd.reset->srst);
+ break;
+ case JTAG_RUNTEST:
+ LOG_DEBUG_IO("runtest %i cycles, end in %i",
+ cmd->cmd.runtest->num_cycles,
+ cmd->cmd.runtest->end_state);
+ amt_jtagaccel_end_state(cmd->cmd.runtest->end_state);
+ amt_jtagaccel_runtest(cmd->cmd.runtest->num_cycles);
+ break;
+ case JTAG_TLR_RESET:
+ LOG_DEBUG_IO("statemove end in %i", cmd->cmd.statemove->end_state);
+ amt_jtagaccel_end_state(cmd->cmd.statemove->end_state);
+ amt_jtagaccel_state_move();
+ break;
+ case JTAG_SCAN:
+ LOG_DEBUG_IO("scan end in %i", cmd->cmd.scan->end_state);
+ amt_jtagaccel_end_state(cmd->cmd.scan->end_state);
+ scan_size = jtag_build_buffer(cmd->cmd.scan, &buffer);
+ type = jtag_scan_type(cmd->cmd.scan);
+ amt_jtagaccel_scan(cmd->cmd.scan->ir_scan, type, buffer, scan_size);
+ if (jtag_read_buffer(buffer, cmd->cmd.scan) != ERROR_OK)
+ retval = ERROR_JTAG_QUEUE_FAILED;
+ free(buffer);
+ break;
+ case JTAG_SLEEP:
+ LOG_DEBUG_IO("sleep %" PRIu32, cmd->cmd.sleep->us);
+ jtag_sleep(cmd->cmd.sleep->us);
+ break;
+ default:
+ LOG_ERROR("BUG: unknown JTAG command type encountered");
+ exit(-1);
}
cmd = cmd->next;
}
@@ -419,6 +419,8 @@ static int amt_jtagaccel_init(void)
#endif
uint8_t ar_status;
+ LOG_WARNING("This adapter is deprecated and support will be removed in the next release!");
+
#if PARPORT_USE_PPDEV == 1
if (device_handle > 0) {
LOG_ERROR("device is already opened");
diff --git a/src/jtag/drivers/angie.c b/src/jtag/drivers/angie.c
index 56a118eaed..6d8dc2c3b1 100644
--- a/src/jtag/drivers/angie.c
+++ b/src/jtag/drivers/angie.c
@@ -1,274 +1,398 @@
// SPDX-License-Identifier: GPL-2.0-or-later
-/***************************************************************************
- File : angie.c *
- Contents : OpenOCD driver code for NanoXplore USB-JTAG ANGIE *
- adapter hardware. *
- Based on openULINK driver code by: Martin Schmoelzer. *
- Copyright 2023, Ahmed Errached BOUDJELIDA, NanoXplore SAS. *
- *
- *
- ***************************************************************************/
+/****************************************************************************
+ * File : angie.c
+ * Contents : Driver code for NanoXplore USB-JTAG ANGIE
+ * adapter hardware.
+ * Based on FT232R driver code by: Serge Vakulenko
+ *
+ * Copyright 2024, Ahmed BOUDJELIDA, NanoXplore SAS.
+ *
+ ****************************************************************************/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
-#include
-#include
-#include
-#include "helper/system.h"
-#include
+#if IS_CYGWIN == 1
+#include "windows.h"
+#undef LOG_ERROR
+#endif
+
+// project specific includes
+#include
#include
#include
+#include
+#include "libusb_helper.h"
#include
#include
-#include "libusb_helper.h"
-#include "angie/include/msgtypes.h"
-/** USB Vendor ID of ANGIE device in unconfigured state (no firmware loaded
- * yet) or with its firmware. */
-#define ANGIE_VID 0x584e
+// system includes
+#include
+#include
+#include
+#include
+#include
+
+/*
+ * Sync bit bang mode is implemented as described in FTDI Application
+ * Note AN232R-01: "Bit Bang Modes for the ANGIE and FT245R".
+ */
-/** USB Product ID of ANGIE device in unconfigured state (no firmware loaded
- * yet) or with its firmware. */
-#define ANGIE_PID 0x414F
-#define ANGIE_PID_2 0x424e
-#define ANGIE_PID_3 0x4255
-#define ANGIE_PID_4 0x4355
-#define ANGIE_PID_5 0x4a55
+/**
+ * USB endpoints.
+ */
+#define IN_EP 0x84
+#define OUT_EP 0x02
-/** Address of EZ-USB ANGIE CPU Control & Status register. This register can be
- * written by issuing a Control EP0 vendor request. */
-#define CPUCS_REG 0xE600
+/**
+ * Address of EZ-USB ANGIE CPU Control & Status register.
+ * This register can be written by issuing a Control EP0 vendor request.
+ */
+#define CPUCS_REG 0xE600
/** USB Control EP0 bRequest: "Firmware Load". */
#define REQUEST_FIRMWARE_LOAD 0xA0
/** Value to write into CPUCS to put EZ-USB ANGIE into reset. */
-#define CPU_RESET 0x01
+#define CPU_RESET 0x01
/** Value to write into CPUCS to put EZ-USB ANGIE out of reset. */
-#define CPU_START 0x00
+#define CPU_START 0x00
/** Base address of firmware in EZ-USB ANGIE code space. */
-#define FIRMWARE_ADDR 0x0000
-
-/** USB interface number */
-#define USB_INTERFACE 0
+#define FIRMWARE_ADDR 0x0000
/** Delay (in microseconds) to wait while EZ-USB performs ReNumeration. */
-#define ANGIE_RENUMERATION_DELAY_US 1500000
+#define ANGIE_RENUMERATION_DELAY_US 800000
/** Default location of ANGIE firmware image. */
-#define ANGIE_FIRMWARE_FILE PKGDATADIR "/angie/angie_firmware.bin"
+#define ANGIE_FIRMWARE_FILE PKGDATADIR "/angie/angie_firmware.bin"
/** Default location of ANGIE firmware image. */
-#define ANGIE_BITSTREAM_FILE PKGDATADIR "/angie/angie_bitstream.bit"
+#define ANGIE_BITSTREAM_FILE PKGDATADIR "/angie/angie_bitstream.bit"
+
+/**
+ * Maximum size of a single firmware section.
+ * Entire EZ-USB ANGIE code space = 16kB
+ */
+#define ANGIE_FW_SECTION_SIZE 16384
+
+/** Vendor Requests */
+#define VR_CFGOPEN 0xB0
+#define VR_DATAOUTOPEN 0xB2
+
+#define ANGIE_VID 0x584E /* NX Vendor id */
+#define ANGIE_NPROG_PID 0x424E /* ANGIE non programmed */
+#define ANGIE_PROG_OOCD_PID 0x414F /* ANGIE programmed OpenOCD */
+#define ANGIE_PROG_NXB2_PID 0x4a55 /* ANGIE programmed Nxbase2 */
+
+#define TCK_GPIO 0
+#define TDI_GPIO 1
+#define TDO_GPIO 2
+#define TMS_GPIO 3
+#define NTRST_GPIO 4
+#define NSYSRST_GPIO 6
-/** Maximum size of a single firmware section. Entire EZ-USB ANGIE code space = 16kB */
-#define SECTION_BUFFERSIZE 16384
+#define ANGIE_XFER_BUFFER_TOTAL_SIZE (16 * 1024)
+#define ANGIE_USB_BULK_SIZE 512
-/** Tuning of OpenOCD SCAN commands split into multiple ANGIE commands. */
-#define SPLIT_SCAN_THRESHOLD 10
+/** USB timeout delay in milliseconds */
+#define ANGIE_USB_TIMEOUT_MS 1000
-/** ANGIE hardware type */
-enum angie_type {
- ANGIE,
+/**
+ * List of elements used in a multiple commands reply.
+ */
+struct read_queue {
+ struct list_head list;
};
-enum angie_payload_direction {
- PAYLOAD_DIRECTION_OUT,
- PAYLOAD_DIRECTION_IN
+/**
+ * Entry element used to forge a reply buffer for openocd JTAG core.
+ */
+struct read_queue_entry {
+ const struct scan_command *cmd;
+ int reply_buffer_offset;
+ uint8_t *buffer;
+ struct list_head list;
};
-enum angie_delay_type {
- DELAY_CLOCK_TCK,
- DELAY_CLOCK_TMS,
- DELAY_SCAN_IN,
- DELAY_SCAN_OUT,
- DELAY_SCAN_IO
+/**
+ * Angie device main context
+ */
+struct angie {
+ struct libusb_device_handle *usbdev;
+ uint8_t xfer_buffer[ANGIE_XFER_BUFFER_TOTAL_SIZE];
+ size_t xfer_buffer_len;
+ uint8_t reply_buffer[ANGIE_XFER_BUFFER_TOTAL_SIZE];
+ size_t reply_buffer_len;
+ struct read_queue read_queue;
};
/**
- * ANGIE command (ANGIE command queue element).
+ * Angie device singleton
+ */
+struct angie *angie_handle;
+
+/**
+ * Init read queue list
*
- * For the OUT direction payload, things are quite easy: Payload is stored
- * in a rather small array (up to 63 bytes), the payload is always allocated
- * by the function generating the command and freed by angie_clear_queue().
+ * @param queue: pointer on the read queue head
+ */
+static void angie_read_queue_init(struct read_queue *queue)
+{
+ INIT_LIST_HEAD(&queue->list);
+}
+
+
+/**
+ * Add a single entry to the read queue
*
- * For the IN direction payload, things get a little bit more complicated:
- * The maximum IN payload size for a single command is 64 bytes. Assume that
- * a single OpenOCD command needs to scan 256 bytes. This results in the
- * generation of four ANGIE commands. The function generating these
- * commands shall allocate an uint8_t[256] array. Each command's #payload_in
- * pointer shall point to the corresponding offset where IN data shall be
- * placed, while #payload_in_start shall point to the first element of the 256
- * byte array.
- * - first command: #payload_in_start + 0
- * - second command: #payload_in_start + 64
- * - third command: #payload_in_start + 128
- * - fourth command: #payload_in_start + 192
+ * @param queue: read queue list
+ * @param entry to append
+ */
+static void angie_read_queue_add(struct read_queue *queue,
+ struct read_queue_entry *entry)
+{
+ list_add_tail(&entry->list, &queue->list);
+}
+
+/**
+ * Execute elements enqueued in the read queue list
*
- * The last command sets #needs_postprocessing to true.
+ * @param queue: read queue list
+ * @param device: pointer on the angie device
*/
-struct angie_cmd {
- uint8_t id; /**< ANGIE command ID */
+static void angie_read_queue_execute(struct read_queue *queue,
+ struct angie *device)
+{
+ struct read_queue_entry *entry;
+ struct read_queue_entry *tmp;
+
+ list_for_each_entry_safe(entry, tmp, &queue->list, list) {
+ int scan_size = jtag_scan_size(entry->cmd);
+
+ // iterate over each bit in scan data
+ for (int bit_cnt = 0; bit_cnt < scan_size; bit_cnt++) {
+ // calculate byte index
+ int bytec = bit_cnt / 8;
+ // calculate bit mask: isolate the specific bit in corresponding byte
+ int bcval = 1 << (bit_cnt % 8);
+ // extract tdo value using index: "bit0_index + bit_cnt*2 + 1"
+ int val = device->reply_buffer[entry->reply_buffer_offset + bit_cnt * 2 + 1];
+ if (val & (1 << TDO_GPIO))
+ entry->buffer[bytec] |= bcval;
+ else
+ entry->buffer[bytec] &= ~bcval;
+ }
+
+ jtag_read_buffer(entry->buffer, entry->cmd);
- uint8_t *payload_out; /**< Pointer where OUT payload shall be stored */
- uint8_t payload_out_size; /**< OUT direction payload size for this command */
+ list_del(&entry->list);
+ free(entry->buffer);
+ free(entry);
+ }
+}
- uint8_t *payload_in_start; /**< Pointer to first element of IN payload array */
- uint8_t *payload_in; /**< Pointer where IN payload shall be stored */
- uint8_t payload_in_size; /**< IN direction payload size for this command */
+/**
+ * Clear the read queue list
+ *
+ * @param queue: read queue list
+ */
+static void angie_read_queue_clean(struct read_queue *queue)
+{
+ struct read_queue_entry *entry;
+ struct read_queue_entry *tmp;
- /** Indicates if this command needs post-processing */
- bool needs_postprocessing;
+ list_for_each_entry_safe(entry, tmp, &queue->list, list) {
+ list_del(&entry->list);
+ free(entry->buffer);
+ free(entry);
+ }
+}
- /** Indicates if angie_clear_queue() should free payload_in_start */
- bool free_payload_in_start;
+/**
+ * Flush a chunk of Angie's buffer
+ *
+ * USB write is done by configuring GPIF register on the target and calling
+ * a USB bulk transfer.
+ * Sequentially a USB read transferred is issued of the same size.
+ * All the operation are synchronous.
+ * Then the read queue list is executed once the read buffer has been retrieved.
+ *
+ * @param device: Angie device pointer
+ * @param xfer_size: amount of bytes to transfer
+ * @param offset: total bytes already sent during this transfer, this will
+ * offset the receive buffer accordingly
+ * @param bytes_sent: will contain the amount of bytes sent
+ * @return ERROR_OK on success, negative error code otherwise
+ */
+static int angie_buffer_flush_chunk(struct angie *device,
+ int xfer_size,
+ int offset,
+ int *bytes_sent)
+{
+ uint8_t gpifcnt[4];
+ int sent_chunk_size = 0, bytes_received = 0;
- /** Pointer to corresponding OpenOCD command for post-processing */
- struct jtag_command *cmd_origin;
+ if (bytes_sent)
+ *bytes_sent = 0;
- struct angie_cmd *next; /**< Pointer to next command (linked list) */
-};
+ h_u32_to_be(gpifcnt, xfer_size);
-/** Describes one driver instance */
-struct angie {
- struct libusb_context *libusb_ctx;
- struct libusb_device_handle *usb_device_handle;
- enum angie_type type;
-
- unsigned int ep_in; /**< IN endpoint number */
- unsigned int ep_out; /**< OUT endpoint number */
-
- /* delay value for "SLOW_CLOCK commands" in [0:255] range in units of 4 us;
- -1 means no need for delay */
- int delay_scan_in; /**< Delay value for SCAN_IN commands */
- int delay_scan_out; /**< Delay value for SCAN_OUT commands */
- int delay_scan_io; /**< Delay value for SCAN_IO commands */
- int delay_clock_tck; /**< Delay value for CLOCK_TMS commands */
- int delay_clock_tms; /**< Delay value for CLOCK_TCK commands */
-
- int commands_in_queue; /**< Number of commands in queue */
- struct angie_cmd *queue_start; /**< Pointer to first command in queue */
- struct angie_cmd *queue_end; /**< Pointer to last command in queue */
-};
+ int ret = jtag_libusb_control_transfer(device->usbdev,
+ LIBUSB_ENDPOINT_OUT | LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE,
+ VR_DATAOUTOPEN, 0, 0, (char *)gpifcnt, sizeof(gpifcnt),
+ ANGIE_USB_TIMEOUT_MS, NULL);
+ if (ret != ERROR_OK) {
+ LOG_ERROR("Failed to send GPIF count to target");
+ return ret;
+ }
-/**************************** Function Prototypes *****************************/
-
-/* USB helper functions */
-static int angie_usb_open(struct angie *device);
-static int angie_usb_close(struct angie *device);
-
-/* ANGIE MCU (Cypress EZ-USB) specific functions */
-static int angie_cpu_reset(struct angie *device, char reset_bit);
-static int angie_load_firmware_and_renumerate(struct angie *device, const char *filename,
- uint32_t delay_us);
-static int angie_load_firmware(struct angie *device, const char *filename);
-static int angie_load_bitstream(struct angie *device, const char *filename);
-static int angie_i2c_write(struct angie *device, uint8_t *i2c_data, uint8_t i2c_data_size);
-static int angie_io_extender_config(struct angie *device, uint8_t i2c_adr, uint8_t cfg_value);
-static int angie_write_firmware_section(struct angie *device,
- struct image *firmware_image, int section_index);
-
-/* Generic helper functions */
-static void angie_dump_signal_states(uint8_t input_signals, uint8_t output_signals);
-
-/* ANGIE command generation helper functions */
-static int angie_allocate_payload(struct angie_cmd *angie_cmd, int size,
- enum angie_payload_direction direction);
-
-/* ANGIE command queue helper functions */
-static int angie_get_queue_size(struct angie *device,
- enum angie_payload_direction direction);
-static void angie_clear_queue(struct angie *device);
-static int angie_append_queue(struct angie *device, struct angie_cmd *angie_cmd);
-static int angie_execute_queued_commands(struct angie *device, int timeout_ms);
-
-static void angie_dump_queue(struct angie *device);
-
-static int angie_append_scan_cmd(struct angie *device,
- enum scan_type scan_type,
- int scan_size_bits,
- uint8_t *tdi,
- uint8_t *tdo_start,
- uint8_t *tdo,
- uint8_t tms_count_start,
- uint8_t tms_sequence_start,
- uint8_t tms_count_end,
- uint8_t tms_sequence_end,
- struct jtag_command *origin,
- bool postprocess);
-static int angie_append_clock_tms_cmd(struct angie *device, uint8_t count,
- uint8_t sequence);
-static int angie_append_clock_tck_cmd(struct angie *device, uint16_t count);
-static int angie_append_get_signals_cmd(struct angie *device);
-static int angie_append_set_signals_cmd(struct angie *device, uint8_t low,
- uint8_t high);
-static int angie_append_sleep_cmd(struct angie *device, uint32_t us);
-static int angie_append_configure_tck_cmd(struct angie *device,
- int delay_scan_in,
- int delay_scan_out,
- int delay_scan_io,
- int delay_tck,
- int delay_tms);
-static int angie_append_test_cmd(struct angie *device);
-
-/* ANGIE TCK frequency helper functions */
-static int angie_calculate_delay(enum angie_delay_type type, long f, int *delay);
-
-/* Interface between ANGIE and OpenOCD */
-static void angie_set_end_state(enum tap_state endstate);
-static int angie_queue_statemove(struct angie *device);
-
-static int angie_queue_scan(struct angie *device, struct jtag_command *cmd);
-static int angie_queue_tlr_reset(struct angie *device, struct jtag_command *cmd);
-static int angie_queue_runtest(struct angie *device, struct jtag_command *cmd);
-static int angie_queue_pathmove(struct angie *device, struct jtag_command *cmd);
-static int angie_queue_sleep(struct angie *device, struct jtag_command *cmd);
-static int angie_queue_stableclocks(struct angie *device, struct jtag_command *cmd);
-
-static int angie_post_process_scan(struct angie_cmd *angie_cmd);
-static int angie_post_process_queue(struct angie *device);
-
-/* adapter driver functions */
-static int angie_execute_queue(struct jtag_command *cmd_queue);
-static int angie_khz(int khz, int *jtag_speed);
-static int angie_speed(int speed);
-static int angie_speed_div(int speed, int *khz);
-static int angie_init(void);
-static int angie_quit(void);
-static int angie_reset(int trst, int srst);
-
-/****************************** Global Variables ******************************/
-
-static struct angie *angie_handle;
-
-/**************************** USB helper functions ****************************/
+ ret = jtag_libusb_bulk_write(device->usbdev, OUT_EP,
+ (char *)device->xfer_buffer + offset,
+ xfer_size, ANGIE_USB_TIMEOUT_MS, &sent_chunk_size);
+ if (ret != ERROR_OK) {
+ LOG_ERROR("USB bulk transfer failed");
+ return ret;
+ }
+
+ ret = jtag_libusb_bulk_read(device->usbdev, IN_EP,
+ (char *)device->reply_buffer + offset,
+ sent_chunk_size, ANGIE_USB_TIMEOUT_MS, &bytes_received);
+ if (ret != ERROR_OK) {
+ LOG_ERROR("Failed to read USB reply");
+ return ret;
+ }
+
+ if (sent_chunk_size == xfer_size && bytes_received == xfer_size) {
+ device->reply_buffer_len += xfer_size;
+ device->xfer_buffer_len -= xfer_size;
+ if (bytes_sent)
+ *bytes_sent += sent_chunk_size;
+ } else {
+ return ERROR_FAIL;
+ }
+
+ return ERROR_OK;
+}
/**
- * Opens the ANGIE device
+ * Flush Angie transfer buffer
*
- * @param device pointer to struct angie identifying ANGIE driver instance.
- * @return on success: ERROR_OK
- * @return on failure: ERROR_FAIL
+ * Flush is done by chunks of 512 bytes to match hardware internal FIFOs.
+ * Then the read queue list is executed once the read buffer has been retrieved.
+ *
+ * @param device: Angie device pointer
+ * @return ERROR_OK on success, negative error code otherwise
*/
-static int angie_usb_open(struct angie *device)
+static int angie_buffer_flush(struct angie *device)
+{
+ if (device->xfer_buffer_len == 0)
+ return ERROR_OK;
+
+ int total_bytes_sent = 0;
+ device->reply_buffer_len = 0;
+
+ do {
+ int sent_chunk_size;
+ size_t xfer_size = MIN(device->xfer_buffer_len, ANGIE_USB_BULK_SIZE);
+ int ret = angie_buffer_flush_chunk(device, xfer_size,
+ total_bytes_sent, &sent_chunk_size);
+ if (ret != ERROR_OK)
+ return ret;
+ total_bytes_sent += sent_chunk_size;
+ } while (device->xfer_buffer_len > 0);
+
+ angie_read_queue_execute(&device->read_queue, device);
+
+ return ERROR_OK;
+}
+
+/**
+ * Check if transfer buffer has enough remaining space for a given size.
+ * If the buffer is not large enough, flush it.
+ *
+ * @param device: Angie device pointer
+ * @param size to check
+ * @return ERROR_OK on success, negative error code otherwise
+ */
+static int angie_buffer_flush_check(struct angie *device, size_t size)
+{
+ if (device->xfer_buffer_len + size >= ANGIE_XFER_BUFFER_TOTAL_SIZE)
+ return angie_buffer_flush(device);
+ return ERROR_OK;
+}
+
+/**
+ * Append a single byte value to the transfer buffer
+ *
+ * @param device: Angie device pointer
+ * @param value to append
+ * @return ERROR_OK on success, negative error code otherwise
+ */
+static int angie_buffer_append_simple(struct angie *device, uint8_t value)
{
- struct libusb_device_handle *usb_device_handle;
- const uint16_t vids[] = {ANGIE_VID, ANGIE_VID, ANGIE_VID, ANGIE_VID, ANGIE_VID, 0};
- const uint16_t pids[] = {ANGIE_PID, ANGIE_PID_2, ANGIE_PID_3, ANGIE_PID_4, ANGIE_PID_5, 0};
+ if (device->xfer_buffer_len >= ANGIE_XFER_BUFFER_TOTAL_SIZE) {
+ int ret = angie_buffer_flush(device);
+ if (ret != ERROR_OK)
+ return ret;
+ }
+ device->xfer_buffer[device->xfer_buffer_len++] = value;
+ return ERROR_OK;
+}
- int ret = jtag_libusb_open(vids, pids, NULL, &usb_device_handle, NULL);
+/**
+ * Append a bit-bang JTAG value to the transfer buffer.
+ *
+ * @param device: Angie device pointer
+ * @param tck value
+ * @param tms value
+ * @param tdi value
+ * @return ERROR_OK on success, negative error code otherwise
+ */
+static int angie_buffer_append(struct angie *device, int tck, int tms, int tdi)
+{
+ uint8_t val = (1 << NTRST_GPIO) | (1 << NSYSRST_GPIO);
+ if (tck)
+ val |= (1 << TCK_GPIO);
+ if (tms)
+ val |= (1 << TMS_GPIO);
+ if (tdi)
+ val |= (1 << TDI_GPIO);
+
+ return angie_buffer_append_simple(device, val);
+}
+/**
+ * Open Angie USB interface
+ *
+ * @param device: Angie device pointer
+ * @return ERROR_OK on success, negative error code otherwise
+ */
+static int angie_usb_open(struct angie *device)
+{
+ uint16_t avids[] = {
+ ANGIE_VID,
+ ANGIE_VID,
+ ANGIE_VID,
+ 0,
+ };
+ uint16_t apids[] = {
+ ANGIE_NPROG_PID,
+ ANGIE_PROG_OOCD_PID,
+ ANGIE_PROG_NXB2_PID,
+ 0,
+ };
+ struct libusb_device_handle *usb_dev;
+
+ int ret = jtag_libusb_open(avids, apids, NULL, &usb_dev, NULL);
if (ret != ERROR_OK) {
- LOG_ERROR("Could not find and open ANGIE");
+ LOG_ERROR("Failed to open ANGIE USB interface");
return ret;
}
- device->usb_device_handle = usb_device_handle;
- device->type = ANGIE;
+ device->usbdev = usb_dev;
return ERROR_OK;
}
@@ -276,80 +400,84 @@ static int angie_usb_open(struct angie *device)
/**
* Releases the ANGIE interface and closes the USB device handle.
*
- * @param device pointer to struct angie identifying ANGIE driver instance.
- * @return on success: ERROR_OK
- * @return on failure: ERROR_FAIL
+ * @param device: Angie device pointer
+ * @return ERROR_OK on success, negative error code otherwise
*/
static int angie_usb_close(struct angie *device)
{
- if (device->usb_device_handle) {
- if (libusb_release_interface(device->usb_device_handle, 0) != 0) {
+ int ret = ERROR_OK;
+
+ if (device->usbdev) {
+ if (libusb_release_interface(device->usbdev, 0) != LIBUSB_SUCCESS) {
LOG_ERROR("Could not release interface 0");
- return ERROR_FAIL;
+ ret = ERROR_FAIL;
}
- jtag_libusb_close(device->usb_device_handle);
- device->usb_device_handle = NULL;
+ jtag_libusb_close(device->usbdev);
+ device->usbdev = NULL;
}
- return ERROR_OK;
-}
-/******************* ANGIE CPU (EZ-USB) specific functions ********************/
+ return ret;
+}
/**
* Writes '0' or '1' to the CPUCS register, putting the EZ-USB CPU into reset
* or out of reset.
*
- * @param device pointer to struct angie identifying ANGIE driver instance.
+ * @param device: Angie device pointer
* @param reset_bit 0 to put CPU into reset, 1 to put CPU out of reset.
- * @return on success: ERROR_OK
- * @return on failure: ERROR_FAIL
+ * @return ERROR_OK on success, negative error code otherwise
*/
static int angie_cpu_reset(struct angie *device, char reset_bit)
{
- return jtag_libusb_control_transfer(device->usb_device_handle,
- (LIBUSB_ENDPOINT_OUT | LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE),
- REQUEST_FIRMWARE_LOAD, CPUCS_REG, 0, &reset_bit, 1, LIBUSB_TIMEOUT_MS, NULL);
+ return jtag_libusb_control_transfer(device->usbdev,
+ LIBUSB_ENDPOINT_OUT | LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE,
+ REQUEST_FIRMWARE_LOAD, CPUCS_REG, 0, &reset_bit, 1,
+ ANGIE_USB_TIMEOUT_MS, NULL);
}
/**
- * Puts the ANGIE's EZ-USB microcontroller into reset state, downloads
- * the firmware image, resumes the microcontroller and re-enumerates
- * USB devices.
+ * Send one contiguous firmware section to the ANGIE's EZ-USB microcontroller
+ * over the USB bus.
*
- * @param device pointer to struct angie identifying ANGIE driver instance.
- * The usb_handle member will be modified during re-enumeration.
- * @param filename path to the Intel HEX file containing the firmware image.
- * @param delay_us the delay to wait for the device to re-enumerate.
- * @return on success: ERROR_OK
- * @return on failure: ERROR_FAIL
+ * @param device: Angie device pointer
+ * @param address: address of the firmware section
+ * @param data: pointer to the data to be sent
+ * @param size: size of the data
+ * @return ERROR_OK on success, negative error code otherwise
*/
-static int angie_load_firmware_and_renumerate(struct angie *device,
- const char *filename, uint32_t delay_us)
+static int angie_write_firmware_section(struct angie *device, uint16_t address,
+ uint8_t *data, size_t size)
{
- int ret;
+ int bytes_remaining = size;
- /* Basic process: After downloading the firmware, the ANGIE will disconnect
- * itself and re-connect after a short amount of time so we have to close
- * the handle and re-enumerate USB devices */
+ // Send section data in chunks of up to 64 bytes to ANGIE
+ while (bytes_remaining > 0) {
+ int chunk_size;
+ int transferred;
- ret = angie_load_firmware(device, filename);
- if (ret != ERROR_OK)
- return ret;
+ if (bytes_remaining > 64)
+ chunk_size = 64;
+ else
+ chunk_size = bytes_remaining;
- ret = angie_usb_close(device);
- if (ret != ERROR_OK)
- return ret;
+ int ret = jtag_libusb_control_transfer(device->usbdev,
+ LIBUSB_ENDPOINT_OUT | LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE,
+ REQUEST_FIRMWARE_LOAD, address, FIRMWARE_ADDR, (char *)data,
+ chunk_size, ANGIE_USB_TIMEOUT_MS, &transferred);
- usleep(delay_us);
+ if (ret != ERROR_OK)
+ return ret;
- ret = angie_usb_open(device);
- if (ret != ERROR_OK)
- return ret;
+ if (transferred != chunk_size) {
+ // Abort if libusb sent less data than requested
+ return ERROR_FAIL;
+ }
- ret = libusb_claim_interface(angie_handle->usb_device_handle, 0);
- if (ret != LIBUSB_SUCCESS)
- return ERROR_FAIL;
+ bytes_remaining -= chunk_size;
+ address += chunk_size;
+ data += chunk_size;
+ }
return ERROR_OK;
}
@@ -358,18 +486,16 @@ static int angie_load_firmware_and_renumerate(struct angie *device,
* Downloads a firmware image to the ANGIE's EZ-USB microcontroller
* over the USB bus.
*
- * @param device pointer to struct angie identifying ANGIE driver instance.
- * @param filename an absolute or relative path to the Intel HEX file
+ * @param device: Angie device pointer
+ * @param filename: an absolute or relative path to the Intel HEX file
* containing the firmware image.
- * @return on success: ERROR_OK
- * @return on failure: ERROR_FAIL
+ * @return ERROR_OK on success, negative error code otherwise
*/
static int angie_load_firmware(struct angie *device, const char *filename)
{
struct image angie_firmware_image;
- int ret;
- ret = angie_cpu_reset(device, CPU_RESET);
+ int ret = angie_cpu_reset(device, CPU_RESET);
if (ret != ERROR_OK) {
LOG_ERROR("Could not halt ANGIE CPU");
return ret;
@@ -384,12 +510,34 @@ static int angie_load_firmware(struct angie *device, const char *filename)
return ret;
}
- /* Download all sections in the image to ANGIE */
+ uint8_t *data = malloc(ANGIE_FW_SECTION_SIZE);
+ if (!data) {
+ LOG_ERROR("Out of memory");
+ return ERROR_FAIL;
+ }
+
+ // Download all sections in the image to ANGIE
for (unsigned int i = 0; i < angie_firmware_image.num_sections; i++) {
- ret = angie_write_firmware_section(device, &angie_firmware_image, i);
+ size_t size_read;
+ uint32_t size = angie_firmware_image.sections[i].size;
+ int addr = angie_firmware_image.sections[i].base_address;
+
+ LOG_DEBUG("section %02i at addr 0x%04x (size 0x%04" PRIx32 ")",
+ i, addr, size);
+
+ ret = image_read_section(&angie_firmware_image, i, 0,
+ size, data, &size_read);
+ if (ret != ERROR_OK)
+ goto exit;
+ if (size_read != size) {
+ ret = ERROR_FAIL;
+ goto exit;
+ }
+
+ ret = angie_write_firmware_section(device, addr, data, size);
if (ret != ERROR_OK) {
LOG_ERROR("Could not write firmware section");
- return ret;
+ goto exit;
}
}
@@ -398,9 +546,52 @@ static int angie_load_firmware(struct angie *device, const char *filename)
ret = angie_cpu_reset(device, CPU_START);
if (ret != ERROR_OK) {
LOG_ERROR("Could not restart ANGIE CPU");
- return ret;
+ goto exit;
}
+exit:
+ free(data);
+ return ret;
+}
+
+/**
+ * Puts the ANGIE's EZ-USB microcontroller into reset state, downloads
+ * the firmware image, resumes the microcontroller and re-enumerates
+ * USB devices.
+ *
+ * @param device: Angie device pointer
+ * The usb_handle member will be modified during re-enumeration.
+ * @param filename: path to the Intel HEX file containing the firmware image.
+ * @param delay_us: the delay to wait for the device to re-enumerate.
+ * @return ERROR_OK on success, negative error code otherwise
+ */
+static int angie_load_firmware_and_renumerate(struct angie *device,
+ const char *filename,
+ uint32_t delay_us)
+{
+ /*
+ * Basic process: After downloading the firmware, the ANGIE will disconnect
+ * itself and re-connect after a short amount of time so we have to close
+ * the handle and re-enumerate USB devices.
+ */
+
+ int ret = angie_load_firmware(device, filename);
+ if (ret != ERROR_OK)
+ return ret;
+
+ ret = angie_usb_close(device);
+ if (ret != ERROR_OK)
+ return ret;
+
+ usleep(delay_us);
+
+ ret = angie_usb_open(device);
+ if (ret != ERROR_OK)
+ return ret;
+
+ if (libusb_claim_interface(angie_handle->usbdev, 0) != LIBUSB_SUCCESS)
+ return ERROR_FAIL;
+
return ERROR_OK;
}
@@ -408,1982 +599,766 @@ static int angie_load_firmware(struct angie *device, const char *filename)
* Downloads a bitstream file to the ANGIE's FPGA through the EZ-USB microcontroller
* over the USB bus.
*
- * @param device pointer to struct angie identifying ANGIE driver instance.
- * @param filename an absolute or relative path to the Xilinx .bit file
+ * @param device: Angie device pointer
+ * @param filename: an absolute or relative path to the Xilinx .bit file
* containing the bitstream data.
- * @return on success: ERROR_OK
- * @return on failure: ERROR_FAIL
+ * @return ERROR_OK on success, negative error code otherwise
*/
static int angie_load_bitstream(struct angie *device, const char *filename)
{
- int ret, transferred;
+ int ret = ERROR_OK, transferred;
const char *bitstream_file_path = filename;
FILE *bitstream_file = NULL;
char *bitstream_data = NULL;
- size_t bitstream_size = 0;
uint8_t gpifcnt[4];
- /* Open the bitstream file */
+ // Open the bitstream file
bitstream_file = fopen(bitstream_file_path, "rb");
if (!bitstream_file) {
LOG_ERROR("Failed to open bitstream file: %s\n", bitstream_file_path);
- return ERROR_FAIL;
+ ret = ERROR_FAIL;
+ goto exit;
}
- /* Get the size of the bitstream file */
+ // Get the size of the bitstream file
fseek(bitstream_file, 0, SEEK_END);
- bitstream_size = ftell(bitstream_file);
+ size_t bitstream_size = ftell(bitstream_file);
fseek(bitstream_file, 0, SEEK_SET);
- /* Allocate memory for the bitstream data */
+ // Allocate memory for the bitstream data
bitstream_data = malloc(bitstream_size);
if (!bitstream_data) {
LOG_ERROR("Failed to allocate memory for bitstream data.");
- fclose(bitstream_file);
- return ERROR_FAIL;
+ ret = ERROR_FAIL;
+ goto exit;
}
- /* Read the bitstream data from the file */
+ // Read the bitstream data from the file
if (fread(bitstream_data, 1, bitstream_size, bitstream_file) != bitstream_size) {
LOG_ERROR("Failed to read bitstream data.");
- free(bitstream_data);
- fclose(bitstream_file);
- return ERROR_FAIL;
+ ret = ERROR_FAIL;
+ goto exit;
}
+ // CFG Open
h_u32_to_be(gpifcnt, bitstream_size);
-
- /* CFGopen */
- ret = jtag_libusb_control_transfer(device->usb_device_handle,
- 0x00, 0xB0, 0, 0, (char *)gpifcnt, 4, LIBUSB_TIMEOUT_MS, &transferred);
+ ret = jtag_libusb_control_transfer(device->usbdev,
+ LIBUSB_ENDPOINT_OUT | LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE,
+ VR_CFGOPEN, 0, 0, (char *)gpifcnt, sizeof(gpifcnt),
+ ANGIE_USB_TIMEOUT_MS, &transferred);
if (ret != ERROR_OK) {
LOG_ERROR("Failed opencfg");
- /* Abort if libusb sent less data than requested */
- return ERROR_FAIL;
+ goto exit;
}
- /* Send the bitstream data to the microcontroller */
+ // Send the bitstream data to the microcontroller
int actual_length = 0;
- ret = jtag_libusb_bulk_write(device->usb_device_handle, 0x02, bitstream_data, bitstream_size, 1000, &actual_length);
+ ret = jtag_libusb_bulk_write(device->usbdev, OUT_EP, bitstream_data,
+ bitstream_size, ANGIE_USB_TIMEOUT_MS, &actual_length);
if (ret != ERROR_OK) {
LOG_ERROR("Failed to send bitstream data: %s", libusb_strerror(ret));
- free(bitstream_data);
- fclose(bitstream_file);
- return ERROR_FAIL;
+ goto exit;
}
LOG_INFO("Bitstream sent successfully.");
- /* Clean up */
+exit:
free(bitstream_data);
- fclose(bitstream_file);
+ if (bitstream_file)
+ fclose(bitstream_file);
- /* CFGclose */
- transferred = 0;
- ret = jtag_libusb_control_transfer(device->usb_device_handle,
- 0x00, 0xB1, 0, 0, NULL, 0, LIBUSB_TIMEOUT_MS, &transferred);
- if (ret != ERROR_OK) {
- LOG_ERROR("Failed cfgclose");
- /* Abort if libusb sent less data than requested */
- return ERROR_FAIL;
- }
- return ERROR_OK;
+ return ret;
}
/**
- * Send an i2c write operation to dev-board components.
+ * Check if Angie firmware must be updated
*
- * @param device pointer to struct angie identifying ANGIE driver instance.
- * @param i2c_data table of i2c data that we want to write to slave device.
- * @param i2c_data_size the size of i2c data table.
- * @return on success: ERROR_OK
- * @return on failure: ERROR_FAIL
+ * @param device: Angie device pointer
+ * @return true if update is needed, false otherwise
*/
-static int angie_i2c_write(struct angie *device, uint8_t *i2c_data, uint8_t i2c_data_size)
+static bool angie_is_firmware_needed(struct angie *device)
{
- char i2c_data_buffer[i2c_data_size + 2];
- char buffer_received[1];
- int ret, transferred;
- i2c_data_buffer[0] = 0; // write = 0
- i2c_data_buffer[1] = i2c_data_size - 1; // i2c_data count (without address)
-
- for (uint8_t i = 0; i < i2c_data_size; i++)
- i2c_data_buffer[i + 2] = i2c_data[i];
-
- // Send i2c packet to Dev-board and configure its clock source /
- ret = jtag_libusb_bulk_write(device->usb_device_handle, 0x06, i2c_data_buffer,
- i2c_data_size + 2, 1000, &transferred);
- if (ret != ERROR_OK) {
- LOG_ERROR("Error in i2c clock gen configuration : ret ERROR");
- return ret;
- }
- if (transferred != i2c_data_size + 2) {
- LOG_ERROR("Error in i2c clock gen configuration : bytes transferred");
- return ERROR_FAIL;
- }
+ struct libusb_device_descriptor desc;
- usleep(500);
+ // Get String Descriptor to determine if firmware needs to be loaded
+ int ret = libusb_get_device_descriptor(libusb_get_device(angie_handle->usbdev),
+ &desc);
+ if (ret != LIBUSB_SUCCESS)
+ // Could not get descriptor -> Unconfigured or original Keil firmware
+ return true;
+ else if (desc.idProduct != ANGIE_PROG_OOCD_PID)
+ return true;
- // Receive packet from ANGIE /
- ret = jtag_libusb_bulk_write(device->usb_device_handle, 0x88, buffer_received, 1, 1000, &transferred);
- if (ret != ERROR_OK) {
- LOG_ERROR("Error in i2c clock gen configuration : ret ERROR");
- return ret;
+ return false;
+}
+
+/**
+ * Set TAP end state
+ *
+ * @param state
+ */
+static void angie_set_end_state(enum tap_state state)
+{
+ if (tap_is_state_stable(state)) {
+ tap_set_end_state(state);
+ } else {
+ LOG_ERROR("BUG: %i is not a valid end state", state);
+ exit(-1);
}
- return ERROR_OK;
}
/**
- * Configure dev-board gpio extender modules by configuring their
- * register 3 and register 1 responsible for IO directions and values.
+ * Move TAP to given state
*
- * @param device pointer to struct angie identifying ANGIE driver instance.
- * @param i2c_adr i2c address of the gpio extender.
- * @param cfg_value IOs configuration to be written in register Number 3.
- * @param value the IOs value to be written in register Number 1.
- * @return on success: ERROR_OK
- * @return on failure: ERROR_FAIL
+ * @param device: Angie device pointer
+ * @param skip: number of state to skip during move
+ * @return ERROR_OK on success, negative error code otherwise
*/
-static int angie_io_extender_config(struct angie *device, uint8_t i2c_adr, uint8_t cfg_value)
+static int angie_state_move(struct angie *device, int skip)
{
- uint8_t ioconfig[3] = {i2c_adr, 3, cfg_value};
- int ret = angie_i2c_write(device, ioconfig, 3);
+ int ret;
+ int tms = 0;
+ uint8_t tms_scan = tap_get_tms_path(tap_get_state(), tap_get_end_state());
+ int tms_count = tap_get_tms_path_len(tap_get_state(), tap_get_end_state());
+
+ // tms_scan has 8 bits that we bitbang one by one
+ for (int i = skip; i < tms_count; i++) {
+ tms = (tms_scan >> i) & 1;
+ ret = angie_buffer_append(device, 0, tms, 0);
+ if (ret != ERROR_OK)
+ return ret;
+ ret = angie_buffer_append(device, 1, tms, 0);
+ if (ret != ERROR_OK)
+ return ret;
+ }
+ ret = angie_buffer_append(device, 0, tms, 0);
if (ret != ERROR_OK)
return ret;
- usleep(500);
- return ret;
+ tap_set_state(tap_get_end_state());
+
+ return ERROR_OK;
}
/**
- * Send one contiguous firmware section to the ANGIE's EZ-USB microcontroller
- * over the USB bus.
+ * Return JTAG SCAN command size in bytes
*
- * @param device pointer to struct angie identifying ANGIE driver instance.
- * @param firmware_image pointer to the firmware image that contains the section
- * which should be sent to the ANGIE's EZ-USB microcontroller.
- * @param section_index index of the section within the firmware image.
- * @return on success: ERROR_OK
- * @return on failure: ERROR_FAIL
+ * @param device: Angie device pointer
+ * @param cmd: SCAN command
+ * @return size of command in the transfer buffer in bytes
*/
-static int angie_write_firmware_section(struct angie *device,
- struct image *firmware_image, int section_index)
+static int angie_jtag_scan_size(struct angie *device,
+ const struct scan_command *cmd)
{
- int addr, bytes_remaining, chunk_size;
- uint8_t data[SECTION_BUFFERSIZE];
- uint8_t *data_ptr = data;
- uint16_t size;
- size_t size_read;
- int ret, transferred;
+ int cmd_size = 0;
+ int count = 0;
- size = (uint16_t)firmware_image->sections[section_index].size;
- addr = (uint16_t)firmware_image->sections[section_index].base_address;
+ // move to TAP_IRSHIFT or TAP_DRSHIFT state
+ if (cmd->ir_scan)
+ count = tap_get_tms_path_len(tap_get_state(), TAP_IRSHIFT);
+ else
+ count = tap_get_tms_path_len(tap_get_state(), TAP_DRSHIFT);
+ cmd_size += count * 2 + 1;
+
+ // add scan size
+ cmd_size += jtag_scan_size(cmd) * 2;
+
+ /*
+ * move to cmd specified end state
+ * Also, see below function
+ * we *KNOW* the above loop transitioned out of
+ * the shift state, so we skip the first state
+ * and move directly to the end state.
+ */
+ if (cmd->ir_scan)
+ count = tap_get_tms_path_len(TAP_IRSHIFT, cmd->end_state) - 1;
+ else
+ count = tap_get_tms_path_len(TAP_DRSHIFT, cmd->end_state) - 1;
+ cmd_size += count * 2 + 1;
- LOG_DEBUG("section %02i at addr 0x%04x (size 0x%04" PRIx16 ")", section_index, addr,
- size);
+ return cmd_size;
+}
- /* Copy section contents to local buffer */
- ret = image_read_section(firmware_image, section_index, 0, size, data,
- &size_read);
+/**
+ * Execute JTAG SCAN command
+ *
+ * @param device: Angie device pointer
+ * @param cmd: SCAN command
+ * @return ERROR_OK on success, negative error code otherwise
+ */
+static int angie_jtag_execute_scan(struct angie *device,
+ const struct scan_command *cmd)
+{
+ uint8_t *buffer = NULL;
+ LOG_DEBUG_IO("SCAN: size=%d %s scan end in %s", jtag_scan_size(cmd),
+ (cmd->ir_scan) ? "IR" : "DR", tap_state_name(cmd->end_state));
+ if (cmd->ir_scan) {
+ if (tap_get_state() != TAP_IRSHIFT)
+ angie_set_end_state(TAP_IRSHIFT);
+ } else {
+ if (tap_get_state() != TAP_DRSHIFT)
+ angie_set_end_state(TAP_DRSHIFT);
+ }
+ int ret = angie_state_move(device, 0);
if (ret != ERROR_OK)
return ret;
- if (size_read != size)
- return ERROR_FAIL;
+ angie_set_end_state(cmd->end_state);
+
+ // Execute scan
+ int scan_size = jtag_build_buffer(cmd, &buffer);
+ enum scan_type type = jtag_scan_type(cmd);
+
+ // starting byte index
+ int start_offset = device->xfer_buffer_len;
+
+ // iterate over each bit in all scan data
+ int tms = 0;
+ int tdi = 0;
+ for (int i = 0; i < scan_size; i++) {
+ // calculate tms
+ // if we finish shifting tdi bits : '1' , else '0'
+ tms = (i == scan_size - 1) ? 1 : 0;
+ // calculate byte index
+ int bytec = i / 8;
+ // calculate bit mask: isolate the specific bit in corresponding byte
+ int bcval = 1 << (i % 8);
+ // if type is not SCAN_IN (not just reading data)
+ // and the bit masked is '1' then tdi = '1'
+ tdi = 0;
+ if (type != SCAN_IN && (buffer[bytec] & bcval))
+ tdi = 1;
+ // write tdi and tms twice in tck=0 and tck=1
+ ret = angie_buffer_append(device, 0, tms, tdi);
+ if (ret != ERROR_OK)
+ return ret;
+ ret = angie_buffer_append(device, 1, tms, tdi);
+ if (ret != ERROR_OK)
+ return ret;
+ }
- bytes_remaining = size;
+ angie_set_end_state(cmd->end_state);
+ if (tap_get_state() != tap_get_end_state()) {
+ /*
+ * We *KNOW* the above loop transitioned out of
+ * the shift state, so we skip the first state
+ * and move directly to the end state.
+ */
+ ret = angie_state_move(device, 1);
+ if (ret != ERROR_OK)
+ return ret;
+ }
- /* Send section data in chunks of up to 64 bytes to ANGIE */
- while (bytes_remaining > 0) {
- if (bytes_remaining > 64)
- chunk_size = 64;
- else
- chunk_size = bytes_remaining;
-
- ret = jtag_libusb_control_transfer(device->usb_device_handle,
- (LIBUSB_ENDPOINT_OUT | LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE),
- REQUEST_FIRMWARE_LOAD, addr, FIRMWARE_ADDR, (char *)data_ptr,
- chunk_size, LIBUSB_TIMEOUT_MS, &transferred);
-
- if (ret != ERROR_OK)
- return ret;
-
- if (transferred != chunk_size) {
- /* Abort if libusb sent less data than requested */
+ if (jtag_scan_type(cmd) != SCAN_OUT) {
+ // queue read back buffer for further processing
+ struct read_queue_entry *entry = malloc(sizeof(*entry));
+ if (!entry) {
+ LOG_ERROR("Out of memory");
+ free(buffer);
return ERROR_FAIL;
}
- bytes_remaining -= chunk_size;
- addr += chunk_size;
- data_ptr += chunk_size;
- }
-
- return ERROR_OK;
-}
-
-/************************** Generic helper functions **************************/
-
-/**
- * Print state of interesting signals via LOG_INFO().
- *
- * @param input_signals input signal states as returned by CMD_GET_SIGNALS
- * @param output_signals output signal states as returned by CMD_GET_SIGNALS
- */
-static void angie_dump_signal_states(uint8_t input_signals, uint8_t output_signals)
-{
- LOG_INFO("ANGIE signal states: TDI: %i, TDO: %i, TMS: %i, TCK: %i, TRST: %i "
- "SRST: %i",
- (output_signals & SIGNAL_TDI ? 1 : 0),
- (input_signals & SIGNAL_TDO ? 1 : 0),
- (output_signals & SIGNAL_TMS ? 1 : 0),
- (output_signals & SIGNAL_TCK ? 1 : 0),
- (output_signals & SIGNAL_TRST ? 1 : 0),
- (output_signals & SIGNAL_SRST ? 1 : 0));
-}
-
-/**************** ANGIE command generation helper functions ***************/
-
-/**
- * Allocate and initialize space in memory for ANGIE command payload.
- *
- * @param angie_cmd pointer to command whose payload should be allocated.
- * @param size the amount of memory to allocate (bytes).
- * @param direction which payload to allocate.
- * @return on success: ERROR_OK
- * @return on failure: ERROR_FAIL
- */
-static int angie_allocate_payload(struct angie_cmd *angie_cmd, int size,
- enum angie_payload_direction direction)
-{
- uint8_t *payload;
-
- payload = calloc(size, sizeof(uint8_t));
-
- if (!payload) {
- LOG_ERROR("Could not allocate ANGIE command payload: out of memory");
- return ERROR_FAIL;
- }
-
- switch (direction) {
- case PAYLOAD_DIRECTION_OUT:
- if (angie_cmd->payload_out) {
- LOG_ERROR("BUG: Duplicate payload allocation for ANGIE command");
- free(payload);
- return ERROR_FAIL;
- }
- angie_cmd->payload_out = payload;
- angie_cmd->payload_out_size = size;
- break;
- case PAYLOAD_DIRECTION_IN:
- if (angie_cmd->payload_in_start) {
- LOG_ERROR("BUG: Duplicate payload allocation for ANGIE command");
- free(payload);
- return ERROR_FAIL;
- }
-
- angie_cmd->payload_in_start = payload;
- angie_cmd->payload_in = payload;
- angie_cmd->payload_in_size = size;
-
- /* By default, free payload_in_start in angie_clear_queue(). Commands
- * that do not want this behavior (e. g. split scans) must turn it off
- * separately! */
- angie_cmd->free_payload_in_start = true;
-
- break;
- }
-
- return ERROR_OK;
-}
-
-/****************** ANGIE command queue helper functions ******************/
-
-/**
- * Get the current number of bytes in the queue, including command IDs.
- *
- * @param device pointer to struct angie identifying ANGIE driver instance.
- * @param direction the transfer direction for which to get byte count.
- * @return the number of bytes currently stored in the queue for the specified
- * direction.
- */
-static int angie_get_queue_size(struct angie *device,
- enum angie_payload_direction direction)
-{
- struct angie_cmd *current = device->queue_start;
- int sum = 0;
-
- while (current) {
- switch (direction) {
- case PAYLOAD_DIRECTION_OUT:
- sum += current->payload_out_size + 1; /* + 1 byte for Command ID */
- break;
- case PAYLOAD_DIRECTION_IN:
- sum += current->payload_in_size;
- break;
- }
-
- current = current->next;
- }
-
- return sum;
-}
-
-/**
- * Clear the ANGIE command queue.
- *
- * @param device pointer to struct angie identifying ANGIE driver instance.
- */
-static void angie_clear_queue(struct angie *device)
-{
- struct angie_cmd *current = device->queue_start;
- struct angie_cmd *next = NULL;
-
- while (current) {
- /* Save pointer to next element */
- next = current->next;
-
- /* Free payloads: OUT payload can be freed immediately */
- free(current->payload_out);
- current->payload_out = NULL;
-
- /* IN payload MUST be freed ONLY if no other commands use the
- * payload_in_start buffer */
- if (current->free_payload_in_start) {
- free(current->payload_in_start);
- current->payload_in_start = NULL;
- current->payload_in = NULL;
- }
-
- /* Free queue element */
- free(current);
-
- /* Proceed with next element */
- current = next;
- }
-
- device->commands_in_queue = 0;
- device->queue_start = NULL;
- device->queue_end = NULL;
-}
-
-/**
- * Add a command to the ANGIE command queue.
- *
- * @param device pointer to struct angie identifying ANGIE driver instance.
- * @param angie_cmd pointer to command that shall be appended to the ANGIE
- * command queue.
- * @return on success: ERROR_OK
- * @return on failure: ERROR_FAIL
- */
-static int angie_append_queue(struct angie *device, struct angie_cmd *angie_cmd)
-{
- int newsize_out, newsize_in;
- int ret = ERROR_OK;
-
- newsize_out = angie_get_queue_size(device, PAYLOAD_DIRECTION_OUT) + 1
- + angie_cmd->payload_out_size;
-
- newsize_in = angie_get_queue_size(device, PAYLOAD_DIRECTION_IN)
- + angie_cmd->payload_in_size;
-
- /* Check if the current command can be appended to the queue */
- if (newsize_out > 64 || newsize_in > 64) {
- /* New command does not fit. Execute all commands in queue before starting
- * new queue with the current command as first entry. */
- ret = angie_execute_queued_commands(device, LIBUSB_TIMEOUT_MS);
-
- if (ret == ERROR_OK)
- ret = angie_post_process_queue(device);
-
- if (ret == ERROR_OK)
- angie_clear_queue(device);
- }
-
- if (!device->queue_start) {
- /* Queue was empty */
- device->commands_in_queue = 1;
-
- device->queue_start = angie_cmd;
- device->queue_end = angie_cmd;
- } else {
- /* There are already commands in the queue */
- device->commands_in_queue++;
-
- device->queue_end->next = angie_cmd;
- device->queue_end = angie_cmd;
- }
-
- if (ret != ERROR_OK)
- angie_clear_queue(device);
-
- return ret;
-}
-
-/**
- * Sends all queued ANGIE commands to the ANGIE for execution.
- *
- * @param device pointer to struct angie identifying ANGIE driver instance.
- * @param timeout_ms
- * @return on success: ERROR_OK
- * @return on failure: ERROR_FAIL
- */
-static int angie_execute_queued_commands(struct angie *device, int timeout_ms)
-{
- struct angie_cmd *current;
- int ret, i, index_out, index_in, count_out, count_in, transferred;
- uint8_t buffer[64];
-
- if (LOG_LEVEL_IS(LOG_LVL_DEBUG_IO))
- angie_dump_queue(device);
-
- index_out = 0;
- count_out = 0;
- count_in = 0;
-
- for (current = device->queue_start; current; current = current->next) {
- /* Add command to packet */
- buffer[index_out] = current->id;
- index_out++;
- count_out++;
-
- for (i = 0; i < current->payload_out_size; i++)
- buffer[index_out + i] = current->payload_out[i];
- index_out += current->payload_out_size;
- count_in += current->payload_in_size;
- count_out += current->payload_out_size;
- }
-
- /* Send packet to ANGIE */
- ret = jtag_libusb_bulk_write(device->usb_device_handle, device->ep_out,
- (char *)buffer, count_out, timeout_ms, &transferred);
- if (ret != ERROR_OK) {
- LOG_ERROR("Libusb bulk write queued commands failed.");
- return ret;
- }
- if (transferred != count_out) {
- LOG_ERROR("Libusb bulk write queued commands failed: transferred byte count");
- return ERROR_FAIL;
- }
-
- /* Wait for response if commands contain IN payload data */
- if (count_in > 0) {
- ret = jtag_libusb_bulk_write(device->usb_device_handle, device->ep_in,
- (char *)buffer, count_in, timeout_ms, &transferred);
- if (ret != ERROR_OK) {
- LOG_ERROR("Libusb bulk write input payload data failed");
- return ret;
- }
- if (transferred != count_in) {
- LOG_ERROR("Libusb bulk write input payload data failed: transferred byte count");
- return ERROR_FAIL;
- }
-
- /* Write back IN payload data */
- index_in = 0;
- for (current = device->queue_start; current; current = current->next) {
- for (i = 0; i < current->payload_in_size; i++) {
- current->payload_in[i] = buffer[index_in];
- index_in++;
- }
- }
- }
- return ERROR_OK;
-}
-
-/**
- * Convert an ANGIE command ID (\a id) to a human-readable string.
- *
- * @param id the ANGIE command ID.
- * @return the corresponding human-readable string.
- */
-static const char *angie_cmd_id_string(uint8_t id)
-{
- switch (id) {
- case CMD_SCAN_IN:
- return "CMD_SCAN_IN";
- case CMD_SLOW_SCAN_IN:
- return "CMD_SLOW_SCAN_IN";
- case CMD_SCAN_OUT:
- return "CMD_SCAN_OUT";
- case CMD_SLOW_SCAN_OUT:
- return "CMD_SLOW_SCAN_OUT";
- case CMD_SCAN_IO:
- return "CMD_SCAN_IO";
- case CMD_SLOW_SCAN_IO:
- return "CMD_SLOW_SCAN_IO";
- case CMD_CLOCK_TMS:
- return "CMD_CLOCK_TMS";
- case CMD_SLOW_CLOCK_TMS:
- return "CMD_SLOW_CLOCK_TMS";
- case CMD_CLOCK_TCK:
- return "CMD_CLOCK_TCK";
- case CMD_SLOW_CLOCK_TCK:
- return "CMD_SLOW_CLOCK_TCK";
- case CMD_SLEEP_US:
- return "CMD_SLEEP_US";
- case CMD_SLEEP_MS:
- return "CMD_SLEEP_MS";
- case CMD_GET_SIGNALS:
- return "CMD_GET_SIGNALS";
- case CMD_SET_SIGNALS:
- return "CMD_SET_SIGNALS";
- case CMD_CONFIGURE_TCK_FREQ:
- return "CMD_CONFIGURE_TCK_FREQ";
- case CMD_SET_LEDS:
- return "CMD_SET_LEDS";
- case CMD_TEST:
- return "CMD_TEST";
- default:
- return "CMD_UNKNOWN";
- }
-}
-
-/**
- * Print one ANGIE command to stdout.
- *
- * @param angie_cmd pointer to ANGIE command.
- */
-static void angie_dump_command(struct angie_cmd *angie_cmd)
-{
- char hex[64 * 3];
- for (int i = 0; i < angie_cmd->payload_out_size; i++)
- sprintf(hex + 3 * i, "%02" PRIX8 " ", angie_cmd->payload_out[i]);
-
- hex[3 * angie_cmd->payload_out_size - 1] = 0;
- LOG_DEBUG_IO(" %-22s | OUT size = %" PRIi8 ", bytes = %s",
- angie_cmd_id_string(angie_cmd->id), angie_cmd->payload_out_size, hex);
-
- LOG_DEBUG_IO("\n | IN size = %" PRIi8 "\n", angie_cmd->payload_in_size);
-}
-
-/**
- * Print the ANGIE command queue to stdout.
- *
- * @param device pointer to struct angie identifying ANGIE driver instance.
- */
-static void angie_dump_queue(struct angie *device)
-{
- struct angie_cmd *current;
-
- LOG_DEBUG_IO("ANGIE command queue:\n");
-
- for (current = device->queue_start; current; current = current->next)
- angie_dump_command(current);
-}
-
-/**
- * Perform JTAG scan
- *
- * Creates and appends a JTAG scan command to the ANGIE command queue.
- * A JTAG scan consists of three steps:
- * - Move to the desired SHIFT state, depending on scan type (IR/DR scan).
- * - Shift TDI data into the JTAG chain, optionally reading the TDO pin.
- * - Move to the desired end state.
- *
- * @param device pointer to struct angie identifying ANGIE driver instance.
- * @param scan_type the type of the scan (IN, OUT, IO (bidirectional)).
- * @param scan_size_bits number of bits to shift into the JTAG chain.
- * @param tdi pointer to array containing TDI data.
- * @param tdo_start pointer to first element of array where TDO data shall be
- * stored. See #angie_cmd for details.
- * @param tdo pointer to array where TDO data shall be stored
- * @param tms_count_start number of TMS state transitions to perform BEFORE
- * shifting data into the JTAG chain.
- * @param tms_sequence_start sequence of TMS state transitions that will be
- * performed BEFORE shifting data into the JTAG chain.
- * @param tms_count_end number of TMS state transitions to perform AFTER
- * shifting data into the JTAG chain.
- * @param tms_sequence_end sequence of TMS state transitions that will be
- * performed AFTER shifting data into the JTAG chain.
- * @param origin pointer to OpenOCD command that generated this scan command.
- * @param postprocess whether this command needs to be post-processed after
- * execution.
- * @return on success: ERROR_OK
- * @return on failure: ERROR_FAIL
- */
-static int angie_append_scan_cmd(struct angie *device, enum scan_type scan_type,
- int scan_size_bits, uint8_t *tdi, uint8_t *tdo_start, uint8_t *tdo,
- uint8_t tms_count_start, uint8_t tms_sequence_start, uint8_t tms_count_end,
- uint8_t tms_sequence_end, struct jtag_command *origin, bool postprocess)
-{
- struct angie_cmd *cmd = calloc(1, sizeof(struct angie_cmd));
- int ret, i, scan_size_bytes;
- uint8_t bits_last_byte;
-
- if (!cmd)
- return ERROR_FAIL;
-
- /* Check size of command. USB buffer can hold 64 bytes, 1 byte is command ID,
- * 5 bytes are setup data -> 58 remaining payload bytes for TDI data */
- if (scan_size_bits > (58 * 8)) {
- LOG_ERROR("BUG: Tried to create CMD_SCAN_IO ANGIE command with too"
- " large payload");
- free(cmd);
- return ERROR_FAIL;
- }
-
- scan_size_bytes = DIV_ROUND_UP(scan_size_bits, 8);
-
- bits_last_byte = scan_size_bits % 8;
- if (bits_last_byte == 0)
- bits_last_byte = 8;
-
- /* Allocate out_payload depending on scan type */
- switch (scan_type) {
- case SCAN_IN:
- if (device->delay_scan_in < 0)
- cmd->id = CMD_SCAN_IN;
- else
- cmd->id = CMD_SLOW_SCAN_IN;
- ret = angie_allocate_payload(cmd, 5, PAYLOAD_DIRECTION_IN);
- break;
- case SCAN_OUT:
- if (device->delay_scan_out < 0)
- cmd->id = CMD_SCAN_OUT;
- else
- cmd->id = CMD_SLOW_SCAN_OUT;
- ret = angie_allocate_payload(cmd, scan_size_bytes + 5, PAYLOAD_DIRECTION_OUT);
- break;
- case SCAN_IO:
- if (device->delay_scan_io < 0)
- cmd->id = CMD_SCAN_IO;
- else
- cmd->id = CMD_SLOW_SCAN_IO;
- ret = angie_allocate_payload(cmd, scan_size_bytes + 5, PAYLOAD_DIRECTION_OUT);
- break;
- default:
- LOG_ERROR("BUG: 'append scan cmd' encountered an unknown scan type");
- ret = ERROR_FAIL;
- break;
- }
-
- if (ret != ERROR_OK) {
- free(cmd);
- return ret;
- }
-
- /* Build payload_out that is common to all scan types */
- cmd->payload_out[0] = scan_size_bytes & 0xFF;
- cmd->payload_out[1] = bits_last_byte & 0xFF;
- cmd->payload_out[2] = ((tms_count_start & 0x0F) << 4) | (tms_count_end & 0x0F);
- cmd->payload_out[3] = tms_sequence_start;
- cmd->payload_out[4] = tms_sequence_end;
-
- /* Setup payload_out for types with OUT transfer */
- if (scan_type == SCAN_OUT || scan_type == SCAN_IO) {
- for (i = 0; i < scan_size_bytes; i++)
- cmd->payload_out[i + 5] = tdi[i];
- }
-
- /* Setup payload_in pointers for types with IN transfer */
- if (scan_type == SCAN_IN || scan_type == SCAN_IO) {
- cmd->payload_in_start = tdo_start;
- cmd->payload_in = tdo;
- cmd->payload_in_size = scan_size_bytes;
- }
-
- cmd->needs_postprocessing = postprocess;
- cmd->cmd_origin = origin;
-
- /* For scan commands, we free payload_in_start only when the command is
- * the last in a series of split commands or a stand-alone command */
- cmd->free_payload_in_start = postprocess;
-
- return angie_append_queue(device, cmd);
-}
-
-/**
- * Perform TAP state transitions
- *
- * @param device pointer to struct angie identifying ANGIE driver instance.
- * @param count defines the number of TCK clock cycles generated (up to 8).
- * @param sequence defines the TMS pin levels for each state transition. The
- * Least-Significant Bit is read first.
- * @return on success: ERROR_OK
- * @return on failure: ERROR_FAIL
- */
-static int angie_append_clock_tms_cmd(struct angie *device, uint8_t count,
- uint8_t sequence)
-{
- struct angie_cmd *cmd = calloc(1, sizeof(struct angie_cmd));
- int ret;
-
- if (!cmd) {
- LOG_ERROR("Out of memory");
- return ERROR_FAIL;
- }
-
- if (device->delay_clock_tms < 0)
- cmd->id = CMD_CLOCK_TMS;
- else
- cmd->id = CMD_SLOW_CLOCK_TMS;
-
- /* CMD_CLOCK_TMS has two OUT payload bytes and zero IN payload bytes */
- ret = angie_allocate_payload(cmd, 2, PAYLOAD_DIRECTION_OUT);
- if (ret != ERROR_OK) {
- free(cmd);
- return ret;
- }
-
- cmd->payload_out[0] = count;
- cmd->payload_out[1] = sequence;
-
- return angie_append_queue(device, cmd);
-}
-
-/**
- * Generate a defined amount of TCK clock cycles
- *
- * All other JTAG signals are left unchanged.
- *
- * @param device pointer to struct angie identifying ANGIE driver instance.
- * @param count the number of TCK clock cycles to generate.
- * @return on success: ERROR_OK
- * @return on failure: ERROR_FAIL
- */
-static int angie_append_clock_tck_cmd(struct angie *device, uint16_t count)
-{
- struct angie_cmd *cmd = calloc(1, sizeof(struct angie_cmd));
- int ret;
-
- if (!cmd) {
- LOG_ERROR("Out of memory");
- return ERROR_FAIL;
- }
-
- if (device->delay_clock_tck < 0)
- cmd->id = CMD_CLOCK_TCK;
- else
- cmd->id = CMD_SLOW_CLOCK_TCK;
-
- /* CMD_CLOCK_TCK has two OUT payload bytes and zero IN payload bytes */
- ret = angie_allocate_payload(cmd, 2, PAYLOAD_DIRECTION_OUT);
- if (ret != ERROR_OK) {
- free(cmd);
- return ret;
- }
-
- cmd->payload_out[0] = count & 0xff;
- cmd->payload_out[1] = (count >> 8) & 0xff;
-
- return angie_append_queue(device, cmd);
-}
-
-/**
- * Read JTAG signals.
- *
- * @param device pointer to struct angie identifying ANGIE driver instance.
- * @return on success: ERROR_OK
- * @return on failure: ERROR_FAIL
- */
-static int angie_append_get_signals_cmd(struct angie *device)
-{
- struct angie_cmd *cmd = calloc(1, sizeof(struct angie_cmd));
- int ret;
-
- if (!cmd) {
- LOG_ERROR("Out of memory");
- return ERROR_FAIL;
- }
-
- cmd->id = CMD_GET_SIGNALS;
- cmd->needs_postprocessing = true;
-
- /* CMD_GET_SIGNALS has two IN payload bytes */
- ret = angie_allocate_payload(cmd, 2, PAYLOAD_DIRECTION_IN);
-
- if (ret != ERROR_OK) {
- free(cmd);
- return ret;
- }
-
- return angie_append_queue(device, cmd);
-}
-
-/**
- * Arbitrarily set JTAG output signals.
- *
- * @param device pointer to struct angie identifying ANGIE driver instance.
- * @param low defines which signals will be de-asserted. Each bit corresponds
- * to a JTAG signal:
- * - SIGNAL_TDI
- * - SIGNAL_TMS
- * - SIGNAL_TCK
- * - SIGNAL_TRST
- * - SIGNAL_BRKIN
- * - SIGNAL_RESET
- * - SIGNAL_OCDSE
- * @param high defines which signals will be asserted.
- * @return on success: ERROR_OK
- * @return on failure: ERROR_FAIL
- */
-static int angie_append_set_signals_cmd(struct angie *device, uint8_t low,
- uint8_t high)
-{
- struct angie_cmd *cmd = calloc(1, sizeof(struct angie_cmd));
- int ret;
-
- if (!cmd) {
- LOG_ERROR("Out of memory");
- return ERROR_FAIL;
- }
-
- cmd->id = CMD_SET_SIGNALS;
-
- /* CMD_SET_SIGNALS has two OUT payload bytes and zero IN payload bytes */
- ret = angie_allocate_payload(cmd, 2, PAYLOAD_DIRECTION_OUT);
-
- if (ret != ERROR_OK) {
- free(cmd);
- return ret;
- }
-
- cmd->payload_out[0] = low;
- cmd->payload_out[1] = high;
-
- return angie_append_queue(device, cmd);
-}
-
-/**
- * Sleep for a pre-defined number of microseconds
- *
- * @param device pointer to struct angie identifying ANGIE driver instance.
- * @param us the number microseconds to sleep.
- * @return on success: ERROR_OK
- * @return on failure: ERROR_FAIL
- */
-static int angie_append_sleep_cmd(struct angie *device, uint32_t us)
-{
- struct angie_cmd *cmd = calloc(1, sizeof(struct angie_cmd));
- int ret;
-
- if (!cmd) {
- LOG_ERROR("Out of memory");
- return ERROR_FAIL;
- }
-
- cmd->id = CMD_SLEEP_US;
-
- /* CMD_SLEEP_US has two OUT payload bytes and zero IN payload bytes */
- ret = angie_allocate_payload(cmd, 2, PAYLOAD_DIRECTION_OUT);
-
- if (ret != ERROR_OK) {
- free(cmd);
- return ret;
- }
-
- cmd->payload_out[0] = us & 0x00ff;
- cmd->payload_out[1] = (us >> 8) & 0x00ff;
-
- return angie_append_queue(device, cmd);
-}
-
-/**
- * Set TCK delay counters
- *
- * @param device pointer to struct angie identifying ANGIE driver instance.
- * @param delay_scan_in delay count top value in jtag_slow_scan_in() function.
- * @param delay_scan_out delay count top value in jtag_slow_scan_out() function.
- * @param delay_scan_io delay count top value in jtag_slow_scan_io() function.
- * @param delay_tck delay count top value in jtag_clock_tck() function.
- * @param delay_tms delay count top value in jtag_slow_clock_tms() function.
- * @return on success: ERROR_OK
- * @return on failure: ERROR_FAIL
- */
-static int angie_append_configure_tck_cmd(struct angie *device, int delay_scan_in,
- int delay_scan_out, int delay_scan_io, int delay_tck, int delay_tms)
-{
- struct angie_cmd *cmd = calloc(1, sizeof(struct angie_cmd));
- int ret;
-
- if (!cmd) {
- LOG_ERROR("Out of memory");
- return ERROR_FAIL;
- }
-
- cmd->id = CMD_CONFIGURE_TCK_FREQ;
-
- /* CMD_CONFIGURE_TCK_FREQ has five OUT payload bytes and zero
- * IN payload bytes */
- ret = angie_allocate_payload(cmd, 5, PAYLOAD_DIRECTION_OUT);
- if (ret != ERROR_OK) {
- free(cmd);
- return ret;
- }
-
- if (delay_scan_in < 0)
- cmd->payload_out[0] = 0;
- else
- cmd->payload_out[0] = (uint8_t)delay_scan_in;
-
- if (delay_scan_out < 0)
- cmd->payload_out[1] = 0;
- else
- cmd->payload_out[1] = (uint8_t)delay_scan_out;
-
- if (delay_scan_io < 0)
- cmd->payload_out[2] = 0;
- else
- cmd->payload_out[2] = (uint8_t)delay_scan_io;
-
- if (delay_tck < 0)
- cmd->payload_out[3] = 0;
- else
- cmd->payload_out[3] = (uint8_t)delay_tck;
-
- if (delay_tms < 0)
- cmd->payload_out[4] = 0;
- else
- cmd->payload_out[4] = (uint8_t)delay_tms;
-
- return angie_append_queue(device, cmd);
-}
-
-/**
- * Test command. Used to check if the ANGIE device is ready to accept new
- * commands.
- *
- * @param device pointer to struct angie identifying ANGIE driver instance.
- * @return on success: ERROR_OK
- * @return on failure: ERROR_FAIL
- */
-static int angie_append_test_cmd(struct angie *device)
-{
- struct angie_cmd *cmd = calloc(1, sizeof(struct angie_cmd));
- int ret;
-
- if (!cmd) {
- LOG_ERROR("Out of memory");
- return ERROR_FAIL;
- }
-
- cmd->id = CMD_TEST;
-
- /* CMD_TEST has one OUT payload byte and zero IN payload bytes */
- ret = angie_allocate_payload(cmd, 1, PAYLOAD_DIRECTION_OUT);
- if (ret != ERROR_OK) {
- free(cmd);
- return ret;
- }
-
- cmd->payload_out[0] = 0xAA;
-
- return angie_append_queue(device, cmd);
-}
-
-/****************** ANGIE TCK frequency helper functions ******************/
-
-/**
- * Calculate delay values for a given TCK frequency.
- *
- * The ANGIE firmware uses five different speed values for different
- * commands. These speed values are calculated in these functions.
- *
- * The five different commands which support variable TCK frequency are
- * implemented twice in the firmware:
- * 1. Maximum possible frequency without any artificial delay
- * 2. Variable frequency with artificial linear delay loop
- *
- * To set the ANGIE to maximum frequency, it is only necessary to use the
- * corresponding command IDs. To set the ANGIE to a lower frequency, the
- * delay loop top values have to be calculated first. Then, a
- * CMD_CONFIGURE_TCK_FREQ command needs to be sent to the ANGIE device.
- *
- * The delay values are described by linear equations:
- * t = k * x + d
- * (t = period, k = constant, x = delay value, d = constant)
- *
- * Thus, the delay can be calculated as in the following equation:
- * x = (t - d) / k
- *
- * The constants in these equations have been determined and validated by
- * measuring the frequency resulting from different delay values.
- *
- * @param type for which command to calculate the delay value.
- * @param f TCK frequency for which to calculate the delay value in Hz.
- * @param delay where to store resulting delay value.
- * @return on success: ERROR_OK
- * @return on failure: ERROR_FAIL
- */
-static int angie_calculate_delay(enum angie_delay_type type, long f, int *delay)
-{
- float t_us, x, x_ceil;
-
- /* Calculate period of requested TCK frequency */
- t_us = 1000000.0 / f;
-
- switch (type) {
- case DELAY_CLOCK_TCK:
- x = (t_us - 6.0) / 4;
- break;
- case DELAY_CLOCK_TMS:
- x = (t_us - 8.5) / 4;
- break;
- case DELAY_SCAN_IN:
- x = (t_us - 8.8308) / 4;
- break;
- case DELAY_SCAN_OUT:
- x = (t_us - 10.527) / 4;
- break;
- case DELAY_SCAN_IO:
- x = (t_us - 13.132) / 4;
- break;
- default:
- return ERROR_FAIL;
- break;
- }
-
- /* Check if the delay value is negative. This happens when a frequency is
- * requested that is too high for the delay loop implementation. In this
- * case, set delay value to zero. */
- if (x < 0)
- x = 0;
-
- /* We need to convert the exact delay value to an integer. Therefore, we
- * round the exact value UP to ensure that the resulting frequency is NOT
- * higher than the requested frequency. */
- x_ceil = ceilf(x);
-
- /* Check if the value is within limits */
- if (x_ceil > 255)
- return ERROR_FAIL;
-
- *delay = (int)x_ceil;
-
- return ERROR_OK;
-}
-
-/**
- * Calculate frequency for a given delay value.
- *
- * Similar to the #angie_calculate_delay function, this function calculates the
- * TCK frequency for a given delay value by using linear equations of the form:
- * t = k * x + d
- * (t = period, k = constant, x = delay value, d = constant)
- *
- * @param type for which command to calculate the delay value.
- * @param delay value for which to calculate the resulting TCK frequency.
- * @return the resulting TCK frequency
- */
-static long angie_calculate_frequency(enum angie_delay_type type, int delay)
-{
- float t_us, f_float;
-
- if (delay > 255)
- return 0;
-
- switch (type) {
- case DELAY_CLOCK_TCK:
- if (delay < 0)
- t_us = 2.666;
- else
- t_us = (4.0 * delay) + 6.0;
- break;
- case DELAY_CLOCK_TMS:
- if (delay < 0)
- t_us = 5.666;
- else
- t_us = (4.0 * delay) + 8.5;
- break;
- case DELAY_SCAN_IN:
- if (delay < 0)
- t_us = 5.5;
- else
- t_us = (4.0 * delay) + 8.8308;
- break;
- case DELAY_SCAN_OUT:
- if (delay < 0)
- t_us = 7.0;
- else
- t_us = (4.0 * delay) + 10.527;
- break;
- case DELAY_SCAN_IO:
- if (delay < 0)
- t_us = 9.926;
- else
- t_us = (4.0 * delay) + 13.132;
- break;
- default:
- return 0;
- }
-
- f_float = 1000000.0 / t_us;
- return roundf(f_float);
-}
-
-/******************* Interface between ANGIE and OpenOCD ******************/
-
-/**
- * Sets the end state follower (see interface.h) if \a endstate is a stable
- * state.
- *
- * @param endstate the state the end state follower should be set to.
- */
-static void angie_set_end_state(enum tap_state endstate)
-{
- if (tap_is_state_stable(endstate))
- tap_set_end_state(endstate);
- else
- LOG_ERROR("BUG: %s is not a valid end state", tap_state_name(endstate));
+ entry->reply_buffer_offset = start_offset;
+ entry->cmd = cmd;
+ entry->buffer = buffer;
+ angie_read_queue_add(&device->read_queue, entry);
+ } else {
+ // built buffer won't be of later use
+ free(buffer);
+ }
+
+ return ERROR_OK;
}
/**
- * Move from the current TAP state to the current TAP end state.
+ * Return JTAG RUNTEST command size in bytes
*
- * @param device pointer to struct angie identifying ANGIE driver instance.
- * @return on success: ERROR_OK
- * @return on failure: ERROR_FAIL
+ * @param device: Angie device pointer
+ * @param cmd: RUNTEST command
+ * @return size of command in the transfer buffer in bytes
*/
-static int angie_queue_statemove(struct angie *device)
+static int angie_jtag_runtest_size(struct angie *device,
+ const struct runtest_command *cmd)
{
- uint8_t tms_sequence, tms_count;
- int ret;
-
- if (tap_get_state() == tap_get_end_state()) {
- /* Do nothing if we are already there */
- return ERROR_OK;
- }
+ int cmd_size = 0;
- tms_sequence = tap_get_tms_path(tap_get_state(), tap_get_end_state());
- tms_count = tap_get_tms_path_len(tap_get_state(), tap_get_end_state());
+ if (tap_get_state() != TAP_IDLE)
+ cmd_size += tap_get_tms_path_len(tap_get_state(), TAP_IDLE) * 2 + 1;
+ cmd_size += cmd->num_cycles * 2 + 1;
+ if (tap_get_end_state() != TAP_IDLE)
+ cmd_size += tap_get_tms_path_len(TAP_IDLE, tap_get_end_state()) * 2 + 1;
- ret = angie_append_clock_tms_cmd(device, tms_count, tms_sequence);
-
- if (ret == ERROR_OK)
- tap_set_state(tap_get_end_state());
-
- return ret;
+ return cmd_size;
}
/**
- * Perform a scan operation on a JTAG register.
+ * Execute JTAG RUNTEST command
*
- * @param device pointer to struct angie identifying ANGIE driver instance.
- * @param cmd pointer to the command that shall be executed.
- * @return on success: ERROR_OK
- * @return on failure: ERROR_FAIL
+ * @param device: Angie device pointer
+ * @param cmd: SCAN command
+ * @return ERROR_OK on success, negative error code otherwise
*/
-static int angie_queue_scan(struct angie *device, struct jtag_command *cmd)
+static int angie_jtag_execute_runtest(struct angie *device,
+ const struct runtest_command *cmd)
{
- uint32_t scan_size_bits, scan_size_bytes, bits_last_scan;
- uint32_t scans_max_payload, bytecount;
- uint8_t *tdi_buffer_start = NULL, *tdi_buffer = NULL;
- uint8_t *tdo_buffer_start = NULL, *tdo_buffer = NULL;
-
- uint8_t first_tms_count, first_tms_sequence;
- uint8_t last_tms_count, last_tms_sequence;
-
- uint8_t tms_count_pause, tms_sequence_pause;
- uint8_t tms_count_resume, tms_sequence_resume;
-
- uint8_t tms_count_start, tms_sequence_start;
- uint8_t tms_count_end, tms_sequence_end;
-
- enum scan_type type;
int ret;
+ enum tap_state saved_end_state = tap_get_end_state();
- /* Determine scan size */
- scan_size_bits = jtag_scan_size(cmd->cmd.scan);
- scan_size_bytes = DIV_ROUND_UP(scan_size_bits, 8);
-
- /* Determine scan type (IN/OUT/IO) */
- type = jtag_scan_type(cmd->cmd.scan);
+ LOG_DEBUG_IO("RUNTEST: %d cycles", cmd->num_cycles);
- /* Determine number of scan commands with maximum payload */
- scans_max_payload = scan_size_bytes / 58;
-
- /* Determine size of last shift command */
- bits_last_scan = scan_size_bits - (scans_max_payload * 58 * 8);
-
- /* Allocate TDO buffer if required */
- if (type == SCAN_IN || type == SCAN_IO) {
- tdo_buffer_start = calloc(scan_size_bytes, sizeof(uint8_t));
-
- if (!tdo_buffer_start)
- return ERROR_FAIL;
-
- tdo_buffer = tdo_buffer_start;
- }
-
- /* Fill TDI buffer if required */
- if (type == SCAN_OUT || type == SCAN_IO) {
- jtag_build_buffer(cmd->cmd.scan, &tdi_buffer_start);
- tdi_buffer = tdi_buffer_start;
+ // only do a state_move when we're not already in IDLE
+ if (tap_get_state() != TAP_IDLE) {
+ angie_set_end_state(TAP_IDLE);
+ ret = angie_state_move(device, 0);
+ if (ret != ERROR_OK)
+ return ret;
}
- /* Get TAP state transitions */
- if (cmd->cmd.scan->ir_scan) {
- angie_set_end_state(TAP_IRSHIFT);
- first_tms_count = tap_get_tms_path_len(tap_get_state(), tap_get_end_state());
- first_tms_sequence = tap_get_tms_path(tap_get_state(), tap_get_end_state());
-
- tap_set_state(TAP_IRSHIFT);
- tap_set_end_state(cmd->cmd.scan->end_state);
- last_tms_count = tap_get_tms_path_len(tap_get_state(), tap_get_end_state());
- last_tms_sequence = tap_get_tms_path(tap_get_state(), tap_get_end_state());
-
- /* TAP state transitions for split scans */
- tms_count_pause = tap_get_tms_path_len(TAP_IRSHIFT, TAP_IRPAUSE);
- tms_sequence_pause = tap_get_tms_path(TAP_IRSHIFT, TAP_IRPAUSE);
- tms_count_resume = tap_get_tms_path_len(TAP_IRPAUSE, TAP_IRSHIFT);
- tms_sequence_resume = tap_get_tms_path(TAP_IRPAUSE, TAP_IRSHIFT);
- } else {
- angie_set_end_state(TAP_DRSHIFT);
- first_tms_count = tap_get_tms_path_len(tap_get_state(), tap_get_end_state());
- first_tms_sequence = tap_get_tms_path(tap_get_state(), tap_get_end_state());
-
- tap_set_state(TAP_DRSHIFT);
- tap_set_end_state(cmd->cmd.scan->end_state);
- last_tms_count = tap_get_tms_path_len(tap_get_state(), tap_get_end_state());
- last_tms_sequence = tap_get_tms_path(tap_get_state(), tap_get_end_state());
-
- /* TAP state transitions for split scans */
- tms_count_pause = tap_get_tms_path_len(TAP_DRSHIFT, TAP_DRPAUSE);
- tms_sequence_pause = tap_get_tms_path(TAP_DRSHIFT, TAP_DRPAUSE);
- tms_count_resume = tap_get_tms_path_len(TAP_DRPAUSE, TAP_DRSHIFT);
- tms_sequence_resume = tap_get_tms_path(TAP_DRPAUSE, TAP_DRSHIFT);
+ // execute num_cycles
+ for (unsigned int i = 0; i < cmd->num_cycles; i++) {
+ ret = angie_buffer_append(device, 0, 0, 0);
+ if (ret != ERROR_OK)
+ return ret;
+ ret = angie_buffer_append(device, 1, 0, 0);
+ if (ret != ERROR_OK)
+ return ret;
}
+ ret = angie_buffer_append(device, 0, 0, 0);
+ if (ret != ERROR_OK)
+ return ret;
- /* Generate scan commands */
- bytecount = scan_size_bytes;
- while (bytecount > 0) {
- if (bytecount == scan_size_bytes) {
- /* This is the first scan */
- tms_count_start = first_tms_count;
- tms_sequence_start = first_tms_sequence;
- } else {
- /* Resume from previous scan */
- tms_count_start = tms_count_resume;
- tms_sequence_start = tms_sequence_resume;
- }
-
- if (bytecount > 58) { /* Full scan, at least one scan will follow */
- tms_count_end = tms_count_pause;
- tms_sequence_end = tms_sequence_pause;
-
- ret = angie_append_scan_cmd(device,
- type,
- 58 * 8,
- tdi_buffer,
- tdo_buffer_start,
- tdo_buffer,
- tms_count_start,
- tms_sequence_start,
- tms_count_end,
- tms_sequence_end,
- cmd,
- false);
-
- bytecount -= 58;
-
- /* Update TDI and TDO buffer pointers */
- if (tdi_buffer_start)
- tdi_buffer += 58;
- if (tdo_buffer_start)
- tdo_buffer += 58;
- } else if (bytecount == 58) { /* Full scan, no further scans */
- tms_count_end = last_tms_count;
- tms_sequence_end = last_tms_sequence;
-
- ret = angie_append_scan_cmd(device,
- type,
- 58 * 8,
- tdi_buffer,
- tdo_buffer_start,
- tdo_buffer,
- tms_count_start,
- tms_sequence_start,
- tms_count_end,
- tms_sequence_end,
- cmd,
- true);
-
- bytecount = 0;
- } else {/* Scan with less than maximum payload, no further scans */
- tms_count_end = last_tms_count;
- tms_sequence_end = last_tms_sequence;
-
- ret = angie_append_scan_cmd(device,
- type,
- bits_last_scan,
- tdi_buffer,
- tdo_buffer_start,
- tdo_buffer,
- tms_count_start,
- tms_sequence_start,
- tms_count_end,
- tms_sequence_end,
- cmd,
- true);
-
- bytecount = 0;
- }
-
- if (ret != ERROR_OK) {
- free(tdi_buffer_start);
- free(tdo_buffer_start);
+ // finish in end_state
+ angie_set_end_state(saved_end_state);
+ if (tap_get_state() != tap_get_end_state()) {
+ ret = angie_state_move(device, 0);
+ if (ret != ERROR_OK)
return ret;
- }
}
- free(tdi_buffer_start);
-
- /* Set current state to the end state requested by the command */
- tap_set_state(cmd->cmd.scan->end_state);
-
return ERROR_OK;
}
/**
- * Move the TAP into the Test Logic Reset state.
- *
- * @param device pointer to struct angie identifying ANGIE driver instance.
- * @param cmd pointer to the command that shall be executed.
- * @return on success: ERROR_OK
- * @return on failure: ERROR_FAIL
- */
-static int angie_queue_tlr_reset(struct angie *device, struct jtag_command *cmd)
-{
- int ret = angie_append_clock_tms_cmd(device, 5, 0xff);
-
- if (ret == ERROR_OK)
- tap_set_state(TAP_RESET);
-
- return ret;
-}
-
-/**
- * Run Test.
+ * Execute JTAG TMS command
+ * Clock a bunch of TMS transitions, to change the JTAG
+ * state machine.
*
- * Generate TCK clock cycles while remaining
- * in the Run-Test/Idle state.
- *
- * @param device pointer to struct angie identifying ANGIE driver instance.
- * @param cmd pointer to the command that shall be executed.
- * @return on success: ERROR_OK
- * @return on failure: ERROR_FAIL
+ * @param device: Angie device pointer
+ * @param cmd: TMS command
+ * @return ERROR_OK on success, negative error code otherwise
*/
-static int angie_queue_runtest(struct angie *device, struct jtag_command *cmd)
+static int angie_jtag_execute_tms(struct angie *device,
+ const struct tms_command *cmd)
{
- int ret;
+ unsigned int num_bits = cmd->num_bits;
+ const uint8_t *bits = cmd->bits;
- /* Only perform statemove if the TAP currently isn't in the TAP_IDLE state */
- if (tap_get_state() != TAP_IDLE) {
- angie_set_end_state(TAP_IDLE);
- angie_queue_statemove(device);
- }
-
- /* Generate the clock cycles */
- ret = angie_append_clock_tck_cmd(device, cmd->cmd.runtest->num_cycles);
- if (ret != ERROR_OK)
- return ret;
+ LOG_DEBUG_IO("TMS: %d bits", num_bits);
- /* Move to end state specified in command */
- if (cmd->cmd.runtest->end_state != tap_get_state()) {
- tap_set_end_state(cmd->cmd.runtest->end_state);
- angie_queue_statemove(device);
+ int tms = 0;
+ for (unsigned int i = 0; i < num_bits; i++) {
+ tms = ((bits[i / 8] >> (i % 8)) & 1);
+ int ret = angie_buffer_append(device, 0, tms, 0);
+ if (ret != ERROR_OK)
+ return ret;
+ ret = angie_buffer_append(device, 1, tms, 0);
+ if (ret != ERROR_OK)
+ return ret;
}
- return ERROR_OK;
+ return angie_buffer_append(device, 0, tms, 0);
}
/**
- * Execute a JTAG_RESET command
+ * Execute JTAG RESET command
+ * Control /TRST and /SYSRST pins.
+ * Perform immediate bitbang transaction.
*
- * @param device
- * @param trst indicate if trst signal is activated.
- * @param srst indicate if srst signal is activated.
- * @return on success: ERROR_OK
- * @return on failure: ERROR_FAIL
+ * @param device: Angie device pointer
+ * @param cmd: RESET command
+ * @return ERROR_OK on success, negative error code otherwise
*/
-static int angie_reset(int trst, int srst)
+static int angie_jtag_execute_reset(struct angie *device,
+ const struct reset_command *cmd)
{
- struct angie *device = angie_handle;
- uint8_t low = 0, high = 0;
+ LOG_DEBUG_IO("RESET: trst %i srst %i", cmd->trst, cmd->srst);
- if (trst) {
+ uint8_t out_value = (1 << NTRST_GPIO) | (1 << NSYSRST_GPIO);
+ if (cmd->trst == 1 ||
+ (cmd->srst && (jtag_get_reset_config() & RESET_SRST_PULLS_TRST)))
tap_set_state(TAP_RESET);
- low |= SIGNAL_TRST;
- } else {
- high |= SIGNAL_TRST;
- }
-
- if (srst)
- low |= SIGNAL_SRST;
- else
- high |= SIGNAL_SRST;
- int ret = angie_append_set_signals_cmd(device, low, high);
- if (ret != ERROR_OK)
- return ret;
-
- ret = angie_execute_queued_commands(device, LIBUSB_TIMEOUT_MS);
- if (ret != ERROR_OK)
- return ret;
+ if (cmd->trst == 1)
+ out_value &= ~(1 << NTRST_GPIO); // switch /TRST low
+ else if (cmd->trst == 0)
+ out_value |= (1 << NTRST_GPIO); // switch /TRST high
- angie_clear_queue(device);
+ if (cmd->srst == 1)
+ out_value &= ~(1 << NSYSRST_GPIO); // switch /SYSRST low
+ else if (cmd->srst == 0)
+ out_value |= (1 << NSYSRST_GPIO); // switch /SYSRST high
- return ERROR_OK;
+ return angie_buffer_append_simple(device, out_value);
}
/**
- * Move to one TAP state or several states in succession.
+ * Execute JTAG STABLECLOCKS command
+ * Issues a number of clock cycles while staying in a stable state.
+ * Because the TMS value required to stay in the RESET state is a 1, whereas
+ * the TMS value required to stay in any of the other stable states is a 0,
+ * this function checks the current stable state to decide on the value of TMS
+ * to use.
*
- * @param device pointer to struct angie identifying ANGIE driver instance.
- * @param cmd pointer to the command that shall be executed.
- * @return on success: ERROR_OK
- * @return on failure: ERROR_FAIL
+ * @param device: Angie device pointer
+ * @param cmd: STABLECLOCKS command
+ * @return ERROR_OK on success, negative error code otherwise
*/
-static int angie_queue_pathmove(struct angie *device, struct jtag_command *cmd)
+static int angie_jtag_execute_stableclocks(struct angie *device,
+ const struct stableclocks_command *cmd)
{
- int ret, state_count;
- enum tap_state *path;
- uint8_t tms_sequence;
-
- unsigned int num_states = cmd->cmd.pathmove->num_states;
- path = cmd->cmd.pathmove->path;
- state_count = 0;
-
- while (num_states > 0) {
- unsigned int batch_size;
+ int tms = (tap_get_state() == TAP_RESET ? 1 : 0);
- tms_sequence = 0;
-
- /* Determine batch size */
- if (num_states >= 8)
- batch_size = 8;
- else
- batch_size = num_states;
-
- for (unsigned int i = 0; i < batch_size; i++) {
- if (tap_state_transition(tap_get_state(), false) == path[state_count]) {
- /* Append '0' transition: clear bit 'i' in tms_sequence */
- buf_set_u32(&tms_sequence, i, 1, 0x0);
- } else if (tap_state_transition(tap_get_state(), true)
- == path[state_count]) {
- /* Append '1' transition: set bit 'i' in tms_sequence */
- buf_set_u32(&tms_sequence, i, 1, 0x1);
- } else {
- /* Invalid state transition */
- LOG_ERROR("BUG: %s -> %s isn't a valid TAP state transition",
- tap_state_name(tap_get_state()),
- tap_state_name(path[state_count]));
- return ERROR_FAIL;
- }
-
- tap_set_state(path[state_count]);
- state_count++;
- num_states--;
- }
-
- /* Append CLOCK_TMS command to ANGIE command queue */
- LOG_INFO("pathmove batch: count = %i, sequence = 0x%" PRIx8 "", batch_size, tms_sequence);
- ret = angie_append_clock_tms_cmd(angie_handle, batch_size, tms_sequence);
+ // send num_cycles clocks onto the cable
+ for (unsigned int i = 0; i < cmd->num_cycles; i++) {
+ int ret = angie_buffer_append(device, 1, tms, 0);
+ if (ret != ERROR_OK)
+ return ret;
+ ret = angie_buffer_append(device, 0, tms, 0);
if (ret != ERROR_OK)
return ret;
}
+ LOG_DEBUG_IO("clocks %i while in %s", cmd->num_cycles,
+ tap_state_name(tap_get_state()));
+
return ERROR_OK;
}
/**
- * Sleep for a specific amount of time.
+ * Execute JTAG STATEMOVE command
*
- * @param device pointer to struct angie identifying ANGIE driver instance.
- * @param cmd pointer to the command that shall be executed.
- * @return on success: ERROR_OK
- * @return on failure: ERROR_FAIL
+ * @param device: Angie device pointer
+ * @param cmd: STATEMOVE command
+ * @return ERROR_OK on success, negative error code otherwise
*/
-static int angie_queue_sleep(struct angie *device, struct jtag_command *cmd)
+static int angie_jtag_execute_statemove(struct angie *device,
+ const struct statemove_command *cmd)
{
- /* IMPORTANT! Due to the time offset in command execution introduced by
- * command queueing, this needs to be implemented in the ANGIE device */
- return angie_append_sleep_cmd(device, cmd->cmd.sleep->us);
+ LOG_DEBUG_IO("statemove end in %s", tap_state_name(cmd->end_state));
+ angie_set_end_state(cmd->end_state);
+ return angie_state_move(device, 0);
}
/**
- * Generate TCK cycles while remaining in a stable state.
+ * Execute JTAG PATHMOVE command
*
- * @param device pointer to struct angie identifying ANGIE driver instance.
- * @param cmd pointer to the command that shall be executed.
+ * @param device: Angie device pointer
+ * @param cmd: PATHMOVE command
+ * @return ERROR_OK on success, negative error code otherwise
*/
-static int angie_queue_stableclocks(struct angie *device, struct jtag_command *cmd)
+static int angie_jtag_execute_pathmove(struct angie *device,
+ const struct pathmove_command *cmd)
{
int ret;
-
- if (!tap_is_state_stable(tap_get_state())) {
- LOG_ERROR("JTAG_STABLECLOCKS: state not stable");
- return ERROR_FAIL;
- }
-
- unsigned int num_cycles = cmd->cmd.stableclocks->num_cycles;
-
- /* TMS stays either high (Test Logic Reset state) or low (all other states) */
- if (tap_get_state() == TAP_RESET)
- ret = angie_append_set_signals_cmd(device, 0, SIGNAL_TMS);
- else
- ret = angie_append_set_signals_cmd(device, SIGNAL_TMS, 0);
-
- if (ret != ERROR_OK)
- return ret;
-
- while (num_cycles > 0) {
- if (num_cycles > 0xFFFF) {
- /* ANGIE CMD_CLOCK_TCK can generate up to 0xFFFF (uint16_t) cycles */
- ret = angie_append_clock_tck_cmd(device, 0xFFFF);
- num_cycles -= 0xFFFF;
+ int num_states = cmd->num_states;
+ int tms = 0;
+
+ LOG_DEBUG_IO("pathmove: %i states, end in %s", cmd->num_states,
+ tap_state_name(cmd->path[cmd->num_states - 1]));
+
+ int state_count = 0;
+ while (num_states) {
+ if (tap_state_transition(tap_get_state(), false) == cmd->path[state_count]) {
+ tms = 0;
+ } else if (tap_state_transition(tap_get_state(), true) == cmd->path[state_count]) {
+ tms = 1;
} else {
- ret = angie_append_clock_tck_cmd(device, num_cycles);
- num_cycles = 0;
+ LOG_ERROR("BUG: %s -> %s isn't a valid TAP transition",
+ tap_state_name(tap_get_state()),
+ tap_state_name(cmd->path[state_count]));
+ return ERROR_JTAG_DEVICE_ERROR;
}
+ ret = angie_buffer_append(device, 0, tms, 0);
+ if (ret != ERROR_OK)
+ return ret;
+ ret = angie_buffer_append(device, 1, tms, 0);
if (ret != ERROR_OK)
return ret;
- }
-
- return ERROR_OK;
-}
-
-/**
- * Post-process JTAG_SCAN command
- *
- * @param angie_cmd pointer to ANGIE command that shall be processed.
- * @return on success: ERROR_OK
- * @return on failure: ERROR_FAIL
- */
-static int angie_post_process_scan(struct angie_cmd *angie_cmd)
-{
- struct jtag_command *cmd = angie_cmd->cmd_origin;
- int ret;
- switch (jtag_scan_type(cmd->cmd.scan)) {
- case SCAN_IN:
- case SCAN_IO:
- ret = jtag_read_buffer(angie_cmd->payload_in_start, cmd->cmd.scan);
- break;
- case SCAN_OUT:
- /* Nothing to do for OUT scans */
- ret = ERROR_OK;
- break;
- default:
- LOG_ERROR("BUG: angie post process scan encountered an unknown JTAG scan type");
- ret = ERROR_FAIL;
- break;
+ tap_set_state(cmd->path[state_count]);
+ state_count++;
+ num_states--;
}
+ ret = angie_buffer_append(device, 0, tms, 0);
+ if (ret != ERROR_OK)
+ return ret;
- return ret;
+ tap_set_end_state(tap_get_state());
+
+ return ERROR_OK;
}
/**
- * Perform post-processing of commands after ANGIE queue has been executed.
+ * Process command size in bytes
*
- * @param device pointer to struct angie identifying ANGIE driver instance.
- * @return on success: ERROR_OK
- * @return on failure: ERROR_FAIL
+ * @param device: Angie device pointer
+ * @param cmd: JTAG command
+ * @return command size in the transfer buffer in bytes
*/
-static int angie_post_process_queue(struct angie *device)
+static size_t angie_cmd_size(struct angie *device, const struct jtag_command *cmd)
{
- struct angie_cmd *current;
- struct jtag_command *openocd_cmd;
- int ret;
-
- current = device->queue_start;
-
- while (current) {
- openocd_cmd = current->cmd_origin;
-
- /* Check if a corresponding OpenOCD command is stored for this
- * ANGIE command */
- if (current->needs_postprocessing && openocd_cmd) {
- switch (openocd_cmd->type) {
- case JTAG_SCAN:
- ret = angie_post_process_scan(current);
- break;
- case JTAG_TLR_RESET:
- case JTAG_RUNTEST:
- case JTAG_PATHMOVE:
- case JTAG_SLEEP:
- case JTAG_STABLECLOCKS:
- /* Nothing to do for these commands */
- ret = ERROR_OK;
- break;
- default:
- ret = ERROR_FAIL;
- LOG_ERROR("BUG: angie post process queue encountered unknown JTAG "
- "command type");
- break;
- }
-
- if (ret != ERROR_OK)
- return ret;
- }
-
- current = current->next;
+ switch (cmd->type) {
+ case JTAG_SCAN:
+ return angie_jtag_scan_size(device, cmd->cmd.scan);
+ case JTAG_TMS:
+ return cmd->cmd.tms->num_bits + 2 + 1;
+ case JTAG_RESET:
+ return 1;
+ case JTAG_RUNTEST:
+ return angie_jtag_runtest_size(device, cmd->cmd.runtest);
+ case JTAG_STABLECLOCKS:
+ return cmd->cmd.stableclocks->num_cycles * 2;
+ case JTAG_TLR_RESET: // renamed from JTAG_STATEMOVE
+ return tap_get_tms_path_len(tap_get_state(),
+ cmd->cmd.statemove->end_state) * 2 + 1;
+ case JTAG_PATHMOVE:
+ return cmd->cmd.pathmove->num_states * 2 + 1;
+ case JTAG_SLEEP:
+ LOG_DEBUG_IO("sleep %" PRIu32, cmd->cmd.sleep->us);
+ return 0;
+ default:
+ LOG_ERROR("BUG: unknown JTAG command type encountered");
+ return 0;
}
-
- return ERROR_OK;
}
-/**************************** JTAG driver functions ***************************/
-
/**
- * Executes the JTAG Command Queue.
+ * Execute JTAG commands queue
*
- * This is done in three stages: First, all OpenOCD commands are processed into
- * queued ANGIE commands. Next, the ANGIE command queue is sent to the
- * ANGIE device and data received from the ANGIE device is cached. Finally,
- * the post-processing function writes back data to the corresponding OpenOCD
- * commands.
- *
- * @return on success: ERROR_OK
- * @return on failure: ERROR_FAIL
+ * @param cmd_queue to execute
+ * @return ERROR_OK on success, negative error code otherwise
*/
-static int angie_execute_queue(struct jtag_command *cmd_queue)
+static int angie_jtag_execute_queue(struct jtag_command *cmd_queue)
{
+ int retval = ERROR_OK;
struct jtag_command *cmd = cmd_queue;
- int ret;
+ struct angie *device = angie_handle;
while (cmd) {
+ retval = angie_buffer_flush_check(device, angie_cmd_size(device, cmd));
+ if (retval != ERROR_OK)
+ return retval;
+
switch (cmd->type) {
- case JTAG_SCAN:
- ret = angie_queue_scan(angie_handle, cmd);
- break;
- case JTAG_TLR_RESET:
- ret = angie_queue_tlr_reset(angie_handle, cmd);
- break;
- case JTAG_RUNTEST:
- ret = angie_queue_runtest(angie_handle, cmd);
- break;
- case JTAG_PATHMOVE:
- ret = angie_queue_pathmove(angie_handle, cmd);
- break;
- case JTAG_SLEEP:
- ret = angie_queue_sleep(angie_handle, cmd);
- break;
- case JTAG_STABLECLOCKS:
- ret = angie_queue_stableclocks(angie_handle, cmd);
- break;
- default:
- ret = ERROR_FAIL;
- LOG_ERROR("BUG: encountered unknown JTAG command type");
- break;
+ case JTAG_SCAN:
+ retval = angie_jtag_execute_scan(device, cmd->cmd.scan);
+ if (retval != ERROR_OK)
+ return retval;
+ break;
+ case JTAG_TMS:
+ retval = angie_jtag_execute_tms(device, cmd->cmd.tms);
+ if (retval != ERROR_OK)
+ return retval;
+ retval = angie_buffer_flush(device);
+ if (retval != ERROR_OK)
+ return retval;
+ break;
+ case JTAG_RESET:
+ angie_jtag_execute_reset(device, cmd->cmd.reset);
+ retval = angie_buffer_flush(device);
+ if (retval != ERROR_OK)
+ return retval;
+ break;
+ case JTAG_RUNTEST:
+ retval = angie_jtag_execute_runtest(device, cmd->cmd.runtest);
+ if (retval != ERROR_OK)
+ return retval;
+ break;
+ case JTAG_STABLECLOCKS:
+ /* this is only allowed while in a stable state. A check for a stable
+ * state was done in jtag_add_clocks()
+ */
+ retval = angie_jtag_execute_stableclocks(device, cmd->cmd.stableclocks);
+ if (retval != ERROR_OK)
+ return retval;
+ retval = angie_buffer_flush(device);
+ if (retval != ERROR_OK)
+ return retval;
+ break;
+ case JTAG_TLR_RESET: // renamed from JTAG_STATEMOVE
+ retval = angie_jtag_execute_statemove(device, cmd->cmd.statemove);
+ if (retval != ERROR_OK)
+ return retval;
+ retval = angie_buffer_flush(device);
+ if (retval != ERROR_OK)
+ return retval;
+ break;
+ case JTAG_PATHMOVE:
+ retval = angie_jtag_execute_pathmove(device, cmd->cmd.pathmove);
+ if (retval != ERROR_OK)
+ return retval;
+ retval = angie_buffer_flush(device);
+ if (retval != ERROR_OK)
+ return retval;
+ break;
+ case JTAG_SLEEP:
+ LOG_DEBUG_IO("sleep %" PRIu32, cmd->cmd.sleep->us);
+ jtag_sleep(cmd->cmd.sleep->us);
+ break;
+ default:
+ LOG_ERROR("BUG: unknown JTAG command type encountered");
+ break;
}
- if (ret != ERROR_OK)
- return ret;
-
cmd = cmd->next;
}
- if (angie_handle->commands_in_queue > 0) {
- ret = angie_execute_queued_commands(angie_handle, LIBUSB_TIMEOUT_MS);
- if (ret != ERROR_OK)
- return ret;
-
- ret = angie_post_process_queue(angie_handle);
- if (ret != ERROR_OK)
- return ret;
-
- angie_clear_queue(angie_handle);
- }
-
- return ERROR_OK;
+ return angie_buffer_flush(device);
}
/**
- * Set the TCK frequency of the ANGIE adapter.
+ * Angie quit method
*
- * @param khz desired JTAG TCK frequency.
- * @param jtag_speed where to store corresponding adapter-specific speed value.
- * @return on success: ERROR_OK
- * @return on failure: ERROR_FAIL
+ * @return ERROR_OK on success, negative error code otherwise
*/
-static int angie_khz(int khz, int *jtag_speed)
+static int angie_quit(void)
{
- int ret;
-
- if (khz == 0) {
- LOG_ERROR("RCLK not supported");
- return ERROR_FAIL;
- }
-
- /* CLOCK_TCK commands are decoupled from others. Therefore, the frequency
- * setting can be done independently from all other commands. */
- if (khz >= 375) {
- angie_handle->delay_clock_tck = -1;
- } else {
- ret = angie_calculate_delay(DELAY_CLOCK_TCK, khz * 1000,
- &angie_handle->delay_clock_tck);
- if (ret != ERROR_OK)
- return ret;
- }
-
- /* SCAN_{IN,OUT,IO} commands invoke CLOCK_TMS commands. Therefore, if the
- * requested frequency goes below the maximum frequency for SLOW_CLOCK_TMS
- * commands, all SCAN commands MUST also use the variable frequency
- * implementation! */
- if (khz >= 176) {
- angie_handle->delay_clock_tms = -1;
- angie_handle->delay_scan_in = -1;
- angie_handle->delay_scan_out = -1;
- angie_handle->delay_scan_io = -1;
- } else {
- ret = angie_calculate_delay(DELAY_CLOCK_TMS, khz * 1000,
- &angie_handle->delay_clock_tms);
- if (ret != ERROR_OK)
- return ret;
-
- ret = angie_calculate_delay(DELAY_SCAN_IN, khz * 1000,
- &angie_handle->delay_scan_in);
- if (ret != ERROR_OK)
- return ret;
-
- ret = angie_calculate_delay(DELAY_SCAN_OUT, khz * 1000,
- &angie_handle->delay_scan_out);
- if (ret != ERROR_OK)
- return ret;
-
- ret = angie_calculate_delay(DELAY_SCAN_IO, khz * 1000,
- &angie_handle->delay_scan_io);
- if (ret != ERROR_OK)
- return ret;
- }
-
- LOG_DEBUG_IO("ANGIE TCK setup: delay_tck = %i (%li Hz),",
- angie_handle->delay_clock_tck,
- angie_calculate_frequency(DELAY_CLOCK_TCK, angie_handle->delay_clock_tck));
- LOG_DEBUG_IO(" delay_tms = %i (%li Hz),",
- angie_handle->delay_clock_tms,
- angie_calculate_frequency(DELAY_CLOCK_TMS, angie_handle->delay_clock_tms));
- LOG_DEBUG_IO(" delay_scan_in = %i (%li Hz),",
- angie_handle->delay_scan_in,
- angie_calculate_frequency(DELAY_SCAN_IN, angie_handle->delay_scan_in));
- LOG_DEBUG_IO(" delay_scan_out = %i (%li Hz),",
- angie_handle->delay_scan_out,
- angie_calculate_frequency(DELAY_SCAN_OUT, angie_handle->delay_scan_out));
- LOG_DEBUG_IO(" delay_scan_io = %i (%li Hz),",
- angie_handle->delay_scan_io,
- angie_calculate_frequency(DELAY_SCAN_IO, angie_handle->delay_scan_io));
-
- /* Configure the ANGIE device with the new delay values */
- ret = angie_append_configure_tck_cmd(angie_handle,
- angie_handle->delay_scan_in,
- angie_handle->delay_scan_out,
- angie_handle->delay_scan_io,
- angie_handle->delay_clock_tck,
- angie_handle->delay_clock_tms);
+ if (!angie_handle)
+ return ERROR_OK;
+ int ret = angie_usb_close(angie_handle);
if (ret != ERROR_OK)
return ret;
- *jtag_speed = khz;
-
- return ERROR_OK;
-}
-
-/**
- * Set the TCK frequency of the ANGIE adapter.
- *
- * Because of the way the TCK frequency is set up in the ANGIE firmware,
- * there are five different speed settings. To simplify things, the
- * adapter-specific speed setting value is identical to the TCK frequency in
- * khz.
- *
- * @param speed desired adapter-specific speed value.
- * @return on success: ERROR_OK
- * @return on failure: ERROR_FAIL
- */
-static int angie_speed(int speed)
-{
- int dummy;
-
- return angie_khz(speed, &dummy);
-}
+ angie_read_queue_clean(&angie_handle->read_queue);
-/**
- * Convert adapter-specific speed value to corresponding TCK frequency in kHz.
- *
- * Because of the way the TCK frequency is set up in the ANGIE firmware,
- * there are five different speed settings. To simplify things, the
- * adapter-specific speed setting value is identical to the TCK frequency in
- * khz.
- *
- * @param speed adapter-specific speed value.
- * @param khz where to store corresponding TCK frequency in kHz.
- * @return on success: ERROR_OK
- * @return on failure: ERROR_FAIL
- */
-static int angie_speed_div(int speed, int *khz)
-{
- *khz = speed;
+ free(angie_handle);
+ angie_handle = NULL;
return ERROR_OK;
}
/**
- * Initiates the firmware download to the ANGIE adapter and prepares
- * the USB handle.
+ * Angie initialization method
*
- * @return on success: ERROR_OK
- * @return on failure: ERROR_FAIL
+ * @return ERROR_OK on success, negative error code otherwise
*/
static int angie_init(void)
{
- int ret, transferred;
- char str_manufacturer[20];
- bool download_firmware = false;
- char dummy[64];
- uint8_t input_signals, output_signals;
-
- angie_handle = calloc(1, sizeof(struct angie));
+ int ret;
+ angie_handle = calloc(1, sizeof(*angie_handle));
if (!angie_handle) {
- LOG_ERROR("Out of memory");
- return ERROR_FAIL;
+ ret = ERROR_FAIL;
+ goto exit;
}
- ret = angie_usb_open(angie_handle);
- if (ret != ERROR_OK) {
- free(angie_handle);
- angie_handle = NULL;
- return ret;
- }
+ angie_read_queue_init(&angie_handle->read_queue);
- /* Get String Descriptor to determine if firmware needs to be loaded */
- ret = libusb_get_string_descriptor_ascii(angie_handle->usb_device_handle, 1, (unsigned char *)str_manufacturer, 20);
- if (ret < 0) {
- /* Could not get descriptor -> Unconfigured or original Keil firmware */
- download_firmware = true;
- } else {
- /* We got a String Descriptor, check if it is the correct one */
- if (strncmp(str_manufacturer, "NanoXplore, SAS.", 16) != 0)
- download_firmware = true;
- }
+ ret = angie_usb_open(angie_handle);
+ if (ret != ERROR_OK)
+ goto exit;
- if (download_firmware) {
+ if (angie_is_firmware_needed(angie_handle)) {
LOG_INFO("Loading ANGIE firmware. This is reversible by power-cycling ANGIE device.");
- if (libusb_claim_interface(angie_handle->usb_device_handle, 0) != LIBUSB_SUCCESS) {
- LOG_ERROR("Could not claim interface 0");
- return ERROR_FAIL;
+
+ ret = libusb_claim_interface(angie_handle->usbdev, 0);
+ if (ret != LIBUSB_SUCCESS) {
+ LOG_ERROR("Failed to claim interface 0");
+ ret = ERROR_FAIL;
+ goto exit;
}
+
ret = angie_load_firmware_and_renumerate(angie_handle,
- ANGIE_FIRMWARE_FILE, ANGIE_RENUMERATION_DELAY_US);
+ ANGIE_FIRMWARE_FILE,
+ ANGIE_RENUMERATION_DELAY_US);
if (ret != ERROR_OK) {
LOG_ERROR("Could not download firmware and re-numerate ANGIE");
angie_quit();
return ret;
}
+
ret = angie_load_bitstream(angie_handle, ANGIE_BITSTREAM_FILE);
if (ret != ERROR_OK) {
LOG_ERROR("Could not download bitstream");
angie_quit();
return ret;
}
- if (libusb_release_interface(angie_handle->usb_device_handle, 0) != LIBUSB_SUCCESS) {
- LOG_ERROR("Fail release interface 0");
- return ERROR_FAIL;
- }
- if (libusb_claim_interface(angie_handle->usb_device_handle, 1) != LIBUSB_SUCCESS) {
- LOG_ERROR("Could not claim interface 1");
- return ERROR_FAIL;
- }
- /* Configure io extender 23: all input */
- ret = angie_io_extender_config(angie_handle, 0x23, 0xFF);
- if (ret != ERROR_OK) {
- LOG_ERROR("Could not configure io extender 23");
- return ret;
- }
- if (libusb_release_interface(angie_handle->usb_device_handle, 1) != LIBUSB_SUCCESS) {
- LOG_ERROR("Fail release interface 1");
- return ERROR_FAIL;
- }
} else {
LOG_INFO("ANGIE device is already running ANGIE firmware");
}
- /* Get ANGIE USB IN/OUT endpoints and claim the interface 0 */
- ret = jtag_libusb_choose_interface(angie_handle->usb_device_handle,
- &angie_handle->ep_in, &angie_handle->ep_out, 0xFF, 0, 0, -1);
- if (ret != ERROR_OK) {
- LOG_ERROR("Choose and claim interface failed");
- angie_quit();
- return ret;
- }
-
- /* Initialize ANGIE command queue */
- angie_clear_queue(angie_handle);
-
- /* Issue one test command with short timeout */
- ret = angie_append_test_cmd(angie_handle);
- if (ret != ERROR_OK) {
- LOG_ERROR("Append test command failed.");
- angie_quit();
- return ret;
- }
+ return ERROR_OK;
+exit:
+ angie_quit();
+ return ret;
+}
- ret = angie_execute_queued_commands(angie_handle, 200);
- if (ret != ERROR_OK) {
- /* Sending test command failed. The ANGIE device may be forever waiting for
- * the host to fetch an USB Bulk IN packet (e. g. OpenOCD crashed or was
- * shut down by the user via Ctrl-C. Try to retrieve this Bulk IN packet. */
+/**
+ * Angie set speed method
+ *
+ * @return ERROR_OK on success, negative error code otherwise
+ */
+static int angie_speed(int divisor)
+{
+ int baud = (divisor == 0) ? 3000000 :
+ (divisor == 1) ? 2000000 :
+ 3000000 / divisor;
+ LOG_DEBUG("angie speed(%d) rate %d bits/sec", divisor, baud);
- ret = jtag_libusb_bulk_write(angie_handle->usb_device_handle, angie_handle->ep_in,
- dummy, 64, 200, &transferred);
+ return ERROR_OK;
+}
- if (ret != ERROR_OK || transferred == 0) {
- /* Bulk IN transfer failed -> unrecoverable error condition */
- LOG_ERROR("Cannot communicate with ANGIE device. Disconnect ANGIE from "
- "the USB port and re-connect, then re-run OpenOCD");
- angie_quit();
- return ERROR_FAIL;
- }
- /* Successfully received Bulk IN packet -> continue */
- LOG_INFO("Recovered from lost Bulk IN packet");
+/**
+ * Angie set khz method
+ *
+ * @param khz
+ * @param divisor returned to caller
+ * @return ERROR_OK on success, negative error code otherwise
+ */
+static int angie_khz(int khz, int *divisor)
+{
+ if (khz == 0) {
+ LOG_DEBUG("RCLK not supported");
+ return ERROR_FAIL;
}
- angie_clear_queue(angie_handle);
-
- /* Execute get signals command */
- ret = angie_append_get_signals_cmd(angie_handle);
- if (ret != ERROR_OK) {
- LOG_ERROR("Append get signals command failed");
- angie_quit();
- return ret;
- }
- ret = angie_execute_queued_commands(angie_handle, 200);
- if (ret != ERROR_OK) {
- LOG_ERROR("Execute get signals command failed");
- angie_quit();
- return ret;
+ // Calculate frequency divisor.
+ if (khz > 2500) {
+ *divisor = 0; // Special case: 3 MHz
+ } else if (khz > 1700) {
+ *divisor = 1; // Special case: 2 MHz
+ } else {
+ *divisor = (2 * 3000 / khz + 1) / 2;
+ if (*divisor > 0x3FFF)
+ *divisor = 0x3FFF;
}
-
- /* Post-process the single CMD_GET_SIGNALS command */
- input_signals = angie_handle->queue_start->payload_in[0];
- output_signals = angie_handle->queue_start->payload_in[1];
- angie_dump_signal_states(input_signals, output_signals);
-
- angie_clear_queue(angie_handle);
-
return ERROR_OK;
}
/**
- * Closes the USB handle for the ANGIE device.
+ * Angie set speed div
*
- * @return on success: ERROR_OK
- * @return on failure: ERROR_FAIL
+ * @param divisor
+ * @param khz returned to caller
+ * @return ERROR_OK on success, negative error code otherwise
*/
-static int angie_quit(void)
+static int angie_speed_div(int divisor, int *khz)
{
- int ret = angie_usb_close(angie_handle);
- free(angie_handle);
- angie_handle = NULL;
-
- return ret;
+ // Maximum 3 Mbaud for bit bang mode
+ if (divisor == 0)
+ *khz = 30000;
+ else if (divisor == 1)
+ *khz = 20000;
+ else
+ *khz = 30000 / divisor;
+ return ERROR_OK;
}
static struct jtag_interface angie_interface = {
- .execute_queue = angie_execute_queue,
+ .supported = DEBUG_CAP_TMS_SEQ,
+ .execute_queue = angie_jtag_execute_queue,
};
struct adapter_driver angie_adapter_driver = {
@@ -2393,7 +1368,6 @@ struct adapter_driver angie_adapter_driver = {
.init = angie_init,
.quit = angie_quit,
- .reset = angie_reset,
.speed = angie_speed,
.khz = angie_khz,
.speed_div = angie_speed_div,
diff --git a/src/jtag/drivers/angie/README b/src/jtag/drivers/angie/README
deleted file mode 100644
index c727154c48..0000000000
--- a/src/jtag/drivers/angie/README
+++ /dev/null
@@ -1,3 +0,0 @@
-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.
diff --git a/src/jtag/drivers/angie/angie_bitstream.bit b/src/jtag/drivers/angie/angie_bitstream.bit
index 7b3a88f7c8..71fbb85e60 100644
Binary files a/src/jtag/drivers/angie/angie_bitstream.bit and b/src/jtag/drivers/angie/angie_bitstream.bit differ
diff --git a/src/jtag/drivers/angie/angie_firmware.bin b/src/jtag/drivers/angie/angie_firmware.bin
index 68486ef8f0..ecf2cfd513 100644
Binary files a/src/jtag/drivers/angie/angie_firmware.bin and b/src/jtag/drivers/angie/angie_firmware.bin differ
diff --git a/src/jtag/drivers/angie/include/msgtypes.h b/src/jtag/drivers/angie/include/msgtypes.h
deleted file mode 100644
index fb045e98c3..0000000000
--- a/src/jtag/drivers/angie/include/msgtypes.h
+++ /dev/null
@@ -1,172 +0,0 @@
-/* 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. *
- *
- *
-*****************************************************************************/
-
-/**
- * @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
diff --git a/src/jtag/drivers/arm-jtag-ew.c b/src/jtag/drivers/arm-jtag-ew.c
index 9d8c592edb..5c0e2ea948 100644
--- a/src/jtag/drivers/arm-jtag-ew.c
+++ b/src/jtag/drivers/arm-jtag-ew.c
@@ -94,69 +94,69 @@ static int armjtagew_execute_queue(struct jtag_command *cmd_queue)
while (cmd) {
switch (cmd->type) {
- case JTAG_RUNTEST:
- LOG_DEBUG_IO("runtest %u cycles, end in %i",
- cmd->cmd.runtest->num_cycles,
- cmd->cmd.runtest->end_state);
+ case JTAG_RUNTEST:
+ LOG_DEBUG_IO("runtest %u cycles, end in %i",
+ cmd->cmd.runtest->num_cycles,
+ cmd->cmd.runtest->end_state);
- armjtagew_end_state(cmd->cmd.runtest->end_state);
- armjtagew_runtest(cmd->cmd.runtest->num_cycles);
- break;
+ armjtagew_end_state(cmd->cmd.runtest->end_state);
+ armjtagew_runtest(cmd->cmd.runtest->num_cycles);
+ break;
- case JTAG_TLR_RESET:
- LOG_DEBUG_IO("statemove end in %i", cmd->cmd.statemove->end_state);
+ case JTAG_TLR_RESET:
+ LOG_DEBUG_IO("statemove end in %i", cmd->cmd.statemove->end_state);
- armjtagew_end_state(cmd->cmd.statemove->end_state);
- armjtagew_state_move();
- break;
+ armjtagew_end_state(cmd->cmd.statemove->end_state);
+ armjtagew_state_move();
+ break;
- case JTAG_PATHMOVE:
- LOG_DEBUG_IO("pathmove: %u states, end in %i",
- cmd->cmd.pathmove->num_states,
- cmd->cmd.pathmove->path[cmd->cmd.pathmove->num_states - 1]);
+ case JTAG_PATHMOVE:
+ LOG_DEBUG_IO("pathmove: %u states, end in %i",
+ cmd->cmd.pathmove->num_states,
+ cmd->cmd.pathmove->path[cmd->cmd.pathmove->num_states - 1]);
- armjtagew_path_move(cmd->cmd.pathmove->num_states,
- cmd->cmd.pathmove->path);
- break;
+ armjtagew_path_move(cmd->cmd.pathmove->num_states,
+ cmd->cmd.pathmove->path);
+ break;
- case JTAG_SCAN:
- LOG_DEBUG_IO("scan end in %i", cmd->cmd.scan->end_state);
+ case JTAG_SCAN:
+ LOG_DEBUG_IO("scan end in %i", cmd->cmd.scan->end_state);
- armjtagew_end_state(cmd->cmd.scan->end_state);
+ armjtagew_end_state(cmd->cmd.scan->end_state);
- scan_size = jtag_build_buffer(cmd->cmd.scan, &buffer);
- LOG_DEBUG_IO("scan input, length = %d", scan_size);
+ scan_size = jtag_build_buffer(cmd->cmd.scan, &buffer);
+ LOG_DEBUG_IO("scan input, length = %d", scan_size);
#ifdef _DEBUG_USB_COMMS_
- armjtagew_debug_buffer(buffer, (scan_size + 7) / 8);
+ armjtagew_debug_buffer(buffer, (scan_size + 7) / 8);
#endif
- type = jtag_scan_type(cmd->cmd.scan);
- armjtagew_scan(cmd->cmd.scan->ir_scan,
- type, buffer,
- scan_size, cmd->cmd.scan);
- break;
-
- case JTAG_RESET:
- LOG_DEBUG_IO("reset trst: %i srst %i",
- cmd->cmd.reset->trst,
- cmd->cmd.reset->srst);
-
- armjtagew_tap_execute();
-
- if (cmd->cmd.reset->trst == 1)
- tap_set_state(TAP_RESET);
- armjtagew_reset(cmd->cmd.reset->trst, cmd->cmd.reset->srst);
- break;
-
- case JTAG_SLEEP:
- LOG_DEBUG_IO("sleep %" PRIu32, cmd->cmd.sleep->us);
- armjtagew_tap_execute();
- jtag_sleep(cmd->cmd.sleep->us);
- break;
-
- default:
- LOG_ERROR("BUG: unknown JTAG command type encountered");
- exit(-1);
+ type = jtag_scan_type(cmd->cmd.scan);
+ armjtagew_scan(cmd->cmd.scan->ir_scan,
+ type, buffer,
+ scan_size, cmd->cmd.scan);
+ break;
+
+ case JTAG_RESET:
+ LOG_DEBUG_IO("reset trst: %i srst %i",
+ cmd->cmd.reset->trst,
+ cmd->cmd.reset->srst);
+
+ armjtagew_tap_execute();
+
+ if (cmd->cmd.reset->trst == 1)
+ tap_set_state(TAP_RESET);
+ armjtagew_reset(cmd->cmd.reset->trst, cmd->cmd.reset->srst);
+ break;
+
+ case JTAG_SLEEP:
+ LOG_DEBUG_IO("sleep %" PRIu32, cmd->cmd.sleep->us);
+ armjtagew_tap_execute();
+ jtag_sleep(cmd->cmd.sleep->us);
+ break;
+
+ default:
+ LOG_ERROR("BUG: unknown JTAG command type encountered");
+ exit(-1);
}
cmd = cmd->next;
}
diff --git a/src/jtag/drivers/bitbang.c b/src/jtag/drivers/bitbang.c
index c2e763ddb3..ebf38c7fa6 100644
--- a/src/jtag/drivers/bitbang.c
+++ b/src/jtag/drivers/bitbang.c
@@ -236,14 +236,14 @@ static int bitbang_scan(bool ir_scan, enum scan_type type, uint8_t *buffer,
buffered++;
} else {
switch (bitbang_interface->read()) {
- case BB_LOW:
- buffer[bytec] &= ~bcval;
- break;
- case BB_HIGH:
- buffer[bytec] |= bcval;
- break;
- default:
- return ERROR_FAIL;
+ case BB_LOW:
+ buffer[bytec] &= ~bcval;
+ break;
+ case BB_HIGH:
+ buffer[bytec] |= bcval;
+ break;
+ default:
+ return ERROR_FAIL;
}
}
}
@@ -256,14 +256,14 @@ static int bitbang_scan(bool ir_scan, enum scan_type type, uint8_t *buffer,
bit_cnt == scan_size - 1)) {
for (unsigned int i = bit_cnt + 1 - buffered; i <= bit_cnt; i++) {
switch (bitbang_interface->read_sample()) {
- case BB_LOW:
- buffer[i/8] &= ~(1 << (i % 8));
- break;
- case BB_HIGH:
- buffer[i/8] |= 1 << (i % 8);
- break;
- default:
- return ERROR_FAIL;
+ case BB_LOW:
+ buffer[i / 8] &= ~(1 << (i % 8));
+ break;
+ case BB_HIGH:
+ buffer[i / 8] |= 1 << (i % 8);
+ break;
+ default:
+ return ERROR_FAIL;
}
}
buffered = 0;
@@ -315,64 +315,64 @@ int bitbang_execute_queue(struct jtag_command *cmd_queue)
while (cmd) {
switch (cmd->type) {
- case JTAG_RUNTEST:
- LOG_DEBUG_IO("runtest %u cycles, end in %s",
- cmd->cmd.runtest->num_cycles,
- tap_state_name(cmd->cmd.runtest->end_state));
- bitbang_end_state(cmd->cmd.runtest->end_state);
- if (bitbang_runtest(cmd->cmd.runtest->num_cycles) != ERROR_OK)
- return ERROR_FAIL;
- break;
-
- case JTAG_STABLECLOCKS:
- /* this is only allowed while in a stable state. A check for a stable
- * state was done in jtag_add_clocks()
- */
- if (bitbang_stableclocks(cmd->cmd.stableclocks->num_cycles) != ERROR_OK)
- return ERROR_FAIL;
- break;
-
- case JTAG_TLR_RESET:
- LOG_DEBUG_IO("statemove end in %s",
- tap_state_name(cmd->cmd.statemove->end_state));
- bitbang_end_state(cmd->cmd.statemove->end_state);
- if (bitbang_state_move(0) != ERROR_OK)
- return ERROR_FAIL;
- break;
- case JTAG_PATHMOVE:
- LOG_DEBUG_IO("pathmove: %u states, end in %s",
- cmd->cmd.pathmove->num_states,
- tap_state_name(cmd->cmd.pathmove->path[cmd->cmd.pathmove->num_states - 1]));
- if (bitbang_path_move(cmd->cmd.pathmove) != ERROR_OK)
- return ERROR_FAIL;
- break;
- case JTAG_SCAN:
- bitbang_end_state(cmd->cmd.scan->end_state);
- scan_size = jtag_build_buffer(cmd->cmd.scan, &buffer);
- LOG_DEBUG_IO("%s scan %d bits; end in %s",
- (cmd->cmd.scan->ir_scan) ? "IR" : "DR",
- scan_size,
- tap_state_name(cmd->cmd.scan->end_state));
- type = jtag_scan_type(cmd->cmd.scan);
- if (bitbang_scan(cmd->cmd.scan->ir_scan, type, buffer,
- scan_size) != ERROR_OK)
- return ERROR_FAIL;
- if (jtag_read_buffer(buffer, cmd->cmd.scan) != ERROR_OK)
- retval = ERROR_JTAG_QUEUE_FAILED;
- free(buffer);
- break;
- case JTAG_SLEEP:
- LOG_DEBUG_IO("sleep %" PRIu32, cmd->cmd.sleep->us);
- if (bitbang_interface->flush && (bitbang_interface->flush() != ERROR_OK))
- return ERROR_FAIL;
- bitbang_sleep(cmd->cmd.sleep->us);
- break;
- case JTAG_TMS:
- retval = bitbang_execute_tms(cmd);
- break;
- default:
- LOG_ERROR("BUG: unknown JTAG command type encountered");
- exit(-1);
+ case JTAG_RUNTEST:
+ LOG_DEBUG_IO("runtest %u cycles, end in %s",
+ cmd->cmd.runtest->num_cycles,
+ tap_state_name(cmd->cmd.runtest->end_state));
+ bitbang_end_state(cmd->cmd.runtest->end_state);
+ if (bitbang_runtest(cmd->cmd.runtest->num_cycles) != ERROR_OK)
+ return ERROR_FAIL;
+ break;
+
+ case JTAG_STABLECLOCKS:
+ /* this is only allowed while in a stable state. A check for a stable
+ * state was done in jtag_add_clocks()
+ */
+ if (bitbang_stableclocks(cmd->cmd.stableclocks->num_cycles) != ERROR_OK)
+ return ERROR_FAIL;
+ break;
+
+ case JTAG_TLR_RESET:
+ LOG_DEBUG_IO("statemove end in %s",
+ tap_state_name(cmd->cmd.statemove->end_state));
+ bitbang_end_state(cmd->cmd.statemove->end_state);
+ if (bitbang_state_move(0) != ERROR_OK)
+ return ERROR_FAIL;
+ break;
+ case JTAG_PATHMOVE:
+ LOG_DEBUG_IO("pathmove: %u states, end in %s",
+ cmd->cmd.pathmove->num_states,
+ tap_state_name(cmd->cmd.pathmove->path[cmd->cmd.pathmove->num_states - 1]));
+ if (bitbang_path_move(cmd->cmd.pathmove) != ERROR_OK)
+ return ERROR_FAIL;
+ break;
+ case JTAG_SCAN:
+ bitbang_end_state(cmd->cmd.scan->end_state);
+ scan_size = jtag_build_buffer(cmd->cmd.scan, &buffer);
+ LOG_DEBUG_IO("%s scan %d bits; end in %s",
+ (cmd->cmd.scan->ir_scan) ? "IR" : "DR",
+ scan_size,
+ tap_state_name(cmd->cmd.scan->end_state));
+ type = jtag_scan_type(cmd->cmd.scan);
+ if (bitbang_scan(cmd->cmd.scan->ir_scan, type, buffer,
+ scan_size) != ERROR_OK)
+ return ERROR_FAIL;
+ if (jtag_read_buffer(buffer, cmd->cmd.scan) != ERROR_OK)
+ retval = ERROR_JTAG_QUEUE_FAILED;
+ free(buffer);
+ break;
+ case JTAG_SLEEP:
+ LOG_DEBUG_IO("sleep %" PRIu32, cmd->cmd.sleep->us);
+ if (bitbang_interface->flush && (bitbang_interface->flush() != ERROR_OK))
+ return ERROR_FAIL;
+ bitbang_sleep(cmd->cmd.sleep->us);
+ break;
+ case JTAG_TMS:
+ retval = bitbang_execute_tms(cmd);
+ break;
+ default:
+ LOG_ERROR("BUG: unknown JTAG command type encountered");
+ exit(-1);
}
cmd = cmd->next;
}
diff --git a/src/jtag/drivers/buspirate.c b/src/jtag/drivers/buspirate.c
index 4283616adc..7eab94bd0a 100644
--- a/src/jtag/drivers/buspirate.c
+++ b/src/jtag/drivers/buspirate.c
@@ -941,24 +941,24 @@ static void buspirate_swd_set_feature(int fd, char feat, char action)
uint8_t tmp[1];
switch (feat) {
- case FEATURE_TRST:
- LOG_DEBUG("Buspirate TRST feature not available in SWD mode");
- return;
- case FEATURE_LED:
- LOG_ERROR("Buspirate LED feature not available in SWD mode");
- return;
- case FEATURE_SRST:
- swd_features = (action == ACTION_ENABLE) ? swd_features | 0x02 : swd_features & 0x0D;
- break;
- case FEATURE_PULLUP:
- swd_features = (action == ACTION_ENABLE) ? swd_features | 0x04 : swd_features & 0x0B;
- break;
- case FEATURE_VREG:
- swd_features = (action == ACTION_ENABLE) ? swd_features | 0x08 : swd_features & 0x07;
- break;
- default:
- LOG_DEBUG("Buspirate unknown feature %d", feat);
- return;
+ case FEATURE_TRST:
+ LOG_DEBUG("Buspirate TRST feature not available in SWD mode");
+ return;
+ case FEATURE_LED:
+ LOG_ERROR("Buspirate LED feature not available in SWD mode");
+ return;
+ case FEATURE_SRST:
+ swd_features = (action == ACTION_ENABLE) ? swd_features | 0x02 : swd_features & 0x0D;
+ break;
+ case FEATURE_PULLUP:
+ swd_features = (action == ACTION_ENABLE) ? swd_features | 0x04 : swd_features & 0x0B;
+ break;
+ case FEATURE_VREG:
+ swd_features = (action == ACTION_ENABLE) ? swd_features | 0x08 : swd_features & 0x07;
+ break;
+ default:
+ LOG_DEBUG("Buspirate unknown feature %d", feat);
+ return;
}
tmp[0] = CMD_RAW_PERIPH | swd_features;
diff --git a/src/jtag/drivers/ch347.c b/src/jtag/drivers/ch347.c
new file mode 100644
index 0000000000..c031ceece2
--- /dev/null
+++ b/src/jtag/drivers/ch347.c
@@ -0,0 +1,2442 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+/***************************************************************************
+ * Driver for CH347-JTAG interface V1.1 *
+ * *
+ * Copyright (C) 2022 by oidcat. *
+ * Author: oidcatiot@163.com *
+ * *
+ * Enhancements by EasyDevKits - info@easydevkits.com *
+ * *
+ * CH347 is a high-speed USB bus converter chip that provides UART, I2C *
+ * and SPI synchronous serial ports and JTAG interface through USB bus. *
+ * *
+ * The JTAG interface by CH347 can supports transmission frequency *
+ * configuration up to 60MHz. *
+ * *
+ * The USB2.0 to JTAG scheme based on CH347 can be used to build *
+ * customized USB high-speed JTAG debugger and other products. *
+ * *
+ * _____________ *
+ * | |____JTAG/SWD (TDO,TDI,TMS,TCK,TRST) *
+ * USB__| CH347T/F | *
+ * |_____________|____UART(TXD1,RXD1,RTS1,CTS1,DTR1) *
+ * ______|______ *
+ * | | *
+ * | 8 MHz XTAL | *
+ * |_____________| *
+ * *
+ * This CH347 driver is only tested for the CH347T chip in mode 3. *
+ * The CH347 datasheet mention another chip the CH347F which was not *
+ * available for testing. *
+ * *
+ * The datasheet for the wch-ic.com's CH347 part is here: *
+ * https://www.wch-ic.com/downloads/CH347DS1_PDF.html *
+ * *
+ ***************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#if IS_CYGWIN == 1
+#include "windows.h"
+#undef LOG_ERROR
+#endif
+
+// project specific includes
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include "libusb_helper.h"
+
+// system includes
+#include
+#include
+#include
+#include
+#include
+
+#define TDI_H BIT(4)
+#define TDI_L 0
+#define TMS_H BIT(1)
+#define TMS_L 0
+#define TCK_H BIT(0)
+#define TCK_L 0
+#define TRST_H BIT(5)
+#define TRST_L 0
+#define LED_ON 1
+#define LED_OFF 0
+#define GPIO_CNT 8 // the CH347 has 8 GPIO's
+/* mask which GPIO's are available in mode 3 of CH347T only GPIO3 (Pin11 / SCL), GPIO4 (Pin15 / ACT),
+ GPIO5 (Pin9 / TRST) and GPIO6 (Pin2 / CTS1) are possible. Tested only with CH347T not CH347F chip.
+ pin numbers are for CH347T */
+#define USEABLE_GPIOS 0x78
+/* For GPIO command: always set bits 7 and 6 for GPIO enable
+ bits 5 and 4 for pin direction output bit 3 is the data bit */
+#define GPIO_SET_L (BIT(4) | BIT(5) | BIT(6) | BIT(7)) // value for setting a GPIO to low
+#define GPIO_SET_H (BIT(3) | BIT(4) | BIT(5) | BIT(6) | BIT(7)) // value for setting a GPIO to high
+
+#define VENDOR_VERSION 0x5F // for getting the chip version
+
+// maybe the hardware of the CH347 chip can capture only this amount of TDO bits
+#define HW_TDO_BUF_SIZE 4096
+// Don't send more than this amount of bytes via libusb in one packet. Also that is the limit for LARGER_PACK mode.
+#define LARGER_PACK_MAX_SIZE 51200
+// The data length contained in each command packet during USB high-speed operation
+#define UCMDPKT_DATA_MAX_BYTES_USBHS 507
+#define USBC_PACKET_USBHS 512 // Maximum data length per packet at USB high speed
+#define CH347_CMD_HEADER 3 // Protocol header length (1 byte command type + 2 bytes data length)
+#define CH347_CMD_INIT_READ_LEN 1 // for JTAG_INIT/SWD_INIT we have only one data byte
+// if we send 9 in the init command we get the STANDARD mode or LARGER_PACK mode flag
+#define CH347_CMD_INIT_GET_MODE_CLOCK_INDEX_VALUE 9
+// No more bits are allowed per CH347_CMD_JTAG_BIT_OP command; this should be dividable by 8
+#define MAX_BITS_PER_BIT_OP 248
+
+/* Protocol transmission format: CMD (1 byte) + Length (2 bytes) + Data
+ Parameter acquisition, used to obtain firmware version, JTAG interface related parameters, etc */
+#define CH347_CMD_INFO_RD 0xCA
+#define CH347_CMD_GPIO 0xCC // GPIO Command
+#define CH347_CMD_JTAG_INIT 0xD0 // JTAG Interface initialization command
+#define CH347_CMD_JTAG_BIT_OP 0xD1 // JTAG interface pin bit control command
+#define CH347_CMD_JTAG_BIT_OP_RD 0xD2 // JTAG interface pin bit control and read commands
+#define CH347_CMD_JTAG_DATA_SHIFT 0xD3 // JTAG interface data shift command
+#define CH347_CMD_JTAG_DATA_SHIFT_RD 0xD4 // JTAG interface data shift and read command
+// for a single command these amount of data can be read at max
+#define CH347_SINGLE_CMD_MAX_READ MAX(GPIO_CNT, CH347_CMD_INIT_READ_LEN)
+
+// for SWD
+#define CH347_CMD_SWD_INIT 0xE5 // SWD Interface Initialization Command
+#define CH347_CMD_SWD 0xE8 // SWD Command group header
+#define CH347_CMD_SWD_REG_W 0xA0 // SWD Interface write reg
+#define CH347_CMD_SWD_SEQ_W 0xA1 // SWD Interface write spec seq
+#define CH347_CMD_SWD_REG_R 0xA2 // SWD Interface read reg
+#define CH347_MAX_PROCESSING_US 7000 // max time in us for packet processing
+ // USB hosts disconnect the adapter if SWD processing takes more!
+#define CH347_MAX_SEND_BUF USBC_PACKET_USBHS
+#define CH347_MAX_RECV_BUF USBC_PACKET_USBHS
+#define CH347_MAX_CMD_BUF 128
+#define CH347_SWD_CLOCK_MAX 5000
+#define CH347_SWD_CLOCK_BASE 1000
+// limited by the longest sequence processing time
+#define CH347_SWD_CLOCK_MAX_DIVISOR (CH347_MAX_PROCESSING_US / swd_seq_dormant_to_swd_len)
+
+#define CH347_EPOUT 0x06u // the usb endpoint number for writing
+#define CH347_EPIN 0x86u // the usb endpoint number for reading
+#define CH347T_MPHSI_INTERFACE 2 // the CH347T JTAG interface is number 2
+#define CH347F_MPHSI_INTERFACE 4 // the CH347F JTAG interface is number 4
+#define USB_WRITE_TIMEOUT 500 // write timeout in milliseconds
+#define USB_READ_TIMEOUT 500 // read timeout in milliseconds
+// BCD version for devices that can use bytewise mode below this version only bitwise mode can be used
+#define BYTEWISE_MODE_VERSION 0x241
+/* if the configuration is not setting the vendor id / product id we search for vendor id 1a86
+ and product id's 0x55dd (CH347T chip in mode 3), 0x55de (CH347F chip) and 0x55e7 (other chip) */
+#define DEFAULT_VENDOR_ID 0x1a86
+#define DEFAULT_CH347T_PRODUCT_ID 0x55dd
+#define DEFAULT_CH347F_PRODUCT_ID 0x55de
+#define DEFAULT_OTHER_PRODUCT_ID 0x55e7
+
+/* There are 3 different CH347 variants. The datasheet mentions the CH347T chip which has the product id 0x55dd
+ as default when it's configured to mode 3. The CH347F chip is also mentioned in the datasheet and has the
+ default product id 0x55de. The 3rd variant is not mentioned in a datasheet but was found here
+ https://github.com/WCHSoftGroup/ch347
+ The code from WCHSoftGroup is also searching for this product id */
+enum ch347_variant {
+ CH347T = 0, // The CH347T chip
+ CH347F = 1, // The CH347F chip
+ OTHER_PRODUCT_ID = 2, // other product id not mentioned in the datasheet
+};
+
+/* STANDARD_PACK means that we can send only one USBC_PACKET_USBHS-sized USB packet
+ and then read data back. LARGER_PACK means, we can send packets as large as
+ LARGER_PACK_MAX_SIZE. libusb splits there large packets into smaller USB packets and
+ transmit the data. Then we read back the data in a bigger packet. */
+enum pack_size {
+ UNSET = -1,
+ STANDARD_PACK = 0,
+ LARGER_PACK = 1,
+};
+
+// for STANDARD_PACK mode: these are the 6 possible speeds; values in kHz
+static const int ch347_standard_pack_clock_speeds[] = {
+ 1875, // 1.875 MHz (60000 : 32)
+ 3750, // 3.75 MHz (60000 : 16)
+ 7500, // 7.5 MHz (60000 : 8)
+ 15000, // 15 MHz (60000 : 4)
+ 30000, // 30 MHz (60000 : 2)
+ 60000 // 60 MHz
+};
+
+// for LARGER_PACK mode: these are the 8 possible speeds; values in kHz
+static const int ch347_larger_pack_clock_speeds[] = {
+ 469, // 468.75 kHz (60000 : 128)
+ 938, // 937.5 kHz (60000 : 64)
+ 1875, // 1.875 MHz (60000 : 32)
+ 3750, // 3.75 MHz (60000 : 16)
+ 7500, // 7.5 MHz (60000 : 8)
+ 15000, // 15 MHz (60000 : 4)
+ 30000, // 30 MHz (60000 : 2)
+ 60000 // 60 MHz
+};
+
+struct ch347_cmd {
+ uint8_t type; // the command type
+ uint8_t *write_data; // data bytes for write
+ uint16_t write_data_len; // count of data bytes in the write_data buffer
+ uint16_t read_len; // if >0 a read is needed after this command
+ uint16_t tdo_bit_count; // how many TDO bits are needed to shift in by this read
+ struct list_head queue; // for handling a queue (list)
+};
+
+struct ch347_scan {
+ struct scan_field *fields; // array of scan_field's for data from the device
+ int fields_len; // scan_fields array length
+ struct list_head queue; // for handling a queue (list)
+};
+
+struct ch347_info {
+ // Record the CH347 pin status
+ int tms_pin;
+ int tdi_pin;
+ int tck_pin;
+ int trst_pin;
+
+ enum ch347_variant chip_variant; // ch347_variant for explanation
+ // if true then we can't us the bytewise commands due to a bug of the chip; depends on BYTEWISE_MODE_VERSION
+ bool use_bitwise_mode;
+ enum pack_size pack_size; // see: pack_size for explanation
+ int max_len; // in STANDARD_PACK or bitwise mode we can send only one USBC_PACKET_USBHS sized package
+ bool swclk_5mhz_supported;
+
+ // a "scratchpad" where we record all bytes for one command
+ uint8_t scratchpad_cmd_type; // command type
+ uint8_t scratchpad[UCMDPKT_DATA_MAX_BYTES_USBHS]; // scratchpad buffer
+ int scratchpad_idx; // current index in scratchpad
+
+ // after a command is complete it will be stored for later processing
+ struct list_head cmd_queue;
+ // all data input scan fields are queued here
+ struct list_head scan_queue;
+ // read buffer for the single commands like CH347_CMD_GPIO and CH347_CMD_JTAG_INIT
+ uint8_t single_read[CH347_SINGLE_CMD_MAX_READ];
+ int singe_read_len; // data length in single_read
+};
+
+struct ch347_swd_io {
+ uint8_t usb_cmd; // 0xA0, 0xA1, 0xA2
+ uint8_t cmd;
+ uint32_t *dst;
+ uint32_t value;
+ struct list_head list_entry;
+};
+
+struct ch347_swd_context {
+ uint8_t send_buf[CH347_MAX_SEND_BUF];
+ uint8_t recv_buf[CH347_MAX_RECV_BUF];
+ int send_len;
+ int recv_len;
+ int need_recv_len;
+ int queued_retval;
+ int sent_cmd_count;
+ unsigned int clk_divisor;
+ unsigned int total_swd_clk;
+ struct list_head send_cmd_head;
+ struct list_head free_cmd_head;
+ struct ch347_swd_io ch347_cmd_buf[CH347_MAX_CMD_BUF];
+};
+
+static struct ch347_swd_context ch347_swd_context;
+static bool swd_mode;
+static uint16_t default_ch347_vids[] = {DEFAULT_VENDOR_ID, DEFAULT_VENDOR_ID, DEFAULT_VENDOR_ID, 0};
+static uint16_t default_ch347_pids[] = {DEFAULT_CH347T_PRODUCT_ID,
+ DEFAULT_CH347F_PRODUCT_ID, DEFAULT_OTHER_PRODUCT_ID, 0};
+static uint16_t custom_ch347_vids[] = {0, 0, 0, 0};
+static uint16_t custom_ch347_pids[] = {0, 0, 0, 0};
+static char *ch347_device_desc;
+static uint8_t ch347_activity_led_gpio_pin = 0xFF;
+static bool ch347_activity_led_active_high;
+static struct ch347_info ch347;
+static struct libusb_device_handle *ch347_handle;
+
+/* there are "single" commands. These commands can't be chained together and
+ need to be send as single command and need a read after write */
+static inline bool ch347_is_single_cmd_type(uint8_t type)
+{
+ return type == CH347_CMD_GPIO || type == CH347_CMD_JTAG_INIT || type == CH347_CMD_SWD_INIT;
+}
+
+static void log_buf_dump(const uint8_t *data, unsigned int size, bool recv)
+{
+ unsigned int i = 0, j = 0;
+ unsigned int n = size * 3 + 1;
+ char *str = malloc(n);
+ if (!str)
+ return;
+
+ while (i < size && j < n) {
+ uint8_t cmd = data[i++];
+ hexify(str + j, &cmd, 1, n - j);
+ j += 2;
+ str[j++] = ' ';
+
+ unsigned int cmd_payload_size = le_to_h_u16(data + i);
+ if (i + 2 <= size && j + 4 < n) {
+ hexify(str + j, data + i, 2, n - j);
+ i += 2;
+ j += 4;
+ str[j++] = ' ';
+ }
+
+ if (cmd == CH347_CMD_SWD) {
+ // nested SWD commands
+ str[j] = '\0';
+ if (i + cmd_payload_size > size) {
+ LOG_DEBUG_IO("%s - bad size", str);
+ cmd_payload_size = size - i;
+ } else {
+ LOG_DEBUG_IO("%s", str);
+ }
+ j = 0;
+ unsigned int swd_base_i = i;
+
+ while (i < swd_base_i + cmd_payload_size) {
+ uint8_t swd_cmd = data[i++];
+ hexify(str + j, &swd_cmd, 1, n - j);
+ j += 2;
+ str[j++] = ' ';
+
+ unsigned int swd_bits = 0;
+ unsigned int swd_payload_size = 0;
+ if (!recv) {
+ if (i + 2 <= size) {
+ swd_bits = le_to_h_u16(data + i);
+ hexify(str + j, data + i, 2, n - j);
+ i += 2;
+ j += 4;
+ str[j++] = ' ';
+ }
+ }
+
+ switch (swd_cmd) {
+ case CH347_CMD_SWD_REG_W:
+ if (recv)
+ swd_payload_size = 1;
+ else
+ swd_payload_size = DIV_ROUND_UP(swd_bits, 8);
+ break;
+ case CH347_CMD_SWD_SEQ_W:
+ if (!recv)
+ swd_payload_size = DIV_ROUND_UP(swd_bits, 8);
+ break;
+ case CH347_CMD_SWD_REG_R:
+ if (recv)
+ swd_payload_size = 1 + 4 + 1;
+ else
+ swd_payload_size = 1;
+ break;
+ }
+
+ hexify(str + j, data + i, MIN(swd_payload_size, size - i), n - j);
+ i += swd_payload_size;
+ j += 2 * swd_payload_size;
+ str[j] = '\0';
+ if (i > size)
+ LOG_DEBUG_IO(" %s - bad size", str);
+ else
+ LOG_DEBUG_IO(" %s", str);
+ j = 0;
+ }
+ } else {
+ hexify(str + j, data + i, MIN(cmd_payload_size, size - i), n - j);
+ i += cmd_payload_size;
+ j += 2 * cmd_payload_size;
+ str[j] = '\0';
+ if (i > size)
+ LOG_DEBUG_IO("%s - bad size", str);
+ else
+ LOG_DEBUG_IO("%s", str);
+ j = 0;
+ }
+ }
+ free(str);
+}
+
+/**
+ * @brief writes data to the CH347 via libusb driver
+ *
+ * @param data Point to the data buffer
+ * @param length Data length in and out
+ * @return ERROR_OK at success
+ */
+static int ch347_write_data(uint8_t *data, int *length)
+{
+ int write_len = *length;
+ int i = 0;
+ int transferred = 0;
+
+ while (true) {
+ int retval = jtag_libusb_bulk_write(ch347_handle, CH347_EPOUT, (char *)&data[i],
+ write_len, USB_WRITE_TIMEOUT, &transferred);
+ if (retval != ERROR_OK) {
+ LOG_ERROR("CH347 write fail");
+ *length = 0;
+ return retval;
+ }
+ i += transferred;
+ if (i >= *length)
+ break;
+ write_len = *length - i;
+ }
+
+ if (LOG_LEVEL_IS(LOG_LVL_DEBUG_IO)) {
+ LOG_DEBUG_IO("size=%d, buf=", i);
+ log_buf_dump(data, i, false);
+ }
+
+ *length = i;
+ return ERROR_OK;
+}
+
+/**
+ * @brief reads data from the CH347 via libusb driver
+ *
+ * @param data Point to the data buffer
+ * @param length Data length in and out
+ * @return ERROR_OK at success
+ */
+static int ch347_read_data(uint8_t *data, int *length)
+{
+ int read_len = *length;
+ int i = 0;
+ int transferred = 0;
+
+ while (true) {
+ int retval = jtag_libusb_bulk_read(ch347_handle, CH347_EPIN, (char *)&data[i],
+ read_len, USB_READ_TIMEOUT, &transferred);
+ if (retval != ERROR_OK) {
+ LOG_ERROR("CH347 read fail");
+ *length = 0;
+ return retval;
+ }
+
+ i += transferred;
+ if (i >= *length)
+ break;
+ read_len = *length - i;
+ }
+
+ if (LOG_LEVEL_IS(LOG_LVL_DEBUG_IO)) {
+ LOG_DEBUG_IO("size=%d, buf=", i);
+ log_buf_dump(data, i, true);
+ }
+
+ *length = i;
+ return ERROR_OK;
+}
+
+/**
+ * @brief calculates the amount of bits and bytes that should be read
+ * for this command
+ *
+ * @param cmd command for the calculation
+ */
+static void ch347_cmd_calc_reads(struct ch347_cmd *cmd)
+{
+ cmd->read_len = 0;
+ cmd->tdo_bit_count = 0;
+
+ switch (cmd->type) {
+ case CH347_CMD_GPIO:
+ // for GPIO we need to read back the same amount of data that we had send
+ cmd->read_len = cmd->write_data_len;
+ break;
+ case CH347_CMD_JTAG_INIT:
+ case CH347_CMD_SWD_INIT:
+ // for JTAG_INIT/SWD_INIT the amount is fixed
+ cmd->read_len = CH347_CMD_INIT_READ_LEN;
+ break;
+ case CH347_CMD_JTAG_BIT_OP_RD:
+ // for bit operations we need to count the TCK high edges
+ for (int i = 0; i < cmd->write_data_len; i++) {
+ if ((cmd->write_data[i] & TCK_H) == TCK_H) {
+ cmd->read_len++;
+ cmd->tdo_bit_count++;
+ }
+ }
+ break;
+ case CH347_CMD_JTAG_DATA_SHIFT_RD:
+ // for byte operations: need to read one byte back for each data byte
+ cmd->read_len = cmd->write_data_len;
+ // we occupy 8 bits per byte in the TDO hardware buffer
+ cmd->tdo_bit_count = cmd->read_len * 8;
+ break;
+ }
+}
+
+/**
+ * @brief copy the scratchpad content into a new command in the command queue
+ *
+ * @param scan_fields array of scan_field's for data from the device
+ * @param scan_fields_len array length
+ * @return ERROR_OK at success
+ */
+static int ch347_cmd_from_scratchpad(void)
+{
+ // nothing to do if no bytes are recorded
+ if (!ch347.scratchpad_idx)
+ return ERROR_OK;
+
+ // malloc for the command and data bytes
+ struct ch347_cmd *cmd = malloc(sizeof(struct ch347_cmd));
+ if (cmd)
+ cmd->write_data = malloc(ch347.scratchpad_idx);
+ if (!cmd || !cmd->write_data) {
+ LOG_ERROR("malloc failed");
+ free(cmd);
+ return ERROR_FAIL;
+ }
+
+ // copy data, calculate the reads and add to the command queue
+ cmd->type = ch347.scratchpad_cmd_type;
+ cmd->write_data_len = ch347.scratchpad_idx;
+ memcpy(cmd->write_data, ch347.scratchpad, ch347.scratchpad_idx);
+ ch347_cmd_calc_reads(cmd);
+ list_add_tail(&cmd->queue, &ch347.cmd_queue);
+
+ // cleanup the scratchpad for the next command
+ ch347.scratchpad_cmd_type = 0;
+ ch347.scratchpad_idx = 0;
+ return ERROR_OK;
+}
+
+/**
+ * @brief Reads data back from CH347 and decode it byte- and bitwise into the buffer
+ *
+ * @param decoded_buf Point to a buffer to place the data to be decoded; need to be sized
+ * to the decoded size length; not the raw_read_len
+ * @param decoded_buf_len length of the decoded_buf
+ * @param raw_read_len Data length in bytes that should be read via libusb; the decoded length can be shorter
+ * @return ERROR_OK at success
+ */
+static int ch347_read_scan(uint8_t *decoded_buf, int decoded_buf_len, int raw_read_len)
+{
+ int read_len = raw_read_len;
+ uint8_t *read_buf = malloc(read_len);
+ if (!read_buf) {
+ LOG_ERROR("malloc failed");
+ return ERROR_FAIL;
+ }
+
+ int retval = ch347_read_data(read_buf, &read_len);
+ if (retval != ERROR_OK) {
+ free(read_buf);
+ return retval;
+ }
+
+ int rd_idx = 0;
+ int decoded_buf_idx = 0;
+
+ while (rd_idx < read_len) {
+ unsigned int type = read_buf[rd_idx++];
+ uint16_t data_len = le_to_h_u16(&read_buf[rd_idx]);
+ rd_idx += 2;
+ if (decoded_buf_idx > decoded_buf_len) {
+ LOG_ERROR("CH347 decoded_buf too small");
+ free(read_buf);
+ return ERROR_FAIL;
+ }
+
+ // nothing to decode? Only read to make the CH347 happy!
+ if (!decoded_buf) {
+ rd_idx += data_len;
+ continue;
+ }
+
+ switch (type) {
+ case CH347_CMD_GPIO:
+ case CH347_CMD_JTAG_INIT:
+ case CH347_CMD_SWD_INIT:
+ case CH347_CMD_JTAG_DATA_SHIFT_RD:
+ // for all bytewise commands: copy the data bytes
+ memcpy(&decoded_buf[decoded_buf_idx], &read_buf[rd_idx], data_len);
+ decoded_buf_idx += data_len;
+ rd_idx += data_len;
+ break;
+ case CH347_CMD_JTAG_BIT_OP_RD:
+ // for CH347_CMD_JTAG_BIT_OP_RD we need to copy bit by bit
+ for (int i = 0; i < data_len; i++) {
+ if (read_buf[rd_idx + i] & BIT(0))
+ decoded_buf[decoded_buf_idx + i / 8] |= BIT(i % 8);
+ else
+ decoded_buf[decoded_buf_idx + i / 8] &= ~(BIT(i % 8));
+ }
+ rd_idx += data_len;
+ decoded_buf_idx += DIV_ROUND_UP(data_len, 8);
+ break;
+ default:
+ LOG_ERROR("CH347 read command fail");
+ free(read_buf);
+ return ERROR_FAIL;
+ }
+ }
+
+ free(read_buf);
+ return ERROR_OK;
+}
+
+/**
+ * @brief Used to put the data from the decoded buffer into the scan command fields
+ *
+ * @param decoded_buf Point to a buffer for the decoded data
+ * @param decoded_buf_len length of the decoded_buf
+ * @return ERROR_OK at success
+ */
+static int ch347_scan_data_to_fields(uint8_t *decoded_buf, int decoded_buf_len)
+{
+ int byte_offset = 0;
+ struct ch347_scan *scan;
+ struct ch347_scan *tmp;
+ int bit_offset = 0;
+ list_for_each_entry_safe(scan, tmp, &ch347.scan_queue, queue) {
+ for (int i = 0; i < scan->fields_len; i++) {
+ int num_bits = scan->fields[i].num_bits;
+ LOG_DEBUG("fields[%d].in_value[%d], read from bit offset: %d", i, num_bits, bit_offset);
+ // only if we need the value
+ if (scan->fields[i].in_value) {
+ uint8_t *capture_buf = malloc(DIV_ROUND_UP(num_bits, 8));
+ if (!capture_buf) {
+ LOG_ERROR("malloc failed");
+ return ERROR_FAIL;
+ }
+ uint8_t *captured = buf_set_buf(decoded_buf, bit_offset, capture_buf, 0, num_bits);
+
+ if (LOG_LEVEL_IS(LOG_LVL_DEBUG_IO)) {
+ char *str = buf_to_hex_str(captured, num_bits);
+ LOG_DEBUG_IO("size=%d, buf=[%s]", num_bits, str);
+ free(str);
+ }
+
+ buf_cpy(captured, scan->fields[i].in_value, num_bits);
+ free(capture_buf);
+ } else {
+ if (LOG_LEVEL_IS(LOG_LVL_DEBUG_IO))
+ LOG_DEBUG_IO("field skipped");
+ }
+ bit_offset += num_bits;
+ }
+ list_del(&scan->queue);
+ free(scan);
+ /* after one round of scan field processing the
+ next data bits are read from the next data byte
+ => round up and calculate the next start bit */
+ byte_offset = DIV_ROUND_UP(bit_offset, 8);
+ bit_offset = byte_offset * 8;
+ }
+
+ // if not all bytes are transferred: put the rest into single_read buffer
+ if (byte_offset < decoded_buf_len) {
+ ch347.singe_read_len = decoded_buf_len - byte_offset;
+ LOG_DEBUG("single read of %d bytes", ch347.singe_read_len);
+ if (ch347.singe_read_len > CH347_SINGLE_CMD_MAX_READ) {
+ LOG_ERROR("Can't read more than %d bytes for a single command!", CH347_SINGLE_CMD_MAX_READ);
+ ch347.singe_read_len = CH347_SINGLE_CMD_MAX_READ;
+ }
+ memcpy(ch347.single_read, &decoded_buf[byte_offset], ch347.singe_read_len);
+ }
+
+ return ERROR_OK;
+}
+
+/**
+ * @brief Sends the write buffer via libusb
+ * and if LARGER_PACK mode is active read also data back
+ *
+ * @return ERROR_OK at success
+ */
+static int ch347_cmd_transmit_queue(void)
+{
+ // queue last command
+ int retval = ch347_cmd_from_scratchpad();
+ if (retval != ERROR_OK)
+ return retval;
+
+ // nothing to do! => done here
+ if (list_empty(&ch347.cmd_queue))
+ return ERROR_OK;
+
+ // calculate the needed buffer length for all decoded bytes
+ struct ch347_cmd *cmd;
+ int decoded_buf_len = 0;
+ list_for_each_entry(cmd, &ch347.cmd_queue, queue)
+ if (cmd->read_len > 0)
+ decoded_buf_len += ch347_is_single_cmd_type(cmd->type) ?
+ cmd->read_len : DIV_ROUND_UP(cmd->tdo_bit_count, 8);
+
+ // create the buffer for all decoded bytes
+ uint8_t *decoded_buf = NULL;
+ int decoded_buf_idx = 0;
+ if (decoded_buf_len > 0) {
+ decoded_buf = malloc(decoded_buf_len);
+ if (!decoded_buf) {
+ LOG_ERROR("malloc failed");
+ return ERROR_FAIL;
+ }
+ }
+
+ while (!list_empty(&ch347.cmd_queue)) {
+ struct ch347_cmd *last_cmd = NULL;
+ int total_len = 0;
+ int total_tdo_count = 0;
+ int bytes_to_write = 0;
+
+ list_for_each_entry(cmd, &ch347.cmd_queue, queue) {
+ total_len += CH347_CMD_HEADER + cmd->write_data_len;
+ total_tdo_count += cmd->tdo_bit_count;
+ // don't exceed max length or max TDO bit count
+ if (total_len >= ch347.max_len || total_tdo_count >= HW_TDO_BUF_SIZE)
+ break;
+ // remember the last cmd to send and bytes to send
+ last_cmd = cmd;
+ bytes_to_write = total_len;
+ }
+
+ // sanity checks
+ if (!last_cmd || bytes_to_write == 0) {
+ LOG_ERROR("Nothing to send!");
+ free(decoded_buf);
+ return ERROR_FAIL;
+ }
+
+ // create the write buffer
+ uint8_t *write_buf = malloc(bytes_to_write);
+ if (!write_buf) {
+ LOG_ERROR("malloc failed");
+ free(decoded_buf);
+ return ERROR_FAIL;
+ }
+
+ int idx = 0;
+ int bytes_to_read = 0;
+ int current_decoded_buf_len = 0;
+ struct ch347_cmd *tmp;
+
+ list_for_each_entry_safe(cmd, tmp, &ch347.cmd_queue, queue) {
+ // copy command to buffer
+ write_buf[idx++] = cmd->type;
+ h_u16_to_le(&write_buf[idx], cmd->write_data_len);
+ idx += 2;
+ memcpy(&write_buf[idx], cmd->write_data, cmd->write_data_len);
+ idx += cmd->write_data_len;
+ // need to read something back?
+ if (cmd->read_len > 0) {
+ bytes_to_read += CH347_CMD_HEADER + cmd->read_len;
+ current_decoded_buf_len += ch347_is_single_cmd_type(cmd->type) ?
+ cmd->read_len : DIV_ROUND_UP(cmd->tdo_bit_count, 8);
+ }
+
+ // cmd data no longer needed
+ list_del(&cmd->queue);
+ free(cmd->write_data);
+ free(cmd);
+
+ if (cmd == last_cmd)
+ break;
+ }
+
+ // write data to device
+ retval = ch347_write_data(write_buf, &idx);
+ free(write_buf);
+ if (retval != ERROR_OK) {
+ free(decoded_buf);
+ return retval;
+ }
+
+ if (!bytes_to_read)
+ continue;
+
+ // Need only to execute a read without decoding the data to make the CH347 happy?
+ if (!current_decoded_buf_len) {
+ // read but don't decode anything
+ retval = ch347_read_scan(NULL, 0, bytes_to_read);
+ } else {
+ retval = ch347_read_scan(&decoded_buf[decoded_buf_idx], current_decoded_buf_len, bytes_to_read);
+ decoded_buf_idx += current_decoded_buf_len;
+ }
+
+ if (retval != ERROR_OK) {
+ free(decoded_buf);
+ return retval;
+ }
+ }
+
+ // something decoded from the data read back from CH347?
+ if (decoded_buf) {
+ // put the decoded data into the scan fields or single_read buffer
+ retval = ch347_scan_data_to_fields(decoded_buf, decoded_buf_len);
+ free(decoded_buf);
+ }
+
+ return retval;
+}
+
+/**
+ * @brief starts the next command in the scratchpad. If it's the same command type
+ * it can concat the data bytes. no need to make a new command for this case
+ *
+ * @param type command type
+ */
+static int ch347_cmd_start_next(uint8_t type)
+{
+ // different command type or non chainable command? (GPIO commands can't be concat)
+ uint8_t prev_type = ch347.scratchpad_cmd_type;
+ if (prev_type != type || ch347_is_single_cmd_type(type)) {
+ // something written in the scratchpad? => store it as command
+ if (prev_type != 0 && ch347.scratchpad_idx > 0) {
+ int retval = ch347_cmd_from_scratchpad();
+ if (retval != ERROR_OK)
+ return retval;
+
+ /* if the last queued command is not chainable we should send it immediately
+ because e.g. the GPIO command can't be combined with any other command */
+ if (ch347_is_single_cmd_type(prev_type)) {
+ retval = ch347_cmd_transmit_queue();
+ if (retval != ERROR_OK)
+ return retval;
+ }
+ }
+
+ /* before we can send non chainable command ("single" like GPIO command) we should send all
+ other commands because we can't send it together with other commands */
+ if (ch347_is_single_cmd_type(type)) {
+ int retval = ch347_cmd_transmit_queue();
+ if (retval != ERROR_OK)
+ return retval;
+ }
+
+ // store the next command type
+ ch347.scratchpad_cmd_type = type;
+ }
+
+ return ERROR_OK;
+}
+
+/**
+ * @brief queue the scan fields into the scan queue
+ *
+ * @param scan_fields array of scan field's for data from the device
+ * @param scan_fields_len array length
+ * @return ERROR_OK at success
+ */
+static int ch347_scan_queue_fields(struct scan_field *scan_fields, int scan_fields_len)
+{
+ // malloc for the scan struct
+ struct ch347_scan *scan = malloc(sizeof(struct ch347_scan));
+ if (!scan) {
+ LOG_ERROR("malloc failed");
+ return ERROR_FAIL;
+ }
+
+ scan->fields = scan_fields;
+ scan->fields_len = scan_fields_len;
+ list_add_tail(&scan->queue, &ch347.scan_queue);
+ return ERROR_OK;
+}
+
+/**
+ * @brief Function executes the single command and deliver one byte from the buffer
+ * that's read back from USB
+ *
+ * @param read_buf_idx index of the byte that should be returned
+ * @param byte returns byte at index or if index is out of range the first byte
+ * @return ERROR_OK at success
+ */
+static int ch347_single_read_get_byte(int read_buf_idx, uint8_t *byte)
+{
+ int retval = ch347_cmd_transmit_queue();
+ if (retval != ERROR_OK)
+ return retval;
+
+ if (read_buf_idx > CH347_SINGLE_CMD_MAX_READ || read_buf_idx < 0) {
+ LOG_ERROR("read_buf_idx out of range");
+ return ERROR_FAIL;
+ }
+
+ *byte = ch347.single_read[read_buf_idx];
+ return ERROR_OK;
+}
+
+/**
+ * @brief checks if the scratchpad is full. If it's full the function creates
+ * a command from it and puts it into the command queue
+ */
+static void ch347_scratchpad_check_full(void)
+{
+ // if full create a new command in the queue
+ if (ch347.scratchpad_idx == UCMDPKT_DATA_MAX_BYTES_USBHS) {
+ uint8_t type = ch347.scratchpad_cmd_type;
+ ch347_cmd_from_scratchpad();
+ ch347.scratchpad_cmd_type = type;
+ }
+}
+
+/**
+ * @brief adds one byte to the scratchpad
+ * if scratchpad is full after this byte the command will be created from the
+ * scratchpad and the scratchpad is cleared for the next command
+ *
+ * @param byte add this byte
+ * @return ERROR_OK at success
+ */
+static int ch347_scratchpad_add_byte(uint8_t byte)
+{
+ if (ch347.scratchpad_cmd_type == 0) {
+ LOG_ERROR("call ch347_next_cmd first!");
+ return ERROR_FAIL;
+ }
+
+ ch347.scratchpad[ch347.scratchpad_idx++] = byte;
+ ch347_scratchpad_check_full();
+ return ERROR_OK;
+}
+
+/**
+ * @brief adds the output pin byte to the scratchpad
+ * if scratchpad is full after this byte the command will be created from the
+ * scratchpad and the scratchpad is cleared for the next command
+ *
+ * @return ERROR_OK at success
+ */
+static int ch347_scratchpad_add_pin_byte(void)
+{
+ return ch347_scratchpad_add_byte(ch347.tms_pin | ch347.tdi_pin | ch347.tck_pin | ch347.trst_pin);
+}
+
+/**
+ * @brief adds bytes from a buffer to the scratchpad
+ * if scratchpad is full after this byte the command will be created from the
+ * scratchpad and the scratchpad is cleared for the next command
+ *
+ * @param bytes add this bytes
+ * @param count byte count
+ *
+ * @return ERROR_OK at success
+ */
+static int ch347_scratchpad_add_bytes(uint8_t *bytes, int count)
+{
+ if (ch347.scratchpad_cmd_type == 0) {
+ LOG_ERROR("call ch347_next_cmd first!");
+ return ERROR_FAIL;
+ }
+
+ int remaining = count;
+ int bytes_idx = 0;
+ while (remaining > 0) {
+ int bytes_to_store = ch347.scratchpad_idx + remaining <= UCMDPKT_DATA_MAX_BYTES_USBHS ?
+ remaining : UCMDPKT_DATA_MAX_BYTES_USBHS - ch347.scratchpad_idx;
+
+ if (bytes)
+ memcpy(&ch347.scratchpad[ch347.scratchpad_idx], &bytes[bytes_idx], bytes_to_store);
+ else
+ memset(&ch347.scratchpad[ch347.scratchpad_idx], 0, bytes_to_store);
+
+ ch347.scratchpad_idx += bytes_to_store;
+ bytes_idx += bytes_to_store;
+ remaining -= bytes_to_store;
+ ch347_scratchpad_check_full();
+ }
+
+ return ERROR_OK;
+}
+
+/**
+ * @brief Function used to change the TMS value at the
+ * rising edge of TCK to switch its TAP state
+ *
+ * @param tms TMS value to be changed; true = output TMS high; false = output TMS low
+ * @return ERROR_OK at success
+ */
+static int ch347_scratchpad_add_clock_tms(bool tms)
+{
+ ch347.tms_pin = tms ? TMS_H : TMS_L;
+ ch347.tck_pin = TCK_L;
+ int retval = ch347_scratchpad_add_pin_byte();
+ if (retval != ERROR_OK)
+ return retval;
+
+ ch347.tck_pin = TCK_H;
+ return ch347_scratchpad_add_pin_byte();
+}
+
+/**
+ * @brief Function adds a certain amount of TCK pulses without changing the TMS pin
+ *
+ * @param count Amount of L/H TCK pulses to add
+ * @return ERROR_OK at success
+ */
+static int ch347_scratchpad_add_stableclocks(int count)
+{
+ if (ch347.scratchpad_cmd_type == 0) {
+ int retval = ch347_cmd_start_next(CH347_CMD_JTAG_BIT_OP);
+ if (retval != ERROR_OK)
+ return retval;
+ }
+
+ bool tms = ch347.tms_pin == TMS_H;
+ for (int i = 0; i < count; i++) {
+ int retval = ch347_scratchpad_add_clock_tms(tms);
+ if (retval != ERROR_OK)
+ return retval;
+ }
+
+ return ERROR_OK;
+}
+
+/**
+ * @brief Function to ensure that the clock is in a low state
+ *
+ * @return ERROR_OK at success
+ */
+static int ch347_scratchpad_add_idle_clock(void)
+{
+ ch347.tck_pin = TCK_L;
+ return ch347_scratchpad_add_pin_byte();
+}
+
+/**
+ * @brief Function that performs state switching by changing the value of TMS
+ *
+ * @param tms_value The TMS values that need to be switched form one byte of data in the switching order
+ * @param step The number of bit values that need to be read from the tms_value value
+ * @param skip Count from the skip bit of tms_value to step
+ * @return ERROR_OK at success
+ */
+static int ch347_scratchpad_add_tms_change(const uint8_t *tms_value, int step, int skip)
+{
+ LOG_DEBUG_IO("TMS Value: %02x..., step = %d, skip = %d", tms_value[0], step, skip);
+
+ int retval = ch347_cmd_start_next(CH347_CMD_JTAG_BIT_OP);
+ if (retval != ERROR_OK)
+ return retval;
+
+ for (int i = skip; i < step; i++) {
+ retval = ch347_scratchpad_add_clock_tms((tms_value[i / 8] >> (i % 8)) & BIT(0));
+ if (retval != ERROR_OK)
+ return retval;
+ }
+
+ return ch347_scratchpad_add_idle_clock();
+}
+
+/**
+ * @brief Obtain the current Tap status and switch to the status TMS value passed down by cmd
+ *
+ * @param cmd Upper layer transfer command parameters
+ * @return ERROR_OK at success; ERROR_JTAG_TRANSITION_INVALID if no transition is possible
+ */
+static int ch347_scratchpad_add_move_path(struct pathmove_command *cmd)
+{
+ LOG_DEBUG_IO("num_states=%d, last_state=%d", cmd->num_states, cmd->path[cmd->num_states - 1]);
+
+ int retval = ch347_cmd_start_next(CH347_CMD_JTAG_BIT_OP);
+ if (retval != ERROR_OK)
+ return retval;
+
+ for (unsigned int i = 0; i < cmd->num_states; i++) {
+ if (tap_state_transition(tap_get_state(), false) == cmd->path[i]) {
+ retval = ch347_scratchpad_add_clock_tms(0);
+ if (retval != ERROR_OK)
+ return retval;
+ } else if (tap_state_transition(tap_get_state(), true) == cmd->path[i]) {
+ retval = ch347_scratchpad_add_clock_tms(1);
+ if (retval != ERROR_OK)
+ return retval;
+ } else {
+ LOG_ERROR("No transition possible!");
+ return ERROR_JTAG_TRANSITION_INVALID;
+ }
+ tap_set_state(cmd->path[i]);
+ }
+
+ return ch347_scratchpad_add_idle_clock();
+}
+
+/**
+ * @brief Toggle the tap state to the target state
+ *
+ * @param state Pre switch target path
+ * @param skip Number of digits to skip
+ * @return ERROR_OK at success
+ */
+static int ch347_scratchpad_add_move_state(enum tap_state state, int skip)
+{
+ uint8_t tms_scan;
+ int tms_len;
+
+ LOG_DEBUG_IO("from %s to %s", tap_state_name(tap_get_state()), tap_state_name(state));
+ // don't do anything if we are already in the right state; but do execute always the TAP_RESET
+ if (tap_get_state() == state && state != TAP_RESET)
+ return ERROR_OK;
+
+ tms_scan = tap_get_tms_path(tap_get_state(), state);
+ tms_len = tap_get_tms_path_len(tap_get_state(), state);
+ int retval = ch347_scratchpad_add_tms_change(&tms_scan, tms_len, skip);
+ tap_set_state(state);
+ return retval;
+}
+
+/**
+ * @brief CH347 Batch read/write function
+ *
+ * @param cmd The scan command
+ * @param bits Read and write data this time
+ * @param bits_len Incoming data length in bits
+ * @param scan The transmission method of incoming data to determine whether to perform data reading
+ * @return ERROR_OK at success
+ */
+static int ch347_scratchpad_add_write_read(struct scan_command *cmd, uint8_t *bits, int bits_len, enum scan_type scan)
+{
+ // the bits and bytes to transfer
+ int byte_count = bits_len / 8;
+ int bit_count = bits_len % 8;
+
+ // only bytes are not possible because we need to set TMS high for the last bit
+ if (byte_count > 0 && bit_count == 0) {
+ // make one byte to eight bits
+ byte_count--;
+ bit_count = 8;
+ }
+
+ // in bitwise mode only bits are allowed
+ if (ch347.use_bitwise_mode) {
+ byte_count = 0;
+ bit_count = bits_len;
+ }
+
+ bool is_read = (scan == SCAN_IN || scan == SCAN_IO);
+
+ // if we need to send bytes
+ if (byte_count > 0) {
+ // start the next cmd and copy the data out bytes to it
+ int retval = ch347_cmd_start_next(is_read ? CH347_CMD_JTAG_DATA_SHIFT_RD : CH347_CMD_JTAG_DATA_SHIFT);
+ if (retval != ERROR_OK)
+ return retval;
+
+ if (bits)
+ retval = ch347_scratchpad_add_bytes(bits, byte_count);
+ else
+ retval = ch347_scratchpad_add_bytes(NULL, byte_count);
+
+ if (retval != ERROR_OK)
+ return retval;
+ }
+
+ // bits are always need to send; no possibility to not send bits
+ int retval = ch347_cmd_start_next(is_read ? CH347_CMD_JTAG_BIT_OP_RD : CH347_CMD_JTAG_BIT_OP);
+ if (retval != ERROR_OK)
+ return retval;
+
+ ch347.tms_pin = TMS_L;
+ ch347.tdi_pin = TDI_L;
+
+ for (int i = 0; i < bit_count; i++) {
+ if (bits)
+ ch347.tdi_pin = ((bits[byte_count + i / 8] >> i % 8) & BIT(0)) ? TDI_H : TDI_L;
+
+ // for the last bit set TMS high to exit the shift state
+ if (i + 1 == bit_count)
+ ch347.tms_pin = TMS_H;
+
+ ch347.tck_pin = TCK_L;
+ retval = ch347_scratchpad_add_pin_byte();
+ if (retval != ERROR_OK)
+ return retval;
+
+ ch347.tck_pin = TCK_H;
+ retval = ch347_scratchpad_add_pin_byte();
+ if (retval != ERROR_OK)
+ return retval;
+
+ /* cut the package after each MAX_BITS_PER_BIT_OP bits because it
+ needs a dividable by 8 bits package */
+ if (i > 0 && (i + 1) % MAX_BITS_PER_BIT_OP == 0) {
+ retval = ch347_cmd_from_scratchpad();
+ if (retval != ERROR_OK)
+ return retval;
+
+ retval = ch347_cmd_start_next(is_read ? CH347_CMD_JTAG_BIT_OP_RD : CH347_CMD_JTAG_BIT_OP);
+ if (retval != ERROR_OK)
+ return retval;
+ }
+ }
+
+ // one TCK_L after the last bit
+ retval = ch347_scratchpad_add_idle_clock();
+ if (retval != ERROR_OK)
+ return retval;
+
+ // if read is involved we need to queue the scan fields
+ if (is_read)
+ return ch347_scan_queue_fields(cmd->fields, cmd->num_fields);
+
+ return ERROR_OK;
+}
+
+/**
+ * @brief Toggle the Tap state to run test/idle
+ *
+ * @param cycles how many clock cycles for output
+ * @param state JTAG end state
+ * @return ERROR_OK at success
+ */
+static int ch347_scratchpad_add_run_test(int cycles, enum tap_state state)
+{
+ LOG_DEBUG_IO("cycles=%d, end_state=%d", cycles, state);
+ int retval;
+ if (tap_get_state() != TAP_IDLE) {
+ retval = ch347_scratchpad_add_move_state(TAP_IDLE, 0);
+ if (retval != ERROR_OK)
+ return retval;
+ }
+
+ retval = ch347_scratchpad_add_stableclocks(cycles);
+ if (retval != ERROR_OK)
+ return retval;
+
+ return ch347_scratchpad_add_move_state(state, 0);
+}
+
+/**
+ * @brief Switch to SHIFT-DR or SHIFT-IR status for scanning
+ *
+ * @param cmd Upper layer transfer command parameters
+ * @return ERROR_OK at success
+ */
+static int ch347_scratchpad_add_scan(struct scan_command *cmd)
+{
+ static const char *const type2str[] = {"", "SCAN_IN", "SCAN_OUT", "SCAN_IO"};
+
+ enum scan_type type = jtag_scan_type(cmd);
+ uint8_t *buf = NULL;
+ int scan_bits = jtag_build_buffer(cmd, &buf);
+
+ // add a move to IRSHIFT or DRSHIFT state
+ int retval;
+ if (cmd->ir_scan)
+ retval = ch347_scratchpad_add_move_state(TAP_IRSHIFT, 0);
+ else
+ retval = ch347_scratchpad_add_move_state(TAP_DRSHIFT, 0);
+
+ if (retval != ERROR_OK) {
+ free(buf);
+ return retval;
+ }
+
+ if (LOG_LEVEL_IS(LOG_LVL_DEBUG_IO)) {
+ char *log_buf = buf_to_hex_str(buf, scan_bits);
+ LOG_DEBUG_IO("scan=%s, type=%s, bits=%d, buf=[%s], end_state=%d",
+ cmd->ir_scan ? "IRSCAN" : "DRSCAN",
+ type2str[type],
+ scan_bits, log_buf, cmd->end_state);
+ free(log_buf);
+ }
+
+ retval = ch347_scratchpad_add_write_read(cmd, buf, scan_bits, type);
+ free(buf);
+ if (retval != ERROR_OK)
+ return retval;
+
+ // add a move to the final state
+ return ch347_scratchpad_add_move_state(cmd->end_state, 1);
+}
+
+/**
+ * @brief Sets a GPIO bit
+ *
+ * @param gpio GPIO bit number 0-7
+ * @param data true for high; false for low
+ * @return ERROR_OK at success
+ */
+static int ch347_gpio_set(int gpio, bool data)
+{
+ int retval = ch347_cmd_start_next(CH347_CMD_GPIO);
+ if (retval != ERROR_OK)
+ return retval;
+
+ uint8_t gpios[GPIO_CNT];
+ memset(gpios, 0, GPIO_CNT);
+ /* always set bits 7 and 6 for GPIO enable
+ bits 5 and 4 for pin direction output
+ bit 3 is the data bit */
+ gpios[gpio] = data == 0 ? GPIO_SET_L : GPIO_SET_H;
+ retval = ch347_scratchpad_add_bytes(gpios, GPIO_CNT);
+ if (retval != ERROR_OK)
+ return retval;
+
+ // check in the read if the bit is set/cleared correctly
+ uint8_t byte;
+ retval = ch347_single_read_get_byte(gpio, &byte);
+ if (retval != ERROR_OK)
+ return retval;
+
+ if ((byte & BIT(6)) >> 6 != data) {
+ LOG_ERROR("Output not set.");
+ return ERROR_FAIL;
+ }
+
+ return ERROR_OK;
+}
+
+/**
+ * @brief Turn the activity LED on or off
+ *
+ * @param led_state LED_ON or LED_OFF
+ * @return ERROR_OK at success or if pin is not configured
+ */
+static int ch347_activity_led_set(int led_state)
+{
+ if (ch347_activity_led_gpio_pin != 0xFF)
+ return ch347_gpio_set(ch347_activity_led_gpio_pin, ch347_activity_led_active_high ? led_state : 1 - led_state);
+
+ // not configured => also OK
+ return ERROR_OK;
+}
+
+/**
+ * @brief Control (assert/deassert) the signals SRST and TRST on the interface.
+ *
+ * @param trst 1 to assert TRST, 0 to deassert TRST.
+ * @param srst 1 to assert SRST, 0 to deassert SRST.
+ * @return Always ERROR_FAIL for asserting via SRST and TRST in SWD mode.
+ * ERROR_OK for assert/deassert in JTAG mode for TRST
+ */
+static int ch347_reset(int trst, int srst)
+{
+ LOG_DEBUG_IO("reset trst: %i srst %i", trst, srst);
+ if (srst) {
+ LOG_ERROR("Asserting SRST not supported!");
+ return ERROR_FAIL;
+ }
+
+ if (swd_mode) {
+ if (trst)
+ LOG_WARNING("Asserting TRST not supported in SWD mode!");
+ return ERROR_OK;
+ }
+
+ int retval = ch347_cmd_start_next(CH347_CMD_JTAG_BIT_OP);
+ if (retval != ERROR_OK)
+ return retval;
+
+ ch347.trst_pin = trst ? TRST_L : TRST_H;
+ retval = ch347_scratchpad_add_pin_byte();
+ if (retval != ERROR_OK)
+ return retval;
+
+ retval = ch347_scratchpad_add_idle_clock();
+ if (retval != ERROR_OK)
+ return retval;
+
+ return ch347_cmd_transmit_queue();
+}
+
+/**
+ * @brief Flushes the command buffer and sleeps for a specific timespan
+ *
+ * @param us Sleep time in microseconds
+ * @return ERROR_OK at success
+ */
+static int ch347_sleep(int us)
+{
+ LOG_DEBUG_IO("us=%d", us);
+ int retval = ch347_cmd_transmit_queue();
+ jtag_sleep(us);
+ return retval;
+}
+
+/**
+ * @brief Executes the command queue
+ *
+ * @return Success returns ERROR_OK
+ */
+static int ch347_execute_queue(struct jtag_command *cmd_queue)
+{
+ struct jtag_command *cmd = cmd_queue;
+
+ int retval = ch347_activity_led_set(LED_ON);
+ if (retval != ERROR_OK)
+ return retval;
+
+ while (retval == ERROR_OK && cmd) {
+ switch (cmd->type) {
+ case JTAG_RUNTEST:
+ retval = ch347_scratchpad_add_run_test(cmd->cmd.runtest->num_cycles, cmd->cmd.runtest->end_state);
+ break;
+ case JTAG_STABLECLOCKS:
+ retval = ch347_scratchpad_add_stableclocks(cmd->cmd.stableclocks->num_cycles);
+ break;
+ case JTAG_TLR_RESET:
+ retval = ch347_scratchpad_add_move_state(cmd->cmd.statemove->end_state, 0);
+ break;
+ case JTAG_PATHMOVE:
+ retval = ch347_scratchpad_add_move_path(cmd->cmd.pathmove);
+ break;
+ case JTAG_TMS:
+ retval = ch347_scratchpad_add_tms_change(cmd->cmd.tms->bits, cmd->cmd.tms->num_bits, 0);
+ break;
+ case JTAG_SLEEP:
+ retval = ch347_sleep(cmd->cmd.sleep->us);
+ break;
+ case JTAG_SCAN:
+ retval = ch347_scratchpad_add_scan(cmd->cmd.scan);
+ break;
+ default:
+ LOG_ERROR("BUG: unknown JTAG command type 0x%X", cmd->type);
+ retval = ERROR_FAIL;
+ break;
+ }
+
+ cmd = cmd->next;
+ }
+
+ if (retval != ERROR_OK)
+ return retval;
+
+ retval = ch347_cmd_transmit_queue();
+ if (retval != ERROR_OK)
+ return retval;
+
+ return ch347_activity_led_set(LED_OFF);
+}
+
+/**
+ * @brief opens the CH347 device via libusb driver
+ *
+ * @return ERROR_OK on success
+ */
+static int ch347_open_device(void)
+{
+ const uint16_t *ch347_vids = custom_ch347_vids[0] != 0 ? custom_ch347_vids : default_ch347_vids;
+ const uint16_t *ch347_pids = custom_ch347_pids[0] != 0 ? custom_ch347_pids : default_ch347_pids;
+
+ int retval = jtag_libusb_open(ch347_vids, ch347_pids, ch347_device_desc, &ch347_handle, NULL);
+ if (retval != ERROR_OK) {
+ char error_message[256];
+ snprintf(error_message, sizeof(error_message), "CH347 not found. Tried VID/PID pairs: ");
+ for (int i = 0; ch347_vids[i] != 0; i++)
+ snprintf(error_message + strlen(error_message), sizeof(error_message) - strlen(error_message),
+ "%04x:%04x ", ch347_vids[i], ch347_pids[i]);
+
+ LOG_ERROR("%s", error_message);
+ return retval;
+ }
+
+ struct libusb_device_descriptor ch347_device_descriptor;
+ libusb_device *device = libusb_get_device(ch347_handle);
+ if (!device) {
+ LOG_ERROR("CH347 error calling libusb_get_device");
+ jtag_libusb_close(ch347_handle);
+ return ERROR_FAIL;
+ }
+
+ retval = libusb_get_device_descriptor(device, &ch347_device_descriptor);
+ if (retval != ERROR_OK) {
+ LOG_ERROR("CH347 error getting device descriptor: %s", libusb_error_name(retval));
+ jtag_libusb_close(ch347_handle);
+ return retval;
+ }
+
+ // CH347T / CH347F detection
+ // if we can claim interface 4 we found a CH347F chip; if we can claim interface 2 we found CH347T chip
+ retval = libusb_claim_interface(ch347_handle, CH347F_MPHSI_INTERFACE);
+ if (retval != ERROR_OK) {
+ retval = libusb_claim_interface(ch347_handle, CH347T_MPHSI_INTERFACE);
+ if (retval != ERROR_OK) {
+ LOG_ERROR("CH347 unable to claim interface: %s", libusb_error_name(retval));
+ jtag_libusb_close(ch347_handle);
+ return retval;
+ }
+ ch347.chip_variant = CH347T;
+ } else {
+ ch347.chip_variant = CH347F;
+ }
+
+ char firmware_version;
+ retval = jtag_libusb_control_transfer(ch347_handle,
+ LIBUSB_ENDPOINT_IN | LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE,
+ VENDOR_VERSION, 0, 0, &firmware_version, sizeof(firmware_version),
+ USB_WRITE_TIMEOUT, NULL);
+ if (retval != ERROR_OK) {
+ LOG_ERROR("CH347 unable to get firmware version");
+ jtag_libusb_close(ch347_handle);
+ return retval;
+ }
+
+ char manufacturer[256 + 1];
+ if (libusb_get_string_descriptor_ascii(ch347_handle, ch347_device_descriptor.iManufacturer,
+ (unsigned char *)manufacturer, sizeof(manufacturer) - 1) < 0) {
+ strcpy(manufacturer, "(unknown)");
+ }
+ char product[256 + 1];
+ if (libusb_get_string_descriptor_ascii(ch347_handle, ch347_device_descriptor.iProduct,
+ (unsigned char *)product, sizeof(product) - 1) < 0) {
+ strcpy(product, "(unknown)");
+ }
+ char serial_number[256 + 1];
+ if (libusb_get_string_descriptor_ascii(ch347_handle, ch347_device_descriptor.iSerialNumber,
+ (unsigned char *)serial_number, sizeof(serial_number) - 1) < 0) {
+ strcpy(serial_number, "(unknown)");
+ }
+
+ LOG_INFO("CH347 %s from vendor %s with serial number %s found. (Chip version=%X.%2X, Firmware=0x%02X)",
+ product,
+ manufacturer,
+ serial_number,
+ (ch347_device_descriptor.bcdDevice >> 8) & 0xFF,
+ ch347_device_descriptor.bcdDevice & 0xFF,
+ firmware_version);
+
+ if (ch347.chip_variant == CH347T && ch347_device_descriptor.bcdDevice < BYTEWISE_MODE_VERSION) {
+ LOG_INFO("CH347T old version of the chip, JTAG only working in bitwise mode. For bytewise mode at least version %X.%X is needed.",
+ (BYTEWISE_MODE_VERSION >> 8) & 0xFF,
+ BYTEWISE_MODE_VERSION & 0xFF);
+ ch347.use_bitwise_mode = true;
+ } else {
+ ch347.use_bitwise_mode = false;
+ }
+
+ if (ch347.chip_variant == CH347T) {
+ if (swd_mode) {
+ ch347.swclk_5mhz_supported = ch347_device_descriptor.bcdDevice >= 0x544;
+
+ if (ch347_device_descriptor.bcdDevice < 0x441)
+ LOG_WARNING("CH347T version older than 4.41 probably does not support SWD transport");
+
+ if (ch347_device_descriptor.bcdDevice == 0x441)
+ LOG_WARNING("If CH347T version 4.41 cannot connect or SWD fails often, insert a resistor to SWDIO circuit");
+
+ } else if (ch347_device_descriptor.bcdDevice == 0x241) {
+ LOG_WARNING("CH347T version 2.41 has very weird clock timing, may not work with a slower JTAG device");
+ }
+
+ if (ch347_device_descriptor.bcdDevice < 0x544)
+ LOG_INFO("Please upgrade CH347T firmware to a production version >= 5.44");
+
+ } else if (ch347.chip_variant == CH347F) {
+ ch347.swclk_5mhz_supported = ch347_device_descriptor.bcdDevice >= 0x101;
+
+ if (ch347_device_descriptor.bcdDevice < 0x101)
+ LOG_INFO("Please upgrade CH347F firmware to a production version >= 1.1");
+ }
+
+ return ERROR_OK;
+}
+
+/**
+ * @brief CH347 Device Release Function
+ *
+ * @return ERROR_OK on success
+ */
+static int ch347_quit(void)
+{
+ // on close set the LED on, because the state without JTAG is on
+ ch347_activity_led_set(LED_ON);
+ int retval = ch347_cmd_transmit_queue();
+ jtag_libusb_close(ch347_handle);
+ LOG_DEBUG_IO("CH347 close");
+ return retval;
+}
+
+/**
+ * @brief Sends the CH347_CMD_JTAG_INIT (D0) command to get the JTAG
+ * interface initialized with the speed index or asking with special clock index 9
+ * for the LARGER_PACK mode support
+ *
+ * @param clock_index Clock index; special clock index 9 is used for checking
+ * if the device supports the LARGER_PACK mode
+ * @param supports_larger_pack_mode returns true if the device supports the LARGER_PACK mode
+ * for newer CH347 devices; false if the device supports only the older STANDARD_PACK mode
+ * @return ERROR_OK on success
+ */
+static int ch347_adapter_init(uint8_t clock_index, bool *supports_larger_pack_mode)
+{
+ int retval = ch347_cmd_start_next(CH347_CMD_JTAG_INIT);
+ if (retval != ERROR_OK)
+ return retval;
+
+ retval = ch347_scratchpad_add_byte(0);
+ if (retval != ERROR_OK)
+ return retval;
+
+ retval = ch347_scratchpad_add_byte(clock_index);
+ if (retval != ERROR_OK)
+ return retval;
+
+ for (int i = 0; i < 4; i++) {
+ retval = ch347_scratchpad_add_pin_byte();
+ if (retval != ERROR_OK)
+ return retval;
+ }
+
+ uint8_t mode;
+ retval = ch347_single_read_get_byte(0, &mode);
+ if (retval != ERROR_OK)
+ return retval;
+
+ *supports_larger_pack_mode = mode != 0;
+ return ERROR_OK;
+}
+
+/**
+ * @brief Sends the CH347_CMD_JTAG_INIT (D0) command to ask the JTAG
+ * interface with special clock index 9 for the LARGER_PACK mode support
+ *
+ * @param supports_larger_pack_mode returns true if the device supports the LARGER_PACK mode
+ * for newer CH347 devices; false if the device supports only the older STANDARD_PACK mode
+ * @return ERROR_OK on success
+ */
+static int ch347_adapter_supports_larger_pack_mode(bool *supports_larger_pack_mode)
+{
+ return ch347_adapter_init(CH347_CMD_INIT_GET_MODE_CLOCK_INDEX_VALUE, supports_larger_pack_mode);
+}
+
+/**
+ * @brief Sends the CH347_CMD_JTAG_INIT (D0) command to get the JTAG
+ * interface initialized with the speed index
+ *
+ * @param clock_index Clock index
+ * @return ERROR_OK on success
+ */
+static int ch347_adapter_set_speed(uint8_t clock_index)
+{
+ bool unused;
+ return ch347_adapter_init(clock_index, &unused);
+}
+
+/**
+ * @brief swd init function
+ * @param clock_divisor Divisor of base SWD frequency 1 MHz or 0 for fast 5 MHz clock
+ *
+ * @return ERROR_OK on success
+ */
+static int ch347_swd_init_cmd(uint8_t clock_divisor)
+{
+ int retval = ch347_cmd_start_next(CH347_CMD_SWD_INIT);
+ if (retval != ERROR_OK)
+ return retval;
+
+ uint8_t cmd_data[] = {0x40, 0x42, 0x0f, 0x00, clock_divisor, 0x00, 0x00, 0x00 };
+ retval = ch347_scratchpad_add_bytes(cmd_data, ARRAY_SIZE(cmd_data));
+ if (retval != ERROR_OK)
+ return retval;
+
+ /* TODO: CH347_CMD_SWD_INIT reads one data byte.
+ But how can we decide if SWD init was successfully executed?
+ Return an error code if init was failed */
+ uint8_t init_result = 0;
+ retval = ch347_single_read_get_byte(0, &init_result);
+ LOG_DEBUG("SWD init clk div %" PRIu8 ", result %02" PRIx8,
+ clock_divisor, init_result);
+ ch347_swd_context.clk_divisor = clock_divisor;
+ return retval;
+}
+
+/**
+ * @brief Initializes the JTAG interface and set CH347 TCK frequency
+ *
+ * @param speed_index speed index for JTAG_INIT command
+ * @return Success returns ERROR_OK, failed returns ERROR_FAIL
+ */
+static int ch347_speed_set(int speed_index)
+{
+ if (swd_mode)
+ return ch347_swd_init_cmd(speed_index);
+
+ int retval = ch347_adapter_set_speed(speed_index);
+ if (retval != ERROR_OK) {
+ LOG_ERROR("Couldn't set CH347 speed");
+ return retval;
+ }
+
+ return ERROR_OK;
+}
+
+/**
+ * @brief inits ch347.pack_size and ch347.max_len
+ *
+ * @return ERROR_OK on success
+ */
+static int ch347_init_pack_size(void)
+{
+ // already set?
+ if (ch347.pack_size != UNSET)
+ return ERROR_OK;
+
+ // set the lower limit for starting
+ ch347.max_len = MIN(USBC_PACKET_USBHS, LARGER_PACK_MAX_SIZE);
+ bool supports_larger_pack_mode;
+ int retval = ch347_adapter_supports_larger_pack_mode(&supports_larger_pack_mode);
+ if (retval != ERROR_OK)
+ return retval;
+
+ ch347.pack_size = supports_larger_pack_mode ? LARGER_PACK : STANDARD_PACK;
+ ch347.max_len = ch347.pack_size == STANDARD_PACK || ch347.use_bitwise_mode ?
+ USBC_PACKET_USBHS : LARGER_PACK_MAX_SIZE;
+ return ERROR_OK;
+}
+
+/**
+ * @brief returns the speed in kHz by the give speed index
+ *
+ * @param speed_idx CH347 speed index
+ * @param khz Output of the speed in kHz
+ * @return ERROR_OK on success
+ */
+static int ch347_speed_get(int speed_idx, int *khz)
+{
+ if (swd_mode) {
+ if (speed_idx)
+ *khz = DIV_ROUND_UP(CH347_SWD_CLOCK_BASE, speed_idx);
+ else
+ *khz = CH347_SWD_CLOCK_MAX;
+ return ERROR_OK;
+ }
+
+ int retval = ch347_init_pack_size();
+ if (retval != ERROR_OK)
+ return retval;
+ const int *speeds = ch347.pack_size == STANDARD_PACK ?
+ ch347_standard_pack_clock_speeds : ch347_larger_pack_clock_speeds;
+ *khz = speeds[speed_idx];
+ return ERROR_OK;
+}
+
+/**
+ * @brief multiplies the input speed by 1000
+ *
+ * @param khz Speed in kHz
+ * @param speed_idx CH347 speed index
+ * @return ERROR_OK at success; ERROR_FAIL if khz is zero
+ */
+static int ch347_speed_get_index(int khz, int *speed_idx)
+{
+ if (khz == 0) {
+ LOG_ERROR("Adaptive clocking not supported");
+ return ERROR_FAIL;
+ }
+
+ if (swd_mode) {
+ if (khz >= CH347_SWD_CLOCK_MAX && ch347.swclk_5mhz_supported) {
+ *speed_idx = 0;
+ } else {
+ // Don't allow too low clk speeds: packet processing is limited to ~8 msec
+ // or triggers host USB disconnect
+ *speed_idx = MIN(DIV_ROUND_UP(CH347_SWD_CLOCK_BASE, khz),
+ (int)CH347_SWD_CLOCK_MAX_DIVISOR);
+ }
+ return ERROR_OK;
+ }
+
+ // when checking with speed index 9 we can see if the device supports STANDARD_PACK or LARGER_PACK mode
+ int retval = ch347_init_pack_size();
+ if (retval != ERROR_OK)
+ return retval;
+ // depending on pack size there are different fixed clock speeds possible
+ const int *speeds = ch347.pack_size == STANDARD_PACK ?
+ ch347_standard_pack_clock_speeds : ch347_larger_pack_clock_speeds;
+ int length = ch347.pack_size == STANDARD_PACK ?
+ ARRAY_SIZE(ch347_standard_pack_clock_speeds) : ARRAY_SIZE(ch347_larger_pack_clock_speeds);
+ int idx = -1;
+ int lower_bound = 0;
+ // find the suitable speed index
+ for (int i = 0; i < length; i++) {
+ if (khz >= lower_bound && khz <= speeds[i]) {
+ idx = i;
+ break;
+ }
+ lower_bound = speeds[i];
+ }
+ // too high! => use max possible speed
+ if (idx == -1) {
+ LOG_INFO("Speed %d kHz is higher than highest speed of %d kHz. Using %d khz!",
+ khz, speeds[length - 1], speeds[length - 1]);
+ idx = length - 1;
+ } else if (speeds[idx] != khz) {
+ LOG_INFO("Requested speed of %d kHz is not possible. Using the next higher speed of %d kHz!",
+ khz, speeds[idx]);
+ }
+ *speed_idx = idx;
+ return ERROR_OK;
+}
+
+/**
+ * @brief The command handler for setting the device usb vid/pid
+ *
+ * @return ERROR_OK at success; ERROR_COMMAND_SYNTAX_ERROR otherwise
+ */
+COMMAND_HANDLER(ch347_handle_vid_pid_command)
+{
+ if (CMD_ARGC < 2)
+ return ERROR_COMMAND_SYNTAX_ERROR;
+
+ for (int i = 0; i < (int)(MIN(CMD_ARGC, ARRAY_SIZE(custom_ch347_pids))); i += 2) {
+ COMMAND_PARSE_NUMBER(u16, CMD_ARGV[i], custom_ch347_vids[i / 2]);
+ COMMAND_PARSE_NUMBER(u16, CMD_ARGV[i + 1], custom_ch347_pids[i / 2]);
+ }
+
+ return ERROR_OK;
+}
+
+/**
+ * @brief The command handler for setting the device description that should be found
+ *
+ * @return ERROR_OK at success; ERROR_COMMAND_SYNTAX_ERROR otherwise
+ */
+COMMAND_HANDLER(ch347_handle_device_desc_command)
+{
+ if (CMD_ARGC != 1)
+ return ERROR_COMMAND_SYNTAX_ERROR;
+
+ free(ch347_device_desc);
+ ch347_device_desc = strdup(CMD_ARGV[0]);
+ return ERROR_OK;
+}
+
+static const struct command_registration ch347_subcommand_handlers[] = {
+ {
+ .name = "vid_pid",
+ .handler = &ch347_handle_vid_pid_command,
+ .mode = COMMAND_CONFIG,
+ .help = "the vendor ID and product ID of the CH347 device",
+ .usage = "(vid pid)*",
+ },
+ {
+ .name = "device_desc",
+ .handler = &ch347_handle_device_desc_command,
+ .mode = COMMAND_CONFIG,
+ .help = "set the USB device description of the CH347 device",
+ .usage = "description_string",
+ },
+ COMMAND_REGISTRATION_DONE
+};
+
+static const struct command_registration ch347_command_handlers[] = {
+ {
+ .name = "ch347",
+ .mode = COMMAND_ANY,
+ .help = "perform ch347 management",
+ .chain = ch347_subcommand_handlers,
+ .usage = "",
+ },
+ COMMAND_REGISTRATION_DONE
+};
+
+/**
+ * @brief Configure which GPIO pin is used as the activity LED.
+ *
+ * Updates the global activity LED GPIO pin and polarity settings
+ * based on the provided configuration. If the given GPIO is not
+ * usable, the function returns without making changes.
+ *
+ * @param led_config Pointer to the GPIO configuration structure for the LED pin
+ */
+static void ch347_configure_activity_led(const struct adapter_gpio_config *led_config)
+{
+ uint8_t gpio = led_config->gpio_num;
+ if (gpio >= GPIO_CNT || (BIT(gpio) & USEABLE_GPIOS) == 0)
+ return;
+
+ ch347_activity_led_gpio_pin = gpio;
+ ch347_activity_led_active_high = !led_config->active_low;
+}
+
+/**
+ * @brief CH347 Initialization function
+ *
+ * @return ERROR_OK on success
+ */
+static int ch347_init(void)
+{
+ int retval = ch347_open_device();
+
+ if (retval != ERROR_OK) {
+ LOG_ERROR("CH347 open error");
+ return retval;
+ }
+
+ LOG_DEBUG_IO("CH347 open success");
+
+ // CH347 JTAG init
+ ch347.tck_pin = TCK_L;
+ ch347.tms_pin = TMS_H;
+ ch347.tdi_pin = TDI_L;
+ ch347.trst_pin = TRST_H;
+ INIT_LIST_HEAD(&ch347.cmd_queue);
+ INIT_LIST_HEAD(&ch347.scan_queue);
+
+ ch347.pack_size = UNSET;
+
+ ch347_configure_activity_led(&adapter_gpio_get_config()[ADAPTER_GPIO_IDX_LED]);
+
+ if (!swd_mode) {
+ tap_set_state(TAP_RESET);
+ } else {
+ retval = ch347_init_pack_size();
+ if (retval != ERROR_OK)
+ return retval;
+
+ retval = ch347_swd_init_cmd(1);
+ }
+ return retval;
+}
+
+/**
+ * @brief Initialization for the swd mode
+ *
+ * @return Always ERROR_OK
+ */
+static int ch347_swd_init(void)
+{
+ LOG_INFO("CH347 SWD mode enabled");
+ swd_mode = true;
+ memset(&ch347_swd_context, 0, sizeof(ch347_swd_context));
+
+ INIT_LIST_HEAD(&ch347_swd_context.send_cmd_head);
+ INIT_LIST_HEAD(&ch347_swd_context.free_cmd_head);
+
+ ch347_swd_context.queued_retval = ERROR_OK;
+ // 0XE8 + 2byte len + N byte cmds
+ ch347_swd_context.send_len = CH347_CMD_HEADER;
+ // 0XE8 + 2byte len + N byte ack + data
+ ch347_swd_context.need_recv_len = CH347_CMD_HEADER;
+ struct ch347_swd_io *pswd_io = ch347_swd_context.ch347_cmd_buf;
+ for (int i = 0; i < CH347_MAX_CMD_BUF; i++, pswd_io++) {
+ INIT_LIST_HEAD(&pswd_io->list_entry);
+ list_add_tail(&pswd_io->list_entry, &ch347_swd_context.free_cmd_head);
+ }
+ return ERROR_OK;
+}
+
+static struct ch347_swd_io *ch347_get_one_swd_io(void)
+{
+ struct ch347_swd_io *pswd_io;
+ if (list_empty(&ch347_swd_context.free_cmd_head))
+ return NULL;
+
+ pswd_io = list_first_entry(&ch347_swd_context.free_cmd_head,
+ struct ch347_swd_io, list_entry);
+ list_del_init(&pswd_io->list_entry);
+ pswd_io->cmd = 0;
+ pswd_io->usb_cmd = CH347_CMD_SWD_SEQ_W;
+ pswd_io->dst = NULL;
+ return pswd_io;
+}
+
+static int ch347_swd_queue_flush(void)
+{
+ int length = ch347_swd_context.send_len;
+ ch347_swd_context.send_buf[0] = CH347_CMD_SWD;
+ h_u16_to_le(&ch347_swd_context.send_buf[1], length - CH347_CMD_HEADER);
+ int retval = ch347_write_data(ch347_swd_context.send_buf, &length);
+ if (retval != ERROR_OK) {
+ ch347_swd_context.queued_retval = retval;
+ LOG_DEBUG("CH347WriteData error");
+ return retval;
+ }
+
+ ch347_swd_context.recv_len = 0;
+ length = ch347_swd_context.need_recv_len;
+ retval = ch347_read_data(&ch347_swd_context.recv_buf[ch347_swd_context.recv_len], &length);
+ if (retval != ERROR_OK) {
+ ch347_swd_context.queued_retval = retval;
+ LOG_DEBUG("CH347ReadData error");
+ return retval;
+ }
+
+ ch347_swd_context.recv_len += length;
+ if (ch347_swd_context.need_recv_len > ch347_swd_context.recv_len) {
+ LOG_ERROR("write/read failed %d %d",
+ ch347_swd_context.recv_len,
+ ch347_swd_context.need_recv_len);
+ retval = ERROR_FAIL;
+ }
+
+ return retval;
+}
+
+static void ch347_write_swd_reg(uint8_t cmd, const uint32_t out)
+{
+ ch347_swd_context.send_buf[ch347_swd_context.send_len++] = CH347_CMD_SWD_REG_W;
+ // 8bit + 32bit +1bit
+ ch347_swd_context.send_buf[ch347_swd_context.send_len++] = 0x29;
+ ch347_swd_context.send_buf[ch347_swd_context.send_len++] = 0x00;
+ ch347_swd_context.send_buf[ch347_swd_context.send_len++] = cmd;
+ h_u32_to_le(&ch347_swd_context.send_buf[ch347_swd_context.send_len], out);
+ ch347_swd_context.send_len += 4;
+ ch347_swd_context.send_buf[ch347_swd_context.send_len++] = parity_u32(out);
+ // 0xA0 + 1 byte(3bit ACK)
+ ch347_swd_context.need_recv_len += (1 + 1);
+ ch347_swd_context.total_swd_clk += 46;
+}
+
+static void ch347_write_spec_seq(const uint8_t *out, uint8_t out_len)
+{
+ ch347_swd_context.send_buf[ch347_swd_context.send_len++] =
+ CH347_CMD_SWD_SEQ_W;
+ ch347_swd_context.send_buf[ch347_swd_context.send_len++] = out_len;
+ ch347_swd_context.send_buf[ch347_swd_context.send_len++] = 0x00;
+ for (uint8_t i = 0; i < DIV_ROUND_UP(out_len, 8); i++)
+ ch347_swd_context.send_buf[ch347_swd_context.send_len++] = out ? out[i] : 0x00;
+ ch347_swd_context.need_recv_len += 1; // 0xA1
+ ch347_swd_context.total_swd_clk += out_len;
+}
+
+static void ch347_read_swd_reg(uint8_t cmd)
+{
+ ch347_swd_context.send_buf[ch347_swd_context.send_len++] = CH347_CMD_SWD_REG_R;
+ ch347_swd_context.send_buf[ch347_swd_context.send_len++] = 0x22;
+ ch347_swd_context.send_buf[ch347_swd_context.send_len++] = 0x00;
+ ch347_swd_context.send_buf[ch347_swd_context.send_len++] = cmd;
+ // 0xA2 + 1 byte(3bit ACK) + 4 byte(data) + 1 byte(1bit parity+1bit trn)
+ ch347_swd_context.need_recv_len += 1 + 1 + 4 + 1;
+ ch347_swd_context.total_swd_clk += 46;
+}
+
+static int ch347_swd_switch_out(enum swd_special_seq seq, const uint8_t *out, unsigned int out_len)
+{
+ if ((ch347_swd_context.send_len + (1 + 2 + DIV_ROUND_UP(out_len, 8))) > CH347_MAX_SEND_BUF)
+ return ERROR_FAIL;
+ if ((ch347_swd_context.need_recv_len + 2) > CH347_MAX_RECV_BUF)
+ return ERROR_FAIL;
+
+ struct ch347_swd_io *pswd_io = ch347_get_one_swd_io();
+ if (pswd_io) {
+ ch347_write_spec_seq(out, out_len);
+ list_add_tail(&pswd_io->list_entry, &ch347_swd_context.send_cmd_head);
+ return ERROR_OK;
+ } else {
+ return ERROR_FAIL;
+ }
+}
+
+// check read/write REG can fill in remaining buff
+static bool ch347_chk_buf_size(uint8_t cmd, uint32_t ap_delay_clk)
+{
+ bool flush = false;
+ int send_len = ch347_swd_context.send_len;
+ int recv_len = ch347_swd_context.need_recv_len;
+ int len;
+ do {
+ if (cmd & SWD_CMD_RNW) {
+ len = 1 + 1 + 1 + 1; // 0xA2 + len + rev + cmd
+ if (send_len + len > CH347_MAX_SEND_BUF)
+ break;
+ send_len += len;
+ len = 1 + 1 + 4 + 1;
+ /* 0xA2 + 1byte(3bit ack) + 4byte(data) +
+ 1byte(1bit parity+1bit trn) */
+ if (recv_len + len > CH347_MAX_RECV_BUF)
+ break;
+ recv_len += len;
+ } else { // write reg
+ len = 1 + 1 + 1 + 1 + 4 + 1;
+ // 0xA0 + len + rev + cmd +data + parity
+ if (send_len + len > CH347_MAX_SEND_BUF)
+ break;
+ send_len += len;
+ len = 1 + 1; // 0xA0 + 1byte(3bit ack)
+ if (recv_len + len > CH347_MAX_RECV_BUF)
+ break;
+ recv_len += len;
+ }
+ if (cmd & SWD_CMD_APNDP) {
+ len = 1 + 1 + 1 + DIV_ROUND_UP(ap_delay_clk, 8);
+ // 0xA1 + Len + rev + n byte(delay)
+ if (send_len + len > CH347_MAX_SEND_BUF)
+ break;
+ len = 1; // 0xA1
+ if ((recv_len + len) > CH347_MAX_RECV_BUF)
+ break;
+ }
+ // swd packet requests
+ flush = true;
+ } while (false);
+
+ return flush;
+}
+
+static int ch347_swd_run_queue_inner(void);
+
+static int ch347_swd_send_idle(uint32_t ap_delay_clk)
+{
+ bool run_q = false;
+ struct ch347_swd_io *pswd_io = NULL;
+ unsigned int max_processing_clk = ch347_swd_context.clk_divisor
+ ? CH347_MAX_PROCESSING_US / ch347_swd_context.clk_divisor
+ : CH347_MAX_PROCESSING_US * 5;
+ bool more_q_runs =
+ 1 + 1 + 1 + DIV_ROUND_UP(ap_delay_clk, 8) > CH347_MAX_SEND_BUF
+ && ap_delay_clk > max_processing_clk;
+
+ if (ch347_swd_context.sent_cmd_count) {
+ unsigned int expected_total_clk = ch347_swd_context.total_swd_clk + ap_delay_clk;
+ unsigned int expected_send_len = ch347_swd_context.send_len
+ + 1 + 1 + 1 + DIV_ROUND_UP(ap_delay_clk, 8);
+ // 0xA1 + Len + rev + n byte(delay)
+ unsigned int expected_recv_len = ch347_swd_context.need_recv_len + 1;
+ // 0xA1
+ unsigned int expected_time = ch347_swd_context.clk_divisor
+ ? expected_total_clk * ch347_swd_context.clk_divisor
+ : expected_total_clk / 5;
+ if (expected_time > CH347_MAX_PROCESSING_US
+ || expected_send_len > CH347_MAX_SEND_BUF
+ || expected_recv_len > CH347_MAX_RECV_BUF) {
+ int send_room = CH347_MAX_SEND_BUF - ch347_swd_context.send_len - 1 - 1 - 1;
+ if (more_q_runs
+ && send_room > 0
+ && expected_recv_len <= CH347_MAX_RECV_BUF
+ && ch347_swd_context.total_swd_clk < max_processing_clk) {
+ pswd_io = ch347_get_one_swd_io();
+ if (pswd_io) {
+ // fill the rest of queue/time by part of delay
+ unsigned int this_delay_clk = MIN(ap_delay_clk, 255);
+ if ((unsigned int)send_room * 8 < this_delay_clk)
+ this_delay_clk = send_room * 8;
+ if (max_processing_clk - ch347_swd_context.total_swd_clk < this_delay_clk)
+ this_delay_clk = max_processing_clk - ch347_swd_context.total_swd_clk;
+ LOG_DEBUG_IO("partial delay %u clk", this_delay_clk);
+ ch347_write_spec_seq(NULL, this_delay_clk);
+ list_add_tail(&pswd_io->list_entry, &ch347_swd_context.send_cmd_head);
+ ap_delay_clk -= this_delay_clk;
+ }
+ }
+ run_q = true;
+ }
+ }
+
+ do {
+ if (!run_q)
+ pswd_io = ch347_get_one_swd_io();
+
+ if (!pswd_io) {
+ int retval = ch347_swd_run_queue_inner();
+ if (retval != ERROR_OK)
+ return retval;
+
+ pswd_io = ch347_get_one_swd_io();
+ if (!pswd_io) {
+ LOG_ERROR("ch347 SWD queue not empty after ch347_swd_run_queue");
+ ch347_swd_context.queued_retval = ERROR_FAIL;
+ return ERROR_FAIL;
+ }
+ }
+
+ unsigned int send_room = CH347_MAX_SEND_BUF - 1 - 1 - 1;
+ unsigned int this_delay_clk = MIN(ap_delay_clk, 255);
+ if (send_room * 8 < this_delay_clk)
+ this_delay_clk = send_room * 8;
+ if (max_processing_clk < this_delay_clk)
+ this_delay_clk = max_processing_clk;
+ LOG_DEBUG_IO("delay %u clk", this_delay_clk);
+ ch347_write_spec_seq(NULL, this_delay_clk);
+ list_add_tail(&pswd_io->list_entry, &ch347_swd_context.send_cmd_head);
+ ap_delay_clk -= this_delay_clk;
+ run_q = true;
+ pswd_io = NULL;
+ } while (ap_delay_clk);
+ return ERROR_OK;
+}
+
+static int ch347_swd_run_queue_inner(void)
+{
+ LOG_DEBUG_IO("Executing %u queued transactions", ch347_swd_context.sent_cmd_count);
+ if (ch347_swd_context.queued_retval != ERROR_OK) {
+ LOG_DEBUG_IO("Skipping due to previous errors: %d", ch347_swd_context.queued_retval);
+ goto skip;
+ }
+
+ int retval = ch347_swd_queue_flush();
+ if (retval != ERROR_OK)
+ return retval;
+
+ if (ch347_swd_context.queued_retval != ERROR_OK) {
+ LOG_ERROR("CH347 usb write/read failed - queued_retval");
+ goto skip;
+ }
+ uint8_t *recv_buf = ch347_swd_context.recv_buf;
+ int recv_len = 0;
+ if (recv_buf[recv_len++] != CH347_CMD_SWD) { // 0XE8
+ ch347_swd_context.queued_retval = ERROR_FAIL;
+ LOG_ERROR("CH347 usb write/read failed - not CH347_CMD_SWD");
+ goto skip;
+ }
+
+ int cmds_len = le_to_h_u16(&recv_buf[recv_len]);
+ recv_len += 2; // cmds_len
+ if ((cmds_len + CH347_CMD_HEADER) > ch347_swd_context.recv_len) {
+ ch347_swd_context.queued_retval = ERROR_FAIL;
+ LOG_ERROR("CH347 usb write/read failed - too long");
+ goto skip;
+ }
+
+ struct list_head *tmp;
+ struct list_head *pos;
+ struct ch347_swd_io *pswd_io;
+
+ list_for_each_safe(pos, tmp, &ch347_swd_context.send_cmd_head) {
+ pswd_io = list_entry(pos, struct ch347_swd_io, list_entry);
+ if (pswd_io->usb_cmd == CH347_CMD_SWD_SEQ_W) {
+ if (recv_buf[recv_len++] != CH347_CMD_SWD_SEQ_W) {
+ ch347_swd_context.queued_retval = ERROR_FAIL;
+ LOG_ERROR("CH347 usb write/read failed - not CH347_CMD_SWD_SEQ_W");
+ goto skip;
+ }
+ } else { // read/write Reg
+ uint32_t ack;
+ bool check_ack;
+ // read Reg
+ if (recv_buf[recv_len] == CH347_CMD_SWD_REG_R) {
+ recv_len++;
+ ack = buf_get_u32(&recv_buf[recv_len++], 0, 3);
+ /* Devices do not reply to DP_TARGETSEL write
+ cmd, ignore received ack */
+ check_ack = swd_cmd_returns_ack(pswd_io->cmd);
+ if (pswd_io->cmd & SWD_CMD_RNW) {
+ uint32_t data = buf_get_u32(&recv_buf[recv_len], 0, 32);
+
+ LOG_CUSTOM_LEVEL((check_ack && ack != SWD_ACK_OK)
+ ? LOG_LVL_DEBUG : LOG_LVL_DEBUG_IO,
+ "%s%s %s read reg %X = %08" PRIx32,
+ check_ack ? "" : "ack ignored ",
+ ack == SWD_ACK_OK ? "OK" :
+ ack == SWD_ACK_WAIT ? "WAIT" :
+ ack == SWD_ACK_FAULT ? "FAULT" : "JUNK",
+ pswd_io->cmd & SWD_CMD_APNDP ? "AP" : "DP",
+ (pswd_io->cmd & SWD_CMD_A32) >> 1,
+ data);
+
+ if (ack != SWD_ACK_OK && check_ack) {
+ ch347_swd_context.queued_retval = swd_ack_to_error_code(ack);
+ goto skip;
+ }
+
+ uint32_t parity = buf_get_u32(&recv_buf[recv_len], 32, 1);
+ if (parity != (uint32_t)parity_u32(data)) {
+ LOG_ERROR("SWD Read data parity mismatch");
+ ch347_swd_context.queued_retval = ERROR_FAIL;
+ goto skip;
+ }
+
+ if (pswd_io->dst)
+ *pswd_io->dst = data;
+ } else {
+ ch347_swd_context.queued_retval = ERROR_FAIL;
+ LOG_ERROR("CH347 usb write/read failed - not SWD_CMD_RNW");
+ goto skip;
+ }
+ recv_len += 5;
+ } else if (recv_buf[recv_len] == CH347_CMD_SWD_REG_W) {
+ recv_len++;
+ ack = buf_get_u32(&recv_buf[recv_len++], 0, 3);
+ /* Devices do not reply to DP_TARGETSEL write
+ cmd, ignore received ack */
+ check_ack = swd_cmd_returns_ack(pswd_io->cmd);
+
+ LOG_CUSTOM_LEVEL((check_ack && ack != SWD_ACK_OK)
+ ? LOG_LVL_DEBUG : LOG_LVL_DEBUG_IO,
+ "%s%s %s write reg %X = %08" PRIx32,
+ check_ack ? "" : "ack ignored ",
+ ack == SWD_ACK_OK ? "OK" :
+ ack == SWD_ACK_WAIT ? "WAIT" :
+ ack == SWD_ACK_FAULT ? "FAULT" : "JUNK",
+ pswd_io->cmd & SWD_CMD_APNDP ? "AP" : "DP",
+ (pswd_io->cmd & SWD_CMD_A32) >> 1,
+ pswd_io->value);
+
+ if (ack != SWD_ACK_OK && check_ack) {
+ ch347_swd_context.queued_retval = swd_ack_to_error_code(ack);
+ goto skip;
+ }
+ } else {
+ ch347_swd_context.queued_retval = ERROR_FAIL;
+ LOG_ERROR("CH347 usb write/read failed recv_len = %d", recv_len);
+ goto skip;
+ }
+ }
+ list_del_init(&pswd_io->list_entry);
+ list_add_tail(&pswd_io->list_entry,
+ &ch347_swd_context.free_cmd_head);
+ }
+
+skip:
+ if (!list_empty(&ch347_swd_context.send_cmd_head)) {
+ list_for_each_safe(pos, tmp, &ch347_swd_context.send_cmd_head) {
+ pswd_io = list_entry(pos, struct ch347_swd_io, list_entry);
+ list_del_init(&pswd_io->list_entry);
+ list_add_tail(&pswd_io->list_entry,
+ &ch347_swd_context.free_cmd_head);
+ }
+ }
+
+ // 0xE8 + 2byte len
+ ch347_swd_context.send_len = CH347_CMD_HEADER;
+ // 0xE8 + 2byte len
+ ch347_swd_context.need_recv_len = CH347_CMD_HEADER;
+ ch347_swd_context.recv_len = 0;
+ ch347_swd_context.sent_cmd_count = 0;
+ ch347_swd_context.total_swd_clk = 0;
+ retval = ch347_swd_context.queued_retval;
+ ch347_swd_context.queued_retval = ERROR_OK;
+ return retval;
+}
+
+static int ch347_swd_run_queue(void)
+{
+ /* A transaction must be followed by another transaction or at least 8
+ idle cycles to ensure that data is clocked through the AP. */
+ int retval = ch347_swd_send_idle(8);
+ if (retval != ERROR_OK)
+ return retval;
+
+ return ch347_swd_run_queue_inner();
+}
+
+static int ch347_swd_queue_cmd(uint8_t cmd, uint32_t *dst, uint32_t data, uint32_t ap_delay_clk)
+{
+ int retval = ERROR_OK;
+ bool run_q = false;
+ if (ch347_swd_context.sent_cmd_count) {
+ unsigned int expected_total_clk = ch347_swd_context.total_swd_clk
+ + 46 // SWD transaction
+ + ap_delay_clk
+ + 8; // 8 idle cycles at the end of queue
+ unsigned int expected_time = ch347_swd_context.clk_divisor
+ ? expected_total_clk * ch347_swd_context.clk_divisor
+ : expected_total_clk / 5;
+ if (expected_time > CH347_MAX_PROCESSING_US) {
+ LOG_DEBUG_IO("Expected queue run %u cycles, with this cmd %u",
+ ch347_swd_context.total_swd_clk, expected_total_clk);
+ run_q = true;
+ } else if (!ch347_chk_buf_size(cmd, ap_delay_clk)) {
+ run_q = true;
+ }
+ }
+
+ struct ch347_swd_io *pswd_io = NULL;
+ if (!run_q)
+ pswd_io = ch347_get_one_swd_io();
+
+ if (!pswd_io) {
+ retval = ch347_swd_run_queue_inner();
+ if (retval != ERROR_OK)
+ return retval;
+
+ pswd_io = ch347_get_one_swd_io();
+ if (!pswd_io) {
+ LOG_ERROR("ch347 SWD queue not empty after ch347_swd_run_queue");
+ ch347_swd_context.queued_retval = ERROR_FAIL;
+ return ERROR_FAIL;
+ }
+ }
+
+ pswd_io->cmd = cmd | SWD_CMD_START | SWD_CMD_PARK;
+
+ if (pswd_io->cmd & SWD_CMD_RNW) {
+ pswd_io->usb_cmd = CH347_CMD_SWD_REG_R;
+ pswd_io->dst = dst;
+ ch347_read_swd_reg(pswd_io->cmd);
+ } else {
+ pswd_io->usb_cmd = CH347_CMD_SWD_REG_W;
+ pswd_io->value = data;
+ ch347_write_swd_reg(pswd_io->cmd, data);
+ }
+
+ ch347_swd_context.sent_cmd_count++;
+ list_add_tail(&pswd_io->list_entry, &ch347_swd_context.send_cmd_head);
+
+ // Insert idle cycles after AP accesses to avoid WAIT
+ if (ap_delay_clk)
+ retval = ch347_swd_send_idle(ap_delay_clk);
+
+ return retval;
+}
+
+static int ch347_swd_switch_seq(enum swd_special_seq seq)
+{
+ switch (seq) {
+ case LINE_RESET:
+ LOG_DEBUG("SWD line reset");
+ return ch347_swd_switch_out(seq, swd_seq_line_reset, swd_seq_line_reset_len);
+ case JTAG_TO_SWD:
+ LOG_DEBUG("JTAG-to-SWD");
+ return ch347_swd_switch_out(seq, swd_seq_jtag_to_swd, swd_seq_jtag_to_swd_len);
+ case JTAG_TO_DORMANT:
+ LOG_DEBUG("JTAG-to-DORMANT");
+ return ch347_swd_switch_out(seq, swd_seq_jtag_to_dormant, swd_seq_jtag_to_dormant_len);
+ case SWD_TO_JTAG:
+ LOG_DEBUG("SWD-to-JTAG");
+ return ch347_swd_switch_out(seq, swd_seq_swd_to_jtag, swd_seq_swd_to_jtag_len);
+ case SWD_TO_DORMANT:
+ LOG_DEBUG("SWD-to-DORMANT");
+ return ch347_swd_switch_out(seq, swd_seq_swd_to_dormant, swd_seq_swd_to_dormant_len);
+ case DORMANT_TO_SWD:
+ LOG_DEBUG("DORMANT-to-SWD");
+ return ch347_swd_switch_out(seq, swd_seq_dormant_to_swd, swd_seq_dormant_to_swd_len);
+ case DORMANT_TO_JTAG:
+ LOG_DEBUG("DORMANT-to-JTAG");
+ return ch347_swd_switch_out(seq, swd_seq_dormant_to_jtag, swd_seq_dormant_to_jtag_len);
+ default:
+ LOG_ERROR("Sequence %d not supported", seq);
+ return ERROR_FAIL;
+ }
+}
+
+static void ch347_swd_read_reg(uint8_t cmd, uint32_t *value, uint32_t ap_delay_clk)
+{
+ assert(cmd & SWD_CMD_RNW);
+ int retval = ch347_swd_queue_cmd(cmd, value, 0, ap_delay_clk);
+ if (retval != ERROR_OK)
+ ch347_swd_context.queued_retval = retval;
+}
+
+static void ch347_swd_write_reg(uint8_t cmd, uint32_t value, uint32_t ap_delay_clk)
+{
+ assert(!(cmd & SWD_CMD_RNW));
+ int retval = ch347_swd_queue_cmd(cmd, NULL, value, ap_delay_clk);
+ if (retval != ERROR_OK)
+ ch347_swd_context.queued_retval = retval;
+}
+
+static const struct swd_driver ch347_swd = {
+ .init = ch347_swd_init,
+ .switch_seq = ch347_swd_switch_seq,
+ .read_reg = ch347_swd_read_reg,
+ .write_reg = ch347_swd_write_reg,
+ .run = ch347_swd_run_queue,
+};
+
+static struct jtag_interface ch347_interface = {
+ .supported = DEBUG_CAP_TMS_SEQ,
+ .execute_queue = ch347_execute_queue,
+};
+
+struct adapter_driver ch347_adapter_driver = {
+ .name = "ch347",
+ .transport_ids = TRANSPORT_JTAG | TRANSPORT_SWD,
+ .transport_preferred_id = TRANSPORT_JTAG,
+ .commands = ch347_command_handlers,
+
+ .init = ch347_init,
+ .quit = ch347_quit,
+ .reset = ch347_reset,
+ .speed = ch347_speed_set,
+ .khz = ch347_speed_get_index,
+ .speed_div = ch347_speed_get,
+
+ .jtag_ops = &ch347_interface,
+ .swd_ops = &ch347_swd,
+};
diff --git a/src/jtag/drivers/cmsis_dap.c b/src/jtag/drivers/cmsis_dap.c
index 2bfcfcc2b0..9f60a5ede4 100644
--- a/src/jtag/drivers/cmsis_dap.c
+++ b/src/jtag/drivers/cmsis_dap.c
@@ -37,7 +37,8 @@
#include
#include "cmsis_dap.h"
-#include "libusb_helper.h"
+
+#define TIMEOUT_MS 6000
/* Create a dummy backend for 'backend' command if real one does not build */
#if BUILD_CMSIS_DAP_USB == 0
@@ -52,9 +53,16 @@ const struct cmsis_dap_backend cmsis_dap_hid_backend = {
};
#endif
+#if BUILD_CMSIS_DAP_TCP == 0
+const struct cmsis_dap_backend cmsis_dap_tcp_backend = {
+ .name = "tcp"
+};
+#endif
+
static const struct cmsis_dap_backend *const cmsis_dap_backends[] = {
&cmsis_dap_usb_backend,
&cmsis_dap_hid_backend,
+ &cmsis_dap_tcp_backend,
};
/* USB Config */
@@ -76,6 +84,7 @@ static uint16_t cmsis_dap_vid[MAX_USB_IDS + 1] = { 0 };
static uint16_t cmsis_dap_pid[MAX_USB_IDS + 1] = { 0 };
static int cmsis_dap_backend = -1;
static bool swd_mode;
+static bool cmsis_dap_quirk_mode; /* enable expensive workarounds */
/* CMSIS-DAP General Commands */
#define CMD_DAP_INFO 0x00
@@ -355,12 +364,12 @@ static int cmsis_dap_xfer(struct cmsis_dap *dap, int txlen)
}
uint8_t current_cmd = dap->command[0];
- int retval = dap->backend->write(dap, txlen, LIBUSB_TIMEOUT_MS);
+ int retval = dap->backend->write(dap, txlen, TIMEOUT_MS);
if (retval < 0)
return retval;
/* get reply */
- retval = dap->backend->read(dap, LIBUSB_TIMEOUT_MS, CMSIS_DAP_BLOCKING);
+ retval = dap->backend->read(dap, TIMEOUT_MS, CMSIS_DAP_BLOCKING);
if (retval < 0)
return retval;
@@ -864,13 +873,13 @@ static void cmsis_dap_swd_write_from_queue(struct cmsis_dap *dap)
}
}
- int retval = dap->backend->write(dap, idx, LIBUSB_TIMEOUT_MS);
+ int retval = dap->backend->write(dap, idx, TIMEOUT_MS);
if (retval < 0) {
queued_retval = retval;
goto skip;
}
- unsigned int packet_count = dap->quirk_mode ? 1 : dap->packet_count;
+ unsigned int packet_count = cmsis_dap_quirk_mode ? 1 : dap->packet_count;
dap->pending_fifo_put_idx = (dap->pending_fifo_put_idx + 1) % packet_count;
dap->pending_fifo_block_count++;
if (dap->pending_fifo_block_count > packet_count)
@@ -905,7 +914,7 @@ static void cmsis_dap_swd_read_process(struct cmsis_dap *dap, enum cmsis_dap_blo
}
/* get reply */
- retval = dap->backend->read(dap, LIBUSB_TIMEOUT_MS, blocking);
+ retval = dap->backend->read(dap, TIMEOUT_MS, blocking);
bool timeout = (retval == ERROR_TIMEOUT_REACHED || retval == 0);
if (timeout && blocking == CMSIS_DAP_NON_BLOCKING)
return;
@@ -990,7 +999,7 @@ static void cmsis_dap_swd_read_process(struct cmsis_dap *dap, enum cmsis_dap_blo
skip:
block->transfer_count = 0;
- if (!dap->quirk_mode && dap->packet_count > 1)
+ if (!cmsis_dap_quirk_mode && dap->packet_count > 1)
dap->pending_fifo_get_idx = (dap->pending_fifo_get_idx + 1) % dap->packet_count;
dap->pending_fifo_block_count--;
}
@@ -1086,7 +1095,7 @@ static void cmsis_dap_swd_queue_cmd(uint8_t cmd, uint32_t *dst, uint32_t data)
/* Not enough room in the queue. Run the queue. */
cmsis_dap_swd_write_from_queue(cmsis_dap_handle);
- unsigned int packet_count = cmsis_dap_handle->quirk_mode ? 1 : cmsis_dap_handle->packet_count;
+ unsigned int packet_count = cmsis_dap_quirk_mode ? 1 : cmsis_dap_handle->packet_count;
if (cmsis_dap_handle->pending_fifo_block_count >= packet_count)
cmsis_dap_swd_read_process(cmsis_dap_handle, CMSIS_DAP_BLOCKING);
}
@@ -1230,7 +1239,7 @@ static int cmsis_dap_swd_switch_seq(enum swd_special_seq seq)
if (swd_mode)
queued_retval = cmsis_dap_swd_run_queue();
- if (cmsis_dap_handle->quirk_mode && seq != LINE_RESET &&
+ if (cmsis_dap_quirk_mode && seq != LINE_RESET &&
(output_pins & (SWJ_PIN_SRST | SWJ_PIN_TRST))
== (SWJ_PIN_SRST | SWJ_PIN_TRST)) {
/* Following workaround deasserts reset on most adapters.
@@ -1558,38 +1567,38 @@ static void debug_parse_cmsis_buf(const uint8_t *cmd, int cmdlen)
printf(" %02x", cmd[i]);
printf("\n");
switch (cmd[0]) {
- case CMD_DAP_JTAG_SEQ: {
- printf("cmsis-dap jtag sequence command %02x (n=%d)\n", cmd[0], cmd[1]);
- /*
- * #1 = number of sequences
- * #2 = sequence info 1
- * #3...4+n_bytes-1 = sequence 1
- * #4+n_bytes = sequence info 2
- * #5+n_bytes = sequence 2 (single bit)
- */
- int pos = 2;
- for (int seq = 0; seq < cmd[1]; ++seq) {
- uint8_t info = cmd[pos++];
- int len = info & DAP_JTAG_SEQ_TCK;
- if (len == 0)
- len = 64;
- printf(" sequence %d starting %d: info %02x (len=%d tms=%d read_tdo=%d): ",
- seq, pos, info, len, info & DAP_JTAG_SEQ_TMS, info & DAP_JTAG_SEQ_TDO);
- for (int i = 0; i < DIV_ROUND_UP(len, 8); ++i)
- printf(" %02x", cmd[pos+i]);
- pos += DIV_ROUND_UP(len, 8);
- printf("\n");
- }
- if (pos != cmdlen) {
- printf("BUFFER LENGTH MISMATCH looks like %d but %d specified", pos, cmdlen);
- exit(-1);
- }
-
- break;
+ case CMD_DAP_JTAG_SEQ: {
+ printf("cmsis-dap jtag sequence command %02x (n=%d)\n", cmd[0], cmd[1]);
+ /*
+ * #1 = number of sequences
+ * #2 = sequence info 1
+ * #3...4+n_bytes-1 = sequence 1
+ * #4+n_bytes = sequence info 2
+ * #5+n_bytes = sequence 2 (single bit)
+ */
+ int pos = 2;
+ for (int seq = 0; seq < cmd[1]; ++seq) {
+ uint8_t info = cmd[pos++];
+ int len = info & DAP_JTAG_SEQ_TCK;
+ if (len == 0)
+ len = 64;
+ printf(" sequence %d starting %d: info %02x (len=%d tms=%d read_tdo=%d): ",
+ seq, pos, info, len, info & DAP_JTAG_SEQ_TMS, info & DAP_JTAG_SEQ_TDO);
+ for (int i = 0; i < DIV_ROUND_UP(len, 8); ++i)
+ printf(" %02x", cmd[pos + i]);
+ pos += DIV_ROUND_UP(len, 8);
+ printf("\n");
}
- default:
- LOG_DEBUG("unknown cmsis-dap command %02x", cmd[1]);
- break;
+ if (pos != cmdlen) {
+ printf("BUFFER LENGTH MISMATCH looks like %d but %d specified", pos, cmdlen);
+ exit(-1);
+ }
+
+ break;
+ }
+ default:
+ LOG_DEBUG("unknown cmsis-dap command %02x", cmd[1]);
+ break;
}
}
#endif
@@ -1930,32 +1939,32 @@ static void cmsis_dap_execute_tms(struct jtag_command *cmd)
static void cmsis_dap_execute_command(struct jtag_command *cmd)
{
switch (cmd->type) {
- case JTAG_SLEEP:
- cmsis_dap_flush();
- cmsis_dap_execute_sleep(cmd);
- break;
- case JTAG_TLR_RESET:
- cmsis_dap_flush();
- cmsis_dap_execute_tlr_reset(cmd);
- break;
- case JTAG_SCAN:
- cmsis_dap_execute_scan(cmd);
- break;
- case JTAG_PATHMOVE:
- cmsis_dap_execute_pathmove(cmd);
- break;
- case JTAG_RUNTEST:
- cmsis_dap_execute_runtest(cmd);
- break;
- case JTAG_STABLECLOCKS:
- cmsis_dap_execute_stableclocks(cmd);
- break;
- case JTAG_TMS:
- cmsis_dap_execute_tms(cmd);
- break;
- default:
- LOG_ERROR("BUG: unknown JTAG command type 0x%X encountered", cmd->type);
- exit(-1);
+ case JTAG_SLEEP:
+ cmsis_dap_flush();
+ cmsis_dap_execute_sleep(cmd);
+ break;
+ case JTAG_TLR_RESET:
+ cmsis_dap_flush();
+ cmsis_dap_execute_tlr_reset(cmd);
+ break;
+ case JTAG_SCAN:
+ cmsis_dap_execute_scan(cmd);
+ break;
+ case JTAG_PATHMOVE:
+ cmsis_dap_execute_pathmove(cmd);
+ break;
+ case JTAG_RUNTEST:
+ cmsis_dap_execute_runtest(cmd);
+ break;
+ case JTAG_STABLECLOCKS:
+ cmsis_dap_execute_stableclocks(cmd);
+ break;
+ case JTAG_TMS:
+ cmsis_dap_execute_tms(cmd);
+ break;
+ default:
+ LOG_ERROR("BUG: unknown JTAG command type 0x%X encountered", cmd->type);
+ exit(-1);
}
}
@@ -2238,11 +2247,13 @@ COMMAND_HANDLER(cmsis_dap_handle_quirk_command)
if (CMD_ARGC > 1)
return ERROR_COMMAND_SYNTAX_ERROR;
- if (CMD_ARGC == 1)
- COMMAND_PARSE_ENABLE(CMD_ARGV[0], cmsis_dap_handle->quirk_mode);
+ if (CMD_ARGC == 1) {
+ COMMAND_PARSE_ENABLE(CMD_ARGV[0], cmsis_dap_quirk_mode);
+ return ERROR_OK;
+ }
+
+ command_print(CMD, "%s", cmsis_dap_quirk_mode ? "enabled" : "disabled");
- command_print(CMD, "CMSIS-DAP quirk workarounds %s",
- cmsis_dap_handle->quirk_mode ? "enabled" : "disabled");
return ERROR_OK;
}
@@ -2272,8 +2283,8 @@ static const struct command_registration cmsis_dap_subcommand_handlers[] = {
.name = "backend",
.handler = &cmsis_dap_handle_backend_command,
.mode = COMMAND_CONFIG,
- .help = "set the communication backend to use (USB bulk or HID).",
- .usage = "(auto | usb_bulk | hid)",
+ .help = "set the communication backend to use (USB bulk or HID, or TCP).",
+ .usage = "(auto | usb_bulk | hid | tcp)",
},
{
.name = "quirk",
@@ -2290,6 +2301,15 @@ static const struct command_registration cmsis_dap_subcommand_handlers[] = {
.help = "USB bulk backend-specific commands",
.usage = "",
},
+#endif
+#if BUILD_CMSIS_DAP_TCP
+ {
+ .name = "tcp",
+ .chain = cmsis_dap_tcp_subcommand_handlers,
+ .mode = COMMAND_ANY,
+ .help = "TCP backend-specific commands",
+ .usage = "",
+ },
#endif
COMMAND_REGISTRATION_DONE
};
diff --git a/src/jtag/drivers/cmsis_dap.h b/src/jtag/drivers/cmsis_dap.h
index aded0e54a3..880fc33502 100644
--- a/src/jtag/drivers/cmsis_dap.h
+++ b/src/jtag/drivers/cmsis_dap.h
@@ -52,7 +52,6 @@ struct cmsis_dap {
unsigned int pending_fifo_block_count;
uint16_t caps;
- bool quirk_mode; /* enable expensive workarounds */
uint32_t swo_buf_sz;
bool trace_enabled;
@@ -78,7 +77,9 @@ struct cmsis_dap_backend {
extern const struct cmsis_dap_backend cmsis_dap_hid_backend;
extern const struct cmsis_dap_backend cmsis_dap_usb_backend;
+extern const struct cmsis_dap_backend cmsis_dap_tcp_backend;
extern const struct command_registration cmsis_dap_usb_subcommand_handlers[];
+extern const struct command_registration cmsis_dap_tcp_subcommand_handlers[];
#define REPORT_ID_SIZE 1
diff --git a/src/jtag/drivers/cmsis_dap_tcp.c b/src/jtag/drivers/cmsis_dap_tcp.c
new file mode 100644
index 0000000000..7894550fe2
--- /dev/null
+++ b/src/jtag/drivers/cmsis_dap_tcp.c
@@ -0,0 +1,541 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+/***************************************************************************
+ * Provides CMSIS-DAP protocol over a TCP/IP socket. *
+ * UART and SWO are currently unsupported. *
+ * *
+ * Copyright (C) 2025 by Brian Kuschak *
+ * *
+ * Adapted from cmsis_dap_usb_hid.c. Copyright (C) 2013-2018 by: *
+ * Mickaël Thomas *
+ * Maksym Hilliaka *
+ * Phillip Pearson *
+ * Paul Fertser *
+ * mike brown *
+ * Spencer Oliver *
+ * *
+ ***************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#ifdef HAVE_ARPA_INET_H
+#include
+#endif
+#include
+#ifdef HAVE_NETDB_H
+#include
+#endif
+#ifdef HAVE_NETINET_TCP_H
+#include
+#endif
+#include
+#include
+#ifdef HAVE_SYS_IOCTL_H
+#include
+#endif
+#ifdef HAVE_SYS_SOCKET_H
+#include
+#endif
+#include
+#ifdef HAVE_UNISTD_H
+#include
+#endif
+
+#ifdef _WIN32
+#include
+#include
+#endif
+
+#include "helper/command.h"
+#include "helper/log.h"
+#include "helper/replacements.h"
+#include "helper/system.h"
+#include "cmsis_dap.h"
+
+#define STRINGIFY(x) #x
+
+// If the protocol changes in the future, the SIGNATURE should also be changed.
+#define DAP_PKT_HDR_SIGNATURE 0x00504144 // "DAP"
+#define DAP_PKT_TYPE_REQUEST 0x01
+#define DAP_PKT_TYPE_RESPONSE 0x02
+
+#define CMSIS_DAP_TCP_PORT 4441 // Default. Can be overridden.
+#define CMSIS_DAP_PACKET_SIZE 1024 // Max payload size not including
+ // header.
+
+/* When flushing after an error, the CMSIS-DAP driver assumes the pipeline is
+ * empty if it doesn't get a response after a short 10 msec timeout. While this
+ * works for USB, it may not work for TCP/IP due to higher network latency. TCP
+ * response packets may take longer to arrive. We set a lower bound on timeout
+ * for blocking reads, to give enough time for packets to arrive.
+ *
+ * The user may override this default value by setting the parameter
+ * 'cmsis-dap tcp min_timeout'
+ */
+#define DEFAULT_MIN_TIMEOUT_MS 150
+
+/* CMSIS-DAP requests are variable length. With CMSIS-DAP over USB, the
+ * transfer sizes are preserved by the USB stack. However, TCP/IP is stream
+ * oriented so we perform our own packetization to preserve the boundaries
+ * between each request. This short header is prepended to each CMSIS-DAP
+ * request and response before being sent over the socket. Little endian format
+ * is used for multibyte values.
+ */
+struct __attribute__((packed)) cmsis_dap_tcp_packet_hdr {
+ uint32_t signature; // "DAP"
+ uint16_t length; // Not including header length.
+ uint8_t packet_type;
+ uint8_t reserved; // Reserved for future use.
+};
+
+/* Defines for struct cmsis_dap_tcp_packet_hdr requested by reviewer. */
+#define HEADER_SIGNATURE_OFFSET 0
+#define HEADER_LENGTH_OFFSET sizeof(uint32_t)
+#define HEADER_PACKET_TYPE_OFFSET (sizeof(uint32_t) + sizeof(uint16_t))
+#define HEADER_RESERVED_OFFSET (sizeof(uint32_t) + sizeof(uint16_t) + \
+ sizeof(uint8_t))
+#define HEADER_SIZE (sizeof(uint32_t) + sizeof(uint16_t) + \
+ 2 * sizeof(uint8_t))
+
+struct cmsis_dap_backend_data {
+ int sockfd;
+};
+
+static char *cmsis_dap_tcp_host;
+static char cmsis_dap_tcp_port_default[] = STRINGIFY(CMSIS_DAP_TCP_PORT);
+static char *cmsis_dap_tcp_port = cmsis_dap_tcp_port_default;
+static int cmsis_dap_tcp_min_timeout_ms = DEFAULT_MIN_TIMEOUT_MS;
+
+static void cmsis_dap_tcp_close(struct cmsis_dap *dap);
+static int cmsis_dap_tcp_alloc(struct cmsis_dap *dap, unsigned int pkt_sz);
+static void cmsis_dap_tcp_free(struct cmsis_dap *dap);
+
+static int cmsis_dap_tcp_open(struct cmsis_dap *dap,
+ uint16_t vids[] __attribute__((unused)),
+ uint16_t pids[] __attribute__((unused)),
+ const char *serial __attribute__((unused)))
+{
+ // Skip the open if the user has not provided a hostname.
+ if (!cmsis_dap_tcp_host) {
+ LOG_DEBUG("No TCP hostname, skipping open.");
+ return ERROR_FAIL;
+ }
+
+ // Ignore vids, pids, serial. We use host and port subcommands instead.
+
+ dap->bdata = malloc(sizeof(struct cmsis_dap_backend_data));
+ if (!dap->bdata) {
+ LOG_ERROR("CMSIS-DAP: unable to allocate memory");
+ return ERROR_FAIL;
+ }
+
+ struct addrinfo hints = {
+ .ai_family = AF_UNSPEC,
+ .ai_socktype = SOCK_STREAM
+ };
+ struct addrinfo *result, *rp;
+ int fd = 0;
+
+ LOG_INFO("CMSIS-DAP: Connecting to %s:%s using TCP backend",
+ cmsis_dap_tcp_host ? cmsis_dap_tcp_host : "localhost",
+ cmsis_dap_tcp_port);
+
+ /* Some of the following code was taken from remote_bitbang.c */
+ /* Obtain address(es) matching host/port */
+ int s = getaddrinfo(cmsis_dap_tcp_host, cmsis_dap_tcp_port, &hints,
+ &result);
+ if (s != 0) {
+ LOG_ERROR("CMSIS-DAP: getaddrinfo: %s\n", gai_strerror(s));
+ free(dap->bdata);
+ return ERROR_FAIL;
+ }
+
+ /* getaddrinfo() returns a list of address structures.
+ Try each address until we successfully connect(2).
+ If socket(2) (or connect(2)) fails, we (close the socket
+ and) try the next address. */
+
+ for (rp = result; rp ; rp = rp->ai_next) {
+ fd = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);
+ if (fd == -1)
+ continue;
+
+ if (connect(fd, rp->ai_addr, rp->ai_addrlen) != -1) {
+ LOG_DEBUG("Connected.");
+ break; /* Success */
+ }
+
+ close(fd);
+ }
+
+ freeaddrinfo(result);
+
+ if (!rp) { /* No address succeeded */
+ LOG_ERROR("CMSIS-DAP: unable to connect to device %s:%s",
+ cmsis_dap_tcp_host ? cmsis_dap_tcp_host : "localhost",
+ cmsis_dap_tcp_port);
+ log_socket_error("Failed to connect");
+ free(dap->bdata);
+ dap->bdata = NULL;
+ return ERROR_FAIL;
+ }
+
+ /* Set NODELAY to minimize latency. */
+ int one = 1;
+ /* On Windows optval has to be a const char *. */
+ setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (const char *)&one, sizeof(one));
+
+ dap->bdata->sockfd = fd;
+
+ int retval = cmsis_dap_tcp_alloc(dap, CMSIS_DAP_PACKET_SIZE);
+ if (retval != ERROR_OK) {
+ cmsis_dap_tcp_close(dap);
+ return retval;
+ }
+ return ERROR_OK;
+}
+
+static void cmsis_dap_tcp_close(struct cmsis_dap *dap)
+{
+ if (close_socket(dap->bdata->sockfd) != 0)
+ log_socket_error("close_socket");
+
+ if (dap->bdata)
+ free(dap->bdata);
+ dap->bdata = NULL;
+ cmsis_dap_tcp_free(dap);
+}
+
+static int socket_bytes_available(int sock, unsigned int *out_avail)
+{
+#ifdef _WIN32
+ u_long avail = 0;
+ if (ioctlsocket((SOCKET)sock, FIONREAD, &avail) == SOCKET_ERROR)
+ return -1;
+#else
+ int avail = 0;
+ if (ioctl(sock, FIONREAD, &avail) < 0)
+ return -1;
+#endif
+ *out_avail = avail;
+ return 0;
+}
+
+static inline int readall_socket(int handle, void *buffer, unsigned int count)
+{
+ // Return after all count bytes available, or timeout, or error.
+ return recv(handle, buffer, count, MSG_WAITALL);
+}
+
+static int peekall_socket(int handle, void *buffer, unsigned int count,
+ enum cmsis_dap_blocking blocking, unsigned int timeout_ms)
+{
+ /* Windows doesn't support MSG_PEEK in combination with MSG_WAITALL:
+ * return recv(handle, buffer, count, MSG_PEEK | MSG_WAITALL);
+ *
+ * So, use this method instead which should work for Windows and others.
+ *
+ * Data remains unread on the socket until recv() is called later without
+ * the MSG_PEEK flag. Return after all count bytes available, or timeout,
+ * or error.
+ */
+
+ if (count == 0)
+ return 0;
+
+ while (true) {
+ int ret;
+ unsigned int avail;
+ if (socket_bytes_available(handle, &avail) < 0)
+ return -1;
+
+ if (avail >= count) {
+ ret = recv(handle, (char *)buffer, (int)count, MSG_PEEK);
+ if (ret < 0) {
+#ifdef _WIN32
+ int err = WSAGetLastError();
+ if (err == WSAEINTR)
+ continue;
+ if (err == WSAEWOULDBLOCK)
+ return -1;
+#else
+ if (errno == EINTR)
+ continue;
+ if (errno == EAGAIN || errno == EWOULDBLOCK)
+ return -1; // Timeout or nonblocking.
+#endif
+ }
+ return ret; // 0: Closed, <0: Other error, >0 Success.
+ }
+
+ // Not enough data available.
+ if (blocking == CMSIS_DAP_NON_BLOCKING) {
+#ifdef _WIN32
+ WSASetLastError(WSAEWOULDBLOCK);
+#else
+ errno = EAGAIN;
+#endif
+ return -1;
+ }
+
+ // Blocking wait.
+ fd_set rfds;
+ FD_ZERO(&rfds);
+ FD_SET(handle, &rfds);
+
+ struct timeval tv;
+ tv.tv_sec = timeout_ms / 1000;
+ tv.tv_usec = (timeout_ms % 1000) * 1000;
+
+ ret = select(handle + 1, &rfds, NULL, NULL, &tv);
+ if (ret > 0)
+ continue; // Readable
+
+ if (ret == 0) { // Timeout
+#ifdef _WIN32
+ WSASetLastError(WSAEWOULDBLOCK);
+#else
+ errno = EAGAIN;
+#endif
+ return -1;
+ }
+
+ // Error
+#ifndef _WIN32
+ if (errno == EINTR)
+ continue;
+#endif
+ return ret;
+ }
+}
+
+static int cmsis_dap_tcp_read(struct cmsis_dap *dap, int transfer_timeout_ms,
+ enum cmsis_dap_blocking blocking)
+{
+ int wait_ms = (blocking == CMSIS_DAP_NON_BLOCKING) ? 0 :
+ transfer_timeout_ms;
+ if (wait_ms) {
+ LOG_DEBUG_IO("CMSIS-DAP: using tcp timeout %d msec", wait_ms);
+
+ // Don't use very short timeouts with TCP/IP as it may not be as fast
+ // to respond as USB. User configurable minimum value.
+ if (wait_ms < cmsis_dap_tcp_min_timeout_ms) {
+ wait_ms = cmsis_dap_tcp_min_timeout_ms;
+ LOG_DEBUG_IO("CMSIS-DAP: extending timeout to %d msec", wait_ms);
+ }
+ }
+ socket_recv_timeout(dap->bdata->sockfd, wait_ms);
+
+ if (blocking == CMSIS_DAP_NON_BLOCKING)
+ socket_nonblock(dap->bdata->sockfd);
+ else
+ socket_block(dap->bdata->sockfd);
+
+ // Peek at the header first to find the length.
+ int retval = peekall_socket(dap->bdata->sockfd, dap->packet_buffer,
+ HEADER_SIZE, blocking, wait_ms);
+ LOG_DEBUG_IO("Reading header returned %d", retval);
+ if (retval == 0) {
+ LOG_DEBUG_IO("CMSIS-DAP: tcp timeout reached 1");
+ return ERROR_TIMEOUT_REACHED;
+ } else if (retval == -1) {
+ if (errno == EAGAIN || errno == EWOULDBLOCK) {
+ if (blocking == CMSIS_DAP_NON_BLOCKING)
+ return ERROR_TIMEOUT_REACHED;
+
+ LOG_DEBUG_IO("CMSIS-DAP: tcp timeout reached 2. timeout = %d msec",
+ wait_ms);
+ return ERROR_TIMEOUT_REACHED;
+ }
+
+ LOG_ERROR("CMSIS-DAP: error reading header");
+ log_socket_error("peek_socket");
+ return ERROR_FAIL;
+ } else if (retval != HEADER_SIZE) {
+ LOG_ERROR("CMSIS-DAP: short header read");
+ log_socket_error("peek_socket header short read");
+ return ERROR_FAIL;
+ }
+
+ struct cmsis_dap_tcp_packet_hdr header;
+ header.signature = le_to_h_u32(dap->packet_buffer +
+ HEADER_SIGNATURE_OFFSET);
+ header.length = le_to_h_u16(dap->packet_buffer + HEADER_LENGTH_OFFSET);
+ header.packet_type = dap->packet_buffer[HEADER_PACKET_TYPE_OFFSET];
+ header.reserved = dap->packet_buffer[HEADER_RESERVED_OFFSET];
+
+ if (header.signature != DAP_PKT_HDR_SIGNATURE) {
+ LOG_ERROR("CMSIS-DAP: Unrecognized packet signature 0x%08x",
+ header.signature);
+ return ERROR_FAIL;
+ } else if (header.packet_type != DAP_PKT_TYPE_RESPONSE) {
+ LOG_ERROR("CMSIS-DAP: Unrecognized packet type 0x%02x",
+ header.packet_type);
+ return ERROR_FAIL;
+ } else if (header.length + HEADER_SIZE > dap->packet_buffer_size) {
+ LOG_ERROR("CMSIS-DAP: Packet length %d too large to fit.",
+ header.length);
+ return ERROR_FAIL;
+ }
+
+ // Read the complete packet.
+ int read_len = HEADER_SIZE + header.length;
+ LOG_DEBUG_IO("Reading %d bytes (%d payload)...", read_len, header.length);
+ retval = readall_socket(dap->bdata->sockfd, dap->packet_buffer, read_len);
+
+ if (retval == 0) {
+ LOG_DEBUG_IO("CMSIS-DAP: tcp timeout reached 3");
+ return ERROR_TIMEOUT_REACHED;
+ } else if (retval == -1) {
+ LOG_ERROR("CMSIS-DAP: error reading data");
+ log_socket_error("read_socket");
+ return ERROR_FAIL;
+ } else if (retval != read_len) {
+ LOG_ERROR("CMSIS-DAP: short read. retval = %d. read_len = %d. "
+ "blocking = %s. wait_ms = %d", retval, read_len,
+ (blocking == CMSIS_DAP_NON_BLOCKING) ? "yes" : "no", wait_ms);
+ log_socket_error("read_socket short read");
+ return ERROR_FAIL;
+ }
+ return retval;
+}
+
+static int cmsis_dap_tcp_write(struct cmsis_dap *dap, int txlen,
+ int timeout_ms __attribute__((unused)))
+{
+ const unsigned int len = txlen + HEADER_SIZE;
+ if (len > dap->packet_buffer_size) {
+ LOG_ERROR("CMSIS-DAP: Packet length %d exceeds TCP buffer size!", len);
+ return ERROR_FAIL;
+ }
+
+ /* Set the header values. */
+ h_u32_to_le(dap->packet_buffer + HEADER_SIGNATURE_OFFSET,
+ DAP_PKT_HDR_SIGNATURE);
+ h_u16_to_le(dap->packet_buffer + HEADER_LENGTH_OFFSET, txlen);
+ dap->packet_buffer[HEADER_PACKET_TYPE_OFFSET] = DAP_PKT_TYPE_REQUEST;
+ dap->packet_buffer[HEADER_RESERVED_OFFSET] = 0;
+
+ /* write data to device */
+ LOG_DEBUG_IO("Writing %d bytes (%d payload)", len, txlen);
+ int retval = write_socket(dap->bdata->sockfd, dap->packet_buffer, len);
+ if (retval < 0) {
+ log_socket_error("write_socket");
+ return ERROR_FAIL;
+ } else if (retval != (int)len) {
+ LOG_ERROR("CMSIS-DAP: error writing data");
+ log_socket_error("write_socket short write");
+ return ERROR_FAIL;
+ }
+ return retval;
+}
+
+static int cmsis_dap_tcp_alloc(struct cmsis_dap *dap, unsigned int pkt_sz)
+{
+ // Reserve space for the packet header.
+ unsigned int packet_buffer_size = pkt_sz + HEADER_SIZE;
+ uint8_t *buf = malloc(packet_buffer_size);
+ if (!buf) {
+ LOG_ERROR("CMSIS-DAP: unable to allocate CMSIS-DAP packet buffer");
+ return ERROR_FAIL;
+ }
+
+ dap->packet_buffer = buf;
+ dap->packet_size = pkt_sz;
+ dap->packet_usable_size = pkt_sz;
+ dap->packet_buffer_size = packet_buffer_size;
+
+ dap->command = dap->packet_buffer + HEADER_SIZE;
+ dap->response = dap->packet_buffer + HEADER_SIZE;
+ return ERROR_OK;
+}
+
+static void cmsis_dap_tcp_free(struct cmsis_dap *dap)
+{
+ free(dap->packet_buffer);
+ dap->packet_buffer = NULL;
+}
+
+static void cmsis_dap_tcp_cancel_all(struct cmsis_dap *dap)
+{
+}
+
+COMMAND_HANDLER(cmsis_dap_handle_tcp_port)
+{
+ if (CMD_ARGC != 1)
+ return ERROR_COMMAND_SYNTAX_ERROR;
+
+ if (cmsis_dap_tcp_port != cmsis_dap_tcp_port_default)
+ free(cmsis_dap_tcp_port);
+
+ cmsis_dap_tcp_port = strdup(CMD_ARGV[0]);
+ if (!cmsis_dap_tcp_port) {
+ LOG_ERROR("CMSIS-DAP: out of memory");
+ return ERROR_FAIL;
+ }
+ return ERROR_OK;
+}
+
+COMMAND_HANDLER(cmsis_dap_handle_tcp_host)
+{
+ if (CMD_ARGC != 1)
+ return ERROR_COMMAND_SYNTAX_ERROR;
+
+ free(cmsis_dap_tcp_host);
+ cmsis_dap_tcp_host = strdup(CMD_ARGV[0]);
+ if (!cmsis_dap_tcp_host) {
+ LOG_ERROR("CMSIS-DAP: out of memory");
+ return ERROR_FAIL;
+ }
+ return ERROR_OK;
+}
+
+COMMAND_HANDLER(cmsis_dap_handle_tcp_min_timeout)
+{
+ if (CMD_ARGC != 1)
+ return ERROR_COMMAND_SYNTAX_ERROR;
+
+ COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], cmsis_dap_tcp_min_timeout_ms);
+ LOG_INFO("CMSIS-DAP: using minimum timeout of %d ms for TCP packets.",
+ cmsis_dap_tcp_min_timeout_ms);
+ return ERROR_OK;
+}
+
+const struct command_registration cmsis_dap_tcp_subcommand_handlers[] = {
+ {
+ .name = "host",
+ .handler = &cmsis_dap_handle_tcp_host,
+ .mode = COMMAND_CONFIG,
+ .help = "set the host name to use (for TCP backend only)",
+ .usage = "",
+ },
+ {
+ .name = "port",
+ .handler = &cmsis_dap_handle_tcp_port,
+ .mode = COMMAND_CONFIG,
+ .help = "set the port number to use for DAP (for TCP backend only)",
+ .usage = "",
+ },
+ {
+ .name = "min_timeout",
+ .handler = &cmsis_dap_handle_tcp_min_timeout,
+ .mode = COMMAND_CONFIG,
+ .help = "set the minimum timeout in milliseconds to wait for response "
+ "packets (for TCP backend only)",
+ .usage = "",
+ },
+ COMMAND_REGISTRATION_DONE
+};
+
+const struct cmsis_dap_backend cmsis_dap_tcp_backend = {
+ .name = "tcp",
+ .open = cmsis_dap_tcp_open,
+ .close = cmsis_dap_tcp_close,
+ .read = cmsis_dap_tcp_read,
+ .write = cmsis_dap_tcp_write,
+ .packet_buffer_alloc = cmsis_dap_tcp_alloc,
+ .packet_buffer_free = cmsis_dap_tcp_free,
+ .cancel_all = cmsis_dap_tcp_cancel_all,
+};
diff --git a/src/jtag/drivers/cmsis_dap_usb_bulk.c b/src/jtag/drivers/cmsis_dap_usb_bulk.c
index 8fbcb029dd..d34d4e31c1 100644
--- a/src/jtag/drivers/cmsis_dap_usb_bulk.c
+++ b/src/jtag/drivers/cmsis_dap_usb_bulk.c
@@ -414,7 +414,19 @@ static int cmsis_dap_usb_open(struct cmsis_dap *dap, uint16_t vids[], uint16_t p
static void cmsis_dap_usb_close(struct cmsis_dap *dap)
{
for (unsigned int i = 0; i < MAX_PENDING_REQUESTS; i++) {
- libusb_free_transfer(dap->bdata->command_transfers[i].transfer);
+ if (dap->bdata->command_transfers[i].status == CMSIS_DAP_TRANSFER_PENDING) {
+ LOG_DEBUG("busy command USB transfer at %u", dap->pending_fifo_put_idx);
+ struct timeval tv = {
+ .tv_sec = 1,
+ .tv_usec = 1000
+ };
+ /* Complete pending commands */
+ int res = libusb_handle_events_timeout_completed(dap->bdata->usb_ctx, &tv, NULL);
+ if (res == 0)
+ libusb_free_transfer(dap->bdata->command_transfers[i].transfer);
+ } else {
+ libusb_free_transfer(dap->bdata->command_transfers[i].transfer);
+ }
libusb_free_transfer(dap->bdata->response_transfers[i].transfer);
}
cmsis_dap_usb_free(dap);
@@ -647,10 +659,10 @@ static void cmsis_dap_usb_cancel_all(struct cmsis_dap *dap)
COMMAND_HANDLER(cmsis_dap_handle_usb_interface_command)
{
- if (CMD_ARGC == 1)
- COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], cmsis_dap_usb_interface);
- else
- LOG_ERROR("expected exactly one argument to cmsis_dap_usb_interface ");
+ if (CMD_ARGC != 1)
+ return ERROR_COMMAND_SYNTAX_ERROR;
+
+ COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], cmsis_dap_usb_interface);
return ERROR_OK;
}
@@ -661,7 +673,7 @@ const struct command_registration cmsis_dap_usb_subcommand_handlers[] = {
.handler = &cmsis_dap_handle_usb_interface_command,
.mode = COMMAND_CONFIG,
.help = "set the USB interface number to use (for USB bulk backend only)",
- .usage = "",
+ .usage = "",
},
COMMAND_REGISTRATION_DONE
};
diff --git a/src/jtag/drivers/dmem.c b/src/jtag/drivers/dmem.c
index e50e84aeeb..0f1b582990 100644
--- a/src/jtag/drivers/dmem.c
+++ b/src/jtag/drivers/dmem.c
@@ -93,14 +93,14 @@ static bool dmem_is_emulated_ap(struct adiv5_ap *ap, unsigned int *idx)
return false;
}
-static void dmem_emu_set_ap_reg(uint64_t addr, uint32_t val)
+static void dmem_emu_set_ap_reg(uint32_t addr, uint32_t val)
{
addr &= ~ARM_APB_PADDR31;
*(volatile uint32_t *)((uintptr_t)dmem_emu_virt_base_addr + addr) = val;
}
-static uint32_t dmem_emu_get_ap_reg(uint64_t addr)
+static uint32_t dmem_emu_get_ap_reg(uint32_t addr)
{
uint32_t val;
@@ -113,46 +113,46 @@ static uint32_t dmem_emu_get_ap_reg(uint64_t addr)
static int dmem_emu_ap_q_read(unsigned int ap_idx, unsigned int reg, uint32_t *data)
{
- uint64_t addr;
+ uint32_t addr;
int ret = ERROR_OK;
struct dmem_emu_ap_info *ap_info = &dmem_emu_ap_list[ap_idx];
switch (reg) {
- case ADIV5_MEM_AP_REG_CSW:
- *data = ap_info->apbap_csw;
- break;
- case ADIV5_MEM_AP_REG_TAR:
- *data = ap_info->apbap_tar;
- break;
- case ADIV5_MEM_AP_REG_CFG:
- *data = 0;
- break;
- case ADIV5_MEM_AP_REG_BASE:
- *data = 0;
- break;
- case ADIV5_AP_REG_IDR:
- *data = 0;
- break;
- case ADIV5_MEM_AP_REG_BD0:
- case ADIV5_MEM_AP_REG_BD1:
- case ADIV5_MEM_AP_REG_BD2:
- case ADIV5_MEM_AP_REG_BD3:
- addr = (ap_info->apbap_tar & ~0xf) + (reg & 0x0C);
-
- *data = dmem_emu_get_ap_reg(addr);
-
- break;
- case ADIV5_MEM_AP_REG_DRW:
- addr = ap_info->apbap_tar;
-
- *data = dmem_emu_get_ap_reg(addr);
-
- ap_info->apbap_tar += dmem_memap_tar_inc(ap_info->apbap_csw);
- break;
- default:
- LOG_INFO("%s: Unknown reg: 0x%02x", __func__, reg);
- ret = ERROR_FAIL;
- break;
+ case ADIV5_MEM_AP_REG_CSW:
+ *data = ap_info->apbap_csw;
+ break;
+ case ADIV5_MEM_AP_REG_TAR:
+ *data = ap_info->apbap_tar;
+ break;
+ case ADIV5_MEM_AP_REG_CFG:
+ *data = 0;
+ break;
+ case ADIV5_MEM_AP_REG_BASE:
+ *data = 0;
+ break;
+ case ADIV5_AP_REG_IDR:
+ *data = 0;
+ break;
+ case ADIV5_MEM_AP_REG_BD0:
+ case ADIV5_MEM_AP_REG_BD1:
+ case ADIV5_MEM_AP_REG_BD2:
+ case ADIV5_MEM_AP_REG_BD3:
+ addr = (ap_info->apbap_tar & ~0xf) + (reg & 0x0C);
+
+ *data = dmem_emu_get_ap_reg(addr);
+
+ break;
+ case ADIV5_MEM_AP_REG_DRW:
+ addr = ap_info->apbap_tar;
+
+ *data = dmem_emu_get_ap_reg(addr);
+
+ ap_info->apbap_tar += dmem_memap_tar_inc(ap_info->apbap_csw);
+ break;
+ default:
+ LOG_INFO("%s: Unknown reg: 0x%02x", __func__, reg);
+ ret = ERROR_FAIL;
+ break;
}
/* Track the last error code. */
@@ -164,51 +164,51 @@ static int dmem_emu_ap_q_read(unsigned int ap_idx, unsigned int reg, uint32_t *d
static int dmem_emu_ap_q_write(unsigned int ap_idx, unsigned int reg, uint32_t data)
{
- uint64_t addr;
+ uint32_t addr;
int ret = ERROR_OK;
struct dmem_emu_ap_info *ap_info = &dmem_emu_ap_list[ap_idx];
switch (reg) {
- case ADIV5_MEM_AP_REG_CSW:
- /*
- * This implementation only supports 32-bit accesses.
- * Force this by ensuring CSW_SIZE field indicates 32-BIT.
- */
- ap_info->apbap_csw = ((data & ~CSW_SIZE_MASK) | CSW_32BIT);
- break;
- case ADIV5_MEM_AP_REG_TAR:
- /*
- * This implementation only supports 32-bit accesses.
- * Force LS 2-bits of TAR to 00b
- */
- ap_info->apbap_tar = (data & ~0x3);
- break;
-
- case ADIV5_MEM_AP_REG_CFG:
- case ADIV5_MEM_AP_REG_BASE:
- case ADIV5_AP_REG_IDR:
- /* We don't use this, so we don't need to store */
- break;
-
- case ADIV5_MEM_AP_REG_BD0:
- case ADIV5_MEM_AP_REG_BD1:
- case ADIV5_MEM_AP_REG_BD2:
- case ADIV5_MEM_AP_REG_BD3:
- addr = (ap_info->apbap_tar & ~0xf) + (reg & 0x0C);
-
- dmem_emu_set_ap_reg(addr, data);
-
- break;
- case ADIV5_MEM_AP_REG_DRW:
- addr = ap_info->apbap_tar;
- dmem_emu_set_ap_reg(addr, data);
-
- ap_info->apbap_tar += dmem_memap_tar_inc(ap_info->apbap_csw);
- break;
- default:
- LOG_INFO("%s: Unknown reg: 0x%02x", __func__, reg);
- ret = EINVAL;
- break;
+ case ADIV5_MEM_AP_REG_CSW:
+ /*
+ * This implementation only supports 32-bit accesses.
+ * Force this by ensuring CSW_SIZE field indicates 32-BIT.
+ */
+ ap_info->apbap_csw = ((data & ~CSW_SIZE_MASK) | CSW_32BIT);
+ break;
+ case ADIV5_MEM_AP_REG_TAR:
+ /*
+ * This implementation only supports 32-bit accesses.
+ * Force LS 2-bits of TAR to 00b
+ */
+ ap_info->apbap_tar = (data & ~0x3);
+ break;
+
+ case ADIV5_MEM_AP_REG_CFG:
+ case ADIV5_MEM_AP_REG_BASE:
+ case ADIV5_AP_REG_IDR:
+ /* We don't use this, so we don't need to store */
+ break;
+
+ case ADIV5_MEM_AP_REG_BD0:
+ case ADIV5_MEM_AP_REG_BD1:
+ case ADIV5_MEM_AP_REG_BD2:
+ case ADIV5_MEM_AP_REG_BD3:
+ addr = (ap_info->apbap_tar & ~0xf) + (reg & 0x0C);
+
+ dmem_emu_set_ap_reg(addr, data);
+
+ break;
+ case ADIV5_MEM_AP_REG_DRW:
+ addr = ap_info->apbap_tar;
+ dmem_emu_set_ap_reg(addr, data);
+
+ ap_info->apbap_tar += dmem_memap_tar_inc(ap_info->apbap_csw);
+ break;
+ default:
+ LOG_INFO("%s: Unknown reg: 0x%02x", __func__, reg);
+ ret = EINVAL;
+ break;
}
/* Track the last error code. */
@@ -242,13 +242,13 @@ static int dmem_dp_q_read(struct adiv5_dap *dap, unsigned int reg, uint32_t *dat
return ERROR_OK;
switch (reg) {
- case DP_CTRL_STAT:
- *data = CDBGPWRUPACK | CSYSPWRUPACK;
- break;
+ case DP_CTRL_STAT:
+ *data = CDBGPWRUPACK | CSYSPWRUPACK;
+ break;
- default:
- *data = 0;
- break;
+ default:
+ *data = 0;
+ break;
}
return ERROR_OK;
@@ -519,7 +519,7 @@ static int dmem_dap_init(void)
MAP_SHARED, dmem_fd,
dmem_mapped_start);
if (dmem_map_base == MAP_FAILED) {
- LOG_ERROR("Mapping address 0x%lx for 0x%lx bytes failed!",
+ LOG_ERROR("Mapping address 0x%zx for 0x%zx bytes failed!",
dmem_mapped_start, dmem_mapped_size);
goto error_fail;
}
@@ -543,7 +543,7 @@ static int dmem_dap_init(void)
MAP_SHARED, dmem_fd,
dmem_mapped_start);
if (dmem_emu_map_base == MAP_FAILED) {
- LOG_ERROR("Mapping EMU address 0x%lx for 0x%lx bytes failed!",
+ LOG_ERROR("Mapping EMU address 0x%" PRIx64 " for 0x%" PRIx64 " bytes failed!",
dmem_emu_base_address, dmem_emu_size);
goto error_fail;
}
diff --git a/src/jtag/drivers/ft232r.c b/src/jtag/drivers/ft232r.c
index f88e4b9408..5bd934c386 100644
--- a/src/jtag/drivers/ft232r.c
+++ b/src/jtag/drivers/ft232r.c
@@ -818,71 +818,71 @@ static int syncbb_execute_queue(struct jtag_command *cmd_queue)
while (cmd) {
switch (cmd->type) {
- case JTAG_RESET:
- LOG_DEBUG_IO("reset trst: %i srst %i", cmd->cmd.reset->trst, cmd->cmd.reset->srst);
+ case JTAG_RESET:
+ LOG_DEBUG_IO("reset trst: %i srst %i", cmd->cmd.reset->trst, cmd->cmd.reset->srst);
- if ((cmd->cmd.reset->trst == 1) ||
+ if (cmd->cmd.reset->trst == 1 ||
(cmd->cmd.reset->srst &&
- (jtag_get_reset_config() & RESET_SRST_PULLS_TRST))) {
- tap_set_state(TAP_RESET);
- }
- ft232r_reset(cmd->cmd.reset->trst, cmd->cmd.reset->srst);
- break;
-
- case JTAG_RUNTEST:
- LOG_DEBUG_IO("runtest %u cycles, end in %s", cmd->cmd.runtest->num_cycles,
- tap_state_name(cmd->cmd.runtest->end_state));
-
- syncbb_end_state(cmd->cmd.runtest->end_state);
- syncbb_runtest(cmd->cmd.runtest->num_cycles);
- break;
-
- case JTAG_STABLECLOCKS:
- /* this is only allowed while in a stable state. A check for a stable
- * state was done in jtag_add_clocks()
- */
- syncbb_stableclocks(cmd->cmd.stableclocks->num_cycles);
- break;
-
- case JTAG_TLR_RESET: /* renamed from JTAG_STATEMOVE */
- LOG_DEBUG_IO("statemove end in %s", tap_state_name(cmd->cmd.statemove->end_state));
-
- syncbb_end_state(cmd->cmd.statemove->end_state);
- syncbb_state_move(0);
- break;
-
- case JTAG_PATHMOVE:
- LOG_DEBUG_IO("pathmove: %u states, end in %s", cmd->cmd.pathmove->num_states,
- tap_state_name(cmd->cmd.pathmove->path[cmd->cmd.pathmove->num_states - 1]));
-
- syncbb_path_move(cmd->cmd.pathmove);
- break;
-
- case JTAG_SCAN:
- LOG_DEBUG_IO("%s scan end in %s", (cmd->cmd.scan->ir_scan) ? "IR" : "DR",
- tap_state_name(cmd->cmd.scan->end_state));
-
- syncbb_end_state(cmd->cmd.scan->end_state);
- scan_size = jtag_build_buffer(cmd->cmd.scan, &buffer);
- type = jtag_scan_type(cmd->cmd.scan);
- syncbb_scan(cmd->cmd.scan->ir_scan, type, buffer, scan_size);
- if (jtag_read_buffer(buffer, cmd->cmd.scan) != ERROR_OK)
- retval = ERROR_JTAG_QUEUE_FAILED;
- free(buffer);
- break;
-
- case JTAG_SLEEP:
- LOG_DEBUG_IO("sleep %" PRIu32, cmd->cmd.sleep->us);
-
- jtag_sleep(cmd->cmd.sleep->us);
- break;
-
- case JTAG_TMS:
- retval = syncbb_execute_tms(cmd);
- break;
- default:
- LOG_ERROR("BUG: unknown JTAG command type encountered");
- exit(-1);
+ (jtag_get_reset_config() & RESET_SRST_PULLS_TRST)))
+ tap_set_state(TAP_RESET);
+
+ ft232r_reset(cmd->cmd.reset->trst, cmd->cmd.reset->srst);
+ break;
+
+ case JTAG_RUNTEST:
+ LOG_DEBUG_IO("runtest %u cycles, end in %s", cmd->cmd.runtest->num_cycles,
+ tap_state_name(cmd->cmd.runtest->end_state));
+
+ syncbb_end_state(cmd->cmd.runtest->end_state);
+ syncbb_runtest(cmd->cmd.runtest->num_cycles);
+ break;
+
+ case JTAG_STABLECLOCKS:
+ /* this is only allowed while in a stable state. A check for a stable
+ * state was done in jtag_add_clocks()
+ */
+ syncbb_stableclocks(cmd->cmd.stableclocks->num_cycles);
+ break;
+
+ case JTAG_TLR_RESET: /* renamed from JTAG_STATEMOVE */
+ LOG_DEBUG_IO("statemove end in %s", tap_state_name(cmd->cmd.statemove->end_state));
+
+ syncbb_end_state(cmd->cmd.statemove->end_state);
+ syncbb_state_move(0);
+ break;
+
+ case JTAG_PATHMOVE:
+ LOG_DEBUG_IO("pathmove: %u states, end in %s", cmd->cmd.pathmove->num_states,
+ tap_state_name(cmd->cmd.pathmove->path[cmd->cmd.pathmove->num_states - 1]));
+
+ syncbb_path_move(cmd->cmd.pathmove);
+ break;
+
+ case JTAG_SCAN:
+ LOG_DEBUG_IO("%s scan end in %s", (cmd->cmd.scan->ir_scan) ? "IR" : "DR",
+ tap_state_name(cmd->cmd.scan->end_state));
+
+ syncbb_end_state(cmd->cmd.scan->end_state);
+ scan_size = jtag_build_buffer(cmd->cmd.scan, &buffer);
+ type = jtag_scan_type(cmd->cmd.scan);
+ syncbb_scan(cmd->cmd.scan->ir_scan, type, buffer, scan_size);
+ if (jtag_read_buffer(buffer, cmd->cmd.scan) != ERROR_OK)
+ retval = ERROR_JTAG_QUEUE_FAILED;
+ free(buffer);
+ break;
+
+ case JTAG_SLEEP:
+ LOG_DEBUG_IO("sleep %" PRIu32, cmd->cmd.sleep->us);
+
+ jtag_sleep(cmd->cmd.sleep->us);
+ break;
+
+ case JTAG_TMS:
+ retval = syncbb_execute_tms(cmd);
+ break;
+ default:
+ LOG_ERROR("BUG: unknown JTAG command type encountered");
+ exit(-1);
}
if (ft232r_output_len > 0)
ft232r_send_recv();
diff --git a/src/jtag/drivers/ftdi.c b/src/jtag/drivers/ftdi.c
index 2c3339e658..ab76458810 100644
--- a/src/jtag/drivers/ftdi.c
+++ b/src/jtag/drivers/ftdi.c
@@ -666,38 +666,38 @@ static void ftdi_execute_command(struct jtag_command *cmd)
{
switch (cmd->type) {
#if BUILD_FTDI_CJTAG == 1
- case JTAG_RESET:
- if (cmd->cmd.reset->trst)
- cjtag_reset_online_activate(); /* put the target (back) into selected cJTAG mode */
- break;
+ case JTAG_RESET:
+ if (cmd->cmd.reset->trst)
+ cjtag_reset_online_activate(); /* put the target (back) into selected cJTAG mode */
+ break;
#endif
- case JTAG_RUNTEST:
- ftdi_execute_runtest(cmd);
- break;
- case JTAG_TLR_RESET:
+ case JTAG_RUNTEST:
+ ftdi_execute_runtest(cmd);
+ break;
+ case JTAG_TLR_RESET:
#if BUILD_FTDI_CJTAG == 1
- cjtag_reset_online_activate(); /* put the target (back) into selected cJTAG mode */
+ cjtag_reset_online_activate(); /* put the target (back) into selected cJTAG mode */
#endif
- ftdi_execute_statemove(cmd);
- break;
- case JTAG_PATHMOVE:
- ftdi_execute_pathmove(cmd);
- break;
- case JTAG_SCAN:
- ftdi_execute_scan(cmd);
- break;
- case JTAG_SLEEP:
- ftdi_execute_sleep(cmd);
- break;
- case JTAG_STABLECLOCKS:
- ftdi_execute_stableclocks(cmd);
- break;
- case JTAG_TMS:
- ftdi_execute_tms(cmd);
- break;
- default:
- LOG_ERROR("BUG: unknown JTAG command type encountered: %d", cmd->type);
- break;
+ ftdi_execute_statemove(cmd);
+ break;
+ case JTAG_PATHMOVE:
+ ftdi_execute_pathmove(cmd);
+ break;
+ case JTAG_SCAN:
+ ftdi_execute_scan(cmd);
+ break;
+ case JTAG_SLEEP:
+ ftdi_execute_sleep(cmd);
+ break;
+ case JTAG_STABLECLOCKS:
+ ftdi_execute_stableclocks(cmd);
+ break;
+ case JTAG_TMS:
+ ftdi_execute_tms(cmd);
+ break;
+ default:
+ LOG_ERROR("BUG: unknown JTAG command type encountered: %d", cmd->type);
+ break;
}
}
diff --git a/src/jtag/drivers/gw16012.c b/src/jtag/drivers/gw16012.c
index 805065f1f4..f6ae684f77 100644
--- a/src/jtag/drivers/gw16012.c
+++ b/src/jtag/drivers/gw16012.c
@@ -284,46 +284,46 @@ static int gw16012_execute_queue(struct jtag_command *cmd_queue)
while (cmd) {
switch (cmd->type) {
- case JTAG_RESET:
- LOG_DEBUG_IO("reset trst: %i srst %i", cmd->cmd.reset->trst, cmd->cmd.reset->srst);
- if (cmd->cmd.reset->trst == 1)
- tap_set_state(TAP_RESET);
- gw16012_reset(cmd->cmd.reset->trst, cmd->cmd.reset->srst);
- break;
- case JTAG_RUNTEST:
- LOG_DEBUG_IO("runtest %u cycles, end in %i", cmd->cmd.runtest->num_cycles,
- cmd->cmd.runtest->end_state);
- gw16012_end_state(cmd->cmd.runtest->end_state);
- gw16012_runtest(cmd->cmd.runtest->num_cycles);
- break;
- case JTAG_TLR_RESET:
- LOG_DEBUG_IO("statemove end in %i", cmd->cmd.statemove->end_state);
- gw16012_end_state(cmd->cmd.statemove->end_state);
- gw16012_state_move();
- break;
- case JTAG_PATHMOVE:
- LOG_DEBUG_IO("pathmove: %i states, end in %i", cmd->cmd.pathmove->num_states,
- cmd->cmd.pathmove->path[cmd->cmd.pathmove->num_states - 1]);
- gw16012_path_move(cmd->cmd.pathmove);
- break;
- case JTAG_SCAN:
- gw16012_end_state(cmd->cmd.scan->end_state);
- scan_size = jtag_build_buffer(cmd->cmd.scan, &buffer);
- type = jtag_scan_type(cmd->cmd.scan);
- LOG_DEBUG_IO("%s scan (%i) %i bit end in %i", (cmd->cmd.scan->ir_scan) ? "ir" : "dr",
- type, scan_size, cmd->cmd.scan->end_state);
- gw16012_scan(cmd->cmd.scan->ir_scan, type, buffer, scan_size);
- if (jtag_read_buffer(buffer, cmd->cmd.scan) != ERROR_OK)
- retval = ERROR_JTAG_QUEUE_FAILED;
- free(buffer);
- break;
- case JTAG_SLEEP:
- LOG_DEBUG_IO("sleep %" PRIu32, cmd->cmd.sleep->us);
- jtag_sleep(cmd->cmd.sleep->us);
- break;
- default:
- LOG_ERROR("BUG: unknown JTAG command type encountered");
- exit(-1);
+ case JTAG_RESET:
+ LOG_DEBUG_IO("reset trst: %i srst %i", cmd->cmd.reset->trst, cmd->cmd.reset->srst);
+ if (cmd->cmd.reset->trst == 1)
+ tap_set_state(TAP_RESET);
+ gw16012_reset(cmd->cmd.reset->trst, cmd->cmd.reset->srst);
+ break;
+ case JTAG_RUNTEST:
+ LOG_DEBUG_IO("runtest %u cycles, end in %i", cmd->cmd.runtest->num_cycles,
+ cmd->cmd.runtest->end_state);
+ gw16012_end_state(cmd->cmd.runtest->end_state);
+ gw16012_runtest(cmd->cmd.runtest->num_cycles);
+ break;
+ case JTAG_TLR_RESET:
+ LOG_DEBUG_IO("statemove end in %i", cmd->cmd.statemove->end_state);
+ gw16012_end_state(cmd->cmd.statemove->end_state);
+ gw16012_state_move();
+ break;
+ case JTAG_PATHMOVE:
+ LOG_DEBUG_IO("pathmove: %i states, end in %i", cmd->cmd.pathmove->num_states,
+ cmd->cmd.pathmove->path[cmd->cmd.pathmove->num_states - 1]);
+ gw16012_path_move(cmd->cmd.pathmove);
+ break;
+ case JTAG_SCAN:
+ gw16012_end_state(cmd->cmd.scan->end_state);
+ scan_size = jtag_build_buffer(cmd->cmd.scan, &buffer);
+ type = jtag_scan_type(cmd->cmd.scan);
+ LOG_DEBUG_IO("%s scan (%i) %i bit end in %i", (cmd->cmd.scan->ir_scan) ? "ir" : "dr",
+ type, scan_size, cmd->cmd.scan->end_state);
+ gw16012_scan(cmd->cmd.scan->ir_scan, type, buffer, scan_size);
+ if (jtag_read_buffer(buffer, cmd->cmd.scan) != ERROR_OK)
+ retval = ERROR_JTAG_QUEUE_FAILED;
+ free(buffer);
+ break;
+ case JTAG_SLEEP:
+ LOG_DEBUG_IO("sleep %" PRIu32, cmd->cmd.sleep->us);
+ jtag_sleep(cmd->cmd.sleep->us);
+ break;
+ default:
+ LOG_ERROR("BUG: unknown JTAG command type encountered");
+ exit(-1);
}
cmd = cmd->next;
}
@@ -461,6 +461,8 @@ static int gw16012_init(void)
{
uint8_t status_port;
+ LOG_WARNING("This adapter is deprecated and support will be removed in the next release!");
+
if (gw16012_init_device() != ERROR_OK)
return ERROR_JTAG_INIT_FAILED;
diff --git a/src/jtag/drivers/jlink.c b/src/jtag/drivers/jlink.c
index 9caf37f6f0..46afa862db 100644
--- a/src/jtag/drivers/jlink.c
+++ b/src/jtag/drivers/jlink.c
@@ -23,6 +23,7 @@
#include
#include
+#include
#include
#include
@@ -40,8 +41,6 @@ static struct jaylink_connection connlist[JAYLINK_MAX_CONNECTIONS];
static enum jaylink_jtag_version jtag_command_version;
static uint8_t caps[JAYLINK_DEV_EXT_CAPS_SIZE];
-static uint32_t serial_number;
-static bool use_serial_number;
static bool use_usb_location;
static enum jaylink_usb_address usb_address;
static bool use_usb_address;
@@ -242,7 +241,7 @@ static void jlink_execute_scan(struct jtag_command *cmd)
static void jlink_execute_sleep(struct jtag_command *cmd)
{
- LOG_DEBUG_IO("sleep %" PRIu32 "", cmd->cmd.sleep->us);
+ LOG_DEBUG_IO("sleep %" PRIu32, cmd->cmd.sleep->us);
jlink_flush();
jtag_sleep(cmd->cmd.sleep->us);
}
@@ -250,27 +249,27 @@ static void jlink_execute_sleep(struct jtag_command *cmd)
static int jlink_execute_command(struct jtag_command *cmd)
{
switch (cmd->type) {
- case JTAG_STABLECLOCKS:
- jlink_execute_stableclocks(cmd);
- break;
- case JTAG_RUNTEST:
- jlink_execute_runtest(cmd);
- break;
- case JTAG_TLR_RESET:
- jlink_execute_statemove(cmd);
- break;
- case JTAG_PATHMOVE:
- jlink_execute_pathmove(cmd);
- break;
- case JTAG_SCAN:
- jlink_execute_scan(cmd);
- break;
- case JTAG_SLEEP:
- jlink_execute_sleep(cmd);
- break;
- default:
- LOG_ERROR("BUG: Unknown JTAG command type encountered");
- return ERROR_JTAG_QUEUE_FAILED;
+ case JTAG_STABLECLOCKS:
+ jlink_execute_stableclocks(cmd);
+ break;
+ case JTAG_RUNTEST:
+ jlink_execute_runtest(cmd);
+ break;
+ case JTAG_TLR_RESET:
+ jlink_execute_statemove(cmd);
+ break;
+ case JTAG_PATHMOVE:
+ jlink_execute_pathmove(cmd);
+ break;
+ case JTAG_SCAN:
+ jlink_execute_scan(cmd);
+ break;
+ case JTAG_SLEEP:
+ jlink_execute_sleep(cmd);
+ break;
+ default:
+ LOG_ERROR("BUG: Unknown JTAG command type encountered");
+ return ERROR_JTAG_QUEUE_FAILED;
}
return ERROR_OK;
@@ -561,8 +560,9 @@ static int jlink_open_device(uint32_t ifaces, bool *found_device)
}
use_usb_location = !!adapter_usb_get_location();
+ const char *adapter_serial = adapter_get_required_serial();
- if (!use_serial_number && !use_usb_address && !use_usb_location && num_devices > 1) {
+ if (!adapter_serial && !use_usb_address && !use_usb_location && num_devices > 1) {
LOG_ERROR("Multiple devices found, specify the desired device");
LOG_INFO("Found devices:");
for (size_t i = 0; devs[i]; i++) {
@@ -575,7 +575,12 @@ static int jlink_open_device(uint32_t ifaces, bool *found_device)
jaylink_strerror(ret));
continue;
}
- LOG_INFO("Device %zu serial: %" PRIu32, i, serial);
+ char name[JAYLINK_NICKNAME_MAX_LENGTH];
+ int name_ret = jaylink_device_get_nickname(devs[i], name);
+ if (name_ret == JAYLINK_OK)
+ LOG_INFO("Device %zu serial: %" PRIu32 ", nickname %s", i, serial, name);
+ else
+ LOG_INFO("Device %zu serial: %" PRIu32, i, serial);
}
jaylink_free_devices(devs, true);
@@ -585,23 +590,39 @@ static int jlink_open_device(uint32_t ifaces, bool *found_device)
*found_device = false;
+ uint32_t serial_number;
+ ret = jaylink_parse_serial_number(adapter_serial, &serial_number);
+ if (ret != JAYLINK_OK)
+ serial_number = 0;
+
for (size_t i = 0; devs[i]; i++) {
struct jaylink_device *dev = devs[i];
- if (use_serial_number) {
- uint32_t tmp;
- ret = jaylink_device_get_serial_number(dev, &tmp);
-
- if (ret == JAYLINK_ERR_NOT_AVAILABLE) {
- continue;
- } else if (ret != JAYLINK_OK) {
- LOG_WARNING("jaylink_device_get_serial_number() failed: %s",
- jaylink_strerror(ret));
- continue;
+ if (adapter_serial) {
+ /*
+ * Treat adapter serial as a nickname first as it can also be numeric.
+ * If it fails to match (optional) device nickname try to compare
+ * adapter serial with the actual device serial number.
+ */
+ char nickname[JAYLINK_NICKNAME_MAX_LENGTH];
+ ret = jaylink_device_get_nickname(dev, nickname);
+ if (ret != JAYLINK_OK || strcmp(nickname, adapter_serial) != 0) {
+ if (!serial_number)
+ continue;
+
+ uint32_t tmp;
+ ret = jaylink_device_get_serial_number(dev, &tmp);
+ if (ret == JAYLINK_ERR_NOT_AVAILABLE) {
+ continue;
+ } else if (ret != JAYLINK_OK) {
+ LOG_WARNING("jaylink_device_get_serial_number() failed: %s",
+ jaylink_strerror(ret));
+ continue;
+ }
+
+ if (serial_number != tmp)
+ continue;
}
-
- if (serial_number != tmp)
- continue;
}
if (use_usb_address) {
@@ -670,29 +691,15 @@ static int jlink_init(void)
return ERROR_JTAG_INIT_FAILED;
}
- const char *serial = adapter_get_required_serial();
- if (serial) {
- ret = jaylink_parse_serial_number(serial, &serial_number);
- if (ret == JAYLINK_ERR) {
- LOG_ERROR("Invalid serial number: %s", serial);
- jaylink_exit(jayctx);
- return ERROR_JTAG_INIT_FAILED;
- }
- if (ret != JAYLINK_OK) {
- LOG_ERROR("jaylink_parse_serial_number() failed: %s", jaylink_strerror(ret));
- jaylink_exit(jayctx);
- return ERROR_JTAG_INIT_FAILED;
- }
- use_serial_number = true;
+ if (adapter_get_required_serial())
use_usb_address = false;
- }
bool found_device;
ret = jlink_open_device(JAYLINK_HIF_USB, &found_device);
if (ret != ERROR_OK)
return ret;
- if (!found_device && use_serial_number) {
+ if (!found_device && adapter_get_required_serial()) {
ret = jlink_open_device(JAYLINK_HIF_TCP, &found_device);
if (ret != ERROR_OK)
return ret;
@@ -2111,44 +2118,44 @@ static int jlink_swd_switch_seq(enum swd_special_seq seq)
unsigned int s_len;
switch (seq) {
- case LINE_RESET:
- LOG_DEBUG_IO("SWD line reset");
- s = swd_seq_line_reset;
- s_len = swd_seq_line_reset_len;
- break;
- case JTAG_TO_SWD:
- LOG_DEBUG("JTAG-to-SWD");
- s = swd_seq_jtag_to_swd;
- s_len = swd_seq_jtag_to_swd_len;
- break;
- case JTAG_TO_DORMANT:
- LOG_DEBUG("JTAG-to-DORMANT");
- s = swd_seq_jtag_to_dormant;
- s_len = swd_seq_jtag_to_dormant_len;
- break;
- case SWD_TO_JTAG:
- LOG_DEBUG("SWD-to-JTAG");
- s = swd_seq_swd_to_jtag;
- s_len = swd_seq_swd_to_jtag_len;
- break;
- case SWD_TO_DORMANT:
- LOG_DEBUG("SWD-to-DORMANT");
- s = swd_seq_swd_to_dormant;
- s_len = swd_seq_swd_to_dormant_len;
- break;
- case DORMANT_TO_SWD:
- LOG_DEBUG("DORMANT-to-SWD");
- s = swd_seq_dormant_to_swd;
- s_len = swd_seq_dormant_to_swd_len;
- break;
- case DORMANT_TO_JTAG:
- LOG_DEBUG("DORMANT-to-JTAG");
- s = swd_seq_dormant_to_jtag;
- s_len = swd_seq_dormant_to_jtag_len;
- break;
- default:
- LOG_ERROR("Sequence %d not supported", seq);
- return ERROR_FAIL;
+ case LINE_RESET:
+ LOG_DEBUG_IO("SWD line reset");
+ s = swd_seq_line_reset;
+ s_len = swd_seq_line_reset_len;
+ break;
+ case JTAG_TO_SWD:
+ LOG_DEBUG("JTAG-to-SWD");
+ s = swd_seq_jtag_to_swd;
+ s_len = swd_seq_jtag_to_swd_len;
+ break;
+ case JTAG_TO_DORMANT:
+ LOG_DEBUG("JTAG-to-DORMANT");
+ s = swd_seq_jtag_to_dormant;
+ s_len = swd_seq_jtag_to_dormant_len;
+ break;
+ case SWD_TO_JTAG:
+ LOG_DEBUG("SWD-to-JTAG");
+ s = swd_seq_swd_to_jtag;
+ s_len = swd_seq_swd_to_jtag_len;
+ break;
+ case SWD_TO_DORMANT:
+ LOG_DEBUG("SWD-to-DORMANT");
+ s = swd_seq_swd_to_dormant;
+ s_len = swd_seq_swd_to_dormant_len;
+ break;
+ case DORMANT_TO_SWD:
+ LOG_DEBUG("DORMANT-to-SWD");
+ s = swd_seq_dormant_to_swd;
+ s_len = swd_seq_dormant_to_swd_len;
+ break;
+ case DORMANT_TO_JTAG:
+ LOG_DEBUG("DORMANT-to-JTAG");
+ s = swd_seq_dormant_to_jtag;
+ s_len = swd_seq_dormant_to_jtag_len;
+ break;
+ default:
+ LOG_ERROR("Sequence %d not supported", seq);
+ return ERROR_FAIL;
}
jlink_queue_data_out(s, s_len);
diff --git a/src/jtag/drivers/kitprog.c b/src/jtag/drivers/kitprog.c
index 88e301cebc..f79e2dca70 100644
--- a/src/jtag/drivers/kitprog.c
+++ b/src/jtag/drivers/kitprog.c
@@ -646,25 +646,24 @@ static void kitprog_swd_read_reg(uint8_t cmd, uint32_t *value, uint32_t ap_delay
static int kitprog_swd_switch_seq(enum swd_special_seq seq)
{
switch (seq) {
- case JTAG_TO_SWD:
- if (kitprog_handle->supports_jtag_to_swd) {
- LOG_DEBUG("JTAG to SWD");
- if (kitprog_swd_seq(SEQUENCE_JTAG_TO_SWD) != ERROR_OK)
- return ERROR_FAIL;
- break;
- } else {
- LOG_DEBUG("JTAG to SWD not supported");
- /* Fall through to fix target reset issue */
- }
- /* fallthrough */
- case LINE_RESET:
- LOG_DEBUG("SWD line reset");
- if (kitprog_swd_seq(SEQUENCE_LINE_RESET) != ERROR_OK)
+ case JTAG_TO_SWD:
+ if (kitprog_handle->supports_jtag_to_swd) {
+ LOG_DEBUG("JTAG to SWD");
+ if (kitprog_swd_seq(SEQUENCE_JTAG_TO_SWD) != ERROR_OK)
return ERROR_FAIL;
break;
- default:
- LOG_ERROR("Sequence %d not supported.", seq);
+ }
+ LOG_DEBUG("JTAG to SWD not supported");
+ /* Fall through to fix target reset issue */
+ /* fallthrough */
+ case LINE_RESET:
+ LOG_DEBUG("SWD line reset");
+ if (kitprog_swd_seq(SEQUENCE_LINE_RESET) != ERROR_OK)
return ERROR_FAIL;
+ break;
+ default:
+ LOG_ERROR("Sequence %d not supported.", seq);
+ return ERROR_FAIL;
}
return ERROR_OK;
diff --git a/src/jtag/drivers/linuxgpiod.c b/src/jtag/drivers/linuxgpiod.c
index 36c7e04934..cc738e9a30 100644
--- a/src/jtag/drivers/linuxgpiod.c
+++ b/src/jtag/drivers/linuxgpiod.c
@@ -19,8 +19,278 @@
#include
#include "bitbang.h"
+/*
+ * In case of libgpiod v1, use as much as possible API from v2 plus
+ * the dummy wrappers below.
+ */
+#ifdef HAVE_LIBGPIOD_V1
+
+#define GPIOD_LINE_DIRECTION_INPUT GPIOD_LINE_REQUEST_DIRECTION_INPUT
+#define GPIOD_LINE_DIRECTION_OUTPUT GPIOD_LINE_REQUEST_DIRECTION_OUTPUT
+
+#define GPIOD_LINE_VALUE_INACTIVE 0
+#define GPIOD_LINE_VALUE_ACTIVE 1
+
+#define GPIOD_LINE_DRIVE_PUSH_PULL 0
+#define GPIOD_LINE_DRIVE_OPEN_DRAIN GPIOD_LINE_REQUEST_FLAG_OPEN_DRAIN
+#define GPIOD_LINE_DRIVE_OPEN_SOURCE GPIOD_LINE_REQUEST_FLAG_OPEN_SOURCE
+
+#define GPIOD_LINE_BIAS_DISABLED GPIOD_LINE_REQUEST_FLAG_BIAS_DISABLE
+#define GPIOD_LINE_BIAS_PULL_UP GPIOD_LINE_REQUEST_FLAG_BIAS_PULL_UP
+#define GPIOD_LINE_BIAS_PULL_DOWN GPIOD_LINE_REQUEST_FLAG_BIAS_PULL_DOWN
+
+struct gpiod_line_settings {
+ int direction;
+ int value;
+ int drive;
+ int bias;
+ int active_low;
+};
+
+static struct gpiod_line_settings *gpiod_line_settings_new(void)
+{
+ struct gpiod_line_settings *rv;
+
+ rv = calloc(sizeof(struct gpiod_line_settings), 1);
+ if (!rv) {
+ LOG_ERROR("No memory for gpiod line settings");
+ return NULL;
+ }
+
+ return rv;
+}
+
+static void gpiod_line_settings_free(struct gpiod_line_settings *settings)
+{
+ free(settings);
+}
+
+static int gpiod_line_settings_set_direction(struct gpiod_line_settings *settings,
+ int direction)
+{
+ settings->direction = direction;
+
+ return 0;
+}
+
+static int gpiod_line_settings_set_output_value(struct gpiod_line_settings *settings,
+ int value)
+{
+ settings->value = value;
+
+ return 0;
+}
+
+static int gpiod_line_settings_set_drive(struct gpiod_line_settings *settings, int drive)
+{
+ settings->drive = drive;
+
+ return 0;
+}
+
+static void gpiod_line_settings_set_active_low(struct gpiod_line_settings *settings,
+ bool active_low)
+{
+ if (active_low)
+ settings->active_low = GPIOD_LINE_REQUEST_FLAG_ACTIVE_LOW;
+}
+
+#ifdef HAVE_LIBGPIOD1_FLAGS_BIAS
+
+static int gpiod_line_settings_set_bias(struct gpiod_line_settings *settings, int bias)
+{
+ settings->bias = bias;
+
+ return 0;
+}
+
+#else /* HAVE_LIBGPIOD1_FLAGS_BIAS */
+
+static int gpiod_line_settings_set_bias(struct gpiod_line_settings *settings, int bias)
+{
+ if (bias == GPIOD_LINE_BIAS_DISABLED)
+ return 0;
+
+ LOG_WARNING("linuxgpiod: ignoring request for pull-%s: not supported by libgpiod v%s",
+ (bias == GPIOD_LINE_BIAS_PULL_UP) ? "up" : "down",
+ gpiod_version_string());
+
+ return 0;
+}
+
+#endif /* HAVE_LIBGPIOD1_FLAGS_BIAS */
+
+struct gpiod_line_config {
+ unsigned int gpio_num;
+ struct gpiod_line_settings *line_settings;
+};
+
+static struct gpiod_line_config *gpiod_line_config_new(void)
+{
+ struct gpiod_line_config *rv;
+
+ rv = calloc(sizeof(struct gpiod_line_config), 1);
+ if (!rv) {
+ LOG_ERROR("No memory for gpiod line config");
+ return NULL;
+ }
+
+ return rv;
+}
+
+static void gpiod_line_config_free(struct gpiod_line_config *config)
+{
+ free(config);
+}
+
+static int gpiod_line_config_add_line_settings(struct gpiod_line_config *config,
+ const unsigned int *offsets, size_t num_offsets, struct gpiod_line_settings *settings)
+{
+ assert(num_offsets == 1);
+
+ config->gpio_num = *offsets;
+ config->line_settings = settings;
+
+ return 0;
+}
+
+struct gpiod_request_config {
+ const char *consumer;
+};
+
+static struct gpiod_request_config *gpiod_request_config_new(void)
+{
+ struct gpiod_request_config *rv;
+
+ rv = calloc(sizeof(struct gpiod_request_config), 1);
+ if (!rv) {
+ LOG_ERROR("No memory for gpiod request config");
+ return NULL;
+ }
+
+ return rv;
+}
+
+static void gpiod_request_config_free(struct gpiod_request_config *config)
+{
+ free(config);
+}
+
+static void gpiod_request_config_set_consumer(struct gpiod_request_config *config,
+ const char *consumer)
+{
+ config->consumer = consumer;
+}
+
+struct gpiod_line_request {
+ struct gpiod_line *gpio_line;
+ struct gpiod_chip *chip;
+ struct gpiod_request_config *req_cfg;
+ struct gpiod_line_config *line_cfg;
+};
+
+static void gpiod_line_request_release(struct gpiod_line_request *request);
+
+static struct gpiod_line_request *gpiod_chip_request_lines(struct gpiod_chip *chip,
+ struct gpiod_request_config *req_cfg, struct gpiod_line_config *line_cfg)
+{
+ struct gpiod_line_request *line_req;
+ int rv, flags = 0;
+
+ assert(req_cfg);
+
+ line_req = calloc(sizeof(struct gpiod_line_request), 1);
+ if (!line_req) {
+ LOG_ERROR("No memory for gpiod line request");
+ return NULL;
+ }
+
+ line_req->gpio_line = gpiod_chip_get_line(chip, line_cfg->gpio_num);
+ if (!line_req->gpio_line) {
+ free(line_req);
+ return NULL;
+ }
+
+ /* remember stuff in case we need to reconfigure later */
+ line_req->chip = chip;
+ line_req->req_cfg = gpiod_request_config_new();
+ *line_req->req_cfg = *req_cfg;
+ line_req->line_cfg = line_cfg;
+
+ flags |= line_cfg->line_settings->drive;
+ flags |= line_cfg->line_settings->bias;
+ flags |= line_cfg->line_settings->active_low;
+
+ struct gpiod_line_request_config config = {
+ .consumer = line_req->req_cfg->consumer,
+ .request_type = line_cfg->line_settings->direction,
+ .flags = flags,
+ };
+
+ rv = gpiod_line_request(line_req->gpio_line, &config, line_cfg->line_settings->value);
+ if (rv < 0) {
+ gpiod_line_request_release(line_req);
+ return NULL;
+ }
+
+ return line_req;
+}
+
+static int gpiod_line_request_get_value(struct gpiod_line_request *request,
+ __attribute__((unused)) unsigned int offset)
+{
+ return gpiod_line_get_value(request->gpio_line);
+}
+
+static int gpiod_line_request_set_value(struct gpiod_line_request *request,
+ __attribute__((unused)) unsigned int offset, int value)
+{
+ return gpiod_line_set_value(request->gpio_line, value);
+}
+
+static void gpiod_line_request_release(struct gpiod_line_request *request)
+{
+ gpiod_request_config_free(request->req_cfg);
+ gpiod_line_release(request->gpio_line);
+ free(request);
+}
+
+static int gpiod_line_request_reconfigure_lines(struct gpiod_line_request *request,
+ struct gpiod_line_config *line_cfg)
+{
+ int rv, flags = 0;
+
+ /* in libgpiod v1 we have to release the line and re-aquire it */
+ gpiod_line_release(request->gpio_line);
+ request->gpio_line = gpiod_chip_get_line(request->chip, request->line_cfg->gpio_num);
+ if (!request->gpio_line)
+ return -1;
+
+ flags |= line_cfg->line_settings->drive;
+ flags |= line_cfg->line_settings->bias;
+ flags |= line_cfg->line_settings->active_low;
+
+ struct gpiod_line_request_config config = {
+ .consumer = request->req_cfg->consumer,
+ .request_type = line_cfg->line_settings->direction,
+ .flags = flags,
+ };
+
+ rv = gpiod_line_request(request->gpio_line, &config, line_cfg->line_settings->value);
+ if (rv < 0)
+ return -1;
+
+ /* remember updated line_cfg */
+ request->line_cfg = line_cfg;
+ return 0;
+}
+
+#endif /* HAVE_LIBGPIOD_V1 */
+
static struct gpiod_chip *gpiod_chip[ADAPTER_GPIO_IDX_NUM] = {};
-static struct gpiod_line *gpiod_line[ADAPTER_GPIO_IDX_NUM] = {};
+static struct gpiod_line_settings *gpiod_line_settings[ADAPTER_GPIO_IDX_NUM] = {};
+static struct gpiod_line_config *gpiod_line_config[ADAPTER_GPIO_IDX_NUM] = {};
+static struct gpiod_line_request *gpiod_line_req[ADAPTER_GPIO_IDX_NUM] = {};
static int last_swclk;
static int last_swdio;
@@ -29,6 +299,20 @@ static bool swdio_input;
static const struct adapter_gpio_config *adapter_gpio_config;
+/* Helper to get/set a single line */
+static int linuxgpiod_line_get_value(enum adapter_gpio_config_index idx)
+{
+ return gpiod_line_request_get_value(gpiod_line_req[idx],
+ adapter_gpio_config[idx].gpio_num);
+}
+
+static int linuxgpiod_line_set_value(enum adapter_gpio_config_index idx, int value)
+{
+ return gpiod_line_request_set_value(gpiod_line_req[idx],
+ adapter_gpio_config[idx].gpio_num,
+ value);
+}
+
/*
* Helper function to determine if gpio config is valid
*
@@ -46,7 +330,7 @@ static enum bb_value linuxgpiod_read(void)
{
int retval;
- retval = gpiod_line_get_value(gpiod_line[ADAPTER_GPIO_IDX_TDO]);
+ retval = linuxgpiod_line_get_value(ADAPTER_GPIO_IDX_TDO);
if (retval < 0) {
LOG_WARNING("reading tdo failed");
return 0;
@@ -79,20 +363,20 @@ static int linuxgpiod_write(int tck, int tms, int tdi)
}
if (tdi != last_tdi) {
- retval = gpiod_line_set_value(gpiod_line[ADAPTER_GPIO_IDX_TDI], tdi);
+ retval = linuxgpiod_line_set_value(ADAPTER_GPIO_IDX_TDI, tdi);
if (retval < 0)
LOG_WARNING("writing tdi failed");
}
if (tms != last_tms) {
- retval = gpiod_line_set_value(gpiod_line[ADAPTER_GPIO_IDX_TMS], tms);
+ retval = linuxgpiod_line_set_value(ADAPTER_GPIO_IDX_TMS, tms);
if (retval < 0)
LOG_WARNING("writing tms failed");
}
/* write clk last */
if (tck != last_tck) {
- retval = gpiod_line_set_value(gpiod_line[ADAPTER_GPIO_IDX_TCK], tck);
+ retval = linuxgpiod_line_set_value(ADAPTER_GPIO_IDX_TCK, tck);
if (retval < 0)
LOG_WARNING("writing tck failed");
}
@@ -108,7 +392,7 @@ static int linuxgpiod_swdio_read(void)
{
int retval;
- retval = gpiod_line_get_value(gpiod_line[ADAPTER_GPIO_IDX_SWDIO]);
+ retval = linuxgpiod_line_get_value(ADAPTER_GPIO_IDX_SWDIO);
if (retval < 0) {
LOG_WARNING("Fail read swdio");
return 0;
@@ -121,30 +405,54 @@ static void linuxgpiod_swdio_drive(bool is_output)
{
int retval;
- /*
- * FIXME: change direction requires release and re-require the line
- * https://stackoverflow.com/questions/58735140/
- * this would change in future libgpiod
- */
- gpiod_line_release(gpiod_line[ADAPTER_GPIO_IDX_SWDIO]);
-
if (is_output) {
- if (gpiod_line[ADAPTER_GPIO_IDX_SWDIO_DIR]) {
- retval = gpiod_line_set_value(gpiod_line[ADAPTER_GPIO_IDX_SWDIO_DIR], 1);
+ if (gpiod_line_req[ADAPTER_GPIO_IDX_SWDIO_DIR]) {
+ retval = linuxgpiod_line_set_value(ADAPTER_GPIO_IDX_SWDIO_DIR, 1);
if (retval < 0)
- LOG_WARNING("Fail set swdio_dir");
+ LOG_WARNING("Failed to set swdio_dir=1");
}
- retval = gpiod_line_request_output(gpiod_line[ADAPTER_GPIO_IDX_SWDIO], "OpenOCD", 1);
+
+ retval = gpiod_line_settings_set_direction(gpiod_line_settings[ADAPTER_GPIO_IDX_SWDIO],
+ GPIOD_LINE_DIRECTION_OUTPUT);
+ if (retval < 0)
+ LOG_WARNING("Failed to set new direction of swdio");
+
+ retval = gpiod_line_settings_set_output_value(gpiod_line_settings[ADAPTER_GPIO_IDX_SWDIO],
+ GPIOD_LINE_VALUE_ACTIVE);
+ if (retval < 0)
+ LOG_WARNING("Failed to set output value of swdio");
+
+ retval = gpiod_line_config_add_line_settings(gpiod_line_config[ADAPTER_GPIO_IDX_SWDIO],
+ &adapter_gpio_config[ADAPTER_GPIO_IDX_SWDIO].gpio_num, 1,
+ gpiod_line_settings[ADAPTER_GPIO_IDX_SWDIO]);
+ if (retval < 0)
+ LOG_WARNING("Failed to apply output configuration to swdio");
+
+ retval = gpiod_line_request_reconfigure_lines(gpiod_line_req[ADAPTER_GPIO_IDX_SWDIO],
+ gpiod_line_config[ADAPTER_GPIO_IDX_SWDIO]);
if (retval < 0)
- LOG_WARNING("Fail request_output line swdio");
+ LOG_WARNING("Failed to switch swdio to output");
} else {
- retval = gpiod_line_request_input(gpiod_line[ADAPTER_GPIO_IDX_SWDIO], "OpenOCD");
+ retval = gpiod_line_settings_set_direction(gpiod_line_settings[ADAPTER_GPIO_IDX_SWDIO],
+ GPIOD_LINE_DIRECTION_INPUT);
if (retval < 0)
- LOG_WARNING("Fail request_input line swdio");
- if (gpiod_line[ADAPTER_GPIO_IDX_SWDIO_DIR]) {
- retval = gpiod_line_set_value(gpiod_line[ADAPTER_GPIO_IDX_SWDIO_DIR], 0);
+ LOG_WARNING("Failed to switch swdio to output");
+
+ retval = gpiod_line_config_add_line_settings(gpiod_line_config[ADAPTER_GPIO_IDX_SWDIO],
+ &adapter_gpio_config[ADAPTER_GPIO_IDX_SWDIO].gpio_num, 1,
+ gpiod_line_settings[ADAPTER_GPIO_IDX_SWDIO]);
+ if (retval < 0)
+ LOG_WARNING("Failed to apply input configuration to swdio");
+
+ retval = gpiod_line_request_reconfigure_lines(gpiod_line_req[ADAPTER_GPIO_IDX_SWDIO],
+ gpiod_line_config[ADAPTER_GPIO_IDX_SWDIO]);
+ if (retval < 0)
+ LOG_WARNING("Failed to switch swdio to input");
+
+ if (gpiod_line_req[ADAPTER_GPIO_IDX_SWDIO_DIR]) {
+ retval = linuxgpiod_line_set_value(ADAPTER_GPIO_IDX_SWDIO_DIR, 0);
if (retval < 0)
- LOG_WARNING("Fail set swdio_dir");
+ LOG_WARNING("Failed to set swdio_dir=0");
}
}
@@ -158,7 +466,7 @@ static int linuxgpiod_swd_write(int swclk, int swdio)
if (!swdio_input) {
if (!last_stored || swdio != last_swdio) {
- retval = gpiod_line_set_value(gpiod_line[ADAPTER_GPIO_IDX_SWDIO], swdio);
+ retval = linuxgpiod_line_set_value(ADAPTER_GPIO_IDX_SWDIO, swdio);
if (retval < 0)
LOG_WARNING("Fail set swdio");
}
@@ -166,7 +474,7 @@ static int linuxgpiod_swd_write(int swclk, int swdio)
/* write swclk last */
if (!last_stored || swclk != last_swclk) {
- retval = gpiod_line_set_value(gpiod_line[ADAPTER_GPIO_IDX_SWCLK], swclk);
+ retval = linuxgpiod_line_set_value(ADAPTER_GPIO_IDX_SWCLK, swclk);
if (retval < 0)
LOG_WARNING("Fail set swclk");
}
@@ -185,7 +493,7 @@ static int linuxgpiod_blink(bool on)
if (!is_gpio_config_valid(ADAPTER_GPIO_IDX_LED))
return ERROR_OK;
- retval = gpiod_line_set_value(gpiod_line[ADAPTER_GPIO_IDX_LED], on ? 1 : 0);
+ retval = linuxgpiod_line_set_value(ADAPTER_GPIO_IDX_LED, on);
if (retval < 0)
LOG_WARNING("Fail set led");
return retval;
@@ -212,17 +520,17 @@ static int linuxgpiod_reset(int trst, int srst)
LOG_DEBUG("linuxgpiod_reset");
/*
- * active low behaviour handled by "adaptor gpio" command and
+ * active low behavior handled by "adaptor gpio" command and
* GPIOD_LINE_REQUEST_FLAG_ACTIVE_LOW flag when requesting the line.
*/
- if (gpiod_line[ADAPTER_GPIO_IDX_SRST]) {
- retval1 = gpiod_line_set_value(gpiod_line[ADAPTER_GPIO_IDX_SRST], srst);
+ if (gpiod_line_req[ADAPTER_GPIO_IDX_SRST]) {
+ retval1 = linuxgpiod_line_set_value(ADAPTER_GPIO_IDX_SRST, srst);
if (retval1 < 0)
LOG_WARNING("set srst value failed");
}
- if (gpiod_line[ADAPTER_GPIO_IDX_TRST]) {
- retval2 = gpiod_line_set_value(gpiod_line[ADAPTER_GPIO_IDX_TRST], trst);
+ if (gpiod_line_req[ADAPTER_GPIO_IDX_TRST]) {
+ retval2 = linuxgpiod_line_set_value(ADAPTER_GPIO_IDX_TRST, trst);
if (retval2 < 0)
LOG_WARNING("set trst value failed");
}
@@ -254,9 +562,17 @@ static bool linuxgpiod_swd_mode_possible(void)
static inline void helper_release(enum adapter_gpio_config_index idx)
{
- if (gpiod_line[idx]) {
- gpiod_line_release(gpiod_line[idx]);
- gpiod_line[idx] = NULL;
+ if (gpiod_line_req[idx]) {
+ gpiod_line_request_release(gpiod_line_req[idx]);
+ gpiod_line_req[idx] = NULL;
+ }
+ if (gpiod_line_config[idx]) {
+ gpiod_line_config_free(gpiod_line_config[idx]);
+ gpiod_line_config[idx] = NULL;
+ }
+ if (gpiod_line_settings[idx]) {
+ gpiod_line_settings_free(gpiod_line_settings[idx]);
+ gpiod_line_settings[idx] = NULL;
}
if (gpiod_chip[idx]) {
gpiod_chip_close(gpiod_chip[idx]);
@@ -275,84 +591,103 @@ static int linuxgpiod_quit(void)
static int helper_get_line(enum adapter_gpio_config_index idx)
{
+ struct gpiod_request_config *req_cfg = NULL;
+ char chip_path[24];
+ int rv = 0;
+
if (!is_gpio_config_valid(idx))
return ERROR_OK;
- int dir = GPIOD_LINE_REQUEST_DIRECTION_INPUT, flags = 0, val = 0, retval;
+ snprintf(chip_path, sizeof(chip_path), "/dev/gpiochip%u", adapter_gpio_config[idx].chip_num);
+ gpiod_chip[idx] = gpiod_chip_open(chip_path);
- gpiod_chip[idx] = gpiod_chip_open_by_number(adapter_gpio_config[idx].chip_num);
if (!gpiod_chip[idx]) {
LOG_ERROR("Cannot open LinuxGPIOD chip %d for %s", adapter_gpio_config[idx].chip_num,
adapter_gpio_get_name(idx));
return ERROR_JTAG_INIT_FAILED;
}
- gpiod_line[idx] = gpiod_chip_get_line(gpiod_chip[idx], adapter_gpio_config[idx].gpio_num);
- if (!gpiod_line[idx]) {
- LOG_ERROR("Error get line %s", adapter_gpio_get_name(idx));
+ gpiod_line_settings[idx] = gpiod_line_settings_new();
+ gpiod_line_config[idx] = gpiod_line_config_new();
+ req_cfg = gpiod_request_config_new();
+
+ if (!gpiod_line_settings[idx] || !gpiod_line_config[idx] || !req_cfg) {
+ LOG_ERROR("Cannot configure LinuxGPIOD line for %s", adapter_gpio_get_name(idx));
+ gpiod_request_config_free(req_cfg);
return ERROR_JTAG_INIT_FAILED;
}
+ gpiod_request_config_set_consumer(req_cfg, "OpenOCD");
+
switch (adapter_gpio_config[idx].init_state) {
case ADAPTER_GPIO_INIT_STATE_INPUT:
- dir = GPIOD_LINE_REQUEST_DIRECTION_INPUT;
+ rv = gpiod_line_settings_set_direction(gpiod_line_settings[idx], GPIOD_LINE_DIRECTION_INPUT);
break;
case ADAPTER_GPIO_INIT_STATE_INACTIVE:
- dir = GPIOD_LINE_REQUEST_DIRECTION_OUTPUT;
- val = 0;
+ rv = gpiod_line_settings_set_direction(gpiod_line_settings[idx], GPIOD_LINE_DIRECTION_OUTPUT);
+ rv |= gpiod_line_settings_set_output_value(gpiod_line_settings[idx], GPIOD_LINE_VALUE_INACTIVE);
break;
case ADAPTER_GPIO_INIT_STATE_ACTIVE:
- dir = GPIOD_LINE_REQUEST_DIRECTION_OUTPUT;
- val = 1;
+ rv = gpiod_line_settings_set_direction(gpiod_line_settings[idx], GPIOD_LINE_DIRECTION_OUTPUT);
+ rv |= gpiod_line_settings_set_output_value(gpiod_line_settings[idx], GPIOD_LINE_VALUE_ACTIVE);
break;
}
+ if (rv < 0) {
+ LOG_ERROR("Error while configuring LinuxGPIOD line init state for %s", adapter_gpio_get_name(idx));
+ gpiod_request_config_free(req_cfg);
+ return ERROR_JTAG_INIT_FAILED;
+ }
switch (adapter_gpio_config[idx].drive) {
case ADAPTER_GPIO_DRIVE_MODE_PUSH_PULL:
+ rv = gpiod_line_settings_set_drive(gpiod_line_settings[idx], GPIOD_LINE_DRIVE_PUSH_PULL);
break;
case ADAPTER_GPIO_DRIVE_MODE_OPEN_DRAIN:
- flags |= GPIOD_LINE_REQUEST_FLAG_OPEN_DRAIN;
+ rv = gpiod_line_settings_set_drive(gpiod_line_settings[idx], GPIOD_LINE_DRIVE_OPEN_DRAIN);
break;
case ADAPTER_GPIO_DRIVE_MODE_OPEN_SOURCE:
- flags |= GPIOD_LINE_REQUEST_FLAG_OPEN_SOURCE;
+ rv = gpiod_line_settings_set_drive(gpiod_line_settings[idx], GPIOD_LINE_DRIVE_OPEN_SOURCE);
break;
}
+ if (rv < 0) {
+ LOG_ERROR("Error while configuring LinuxGPIOD line driving for %s", adapter_gpio_get_name(idx));
+ gpiod_request_config_free(req_cfg);
+ return ERROR_JTAG_INIT_FAILED;
+ }
switch (adapter_gpio_config[idx].pull) {
case ADAPTER_GPIO_PULL_NONE:
-#ifdef HAVE_LIBGPIOD1_FLAGS_BIAS
- flags |= GPIOD_LINE_REQUEST_FLAG_BIAS_DISABLE;
-#endif
+ rv = gpiod_line_settings_set_bias(gpiod_line_settings[idx], GPIOD_LINE_BIAS_DISABLED);
break;
case ADAPTER_GPIO_PULL_UP:
-#ifdef HAVE_LIBGPIOD1_FLAGS_BIAS
- flags |= GPIOD_LINE_REQUEST_FLAG_BIAS_PULL_UP;
-#else
- LOG_WARNING("linuxgpiod: ignoring request for pull-up on %s: not supported by gpiod v%s",
- adapter_gpio_get_name(idx), gpiod_version_string());
-#endif
+ rv = gpiod_line_settings_set_bias(gpiod_line_settings[idx], GPIOD_LINE_BIAS_PULL_UP);
break;
case ADAPTER_GPIO_PULL_DOWN:
-#ifdef HAVE_LIBGPIOD1_FLAGS_BIAS
- flags |= GPIOD_LINE_REQUEST_FLAG_BIAS_PULL_DOWN;
-#else
- LOG_WARNING("linuxgpiod: ignoring request for pull-down on %s: not supported by gpiod v%s",
- adapter_gpio_get_name(idx), gpiod_version_string());
-#endif
+ rv = gpiod_line_settings_set_bias(gpiod_line_settings[idx], GPIOD_LINE_BIAS_PULL_DOWN);
break;
}
+ if (rv < 0) {
+ LOG_ERROR("Error while configuring LinuxGPIOD line biasing for %s", adapter_gpio_get_name(idx));
+ gpiod_request_config_free(req_cfg);
+ return ERROR_JTAG_INIT_FAILED;
+ }
- if (adapter_gpio_config[idx].active_low)
- flags |= GPIOD_LINE_REQUEST_FLAG_ACTIVE_LOW;
+ gpiod_line_settings_set_active_low(gpiod_line_settings[idx], adapter_gpio_config[idx].active_low);
- struct gpiod_line_request_config config = {
- .consumer = "OpenOCD",
- .request_type = dir,
- .flags = flags,
- };
+ rv = gpiod_line_config_add_line_settings(gpiod_line_config[idx],
+ &adapter_gpio_config[idx].gpio_num, 1,
+ gpiod_line_settings[idx]);
+ if (rv < 0) {
+ LOG_ERROR("Error configuring gpio line %s", adapter_gpio_get_name(idx));
+ gpiod_request_config_free(req_cfg);
+ return ERROR_JTAG_INIT_FAILED;
+ }
- retval = gpiod_line_request(gpiod_line[idx], &config, val);
- if (retval < 0) {
+ gpiod_line_req[idx] = gpiod_chip_request_lines(gpiod_chip[idx], req_cfg, gpiod_line_config[idx]);
+
+ gpiod_request_config_free(req_cfg);
+
+ if (!gpiod_line_req[idx]) {
LOG_ERROR("Error requesting gpio line %s", adapter_gpio_get_name(idx));
return ERROR_JTAG_INIT_FAILED;
}
diff --git a/src/jtag/drivers/opendous.c b/src/jtag/drivers/opendous.c
index 04626cb1e5..4b5981ab5d 100644
--- a/src/jtag/drivers/opendous.c
+++ b/src/jtag/drivers/opendous.c
@@ -173,26 +173,26 @@ COMMAND_HANDLER(opendous_handle_opendous_info_command)
COMMAND_HANDLER(opendous_handle_opendous_hw_jtag_command)
{
switch (CMD_ARGC) {
- case 0:
- command_print(CMD, "opendous hw jtag %i", opendous_hw_jtag_version);
+ case 0:
+ command_print(CMD, "opendous hw jtag %i", opendous_hw_jtag_version);
+ break;
+
+ case 1: {
+ int request_version = atoi(CMD_ARGV[0]);
+ switch (request_version) {
+ case 2:
+ case 3:
+ opendous_hw_jtag_version = request_version;
break;
- case 1: {
- int request_version = atoi(CMD_ARGV[0]);
- switch (request_version) {
- case 2:
- case 3:
- opendous_hw_jtag_version = request_version;
- break;
-
- default:
- return ERROR_COMMAND_SYNTAX_ERROR;
- }
- break;
- }
-
default:
return ERROR_COMMAND_SYNTAX_ERROR;
+ }
+ break;
+ }
+
+ default:
+ return ERROR_COMMAND_SYNTAX_ERROR;
}
return ERROR_OK;
@@ -248,66 +248,66 @@ static int opendous_execute_queue(struct jtag_command *cmd_queue)
while (cmd) {
switch (cmd->type) {
- case JTAG_RUNTEST:
- LOG_DEBUG_IO("runtest %u cycles, end in %i", cmd->cmd.runtest->num_cycles,
- cmd->cmd.runtest->end_state);
+ case JTAG_RUNTEST:
+ LOG_DEBUG_IO("runtest %u cycles, end in %i", cmd->cmd.runtest->num_cycles,
+ cmd->cmd.runtest->end_state);
- if (cmd->cmd.runtest->end_state != -1)
- opendous_end_state(cmd->cmd.runtest->end_state);
- opendous_runtest(cmd->cmd.runtest->num_cycles);
- break;
+ if (cmd->cmd.runtest->end_state != -1)
+ opendous_end_state(cmd->cmd.runtest->end_state);
+ opendous_runtest(cmd->cmd.runtest->num_cycles);
+ break;
- case JTAG_TLR_RESET:
- LOG_DEBUG_IO("statemove end in %i", cmd->cmd.statemove->end_state);
+ case JTAG_TLR_RESET:
+ LOG_DEBUG_IO("statemove end in %i", cmd->cmd.statemove->end_state);
- if (cmd->cmd.statemove->end_state != -1)
- opendous_end_state(cmd->cmd.statemove->end_state);
- opendous_state_move();
- break;
+ if (cmd->cmd.statemove->end_state != -1)
+ opendous_end_state(cmd->cmd.statemove->end_state);
+ opendous_state_move();
+ break;
- case JTAG_PATHMOVE:
- LOG_DEBUG_IO("pathmove: %u states, end in %i",
- cmd->cmd.pathmove->num_states,
- cmd->cmd.pathmove->path[cmd->cmd.pathmove->num_states - 1]);
+ case JTAG_PATHMOVE:
+ LOG_DEBUG_IO("pathmove: %u states, end in %i",
+ cmd->cmd.pathmove->num_states,
+ cmd->cmd.pathmove->path[cmd->cmd.pathmove->num_states - 1]);
- opendous_path_move(cmd->cmd.pathmove->num_states, cmd->cmd.pathmove->path);
- break;
+ opendous_path_move(cmd->cmd.pathmove->num_states, cmd->cmd.pathmove->path);
+ break;
- case JTAG_SCAN:
- LOG_DEBUG_IO("scan end in %i", cmd->cmd.scan->end_state);
+ case JTAG_SCAN:
+ LOG_DEBUG_IO("scan end in %i", cmd->cmd.scan->end_state);
- if (cmd->cmd.scan->end_state != -1)
- opendous_end_state(cmd->cmd.scan->end_state);
+ if (cmd->cmd.scan->end_state != -1)
+ opendous_end_state(cmd->cmd.scan->end_state);
- scan_size = jtag_build_buffer(cmd->cmd.scan, &buffer);
- LOG_DEBUG_IO("scan input, length = %d", scan_size);
+ scan_size = jtag_build_buffer(cmd->cmd.scan, &buffer);
+ LOG_DEBUG_IO("scan input, length = %d", scan_size);
#ifdef _DEBUG_USB_COMMS_
- opendous_debug_buffer(buffer, (scan_size + 7) / 8);
+ opendous_debug_buffer(buffer, (scan_size + 7) / 8);
#endif
- type = jtag_scan_type(cmd->cmd.scan);
- opendous_scan(cmd->cmd.scan->ir_scan, type, buffer, scan_size, cmd->cmd.scan);
- break;
+ type = jtag_scan_type(cmd->cmd.scan);
+ opendous_scan(cmd->cmd.scan->ir_scan, type, buffer, scan_size, cmd->cmd.scan);
+ break;
- case JTAG_RESET:
- LOG_DEBUG_IO("reset trst: %i srst %i", cmd->cmd.reset->trst, cmd->cmd.reset->srst);
+ case JTAG_RESET:
+ LOG_DEBUG_IO("reset trst: %i srst %i", cmd->cmd.reset->trst, cmd->cmd.reset->srst);
- opendous_tap_execute();
+ opendous_tap_execute();
- if (cmd->cmd.reset->trst == 1)
- tap_set_state(TAP_RESET);
- opendous_reset(cmd->cmd.reset->trst, cmd->cmd.reset->srst);
- break;
+ if (cmd->cmd.reset->trst == 1)
+ tap_set_state(TAP_RESET);
+ opendous_reset(cmd->cmd.reset->trst, cmd->cmd.reset->srst);
+ break;
- case JTAG_SLEEP:
- LOG_DEBUG_IO("sleep %" PRIu32, cmd->cmd.sleep->us);
- opendous_tap_execute();
- jtag_sleep(cmd->cmd.sleep->us);
- break;
+ case JTAG_SLEEP:
+ LOG_DEBUG_IO("sleep %" PRIu32, cmd->cmd.sleep->us);
+ opendous_tap_execute();
+ jtag_sleep(cmd->cmd.sleep->us);
+ break;
- default:
- LOG_ERROR("BUG: unknown JTAG command type encountered");
- exit(-1);
+ default:
+ LOG_ERROR("BUG: unknown JTAG command type encountered");
+ exit(-1);
}
cmd = cmd->next;
}
diff --git a/src/jtag/drivers/openjtag.c b/src/jtag/drivers/openjtag.c
index 943ad854e8..d45a1c6a97 100644
--- a/src/jtag/drivers/openjtag.c
+++ b/src/jtag/drivers/openjtag.c
@@ -135,36 +135,36 @@ static void openjtag_debug_buffer(uint8_t *buffer, int length, uint8_t type)
int j;
switch (type) {
+ case DEBUG_TYPE_READ:
+ sprintf(line, "USB READ %d bytes", length);
+ break;
+ case DEBUG_TYPE_WRITE:
+ sprintf(line, "USB WRITE %d bytes", length);
+ break;
+ case DEBUG_TYPE_OCD_READ:
+ sprintf(line, "TO OpenOCD %d bytes", length);
+ break;
+ case DEBUG_TYPE_BUFFER:
+ sprintf(line, "Buffer %d bytes", length);
+ break;
+ }
+
+ LOG_DEBUG("%s", line);
+
+ for (i = 0; i < length; i += LINE_LEN) {
+ switch (type) {
case DEBUG_TYPE_READ:
- sprintf(line, "USB READ %d bytes", length);
+ sprintf(line, "USB READ: %04x", i);
break;
case DEBUG_TYPE_WRITE:
- sprintf(line, "USB WRITE %d bytes", length);
+ sprintf(line, "USB WRITE: %04x", i);
break;
case DEBUG_TYPE_OCD_READ:
- sprintf(line, "TO OpenOCD %d bytes", length);
+ sprintf(line, "TO OpenOCD: %04x", i);
break;
case DEBUG_TYPE_BUFFER:
- sprintf(line, "Buffer %d bytes", length);
+ sprintf(line, "BUFFER: %04x", i);
break;
- }
-
- LOG_DEBUG("%s", line);
-
- for (i = 0; i < length; i += LINE_LEN) {
- switch (type) {
- case DEBUG_TYPE_READ:
- sprintf(line, "USB READ: %04x", i);
- break;
- case DEBUG_TYPE_WRITE:
- sprintf(line, "USB WRITE: %04x", i);
- break;
- case DEBUG_TYPE_OCD_READ:
- sprintf(line, "TO OpenOCD: %04x", i);
- break;
- case DEBUG_TYPE_BUFFER:
- sprintf(line, "BUFFER: %04x", i);
- break;
}
for (j = i; j < i + LINE_LEN && j < length; j++) {
@@ -182,24 +182,24 @@ static int8_t openjtag_get_tap_state(int8_t state)
{
switch (state) {
- case TAP_DREXIT2: return OPENJTAG_TAP_EXIT2_DR;
- case TAP_DREXIT1: return OPENJTAG_TAP_EXIT1_DR;
- case TAP_DRSHIFT: return OPENJTAG_TAP_SHIFT_DR;
- case TAP_DRPAUSE: return OPENJTAG_TAP_PAUSE_DR;
- case TAP_IRSELECT: return OPENJTAG_TAP_SELECT_IR;
- case TAP_DRUPDATE: return OPENJTAG_TAP_UPDATE_DR;
- case TAP_DRCAPTURE: return OPENJTAG_TAP_CAPTURE_DR;
- case TAP_DRSELECT: return OPENJTAG_TAP_SELECT_DR;
- case TAP_IREXIT2: return OPENJTAG_TAP_EXIT2_IR;
- case TAP_IREXIT1: return OPENJTAG_TAP_EXIT1_IR;
- case TAP_IRSHIFT: return OPENJTAG_TAP_SHIFT_IR;
- case TAP_IRPAUSE: return OPENJTAG_TAP_PAUSE_IR;
- case TAP_IDLE: return OPENJTAG_TAP_IDLE;
- case TAP_IRUPDATE: return OPENJTAG_TAP_UPDATE_IR;
- case TAP_IRCAPTURE: return OPENJTAG_TAP_CAPURE_IR;
- case TAP_RESET: return OPENJTAG_TAP_RESET;
- case TAP_INVALID:
- default: return OPENJTAG_TAP_INVALID;
+ case TAP_DREXIT2: return OPENJTAG_TAP_EXIT2_DR;
+ case TAP_DREXIT1: return OPENJTAG_TAP_EXIT1_DR;
+ case TAP_DRSHIFT: return OPENJTAG_TAP_SHIFT_DR;
+ case TAP_DRPAUSE: return OPENJTAG_TAP_PAUSE_DR;
+ case TAP_IRSELECT: return OPENJTAG_TAP_SELECT_IR;
+ case TAP_DRUPDATE: return OPENJTAG_TAP_UPDATE_DR;
+ case TAP_DRCAPTURE: return OPENJTAG_TAP_CAPTURE_DR;
+ case TAP_DRSELECT: return OPENJTAG_TAP_SELECT_DR;
+ case TAP_IREXIT2: return OPENJTAG_TAP_EXIT2_IR;
+ case TAP_IREXIT1: return OPENJTAG_TAP_EXIT1_IR;
+ case TAP_IRSHIFT: return OPENJTAG_TAP_SHIFT_IR;
+ case TAP_IRPAUSE: return OPENJTAG_TAP_PAUSE_IR;
+ case TAP_IDLE: return OPENJTAG_TAP_IDLE;
+ case TAP_IRUPDATE: return OPENJTAG_TAP_UPDATE_IR;
+ case TAP_IRCAPTURE: return OPENJTAG_TAP_CAPURE_IR;
+ case TAP_RESET: return OPENJTAG_TAP_RESET;
+ case TAP_INVALID:
+ default: return OPENJTAG_TAP_INVALID;
}
}
@@ -347,34 +347,34 @@ static int openjtag_speed(int speed)
{
int clockcmd;
switch (speed) {
- case 48000:
- clockcmd = 0x00;
- break;
- case 24000:
- clockcmd = 0x20;
- break;
- case 12000:
- clockcmd = 0x40;
- break;
- case 6000:
- clockcmd = 0x60;
- break;
- case 3000:
- clockcmd = 0x80;
- break;
- case 1500:
- clockcmd = 0xA0;
- break;
- case 750:
- clockcmd = 0xC0;
- break;
- case 375:
- clockcmd = 0xE0;
- break;
- default:
- clockcmd = 0xE0;
- LOG_WARNING("adapter speed not recognized, reverting to 375 kHz");
- break;
+ case 48000:
+ clockcmd = 0x00;
+ break;
+ case 24000:
+ clockcmd = 0x20;
+ break;
+ case 12000:
+ clockcmd = 0x40;
+ break;
+ case 6000:
+ clockcmd = 0x60;
+ break;
+ case 3000:
+ clockcmd = 0x80;
+ break;
+ case 1500:
+ clockcmd = 0xA0;
+ break;
+ case 750:
+ clockcmd = 0xC0;
+ break;
+ case 375:
+ clockcmd = 0xE0;
+ break;
+ default:
+ clockcmd = 0xE0;
+ LOG_WARNING("adapter speed not recognized, reverting to 375 kHz");
+ break;
}
openjtag_sendcommand(clockcmd);
diff --git a/src/jtag/drivers/parport.c b/src/jtag/drivers/parport.c
index 143f3bde1f..794f8296e5 100644
--- a/src/jtag/drivers/parport.c
+++ b/src/jtag/drivers/parport.c
@@ -20,7 +20,7 @@
#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
#include
#include
-#define ioperm(startport, length, enable)\
+#define ioperm(startport, length, enable) \
i386_set_ioperm((startport), (length), (enable))
#endif /* __FreeBSD__ */
@@ -45,67 +45,17 @@
#include
#endif
-// Parallel port cable description.
-struct cable {
- const char *name;
- // Status port bit containing current TDO value.
- uint8_t tdo_mask;
- // Data port bit for TRST.
- uint8_t trst_mask;
- // Data port bit for TMD.
- uint8_t tms_mask;
- // Data port bit for TCK.
- uint8_t tck_mask;
- // Data port bit for TDI.
- uint8_t tdi_mask;
- // Data port bit for SRST.
- uint8_t srst_mask;
- // Data port bits that should be inverted.
- uint8_t output_invert;
- // Status port that should be inverted.
- uint8_t input_invert;
- // Initialize data port with this value.
- uint8_t port_init;
- // De-initialize data port with this value.
- uint8_t port_exit;
- // Data port bit for LED.
- uint8_t led_mask;
-};
-
-static const struct cable cables[] = {
- /* name tdo trst tms tck tdi srst o_inv i_inv init exit led */
- { "wiggler", 0x80, 0x10, 0x02, 0x04, 0x08, 0x01, 0x01, 0x80, 0x80, 0x80, 0x00 },
- { "wiggler2", 0x80, 0x10, 0x02, 0x04, 0x08, 0x01, 0x01, 0x80, 0x80, 0x00, 0x20 },
- { "wiggler_ntrst_inverted", 0x80, 0x10, 0x02, 0x04, 0x08, 0x01, 0x11, 0x80, 0x80, 0x80, 0x00 },
- { "old_amt_wiggler", 0x80, 0x01, 0x02, 0x04, 0x08, 0x10, 0x11, 0x80, 0x80, 0x80, 0x00 },
- { "arm-jtag", 0x80, 0x01, 0x02, 0x04, 0x08, 0x10, 0x01, 0x80, 0x80, 0x80, 0x00 },
- { "chameleon", 0x80, 0x00, 0x04, 0x01, 0x02, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00 },
- { "dlc5", 0x10, 0x00, 0x04, 0x02, 0x01, 0x00, 0x00, 0x00, 0x10, 0x10, 0x00 },
- { "triton", 0x80, 0x08, 0x04, 0x01, 0x02, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00 },
- { "lattice", 0x40, 0x10, 0x04, 0x02, 0x01, 0x08, 0x00, 0x00, 0x18, 0x18, 0x00 },
- { "flashlink", 0x20, 0x10, 0x02, 0x01, 0x04, 0x20, 0x30, 0x20, 0x00, 0x00, 0x00 },
-/* Altium Universal JTAG cable. Set the cable to Xilinx Mode and wire to target as follows:
- HARD TCK - Target TCK
- HARD TMS - Target TMS
- HARD TDI - Target TDI
- HARD TDO - Target TDO
- SOFT TCK - Target TRST
- SOFT TDI - Target SRST
-*/
- { "altium", 0x10, 0x20, 0x04, 0x02, 0x01, 0x80, 0x00, 0x00, 0x10, 0x00, 0x08 },
- { "aspo", 0x10, 0x01, 0x04, 0x08, 0x02, 0x10, 0x17, 0x00, 0x17, 0x17, 0x00 },
- { NULL, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }
-};
+static const struct adapter_gpio_config *adapter_gpio_config;
-// Configuration variables.
-static char *parport_cable;
+#if PARPORT_USE_PPDEV == 0
static uint16_t parport_port;
-static bool parport_exit;
+#endif
+static bool parport_write_exit_state;
+static char *parport_device_file;
static uint32_t parport_toggling_time_ns = 1000;
static int wait_states;
// Interface variables.
-static const struct cable *cable;
static uint8_t dataport_value;
#if PARPORT_USE_PPDEV == 1
@@ -115,6 +65,20 @@ static unsigned long dataport;
static unsigned long statusport;
#endif
+// Bitmask map for the input pins.
+static struct {
+ uint8_t mask;
+} input_pin_bitmask_map[] = {
+ [10] = {0x40},
+ [11] = {0x80},
+ [12] = {0x20},
+ [13] = {0x10},
+ [15] = {0x08},
+};
+
+// Generate an output pin bitmask for an adapter signal.
+#define OUTPUT_BITMASK(gpio_index) BIT((adapter_gpio_config[(gpio_index)].gpio_num - 2))
+
static enum bb_value parport_read(void)
{
int data = 0;
@@ -125,16 +89,15 @@ static enum bb_value parport_read(void)
data = inb(statusport);
#endif
- if ((data ^ cable->input_invert) & cable->tdo_mask)
- return BB_HIGH;
- else
- return BB_LOW;
+ const struct adapter_gpio_config *gpio_config = &adapter_gpio_config[ADAPTER_GPIO_IDX_TDO];
+ const bool tdo_state = data & input_pin_bitmask_map[gpio_config->gpio_num].mask;
+
+ return (tdo_state ^ gpio_config->active_low) ? BB_HIGH : BB_LOW;
}
-static inline void parport_write_data(void)
+static void parport_write_data(void)
{
- uint8_t output;
- output = dataport_value ^ cable->output_invert;
+ const uint8_t output = dataport_value;
#if PARPORT_USE_PPDEV == 1
ioctl(device_handle, PPWDATA, &output);
@@ -147,26 +110,27 @@ static inline void parport_write_data(void)
#endif
}
-static int parport_write(int tck, int tms, int tdi)
+static bool is_gpio_configured(enum adapter_gpio_config_index gpio_index)
{
- int i = wait_states + 1;
-
- if (tck)
- dataport_value |= cable->tck_mask;
- else
- dataport_value &= ~cable->tck_mask;
+ return adapter_gpio_config[gpio_index].gpio_num != ADAPTER_GPIO_NOT_SET;
+}
- if (tms)
- dataport_value |= cable->tms_mask;
+static void set_pin_state(enum adapter_gpio_config_index gpio_index,
+ bool state)
+{
+ if (state ^ adapter_gpio_config[gpio_index].active_low)
+ dataport_value |= OUTPUT_BITMASK(gpio_index);
else
- dataport_value &= ~cable->tms_mask;
+ dataport_value &= ~OUTPUT_BITMASK(gpio_index);
+}
- if (tdi)
- dataport_value |= cable->tdi_mask;
- else
- dataport_value &= ~cable->tdi_mask;
+static int parport_write(int tck, int tms, int tdi)
+{
+ set_pin_state(ADAPTER_GPIO_IDX_TCK, tck == 1);
+ set_pin_state(ADAPTER_GPIO_IDX_TMS, tms == 1);
+ set_pin_state(ADAPTER_GPIO_IDX_TDI, tdi == 1);
- while (i-- > 0)
+ for (int i = 0; i < wait_states + 1; i++)
parport_write_data();
return ERROR_OK;
@@ -177,15 +141,11 @@ static int parport_reset(int trst, int srst)
{
LOG_DEBUG("trst: %i, srst: %i", trst, srst);
- if (trst == 0)
- dataport_value |= cable->trst_mask;
- else if (trst == 1)
- dataport_value &= ~cable->trst_mask;
+ if (is_gpio_configured(ADAPTER_GPIO_IDX_TRST))
+ set_pin_state(ADAPTER_GPIO_IDX_TRST, trst == 0);
- if (srst == 0)
- dataport_value |= cable->srst_mask;
- else if (srst == 1)
- dataport_value &= ~cable->srst_mask;
+ if (is_gpio_configured(ADAPTER_GPIO_IDX_SRST))
+ set_pin_state(ADAPTER_GPIO_IDX_SRST, srst == 0);
parport_write_data();
@@ -194,11 +154,10 @@ static int parport_reset(int trst, int srst)
static int parport_led(bool on)
{
- if (on)
- dataport_value |= cable->led_mask;
- else
- dataport_value &= ~cable->led_mask;
+ if (!is_gpio_configured(ADAPTER_GPIO_IDX_LED))
+ return ERROR_OK;
+ set_pin_state(ADAPTER_GPIO_IDX_LED, on);
parport_write_data();
return ERROR_OK;
@@ -213,11 +172,12 @@ static int parport_speed(int speed)
static int parport_khz(int khz, int *jtag_speed)
{
if (!khz) {
- LOG_DEBUG("RCLK not supported");
+ LOG_ERROR("RCLK is not supported by the adapter");
return ERROR_FAIL;
}
*jtag_speed = 499999 / (khz * parport_toggling_time_ns);
+
return ERROR_OK;
}
@@ -226,32 +186,35 @@ static int parport_speed_div(int speed, int *khz)
uint32_t denominator = (speed + 1) * parport_toggling_time_ns;
*khz = (499999 + denominator) / denominator;
+
return ERROR_OK;
}
#if PARPORT_USE_GIVEIO == 1
-static int parport_get_giveio_access(void)
+static bool parport_get_giveio_access(void)
{
- HANDLE h;
OSVERSIONINFO version;
version.dwOSVersionInfoSize = sizeof(version);
if (!GetVersionEx(&version)) {
errno = EINVAL;
- return -1;
+ return false;
}
+
if (version.dwPlatformId != VER_PLATFORM_WIN32_NT)
- return 0;
+ return true;
+
+ HANDLE h = CreateFile("\\\\.\\giveio", GENERIC_READ, 0, NULL, OPEN_EXISTING,
+ FILE_ATTRIBUTE_NORMAL, NULL);
- h = CreateFile("\\\\.\\giveio", GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (h == INVALID_HANDLE_VALUE) {
errno = ENODEV;
- return -1;
+ return false;
}
CloseHandle(h);
- return 0;
+ return true;
}
#endif
@@ -261,105 +224,150 @@ static const struct bitbang_interface parport_bitbang = {
.blink = &parport_led,
};
+static const struct {
+ enum adapter_gpio_config_index gpio_index;
+ bool required;
+} all_signals[] = {
+ { ADAPTER_GPIO_IDX_TDO, true },
+ { ADAPTER_GPIO_IDX_TDI, true },
+ { ADAPTER_GPIO_IDX_TMS, true },
+ { ADAPTER_GPIO_IDX_TCK, true },
+ { ADAPTER_GPIO_IDX_TRST, false },
+ { ADAPTER_GPIO_IDX_SRST, false },
+ { ADAPTER_GPIO_IDX_LED, false },
+ { ADAPTER_GPIO_IDX_USER0, false },
+};
+
static int parport_init(void)
{
- const struct cable *cur_cable;
-#if PARPORT_USE_PPDEV == 1
- char buffer[256];
-#endif
+ adapter_gpio_config = adapter_gpio_get_config();
- cur_cable = cables;
+ // Check if all signals are configured properly.
+ for (size_t i = 0; i < ARRAY_SIZE(all_signals); i++) {
+ const enum adapter_gpio_config_index gpio_index = all_signals[i].gpio_index;
+ const struct adapter_gpio_config gpio = adapter_gpio_config[gpio_index];
- if (!parport_cable) {
- parport_cable = strdup("wiggler");
- LOG_WARNING("No parport cable specified, using default 'wiggler'");
- }
+ if (gpio.gpio_num == ADAPTER_GPIO_NOT_SET) {
+ if (all_signals[i].required) {
+ LOG_ERROR("The signal '%s' is required and must be configured",
+ adapter_gpio_get_name(gpio_index));
+ return ERROR_FAIL;
+ }
- while (cur_cable->name) {
- if (!strcmp(cur_cable->name, parport_cable)) {
- cable = cur_cable;
- break;
+ continue;
}
- cur_cable++;
- }
- if (!cable) {
- LOG_ERROR("No matching cable found for %s", parport_cable);
- return ERROR_JTAG_INIT_FAILED;
+ if (gpio_index == ADAPTER_GPIO_IDX_TDO) {
+ if (gpio.gpio_num < 10 || gpio.gpio_num > 15 || gpio.gpio_num == 14) {
+ LOG_ERROR("The '%s' signal pin must be 10, 11, 12, 13, or 15",
+ adapter_gpio_get_name(gpio_index));
+ goto init_fail;
+ }
+ } else {
+ if (gpio.gpio_num < 2 || gpio.gpio_num > 9) {
+ LOG_ERROR("The '%s' signal pin must be 2, 3, 4, 5, 6, 7, 8, or 9",
+ adapter_gpio_get_name(gpio_index));
+ goto init_fail;
+ }
+ }
}
- dataport_value = cable->port_init;
+ // Initialize signal pin states.
+ for (size_t i = 0; i < ARRAY_SIZE(all_signals); i++) {
+ const enum adapter_gpio_config_index gpio_index = all_signals[i].gpio_index;
+ const struct adapter_gpio_config gpio = adapter_gpio_config[gpio_index];
+
+ // The TDO (input) and LED (controlled by the adapter) pins cannot be
+ // initialized.
+ if (gpio_index == ADAPTER_GPIO_IDX_TDO || gpio_index == ADAPTER_GPIO_IDX_LED)
+ continue;
+
+ // Do not initialize unconfigured GPIO pins.
+ if (gpio.gpio_num == ADAPTER_GPIO_NOT_SET)
+ continue;
+
+ if (gpio.init_state == ADAPTER_GPIO_INIT_STATE_ACTIVE)
+ set_pin_state(gpio_index, true);
+ else if (gpio.init_state == ADAPTER_GPIO_INIT_STATE_INACTIVE)
+ set_pin_state(gpio_index, false);
+ }
#if PARPORT_USE_PPDEV == 1
if (device_handle > 0) {
- LOG_ERROR("device is already opened");
- return ERROR_JTAG_INIT_FAILED;
+ LOG_ERROR("Parallel port is already open");
+ goto init_fail;
}
+ if (!parport_device_file) {
#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
- LOG_DEBUG("opening /dev/ppi%d...", parport_port);
+ parport_device_file = strdup("/dev/ppi0");
+#else
+ parport_device_file = strdup("/dev/parport0");
+#endif
+ LOG_WARNING("No parallel port specified, using %s", parport_device_file);
+ LOG_WARNING("DEPRECATED! The lack of a parallel port specification is deprecated and will no longer work in the future");
+ }
- snprintf(buffer, 256, "/dev/ppi%d", parport_port);
- device_handle = open(buffer, O_WRONLY);
-#else /* not __FreeBSD__, __FreeBSD_kernel__ */
- LOG_DEBUG("opening /dev/parport%d...", parport_port);
+ LOG_DEBUG("Using parallel port %s", parport_device_file);
- snprintf(buffer, 256, "/dev/parport%d", parport_port);
- device_handle = open(buffer, O_WRONLY);
-#endif /* __FreeBSD__, __FreeBSD_kernel__ */
+ device_handle = open(parport_device_file, O_WRONLY);
if (device_handle < 0) {
int err = errno;
- LOG_ERROR("cannot open device. check it exists and that user read and write rights are set. errno=%d", err);
- return ERROR_JTAG_INIT_FAILED;
+ LOG_ERROR("Failed to open parallel port %s (errno = %d)",
+ parport_device_file, err);
+ LOG_ERROR("Check whether the device exists and if you have the required access rights");
+ goto init_fail;
}
- LOG_DEBUG("...open");
-
#if !defined(__FreeBSD__) && !defined(__FreeBSD_kernel__)
- int i = ioctl(device_handle, PPCLAIM);
+ int retval = ioctl(device_handle, PPCLAIM);
- if (i < 0) {
- LOG_ERROR("cannot claim device");
- return ERROR_JTAG_INIT_FAILED;
+ if (retval < 0) {
+ LOG_ERROR("Failed to claim parallel port %s", parport_device_file);
+ goto init_fail;
}
- i = PARPORT_MODE_COMPAT;
- i = ioctl(device_handle, PPSETMODE, &i);
- if (i < 0) {
- LOG_ERROR(" cannot set compatible mode to device");
- return ERROR_JTAG_INIT_FAILED;
+ int value = PARPORT_MODE_COMPAT;
+ retval = ioctl(device_handle, PPSETMODE, &value);
+
+ if (retval < 0) {
+ LOG_ERROR("Cannot set compatible mode to device");
+ goto init_fail;
}
- i = IEEE1284_MODE_COMPAT;
- i = ioctl(device_handle, PPNEGOT, &i);
- if (i < 0) {
- LOG_ERROR("cannot set compatible 1284 mode to device");
- return ERROR_JTAG_INIT_FAILED;
+ value = IEEE1284_MODE_COMPAT;
+ retval = ioctl(device_handle, PPNEGOT, &value);
+
+ if (retval < 0) {
+ LOG_ERROR("Cannot set compatible 1284 mode to device");
+ goto init_fail;
}
#endif /* not __FreeBSD__, __FreeBSD_kernel__ */
#else /* not PARPORT_USE_PPDEV */
+ LOG_WARNING("DEPRECATED: Parallel port access with direct I/O is deprecated and support will be removed in the next release");
+
if (!parport_port) {
parport_port = 0x378;
- LOG_WARNING("No parport port specified, using default '0x378' (LPT1)");
+ LOG_WARNING("No parallel port specified, using default 0x378 (LPT1)");
}
+ LOG_DEBUG("Using parallel port 0x%x", parport_port);
+
dataport = parport_port;
statusport = parport_port + 1;
- LOG_DEBUG("requesting privileges for parallel port 0x%lx...", dataport);
#if PARPORT_USE_GIVEIO == 1
- if (parport_get_giveio_access() != 0) {
+ if (!parport_get_giveio_access()) {
#else /* PARPORT_USE_GIVEIO */
if (ioperm(dataport, 3, 1) != 0) {
#endif /* PARPORT_USE_GIVEIO */
- LOG_ERROR("missing privileges for direct i/o");
- return ERROR_JTAG_INIT_FAILED;
+ LOG_ERROR("Missing privileges for direct I/O");
+ goto init_fail;
}
- LOG_DEBUG("...privileges granted");
- // Make sure parallel port is in right mode (clear tristate and interrupt.
+ // Make sure parallel port is in right mode (clear tristate and interrupt).
#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
outb(parport_port + 2, 0x0);
#else
@@ -369,110 +377,153 @@ static int parport_init(void)
#endif /* PARPORT_USE_PPDEV */
if (parport_reset(0, 0) != ERROR_OK)
- return ERROR_FAIL;
+ goto init_fail;
+
if (parport_write(0, 0, 0) != ERROR_OK)
- return ERROR_FAIL;
+ goto init_fail;
+
if (parport_led(true) != ERROR_OK)
- return ERROR_FAIL;
+ goto init_fail;
bitbang_interface = &parport_bitbang;
return ERROR_OK;
+
+init_fail:
+ free(parport_device_file);
+ return ERROR_JTAG_INIT_FAILED;
}
static int parport_quit(void)
{
- if (parport_led(false) != ERROR_OK)
- return ERROR_FAIL;
+ free(parport_device_file);
+
+ // Deinitialize signal pin states.
+ for (size_t i = 0; i < ARRAY_SIZE(all_signals); i++) {
+ const enum adapter_gpio_config_index gpio_index = all_signals[i].gpio_index;
+ const struct adapter_gpio_config gpio = adapter_gpio_config[gpio_index];
+
+ // The TDO (input) and LED (controlled by the adapter) pins cannot be
+ // deinitialized.
+ if (gpio_index == ADAPTER_GPIO_IDX_TDO || gpio_index == ADAPTER_GPIO_IDX_LED)
+ continue;
+
+ // Do not deinitialize unconfigured GPIO pins.
+ if (gpio.gpio_num == ADAPTER_GPIO_NOT_SET)
+ continue;
+
+ if (gpio.exit_state == ADAPTER_GPIO_EXIT_STATE_ACTIVE)
+ set_pin_state(gpio_index, true);
+ else if (gpio.exit_state == ADAPTER_GPIO_EXIT_STATE_INACTIVE)
+ set_pin_state(gpio_index, false);
+ }
- if (parport_exit) {
- dataport_value = cable->port_exit;
+ if (parport_write_exit_state)
parport_write_data();
- }
- free(parport_cable);
- parport_cable = NULL;
+ if (parport_led(false) != ERROR_OK)
+ return ERROR_FAIL;
return ERROR_OK;
}
COMMAND_HANDLER(parport_handle_port_command)
{
- if (CMD_ARGC == 1) {
- // Only if the port wasn't overwritten by cmdline.
- if (!parport_port) {
- COMMAND_PARSE_NUMBER(u16, CMD_ARGV[0], parport_port);
- } else {
- LOG_ERROR("The parport port was already configured!");
- return ERROR_FAIL;
- }
+ if (CMD_ARGC != 1)
+ return ERROR_COMMAND_SYNTAX_ERROR;
+
+#if PARPORT_USE_PPDEV == 1
+ if (parport_device_file) {
+ LOG_ERROR("The parallel port device file is already configured");
+ return ERROR_FAIL;
}
- command_print(CMD, "parport port = 0x%" PRIx16 "", parport_port);
+ char *tmp;
- return ERROR_OK;
-}
+ // We do not use the parse_xxx() or COMMAND_PARSE_xxx() functions here since
+ // they generate an error message if parsing fails.
+ char *endptr = NULL;
+ unsigned long port_number = strtoul(CMD_ARGV[0], &endptr, 0);
-COMMAND_HANDLER(parport_handle_cable_command)
-{
- if (!CMD_ARGC)
- return ERROR_OK;
+ if (*endptr == '\0' && endptr != CMD_ARGV[0]) {
+ LOG_WARNING("DEPRECATED! Using a port number is deprecated, use the device file instead");
- // Only if the cable name wasn't overwritten by cmdline.
- if (!parport_cable) {
- // TODO: REVISIT first verify that it's listed in cables[].
- parport_cable = malloc(strlen(CMD_ARGV[0]) + sizeof(char));
- if (!parport_cable) {
- LOG_ERROR("Out of memory");
- return ERROR_FAIL;
- }
- strcpy(parport_cable, CMD_ARGV[0]);
+#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
+ tmp = alloc_printf("/dev/ppi%lu", port_number);
+#else
+ tmp = alloc_printf("/dev/parport%lu", port_number);
+#endif
+ } else {
+ tmp = strdup(CMD_ARGV[0]);
+ }
+
+ if (!tmp) {
+ LOG_ERROR("Failed to allocate memory");
+ return ERROR_FAIL;
+ }
+
+ free(parport_device_file);
+ parport_device_file = tmp;
+#else
+ if (parport_port > 0) {
+ command_print(CMD, "The parallel port is already configured");
+ return ERROR_FAIL;
}
- // TODO: REVISIT it's probably worth returning the current value.
+ COMMAND_PARSE_NUMBER(u16, CMD_ARGV[0], parport_port);
+#endif
return ERROR_OK;
}
+// This command is only for backward compatibility and will be removed in the
+// future.
+COMMAND_HANDLER(parport_handle_cable_command)
+{
+ if (CMD_ARGC != 1)
+ return ERROR_COMMAND_SYNTAX_ERROR;
+
+ return command_run_linef(CMD_CTX, "parport_select_cable %s", CMD_ARGV[0]);
+}
+
COMMAND_HANDLER(parport_handle_write_on_exit_command)
{
if (CMD_ARGC != 1)
return ERROR_COMMAND_SYNTAX_ERROR;
- COMMAND_PARSE_ON_OFF(CMD_ARGV[0], parport_exit);
+ LOG_WARNING("DEPRECATED: 'parport write_on_exit' will be removed in the future, use the 'adapter gpio' command to configure the exit state for pins");
+
+ COMMAND_PARSE_ON_OFF(CMD_ARGV[0], parport_write_exit_state);
return ERROR_OK;
}
COMMAND_HANDLER(parport_handle_toggling_time_command)
{
- if (CMD_ARGC == 1) {
- uint32_t ns;
- int retval = parse_u32(CMD_ARGV[0], &ns);
+ if (CMD_ARGC != 1)
+ return ERROR_COMMAND_SYNTAX_ERROR;
- if (retval != ERROR_OK)
- return retval;
+ uint32_t toggling_time;
- if (!ns) {
- LOG_ERROR("0 ns is not a valid parport toggling time");
- return ERROR_FAIL;
- }
+ COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], toggling_time);
- parport_toggling_time_ns = ns;
- retval = adapter_get_speed(&wait_states);
- if (retval != ERROR_OK) {
- /*
- * If adapter_get_speed fails then the clock_mode has
- * not been configured, this happens if toggling_time is
- * called before the adapter speed is set.
- */
- LOG_INFO("no parport speed set - defaulting to zero wait states");
- wait_states = 0;
- }
+ if (!toggling_time) {
+ command_print(CMD, "toggling time must not be 0 ns");
+ return ERROR_COMMAND_ARGUMENT_INVALID;
}
- command_print(CMD, "parport toggling time = %" PRIu32 " ns",
- parport_toggling_time_ns);
+ parport_toggling_time_ns = toggling_time;
+ int retval = adapter_get_speed(&wait_states);
+
+ if (retval != ERROR_OK) {
+ /*
+ * If adapter_get_speed fails then the clock_mode has not been
+ * configured, this happens if toggling_time is called before the
+ * adapter speed is set.
+ */
+ LOG_INFO("No parallel port speed set, using zero wait states");
+ wait_states = 0;
+ }
return ERROR_OK;
}
@@ -482,35 +533,30 @@ static const struct command_registration parport_subcommand_handlers[] = {
.name = "port",
.handler = parport_handle_port_command,
.mode = COMMAND_CONFIG,
- .help = "Display the address of the I/O port (e.g. 0x378) "
- "or the number of the '/dev/parport' device used. "
- "If a parameter is provided, first change that port.",
- .usage = "[port_number]",
+ .help = "Specify the device file of the parallel port",
+ .usage = "file",
},
{
.name = "cable",
.handler = parport_handle_cable_command,
.mode = COMMAND_CONFIG,
.help = "Set the layout of the parallel port cable "
- "used to connect to the target.",
- // TODO: REVISIT there's no way to list layouts we know.
- .usage = "[layout]",
+ "used to connect to the target",
+ .usage = "cable",
},
{
.name = "write_on_exit",
.handler = parport_handle_write_on_exit_command,
.mode = COMMAND_CONFIG,
- .help = "Configure the parallel driver to write "
- "a known value to the parallel interface on exit.",
+ .help = "Configure the driver to write a value to the parallel port on shutdown",
.usage = "('on'|'off')",
},
{
.name = "toggling_time",
.handler = parport_handle_toggling_time_command,
.mode = COMMAND_CONFIG,
- .help = "Displays or assigns how many nanoseconds it "
- "takes for the hardware to toggle TCK.",
- .usage = "[nanoseconds]",
+ .help = "Configure how many nanoseconds it takes for the hardware to toggle TCK",
+ .usage = "time",
},
COMMAND_REGISTRATION_DONE
};
diff --git a/src/jtag/drivers/remote_bitbang.c b/src/jtag/drivers/remote_bitbang.c
index 449c616545..71ec572b3c 100644
--- a/src/jtag/drivers/remote_bitbang.c
+++ b/src/jtag/drivers/remote_bitbang.c
@@ -179,14 +179,14 @@ static int remote_bitbang_quit(void)
static enum bb_value char_to_int(int c)
{
switch (c) {
- case '0':
- return BB_LOW;
- case '1':
- return BB_HIGH;
- default:
- remote_bitbang_quit();
- LOG_ERROR("remote_bitbang: invalid read response: %c(%i)", c, c);
- return BB_ERROR;
+ case '0':
+ return BB_LOW;
+ case '1':
+ return BB_HIGH;
+ default:
+ remote_bitbang_quit();
+ LOG_ERROR("remote_bitbang: invalid read response: %c(%i)", c, c);
+ return BB_ERROR;
}
}
diff --git a/src/jtag/drivers/rlink.c b/src/jtag/drivers/rlink.c
index a818996255..83c6d68530 100644
--- a/src/jtag/drivers/rlink.c
+++ b/src/jtag/drivers/rlink.c
@@ -321,67 +321,53 @@ static int dtc_load_from_buffer(struct libusb_device_handle *hdev_param, const u
}
switch (header->type) {
- case DTCLOAD_COMMENT:
- break;
-
- case DTCLOAD_ENTRY:
- /* store entry addresses somewhere */
- if (!strncmp("download", (char *)buffer + 1, 8))
- dtc_entry_download = buffer[0];
- break;
-
- case DTCLOAD_LOAD:
- /* Send the DTC program to ST7 RAM. */
- usb_err = ep1_memory_write(
- hdev_param,
- DTC_LOAD_BUFFER,
- header->length + 1, buffer
- );
- if (usb_err < 0)
- return usb_err;
-
- /* Load it into the DTC. */
- usb_err = ep1_generic_commandl(
- hdev_param, 3,
- EP1_CMD_DTC_LOAD,
- (DTC_LOAD_BUFFER >> 8),
- DTC_LOAD_BUFFER
- );
- if (usb_err < 0)
- return usb_err;
-
- break;
-
- case DTCLOAD_RUN:
- usb_err = ep1_generic_commandl(
- hdev_param, 3,
- EP1_CMD_DTC_CALL,
- buffer[0],
- EP1_CMD_DTC_WAIT
- );
- if (usb_err < 0)
- return usb_err;
-
- break;
-
- case DTCLOAD_LUT_START:
- lut_start = buffer[0];
- break;
-
- case DTCLOAD_LUT:
- usb_err = ep1_memory_write(
- hdev_param,
- ST7_USB_BUF_EP0OUT + lut_start,
- header->length + 1, buffer
- );
- if (usb_err < 0)
- return usb_err;
- break;
-
- default:
- LOG_ERROR("Invalid DTC image record type: 0x%02x", header->type);
- exit(1);
- break;
+ case DTCLOAD_COMMENT:
+ break;
+
+ case DTCLOAD_ENTRY:
+ /* store entry addresses somewhere */
+ if (!strncmp("download", (char *)buffer + 1, 8))
+ dtc_entry_download = buffer[0];
+ break;
+
+ case DTCLOAD_LOAD:
+ /* Send the DTC program to ST7 RAM. */
+ usb_err = ep1_memory_write(hdev_param, DTC_LOAD_BUFFER,
+ header->length + 1, buffer);
+ if (usb_err < 0)
+ return usb_err;
+
+ /* Load it into the DTC. */
+ usb_err = ep1_generic_commandl(hdev_param, 3, EP1_CMD_DTC_LOAD,
+ (DTC_LOAD_BUFFER >> 8), DTC_LOAD_BUFFER);
+ if (usb_err < 0)
+ return usb_err;
+
+ break;
+
+ case DTCLOAD_RUN:
+ usb_err = ep1_generic_commandl(hdev_param, 3, EP1_CMD_DTC_CALL,
+ buffer[0], EP1_CMD_DTC_WAIT);
+ if (usb_err < 0)
+ return usb_err;
+
+ break;
+
+ case DTCLOAD_LUT_START:
+ lut_start = buffer[0];
+ break;
+
+ case DTCLOAD_LUT:
+ usb_err = ep1_memory_write(hdev_param,
+ ST7_USB_BUF_EP0OUT + lut_start, header->length + 1, buffer);
+ if (usb_err < 0)
+ return usb_err;
+ break;
+
+ default:
+ LOG_ERROR("Invalid DTC image record type: 0x%02x", header->type);
+ exit(1);
+ break;
}
buffer += (header->length + 1);
@@ -1147,15 +1133,15 @@ static int rlink_scan(struct jtag_command *cmd, enum scan_type type,
chunk_bytes = chunk_bits / 8;
switch (type) {
- case SCAN_IN:
- x = DTC_CMD_SHIFT_TDO_BYTES(chunk_bytes);
- break;
- case SCAN_OUT:
- x = DTC_CMD_SHIFT_TDI_BYTES(chunk_bytes);
- break;
- default:
- x = DTC_CMD_SHIFT_TDIO_BYTES(chunk_bytes);
- break;
+ case SCAN_IN:
+ x = DTC_CMD_SHIFT_TDO_BYTES(chunk_bytes);
+ break;
+ case SCAN_OUT:
+ x = DTC_CMD_SHIFT_TDI_BYTES(chunk_bytes);
+ break;
+ default:
+ x = DTC_CMD_SHIFT_TDIO_BYTES(chunk_bytes);
+ break;
}
dtc_queue.cmd_buffer[dtc_queue.cmd_index++] = x;
@@ -1281,69 +1267,69 @@ static int rlink_execute_queue(struct jtag_command *cmd_queue)
while (cmd) {
switch (cmd->type) {
- case JTAG_RUNTEST:
- case JTAG_TLR_RESET:
- case JTAG_PATHMOVE:
- case JTAG_SCAN:
- break;
-
- default:
- /* some events, such as resets, need a queue flush to ensure
- *consistency */
- tap_state_queue_run();
- dtc_queue_run();
- break;
+ case JTAG_RUNTEST:
+ case JTAG_TLR_RESET:
+ case JTAG_PATHMOVE:
+ case JTAG_SCAN:
+ break;
+
+ default:
+ /* some events, such as resets, need a queue flush to ensure
+ *consistency */
+ tap_state_queue_run();
+ dtc_queue_run();
+ break;
}
switch (cmd->type) {
- case JTAG_RESET:
- LOG_DEBUG_IO("reset trst: %i srst %i",
- cmd->cmd.reset->trst,
- cmd->cmd.reset->srst);
- if ((cmd->cmd.reset->trst == 1) ||
- (cmd->cmd.reset->srst &&
- (jtag_get_reset_config() & RESET_SRST_PULLS_TRST)))
- tap_set_state(TAP_RESET);
- rlink_reset(cmd->cmd.reset->trst, cmd->cmd.reset->srst);
- break;
- case JTAG_RUNTEST:
- LOG_DEBUG_IO("runtest %i cycles, end in %i",
- cmd->cmd.runtest->num_cycles,
- cmd->cmd.runtest->end_state);
- if (cmd->cmd.runtest->end_state != -1)
- rlink_end_state(cmd->cmd.runtest->end_state);
- rlink_runtest(cmd->cmd.runtest->num_cycles);
- break;
- case JTAG_TLR_RESET:
- LOG_DEBUG_IO("statemove end in %i", cmd->cmd.statemove->end_state);
- if (cmd->cmd.statemove->end_state != -1)
- rlink_end_state(cmd->cmd.statemove->end_state);
- rlink_state_move();
- break;
- case JTAG_PATHMOVE:
- LOG_DEBUG_IO("pathmove: %u states, end in %i",
- cmd->cmd.pathmove->num_states,
- cmd->cmd.pathmove->path[cmd->cmd.pathmove->num_states - 1]);
- rlink_path_move(cmd->cmd.pathmove);
- break;
- case JTAG_SCAN:
- LOG_DEBUG_IO("%s scan end in %i",
- (cmd->cmd.scan->ir_scan) ? "IR" : "DR",
- cmd->cmd.scan->end_state);
- if (cmd->cmd.scan->end_state != -1)
- rlink_end_state(cmd->cmd.scan->end_state);
- scan_size = jtag_build_buffer(cmd->cmd.scan, &buffer);
- type = jtag_scan_type(cmd->cmd.scan);
- if (rlink_scan(cmd, type, buffer, scan_size) != ERROR_OK)
- retval = ERROR_FAIL;
- break;
- case JTAG_SLEEP:
- LOG_DEBUG_IO("sleep %" PRIu32, cmd->cmd.sleep->us);
- jtag_sleep(cmd->cmd.sleep->us);
- break;
- default:
- LOG_ERROR("BUG: unknown JTAG command type encountered");
- exit(-1);
+ case JTAG_RESET:
+ LOG_DEBUG_IO("reset trst: %i srst %i",
+ cmd->cmd.reset->trst,
+ cmd->cmd.reset->srst);
+ if (cmd->cmd.reset->trst == 1 ||
+ (cmd->cmd.reset->srst &&
+ (jtag_get_reset_config() & RESET_SRST_PULLS_TRST)))
+ tap_set_state(TAP_RESET);
+ rlink_reset(cmd->cmd.reset->trst, cmd->cmd.reset->srst);
+ break;
+ case JTAG_RUNTEST:
+ LOG_DEBUG_IO("runtest %i cycles, end in %i",
+ cmd->cmd.runtest->num_cycles,
+ cmd->cmd.runtest->end_state);
+ if (cmd->cmd.runtest->end_state != -1)
+ rlink_end_state(cmd->cmd.runtest->end_state);
+ rlink_runtest(cmd->cmd.runtest->num_cycles);
+ break;
+ case JTAG_TLR_RESET:
+ LOG_DEBUG_IO("statemove end in %i", cmd->cmd.statemove->end_state);
+ if (cmd->cmd.statemove->end_state != -1)
+ rlink_end_state(cmd->cmd.statemove->end_state);
+ rlink_state_move();
+ break;
+ case JTAG_PATHMOVE:
+ LOG_DEBUG_IO("pathmove: %u states, end in %i",
+ cmd->cmd.pathmove->num_states,
+ cmd->cmd.pathmove->path[cmd->cmd.pathmove->num_states - 1]);
+ rlink_path_move(cmd->cmd.pathmove);
+ break;
+ case JTAG_SCAN:
+ LOG_DEBUG_IO("%s scan end in %i",
+ (cmd->cmd.scan->ir_scan) ? "IR" : "DR",
+ cmd->cmd.scan->end_state);
+ if (cmd->cmd.scan->end_state != -1)
+ rlink_end_state(cmd->cmd.scan->end_state);
+ scan_size = jtag_build_buffer(cmd->cmd.scan, &buffer);
+ type = jtag_scan_type(cmd->cmd.scan);
+ if (rlink_scan(cmd, type, buffer, scan_size) != ERROR_OK)
+ retval = ERROR_FAIL;
+ break;
+ case JTAG_SLEEP:
+ LOG_DEBUG_IO("sleep %" PRIu32, cmd->cmd.sleep->us);
+ jtag_sleep(cmd->cmd.sleep->us);
+ break;
+ default:
+ LOG_ERROR("BUG: unknown JTAG command type encountered");
+ exit(-1);
}
cmd = cmd->next;
}
diff --git a/src/jtag/drivers/stlink_usb.c b/src/jtag/drivers/stlink_usb.c
index 5ee1f85261..b4d21100cc 100644
--- a/src/jtag/drivers/stlink_usb.c
+++ b/src/jtag/drivers/stlink_usb.c
@@ -608,28 +608,28 @@ static int transfer_error_status(const struct libusb_transfer *transfer)
int r = 0;
switch (transfer->status) {
- case LIBUSB_TRANSFER_COMPLETED:
- r = 0;
- break;
- case LIBUSB_TRANSFER_TIMED_OUT:
- r = LIBUSB_ERROR_TIMEOUT;
- break;
- case LIBUSB_TRANSFER_STALL:
- r = LIBUSB_ERROR_PIPE;
- break;
- case LIBUSB_TRANSFER_OVERFLOW:
- r = LIBUSB_ERROR_OVERFLOW;
- break;
- case LIBUSB_TRANSFER_NO_DEVICE:
- r = LIBUSB_ERROR_NO_DEVICE;
- break;
- case LIBUSB_TRANSFER_ERROR:
- case LIBUSB_TRANSFER_CANCELLED:
- r = LIBUSB_ERROR_IO;
- break;
- default:
- r = LIBUSB_ERROR_OTHER;
- break;
+ case LIBUSB_TRANSFER_COMPLETED:
+ r = 0;
+ break;
+ case LIBUSB_TRANSFER_TIMED_OUT:
+ r = LIBUSB_ERROR_TIMEOUT;
+ break;
+ case LIBUSB_TRANSFER_STALL:
+ r = LIBUSB_ERROR_PIPE;
+ break;
+ case LIBUSB_TRANSFER_OVERFLOW:
+ r = LIBUSB_ERROR_OVERFLOW;
+ break;
+ case LIBUSB_TRANSFER_NO_DEVICE:
+ r = LIBUSB_ERROR_NO_DEVICE;
+ break;
+ case LIBUSB_TRANSFER_ERROR:
+ case LIBUSB_TRANSFER_CANCELLED:
+ r = LIBUSB_ERROR_IO;
+ break;
+ default:
+ r = LIBUSB_ERROR_OTHER;
+ break;
}
return r;
@@ -1058,13 +1058,13 @@ static int stlink_usb_error_check(void *handle)
if (h->st_mode == STLINK_MODE_DEBUG_SWIM) {
switch (h->databuf[0]) {
- case STLINK_SWIM_ERR_OK:
- return ERROR_OK;
- case STLINK_SWIM_BUSY:
- return ERROR_WAIT;
- default:
- LOG_DEBUG("unknown/unexpected STLINK status code 0x%x", h->databuf[0]);
- return ERROR_FAIL;
+ case STLINK_SWIM_ERR_OK:
+ return ERROR_OK;
+ case STLINK_SWIM_BUSY:
+ return ERROR_WAIT;
+ default:
+ LOG_DEBUG("unknown/unexpected STLINK status code 0x%x", h->databuf[0]);
+ return ERROR_FAIL;
}
}
@@ -1073,64 +1073,64 @@ static int stlink_usb_error_check(void *handle)
h->databuf[0] = STLINK_DEBUG_ERR_OK;
switch (h->databuf[0]) {
- case STLINK_DEBUG_ERR_OK:
- return ERROR_OK;
- case STLINK_DEBUG_ERR_FAULT:
- LOG_DEBUG("SWD fault response (0x%x)", STLINK_DEBUG_ERR_FAULT);
- return ERROR_FAIL;
- case STLINK_SWD_AP_WAIT:
- LOG_DEBUG("wait status SWD_AP_WAIT (0x%x)", STLINK_SWD_AP_WAIT);
- return ERROR_WAIT;
- case STLINK_SWD_DP_WAIT:
- LOG_DEBUG("wait status SWD_DP_WAIT (0x%x)", STLINK_SWD_DP_WAIT);
- return ERROR_WAIT;
- case STLINK_JTAG_GET_IDCODE_ERROR:
- LOG_DEBUG("STLINK_JTAG_GET_IDCODE_ERROR");
- return ERROR_FAIL;
- case STLINK_JTAG_WRITE_ERROR:
- LOG_DEBUG("Write error");
- return ERROR_FAIL;
- case STLINK_JTAG_WRITE_VERIF_ERROR:
- LOG_DEBUG("Write verify error, ignoring");
- return ERROR_OK;
- case STLINK_SWD_AP_FAULT:
- /* git://git.ac6.fr/openocd commit 657e3e885b9ee10
- * returns ERROR_OK with the comment:
- * Change in error status when reading outside RAM.
- * This fix allows CDT plugin to visualize memory.
- */
- LOG_DEBUG("STLINK_SWD_AP_FAULT");
- return ERROR_FAIL;
- case STLINK_SWD_AP_ERROR:
- LOG_DEBUG("STLINK_SWD_AP_ERROR");
- return ERROR_FAIL;
- case STLINK_SWD_AP_PARITY_ERROR:
- LOG_DEBUG("STLINK_SWD_AP_PARITY_ERROR");
- return ERROR_FAIL;
- case STLINK_SWD_DP_FAULT:
- LOG_DEBUG("STLINK_SWD_DP_FAULT");
- return ERROR_FAIL;
- case STLINK_SWD_DP_ERROR:
- LOG_DEBUG("STLINK_SWD_DP_ERROR");
- return ERROR_FAIL;
- case STLINK_SWD_DP_PARITY_ERROR:
- LOG_DEBUG("STLINK_SWD_DP_PARITY_ERROR");
- return ERROR_FAIL;
- case STLINK_SWD_AP_WDATA_ERROR:
- LOG_DEBUG("STLINK_SWD_AP_WDATA_ERROR");
- return ERROR_FAIL;
- case STLINK_SWD_AP_STICKY_ERROR:
- LOG_DEBUG("STLINK_SWD_AP_STICKY_ERROR");
- return ERROR_FAIL;
- case STLINK_SWD_AP_STICKYORUN_ERROR:
- LOG_DEBUG("STLINK_SWD_AP_STICKYORUN_ERROR");
- return ERROR_FAIL;
- case STLINK_BAD_AP_ERROR:
- LOG_DEBUG("STLINK_BAD_AP_ERROR");
- return ERROR_FAIL;
- default:
- LOG_DEBUG("unknown/unexpected STLINK status code 0x%x", h->databuf[0]);
- return ERROR_FAIL;
+ case STLINK_DEBUG_ERR_OK:
+ return ERROR_OK;
+ case STLINK_DEBUG_ERR_FAULT:
+ LOG_DEBUG("SWD fault response (0x%x)", STLINK_DEBUG_ERR_FAULT);
+ return ERROR_FAIL;
+ case STLINK_SWD_AP_WAIT:
+ LOG_DEBUG("wait status SWD_AP_WAIT (0x%x)", STLINK_SWD_AP_WAIT);
+ return ERROR_WAIT;
+ case STLINK_SWD_DP_WAIT:
+ LOG_DEBUG("wait status SWD_DP_WAIT (0x%x)", STLINK_SWD_DP_WAIT);
+ return ERROR_WAIT;
+ case STLINK_JTAG_GET_IDCODE_ERROR:
+ LOG_DEBUG("STLINK_JTAG_GET_IDCODE_ERROR");
+ return ERROR_FAIL;
+ case STLINK_JTAG_WRITE_ERROR:
+ LOG_DEBUG("Write error");
+ return ERROR_FAIL;
+ case STLINK_JTAG_WRITE_VERIF_ERROR:
+ LOG_DEBUG("Write verify error, ignoring");
+ return ERROR_OK;
+ case STLINK_SWD_AP_FAULT:
+ /* git://git.ac6.fr/openocd commit 657e3e885b9ee10
+ * returns ERROR_OK with the comment:
+ * Change in error status when reading outside RAM.
+ * This fix allows CDT plugin to visualize memory.
+ */
+ LOG_DEBUG("STLINK_SWD_AP_FAULT");
+ return ERROR_FAIL;
+ case STLINK_SWD_AP_ERROR:
+ LOG_DEBUG("STLINK_SWD_AP_ERROR");
+ return ERROR_FAIL;
+ case STLINK_SWD_AP_PARITY_ERROR:
+ LOG_DEBUG("STLINK_SWD_AP_PARITY_ERROR");
+ return ERROR_FAIL;
+ case STLINK_SWD_DP_FAULT:
+ LOG_DEBUG("STLINK_SWD_DP_FAULT");
+ return ERROR_FAIL;
+ case STLINK_SWD_DP_ERROR:
+ LOG_DEBUG("STLINK_SWD_DP_ERROR");
+ return ERROR_FAIL;
+ case STLINK_SWD_DP_PARITY_ERROR:
+ LOG_DEBUG("STLINK_SWD_DP_PARITY_ERROR");
+ return ERROR_FAIL;
+ case STLINK_SWD_AP_WDATA_ERROR:
+ LOG_DEBUG("STLINK_SWD_AP_WDATA_ERROR");
+ return ERROR_FAIL;
+ case STLINK_SWD_AP_STICKY_ERROR:
+ LOG_DEBUG("STLINK_SWD_AP_STICKY_ERROR");
+ return ERROR_FAIL;
+ case STLINK_SWD_AP_STICKYORUN_ERROR:
+ LOG_DEBUG("STLINK_SWD_AP_STICKYORUN_ERROR");
+ return ERROR_FAIL;
+ case STLINK_BAD_AP_ERROR:
+ LOG_DEBUG("STLINK_BAD_AP_ERROR");
+ return ERROR_FAIL;
+ default:
+ LOG_DEBUG("unknown/unexpected STLINK status code 0x%x", h->databuf[0]);
+ return ERROR_FAIL;
}
}
@@ -1597,31 +1597,31 @@ static int stlink_usb_mode_enter(void *handle, enum stlink_mode type)
stlink_usb_init_buffer(handle, h->rx_ep, rx_size);
switch (type) {
- case STLINK_MODE_DEBUG_JTAG:
- h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_COMMAND;
- if (h->version.jtag_api == STLINK_JTAG_API_V1)
- h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_APIV1_ENTER;
- else
- h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_APIV2_ENTER;
- h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_ENTER_JTAG_NO_RESET;
- break;
- case STLINK_MODE_DEBUG_SWD:
- h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_COMMAND;
- if (h->version.jtag_api == STLINK_JTAG_API_V1)
- h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_APIV1_ENTER;
- else
- h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_APIV2_ENTER;
- h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_ENTER_SWD_NO_RESET;
- break;
- case STLINK_MODE_DEBUG_SWIM:
- h->cmdbuf[h->cmdidx++] = STLINK_SWIM_COMMAND;
- h->cmdbuf[h->cmdidx++] = STLINK_SWIM_ENTER;
- /* swim enter does not return any response or status */
- return stlink_usb_xfer_noerrcheck(handle, h->databuf, 0);
- case STLINK_MODE_DFU:
- case STLINK_MODE_MASS:
- default:
- return ERROR_FAIL;
+ case STLINK_MODE_DEBUG_JTAG:
+ h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_COMMAND;
+ if (h->version.jtag_api == STLINK_JTAG_API_V1)
+ h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_APIV1_ENTER;
+ else
+ h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_APIV2_ENTER;
+ h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_ENTER_JTAG_NO_RESET;
+ break;
+ case STLINK_MODE_DEBUG_SWD:
+ h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_COMMAND;
+ if (h->version.jtag_api == STLINK_JTAG_API_V1)
+ h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_APIV1_ENTER;
+ else
+ h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_APIV2_ENTER;
+ h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_ENTER_SWD_NO_RESET;
+ break;
+ case STLINK_MODE_DEBUG_SWIM:
+ h->cmdbuf[h->cmdidx++] = STLINK_SWIM_COMMAND;
+ h->cmdbuf[h->cmdidx++] = STLINK_SWIM_ENTER;
+ /* swim enter does not return any response or status */
+ return stlink_usb_xfer_noerrcheck(handle, h->databuf, 0);
+ case STLINK_MODE_DFU:
+ case STLINK_MODE_MASS:
+ default:
+ return ERROR_FAIL;
}
return stlink_cmd_allow_retry(handle, h->databuf, rx_size);
@@ -1639,22 +1639,22 @@ static int stlink_usb_mode_leave(void *handle, enum stlink_mode type)
stlink_usb_init_buffer(handle, h->rx_ep, 0);
switch (type) {
- case STLINK_MODE_DEBUG_JTAG:
- case STLINK_MODE_DEBUG_SWD:
- h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_COMMAND;
- h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_EXIT;
- break;
- case STLINK_MODE_DEBUG_SWIM:
- h->cmdbuf[h->cmdidx++] = STLINK_SWIM_COMMAND;
- h->cmdbuf[h->cmdidx++] = STLINK_SWIM_EXIT;
- break;
- case STLINK_MODE_DFU:
- h->cmdbuf[h->cmdidx++] = STLINK_DFU_COMMAND;
- h->cmdbuf[h->cmdidx++] = STLINK_DFU_EXIT;
- break;
- case STLINK_MODE_MASS:
- default:
- return ERROR_FAIL;
+ case STLINK_MODE_DEBUG_JTAG:
+ case STLINK_MODE_DEBUG_SWD:
+ h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_COMMAND;
+ h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_EXIT;
+ break;
+ case STLINK_MODE_DEBUG_SWIM:
+ h->cmdbuf[h->cmdidx++] = STLINK_SWIM_COMMAND;
+ h->cmdbuf[h->cmdidx++] = STLINK_SWIM_EXIT;
+ break;
+ case STLINK_MODE_DFU:
+ h->cmdbuf[h->cmdidx++] = STLINK_DFU_COMMAND;
+ h->cmdbuf[h->cmdidx++] = STLINK_DFU_EXIT;
+ break;
+ case STLINK_MODE_MASS:
+ default:
+ return ERROR_FAIL;
}
res = stlink_usb_xfer_noerrcheck(handle, h->databuf, 0);
@@ -1697,20 +1697,20 @@ static int stlink_usb_exit_mode(void *handle)
/* try to exit current mode */
switch (mode) {
- case STLINK_DEV_DFU_MODE:
- emode = STLINK_MODE_DFU;
- break;
- case STLINK_DEV_DEBUG_MODE:
- emode = STLINK_MODE_DEBUG_SWD;
- break;
- case STLINK_DEV_SWIM_MODE:
- emode = STLINK_MODE_DEBUG_SWIM;
- break;
- case STLINK_DEV_BOOTLOADER_MODE:
- case STLINK_DEV_MASS_MODE:
- default:
- emode = STLINK_MODE_UNKNOWN;
- break;
+ case STLINK_DEV_DFU_MODE:
+ emode = STLINK_MODE_DFU;
+ break;
+ case STLINK_DEV_DEBUG_MODE:
+ emode = STLINK_MODE_DEBUG_SWD;
+ break;
+ case STLINK_DEV_SWIM_MODE:
+ emode = STLINK_MODE_DEBUG_SWIM;
+ break;
+ case STLINK_DEV_BOOTLOADER_MODE:
+ case STLINK_DEV_MASS_MODE:
+ default:
+ emode = STLINK_MODE_UNKNOWN;
+ break;
}
if (emode != STLINK_MODE_UNKNOWN)
@@ -3430,34 +3430,34 @@ static int stlink_usb_usb_open(void *handle, struct hl_interface_param *param)
/* wrap version for first read */
switch (pid) {
- case STLINK_V1_PID:
- h->version.stlink = 1;
- h->tx_ep = STLINK_TX_EP;
- break;
- case STLINK_V3_USBLOADER_PID:
- case STLINK_V3E_PID:
- 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;
- break;
- case STLINK_V2_1_PID:
- case STLINK_V2_1_NO_MSD_PID:
- h->version.stlink = 2;
- h->tx_ep = STLINK_V2_1_TX_EP;
- h->trace_ep = STLINK_V2_1_TRACE_EP;
- break;
- default:
- /* fall through - we assume V2 to be the default version*/
- case STLINK_V2_PID:
- h->version.stlink = 2;
- h->tx_ep = STLINK_TX_EP;
- h->trace_ep = STLINK_TRACE_EP;
- break;
+ case STLINK_V1_PID:
+ h->version.stlink = 1;
+ h->tx_ep = STLINK_TX_EP;
+ break;
+ case STLINK_V3_USBLOADER_PID:
+ case STLINK_V3E_PID:
+ 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;
+ break;
+ case STLINK_V2_1_PID:
+ case STLINK_V2_1_NO_MSD_PID:
+ h->version.stlink = 2;
+ h->tx_ep = STLINK_V2_1_TX_EP;
+ h->trace_ep = STLINK_V2_1_TRACE_EP;
+ break;
+ default:
+ /* fall through - we assume V2 to be the default version */
+ case STLINK_V2_PID:
+ h->version.stlink = 2;
+ h->tx_ep = STLINK_TX_EP;
+ h->trace_ep = STLINK_TRACE_EP;
+ break;
}
/* get the device version */
@@ -3758,21 +3758,21 @@ static int stlink_open(struct hl_interface_param *param, enum stlink_mode mode,
int err = ERROR_OK;
switch (h->st_mode) {
- case STLINK_MODE_DEBUG_SWD:
- if (h->version.jtag_api == STLINK_JTAG_API_V1)
- err = ERROR_FAIL;
- /* fall-through */
- case STLINK_MODE_DEBUG_JTAG:
- if (h->version.jtag == 0)
- err = ERROR_FAIL;
- break;
- case STLINK_MODE_DEBUG_SWIM:
- if (h->version.swim == 0)
- err = ERROR_FAIL;
- break;
- default:
+ case STLINK_MODE_DEBUG_SWD:
+ if (h->version.jtag_api == STLINK_JTAG_API_V1)
err = ERROR_FAIL;
- break;
+ /* fall-through */
+ case STLINK_MODE_DEBUG_JTAG:
+ if (h->version.jtag == 0)
+ err = ERROR_FAIL;
+ break;
+ case STLINK_MODE_DEBUG_SWIM:
+ if (h->version.swim == 0)
+ err = ERROR_FAIL;
+ break;
+ default:
+ err = ERROR_FAIL;
+ break;
}
if (err != ERROR_OK) {
@@ -4194,7 +4194,7 @@ static int stlink_dap_op_connect(struct adiv5_dap *dap)
uint32_t idcode;
int retval;
- LOG_INFO("stlink_dap_op_connect(%sconnect)", dap->do_reconnect ? "re" : "");
+ LOG_DEBUG("%s(%sconnect)", __func__, dap->do_reconnect ? "re" : "");
/* Check if we should reset srst already when connecting, but not if reconnecting. */
if (!dap->do_reconnect) {
diff --git a/src/jtag/drivers/ti_icdi_usb.c b/src/jtag/drivers/ti_icdi_usb.c
index 0e01171ea9..9f0791f3d2 100644
--- a/src/jtag/drivers/ti_icdi_usb.c
+++ b/src/jtag/drivers/ti_icdi_usb.c
@@ -692,14 +692,14 @@ static int icdi_usb_open(struct hl_interface_param *param, void **fd)
switch (param->transport) {
#if 0
- /* TODO place holder as swd is not currently supported */
- case HL_TRANSPORT_SWD:
+ /* TODO place holder as swd is not currently supported */
+ case HL_TRANSPORT_SWD:
#endif
- case HL_TRANSPORT_JTAG:
- break;
- default:
- retval = ERROR_FAIL;
- break;
+ case HL_TRANSPORT_JTAG:
+ break;
+ default:
+ retval = ERROR_FAIL;
+ break;
}
if (retval != ERROR_OK) {
diff --git a/src/jtag/drivers/ulink.c b/src/jtag/drivers/ulink.c
index 417d560cde..1f14b1a047 100644
--- a/src/jtag/drivers/ulink.c
+++ b/src/jtag/drivers/ulink.c
@@ -523,32 +523,30 @@ static int ulink_allocate_payload(struct ulink_cmd *ulink_cmd, int size,
}
switch (direction) {
- case PAYLOAD_DIRECTION_OUT:
- if (ulink_cmd->payload_out) {
- LOG_ERROR("BUG: Duplicate payload allocation for OpenULINK command");
- free(payload);
- return ERROR_FAIL;
- } else {
- ulink_cmd->payload_out = payload;
- ulink_cmd->payload_out_size = size;
- }
- break;
- case PAYLOAD_DIRECTION_IN:
- if (ulink_cmd->payload_in_start) {
- LOG_ERROR("BUG: Duplicate payload allocation for OpenULINK command");
- free(payload);
- return ERROR_FAIL;
- } else {
- ulink_cmd->payload_in_start = payload;
- ulink_cmd->payload_in = payload;
- ulink_cmd->payload_in_size = size;
-
- /* By default, free payload_in_start in ulink_clear_queue(). Commands
- * that do not want this behavior (e. g. split scans) must turn it off
- * separately! */
- ulink_cmd->free_payload_in_start = true;
- }
- break;
+ case PAYLOAD_DIRECTION_OUT:
+ if (ulink_cmd->payload_out) {
+ LOG_ERROR("BUG: Duplicate payload allocation for OpenULINK command");
+ free(payload);
+ return ERROR_FAIL;
+ }
+ ulink_cmd->payload_out = payload;
+ ulink_cmd->payload_out_size = size;
+ break;
+ case PAYLOAD_DIRECTION_IN:
+ if (ulink_cmd->payload_in_start) {
+ LOG_ERROR("BUG: Duplicate payload allocation for OpenULINK command");
+ free(payload);
+ return ERROR_FAIL;
+ }
+ ulink_cmd->payload_in_start = payload;
+ ulink_cmd->payload_in = payload;
+ ulink_cmd->payload_in_size = size;
+
+ /* By default, free payload_in_start in ulink_clear_queue(). Commands
+ * that do not want this behavior (e.g. split scans) must turn it off
+ * separately! */
+ ulink_cmd->free_payload_in_start = true;
+ break;
}
return ERROR_OK;
@@ -572,12 +570,12 @@ static int ulink_get_queue_size(struct ulink *device,
while (current) {
switch (direction) {
- case PAYLOAD_DIRECTION_OUT:
- sum += current->payload_out_size + 1; /* + 1 byte for Command ID */
- break;
- case PAYLOAD_DIRECTION_IN:
- sum += current->payload_in_size;
- break;
+ case PAYLOAD_DIRECTION_OUT:
+ sum += current->payload_out_size + 1; /* + 1 byte for Command ID */
+ break;
+ case PAYLOAD_DIRECTION_IN:
+ sum += current->payload_in_size;
+ break;
}
current = current->next;
@@ -881,31 +879,31 @@ static int ulink_append_scan_cmd(struct ulink *device, enum scan_type scan_type,
/* Allocate out_payload depending on scan type */
switch (scan_type) {
- case SCAN_IN:
- if (device->delay_scan_in < 0)
- cmd->id = CMD_SCAN_IN;
- else
- cmd->id = CMD_SLOW_SCAN_IN;
- ret = ulink_allocate_payload(cmd, 5, PAYLOAD_DIRECTION_OUT);
- break;
- case SCAN_OUT:
- if (device->delay_scan_out < 0)
- cmd->id = CMD_SCAN_OUT;
- else
- cmd->id = CMD_SLOW_SCAN_OUT;
- ret = ulink_allocate_payload(cmd, scan_size_bytes + 5, PAYLOAD_DIRECTION_OUT);
- break;
- case SCAN_IO:
- if (device->delay_scan_io < 0)
- cmd->id = CMD_SCAN_IO;
- else
- cmd->id = CMD_SLOW_SCAN_IO;
- ret = ulink_allocate_payload(cmd, scan_size_bytes + 5, PAYLOAD_DIRECTION_OUT);
- break;
- default:
- LOG_ERROR("BUG: ulink_append_scan_cmd() encountered an unknown scan type");
- ret = ERROR_FAIL;
- break;
+ case SCAN_IN:
+ if (device->delay_scan_in < 0)
+ cmd->id = CMD_SCAN_IN;
+ else
+ cmd->id = CMD_SLOW_SCAN_IN;
+ ret = ulink_allocate_payload(cmd, 5, PAYLOAD_DIRECTION_OUT);
+ break;
+ case SCAN_OUT:
+ if (device->delay_scan_out < 0)
+ cmd->id = CMD_SCAN_OUT;
+ else
+ cmd->id = CMD_SLOW_SCAN_OUT;
+ ret = ulink_allocate_payload(cmd, scan_size_bytes + 5, PAYLOAD_DIRECTION_OUT);
+ break;
+ case SCAN_IO:
+ if (device->delay_scan_io < 0)
+ cmd->id = CMD_SCAN_IO;
+ else
+ cmd->id = CMD_SLOW_SCAN_IO;
+ ret = ulink_allocate_payload(cmd, scan_size_bytes + 5, PAYLOAD_DIRECTION_OUT);
+ break;
+ default:
+ LOG_ERROR("BUG: %s() encountered an unknown scan type", __func__);
+ ret = ERROR_FAIL;
+ break;
}
if (ret != ERROR_OK) {
@@ -1287,24 +1285,24 @@ static int ulink_calculate_delay(enum ulink_delay_type type, long f, int *delay)
t = 1.0 / (float)(f);
switch (type) {
- case DELAY_CLOCK_TCK:
- x = (t - (float)(6E-6)) / (float)(4E-6);
- break;
- case DELAY_CLOCK_TMS:
- x = (t - (float)(8.5E-6)) / (float)(4E-6);
- break;
- case DELAY_SCAN_IN:
- x = (t - (float)(8.8308E-6)) / (float)(4E-6);
- break;
- case DELAY_SCAN_OUT:
- x = (t - (float)(1.0527E-5)) / (float)(4E-6);
- break;
- case DELAY_SCAN_IO:
- x = (t - (float)(1.3132E-5)) / (float)(4E-6);
- break;
- default:
- return ERROR_FAIL;
- break;
+ case DELAY_CLOCK_TCK:
+ x = (t - (float)(6E-6)) / (float)(4E-6);
+ break;
+ case DELAY_CLOCK_TMS:
+ x = (t - (float)(8.5E-6)) / (float)(4E-6);
+ break;
+ case DELAY_SCAN_IN:
+ x = (t - (float)(8.8308E-6)) / (float)(4E-6);
+ break;
+ case DELAY_SCAN_OUT:
+ x = (t - (float)(1.0527E-5)) / (float)(4E-6);
+ break;
+ case DELAY_SCAN_IO:
+ x = (t - (float)(1.3132E-5)) / (float)(4E-6);
+ break;
+ default:
+ return ERROR_FAIL;
+ break;
}
/* Check if the delay value is negative. This happens when a frequency is
@@ -1347,38 +1345,38 @@ static long ulink_calculate_frequency(enum ulink_delay_type type, int delay)
return 0;
switch (type) {
- case DELAY_CLOCK_TCK:
- if (delay < 0)
- t = (float)(2.666E-6);
- else
- t = (float)(4E-6) * (float)(delay) + (float)(6E-6);
- break;
- case DELAY_CLOCK_TMS:
- if (delay < 0)
- t = (float)(5.666E-6);
- else
- t = (float)(4E-6) * (float)(delay) + (float)(8.5E-6);
- break;
- case DELAY_SCAN_IN:
- if (delay < 0)
- t = (float)(5.5E-6);
- else
- t = (float)(4E-6) * (float)(delay) + (float)(8.8308E-6);
- break;
- case DELAY_SCAN_OUT:
- if (delay < 0)
- t = (float)(7.0E-6);
- else
- t = (float)(4E-6) * (float)(delay) + (float)(1.0527E-5);
- break;
- case DELAY_SCAN_IO:
- if (delay < 0)
- t = (float)(9.926E-6);
- else
- t = (float)(4E-6) * (float)(delay) + (float)(1.3132E-5);
- break;
- default:
- return 0;
+ case DELAY_CLOCK_TCK:
+ if (delay < 0)
+ t = (float)(2.666E-6);
+ else
+ t = (float)(4E-6) * (float)(delay) + (float)(6E-6);
+ break;
+ case DELAY_CLOCK_TMS:
+ if (delay < 0)
+ t = (float)(5.666E-6);
+ else
+ t = (float)(4E-6) * (float)(delay) + (float)(8.5E-6);
+ break;
+ case DELAY_SCAN_IN:
+ if (delay < 0)
+ t = (float)(5.5E-6);
+ else
+ t = (float)(4E-6) * (float)(delay) + (float)(8.8308E-6);
+ break;
+ case DELAY_SCAN_OUT:
+ if (delay < 0)
+ t = (float)(7.0E-6);
+ else
+ t = (float)(4E-6) * (float)(delay) + (float)(1.0527E-5);
+ break;
+ case DELAY_SCAN_IO:
+ if (delay < 0)
+ t = (float)(9.926E-6);
+ else
+ t = (float)(4E-6) * (float)(delay) + (float)(1.3132E-5);
+ break;
+ default:
+ return 0;
}
f_float = 1.0 / t;
@@ -1823,19 +1821,18 @@ static int ulink_post_process_scan(struct ulink_cmd *ulink_cmd)
int ret;
switch (jtag_scan_type(cmd->cmd.scan)) {
- case SCAN_IN:
- case SCAN_IO:
- ret = jtag_read_buffer(ulink_cmd->payload_in_start, cmd->cmd.scan);
- break;
- case SCAN_OUT:
- /* Nothing to do for OUT scans */
- ret = ERROR_OK;
- break;
- default:
- LOG_ERROR("BUG: ulink_post_process_scan() encountered an unknown"
- " JTAG scan type");
- ret = ERROR_FAIL;
- break;
+ case SCAN_IN:
+ case SCAN_IO:
+ ret = jtag_read_buffer(ulink_cmd->payload_in_start, cmd->cmd.scan);
+ break;
+ case SCAN_OUT:
+ /* Nothing to do for OUT scans */
+ ret = ERROR_OK;
+ break;
+ default:
+ LOG_ERROR("BUG: %s() encountered an unknown JTAG scan type", __func__);
+ ret = ERROR_FAIL;
+ break;
}
return ret;
@@ -1863,23 +1860,22 @@ static int ulink_post_process_queue(struct ulink *device)
* OpenULINK command */
if (current->needs_postprocessing && openocd_cmd) {
switch (openocd_cmd->type) {
- case JTAG_SCAN:
- ret = ulink_post_process_scan(current);
- break;
- case JTAG_TLR_RESET:
- case JTAG_RUNTEST:
- case JTAG_RESET:
- case JTAG_PATHMOVE:
- case JTAG_SLEEP:
- case JTAG_STABLECLOCKS:
- /* Nothing to do for these commands */
- ret = ERROR_OK;
- break;
- default:
- ret = ERROR_FAIL;
- LOG_ERROR("BUG: ulink_post_process_queue() encountered unknown JTAG "
- "command type");
- break;
+ case JTAG_SCAN:
+ ret = ulink_post_process_scan(current);
+ break;
+ case JTAG_TLR_RESET:
+ case JTAG_RUNTEST:
+ case JTAG_RESET:
+ case JTAG_PATHMOVE:
+ case JTAG_SLEEP:
+ case JTAG_STABLECLOCKS:
+ /* Nothing to do for these commands */
+ ret = ERROR_OK;
+ break;
+ default:
+ ret = ERROR_FAIL;
+ LOG_ERROR("BUG: %s() encountered unknown JTAG command type", __func__);
+ break;
}
if (ret != ERROR_OK)
@@ -1913,31 +1909,31 @@ static int ulink_execute_queue(struct jtag_command *cmd_queue)
while (cmd) {
switch (cmd->type) {
- case JTAG_SCAN:
- ret = ulink_queue_scan(ulink_handle, cmd);
- break;
- case JTAG_TLR_RESET:
- ret = ulink_queue_tlr_reset(ulink_handle, cmd);
- break;
- case JTAG_RUNTEST:
- ret = ulink_queue_runtest(ulink_handle, cmd);
- break;
- case JTAG_RESET:
- ret = ulink_queue_reset(ulink_handle, cmd);
- break;
- case JTAG_PATHMOVE:
- ret = ulink_queue_pathmove(ulink_handle, cmd);
- break;
- case JTAG_SLEEP:
- ret = ulink_queue_sleep(ulink_handle, cmd);
- break;
- case JTAG_STABLECLOCKS:
- ret = ulink_queue_stableclocks(ulink_handle, cmd);
- break;
- default:
- ret = ERROR_FAIL;
- LOG_ERROR("BUG: encountered unknown JTAG command type");
- break;
+ case JTAG_SCAN:
+ ret = ulink_queue_scan(ulink_handle, cmd);
+ break;
+ case JTAG_TLR_RESET:
+ ret = ulink_queue_tlr_reset(ulink_handle, cmd);
+ break;
+ case JTAG_RUNTEST:
+ ret = ulink_queue_runtest(ulink_handle, cmd);
+ break;
+ case JTAG_RESET:
+ ret = ulink_queue_reset(ulink_handle, cmd);
+ break;
+ case JTAG_PATHMOVE:
+ ret = ulink_queue_pathmove(ulink_handle, cmd);
+ break;
+ case JTAG_SLEEP:
+ ret = ulink_queue_sleep(ulink_handle, cmd);
+ break;
+ case JTAG_STABLECLOCKS:
+ ret = ulink_queue_stableclocks(ulink_handle, cmd);
+ break;
+ default:
+ ret = ERROR_FAIL;
+ LOG_ERROR("BUG: encountered unknown JTAG command type");
+ break;
}
if (ret != ERROR_OK)
diff --git a/src/jtag/drivers/usbprog.c b/src/jtag/drivers/usbprog.c
index 264b45f721..4783e7569a 100644
--- a/src/jtag/drivers/usbprog.c
+++ b/src/jtag/drivers/usbprog.c
@@ -274,18 +274,18 @@ static void usbprog_scan(bool ir_scan, enum scan_type type, uint8_t *buffer, int
void (*f)(struct usbprog_jtag *usbprog_jtag, char *buffer_local, int size);
switch (type) {
- case SCAN_OUT:
- f = &usbprog_jtag_write_tdi;
- break;
- case SCAN_IN:
- f = &usbprog_jtag_read_tdo;
- break;
- case SCAN_IO:
- f = &usbprog_jtag_write_and_read;
- break;
- default:
- LOG_ERROR("unknown scan type: %i", type);
- exit(-1);
+ case SCAN_OUT:
+ f = &usbprog_jtag_write_tdi;
+ break;
+ case SCAN_IN:
+ f = &usbprog_jtag_read_tdo;
+ break;
+ case SCAN_IO:
+ f = &usbprog_jtag_write_and_read;
+ break;
+ default:
+ LOG_ERROR("unknown scan type: %i", type);
+ exit(-1);
}
f(usbprog_jtag_handle, (char *)buffer, scan_size);
diff --git a/src/jtag/drivers/vdebug.c b/src/jtag/drivers/vdebug.c
index 38685950a8..29bfa8360d 100644
--- a/src/jtag/drivers/vdebug.c
+++ b/src/jtag/drivers/vdebug.c
@@ -47,19 +47,20 @@
#include "jtag/interface.h"
#include "jtag/commands.h"
#include "transport/transport.h"
+#include "target/target.h"
#include "target/arm_adi_v5.h"
#include "helper/time_support.h"
#include "helper/replacements.h"
#include "helper/log.h"
#include "helper/list.h"
-#define VD_VERSION 48
+#define VD_VERSION 50
#define VD_BUFFER_LEN 4024
#define VD_CHEADER_LEN 24
#define VD_SHEADER_LEN 16
#define VD_MAX_MEMORIES 20
-#define VD_POLL_INTERVAL 500
+#define VD_POLL_INTERVAL 1000
#define VD_SCALE_PSTOMS 1000000000
/**
@@ -205,6 +206,7 @@ struct vd_client {
uint32_t poll_max;
uint32_t targ_time;
int hsocket;
+ int64_t poll_ts;
char server_name[32];
char bfm_path[128];
char mem_path[VD_MAX_MEMORIES][128];
@@ -839,6 +841,35 @@ static void vdebug_mem_close(int hsock, struct vd_shm *pm, uint8_t ndx)
}
+/* function gets invoked through a callback every VD_POLL_INTERVAL ms
+ * if the idle time, measured by VD_POLL_INTERVAL - targ_time is more than poll_min
+ * the wait function is called and its time measured and wait cycles adjusted.
+ * The wait allows hardware to advance, when no data activity from the vdebug occurs
+ */
+static int vdebug_poll(void *priv)
+{
+ int64_t ts, te;
+
+ ts = timeval_ms();
+ if (ts - vdc.poll_ts - vdc.targ_time >= vdc.poll_min) {
+ vdebug_wait(vdc.hsocket, pbuf, vdc.poll_cycles);
+ te = timeval_ms();
+ LOG_DEBUG("poll after %" PRId64 "ms, busy %" PRIu32 "ms; wait %" PRIu32 " %" PRId64 "ms",
+ ts - vdc.poll_ts, vdc.targ_time, vdc.poll_cycles, te - ts);
+
+ if (te - ts + vdc.targ_time < vdc.poll_max / 2)
+ vdc.poll_cycles *= 2;
+ else if (te - ts + vdc.targ_time > vdc.poll_max)
+ vdc.poll_cycles /= 2;
+ } else {
+ LOG_DEBUG("poll after %" PRId64 "ms, busy %" PRIu32 "ms", ts - vdc.poll_ts, vdc.targ_time);
+ }
+ vdc.poll_ts = ts;
+ vdc.targ_time = 0; /* reset target time counter */
+
+ return ERROR_OK;
+}
+
static int vdebug_init(void)
{
vdc.hsocket = vdebug_socket_open(vdc.server_name, vdc.server_port);
@@ -858,6 +889,7 @@ static int vdebug_init(void)
}
vdc.trans_first = 1;
vdc.poll_cycles = vdc.poll_max;
+ vdc.poll_ts = timeval_ms();
uint32_t sig_mask = VD_SIG_RESET;
if (transport_is_jtag())
sig_mask |= VD_SIG_TRST | VD_SIG_TCKDIV;
@@ -876,6 +908,8 @@ static int vdebug_init(void)
LOG_ERROR("0x%x cannot connect to %s", rc, vdc.mem_path[i]);
}
+ target_register_timer_callback(vdebug_poll, VD_POLL_INTERVAL,
+ TARGET_TIMER_TYPE_PERIODIC, &vdc);
LOG_INFO("vdebug %d connected to %s through %s:%" PRIu16,
VD_VERSION, vdc.bfm_path, vdc.server_name, vdc.server_port);
}
@@ -885,6 +919,8 @@ static int vdebug_init(void)
static int vdebug_quit(void)
{
+ target_unregister_timer_callback(vdebug_poll, &vdc);
+
for (uint8_t i = 0; i < vdc.mem_ndx; i++)
if (vdc.mem_width[i])
vdebug_mem_close(vdc.hsocket, pbuf, i);
@@ -1299,16 +1335,16 @@ static const struct command_registration vdebug_command_handlers[] = {
{
.name = "batching",
.handler = &vdebug_set_batching,
- .mode = COMMAND_CONFIG,
+ .mode = COMMAND_ANY,
.help = "set the transaction batching no|wr|rd [0|1|2]",
.usage = "",
},
{
.name = "polling",
.handler = &vdebug_set_polling,
- .mode = COMMAND_CONFIG,
- .help = "set the polling pause, executing hardware cycles between min and max",
- .usage = " ",
+ .mode = COMMAND_ANY,
+ .help = "set the min idle time and max wait time in ms",
+ .usage = " ",
},
COMMAND_REGISTRATION_DONE
};
diff --git a/src/jtag/drivers/xds110.c b/src/jtag/drivers/xds110.c
index d1bb705908..a2b0dd213e 100644
--- a/src/jtag/drivers/xds110.c
+++ b/src/jtag/drivers/xds110.c
@@ -428,7 +428,7 @@ static bool usb_connect(void)
/* Log the results */
if (result == 0)
- LOG_INFO("XDS110: connected");
+ LOG_DEBUG("XDS110: connected");
else
LOG_ERROR("XDS110: failed to connect");
@@ -448,7 +448,7 @@ static void usb_disconnect(void)
xds110.ctx = NULL;
}
- LOG_INFO("XDS110: disconnected");
+ LOG_DEBUG("XDS110: disconnected");
}
static bool usb_read(unsigned char *buffer, int size, int *bytes_read,
@@ -1551,42 +1551,42 @@ static void xds110_flush(void)
while (xds110.txn_requests[request] != 0) {
command = xds110.txn_requests[request++];
switch (command) {
- case CMD_IR_SCAN:
- case CMD_DR_SCAN:
- if (command == CMD_IR_SCAN)
- shift_state = XDS_JTAG_STATE_SHIFT_IR;
- else
- shift_state = XDS_JTAG_STATE_SHIFT_DR;
- end_state = (uint32_t)(xds110.txn_requests[request++]);
- bits = (uint32_t)(xds110.txn_requests[request++]) << 0;
- bits |= (uint32_t)(xds110.txn_requests[request++]) << 8;
- data_out = &xds110.txn_requests[request];
- bytes = DIV_ROUND_UP(bits, 8);
- xds110_legacy_scan(shift_state, bits, end_state, data_out,
- &data_in[result]);
- result += bytes;
- request += bytes;
- break;
- case CMD_RUNTEST:
- clocks = (uint32_t)(xds110.txn_requests[request++]) << 0;
- clocks |= (uint32_t)(xds110.txn_requests[request++]) << 8;
- clocks |= (uint32_t)(xds110.txn_requests[request++]) << 16;
- clocks |= (uint32_t)(xds110.txn_requests[request++]) << 24;
- end_state = (uint32_t)xds110.txn_requests[request++];
- xds110_legacy_runtest(clocks, end_state);
- break;
- case CMD_STABLECLOCKS:
- clocks = (uint32_t)(xds110.txn_requests[request++]) << 0;
- clocks |= (uint32_t)(xds110.txn_requests[request++]) << 8;
- clocks |= (uint32_t)(xds110.txn_requests[request++]) << 16;
- clocks |= (uint32_t)(xds110.txn_requests[request++]) << 24;
- xds110_legacy_stableclocks(clocks);
- break;
- default:
- LOG_ERROR("BUG: unknown JTAG command type 0x%x encountered",
- command);
- exit(-1);
- break;
+ case CMD_IR_SCAN:
+ case CMD_DR_SCAN:
+ if (command == CMD_IR_SCAN)
+ shift_state = XDS_JTAG_STATE_SHIFT_IR;
+ else
+ shift_state = XDS_JTAG_STATE_SHIFT_DR;
+ end_state = (uint32_t)(xds110.txn_requests[request++]);
+ bits = (uint32_t)(xds110.txn_requests[request++]) << 0;
+ bits |= (uint32_t)(xds110.txn_requests[request++]) << 8;
+ data_out = &xds110.txn_requests[request];
+ bytes = DIV_ROUND_UP(bits, 8);
+ xds110_legacy_scan(shift_state, bits, end_state, data_out,
+ &data_in[result]);
+ result += bytes;
+ request += bytes;
+ break;
+ case CMD_RUNTEST:
+ clocks = (uint32_t)(xds110.txn_requests[request++]) << 0;
+ clocks |= (uint32_t)(xds110.txn_requests[request++]) << 8;
+ clocks |= (uint32_t)(xds110.txn_requests[request++]) << 16;
+ clocks |= (uint32_t)(xds110.txn_requests[request++]) << 24;
+ end_state = (uint32_t)xds110.txn_requests[request++];
+ xds110_legacy_runtest(clocks, end_state);
+ break;
+ case CMD_STABLECLOCKS:
+ clocks = (uint32_t)(xds110.txn_requests[request++]) << 0;
+ clocks |= (uint32_t)(xds110.txn_requests[request++]) << 8;
+ clocks |= (uint32_t)(xds110.txn_requests[request++]) << 16;
+ clocks |= (uint32_t)(xds110.txn_requests[request++]) << 24;
+ xds110_legacy_stableclocks(clocks);
+ break;
+ default:
+ LOG_ERROR("BUG: unknown JTAG command type 0x%x encountered",
+ command);
+ exit(-1);
+ break;
}
}
}
@@ -1809,32 +1809,32 @@ static void xds110_queue_stableclocks(struct jtag_command *cmd)
static void xds110_execute_command(struct jtag_command *cmd)
{
switch (cmd->type) {
- case JTAG_SLEEP:
- xds110_flush();
- xds110_execute_sleep(cmd);
- break;
- case JTAG_TLR_RESET:
- xds110_flush();
- xds110_execute_tlr_reset(cmd);
- break;
- case JTAG_PATHMOVE:
- xds110_flush();
- xds110_execute_pathmove(cmd);
- break;
- case JTAG_SCAN:
- xds110_queue_scan(cmd);
- break;
- case JTAG_RUNTEST:
- xds110_queue_runtest(cmd);
- break;
- case JTAG_STABLECLOCKS:
- xds110_queue_stableclocks(cmd);
- break;
- case JTAG_TMS:
- default:
- LOG_ERROR("BUG: unknown JTAG command type 0x%x encountered",
- cmd->type);
- exit(-1);
+ case JTAG_SLEEP:
+ xds110_flush();
+ xds110_execute_sleep(cmd);
+ break;
+ case JTAG_TLR_RESET:
+ xds110_flush();
+ xds110_execute_tlr_reset(cmd);
+ break;
+ case JTAG_PATHMOVE:
+ xds110_flush();
+ xds110_execute_pathmove(cmd);
+ break;
+ case JTAG_SCAN:
+ xds110_queue_scan(cmd);
+ break;
+ case JTAG_RUNTEST:
+ xds110_queue_runtest(cmd);
+ break;
+ case JTAG_STABLECLOCKS:
+ xds110_queue_stableclocks(cmd);
+ break;
+ case JTAG_TMS:
+ default:
+ LOG_ERROR("BUG: unknown JTAG command type 0x%x encountered",
+ cmd->type);
+ exit(-1);
}
}
diff --git a/src/jtag/drivers/xlnx-pcie-xvc.c b/src/jtag/drivers/xlnx-xvc.c
similarity index 50%
rename from src/jtag/drivers/xlnx-pcie-xvc.c
rename to src/jtag/drivers/xlnx-xvc.c
index 3baa183d95..f00650671d 100644
--- a/src/jtag/drivers/xlnx-pcie-xvc.c
+++ b/src/jtag/drivers/xlnx-xvc.c
@@ -1,8 +1,14 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
- * Copyright (c) 2019 Google, LLC.
- * Author: Moritz Fischer
+ * Copyright (C) 2019 Google, LLC.
+ * Moritz Fischer
+ *
+ * Copyright (C) 2021 Western Digital Corporation or its affiliates
+ * Jeremy Garff
+ *
+ * Copyright (C) 2024 Inria
+ * Nicolas Derumigny
*/
#ifdef HAVE_CONFIG_H
@@ -11,13 +17,14 @@
#include
#include
-#include
#include
#include
+#include
#include
-#include
#include
+#include
+#include
#include
#include
@@ -28,14 +35,24 @@
#define PCIE_EXT_CAP_LST 0x100
-#define XLNX_XVC_EXT_CAP 0x00
-#define XLNX_XVC_VSEC_HDR 0x04
-#define XLNX_XVC_LEN_REG 0x0C
-#define XLNX_XVC_TMS_REG 0x10
-#define XLNX_XVC_TDX_REG 0x14
+#define XLNX_PCIE_XVC_EXT_CAP 0x00
+#define XLNX_PCIE_XVC_VSEC_HDR 0x04
+#define XLNX_PCIE_XVC_LEN_REG 0x0C
+#define XLNX_PCIE_XVC_TMS_REG 0x10
+#define XLNX_PCIE_XVC_TDX_REG 0x14
+
+#define XLNX_PCIE_XVC_CAP_SIZE 0x20
+#define XLNX_PCIE_XVC_VSEC_ID 0x8
+
+#define XLNX_AXI_XVC_LEN_REG 0x00
+#define XLNX_AXI_XVC_TMS_REG 0x04
+#define XLNX_AXI_XVC_TDI_REG 0x08
+#define XLNX_AXI_XVC_TDO_REG 0x0c
+#define XLNX_AXI_XVC_CTRL_REG 0x10
+#define XLNX_AXI_XVC_MAX_REG 0x18
+
+#define XLNX_AXI_XVC_CTRL_REG_ENABLE_MASK 0x01
-#define XLNX_XVC_CAP_SIZE 0x20
-#define XLNX_XVC_VSEC_ID 0x8
#define XLNX_XVC_MAX_BITS 0x20
#define MASK_ACK(x) (((x) >> 9) & 0x7)
@@ -47,8 +64,23 @@ struct xlnx_pcie_xvc {
char *device;
};
+struct xlnx_axi_xvc {
+ int fd;
+ uint32_t *base;
+ char *device_addr;
+ // Defaults to `/dev/mem` if NULL
+ char *device_file;
+};
+
+enum xlnx_xvc_type_t {
+ PCIE,
+ AXI
+};
+
static struct xlnx_pcie_xvc xlnx_pcie_xvc_state;
static struct xlnx_pcie_xvc *xlnx_pcie_xvc = &xlnx_pcie_xvc_state;
+static struct xlnx_axi_xvc xlnx_axi_xvc_state;
+static struct xlnx_axi_xvc *xlnx_axi_xvc = &xlnx_axi_xvc_state;
static int xlnx_pcie_xvc_read_reg(const int offset, uint32_t *val)
{
@@ -60,9 +92,9 @@ static int xlnx_pcie_xvc_read_reg(const int offset, uint32_t *val)
* space accessor functions
*/
err = pread(xlnx_pcie_xvc->fd, &res, sizeof(res),
- xlnx_pcie_xvc->offset + offset);
+ xlnx_pcie_xvc->offset + offset);
if (err != sizeof(res)) {
- LOG_ERROR("Failed to read offset %x", offset);
+ LOG_ERROR("Failed to read offset 0x%x", offset);
return ERROR_JTAG_DEVICE_ERROR;
}
@@ -72,6 +104,19 @@ static int xlnx_pcie_xvc_read_reg(const int offset, uint32_t *val)
return ERROR_OK;
}
+static int xlnx_axi_xvc_read_reg(const int offset, uint32_t *val)
+{
+ uintptr_t b = ((uintptr_t)xlnx_axi_xvc->base) + offset;
+ volatile uint32_t *w = (uint32_t *)b;
+
+ if (val) {
+ __atomic_thread_fence(__ATOMIC_SEQ_CST);
+ *val = *w;
+ }
+
+ return ERROR_OK;
+}
+
static int xlnx_pcie_xvc_write_reg(const int offset, const uint32_t val)
{
int err;
@@ -81,9 +126,9 @@ static int xlnx_pcie_xvc_write_reg(const int offset, const uint32_t val)
* space accessor functions
*/
err = pwrite(xlnx_pcie_xvc->fd, &val, sizeof(val),
- xlnx_pcie_xvc->offset + offset);
+ xlnx_pcie_xvc->offset + offset);
if (err != sizeof(val)) {
- LOG_ERROR("Failed to write offset: %x with value: %" PRIx32,
+ LOG_ERROR("Failed to write offset: 0x%x with value: %" PRIx32,
offset, val);
return ERROR_JTAG_DEVICE_ERROR;
}
@@ -91,37 +136,117 @@ static int xlnx_pcie_xvc_write_reg(const int offset, const uint32_t val)
return ERROR_OK;
}
+static int xlnx_axi_xvc_write_reg(const int offset, const uint32_t val)
+{
+ uintptr_t b = ((uintptr_t)xlnx_axi_xvc->base) + offset;
+ volatile uint32_t *w = (uint32_t *)b;
+
+ *w = val;
+ __atomic_thread_fence(__ATOMIC_SEQ_CST);
+
+ return ERROR_OK;
+}
+
static int xlnx_pcie_xvc_transact(size_t num_bits, uint32_t tms, uint32_t tdi,
uint32_t *tdo)
{
int err;
- err = xlnx_pcie_xvc_write_reg(XLNX_XVC_LEN_REG, num_bits);
+ err = xlnx_pcie_xvc_write_reg(XLNX_PCIE_XVC_LEN_REG, num_bits);
if (err != ERROR_OK)
return err;
- err = xlnx_pcie_xvc_write_reg(XLNX_XVC_TMS_REG, tms);
+ err = xlnx_pcie_xvc_write_reg(XLNX_PCIE_XVC_TMS_REG, tms);
if (err != ERROR_OK)
return err;
- err = xlnx_pcie_xvc_write_reg(XLNX_XVC_TDX_REG, tdi);
+ err = xlnx_pcie_xvc_write_reg(XLNX_PCIE_XVC_TDX_REG, tdi);
if (err != ERROR_OK)
return err;
- err = xlnx_pcie_xvc_read_reg(XLNX_XVC_TDX_REG, tdo);
+ err = xlnx_pcie_xvc_read_reg(XLNX_PCIE_XVC_TDX_REG, tdo);
if (err != ERROR_OK)
return err;
if (tdo)
LOG_DEBUG_IO("Transact num_bits: %zu, tms: %" PRIx32 ", tdi: %" PRIx32 ", tdo: %" PRIx32,
- num_bits, tms, tdi, *tdo);
+ num_bits, tms, tdi, *tdo);
else
LOG_DEBUG_IO("Transact num_bits: %zu, tms: %" PRIx32 ", tdi: %" PRIx32 ", tdo: ",
- num_bits, tms, tdi);
+ num_bits, tms, tdi);
+ return ERROR_OK;
+}
+
+static int xlnx_axi_xvc_transact(size_t num_bits, uint32_t tms, uint32_t tdi,
+ uint32_t *tdo)
+{
+ uint32_t ctrl;
+ int done = 0;
+ int err;
+
+ err = xlnx_axi_xvc_write_reg(XLNX_AXI_XVC_LEN_REG, num_bits);
+ if (err != ERROR_OK)
+ return err;
+
+ err = xlnx_axi_xvc_write_reg(XLNX_AXI_XVC_TMS_REG, tms);
+ if (err != ERROR_OK)
+ return err;
+
+ err = xlnx_axi_xvc_write_reg(XLNX_AXI_XVC_TDI_REG, tdi);
+ if (err != ERROR_OK)
+ return err;
+
+ err = xlnx_axi_xvc_write_reg(XLNX_AXI_XVC_CTRL_REG, XLNX_AXI_XVC_CTRL_REG_ENABLE_MASK);
+ if (err != ERROR_OK)
+ return err;
+
+ while (!done) {
+ err = xlnx_axi_xvc_read_reg(XLNX_AXI_XVC_CTRL_REG, &ctrl);
+ if (err != ERROR_OK)
+ return err;
+
+ if (!(ctrl & XLNX_AXI_XVC_CTRL_REG_ENABLE_MASK))
+ done = 1;
+
+ /*
+ There is no delay here intentionally. The usleep()
+ function doesn't block and burns CPU cycles anyway.
+ The turnaround time is fast enough at high JTAG rates
+ that adding the call can slow down the overall
+ throughput. So we'll just sacrifice the CPU to get
+ best performance.
+
+ Additionally there is no timeout. The underlying
+ hardware is guaranteed to unset the enable bit within
+ 32 JTAG clock cycles. There is no hardware condition
+ that will keep it set forever. Essentially, the hardware
+ is also our timeout mechanism.
+ */
+ }
+
+ err = xlnx_axi_xvc_read_reg(XLNX_AXI_XVC_TDO_REG, tdo);
+ if (err != ERROR_OK)
+ return err;
+
+ if (tdo)
+ LOG_DEBUG_IO("Transact num_bits: %zu, tms: 0x%x, tdi: 0x%x, tdo: 0x%x",
+ num_bits, tms, tdi, *tdo);
+ else
+ LOG_DEBUG_IO("Transact num_bits: %zu, tms: 0x%x, tdi: 0x%x, tdo: ",
+ num_bits, tms, tdi);
return ERROR_OK;
}
-static int xlnx_pcie_xvc_execute_stableclocks(struct jtag_command *cmd)
+static int xlnx_xvc_transact(size_t num_bits, uint32_t tms, uint32_t tdi,
+ uint32_t *tdo, enum xlnx_xvc_type_t xvc_type)
+{
+ if (xvc_type == PCIE)
+ return xlnx_pcie_xvc_transact(num_bits, tms, tdi, tdo);
+ assert(xvc_type == AXI);
+ return xlnx_axi_xvc_transact(num_bits, tms, tdi, tdo);
+}
+
+static int xlnx_xvc_execute_stableclocks(struct jtag_command *cmd, enum xlnx_xvc_type_t xvc_type)
{
int tms = tap_get_state() == TAP_RESET ? 1 : 0;
size_t left = cmd->cmd.stableclocks->num_cycles;
@@ -132,7 +257,7 @@ static int xlnx_pcie_xvc_execute_stableclocks(struct jtag_command *cmd)
while (left) {
write = MIN(XLNX_XVC_MAX_BITS, left);
- err = xlnx_pcie_xvc_transact(write, tms, 0, NULL);
+ err = xlnx_xvc_transact(write, tms, 0, NULL, xvc_type);
if (err != ERROR_OK)
return err;
left -= write;
@@ -141,12 +266,12 @@ static int xlnx_pcie_xvc_execute_stableclocks(struct jtag_command *cmd)
return ERROR_OK;
}
-static int xlnx_pcie_xvc_execute_statemove(size_t skip)
+static int xlnx_xvc_execute_statemove(size_t skip, enum xlnx_xvc_type_t xvc_type)
{
uint8_t tms_scan = tap_get_tms_path(tap_get_state(),
- tap_get_end_state());
+ tap_get_end_state());
int tms_count = tap_get_tms_path_len(tap_get_state(),
- tap_get_end_state());
+ tap_get_end_state());
int err;
LOG_DEBUG("statemove starting at (skip: %zu) %s end in %s", skip,
@@ -154,7 +279,7 @@ static int xlnx_pcie_xvc_execute_statemove(size_t skip)
tap_state_name(tap_get_end_state()));
- err = xlnx_pcie_xvc_transact(tms_count - skip, tms_scan >> skip, 0, NULL);
+ err = xlnx_xvc_transact(tms_count - skip, tms_scan >> skip, 0, NULL, xvc_type);
if (err != ERROR_OK)
return err;
@@ -163,7 +288,8 @@ static int xlnx_pcie_xvc_execute_statemove(size_t skip)
return ERROR_OK;
}
-static int xlnx_pcie_xvc_execute_runtest(struct jtag_command *cmd)
+static int xlnx_xvc_execute_runtest(struct jtag_command *cmd,
+ enum xlnx_xvc_type_t xvc_type)
{
int err = ERROR_OK;
@@ -175,7 +301,7 @@ static int xlnx_pcie_xvc_execute_runtest(struct jtag_command *cmd)
if (tap_get_state() != TAP_IDLE) {
tap_set_end_state(TAP_IDLE);
- err = xlnx_pcie_xvc_execute_statemove(0);
+ err = xlnx_xvc_execute_statemove(0, xvc_type);
if (err != ERROR_OK)
return err;
};
@@ -185,7 +311,7 @@ static int xlnx_pcie_xvc_execute_runtest(struct jtag_command *cmd)
while (left) {
write = MIN(XLNX_XVC_MAX_BITS, left);
- err = xlnx_pcie_xvc_transact(write, 0, 0, NULL);
+ err = xlnx_xvc_transact(write, 0, 0, NULL, xvc_type);
if (err != ERROR_OK)
return err;
left -= write;
@@ -193,12 +319,13 @@ static int xlnx_pcie_xvc_execute_runtest(struct jtag_command *cmd)
tap_set_end_state(tmp_state);
if (tap_get_state() != tap_get_end_state())
- err = xlnx_pcie_xvc_execute_statemove(0);
+ err = xlnx_xvc_execute_statemove(0, xvc_type);
return err;
}
-static int xlnx_pcie_xvc_execute_pathmove(struct jtag_command *cmd)
+static int xlnx_xvc_execute_pathmove(struct jtag_command *cmd,
+ enum xlnx_xvc_type_t xvc_type)
{
unsigned int num_states = cmd->cmd.pathmove->num_states;
enum tap_state *path = cmd->cmd.pathmove->path;
@@ -210,9 +337,9 @@ static int xlnx_pcie_xvc_execute_pathmove(struct jtag_command *cmd)
for (unsigned int i = 0; i < num_states; i++) {
if (path[i] == tap_state_transition(tap_get_state(), false)) {
- err = xlnx_pcie_xvc_transact(1, 1, 0, NULL);
+ err = xlnx_xvc_transact(1, 0, 0, NULL, xvc_type);
} else if (path[i] == tap_state_transition(tap_get_state(), true)) {
- err = xlnx_pcie_xvc_transact(1, 0, 0, NULL);
+ err = xlnx_xvc_transact(1, 1, 0, NULL, xvc_type);
} else {
LOG_ERROR("BUG: %s -> %s isn't a valid TAP transition.",
tap_state_name(tap_get_state()),
@@ -229,7 +356,8 @@ static int xlnx_pcie_xvc_execute_pathmove(struct jtag_command *cmd)
return ERROR_OK;
}
-static int xlnx_pcie_xvc_execute_scan(struct jtag_command *cmd)
+static int xlnx_xvc_execute_scan(struct jtag_command *cmd,
+ enum xlnx_xvc_type_t xvc_type)
{
enum scan_type type = jtag_scan_type(cmd->cmd.scan);
enum tap_state saved_end_state = cmd->cmd.scan->end_state;
@@ -253,13 +381,13 @@ static int xlnx_pcie_xvc_execute_scan(struct jtag_command *cmd)
*/
if (ir_scan && tap_get_state() != TAP_IRSHIFT) {
tap_set_end_state(TAP_IRSHIFT);
- err = xlnx_pcie_xvc_execute_statemove(0);
+ err = xlnx_xvc_execute_statemove(0, xvc_type);
if (err != ERROR_OK)
goto out_err;
tap_set_end_state(saved_end_state);
} else if (!ir_scan && (tap_get_state() != TAP_DRSHIFT)) {
tap_set_end_state(TAP_DRSHIFT);
- err = xlnx_pcie_xvc_execute_statemove(0);
+ err = xlnx_xvc_execute_statemove(0, xvc_type);
if (err != ERROR_OK)
goto out_err;
tap_set_end_state(saved_end_state);
@@ -271,8 +399,8 @@ static int xlnx_pcie_xvc_execute_scan(struct jtag_command *cmd)
/* the last TMS should be a 1, to leave the state */
tms = left <= XLNX_XVC_MAX_BITS ? BIT(write - 1) : 0;
tdi = (type != SCAN_IN) ? buf_get_u32(rd_ptr, 0, write) : 0;
- err = xlnx_pcie_xvc_transact(write, tms, tdi, type != SCAN_OUT ?
- &tdo : NULL);
+ err = xlnx_xvc_transact(write, tms, tdi, type != SCAN_OUT ?
+ &tdo : NULL, xvc_type);
if (err != ERROR_OK)
goto out_err;
left -= write;
@@ -285,7 +413,7 @@ static int xlnx_pcie_xvc_execute_scan(struct jtag_command *cmd)
free(buf);
if (tap_get_state() != tap_get_end_state())
- err = xlnx_pcie_xvc_execute_statemove(1);
+ err = xlnx_xvc_execute_statemove(1, xvc_type);
return err;
@@ -294,19 +422,14 @@ static int xlnx_pcie_xvc_execute_scan(struct jtag_command *cmd)
return err;
}
-static void xlnx_pcie_xvc_execute_reset(struct jtag_command *cmd)
-{
- LOG_DEBUG("reset trst: %i srst: %i", cmd->cmd.reset->trst,
- cmd->cmd.reset->srst);
-}
-
-static void xlnx_pcie_xvc_execute_sleep(struct jtag_command *cmd)
+static void xlnx_xvc_execute_sleep(struct jtag_command *cmd)
{
- LOG_DEBUG("sleep %" PRIu32 "", cmd->cmd.sleep->us);
+ LOG_DEBUG("sleep %" PRIu32, cmd->cmd.sleep->us);
usleep(cmd->cmd.sleep->us);
}
-static int xlnx_pcie_xvc_execute_tms(struct jtag_command *cmd)
+static int xlnx_xvc_execute_tms(struct jtag_command *cmd,
+ enum xlnx_xvc_type_t xvc_type)
{
const size_t num_bits = cmd->cmd.tms->num_bits;
const uint8_t *bits = cmd->cmd.tms->bits;
@@ -320,7 +443,7 @@ static int xlnx_pcie_xvc_execute_tms(struct jtag_command *cmd)
while (left) {
write = MIN(XLNX_XVC_MAX_BITS, left);
tms = buf_get_u32(bits, 0, write);
- err = xlnx_pcie_xvc_transact(write, tms, 0, NULL);
+ err = xlnx_xvc_transact(write, tms, 0, NULL, xvc_type);
if (err != ERROR_OK)
return err;
left -= write;
@@ -330,29 +453,30 @@ static int xlnx_pcie_xvc_execute_tms(struct jtag_command *cmd)
return ERROR_OK;
}
-static int xlnx_pcie_xvc_execute_command(struct jtag_command *cmd)
+static int xlnx_xvc_execute_command(struct jtag_command *cmd,
+ enum xlnx_xvc_type_t xvc_type)
{
LOG_DEBUG("%s: cmd->type: %u", __func__, cmd->type);
switch (cmd->type) {
case JTAG_STABLECLOCKS:
- return xlnx_pcie_xvc_execute_stableclocks(cmd);
+ return xlnx_xvc_execute_stableclocks(cmd, xvc_type);
case JTAG_RUNTEST:
- return xlnx_pcie_xvc_execute_runtest(cmd);
+ return xlnx_xvc_execute_runtest(cmd, xvc_type);
case JTAG_TLR_RESET:
tap_set_end_state(cmd->cmd.statemove->end_state);
- return xlnx_pcie_xvc_execute_statemove(0);
+ return xlnx_xvc_execute_statemove(0, xvc_type);
case JTAG_PATHMOVE:
- return xlnx_pcie_xvc_execute_pathmove(cmd);
+ return xlnx_xvc_execute_pathmove(cmd, xvc_type);
case JTAG_SCAN:
- return xlnx_pcie_xvc_execute_scan(cmd);
+ return xlnx_xvc_execute_scan(cmd, xvc_type);
case JTAG_RESET:
- xlnx_pcie_xvc_execute_reset(cmd);
+ LOG_INFO("WARN: XVC driver has no reset.");
break;
case JTAG_SLEEP:
- xlnx_pcie_xvc_execute_sleep(cmd);
+ xlnx_xvc_execute_sleep(cmd);
break;
case JTAG_TMS:
- return xlnx_pcie_xvc_execute_tms(cmd);
+ return xlnx_xvc_execute_tms(cmd, xvc_type);
default:
LOG_ERROR("BUG: Unknown JTAG command type encountered.");
return ERROR_JTAG_QUEUE_FAILED;
@@ -361,13 +485,14 @@ static int xlnx_pcie_xvc_execute_command(struct jtag_command *cmd)
return ERROR_OK;
}
-static int xlnx_pcie_xvc_execute_queue(struct jtag_command *cmd_queue)
+static int xlnx_xvc_execute_queue(struct jtag_command *cmd_queue,
+ enum xlnx_xvc_type_t xvc_type)
{
struct jtag_command *cmd = cmd_queue;
int ret;
while (cmd) {
- ret = xlnx_pcie_xvc_execute_command(cmd);
+ ret = xlnx_xvc_execute_command(cmd, xvc_type);
if (ret != ERROR_OK)
return ret;
@@ -378,6 +503,15 @@ static int xlnx_pcie_xvc_execute_queue(struct jtag_command *cmd_queue)
return ERROR_OK;
}
+static int xlnx_pcie_xvc_execute_queue(struct jtag_command *cmd_queue)
+{
+ return xlnx_xvc_execute_queue(cmd_queue, PCIE);
+}
+
+static int xlnx_axi_xvc_execute_queue(struct jtag_command *cmd_queue)
+{
+ return xlnx_xvc_execute_queue(cmd_queue, AXI);
+}
static int xlnx_pcie_xvc_init(void)
{
@@ -399,8 +533,8 @@ static int xlnx_pcie_xvc_init(void)
* vendor specific header */
xlnx_pcie_xvc->offset = PCIE_EXT_CAP_LST;
while (xlnx_pcie_xvc->offset <= PCI_CFG_SPACE_EXP_SIZE - sizeof(cap) &&
- xlnx_pcie_xvc->offset >= PCIE_EXT_CAP_LST) {
- err = xlnx_pcie_xvc_read_reg(XLNX_XVC_EXT_CAP, &cap);
+ xlnx_pcie_xvc->offset >= PCIE_EXT_CAP_LST) {
+ err = xlnx_pcie_xvc_read_reg(XLNX_PCIE_XVC_EXT_CAP, &cap);
if (err != ERROR_OK)
return err;
LOG_DEBUG("Checking capability at 0x%x; id=0x%04" PRIx32 " version=0x%" PRIx32 " next=0x%" PRIx32,
@@ -409,7 +543,7 @@ static int xlnx_pcie_xvc_init(void)
PCI_EXT_CAP_VER(cap),
PCI_EXT_CAP_NEXT(cap));
if (PCI_EXT_CAP_ID(cap) == PCI_EXT_CAP_ID_VNDR) {
- err = xlnx_pcie_xvc_read_reg(XLNX_XVC_VSEC_HDR, &vh);
+ err = xlnx_pcie_xvc_read_reg(XLNX_PCIE_XVC_VSEC_HDR, &vh);
if (err != ERROR_OK)
return err;
LOG_DEBUG("Checking possible match at 0x%x; id: 0x%" PRIx32 "; rev: 0x%" PRIx32 "; length: 0x%" PRIx32,
@@ -417,14 +551,14 @@ static int xlnx_pcie_xvc_init(void)
PCI_VNDR_HEADER_ID(vh),
PCI_VNDR_HEADER_REV(vh),
PCI_VNDR_HEADER_LEN(vh));
- if ((PCI_VNDR_HEADER_ID(vh) == XLNX_XVC_VSEC_ID) &&
- (PCI_VNDR_HEADER_LEN(vh) == XLNX_XVC_CAP_SIZE))
+ if ((PCI_VNDR_HEADER_ID(vh) == XLNX_PCIE_XVC_VSEC_ID) &&
+ (PCI_VNDR_HEADER_LEN(vh) == XLNX_PCIE_XVC_CAP_SIZE))
break;
}
xlnx_pcie_xvc->offset = PCI_EXT_CAP_NEXT(cap);
}
- if ((xlnx_pcie_xvc->offset > PCI_CFG_SPACE_EXP_SIZE - XLNX_XVC_CAP_SIZE) ||
- xlnx_pcie_xvc->offset < PCIE_EXT_CAP_LST) {
+ if ((xlnx_pcie_xvc->offset > PCI_CFG_SPACE_EXP_SIZE - XLNX_PCIE_XVC_CAP_SIZE) ||
+ xlnx_pcie_xvc->offset < PCIE_EXT_CAP_LST) {
close(xlnx_pcie_xvc->fd);
return ERROR_JTAG_INIT_FAILED;
}
@@ -434,6 +568,44 @@ static int xlnx_pcie_xvc_init(void)
return ERROR_OK;
}
+static int xlnx_axi_xvc_init(void)
+{
+ uint64_t baseaddr;
+
+ if (xlnx_axi_xvc->device_addr) {
+ baseaddr = strtoul(xlnx_axi_xvc->device_addr, NULL, 0);
+ } else {
+ LOG_ERROR("Please set device addr.");
+ return ERROR_JTAG_INIT_FAILED;
+ }
+
+ if (xlnx_axi_xvc->device_file) {
+ LOG_INFO("Opening %s for AXI communication", xlnx_axi_xvc->device_file);
+ xlnx_axi_xvc->fd = open(xlnx_axi_xvc->device_file, O_RDWR | O_SYNC);
+ } else {
+ LOG_INFO("Opening /dev/mem for AXI communication");
+ xlnx_axi_xvc->fd = open("/dev/mem", O_RDWR | O_SYNC);
+ }
+
+ if (xlnx_axi_xvc->fd < 0) {
+ LOG_ERROR("Failed to open device file, check permissions.");
+ return ERROR_JTAG_INIT_FAILED;
+ }
+
+ xlnx_axi_xvc->base = mmap(0, XLNX_AXI_XVC_MAX_REG, PROT_READ | PROT_WRITE,
+ MAP_SHARED, xlnx_axi_xvc->fd, baseaddr);
+ if (xlnx_axi_xvc->base == MAP_FAILED) {
+ LOG_ERROR("mmap() failed, check permissions.");
+ close(xlnx_axi_xvc->fd);
+ return ERROR_JTAG_INIT_FAILED;
+ }
+
+ LOG_INFO("Mapped Xilinx XVC/AXI vaddr %p paddr 0x%" PRIx64,
+ xlnx_axi_xvc->base, baseaddr);
+
+ return ERROR_OK;
+}
+
static int xlnx_pcie_xvc_quit(void)
{
int err;
@@ -445,21 +617,55 @@ static int xlnx_pcie_xvc_quit(void)
return ERROR_OK;
}
+static int xlnx_axi_xvc_quit(void)
+{
+ int err;
+
+ munmap(xlnx_axi_xvc->base, XLNX_AXI_XVC_MAX_REG);
+ free(xlnx_pcie_xvc->device);
+ free(xlnx_axi_xvc->device_file);
+ free(xlnx_axi_xvc->device_addr);
+
+ err = close(xlnx_axi_xvc->fd);
+ if (err)
+ return err;
+
+ return ERROR_OK;
+}
+
COMMAND_HANDLER(xlnx_pcie_xvc_handle_config_command)
{
- if (CMD_ARGC < 1)
+ if (CMD_ARGC != 1)
return ERROR_COMMAND_SYNTAX_ERROR;
- /* we can't really free this in a safe manner, so at least
- * limit the memory we're leaking by freeing the old one first
- * before allocating a new one ...
- */
free(xlnx_pcie_xvc->device);
xlnx_pcie_xvc->device = strdup(CMD_ARGV[0]);
return ERROR_OK;
}
+COMMAND_HANDLER(xlnx_axi_xvc_handle_dev_addr_command)
+{
+ if (CMD_ARGC != 1)
+ return ERROR_COMMAND_SYNTAX_ERROR;
+
+ free(xlnx_axi_xvc->device_addr);
+
+ xlnx_axi_xvc->device_addr = strdup(CMD_ARGV[0]);
+ return ERROR_OK;
+}
+
+COMMAND_HANDLER(xlnx_axi_xvc_handle_dev_file_command)
+{
+ if (CMD_ARGC != 1)
+ return ERROR_COMMAND_SYNTAX_ERROR;
+
+ free(xlnx_axi_xvc->device_file);
+
+ xlnx_axi_xvc->device_file = strdup(CMD_ARGV[0]);
+ return ERROR_OK;
+}
+
static const struct command_registration xlnx_pcie_xvc_subcommand_handlers[] = {
{
.name = "config",
@@ -482,11 +688,45 @@ static const struct command_registration xlnx_pcie_xvc_command_handlers[] = {
COMMAND_REGISTRATION_DONE
};
+static const struct command_registration xlnx_axi_xvc_subcommand_handlers[] = {
+ {
+ .name = "dev_addr",
+ .handler = xlnx_axi_xvc_handle_dev_addr_command,
+ .mode = COMMAND_CONFIG,
+ .help = "Configure XVC/AXI JTAG device memory address",
+ .usage = "addr",
+ },
+ {
+ .name = "dev_file",
+ .handler = xlnx_axi_xvc_handle_dev_file_command,
+ .mode = COMMAND_CONFIG,
+ .help = "Configure XVC/AXI JTAG device file location",
+ .usage = "addr",
+ },
+ COMMAND_REGISTRATION_DONE
+};
+
+static const struct command_registration xlnx_axi_xvc_command_handlers[] = {
+ {
+ .name = "xlnx_axi_xvc",
+ .mode = COMMAND_ANY,
+ .help = "perform xlnx_axi_xvc management",
+ .chain = xlnx_axi_xvc_subcommand_handlers,
+ .usage = "",
+ },
+ COMMAND_REGISTRATION_DONE
+};
+
static struct jtag_interface xlnx_pcie_xvc_jtag_ops = {
.execute_queue = &xlnx_pcie_xvc_execute_queue,
};
-static int xlnx_pcie_xvc_swd_sequence(const uint8_t *seq, size_t length)
+static struct jtag_interface xlnx_axi_xvc_jtag_ops = {
+ .execute_queue = &xlnx_axi_xvc_execute_queue,
+};
+
+static int xlnx_xvc_swd_sequence(const uint8_t *seq, size_t length,
+ enum xlnx_xvc_type_t xvc_type)
{
size_t left, write;
uint32_t send;
@@ -496,7 +736,7 @@ static int xlnx_pcie_xvc_swd_sequence(const uint8_t *seq, size_t length)
while (left) {
write = MIN(XLNX_XVC_MAX_BITS, left);
send = buf_get_u32(seq, 0, write);
- err = xlnx_pcie_xvc_transact(write, send, 0, NULL);
+ err = xlnx_xvc_transact(write, send, 0, NULL, xvc_type);
if (err != ERROR_OK)
return err;
left -= write;
@@ -506,21 +746,22 @@ static int xlnx_pcie_xvc_swd_sequence(const uint8_t *seq, size_t length)
return ERROR_OK;
}
-static int xlnx_pcie_xvc_swd_switch_seq(enum swd_special_seq seq)
+static int xlnx_xvc_swd_switch_seq(enum swd_special_seq seq,
+ enum xlnx_xvc_type_t xvc_type)
{
switch (seq) {
case LINE_RESET:
LOG_DEBUG("SWD line reset");
- return xlnx_pcie_xvc_swd_sequence(swd_seq_line_reset,
- swd_seq_line_reset_len);
+ return xlnx_xvc_swd_sequence(swd_seq_line_reset,
+ swd_seq_line_reset_len, xvc_type);
case JTAG_TO_SWD:
LOG_DEBUG("JTAG-to-SWD");
- return xlnx_pcie_xvc_swd_sequence(swd_seq_jtag_to_swd,
- swd_seq_jtag_to_swd_len);
+ return xlnx_xvc_swd_sequence(swd_seq_jtag_to_swd,
+ swd_seq_jtag_to_swd_len, xvc_type);
case SWD_TO_JTAG:
LOG_DEBUG("SWD-to-JTAG");
- return xlnx_pcie_xvc_swd_sequence(swd_seq_swd_to_jtag,
- swd_seq_swd_to_jtag_len);
+ return xlnx_xvc_swd_sequence(swd_seq_swd_to_jtag,
+ swd_seq_swd_to_jtag_len, xvc_type);
default:
LOG_ERROR("Sequence %d not supported", seq);
return ERROR_FAIL;
@@ -529,19 +770,31 @@ static int xlnx_pcie_xvc_swd_switch_seq(enum swd_special_seq seq)
return ERROR_OK;
}
+static int xlnx_pcie_xvc_swd_switch_seq(enum swd_special_seq seq)
+{
+ return xlnx_xvc_swd_switch_seq(seq, PCIE);
+}
+
+static int xlnx_axi_xvc_swd_switch_seq(enum swd_special_seq seq)
+{
+ return xlnx_xvc_swd_switch_seq(seq, AXI);
+}
+
static int queued_retval;
-static void xlnx_pcie_xvc_swd_write_reg(uint8_t cmd, uint32_t value,
- uint32_t ap_delay_clk);
+static void xlnx_xvc_swd_write_reg(uint8_t cmd, uint32_t value,
+ uint32_t ap_delay_clk,
+ enum xlnx_xvc_type_t xvc_type);
-static void swd_clear_sticky_errors(void)
+static void swd_clear_sticky_errors(enum xlnx_xvc_type_t xvc_type)
{
- xlnx_pcie_xvc_swd_write_reg(swd_cmd(false, false, DP_ABORT),
- STKCMPCLR | STKERRCLR | WDERRCLR | ORUNERRCLR, 0);
+ xlnx_xvc_swd_write_reg(swd_cmd(false, false, DP_ABORT),
+ STKCMPCLR | STKERRCLR | WDERRCLR | ORUNERRCLR, 0, xvc_type);
}
-static void xlnx_pcie_xvc_swd_read_reg(uint8_t cmd, uint32_t *value,
- uint32_t ap_delay_clk)
+static void xlnx_xvc_swd_read_reg(uint8_t cmd, uint32_t *value,
+ uint32_t ap_delay_clk,
+ enum xlnx_xvc_type_t xvc_type)
{
uint32_t res, ack, rpar;
int err;
@@ -550,23 +803,23 @@ static void xlnx_pcie_xvc_swd_read_reg(uint8_t cmd, uint32_t *value,
cmd |= SWD_CMD_START | SWD_CMD_PARK;
/* cmd + ack */
- err = xlnx_pcie_xvc_transact(12, cmd, 0, &res);
+ err = xlnx_xvc_transact(12, cmd, 0, &res, xvc_type);
if (err != ERROR_OK)
goto err_out;
ack = MASK_ACK(res);
/* read data */
- err = xlnx_pcie_xvc_transact(32, 0, 0, &res);
+ err = xlnx_xvc_transact(32, 0, 0, &res, xvc_type);
if (err != ERROR_OK)
goto err_out;
/* parity + trn */
- err = xlnx_pcie_xvc_transact(2, 0, 0, &rpar);
+ err = xlnx_xvc_transact(2, 0, 0, &rpar, xvc_type);
if (err != ERROR_OK)
goto err_out;
- LOG_DEBUG("%s %s %s reg %X = %08"PRIx32,
+ LOG_DEBUG("%s %s %s reg %X = %08" PRIx32,
ack == SWD_ACK_OK ? "OK" : ack == SWD_ACK_WAIT ?
"WAIT" : ack == SWD_ACK_FAULT ? "FAULT" : "JUNK",
cmd & SWD_CMD_APNDP ? "AP" : "DP",
@@ -583,19 +836,19 @@ static void xlnx_pcie_xvc_swd_read_reg(uint8_t cmd, uint32_t *value,
if (value)
*value = res;
if (cmd & SWD_CMD_APNDP)
- err = xlnx_pcie_xvc_transact(ap_delay_clk, 0, 0, NULL);
+ err = xlnx_xvc_transact(ap_delay_clk, 0, 0, NULL, xvc_type);
queued_retval = err;
return;
case SWD_ACK_WAIT:
LOG_DEBUG_IO("SWD_ACK_WAIT");
- swd_clear_sticky_errors();
+ swd_clear_sticky_errors(xvc_type);
return;
case SWD_ACK_FAULT:
LOG_DEBUG_IO("SWD_ACK_FAULT");
queued_retval = ack;
return;
default:
- LOG_DEBUG_IO("No valid acknowledge: ack=%02"PRIx32, ack);
+ LOG_DEBUG_IO("No valid acknowledge: ack=%02" PRIx32, ack);
queued_retval = ack;
return;
}
@@ -603,8 +856,21 @@ static void xlnx_pcie_xvc_swd_read_reg(uint8_t cmd, uint32_t *value,
queued_retval = err;
}
-static void xlnx_pcie_xvc_swd_write_reg(uint8_t cmd, uint32_t value,
+static void xlnx_pcie_xvc_swd_read_reg(uint8_t cmd, uint32_t *value,
uint32_t ap_delay_clk)
+{
+ xlnx_xvc_swd_read_reg(cmd, value, ap_delay_clk, PCIE);
+}
+
+static void xlnx_axi_xvc_swd_read_reg(uint8_t cmd, uint32_t *value,
+ uint32_t ap_delay_clk)
+{
+ xlnx_xvc_swd_read_reg(cmd, value, ap_delay_clk, AXI);
+}
+
+static void xlnx_xvc_swd_write_reg(uint8_t cmd, uint32_t value,
+ uint32_t ap_delay_clk,
+ enum xlnx_xvc_type_t xvc_type)
{
uint32_t res, ack;
int err;
@@ -613,23 +879,23 @@ static void xlnx_pcie_xvc_swd_write_reg(uint8_t cmd, uint32_t value,
cmd |= SWD_CMD_START | SWD_CMD_PARK;
/* cmd + trn + ack */
- err = xlnx_pcie_xvc_transact(13, cmd, 0, &res);
+ err = xlnx_xvc_transact(13, cmd, 0, &res, xvc_type);
if (err != ERROR_OK)
goto err_out;
ack = MASK_ACK(res);
/* write data */
- err = xlnx_pcie_xvc_transact(32, value, 0, NULL);
+ err = xlnx_xvc_transact(32, value, 0, NULL, xvc_type);
if (err != ERROR_OK)
goto err_out;
/* parity + trn */
- err = xlnx_pcie_xvc_transact(2, parity_u32(value), 0, NULL);
+ err = xlnx_xvc_transact(2, parity_u32(value), 0, NULL, xvc_type);
if (err != ERROR_OK)
goto err_out;
- LOG_DEBUG("%s %s %s reg %X = %08"PRIx32,
+ LOG_DEBUG("%s %s %s reg %X = %08" PRIx32,
ack == SWD_ACK_OK ? "OK" : ack == SWD_ACK_WAIT ?
"WAIT" : ack == SWD_ACK_FAULT ? "FAULT" : "JUNK",
cmd & SWD_CMD_APNDP ? "AP" : "DP",
@@ -640,19 +906,19 @@ static void xlnx_pcie_xvc_swd_write_reg(uint8_t cmd, uint32_t value,
switch (ack) {
case SWD_ACK_OK:
if (cmd & SWD_CMD_APNDP)
- err = xlnx_pcie_xvc_transact(ap_delay_clk, 0, 0, NULL);
+ err = xlnx_xvc_transact(ap_delay_clk, 0, 0, NULL, xvc_type);
queued_retval = err;
return;
case SWD_ACK_WAIT:
LOG_DEBUG_IO("SWD_ACK_WAIT");
- swd_clear_sticky_errors();
+ swd_clear_sticky_errors(xvc_type);
return;
case SWD_ACK_FAULT:
LOG_DEBUG_IO("SWD_ACK_FAULT");
queued_retval = ack;
return;
default:
- LOG_DEBUG_IO("No valid acknowledge: ack=%02"PRIx32, ack);
+ LOG_DEBUG_IO("No valid acknowledge: ack=%02" PRIx32, ack);
queued_retval = ack;
return;
}
@@ -661,12 +927,24 @@ static void xlnx_pcie_xvc_swd_write_reg(uint8_t cmd, uint32_t value,
queued_retval = err;
}
-static int xlnx_pcie_xvc_swd_run_queue(void)
+static void xlnx_pcie_xvc_swd_write_reg(uint8_t cmd, uint32_t value,
+ uint32_t ap_delay_clk)
+{
+ xlnx_xvc_swd_write_reg(cmd, value, ap_delay_clk, PCIE);
+}
+
+static void xlnx_axi_xvc_swd_write_reg(uint8_t cmd, uint32_t value,
+ uint32_t ap_delay_clk)
+{
+ xlnx_xvc_swd_write_reg(cmd, value, ap_delay_clk, AXI);
+}
+
+static int xlnx_xvc_swd_run_queue(enum xlnx_xvc_type_t xvc_type)
{
int err;
/* we want at least 8 idle cycles between each transaction */
- err = xlnx_pcie_xvc_transact(8, 0, 0, NULL);
+ err = xlnx_xvc_transact(8, 0, 0, NULL, xvc_type);
if (err != ERROR_OK)
return err;
@@ -677,19 +955,37 @@ static int xlnx_pcie_xvc_swd_run_queue(void)
return err;
}
-static int xlnx_pcie_xvc_swd_init(void)
+static int xlnx_pcie_xvc_swd_run_queue(void)
+{
+ return xlnx_xvc_swd_run_queue(PCIE);
+}
+
+static int xlnx_axi_xvc_swd_run_queue(void)
+{
+ return xlnx_xvc_swd_run_queue(AXI);
+}
+
+static int xlnx_xvc_swd_init(void)
{
return ERROR_OK;
}
static const struct swd_driver xlnx_pcie_xvc_swd_ops = {
- .init = xlnx_pcie_xvc_swd_init,
+ .init = xlnx_xvc_swd_init,
.switch_seq = xlnx_pcie_xvc_swd_switch_seq,
.read_reg = xlnx_pcie_xvc_swd_read_reg,
.write_reg = xlnx_pcie_xvc_swd_write_reg,
.run = xlnx_pcie_xvc_swd_run_queue,
};
+static const struct swd_driver xlnx_axi_xvc_swd_ops = {
+ .init = xlnx_xvc_swd_init,
+ .switch_seq = xlnx_axi_xvc_swd_switch_seq,
+ .read_reg = xlnx_axi_xvc_swd_read_reg,
+ .write_reg = xlnx_axi_xvc_swd_write_reg,
+ .run = xlnx_axi_xvc_swd_run_queue,
+};
+
struct adapter_driver xlnx_pcie_xvc_adapter_driver = {
.name = "xlnx_pcie_xvc",
.transport_ids = TRANSPORT_JTAG | TRANSPORT_SWD,
@@ -702,3 +998,16 @@ struct adapter_driver xlnx_pcie_xvc_adapter_driver = {
.jtag_ops = &xlnx_pcie_xvc_jtag_ops,
.swd_ops = &xlnx_pcie_xvc_swd_ops,
};
+
+struct adapter_driver xlnx_axi_xvc_adapter_driver = {
+ .name = "xlnx_axi_xvc",
+ .transport_ids = TRANSPORT_JTAG | TRANSPORT_SWD,
+ .transport_preferred_id = TRANSPORT_JTAG,
+ .commands = xlnx_axi_xvc_command_handlers,
+
+ .init = &xlnx_axi_xvc_init,
+ .quit = &xlnx_axi_xvc_quit,
+
+ .jtag_ops = &xlnx_axi_xvc_jtag_ops,
+ .swd_ops = &xlnx_axi_xvc_swd_ops,
+};
diff --git a/src/jtag/interface.c b/src/jtag/interface.c
index 92c88ca934..23b5bcf4f1 100644
--- a/src/jtag/interface.c
+++ b/src/jtag/interface.c
@@ -67,28 +67,28 @@ int tap_move_ndx(enum tap_state astate)
int ndx;
switch (astate) {
- case TAP_RESET:
- ndx = 0;
- break;
- case TAP_IDLE:
- ndx = 1;
- break;
- case TAP_DRSHIFT:
- ndx = 2;
- break;
- case TAP_DRPAUSE:
- ndx = 3;
- break;
- case TAP_IRSHIFT:
- ndx = 4;
- break;
- case TAP_IRPAUSE:
- ndx = 5;
- break;
- default:
- LOG_ERROR("FATAL: unstable state \"%s\" in tap_move_ndx()",
- tap_state_name(astate));
- exit(1);
+ case TAP_RESET:
+ ndx = 0;
+ break;
+ case TAP_IDLE:
+ ndx = 1;
+ break;
+ case TAP_DRSHIFT:
+ ndx = 2;
+ break;
+ case TAP_DRPAUSE:
+ ndx = 3;
+ break;
+ case TAP_IRSHIFT:
+ ndx = 4;
+ break;
+ case TAP_IRPAUSE:
+ ndx = 5;
+ break;
+ default:
+ LOG_ERROR("FATAL: unstable state \"%s\" in %s()",
+ tap_state_name(astate), __func__);
+ exit(1);
}
return ndx;
@@ -205,16 +205,16 @@ bool tap_is_state_stable(enum tap_state astate)
* (not value dependent like an array), and can also check bounds.
*/
switch (astate) {
- case TAP_RESET:
- case TAP_IDLE:
- case TAP_DRSHIFT:
- case TAP_DRPAUSE:
- case TAP_IRSHIFT:
- case TAP_IRPAUSE:
- is_stable = true;
- break;
- default:
- is_stable = false;
+ case TAP_RESET:
+ case TAP_IDLE:
+ case TAP_DRSHIFT:
+ case TAP_DRPAUSE:
+ case TAP_IRSHIFT:
+ case TAP_IRPAUSE:
+ is_stable = true;
+ break;
+ default:
+ is_stable = false;
}
return is_stable;
@@ -230,83 +230,83 @@ enum tap_state tap_state_transition(enum tap_state cur_state, bool tms)
if (tms) {
switch (cur_state) {
- case TAP_RESET:
- new_state = cur_state;
- break;
- case TAP_IDLE:
- case TAP_DRUPDATE:
- case TAP_IRUPDATE:
- new_state = TAP_DRSELECT;
- break;
- case TAP_DRSELECT:
- new_state = TAP_IRSELECT;
- break;
- case TAP_DRCAPTURE:
- case TAP_DRSHIFT:
- new_state = TAP_DREXIT1;
- break;
- case TAP_DREXIT1:
- case TAP_DREXIT2:
- new_state = TAP_DRUPDATE;
- break;
- case TAP_DRPAUSE:
- new_state = TAP_DREXIT2;
- break;
- case TAP_IRSELECT:
- new_state = TAP_RESET;
- break;
- case TAP_IRCAPTURE:
- case TAP_IRSHIFT:
- new_state = TAP_IREXIT1;
- break;
- case TAP_IREXIT1:
- case TAP_IREXIT2:
- new_state = TAP_IRUPDATE;
- break;
- case TAP_IRPAUSE:
- new_state = TAP_IREXIT2;
- break;
- default:
- LOG_ERROR("fatal: invalid argument cur_state=%d", cur_state);
- exit(1);
- break;
+ case TAP_RESET:
+ new_state = cur_state;
+ break;
+ case TAP_IDLE:
+ case TAP_DRUPDATE:
+ case TAP_IRUPDATE:
+ new_state = TAP_DRSELECT;
+ break;
+ case TAP_DRSELECT:
+ new_state = TAP_IRSELECT;
+ break;
+ case TAP_DRCAPTURE:
+ case TAP_DRSHIFT:
+ new_state = TAP_DREXIT1;
+ break;
+ case TAP_DREXIT1:
+ case TAP_DREXIT2:
+ new_state = TAP_DRUPDATE;
+ break;
+ case TAP_DRPAUSE:
+ new_state = TAP_DREXIT2;
+ break;
+ case TAP_IRSELECT:
+ new_state = TAP_RESET;
+ break;
+ case TAP_IRCAPTURE:
+ case TAP_IRSHIFT:
+ new_state = TAP_IREXIT1;
+ break;
+ case TAP_IREXIT1:
+ case TAP_IREXIT2:
+ new_state = TAP_IRUPDATE;
+ break;
+ case TAP_IRPAUSE:
+ new_state = TAP_IREXIT2;
+ break;
+ default:
+ LOG_ERROR("fatal: invalid argument cur_state=%d", cur_state);
+ exit(1);
+ break;
}
} else {
switch (cur_state) {
- case TAP_RESET:
- case TAP_IDLE:
- case TAP_DRUPDATE:
- case TAP_IRUPDATE:
- new_state = TAP_IDLE;
- break;
- case TAP_DRSELECT:
- new_state = TAP_DRCAPTURE;
- break;
- case TAP_DRCAPTURE:
- case TAP_DRSHIFT:
- case TAP_DREXIT2:
- new_state = TAP_DRSHIFT;
- break;
- case TAP_DREXIT1:
- case TAP_DRPAUSE:
- new_state = TAP_DRPAUSE;
- break;
- case TAP_IRSELECT:
- new_state = TAP_IRCAPTURE;
- break;
- case TAP_IRCAPTURE:
- case TAP_IRSHIFT:
- case TAP_IREXIT2:
- new_state = TAP_IRSHIFT;
- break;
- case TAP_IREXIT1:
- case TAP_IRPAUSE:
- new_state = TAP_IRPAUSE;
- break;
- default:
- LOG_ERROR("fatal: invalid argument cur_state=%d", cur_state);
- exit(1);
- break;
+ case TAP_RESET:
+ case TAP_IDLE:
+ case TAP_DRUPDATE:
+ case TAP_IRUPDATE:
+ new_state = TAP_IDLE;
+ break;
+ case TAP_DRSELECT:
+ new_state = TAP_DRCAPTURE;
+ break;
+ case TAP_DRCAPTURE:
+ case TAP_DRSHIFT:
+ case TAP_DREXIT2:
+ new_state = TAP_DRSHIFT;
+ break;
+ case TAP_DREXIT1:
+ case TAP_DRPAUSE:
+ new_state = TAP_DRPAUSE;
+ break;
+ case TAP_IRSELECT:
+ new_state = TAP_IRCAPTURE;
+ break;
+ case TAP_IRCAPTURE:
+ case TAP_IRSHIFT:
+ case TAP_IREXIT2:
+ new_state = TAP_IRSHIFT;
+ break;
+ case TAP_IREXIT1:
+ case TAP_IRPAUSE:
+ new_state = TAP_IRPAUSE;
+ break;
+ default:
+ LOG_ERROR("fatal: invalid argument cur_state=%d", cur_state);
+ exit(1);
+ break;
}
}
diff --git a/src/jtag/interface.h b/src/jtag/interface.h
index 475dbed36e..51cbf9ac0d 100644
--- a/src/jtag/interface.h
+++ b/src/jtag/interface.h
@@ -371,6 +371,7 @@ int adapter_config_trace(bool enabled, enum tpiu_pin_protocol pin_protocol,
unsigned int traceclkin_freq, uint16_t *prescaler);
int adapter_poll_trace(uint8_t *buf, size_t *size);
+// Keep in alphabetic order this list of drivers
extern struct adapter_driver am335xgpio_adapter_driver;
extern struct adapter_driver amt_jtagaccel_adapter_driver;
extern struct adapter_driver angie_adapter_driver;
@@ -378,6 +379,7 @@ extern struct adapter_driver armjtagew_adapter_driver;
extern struct adapter_driver at91rm9200_adapter_driver;
extern struct adapter_driver bcm2835gpio_adapter_driver;
extern struct adapter_driver buspirate_adapter_driver;
+extern struct adapter_driver ch347_adapter_driver;
extern struct adapter_driver cmsis_dap_adapter_driver;
extern struct adapter_driver dmem_dap_adapter_driver;
extern struct adapter_driver dummy_adapter_driver;
@@ -410,6 +412,7 @@ extern struct adapter_driver usbprog_adapter_driver;
extern struct adapter_driver vdebug_adapter_driver;
extern struct adapter_driver vsllink_adapter_driver;
extern struct adapter_driver xds110_adapter_driver;
+extern struct adapter_driver xlnx_axi_xvc_adapter_driver;
extern struct adapter_driver xlnx_pcie_xvc_adapter_driver;
#endif /* OPENOCD_JTAG_INTERFACE_H */
diff --git a/src/jtag/interfaces.c b/src/jtag/interfaces.c
index e49bd9e0f3..e29937b587 100644
--- a/src/jtag/interfaces.c
+++ b/src/jtag/interfaces.c
@@ -36,125 +36,132 @@
* drivers that were enabled by the @c configure script.
*/
struct adapter_driver *adapter_drivers[] = {
-#if BUILD_PARPORT == 1
- &parport_adapter_driver,
+ // Keep in alphabetic order this list of drivers
+
+#if BUILD_AM335XGPIO == 1
+ &am335xgpio_adapter_driver,
#endif
-#if BUILD_DUMMY == 1
- &dummy_adapter_driver,
+#if BUILD_AMTJTAGACCEL == 1
+ &amt_jtagaccel_adapter_driver,
#endif
-#if BUILD_FTDI == 1
- &ftdi_adapter_driver,
+#if BUILD_ANGIE == 1
+ &angie_adapter_driver,
#endif
-#if BUILD_USB_BLASTER || BUILD_USB_BLASTER_2 == 1
- &usb_blaster_adapter_driver,
+#if BUILD_ARMJTAGEW == 1
+ &armjtagew_adapter_driver,
#endif
-#if BUILD_ESP_USB_JTAG == 1
- &esp_usb_adapter_driver,
+#if BUILD_AT91RM9200 == 1
+ &at91rm9200_adapter_driver,
#endif
-#if BUILD_JTAG_VPI == 1
- &jtag_vpi_adapter_driver,
+#if BUILD_BCM2835GPIO == 1
+ &bcm2835gpio_adapter_driver,
#endif
-#if BUILD_VDEBUG == 1
- &vdebug_adapter_driver,
+#if BUILD_BUS_PIRATE == 1
+ &buspirate_adapter_driver,
#endif
-#if BUILD_JTAG_DPI == 1
- &jtag_dpi_adapter_driver,
+#if BUILD_CH347 == 1
+ &ch347_adapter_driver,
#endif
-#if BUILD_FT232R == 1
- &ft232r_adapter_driver,
+#if BUILD_CMSIS_DAP_USB == 1 || BUILD_CMSIS_DAP_HID == 1
+ &cmsis_dap_adapter_driver,
#endif
-#if BUILD_AMTJTAGACCEL == 1
- &amt_jtagaccel_adapter_driver,
+#if BUILD_DMEM == 1
+ &dmem_dap_adapter_driver,
+#endif
+#if BUILD_DUMMY == 1
+ &dummy_adapter_driver,
#endif
#if BUILD_EP93XX == 1
&ep93xx_adapter_driver,
#endif
-#if BUILD_AT91RM9200 == 1
- &at91rm9200_adapter_driver,
+#if BUILD_ESP_USB_JTAG == 1
+ &esp_usb_adapter_driver,
+#endif
+#if BUILD_FT232R == 1
+ &ft232r_adapter_driver,
+#endif
+#if BUILD_FTDI == 1
+ &ftdi_adapter_driver,
#endif
#if BUILD_GW16012 == 1
&gw16012_adapter_driver,
#endif
-#if BUILD_PRESTO
- &presto_adapter_driver,
-#endif
-#if BUILD_USBPROG == 1
- &usbprog_adapter_driver,
+#if BUILD_HLADAPTER == 1
+ &hl_adapter_driver,
#endif
-#if BUILD_OPENJTAG == 1
- &openjtag_adapter_driver,
+#if BUILD_IMX_GPIO == 1
+ &imx_gpio_adapter_driver,
#endif
#if BUILD_JLINK == 1
&jlink_adapter_driver,
#endif
-#if BUILD_VSLLINK == 1
- &vsllink_adapter_driver,
-#endif
-#if BUILD_RLINK == 1
- &rlink_adapter_driver,
+#if BUILD_JTAG_DPI == 1
+ &jtag_dpi_adapter_driver,
#endif
-#if BUILD_ULINK == 1
- &ulink_adapter_driver,
+#if BUILD_JTAG_VPI == 1
+ &jtag_vpi_adapter_driver,
#endif
-#if BUILD_ANGIE == 1
- &angie_adapter_driver,
+#if BUILD_KITPROG == 1
+ &kitprog_adapter_driver,
#endif
-#if BUILD_ARMJTAGEW == 1
- &armjtagew_adapter_driver,
+#if BUILD_LINUXGPIOD == 1
+ &linuxgpiod_adapter_driver,
#endif
-#if BUILD_BUS_PIRATE == 1
- &buspirate_adapter_driver,
+#if BUILD_LINUXSPIDEV == 1
+ &linuxspidev_adapter_driver,
#endif
-#if BUILD_REMOTE_BITBANG == 1
- &remote_bitbang_adapter_driver,
+#if BUILD_OPENDOUS == 1
+ &opendous_adapter_driver,
#endif
-#if BUILD_HLADAPTER == 1
- &hl_adapter_driver,
+#if BUILD_OPENJTAG == 1
+ &openjtag_adapter_driver,
#endif
#if BUILD_OSBDM == 1
&osbdm_adapter_driver,
#endif
-#if BUILD_OPENDOUS == 1
- &opendous_adapter_driver,
+#if BUILD_PARPORT == 1
+ &parport_adapter_driver,
#endif
-#if BUILD_SYSFSGPIO == 1
- &sysfsgpio_adapter_driver,
+#if BUILD_PRESTO == 1
+ &presto_adapter_driver,
#endif
-#if BUILD_LINUXGPIOD == 1
- &linuxgpiod_adapter_driver,
+#if BUILD_REMOTE_BITBANG == 1
+ &remote_bitbang_adapter_driver,
#endif
-#if BUILD_LINUXSPIDEV == 1
- &linuxspidev_adapter_driver,
+#if BUILD_RLINK == 1
+ &rlink_adapter_driver,
#endif
-#if BUILD_XLNX_PCIE_XVC == 1
- &xlnx_pcie_xvc_adapter_driver,
+#if BUILD_RSHIM == 1
+ &rshim_dap_adapter_driver,
#endif
-#if BUILD_BCM2835GPIO == 1
- &bcm2835gpio_adapter_driver,
+#if BUILD_HLADAPTER_STLINK == 1
+ &stlink_dap_adapter_driver,
#endif
-#if BUILD_CMSIS_DAP_USB == 1 || BUILD_CMSIS_DAP_HID == 1
- &cmsis_dap_adapter_driver,
+#if BUILD_SYSFSGPIO == 1
+ &sysfsgpio_adapter_driver,
#endif
-#if BUILD_KITPROG == 1
- &kitprog_adapter_driver,
+#if BUILD_ULINK == 1
+ &ulink_adapter_driver,
#endif
-#if BUILD_IMX_GPIO == 1
- &imx_gpio_adapter_driver,
+#if BUILD_USB_BLASTER == 1 || BUILD_USB_BLASTER_2 == 1
+ &usb_blaster_adapter_driver,
#endif
-#if BUILD_XDS110 == 1
- &xds110_adapter_driver,
+#if BUILD_USBPROG == 1
+ &usbprog_adapter_driver,
#endif
-#if BUILD_HLADAPTER_STLINK == 1
- &stlink_dap_adapter_driver,
+#if BUILD_VDEBUG == 1
+ &vdebug_adapter_driver,
#endif
-#if BUILD_RSHIM == 1
- &rshim_dap_adapter_driver,
+#if BUILD_VSLLINK == 1
+ &vsllink_adapter_driver,
#endif
-#if BUILD_DMEM == 1
- &dmem_dap_adapter_driver,
+#if BUILD_XDS110 == 1
+ &xds110_adapter_driver,
#endif
-#if BUILD_AM335XGPIO == 1
- &am335xgpio_adapter_driver,
+#if BUILD_XLNX_XVC == 1
+ &xlnx_pcie_xvc_adapter_driver,
+ &xlnx_axi_xvc_adapter_driver,
#endif
+
NULL,
- };
+};
diff --git a/src/jtag/startup.tcl b/src/jtag/startup.tcl
index 2d8ebf0410..5c466c628a 100644
--- a/src/jtag/startup.tcl
+++ b/src/jtag/startup.tcl
@@ -359,6 +359,27 @@ proc parport_cable args {
eval parport cable $args
}
+lappend _telnet_autocomplete_skip parport_select_cable
+proc parport_select_cable {cable} {
+ echo "DEPRECATED! Do not use 'parport cable' but use a cable configuration file in interface/parport"
+
+ switch $cable {
+ "wiggler" { source [find interface/parport/wiggler.cfg] }
+ "wiggler2" { source [find interface/parport/wiggler2.cfg] }
+ "wiggler_ntrst_inverted" { source [find interface/parport/wiggler-ntrst-inverted.cfg] }
+ "old_amt_wiggler" { source [find interface/parport/amt-wiggler-old.cfg ] }
+ "arm-jtag" { source [find interface/parport/arm-jtag.cfg] }
+ "chameleon" { source [find interface/parport/chameleon.cfg] }
+ "dlc5" { source [find interface/parport/dlc5.cfg] }
+ "triton" { source [find interface/parport/triton.cfg] }
+ "lattice" { source [find interface/parport/lattice.cfg] }
+ "flashlink" { source [find interface/parport/flashlink.cfg] }
+ "altium" { source [find interface/parport/altium.cfg] }
+ "aspo" { source [find interface/parport/aspo.cfg] }
+ default { error "invalid parallel port cable '$cable'" }
+ }
+}
+
lappend _telnet_autocomplete_skip parport_write_on_exit
proc parport_write_on_exit args {
echo "DEPRECATED! use 'parport write_on_exit' not 'parport_write_on_exit'"
@@ -413,6 +434,12 @@ proc xlnx_pcie_xvc_config args {
eval xlnx_pcie_xvc config $args
}
+lappend _telnet_autocomplete_skip xlnx_axi_xvc_config
+proc xlnx_axi_xvc_config args {
+ echo "DEPRECATED! use 'xlnx_axi_xvc config' not 'xlnx_axi_xvc_config'"
+ eval xlnx_axi_xvc config $args
+}
+
lappend _telnet_autocomplete_skip ulink_download_firmware
proc ulink_download_firmware args {
echo "DEPRECATED! use 'ulink download_firmware' not 'ulink_download_firmware'"
diff --git a/src/jtag/swd.h b/src/jtag/swd.h
index 3fe1365b58..c4b6215abd 100644
--- a/src/jtag/swd.h
+++ b/src/jtag/swd.h
@@ -270,6 +270,7 @@ struct swd_driver {
* @param Where to store value to read from register
* @param ap_delay_hint Number of idle cycles that may be
* needed after an AP access to avoid WAITs
+ * or zero in case of DP read.
*/
void (*read_reg)(uint8_t cmd, uint32_t *value, uint32_t ap_delay_hint);
@@ -280,6 +281,7 @@ struct swd_driver {
* @param Value to be written to the register
* @param ap_delay_hint Number of idle cycles that may be
* needed after an AP access to avoid WAITs
+ * or zero in case of DP write.
*/
void (*write_reg)(uint8_t cmd, uint32_t value, uint32_t ap_delay_hint);
diff --git a/src/jtag/tcl.c b/src/jtag/tcl.c
index 8b0bc7affb..9cffd6b5d1 100644
--- a/src/jtag/tcl.c
+++ b/src/jtag/tcl.c
@@ -64,13 +64,13 @@ struct jtag_tap *jtag_tap_by_jim_obj(Jim_Interp *interp, Jim_Obj *o)
static bool scan_is_safe(enum tap_state state)
{
switch (state) {
- case TAP_RESET:
- case TAP_IDLE:
- case TAP_DRPAUSE:
- case TAP_IRPAUSE:
- return true;
- default:
- return false;
+ case TAP_RESET:
+ case TAP_IDLE:
+ case TAP_DRPAUSE:
+ case TAP_IRPAUSE:
+ return true;
+ default:
+ return false;
}
}
@@ -558,18 +558,18 @@ static void jtag_tap_handle_event(struct jtag_tap *tap, enum jtag_event e)
}
switch (e) {
- case JTAG_TAP_EVENT_ENABLE:
- case JTAG_TAP_EVENT_DISABLE:
- /* NOTE: we currently assume the handlers
- * can't fail. Right here is where we should
- * really be verifying the scan chains ...
- */
- tap->enabled = (e == JTAG_TAP_EVENT_ENABLE);
- LOG_INFO("JTAG tap: %s %s", tap->dotted_name,
+ case JTAG_TAP_EVENT_ENABLE:
+ case JTAG_TAP_EVENT_DISABLE:
+ /* NOTE: we currently assume the handlers
+ * can't fail. Right here is where we should
+ * really be verifying the scan chains ...
+ */
+ tap->enabled = (e == JTAG_TAP_EVENT_ENABLE);
+ LOG_INFO("JTAG tap: %s %s", tap->dotted_name,
tap->enabled ? "enabled" : "disabled");
- break;
- default:
- break;
+ break;
+ default:
+ break;
}
}
}
diff --git a/src/openocd.c b/src/openocd.c
index 3fbece3955..f3e1bee48e 100644
--- a/src/openocd.c
+++ b/src/openocd.c
@@ -75,20 +75,20 @@ static int log_target_callback_event_handler(struct target *target,
void *priv)
{
switch (event) {
- case TARGET_EVENT_GDB_START:
- target->verbose_halt_msg = false;
- break;
- case TARGET_EVENT_GDB_END:
- target->verbose_halt_msg = true;
- break;
- case TARGET_EVENT_HALTED:
- if (target->verbose_halt_msg) {
- /* do not display information when debugger caused the halt */
- target_arch_state(target);
- }
- break;
- default:
- break;
+ case TARGET_EVENT_GDB_START:
+ target->verbose_halt_msg = false;
+ break;
+ case TARGET_EVENT_GDB_END:
+ target->verbose_halt_msg = true;
+ break;
+ case TARGET_EVENT_HALTED:
+ if (target->verbose_halt_msg) {
+ /* do not display information when debugger caused the halt */
+ target_arch_state(target);
+ }
+ break;
+ default:
+ break;
}
return ERROR_OK;
@@ -170,7 +170,8 @@ COMMAND_HANDLER(handle_init_command)
jtag_poll_unmask(save_poll_mask);
/* initialize telnet subsystem */
- gdb_target_add_all(all_targets);
+ if (gdb_target_add_all(all_targets) != ERROR_OK)
+ return ERROR_FAIL;
target_register_event_callback(log_target_callback_event_handler, CMD_CTX);
diff --git a/src/pld/xilinx_bit.c b/src/pld/xilinx_bit.c
index e4cc52ef97..1c04c74906 100644
--- a/src/pld/xilinx_bit.c
+++ b/src/pld/xilinx_bit.c
@@ -113,7 +113,7 @@ int xilinx_read_bit_file(struct xilinx_bit_file *bit_file, const char *filename)
return ERROR_PLD_FILE_LOAD_FAILED;
}
- LOG_DEBUG("bit_file: %s %s %s,%s %" PRIu32 "", bit_file->source_file, bit_file->part_name,
+ LOG_DEBUG("bit_file: %s %s %s,%s %" PRIu32, bit_file->source_file, bit_file->part_name,
bit_file->date, bit_file->time, bit_file->length);
fclose(input_file);
diff --git a/src/rtos/chibios.c b/src/rtos/chibios.c
index af590c2cb1..0cd99e4720 100644
--- a/src/rtos/chibios.c
+++ b/src/rtos/chibios.c
@@ -515,10 +515,10 @@ static int chibios_create(struct target *target)
for (unsigned int i = 0; i < ARRAY_SIZE(chibios_params_list); i++)
if (strcmp(chibios_params_list[i].target_name, target_type_name(target)) == 0) {
target->rtos->rtos_specific_params = (void *)&chibios_params_list[i];
- return 0;
+ return ERROR_OK;
}
LOG_WARNING("Could not find target \"%s\" in ChibiOS compatibility "
"list", target_type_name(target));
- return -1;
+ return ERROR_FAIL;
}
diff --git a/src/rtos/ecos.c b/src/rtos/ecos.c
index 7048b006e0..41159bf094 100644
--- a/src/rtos/ecos.c
+++ b/src/rtos/ecos.c
@@ -539,7 +539,7 @@ static int ecos_check_app_info(struct rtos *rtos, struct ecos_params *param)
return -1;
if (param->flush_common) {
- if (debug_level >= LOG_LVL_DEBUG) {
+ if (LOG_LEVEL_IS(LOG_LVL_DEBUG)) {
for (unsigned int idx = 0; idx < ARRAY_SIZE(ecos_symbol_list); idx++) {
LOG_DEBUG("eCos: %s 0x%016" PRIX64 " %s",
rtos->symbols[idx].optional ? "OPTIONAL" : " ",
@@ -1004,7 +1004,7 @@ static int ecos_update_threads(struct rtos *rtos)
if (tr_extra && reason_desc)
soff += snprintf(&eistr[soff], (eilen - soff), " (%s)", reason_desc);
if (pri_extra)
- (void)snprintf(&eistr[soff], (eilen - soff), ", Priority: %" PRId64 "", priority);
+ (void)snprintf(&eistr[soff], (eilen - soff), ", Priority: %" PRId64, priority);
rtos->thread_details[tasks_found].extra_info_str = eistr;
rtos->thread_details[tasks_found].exists = true;
@@ -1073,7 +1073,7 @@ static int ecos_get_thread_reg_list(struct rtos *rtos, int64_t thread_id,
param->uid_width,
(uint8_t *)&id);
if (retval != ERROR_OK) {
- LOG_ERROR("Error reading unique id from eCos thread 0x%08" PRIX32 "", thread_index);
+ LOG_ERROR("Error reading unique id from eCos thread 0x%08" PRIX32, thread_index);
return retval;
}
@@ -1213,12 +1213,12 @@ static int ecos_create(struct target *target)
target->rtos->gdb_thread_packet = ecos_packet_hook;
/* We do not currently use the target->rtos->gdb_target_for_threadid
* hook. */
- return 0;
+ return ERROR_OK;
}
tnames++;
}
}
LOG_ERROR("Could not find target in eCos compatibility list");
- return -1;
+ return ERROR_FAIL;
}
diff --git a/src/rtos/embkernel.c b/src/rtos/embkernel.c
index 7e6de7902a..7ad937be59 100644
--- a/src/rtos/embkernel.c
+++ b/src/rtos/embkernel.c
@@ -115,11 +115,11 @@ static int embkernel_create(struct target *target)
if (i >= ARRAY_SIZE(embkernel_params_list)) {
LOG_WARNING("Could not find target \"%s\" in embKernel compatibility "
"list", target_type_name(target));
- return -1;
+ return ERROR_FAIL;
}
target->rtos->rtos_specific_params = (void *) &embkernel_params_list[i];
- return 0;
+ return ERROR_OK;
}
static int embkernel_get_tasks_details(struct rtos *rtos, int64_t iterable, const struct embkernel_params *param,
diff --git a/src/rtos/hwthread.c b/src/rtos/hwthread.c
index 3e4a4ec42d..5c0c0f07a0 100644
--- a/src/rtos/hwthread.c
+++ b/src/rtos/hwthread.c
@@ -211,8 +211,8 @@ static int hwthread_update_threads(struct rtos *rtos)
else
rtos->current_thread = threadid_from_target(target);
- LOG_TARGET_DEBUG(target, "current_thread=%i, threads_found=%d",
- (int)rtos->current_thread, threads_found);
+ LOG_TARGET_DEBUG(target, "current_thread=%" PRId64 ", threads_found=%d",
+ rtos->current_thread, threads_found);
return 0;
}
@@ -422,7 +422,7 @@ static int hwthread_create(struct target *target)
target->rtos->thread_details = NULL;
target->rtos->gdb_target_for_threadid = hwthread_target_for_threadid;
target->rtos->gdb_thread_packet = hwthread_thread_packet;
- return 0;
+ return ERROR_OK;
}
static bool hwthread_needs_fake_step(struct target *target, int64_t thread_id)
diff --git a/src/rtos/linux.c b/src/rtos/linux.c
index 5efdc9f609..5f59dc883a 100644
--- a/src/rtos/linux.c
+++ b/src/rtos/linux.c
@@ -1282,86 +1282,77 @@ static int linux_thread_packet(struct connection *connection, char const *packet
target->rtos->rtos_specific_params;
switch (packet[0]) {
- case 'T': /* Is thread alive?*/
-
- linux_gdb_t_packet(connection, target, packet, packet_size);
- break;
- case 'H': /* Set current thread */
- /* ( 'c' for step and continue, 'g' for all other operations )*/
- /*LOG_INFO(" H packet received '%s'", packet);*/
- linux_gdb_h_packet(connection, target, packet, packet_size);
- break;
- case 'q':
-
- if (strncmp(packet, "qSymbol", 7) == 0) {
- if (rtos_qsymbol(connection, packet, packet_size) == 1) {
- linux_compute_virt2phys(target,
- target->rtos->symbols[INIT_TASK].address);
- }
-
- break;
- } else if (strncmp(packet, "qfThreadInfo", 12) == 0) {
- if (!linux_os->thread_list) {
- retval = linux_gdb_thread_packet(target,
- connection,
- packet,
- packet_size);
- break;
- } else {
- retval = linux_gdb_thread_update(target,
- connection,
- packet,
- packet_size);
- break;
- }
- } else if (strncmp(packet, "qsThreadInfo", 12) == 0) {
- gdb_put_packet(connection, "l", 1);
- break;
- } else if (strncmp(packet, "qThreadExtraInfo,", 17) == 0) {
- linux_thread_extra_info(target, connection, packet,
+ case 'T': /* Is thread alive?*/
+ linux_gdb_t_packet(connection, target, packet, packet_size);
+ break;
+
+ case 'H': /* Set current thread */
+ /* ( 'c' for step and continue, 'g' for all other operations )*/
+ /*LOG_INFO(" H packet received '%s'", packet);*/
+ linux_gdb_h_packet(connection, target, packet, packet_size);
+ break;
+
+ case 'q':
+ if (!strncmp(packet, "qSymbol", 7)) {
+ if (rtos_qsymbol(connection, packet, packet_size) == 1) {
+ linux_compute_virt2phys(target,
+ target->rtos->symbols[INIT_TASK].address);
+ }
+ } else if (!strncmp(packet, "qfThreadInfo", 12)) {
+ if (!linux_os->thread_list) {
+ retval = linux_gdb_thread_packet(target,
+ connection,
+ packet,
packet_size);
- break;
} else {
- retval = GDB_THREAD_PACKET_NOT_CONSUMED;
- break;
+ retval = linux_gdb_thread_update(target,
+ connection,
+ packet,
+ packet_size);
}
-
- case 'Q':
- /* previously response was : thread not found
- * gdb_put_packet(connection, "E01", 3); */
+ } else if (!strncmp(packet, "qsThreadInfo", 12)) {
+ gdb_put_packet(connection, "l", 1);
+ } else if (!strncmp(packet, "qThreadExtraInfo,", 17)) {
+ linux_thread_extra_info(target, connection, packet,
+ packet_size);
+ } else {
retval = GDB_THREAD_PACKET_NOT_CONSUMED;
- break;
- case 'c':
- case 's': {
- if (linux_os->threads_lookup == 1) {
- ct = linux_os->current_threads;
+ }
+ break;
- while ((ct) && (ct->core_id) != target->coreid)
- ct = ct->next;
+ case 'Q':
+ /* previously response was : thread not found
+ * gdb_put_packet(connection, "E01", 3); */
+ retval = GDB_THREAD_PACKET_NOT_CONSUMED;
+ break;
- if ((ct) && (ct->threadid == -1)) {
- ct = linux_os->current_threads;
+ case 'c':
+ case 's':
+ if (linux_os->threads_lookup == 1) {
+ ct = linux_os->current_threads;
- while ((ct) && (ct->threadid == -1))
- ct = ct->next;
- }
+ while ((ct) && (ct->core_id) != target->coreid)
+ ct = ct->next;
- if ((ct) && (ct->threadid !=
- target->rtos->current_threadid)
- && (target->rtos->current_threadid != -1))
- LOG_WARNING("WARNING! current GDB thread do not match "
- "current thread running. "
- "Switch thread in GDB to threadid %d",
- (int)ct->threadid);
+ if ((ct) && (ct->threadid == -1)) {
+ ct = linux_os->current_threads;
- LOG_INFO("threads_needs_update = 1");
- linux_os->threads_needs_update = 1;
+ while ((ct) && (ct->threadid == -1))
+ ct = ct->next;
}
- }
- /* if a packet handler returned an error, exit input loop */
- if (retval != ERROR_OK)
- return retval;
+ if ((ct) && (ct->threadid !=
+ target->rtos->current_threadid)
+ && (target->rtos->current_threadid != -1))
+ LOG_WARNING("WARNING! current GDB thread do not match "
+ "current thread running. "
+ "Switch thread in GDB to threadid %d",
+ (int)ct->threadid);
+
+ LOG_INFO("threads_needs_update = 1");
+ linux_os->threads_needs_update = 1;
+ }
+ break;
}
return retval;
@@ -1424,7 +1415,7 @@ static int linux_os_create(struct target *target)
/* initialize a default virt 2 phys translation */
os_linux->phys_mask = ~0xc0000000;
os_linux->phys_base = 0x0;
- return JIM_OK;
+ return ERROR_OK;
}
static char *linux_ps_command(struct target *target)
diff --git a/src/rtos/mqx.c b/src/rtos/mqx.c
index 017fd2b01c..dbb48952f2 100644
--- a/src/rtos/mqx.c
+++ b/src/rtos/mqx.c
@@ -251,11 +251,11 @@ static int mqx_create(
if (strcmp(mqx_params_list[i].target_name, target_type_name(target)) == 0) {
target->rtos->rtos_specific_params = (void *)&mqx_params_list[i];
/* LOG_DEBUG("MQX RTOS - valid architecture: %s", target_type_name(target)); */
- return 0;
+ return ERROR_OK;
}
}
LOG_ERROR("MQX RTOS - could not find target \"%s\" in MQX compatibility list", target_type_name(target));
- return -1;
+ return ERROR_FAIL;
}
/*
diff --git a/src/rtos/nuttx.c b/src/rtos/nuttx.c
index 821e550885..27bf086c83 100644
--- a/src/rtos/nuttx.c
+++ b/src/rtos/nuttx.c
@@ -129,13 +129,13 @@ static int nuttx_create(struct target *target)
if (i >= ARRAY_SIZE(nuttx_params_list)) {
LOG_ERROR("Could not find \"%s\" target in NuttX compatibility list", target_type_name(target));
- return JIM_ERR;
+ return ERROR_FAIL;
}
/* We found a target in our list, copy its reference. */
target->rtos->rtos_specific_params = (void *)param;
- return JIM_OK;
+ return ERROR_OK;
}
static int nuttx_smp_init(struct target *target)
diff --git a/src/rtos/rtkernel.c b/src/rtos/rtkernel.c
index aebbf3d94d..2be1996fcd 100644
--- a/src/rtos/rtkernel.c
+++ b/src/rtos/rtkernel.c
@@ -364,12 +364,12 @@ static int rtkernel_create(struct target *target)
for (size_t i = 0; i < ARRAY_SIZE(rtkernel_params_list); i++) {
if (strcmp(rtkernel_params_list[i].target_name, target_type_name(target)) == 0) {
target->rtos->rtos_specific_params = (void *)&rtkernel_params_list[i];
- return 0;
+ return ERROR_OK;
}
}
LOG_ERROR("Could not find target in rt-kernel compatibility list");
- return -1;
+ return ERROR_FAIL;
}
const struct rtos_type rtkernel_rtos = {
diff --git a/src/rtos/rtos.c b/src/rtos/rtos.c
index e87e51cbd6..5a968ade90 100644
--- a/src/rtos/rtos.c
+++ b/src/rtos/rtos.c
@@ -14,29 +14,29 @@
#include "target/smp.h"
#include "helper/log.h"
#include "helper/binarybuffer.h"
+#include "helper/types.h"
#include "server/gdb_server.h"
static const struct rtos_type *rtos_types[] = {
- &threadx_rtos,
- &freertos_rtos,
- &ecos_rtos,
- &linux_rtos,
+ // Keep in alphabetic order this list of rtos, except hwthread
&chibios_rtos,
&chromium_ec_rtos,
+ &ecos_rtos,
&embkernel_rtos,
+ &freertos_rtos,
+ &linux_rtos,
&mqx_rtos,
- &ucos_iii_rtos,
&nuttx_rtos,
&riot_rtos,
- &zephyr_rtos,
&rtkernel_rtos,
- /* keep this as last, as it always matches with rtos auto */
+ &threadx_rtos,
+ &ucos_iii_rtos,
+ &zephyr_rtos,
+
+ // keep this as last, as it always matches with rtos auto
&hwthread_rtos,
- NULL
};
-static int rtos_try_next(struct target *target);
-
int rtos_smp_init(struct target *target)
{
if (target->rtos->type->smp_init)
@@ -61,7 +61,7 @@ static int os_alloc(struct target *target, const struct rtos_type *ostype,
struct rtos *os = target->rtos = calloc(1, sizeof(struct rtos));
if (!os)
- return JIM_ERR;
+ return ERROR_FAIL;
os->type = ostype;
os->current_threadid = -1;
@@ -74,7 +74,7 @@ static int os_alloc(struct target *target, const struct rtos_type *ostype,
os->gdb_target_for_threadid = rtos_target_for_threadid;
os->cmd_ctx = cmd_ctx;
- return JIM_OK;
+ return ERROR_OK;
}
static void os_free(struct target *target)
@@ -92,40 +92,26 @@ static int os_alloc_create(struct target *target, const struct rtos_type *ostype
struct command_context *cmd_ctx)
{
int ret = os_alloc(target, ostype, cmd_ctx);
+ if (ret != ERROR_OK)
+ return ret;
- if (ret == JIM_OK) {
- ret = target->rtos->type->create(target);
- if (ret != JIM_OK)
- os_free(target);
- }
+ ret = target->rtos->type->create(target);
+ if (ret != ERROR_OK)
+ os_free(target);
return ret;
}
-int rtos_create(struct jim_getopt_info *goi, struct target *target)
+int rtos_create(struct command_invocation *cmd, struct target *target,
+ const char *rtos_name)
{
- int x;
- const char *cp;
- Jim_Obj *res;
- int e;
-
- if (!goi->is_configure && goi->argc != 0) {
- Jim_WrongNumArgs(goi->interp, goi->argc, goi->argv, "NO PARAMS");
- return JIM_ERR;
- }
-
- struct command_context *cmd_ctx = current_command_context(goi->interp);
-
os_free(target);
+ target->rtos_auto_detect = false;
- e = jim_getopt_string(goi, &cp, NULL);
- if (e != JIM_OK)
- return e;
-
- if (strcmp(cp, "none") == 0)
- return JIM_OK;
+ if (strcmp(rtos_name, "none") == 0)
+ return ERROR_OK;
- if (strcmp(cp, "auto") == 0) {
+ if (strcmp(rtos_name, "auto") == 0) {
/* Auto detect tries to look up all symbols for each RTOS,
* and runs the RTOS driver's _detect() function when GDB
* finds all symbols for any RTOS. See rtos_qsymbol(). */
@@ -133,20 +119,32 @@ int rtos_create(struct jim_getopt_info *goi, struct target *target)
/* rtos_qsymbol() will iterate over all RTOSes. Allocate
* target->rtos here, and set it to the first RTOS type. */
- return os_alloc(target, rtos_types[0], cmd_ctx);
+ return os_alloc(target, rtos_types[0], CMD_CTX);
}
- for (x = 0; rtos_types[x]; x++)
- if (strcmp(cp, rtos_types[x]->name) == 0)
- return os_alloc_create(target, rtos_types[x], cmd_ctx);
+ for (size_t x = 0; x < ARRAY_SIZE(rtos_types); x++)
+ if (strcmp(rtos_name, rtos_types[x]->name) == 0)
+ return os_alloc_create(target, rtos_types[x], CMD_CTX);
- Jim_SetResultFormatted(goi->interp, "Unknown RTOS type %s, try one of: ", cp);
- res = Jim_GetResult(goi->interp);
- for (x = 0; rtos_types[x]; x++)
- Jim_AppendStrings(goi->interp, res, rtos_types[x]->name, ", ", NULL);
- Jim_AppendStrings(goi->interp, res, ", auto or none", NULL);
+ char *all = NULL;
+ for (size_t x = 0; x < ARRAY_SIZE(rtos_types); x++) {
+ char *prev = all;
+ if (all)
+ all = alloc_printf("%s, %s", all, rtos_types[x]->name);
+ else
+ all = alloc_printf("%s", rtos_types[x]->name);
+ free(prev);
+ if (!all) {
+ LOG_ERROR("Out of memory");
+ return ERROR_FAIL;
+ }
+ }
- return JIM_ERR;
+ command_print(cmd, "Unknown RTOS type %s, try one of: %s, auto or none",
+ rtos_name, all);
+ free(all);
+
+ return ERROR_COMMAND_ARGUMENT_INVALID;
}
void rtos_destroy(struct target *target)
@@ -163,6 +161,29 @@ int gdb_thread_packet(struct connection *connection, char const *packet, int pac
return target->rtos->gdb_thread_packet(connection, packet, packet_size);
}
+static bool rtos_try_next(struct target *target)
+{
+ struct rtos *os = target->rtos;
+
+ if (!os)
+ return false;
+
+ for (size_t x = 0; x < ARRAY_SIZE(rtos_types) - 1; x++) {
+ if (os->type == rtos_types[x]) {
+ // Use next RTOS in the list
+ os->type = rtos_types[x + 1];
+
+ free(os->symbols);
+ os->symbols = NULL;
+
+ return true;
+ }
+ }
+
+ // No next RTOS to try
+ return false;
+}
+
static struct symbol_table_elem *find_symbol(const struct rtos *os, const char *symbol)
{
struct symbol_table_elem *s;
@@ -791,28 +812,6 @@ int rtos_generic_stack_write_reg(struct target *target,
return ERROR_OK;
}
-static int rtos_try_next(struct target *target)
-{
- struct rtos *os = target->rtos;
- const struct rtos_type **type = rtos_types;
-
- if (!os)
- return 0;
-
- while (*type && os->type != *type)
- type++;
-
- if (!*type || !*(++type))
- return 0;
-
- os->type = *type;
-
- free(os->symbols);
- os->symbols = NULL;
-
- return 1;
-}
-
struct rtos *rtos_of_target(struct target *target)
{
/* Primarily consider the rtos field of the target itself, secondarily consider
diff --git a/src/rtos/rtos.h b/src/rtos/rtos.h
index 210f4fc99e..0375f64757 100644
--- a/src/rtos/rtos.h
+++ b/src/rtos/rtos.h
@@ -11,7 +11,6 @@
#include "server/server.h"
#include "target/breakpoints.h"
#include "target/target.h"
-#include
typedef int64_t threadid_t;
typedef int64_t symbol_address_t;
@@ -139,7 +138,8 @@ struct rtos_register_stacking {
#define GDB_THREAD_PACKET_NOT_CONSUMED (-40)
-int rtos_create(struct jim_getopt_info *goi, struct target *target);
+int rtos_create(struct command_invocation *cmd, struct target *target,
+ const char *rtos_name);
void rtos_destroy(struct target *target);
int rtos_set_reg(struct connection *connection, int reg_num,
uint8_t *reg_value);
@@ -174,6 +174,7 @@ struct target *rtos_swbp_target(struct target *target, target_addr_t address,
uint32_t length, enum breakpoint_type type);
struct rtos *rtos_of_target(struct target *target);
+// Keep in alphabetic order this list of rtos
extern const struct rtos_type chibios_rtos;
extern const struct rtos_type chromium_ec_rtos;
extern const struct rtos_type ecos_rtos;
diff --git a/src/rtos/threadx.c b/src/rtos/threadx.c
index 61c49264e8..620f43cc8e 100644
--- a/src/rtos/threadx.c
+++ b/src/rtos/threadx.c
@@ -611,9 +611,9 @@ static int threadx_create(struct target *target)
target->rtos->rtos_specific_params = (void *)&threadx_params_list[i];
target->rtos->current_thread = 0;
target->rtos->thread_details = NULL;
- return 0;
+ return ERROR_OK;
}
LOG_ERROR("Could not find target in ThreadX compatibility list");
- return -1;
+ return ERROR_FAIL;
}
diff --git a/src/rtt/rtt.c b/src/rtt/rtt.c
index 15b9a373a5..3c7a966a79 100644
--- a/src/rtt/rtt.c
+++ b/src/rtt/rtt.c
@@ -288,7 +288,7 @@ int rtt_set_polling_interval(unsigned int interval)
int rtt_write_channel(unsigned int channel_index, const uint8_t *buffer,
size_t *length)
{
- if (channel_index >= rtt.ctrl.num_up_channels) {
+ if (channel_index >= rtt.ctrl.num_down_channels) {
LOG_WARNING("rtt: Down-channel %u is not available", channel_index);
return ERROR_OK;
}
diff --git a/src/server/gdb_server.c b/src/server/gdb_server.c
index d9825c57eb..e9e8503b65 100644
--- a/src/server/gdb_server.c
+++ b/src/server/gdb_server.c
@@ -50,6 +50,8 @@
* found in most modern embedded processors.
*/
+#define CTRL(c) ((c) - '@')
+
enum gdb_output_flag {
/* GDB doesn't accept 'O' packets */
GDB_OUTPUT_NO,
@@ -477,6 +479,10 @@ static int gdb_put_packet_inner(struct connection *connection,
gdb_putback_char(connection, reply);
LOG_DEBUG("Unexpected start of new packet");
break;
+ } else if (reply == CTRL('C')) {
+ /* do not discard Ctrl-C */
+ gdb_putback_char(connection, reply);
+ break;
}
LOG_DEBUG("Discard unexpected char %c", reply);
@@ -488,7 +494,7 @@ static int gdb_put_packet_inner(struct connection *connection,
char local_buffer[1024];
local_buffer[0] = '$';
- if ((size_t)len + 4 <= sizeof(local_buffer)) {
+ if ((size_t)len + 5 <= sizeof(local_buffer)) {
/* performance gain on smaller packets by only a single call to gdb_write() */
memcpy(local_buffer + 1, buffer, len++);
len += snprintf(local_buffer + len, sizeof(local_buffer) - len, "#%02x", my_checksum);
@@ -525,7 +531,7 @@ static int gdb_put_packet_inner(struct connection *connection,
gdb_con->output_flag = GDB_OUTPUT_NO;
gdb_log_incoming_packet(connection, "-");
LOG_WARNING("negative reply, retrying");
- } else if (reply == 0x3) {
+ } else if (reply == CTRL('C')) {
gdb_con->ctrl_c = true;
gdb_log_incoming_packet(connection, "");
retval = gdb_get_char(connection, &reply);
@@ -735,7 +741,7 @@ static int gdb_get_packet_inner(struct connection *connection,
gdb_log_incoming_packet(connection, "-");
LOG_WARNING("negative acknowledgment, but no packet pending");
break;
- case 0x3:
+ case CTRL('C'):
gdb_log_incoming_packet(connection, "");
gdb_con->ctrl_c = true;
*len = 0;
@@ -1058,8 +1064,8 @@ static int gdb_new_connection(struct connection *connection)
* GDB session could leave dangling breakpoints if e.g. communication
* timed out.
*/
- breakpoint_clear_target(target);
- watchpoint_clear_target(target);
+ breakpoint_remove_all(target);
+ watchpoint_remove_all(target);
/* Since version 3.95 (gdb-19990504), with the exclusion of 6.5~6.8, GDB
* sends an ACK at connection with the following comment in its source code:
@@ -1579,7 +1585,7 @@ static int gdb_read_memory_packet(struct connection *connection,
buffer = malloc(len);
- LOG_DEBUG("addr: 0x%16.16" PRIx64 ", len: 0x%8.8" PRIx32 "", addr, len);
+ LOG_DEBUG("addr: 0x%16.16" PRIx64 ", len: 0x%8.8" PRIx32, addr, len);
retval = ERROR_NOT_IMPLEMENTED;
if (target->rtos)
@@ -1651,7 +1657,7 @@ static int gdb_write_memory_packet(struct connection *connection,
buffer = malloc(len);
- LOG_DEBUG("addr: 0x%" PRIx64 ", len: 0x%8.8" PRIx32 "", addr, len);
+ LOG_DEBUG("addr: 0x%" PRIx64 ", len: 0x%8.8" PRIx32, addr, len);
if (unhexify(buffer, separator, len) != len)
LOG_ERROR("unable to decode memory packet");
@@ -1727,7 +1733,7 @@ static int gdb_write_memory_binary_packet(struct connection *connection,
}
if (len) {
- LOG_DEBUG("addr: 0x%" PRIx64 ", len: 0x%8.8" PRIx32 "", addr, len);
+ LOG_DEBUG("addr: 0x%" PRIx64 ", len: 0x%8.8" PRIx32, addr, len);
retval = ERROR_NOT_IMPLEMENTED;
if (target->rtos)
@@ -2904,7 +2910,7 @@ static int gdb_query_packet(struct connection *connection,
gdb_connection->output_flag = GDB_OUTPUT_NO;
if (retval == ERROR_OK) {
- snprintf(gdb_reply, 10, "C%8.8" PRIx32 "", checksum);
+ snprintf(gdb_reply, 10, "C%8.8" PRIx32, checksum);
gdb_put_packet(connection, gdb_reply, 9);
} else {
retval = gdb_error(connection, retval);
@@ -3039,7 +3045,7 @@ static bool gdb_handle_vcont_packet(struct connection *connection, const char *p
__attribute__((unused)) int packet_size)
{
struct gdb_connection *gdb_connection = connection->priv;
- struct target *target = get_target_from_connection(connection);
+ struct target *target = get_available_target_from_connection(connection);
const char *parse = packet;
int retval;
@@ -3284,8 +3290,8 @@ static void gdb_restart_inferior(struct connection *connection, const char *pack
struct gdb_connection *gdb_con = connection->priv;
struct target *target = get_target_from_connection(connection);
- breakpoint_clear_target(target);
- watchpoint_clear_target(target);
+ breakpoint_remove_all(target);
+ watchpoint_remove_all(target);
command_run_linef(connection->cmd_ctx, "ocd_gdb_restart %s",
target_name(target));
/* set connection as attached after reset */
diff --git a/src/server/server.c b/src/server/server.c
index 0649ec942b..5f6bb584e5 100644
--- a/src/server/server.c
+++ b/src/server/server.c
@@ -43,10 +43,10 @@ enum shutdown_reason {
SHUTDOWN_WITH_ERROR_CODE, /* set by shutdown command; quit with non-zero return code */
SHUTDOWN_WITH_SIGNAL_CODE /* set by sig_handler; exec shutdown then exit with signal as return code */
};
-static enum shutdown_reason shutdown_openocd = CONTINUE_MAIN_LOOP;
+static volatile sig_atomic_t shutdown_openocd = CONTINUE_MAIN_LOOP;
/* store received signal to exit application by killing ourselves */
-static int last_signal;
+static volatile sig_atomic_t last_signal;
/* set the polling period to 100ms */
static int polling_period = 100;
@@ -604,6 +604,7 @@ static void sig_handler(int sig)
/* store only first signal that hits us */
if (shutdown_openocd == CONTINUE_MAIN_LOOP) {
shutdown_openocd = SHUTDOWN_WITH_SIGNAL_CODE;
+ assert(sig >= SIG_ATOMIC_MIN && sig <= SIG_ATOMIC_MAX);
last_signal = sig;
LOG_DEBUG("Terminating on Signal %d", sig);
} else
diff --git a/src/server/telnet_server.c b/src/server/telnet_server.c
index 2c3f769801..3634a2a592 100644
--- a/src/server/telnet_server.c
+++ b/src/server/telnet_server.c
@@ -671,7 +671,7 @@ static void telnet_auto_complete(struct connection *connection)
} else if (jimcmd_is_oocd_command(jim_cmd)) {
struct command *cmd = jimcmd_privdata(jim_cmd);
- if (cmd && !cmd->handler && !cmd->jim_handler) {
+ if (cmd && !cmd->handler) {
/* Initial part of a multi-word command. Ignore it! */
ignore_cmd = true;
} else if (cmd && cmd->mode == COMMAND_CONFIG) {
diff --git a/src/svf/svf.c b/src/svf/svf.c
index ce994686f1..7491ad6515 100644
--- a/src/svf/svf.c
+++ b/src/svf/svf.c
@@ -702,71 +702,71 @@ static int svf_read_command_from_file(FILE *fd)
ch = svf_read_line[0];
while (!cmd_ok && (ch != 0)) {
switch (ch) {
- case '!':
+ case '!':
+ slash = 0;
+ if (svf_getline(&svf_read_line, &svf_read_line_size, svf_fd) <= 0)
+ return ERROR_FAIL;
+ svf_line_number++;
+ i = -1;
+ break;
+ case '/':
+ if (++slash == 2) {
slash = 0;
- if (svf_getline(&svf_read_line, &svf_read_line_size, svf_fd) <= 0)
+ if (svf_getline(&svf_read_line, &svf_read_line_size,
+ svf_fd) <= 0)
return ERROR_FAIL;
svf_line_number++;
i = -1;
+ }
+ break;
+ case ';':
+ slash = 0;
+ cmd_ok = 1;
+ break;
+ case '\n':
+ svf_line_number++;
+ if (svf_getline(&svf_read_line, &svf_read_line_size, svf_fd) <= 0)
+ return ERROR_FAIL;
+ i = -1;
+ /* fallthrough */
+ case '\r':
+ slash = 0;
+ /* Don't save '\r' and '\n' if no data is parsed */
+ if (!cmd_pos)
break;
- case '/':
- if (++slash == 2) {
- slash = 0;
- if (svf_getline(&svf_read_line, &svf_read_line_size,
- svf_fd) <= 0)
- return ERROR_FAIL;
- svf_line_number++;
- i = -1;
- }
- break;
- case ';':
- slash = 0;
- cmd_ok = 1;
- break;
- case '\n':
- svf_line_number++;
- if (svf_getline(&svf_read_line, &svf_read_line_size, svf_fd) <= 0)
+ /* fallthrough */
+ default:
+ /* The parsing code currently expects a space
+ * before parentheses -- "TDI (123)". Also a
+ * space afterwards -- "TDI (123) TDO(456)".
+ * But such spaces are optional... instead of
+ * parser updates, cope with that by adding the
+ * spaces as needed.
+ *
+ * Ensure there are 3 bytes available, for:
+ * - current character
+ * - added space.
+ * - terminating NUL ('\0')
+ */
+ if (cmd_pos + 3 > svf_command_buffer_size) {
+ svf_command_buffer = realloc(svf_command_buffer, cmd_pos + 3);
+ svf_command_buffer_size = cmd_pos + 3;
+ if (!svf_command_buffer) {
+ LOG_ERROR("not enough memory");
return ERROR_FAIL;
- i = -1;
- /* fallthrough */
- case '\r':
- slash = 0;
- /* Don't save '\r' and '\n' if no data is parsed */
- if (!cmd_pos)
- break;
- /* fallthrough */
- default:
- /* The parsing code currently expects a space
- * before parentheses -- "TDI (123)". Also a
- * space afterwards -- "TDI (123) TDO(456)".
- * But such spaces are optional... instead of
- * parser updates, cope with that by adding the
- * spaces as needed.
- *
- * Ensure there are 3 bytes available, for:
- * - current character
- * - added space.
- * - terminating NUL ('\0')
- */
- if (cmd_pos + 3 > svf_command_buffer_size) {
- svf_command_buffer = realloc(svf_command_buffer, cmd_pos + 3);
- svf_command_buffer_size = cmd_pos + 3;
- if (!svf_command_buffer) {
- LOG_ERROR("not enough memory");
- return ERROR_FAIL;
- }
}
+ }
- /* insert a space before '(' */
- if ('(' == ch)
- svf_command_buffer[cmd_pos++] = ' ';
+ /* insert a space before '(' */
+ if ('(' == ch)
+ svf_command_buffer[cmd_pos++] = ' ';
- svf_command_buffer[cmd_pos++] = (char)toupper(ch);
+ svf_command_buffer[cmd_pos++] = (char)toupper(ch);
- /* insert a space after ')' */
- if (')' == ch)
- svf_command_buffer[cmd_pos++] = ' ';
- break;
+ /* insert a space after ')' */
+ if (')' == ch)
+ svf_command_buffer[cmd_pos++] = ' ';
+ break;
}
ch = svf_read_line[++i];
}
@@ -780,31 +780,33 @@ static int svf_read_command_from_file(FILE *fd)
static int svf_parse_cmd_string(char *str, int len, char **argus, int *num_of_argu)
{
- int pos = 0, num = 0, space_found = 1, in_bracket = 0;
+ bool space_found = true, in_bracket = false;
+ int pos = 0, num = 0;
while (pos < len) {
switch (str[pos]) {
- case '!':
- case '/':
- LOG_ERROR("fail to parse svf command");
- return ERROR_FAIL;
- case '(':
- in_bracket = 1;
- goto parse_char;
- case ')':
- in_bracket = 0;
- goto parse_char;
- default:
-parse_char:
- if (!in_bracket && isspace((int) str[pos])) {
- space_found = 1;
- str[pos] = '\0';
- } else if (space_found) {
- argus[num++] = &str[pos];
- space_found = 0;
- }
- break;
+ case '!':
+ case '/':
+ LOG_ERROR("fail to parse svf command");
+ return ERROR_FAIL;
+ case '(':
+ in_bracket = true;
+ break;
+ case ')':
+ in_bracket = false;
+ break;
+ default:
+ break;
+ }
+
+ if (!in_bracket && isspace((int)str[pos])) {
+ space_found = true;
+ str[pos] = '\0';
+ } else if (space_found) {
+ argus[num++] = &str[pos];
+ space_found = false;
}
+
pos++;
}
@@ -979,10 +981,295 @@ static int svf_execute_tap(void)
return ERROR_OK;
}
+static int svf_xxr_common(char **argus, int num_of_argu, char command, struct svf_xxr_para *xxr_para_tmp)
+{
+ int i, i_tmp;
+ uint8_t **pbuffer_tmp;
+ struct scan_field field;
+
+ /* XXR length [TDI (tdi)] [TDO (tdo)][MASK (mask)] [SMASK (smask)] */
+ if (num_of_argu > 10 || (num_of_argu % 2)) {
+ LOG_ERROR("invalid parameter of %s", argus[0]);
+ return ERROR_FAIL;
+ }
+ i_tmp = xxr_para_tmp->len;
+ xxr_para_tmp->len = atoi(argus[1]);
+ /* If we are to enlarge the buffers, all parts of xxr_para_tmp
+ * need to be freed */
+ if (i_tmp < xxr_para_tmp->len) {
+ free(xxr_para_tmp->tdi);
+ xxr_para_tmp->tdi = NULL;
+ free(xxr_para_tmp->tdo);
+ xxr_para_tmp->tdo = NULL;
+ free(xxr_para_tmp->mask);
+ xxr_para_tmp->mask = NULL;
+ free(xxr_para_tmp->smask);
+ xxr_para_tmp->smask = NULL;
+ }
+
+ LOG_DEBUG("\tlength = %d", xxr_para_tmp->len);
+ xxr_para_tmp->data_mask = 0;
+ for (i = 2; i < num_of_argu; i += 2) {
+ if ((strlen(argus[i + 1]) < 3) || (argus[i + 1][0] != '(') ||
+ argus[i + 1][strlen(argus[i + 1]) - 1] != ')') {
+ LOG_ERROR("data section error");
+ return ERROR_FAIL;
+ }
+ argus[i + 1][strlen(argus[i + 1]) - 1] = '\0';
+ /* TDI, TDO, MASK, SMASK */
+ if (!strcmp(argus[i], "TDI")) {
+ /* TDI */
+ pbuffer_tmp = &xxr_para_tmp->tdi;
+ xxr_para_tmp->data_mask |= XXR_TDI;
+ } else if (!strcmp(argus[i], "TDO")) {
+ /* TDO */
+ pbuffer_tmp = &xxr_para_tmp->tdo;
+ xxr_para_tmp->data_mask |= XXR_TDO;
+ } else if (!strcmp(argus[i], "MASK")) {
+ /* MASK */
+ pbuffer_tmp = &xxr_para_tmp->mask;
+ xxr_para_tmp->data_mask |= XXR_MASK;
+ } else if (!strcmp(argus[i], "SMASK")) {
+ /* SMASK */
+ pbuffer_tmp = &xxr_para_tmp->smask;
+ xxr_para_tmp->data_mask |= XXR_SMASK;
+ } else {
+ LOG_ERROR("unknown parameter: %s", argus[i]);
+ return ERROR_FAIL;
+ }
+ if (svf_copy_hexstring_to_binary(&argus[i + 1][1], pbuffer_tmp, i_tmp,
+ xxr_para_tmp->len) != ERROR_OK) {
+ LOG_ERROR("fail to parse hex value");
+ return ERROR_FAIL;
+ }
+ SVF_BUF_LOG(DEBUG, *pbuffer_tmp, xxr_para_tmp->len, argus[i]);
+ }
+ /* If a command changes the length of the last scan of the same type and the
+ * MASK parameter is absent, */
+ /* the mask pattern used is all cares */
+ if (!(xxr_para_tmp->data_mask & XXR_MASK) && i_tmp != xxr_para_tmp->len) {
+ /* MASK not defined and length changed */
+ if (svf_adjust_array_length(&xxr_para_tmp->mask, i_tmp, xxr_para_tmp->len)
+ != ERROR_OK) {
+ LOG_ERROR("fail to adjust length of array");
+ return ERROR_FAIL;
+ }
+ buf_set_ones(xxr_para_tmp->mask, xxr_para_tmp->len);
+ }
+ /* If TDO is absent, no comparison is needed, set the mask to 0 */
+ if (!(xxr_para_tmp->data_mask & XXR_TDO)) {
+ if (!xxr_para_tmp->tdo) {
+ if (svf_adjust_array_length(&xxr_para_tmp->tdo, i_tmp, xxr_para_tmp->len)
+ != ERROR_OK) {
+ LOG_ERROR("fail to adjust length of array");
+ return ERROR_FAIL;
+ }
+ }
+ if (!xxr_para_tmp->mask) {
+ if (svf_adjust_array_length(&xxr_para_tmp->mask, i_tmp, xxr_para_tmp->len)
+ != ERROR_OK) {
+ LOG_ERROR("fail to adjust length of array");
+ return ERROR_FAIL;
+ }
+ }
+ memset(xxr_para_tmp->mask, 0, (xxr_para_tmp->len + 7) >> 3);
+ }
+ /* do scan if necessary */
+ if (command == SDR) {
+ /* check buffer size first, reallocate if necessary */
+ i = svf_para.hdr_para.len + svf_para.sdr_para.len +
+ svf_para.tdr_para.len;
+ if ((svf_buffer_size - svf_buffer_index) < ((i + 7) >> 3)) {
+ /* reallocate buffer */
+ if (svf_realloc_buffers(svf_buffer_index + ((i + 7) >> 3)) != ERROR_OK) {
+ LOG_ERROR("not enough memory");
+ return ERROR_FAIL;
+ }
+ }
+
+ /* assemble dr data */
+ i = 0;
+ buf_set_buf(svf_para.hdr_para.tdi,
+ 0,
+ &svf_tdi_buffer[svf_buffer_index],
+ i,
+ svf_para.hdr_para.len);
+ i += svf_para.hdr_para.len;
+ buf_set_buf(svf_para.sdr_para.tdi,
+ 0,
+ &svf_tdi_buffer[svf_buffer_index],
+ i,
+ svf_para.sdr_para.len);
+ i += svf_para.sdr_para.len;
+ buf_set_buf(svf_para.tdr_para.tdi,
+ 0,
+ &svf_tdi_buffer[svf_buffer_index],
+ i,
+ svf_para.tdr_para.len);
+ i += svf_para.tdr_para.len;
+
+ /* add check data */
+ if (svf_para.sdr_para.data_mask & XXR_TDO) {
+ /* assemble dr mask data */
+ i = 0;
+ buf_set_buf(svf_para.hdr_para.mask,
+ 0,
+ &svf_mask_buffer[svf_buffer_index],
+ i,
+ svf_para.hdr_para.len);
+ i += svf_para.hdr_para.len;
+ buf_set_buf(svf_para.sdr_para.mask,
+ 0,
+ &svf_mask_buffer[svf_buffer_index],
+ i,
+ svf_para.sdr_para.len);
+ i += svf_para.sdr_para.len;
+ buf_set_buf(svf_para.tdr_para.mask,
+ 0,
+ &svf_mask_buffer[svf_buffer_index],
+ i,
+ svf_para.tdr_para.len);
+
+ /* assemble dr check data */
+ i = 0;
+ buf_set_buf(svf_para.hdr_para.tdo,
+ 0,
+ &svf_tdo_buffer[svf_buffer_index],
+ i,
+ svf_para.hdr_para.len);
+ i += svf_para.hdr_para.len;
+ buf_set_buf(svf_para.sdr_para.tdo,
+ 0,
+ &svf_tdo_buffer[svf_buffer_index],
+ i,
+ svf_para.sdr_para.len);
+ i += svf_para.sdr_para.len;
+ buf_set_buf(svf_para.tdr_para.tdo,
+ 0,
+ &svf_tdo_buffer[svf_buffer_index],
+ i,
+ svf_para.tdr_para.len);
+ i += svf_para.tdr_para.len;
+
+ svf_add_check_para(1, svf_buffer_index, i);
+ } else {
+ svf_add_check_para(0, svf_buffer_index, i);
+ }
+ field.num_bits = i;
+ field.out_value = &svf_tdi_buffer[svf_buffer_index];
+ field.in_value = (xxr_para_tmp->data_mask & XXR_TDO) ? &svf_tdi_buffer[svf_buffer_index] : NULL;
+ if (!svf_nil) {
+ /* NOTE: doesn't use SVF-specified state paths */
+ jtag_add_plain_dr_scan(field.num_bits,
+ field.out_value,
+ field.in_value,
+ svf_para.dr_end_state);
+ }
+
+ if (svf_addcycles)
+ jtag_add_clocks(svf_addcycles);
+
+ svf_buffer_index += (i + 7) >> 3;
+ } else if (command == SIR) {
+ /* check buffer size first, reallocate if necessary */
+ i = svf_para.hir_para.len + svf_para.sir_para.len +
+ svf_para.tir_para.len;
+ if ((svf_buffer_size - svf_buffer_index) < ((i + 7) >> 3)) {
+ if (svf_realloc_buffers(svf_buffer_index + ((i + 7) >> 3)) != ERROR_OK) {
+ LOG_ERROR("not enough memory");
+ return ERROR_FAIL;
+ }
+ }
+
+ /* assemble ir data */
+ i = 0;
+ buf_set_buf(svf_para.hir_para.tdi,
+ 0,
+ &svf_tdi_buffer[svf_buffer_index],
+ i,
+ svf_para.hir_para.len);
+ i += svf_para.hir_para.len;
+ buf_set_buf(svf_para.sir_para.tdi,
+ 0,
+ &svf_tdi_buffer[svf_buffer_index],
+ i,
+ svf_para.sir_para.len);
+ i += svf_para.sir_para.len;
+ buf_set_buf(svf_para.tir_para.tdi,
+ 0,
+ &svf_tdi_buffer[svf_buffer_index],
+ i,
+ svf_para.tir_para.len);
+ i += svf_para.tir_para.len;
+
+ /* add check data */
+ if (svf_para.sir_para.data_mask & XXR_TDO) {
+ /* assemble dr mask data */
+ i = 0;
+ buf_set_buf(svf_para.hir_para.mask,
+ 0,
+ &svf_mask_buffer[svf_buffer_index],
+ i,
+ svf_para.hir_para.len);
+ i += svf_para.hir_para.len;
+ buf_set_buf(svf_para.sir_para.mask,
+ 0,
+ &svf_mask_buffer[svf_buffer_index],
+ i,
+ svf_para.sir_para.len);
+ i += svf_para.sir_para.len;
+ buf_set_buf(svf_para.tir_para.mask,
+ 0,
+ &svf_mask_buffer[svf_buffer_index],
+ i,
+ svf_para.tir_para.len);
+
+ /* assemble dr check data */
+ i = 0;
+ buf_set_buf(svf_para.hir_para.tdo,
+ 0,
+ &svf_tdo_buffer[svf_buffer_index],
+ i,
+ svf_para.hir_para.len);
+ i += svf_para.hir_para.len;
+ buf_set_buf(svf_para.sir_para.tdo,
+ 0,
+ &svf_tdo_buffer[svf_buffer_index],
+ i,
+ svf_para.sir_para.len);
+ i += svf_para.sir_para.len;
+ buf_set_buf(svf_para.tir_para.tdo,
+ 0,
+ &svf_tdo_buffer[svf_buffer_index],
+ i,
+ svf_para.tir_para.len);
+ i += svf_para.tir_para.len;
+
+ svf_add_check_para(1, svf_buffer_index, i);
+ } else {
+ svf_add_check_para(0, svf_buffer_index, i);
+ }
+ field.num_bits = i;
+ field.out_value = &svf_tdi_buffer[svf_buffer_index];
+ field.in_value = (xxr_para_tmp->data_mask & XXR_TDO) ? &svf_tdi_buffer[svf_buffer_index] : NULL;
+ if (!svf_nil) {
+ /* NOTE: doesn't use SVF-specified state paths */
+ jtag_add_plain_ir_scan(field.num_bits,
+ field.out_value,
+ field.in_value,
+ svf_para.ir_end_state);
+ }
+
+ svf_buffer_index += (i + 7) >> 3;
+ }
+
+ return ERROR_OK;
+}
+
static int svf_run_command(struct command_context *cmd_ctx, char *cmd_str)
{
char *argus[256], command;
- int num_of_argu = 0, i;
+ int num_of_argu = 0, i, retval;
/* tmp variable */
int i_tmp;
@@ -990,10 +1277,6 @@ static int svf_run_command(struct command_context *cmd_ctx, char *cmd_str)
/* for RUNTEST */
int run_count;
float min_time;
- /* for XXR */
- struct svf_xxr_para *xxr_para_tmp;
- uint8_t **pbuffer_tmp;
- struct scan_field field;
/* for STATE */
enum tap_state *path = NULL, state;
/* flag padding commands skipped due to -tap command */
@@ -1009,594 +1292,327 @@ static int svf_run_command(struct command_context *cmd_ctx, char *cmd_str)
command = svf_find_string_in_array(argus[0],
(char **)svf_command_name, ARRAY_SIZE(svf_command_name));
switch (command) {
- case ENDDR:
- case ENDIR:
- if (num_of_argu != 2) {
- LOG_ERROR("invalid parameter of %s", argus[0]);
- return ERROR_FAIL;
- }
+ case ENDDR:
+ case ENDIR:
+ if (num_of_argu != 2) {
+ LOG_ERROR("invalid parameter of %s", argus[0]);
+ return ERROR_FAIL;
+ }
- i_tmp = tap_state_by_name(argus[1]);
+ i_tmp = tap_state_by_name(argus[1]);
- if (svf_tap_state_is_stable(i_tmp)) {
- if (command == ENDIR) {
- svf_para.ir_end_state = i_tmp;
- LOG_DEBUG("\tIR end_state = %s",
- tap_state_name(i_tmp));
- } else {
- svf_para.dr_end_state = i_tmp;
- LOG_DEBUG("\tDR end_state = %s",
- tap_state_name(i_tmp));
- }
+ if (svf_tap_state_is_stable(i_tmp)) {
+ if (command == ENDIR) {
+ svf_para.ir_end_state = i_tmp;
+ LOG_DEBUG("\tIR end_state = %s",
+ tap_state_name(i_tmp));
} else {
- LOG_ERROR("%s: %s is not a stable state",
- argus[0], argus[1]);
- return ERROR_FAIL;
+ svf_para.dr_end_state = i_tmp;
+ LOG_DEBUG("\tDR end_state = %s",
+ tap_state_name(i_tmp));
}
- break;
- case FREQUENCY:
- if ((num_of_argu != 1) && (num_of_argu != 3)) {
- LOG_ERROR("invalid parameter of %s", argus[0]);
+ } else {
+ LOG_ERROR("%s: %s is not a stable state",
+ argus[0], argus[1]);
+ return ERROR_FAIL;
+ }
+ break;
+ case FREQUENCY:
+ if (num_of_argu != 1 && num_of_argu != 3) {
+ LOG_ERROR("invalid parameter of %s", argus[0]);
+ return ERROR_FAIL;
+ }
+ if (num_of_argu == 1) {
+ /* TODO: set jtag speed to full speed */
+ svf_para.frequency = 0;
+ } else {
+ if (strcmp(argus[2], "HZ")) {
+ LOG_ERROR("HZ not found in FREQUENCY command");
return ERROR_FAIL;
}
- if (num_of_argu == 1) {
- /* TODO: set jtag speed to full speed */
- svf_para.frequency = 0;
- } else {
- if (strcmp(argus[2], "HZ")) {
- LOG_ERROR("HZ not found in FREQUENCY command");
- return ERROR_FAIL;
- }
- if (svf_execute_tap() != ERROR_OK)
- return ERROR_FAIL;
- svf_para.frequency = atof(argus[1]);
- /* TODO: set jtag speed to */
- if (svf_para.frequency > 0) {
- command_run_linef(cmd_ctx,
- "adapter speed %d",
- (int)svf_para.frequency / 1000);
- LOG_DEBUG("\tfrequency = %f", svf_para.frequency);
- }
- }
- break;
- case HDR:
- if (svf_tap_is_specified) {
- padding_command_skipped = 1;
- break;
- }
- xxr_para_tmp = &svf_para.hdr_para;
- goto xxr_common;
- case HIR:
- if (svf_tap_is_specified) {
- padding_command_skipped = 1;
- break;
- }
- xxr_para_tmp = &svf_para.hir_para;
- goto xxr_common;
- case TDR:
- if (svf_tap_is_specified) {
- padding_command_skipped = 1;
- break;
- }
- xxr_para_tmp = &svf_para.tdr_para;
- goto xxr_common;
- case TIR:
- if (svf_tap_is_specified) {
- padding_command_skipped = 1;
- break;
- }
- xxr_para_tmp = &svf_para.tir_para;
- goto xxr_common;
- case SDR:
- xxr_para_tmp = &svf_para.sdr_para;
- goto xxr_common;
- case SIR:
- xxr_para_tmp = &svf_para.sir_para;
- goto xxr_common;
-xxr_common:
- /* XXR length [TDI (tdi)] [TDO (tdo)][MASK (mask)] [SMASK (smask)] */
- if ((num_of_argu > 10) || (num_of_argu % 2)) {
- LOG_ERROR("invalid parameter of %s", argus[0]);
+ if (svf_execute_tap() != ERROR_OK)
return ERROR_FAIL;
+ svf_para.frequency = atof(argus[1]);
+ /* TODO: set jtag speed to */
+ if (svf_para.frequency > 0) {
+ command_run_linef(cmd_ctx,
+ "adapter speed %d",
+ (int)svf_para.frequency / 1000);
+ LOG_DEBUG("\tfrequency = %f", svf_para.frequency);
}
- i_tmp = xxr_para_tmp->len;
- xxr_para_tmp->len = atoi(argus[1]);
- /* If we are to enlarge the buffers, all parts of xxr_para_tmp
- * need to be freed */
- if (i_tmp < xxr_para_tmp->len) {
- free(xxr_para_tmp->tdi);
- xxr_para_tmp->tdi = NULL;
- free(xxr_para_tmp->tdo);
- xxr_para_tmp->tdo = NULL;
- free(xxr_para_tmp->mask);
- xxr_para_tmp->mask = NULL;
- free(xxr_para_tmp->smask);
- xxr_para_tmp->smask = NULL;
- }
-
- LOG_DEBUG("\tlength = %d", xxr_para_tmp->len);
- xxr_para_tmp->data_mask = 0;
- for (i = 2; i < num_of_argu; i += 2) {
- if ((strlen(argus[i + 1]) < 3) || (argus[i + 1][0] != '(') ||
- (argus[i + 1][strlen(argus[i + 1]) - 1] != ')')) {
- LOG_ERROR("data section error");
- return ERROR_FAIL;
- }
- argus[i + 1][strlen(argus[i + 1]) - 1] = '\0';
- /* TDI, TDO, MASK, SMASK */
- if (!strcmp(argus[i], "TDI")) {
- /* TDI */
- pbuffer_tmp = &xxr_para_tmp->tdi;
- xxr_para_tmp->data_mask |= XXR_TDI;
- } else if (!strcmp(argus[i], "TDO")) {
- /* TDO */
- pbuffer_tmp = &xxr_para_tmp->tdo;
- xxr_para_tmp->data_mask |= XXR_TDO;
- } else if (!strcmp(argus[i], "MASK")) {
- /* MASK */
- pbuffer_tmp = &xxr_para_tmp->mask;
- xxr_para_tmp->data_mask |= XXR_MASK;
- } else if (!strcmp(argus[i], "SMASK")) {
- /* SMASK */
- pbuffer_tmp = &xxr_para_tmp->smask;
- xxr_para_tmp->data_mask |= XXR_SMASK;
- } else {
- LOG_ERROR("unknown parameter: %s", argus[i]);
- return ERROR_FAIL;
- }
- if (ERROR_OK !=
- svf_copy_hexstring_to_binary(&argus[i + 1][1], pbuffer_tmp, i_tmp,
- xxr_para_tmp->len)) {
- LOG_ERROR("fail to parse hex value");
- return ERROR_FAIL;
- }
- SVF_BUF_LOG(DEBUG, *pbuffer_tmp, xxr_para_tmp->len, argus[i]);
- }
- /* If a command changes the length of the last scan of the same type and the
- * MASK parameter is absent, */
- /* the mask pattern used is all cares */
- if (!(xxr_para_tmp->data_mask & XXR_MASK) && (i_tmp != xxr_para_tmp->len)) {
- /* MASK not defined and length changed */
- if (ERROR_OK !=
- svf_adjust_array_length(&xxr_para_tmp->mask, i_tmp,
- xxr_para_tmp->len)) {
- LOG_ERROR("fail to adjust length of array");
- return ERROR_FAIL;
- }
- buf_set_ones(xxr_para_tmp->mask, xxr_para_tmp->len);
- }
- /* If TDO is absent, no comparison is needed, set the mask to 0 */
- if (!(xxr_para_tmp->data_mask & XXR_TDO)) {
- if (!xxr_para_tmp->tdo) {
- if (ERROR_OK !=
- svf_adjust_array_length(&xxr_para_tmp->tdo, i_tmp,
- xxr_para_tmp->len)) {
- LOG_ERROR("fail to adjust length of array");
- return ERROR_FAIL;
- }
- }
- if (!xxr_para_tmp->mask) {
- if (ERROR_OK !=
- svf_adjust_array_length(&xxr_para_tmp->mask, i_tmp,
- xxr_para_tmp->len)) {
- LOG_ERROR("fail to adjust length of array");
- return ERROR_FAIL;
- }
- }
- memset(xxr_para_tmp->mask, 0, (xxr_para_tmp->len + 7) >> 3);
- }
- /* do scan if necessary */
- if (command == SDR) {
- /* check buffer size first, reallocate if necessary */
- i = svf_para.hdr_para.len + svf_para.sdr_para.len +
- svf_para.tdr_para.len;
- if ((svf_buffer_size - svf_buffer_index) < ((i + 7) >> 3)) {
- /* reallocate buffer */
- if (svf_realloc_buffers(svf_buffer_index + ((i + 7) >> 3)) != ERROR_OK) {
- LOG_ERROR("not enough memory");
- return ERROR_FAIL;
- }
- }
-
- /* assemble dr data */
- i = 0;
- buf_set_buf(svf_para.hdr_para.tdi,
- 0,
- &svf_tdi_buffer[svf_buffer_index],
- i,
- svf_para.hdr_para.len);
- i += svf_para.hdr_para.len;
- buf_set_buf(svf_para.sdr_para.tdi,
- 0,
- &svf_tdi_buffer[svf_buffer_index],
- i,
- svf_para.sdr_para.len);
- i += svf_para.sdr_para.len;
- buf_set_buf(svf_para.tdr_para.tdi,
- 0,
- &svf_tdi_buffer[svf_buffer_index],
- i,
- svf_para.tdr_para.len);
- i += svf_para.tdr_para.len;
-
- /* add check data */
- if (svf_para.sdr_para.data_mask & XXR_TDO) {
- /* assemble dr mask data */
- i = 0;
- buf_set_buf(svf_para.hdr_para.mask,
- 0,
- &svf_mask_buffer[svf_buffer_index],
- i,
- svf_para.hdr_para.len);
- i += svf_para.hdr_para.len;
- buf_set_buf(svf_para.sdr_para.mask,
- 0,
- &svf_mask_buffer[svf_buffer_index],
- i,
- svf_para.sdr_para.len);
- i += svf_para.sdr_para.len;
- buf_set_buf(svf_para.tdr_para.mask,
- 0,
- &svf_mask_buffer[svf_buffer_index],
- i,
- svf_para.tdr_para.len);
-
- /* assemble dr check data */
- i = 0;
- buf_set_buf(svf_para.hdr_para.tdo,
- 0,
- &svf_tdo_buffer[svf_buffer_index],
- i,
- svf_para.hdr_para.len);
- i += svf_para.hdr_para.len;
- buf_set_buf(svf_para.sdr_para.tdo,
- 0,
- &svf_tdo_buffer[svf_buffer_index],
- i,
- svf_para.sdr_para.len);
- i += svf_para.sdr_para.len;
- buf_set_buf(svf_para.tdr_para.tdo,
- 0,
- &svf_tdo_buffer[svf_buffer_index],
- i,
- svf_para.tdr_para.len);
- i += svf_para.tdr_para.len;
-
- svf_add_check_para(1, svf_buffer_index, i);
- } else
- svf_add_check_para(0, svf_buffer_index, i);
- field.num_bits = i;
- field.out_value = &svf_tdi_buffer[svf_buffer_index];
- field.in_value = (xxr_para_tmp->data_mask & XXR_TDO) ? &svf_tdi_buffer[svf_buffer_index] : NULL;
- if (!svf_nil) {
- /* NOTE: doesn't use SVF-specified state paths */
- jtag_add_plain_dr_scan(field.num_bits,
- field.out_value,
- field.in_value,
- svf_para.dr_end_state);
- }
-
- if (svf_addcycles)
- jtag_add_clocks(svf_addcycles);
-
- svf_buffer_index += (i + 7) >> 3;
- } else if (command == SIR) {
- /* check buffer size first, reallocate if necessary */
- i = svf_para.hir_para.len + svf_para.sir_para.len +
- svf_para.tir_para.len;
- if ((svf_buffer_size - svf_buffer_index) < ((i + 7) >> 3)) {
- if (svf_realloc_buffers(svf_buffer_index + ((i + 7) >> 3)) != ERROR_OK) {
- LOG_ERROR("not enough memory");
- return ERROR_FAIL;
- }
- }
-
- /* assemble ir data */
- i = 0;
- buf_set_buf(svf_para.hir_para.tdi,
- 0,
- &svf_tdi_buffer[svf_buffer_index],
- i,
- svf_para.hir_para.len);
- i += svf_para.hir_para.len;
- buf_set_buf(svf_para.sir_para.tdi,
- 0,
- &svf_tdi_buffer[svf_buffer_index],
- i,
- svf_para.sir_para.len);
- i += svf_para.sir_para.len;
- buf_set_buf(svf_para.tir_para.tdi,
- 0,
- &svf_tdi_buffer[svf_buffer_index],
- i,
- svf_para.tir_para.len);
- i += svf_para.tir_para.len;
-
- /* add check data */
- if (svf_para.sir_para.data_mask & XXR_TDO) {
- /* assemble dr mask data */
- i = 0;
- buf_set_buf(svf_para.hir_para.mask,
- 0,
- &svf_mask_buffer[svf_buffer_index],
- i,
- svf_para.hir_para.len);
- i += svf_para.hir_para.len;
- buf_set_buf(svf_para.sir_para.mask,
- 0,
- &svf_mask_buffer[svf_buffer_index],
- i,
- svf_para.sir_para.len);
- i += svf_para.sir_para.len;
- buf_set_buf(svf_para.tir_para.mask,
- 0,
- &svf_mask_buffer[svf_buffer_index],
- i,
- svf_para.tir_para.len);
-
- /* assemble dr check data */
- i = 0;
- buf_set_buf(svf_para.hir_para.tdo,
- 0,
- &svf_tdo_buffer[svf_buffer_index],
- i,
- svf_para.hir_para.len);
- i += svf_para.hir_para.len;
- buf_set_buf(svf_para.sir_para.tdo,
- 0,
- &svf_tdo_buffer[svf_buffer_index],
- i,
- svf_para.sir_para.len);
- i += svf_para.sir_para.len;
- buf_set_buf(svf_para.tir_para.tdo,
- 0,
- &svf_tdo_buffer[svf_buffer_index],
- i,
- svf_para.tir_para.len);
- i += svf_para.tir_para.len;
-
- svf_add_check_para(1, svf_buffer_index, i);
- } else
- svf_add_check_para(0, svf_buffer_index, i);
- field.num_bits = i;
- field.out_value = &svf_tdi_buffer[svf_buffer_index];
- field.in_value = (xxr_para_tmp->data_mask & XXR_TDO) ? &svf_tdi_buffer[svf_buffer_index] : NULL;
- if (!svf_nil) {
- /* NOTE: doesn't use SVF-specified state paths */
- jtag_add_plain_ir_scan(field.num_bits,
- field.out_value,
- field.in_value,
- svf_para.ir_end_state);
- }
-
- svf_buffer_index += (i + 7) >> 3;
- }
+ }
+ break;
+ case HDR:
+ if (svf_tap_is_specified) {
+ padding_command_skipped = 1;
break;
- case PIO:
- case PIOMAP:
- LOG_ERROR("PIO and PIOMAP are not supported");
+ }
+ retval = svf_xxr_common(argus, num_of_argu, command, &svf_para.hdr_para);
+ if (retval != ERROR_OK)
+ return retval;
+ break;
+ case HIR:
+ if (svf_tap_is_specified) {
+ padding_command_skipped = 1;
+ break;
+ }
+ retval = svf_xxr_common(argus, num_of_argu, command, &svf_para.hir_para);
+ if (retval != ERROR_OK)
+ return retval;
+ break;
+ case TDR:
+ if (svf_tap_is_specified) {
+ padding_command_skipped = 1;
+ break;
+ }
+ retval = svf_xxr_common(argus, num_of_argu, command, &svf_para.tdr_para);
+ if (retval != ERROR_OK)
+ return retval;
+ break;
+ case TIR:
+ if (svf_tap_is_specified) {
+ padding_command_skipped = 1;
+ break;
+ }
+ retval = svf_xxr_common(argus, num_of_argu, command, &svf_para.tir_para);
+ if (retval != ERROR_OK)
+ return retval;
+ break;
+ case SDR:
+ retval = svf_xxr_common(argus, num_of_argu, command, &svf_para.sdr_para);
+ if (retval != ERROR_OK)
+ return retval;
+ break;
+ case SIR:
+ retval = svf_xxr_common(argus, num_of_argu, command, &svf_para.sir_para);
+ if (retval != ERROR_OK)
+ return retval;
+ break;
+ case PIO:
+ case PIOMAP:
+ LOG_ERROR("PIO and PIOMAP are not supported");
+ return ERROR_FAIL;
+ case RUNTEST:
+ /* RUNTEST [run_state] run_count run_clk [min_time SEC [MAXIMUM max_time
+ * SEC]] [ENDSTATE end_state] */
+ /* RUNTEST [run_state] min_time SEC [MAXIMUM max_time SEC] [ENDSTATE
+ * end_state] */
+ if (num_of_argu < 3 || num_of_argu > 11) {
+ LOG_ERROR("invalid parameter of %s", argus[0]);
return ERROR_FAIL;
- case RUNTEST:
- /* RUNTEST [run_state] run_count run_clk [min_time SEC [MAXIMUM max_time
- * SEC]] [ENDSTATE end_state] */
- /* RUNTEST [run_state] min_time SEC [MAXIMUM max_time SEC] [ENDSTATE
- * end_state] */
- if ((num_of_argu < 3) || (num_of_argu > 11)) {
- LOG_ERROR("invalid parameter of %s", argus[0]);
+ }
+ /* init */
+ run_count = 0;
+ min_time = 0;
+ i = 1;
+
+ /* run_state */
+ i_tmp = tap_state_by_name(argus[i]);
+ if (i_tmp != TAP_INVALID) {
+ if (svf_tap_state_is_stable(i_tmp)) {
+ svf_para.runtest_run_state = i_tmp;
+
+ /* When a run_state is specified, the new
+ * run_state becomes the default end_state.
+ */
+ svf_para.runtest_end_state = i_tmp;
+ LOG_DEBUG("\trun_state = %s", tap_state_name(i_tmp));
+ i++;
+ } else {
+ LOG_ERROR("%s: %s is not a stable state", argus[0], tap_state_name(i_tmp));
return ERROR_FAIL;
}
- /* init */
- run_count = 0;
- min_time = 0;
- i = 1;
-
- /* run_state */
- i_tmp = tap_state_by_name(argus[i]);
- if (i_tmp != TAP_INVALID) {
- if (svf_tap_state_is_stable(i_tmp)) {
- svf_para.runtest_run_state = i_tmp;
-
- /* When a run_state is specified, the new
- * run_state becomes the default end_state.
- */
- svf_para.runtest_end_state = i_tmp;
- LOG_DEBUG("\trun_state = %s", tap_state_name(i_tmp));
- i++;
- } else {
- LOG_ERROR("%s: %s is not a stable state", argus[0], tap_state_name(i_tmp));
- return ERROR_FAIL;
- }
- }
+ }
- /* run_count run_clk */
- if (((i + 2) <= num_of_argu) && strcmp(argus[i + 1], "SEC")) {
- if (!strcmp(argus[i + 1], "TCK")) {
- /* clock source is TCK */
- run_count = atoi(argus[i]);
- LOG_DEBUG("\trun_count@TCK = %d", run_count);
- } else {
- LOG_ERROR("%s not supported for clock", argus[i + 1]);
- return ERROR_FAIL;
- }
- i += 2;
- }
- /* min_time SEC */
- if (((i + 2) <= num_of_argu) && !strcmp(argus[i + 1], "SEC")) {
- min_time = atof(argus[i]);
- LOG_DEBUG("\tmin_time = %fs", min_time);
- i += 2;
- }
- /* MAXIMUM max_time SEC */
- if (((i + 3) <= num_of_argu) &&
- !strcmp(argus[i], "MAXIMUM") && !strcmp(argus[i + 2], "SEC")) {
- float max_time = 0;
- max_time = atof(argus[i + 1]);
- LOG_DEBUG("\tmax_time = %fs", max_time);
- i += 3;
+ /* run_count run_clk */
+ if (((i + 2) <= num_of_argu) && strcmp(argus[i + 1], "SEC")) {
+ if (!strcmp(argus[i + 1], "TCK")) {
+ /* clock source is TCK */
+ run_count = atoi(argus[i]);
+ LOG_DEBUG("\trun_count@TCK = %d", run_count);
+ } else {
+ LOG_ERROR("%s not supported for clock", argus[i + 1]);
+ return ERROR_FAIL;
}
- /* ENDSTATE end_state */
- if (((i + 2) <= num_of_argu) && !strcmp(argus[i], "ENDSTATE")) {
- i_tmp = tap_state_by_name(argus[i + 1]);
+ i += 2;
+ }
+ /* min_time SEC */
+ if (((i + 2) <= num_of_argu) && !strcmp(argus[i + 1], "SEC")) {
+ min_time = atof(argus[i]);
+ LOG_DEBUG("\tmin_time = %fs", min_time);
+ i += 2;
+ }
+ /* MAXIMUM max_time SEC */
+ if (((i + 3) <= num_of_argu) &&
+ !strcmp(argus[i], "MAXIMUM") && !strcmp(argus[i + 2], "SEC")) {
+ float max_time = 0;
+ max_time = atof(argus[i + 1]);
+ LOG_DEBUG("\tmax_time = %fs", max_time);
+ i += 3;
+ }
+ /* ENDSTATE end_state */
+ if (((i + 2) <= num_of_argu) && !strcmp(argus[i], "ENDSTATE")) {
+ i_tmp = tap_state_by_name(argus[i + 1]);
- if (svf_tap_state_is_stable(i_tmp)) {
- svf_para.runtest_end_state = i_tmp;
- LOG_DEBUG("\tend_state = %s", tap_state_name(i_tmp));
- } else {
- LOG_ERROR("%s: %s is not a stable state", argus[0], tap_state_name(i_tmp));
- return ERROR_FAIL;
- }
- i += 2;
+ if (svf_tap_state_is_stable(i_tmp)) {
+ svf_para.runtest_end_state = i_tmp;
+ LOG_DEBUG("\tend_state = %s", tap_state_name(i_tmp));
+ } else {
+ LOG_ERROR("%s: %s is not a stable state", argus[0], tap_state_name(i_tmp));
+ return ERROR_FAIL;
}
+ i += 2;
+ }
- /* all parameter should be parsed */
- if (i == num_of_argu) {
+ /* all parameter should be parsed */
+ if (i == num_of_argu) {
#if 1
- /* FIXME handle statemove failures */
- uint32_t min_usec = 1000000 * min_time;
+ /* FIXME handle statemove failures */
+ uint32_t min_usec = 1000000 * min_time;
- /* enter into run_state if necessary */
- if (cmd_queue_cur_state != svf_para.runtest_run_state)
- svf_add_statemove(svf_para.runtest_run_state);
+ /* enter into run_state if necessary */
+ if (cmd_queue_cur_state != svf_para.runtest_run_state)
+ svf_add_statemove(svf_para.runtest_run_state);
- /* add clocks and/or min wait */
- if (run_count > 0) {
- if (!svf_nil)
- jtag_add_clocks(run_count);
- }
+ /* add clocks and/or min wait */
+ if (run_count > 0) {
+ if (!svf_nil)
+ jtag_add_clocks(run_count);
+ }
- if (min_usec > 0) {
- if (!svf_nil)
- jtag_add_sleep(min_usec);
- }
+ if (min_usec > 0) {
+ if (!svf_nil)
+ jtag_add_sleep(min_usec);
+ }
- /* move to end_state if necessary */
- if (svf_para.runtest_end_state != svf_para.runtest_run_state)
- svf_add_statemove(svf_para.runtest_end_state);
+ /* move to end_state if necessary */
+ if (svf_para.runtest_end_state != svf_para.runtest_run_state)
+ svf_add_statemove(svf_para.runtest_end_state);
#else
- if (svf_para.runtest_run_state != TAP_IDLE) {
- LOG_ERROR("cannot runtest in %s state",
- tap_state_name(svf_para.runtest_run_state));
- return ERROR_FAIL;
- }
-
- if (!svf_nil)
- jtag_add_runtest(run_count, svf_para.runtest_end_state);
-#endif
- } else {
- LOG_ERROR("fail to parse parameter of RUNTEST, %d out of %d is parsed",
- i,
- num_of_argu);
+ if (svf_para.runtest_run_state != TAP_IDLE) {
+ LOG_ERROR("cannot runtest in %s state",
+ tap_state_name(svf_para.runtest_run_state));
return ERROR_FAIL;
}
- break;
- case STATE:
- /* STATE [pathstate1 [pathstate2 ...[pathstaten]]] stable_state */
- if (num_of_argu < 2) {
- LOG_ERROR("invalid parameter of %s", argus[0]);
+
+ if (!svf_nil)
+ jtag_add_runtest(run_count, svf_para.runtest_end_state);
+#endif
+ } else {
+ LOG_ERROR("fail to parse parameter of RUNTEST, %d out of %d is parsed",
+ i,
+ num_of_argu);
+ return ERROR_FAIL;
+ }
+ break;
+ case STATE:
+ /* STATE [pathstate1 [pathstate2 ...[pathstaten]]] stable_state */
+ if (num_of_argu < 2) {
+ LOG_ERROR("invalid parameter of %s", argus[0]);
+ return ERROR_FAIL;
+ }
+ if (num_of_argu > 2) {
+ /* STATE pathstate1 ... stable_state */
+ path = malloc((num_of_argu - 1) * sizeof(enum tap_state));
+ if (!path) {
+ LOG_ERROR("not enough memory");
return ERROR_FAIL;
}
- if (num_of_argu > 2) {
- /* STATE pathstate1 ... stable_state */
- path = malloc((num_of_argu - 1) * sizeof(enum tap_state));
- if (!path) {
- LOG_ERROR("not enough memory");
+ num_of_argu--; /* num of path */
+ i_tmp = 1; /* path is from parameter 1 */
+ for (i = 0; i < num_of_argu; i++, i_tmp++) {
+ path[i] = tap_state_by_name(argus[i_tmp]);
+ if (path[i] == TAP_INVALID) {
+ LOG_ERROR("%s: %s is not a valid state", argus[0], argus[i_tmp]);
+ free(path);
return ERROR_FAIL;
}
- num_of_argu--; /* num of path */
- i_tmp = 1; /* path is from parameter 1 */
- for (i = 0; i < num_of_argu; i++, i_tmp++) {
- path[i] = tap_state_by_name(argus[i_tmp]);
- if (path[i] == TAP_INVALID) {
- LOG_ERROR("%s: %s is not a valid state", argus[0], argus[i_tmp]);
- free(path);
- return ERROR_FAIL;
- }
- /* OpenOCD refuses paths containing TAP_RESET */
- if (path[i] == TAP_RESET) {
- /* FIXME last state MUST be stable! */
- if (i > 0) {
- if (!svf_nil)
- jtag_add_pathmove(i, path);
- }
+ /* OpenOCD refuses paths containing TAP_RESET */
+ if (path[i] == TAP_RESET) {
+ /* FIXME last state MUST be stable! */
+ if (i > 0) {
if (!svf_nil)
- jtag_add_tlr();
- num_of_argu -= i + 1;
- i = -1;
- }
- }
- if (num_of_argu > 0) {
- /* execute last path if necessary */
- if (svf_tap_state_is_stable(path[num_of_argu - 1])) {
- /* last state MUST be stable state */
- if (!svf_nil)
- jtag_add_pathmove(num_of_argu, path);
- LOG_DEBUG("\tmove to %s by path_move",
- tap_state_name(path[num_of_argu - 1]));
- } else {
- LOG_ERROR("%s: %s is not a stable state",
- argus[0],
- tap_state_name(path[num_of_argu - 1]));
- free(path);
- return ERROR_FAIL;
+ jtag_add_pathmove(i, path);
}
+ if (!svf_nil)
+ jtag_add_tlr();
+ num_of_argu -= i + 1;
+ i = -1;
}
-
- free(path);
- path = NULL;
- } else {
- /* STATE stable_state */
- state = tap_state_by_name(argus[1]);
- if (svf_tap_state_is_stable(state)) {
- LOG_DEBUG("\tmove to %s by svf_add_statemove",
- tap_state_name(state));
- /* FIXME handle statemove failures */
- svf_add_statemove(state);
+ }
+ if (num_of_argu > 0) {
+ /* execute last path if necessary */
+ if (svf_tap_state_is_stable(path[num_of_argu - 1])) {
+ /* last state MUST be stable state */
+ if (!svf_nil)
+ jtag_add_pathmove(num_of_argu, path);
+ LOG_DEBUG("\tmove to %s by path_move",
+ tap_state_name(path[num_of_argu - 1]));
} else {
LOG_ERROR("%s: %s is not a stable state",
- argus[0], tap_state_name(state));
+ argus[0],
+ tap_state_name(path[num_of_argu - 1]));
+ free(path);
return ERROR_FAIL;
}
}
- break;
- case TRST:
- /* TRST trst_mode */
- if (num_of_argu != 2) {
- LOG_ERROR("invalid parameter of %s", argus[0]);
+
+ free(path);
+ path = NULL;
+ } else {
+ /* STATE stable_state */
+ state = tap_state_by_name(argus[1]);
+ if (svf_tap_state_is_stable(state)) {
+ LOG_DEBUG("\tmove to %s by svf_add_statemove",
+ tap_state_name(state));
+ /* FIXME handle statemove failures */
+ svf_add_statemove(state);
+ } else {
+ LOG_ERROR("%s: %s is not a stable state",
+ argus[0], tap_state_name(state));
return ERROR_FAIL;
}
- if (svf_para.trst_mode != TRST_ABSENT) {
- if (svf_execute_tap() != ERROR_OK)
- return ERROR_FAIL;
- i_tmp = svf_find_string_in_array(argus[1],
- (char **)svf_trst_mode_name,
- ARRAY_SIZE(svf_trst_mode_name));
- switch (i_tmp) {
- case TRST_ON:
- if (!svf_nil)
- jtag_add_reset(1, 0);
- break;
- case TRST_Z:
- case TRST_OFF:
- if (!svf_nil)
- jtag_add_reset(0, 0);
- break;
- case TRST_ABSENT:
- break;
- default:
- LOG_ERROR("unknown TRST mode: %s", argus[1]);
- return ERROR_FAIL;
- }
- svf_para.trst_mode = i_tmp;
- LOG_DEBUG("\ttrst_mode = %s", svf_trst_mode_name[svf_para.trst_mode]);
- } else {
- LOG_ERROR("can not accept TRST command if trst_mode is ABSENT");
+ }
+ break;
+ case TRST:
+ /* TRST trst_mode */
+ if (num_of_argu != 2) {
+ LOG_ERROR("invalid parameter of %s", argus[0]);
+ return ERROR_FAIL;
+ }
+ if (svf_para.trst_mode != TRST_ABSENT) {
+ if (svf_execute_tap() != ERROR_OK)
+ return ERROR_FAIL;
+ i_tmp = svf_find_string_in_array(argus[1],
+ (char **)svf_trst_mode_name,
+ ARRAY_SIZE(svf_trst_mode_name));
+ switch (i_tmp) {
+ case TRST_ON:
+ if (!svf_nil)
+ jtag_add_reset(1, 0);
+ break;
+ case TRST_Z:
+ case TRST_OFF:
+ if (!svf_nil)
+ jtag_add_reset(0, 0);
+ break;
+ case TRST_ABSENT:
+ break;
+ default:
+ LOG_ERROR("unknown TRST mode: %s", argus[1]);
return ERROR_FAIL;
}
- break;
- default:
- LOG_ERROR("invalid svf command: %s", argus[0]);
+ svf_para.trst_mode = i_tmp;
+ LOG_DEBUG("\ttrst_mode = %s", svf_trst_mode_name[svf_para.trst_mode]);
+ } else {
+ LOG_ERROR("can not accept TRST command if trst_mode is ABSENT");
return ERROR_FAIL;
+ }
+ break;
+ default:
+ LOG_ERROR("invalid svf command: %s", argus[0]);
+ return ERROR_FAIL;
}
if (!svf_quiet) {
@@ -1604,7 +1620,7 @@ static int svf_run_command(struct command_context *cmd_ctx, char *cmd_str)
LOG_USER("(Above Padding command skipped, as per -tap argument)");
}
- if (debug_level >= LOG_LVL_DEBUG) {
+ if (LOG_LEVEL_IS(LOG_LVL_DEBUG)) {
/* for convenient debugging, execute tap if possible */
if ((svf_buffer_index > 0) &&
(((command != STATE) && (command != RUNTEST)) ||
diff --git a/src/target/Makefile.am b/src/target/Makefile.am
index 1a76864180..0b5a85704c 100644
--- a/src/target/Makefile.am
+++ b/src/target/Makefile.am
@@ -75,6 +75,7 @@ ARMV6_SRC = \
ARMV7_SRC = \
%D%/armv7m.c \
+ %D%/armv7m_cache.c \
%D%/armv7m_trace.c \
%D%/cortex_m.c \
%D%/armv7a.c \
@@ -183,6 +184,7 @@ ARC_SRC = \
%D%/armv4_5_cache.h \
%D%/armv7a.h \
%D%/armv7m.h \
+ %D%/armv7m_cache.h \
%D%/armv7m_trace.h \
%D%/armv8.h \
%D%/armv8_dpm.h \
diff --git a/src/target/aarch64.c b/src/target/aarch64.c
index 101cb14408..ed9cb48aa7 100644
--- a/src/target/aarch64.c
+++ b/src/target/aarch64.c
@@ -50,7 +50,7 @@ static int aarch64_set_hybrid_breakpoint(struct target *target,
struct breakpoint *breakpoint);
static int aarch64_unset_breakpoint(struct target *target,
struct breakpoint *breakpoint);
-static int aarch64_mmu(struct target *target, int *enabled);
+static int aarch64_mmu(struct target *target, bool *enabled);
static int aarch64_virt2phys(struct target *target,
target_addr_t virt, target_addr_t *phys);
static int aarch64_read_cpu_memory(struct target *target,
@@ -613,22 +613,22 @@ static int aarch64_restore_one(struct target *target, bool current,
* kill the return address
*/
switch (arm->core_state) {
- case ARM_STATE_ARM:
- resume_pc &= 0xFFFFFFFC;
- break;
- case ARM_STATE_AARCH64:
- resume_pc &= 0xFFFFFFFFFFFFFFFCULL;
- break;
- case ARM_STATE_THUMB:
- case ARM_STATE_THUMB_EE:
- /* When the return address is loaded into PC
- * bit 0 must be 1 to stay in Thumb state
- */
- resume_pc |= 0x1;
- break;
- case ARM_STATE_JAZELLE:
- LOG_ERROR("How do I resume into Jazelle state??");
- return ERROR_FAIL;
+ case ARM_STATE_ARM:
+ resume_pc &= 0xFFFFFFFC;
+ break;
+ case ARM_STATE_AARCH64:
+ resume_pc &= 0xFFFFFFFFFFFFFFFCULL;
+ break;
+ case ARM_STATE_THUMB:
+ case ARM_STATE_THUMB_EE:
+ /* When the return address is loaded into PC
+ * bit 0 must be 1 to stay in Thumb state
+ */
+ resume_pc |= 0x1;
+ break;
+ case ARM_STATE_JAZELLE:
+ LOG_ERROR("How do I resume into Jazelle state??");
+ return ERROR_FAIL;
}
LOG_DEBUG("resume pc = 0x%016" PRIx64, resume_pc);
buf_set_u64(arm->pc->value, 0, 64, resume_pc);
@@ -1095,20 +1095,19 @@ static int aarch64_post_debug_entry(struct target *target)
LOG_DEBUG("System_register: %8.8" PRIx64, aarch64->system_control_reg);
aarch64->system_control_reg_curr = aarch64->system_control_reg;
- if (armv8->armv8_mmu.armv8_cache.info == -1) {
+ if (!armv8->armv8_mmu.armv8_cache.info_valid) {
armv8_identify_cache(armv8);
armv8_read_mpidr(armv8);
}
if (armv8->is_armv8r) {
- armv8->armv8_mmu.mmu_enabled = 0;
+ armv8->armv8_mmu.mmu_enabled = false;
} else {
- armv8->armv8_mmu.mmu_enabled =
- (aarch64->system_control_reg & 0x1U) ? 1 : 0;
+ armv8->armv8_mmu.mmu_enabled = aarch64->system_control_reg & 0x1U;
}
armv8->armv8_mmu.armv8_cache.d_u_cache_enabled =
- (aarch64->system_control_reg & 0x4U) ? 1 : 0;
+ aarch64->system_control_reg & 0x4U;
armv8->armv8_mmu.armv8_cache.i_cache_enabled =
- (aarch64->system_control_reg & 0x1000U) ? 1 : 0;
+ aarch64->system_control_reg & 0x1000U;
return ERROR_OK;
}
@@ -2529,7 +2528,7 @@ static int aarch64_read_phys_memory(struct target *target,
static int aarch64_read_memory(struct target *target, target_addr_t address,
uint32_t size, uint32_t count, uint8_t *buffer)
{
- int mmu_enabled = 0;
+ bool mmu_enabled = false;
int retval;
/* determine if MMU was enabled on target stop */
@@ -2566,7 +2565,7 @@ static int aarch64_write_phys_memory(struct target *target,
static int aarch64_write_memory(struct target *target, target_addr_t address,
uint32_t size, uint32_t count, const uint8_t *buffer)
{
- int mmu_enabled = 0;
+ bool mmu_enabled = false;
int retval;
/* determine if MMU was enabled on target stop */
@@ -2877,7 +2876,7 @@ static void aarch64_deinit_target(struct target *target)
free(aarch64);
}
-static int aarch64_mmu(struct target *target, int *enabled)
+static int aarch64_mmu(struct target *target, bool *enabled)
{
struct aarch64_common *aarch64 = target_to_aarch64(target);
struct armv8_common *armv8 = &aarch64->armv8_common;
@@ -2886,7 +2885,7 @@ static int aarch64_mmu(struct target *target, int *enabled)
return ERROR_TARGET_NOT_HALTED;
}
if (armv8->is_armv8r)
- *enabled = 0;
+ *enabled = false;
else
*enabled = target_to_aarch64(target)->armv8_common.armv8_mmu.mmu_enabled;
return ERROR_OK;
@@ -3027,14 +3026,14 @@ COMMAND_HANDLER(aarch64_handle_disassemble_command)
target_addr_t address;
switch (CMD_ARGC) {
- case 2:
- COMMAND_PARSE_NUMBER(int, CMD_ARGV[1], count);
- /* FALL THROUGH */
- case 1:
- COMMAND_PARSE_ADDRESS(CMD_ARGV[0], address);
- break;
- default:
- return ERROR_COMMAND_SYNTAX_ERROR;
+ case 2:
+ COMMAND_PARSE_NUMBER(int, CMD_ARGV[1], count);
+ /* FALL THROUGH */
+ case 1:
+ COMMAND_PARSE_ADDRESS(CMD_ARGV[0], address);
+ break;
+ default:
+ return ERROR_COMMAND_SYNTAX_ERROR;
}
return a64_disassemble(CMD, target, address, count);
diff --git a/src/target/arc.c b/src/target/arc.c
index f2482c25ef..629f79aa03 100644
--- a/src/target/arc.c
+++ b/src/target/arc.c
@@ -769,7 +769,7 @@ static int arc_exit_debug(struct target *target)
target->state = TARGET_HALTED;
CHECK_RETVAL(target_call_event_callbacks(target, TARGET_EVENT_HALTED));
- if (debug_level >= LOG_LVL_DEBUG) {
+ if (LOG_LEVEL_IS(LOG_LVL_DEBUG)) {
LOG_TARGET_DEBUG(target, "core stopped (halted) debug-reg: 0x%08" PRIx32, value);
CHECK_RETVAL(arc_jtag_read_aux_reg_one(&arc->jtag_info, AUX_STATUS32_REG, &value));
LOG_TARGET_DEBUG(target, "core STATUS32: 0x%08" PRIx32, value);
@@ -824,7 +824,7 @@ static int arc_halt(struct target *target)
CHECK_RETVAL(target_call_event_callbacks(target, TARGET_EVENT_HALTED));
/* some more debug information */
- if (debug_level >= LOG_LVL_DEBUG) {
+ if (LOG_LEVEL_IS(LOG_LVL_DEBUG)) {
LOG_TARGET_DEBUG(target, "core stopped (halted) DEGUB-REG: 0x%08" PRIx32, value);
CHECK_RETVAL(arc_get_register_value(target, "status32", &value));
LOG_TARGET_DEBUG(target, "core STATUS32: 0x%08" PRIx32, value);
@@ -1148,7 +1148,7 @@ static int arc_arch_state(struct target *target)
{
uint32_t pc_value;
- if (debug_level < LOG_LVL_DEBUG)
+ if (!LOG_LEVEL_IS(LOG_LVL_DEBUG))
return ERROR_OK;
CHECK_RETVAL(arc_get_register_value(target, "pc", &pc_value));
@@ -1892,18 +1892,18 @@ static int arc_set_watchpoint(struct target *target,
int enable = AP_AC_TT_DISABLE;
switch (watchpoint->rw) {
- case WPT_READ:
- enable = AP_AC_TT_READ;
- break;
- case WPT_WRITE:
- enable = AP_AC_TT_WRITE;
- break;
- case WPT_ACCESS:
- enable = AP_AC_TT_READWRITE;
- break;
- default:
- LOG_TARGET_ERROR(target, "BUG: watchpoint->rw neither read, write nor access");
- return ERROR_FAIL;
+ case WPT_READ:
+ enable = AP_AC_TT_READ;
+ break;
+ case WPT_WRITE:
+ enable = AP_AC_TT_WRITE;
+ break;
+ case WPT_ACCESS:
+ enable = AP_AC_TT_READWRITE;
+ break;
+ default:
+ LOG_TARGET_ERROR(target, "BUG: watchpoint->rw neither read, write nor access");
+ return ERROR_FAIL;
}
int retval = arc_configure_actionpoint(target, wp_num,
diff --git a/src/target/arc_cmd.c b/src/target/arc_cmd.c
index bf8a8aa28b..2e42398d28 100644
--- a/src/target/arc_cmd.c
+++ b/src/target/arc_cmd.c
@@ -709,29 +709,29 @@ COMMAND_HANDLER(arc_handle_get_reg_field)
int retval = arc_reg_get_field(target, reg_name, field_name, &value);
switch (retval) {
- case ERROR_OK:
- break;
- case ERROR_ARC_REGISTER_NOT_FOUND:
- command_print(CMD,
- "Register `%s' has not been found.", reg_name);
- return ERROR_COMMAND_ARGUMENT_INVALID;
- case ERROR_ARC_REGISTER_IS_NOT_STRUCT:
- command_print(CMD,
- "Register `%s' must have 'struct' type.", reg_name);
- return ERROR_COMMAND_ARGUMENT_INVALID;
- case ERROR_ARC_REGISTER_FIELD_NOT_FOUND:
- command_print(CMD,
- "Field `%s' has not been found in register `%s'.",
- field_name, reg_name);
- return ERROR_COMMAND_ARGUMENT_INVALID;
- case ERROR_ARC_FIELD_IS_NOT_BITFIELD:
- command_print(CMD,
- "Field `%s' is not a 'bitfield' field in a structure.",
- field_name);
- return ERROR_COMMAND_ARGUMENT_INVALID;
- default:
- /* Pass through other errors. */
- return retval;
+ case ERROR_OK:
+ break;
+ case ERROR_ARC_REGISTER_NOT_FOUND:
+ command_print(CMD,
+ "Register `%s' has not been found.", reg_name);
+ return ERROR_COMMAND_ARGUMENT_INVALID;
+ case ERROR_ARC_REGISTER_IS_NOT_STRUCT:
+ command_print(CMD,
+ "Register `%s' must have 'struct' type.", reg_name);
+ return ERROR_COMMAND_ARGUMENT_INVALID;
+ case ERROR_ARC_REGISTER_FIELD_NOT_FOUND:
+ command_print(CMD,
+ "Field `%s' has not been found in register `%s'.",
+ field_name, reg_name);
+ return ERROR_COMMAND_ARGUMENT_INVALID;
+ case ERROR_ARC_FIELD_IS_NOT_BITFIELD:
+ command_print(CMD,
+ "Field `%s' is not a 'bitfield' field in a structure.",
+ field_name);
+ return ERROR_COMMAND_ARGUMENT_INVALID;
+ default:
+ /* Pass through other errors. */
+ return retval;
}
command_print(CMD, "0x%" PRIx32, value);
diff --git a/src/target/arm11.c b/src/target/arm11.c
index 583830f948..81026c68c4 100644
--- a/src/target/arm11.c
+++ b/src/target/arm11.c
@@ -414,19 +414,19 @@ static uint32_t arm11_nextpc(struct arm11_common *arm11, bool current,
* kill the return address
*/
switch (arm11->arm.core_state) {
- case ARM_STATE_ARM:
- address &= 0xFFFFFFFC;
- break;
- case ARM_STATE_THUMB:
- /* When the return address is loaded into PC
- * bit 0 must be 1 to stay in Thumb state
- */
- address |= 0x1;
- break;
-
- /* catch-all for JAZELLE and THUMB_EE */
- default:
- break;
+ case ARM_STATE_ARM:
+ address &= 0xFFFFFFFC;
+ break;
+ case ARM_STATE_THUMB:
+ /* When the return address is loaded into PC
+ * bit 0 must be 1 to stay in Thumb state
+ */
+ address |= 0x1;
+ break;
+
+ /* catch-all for JAZELLE and THUMB_EE */
+ default:
+ break;
}
buf_set_u32(value, 0, 32, address);
@@ -469,7 +469,7 @@ static int arm11_resume(struct target *target, bool current,
for (bp = target->breakpoints; bp; bp = bp->next) {
if (bp->address == address) {
- LOG_DEBUG("must step over %08" TARGET_PRIxADDR "", bp->address);
+ LOG_DEBUG("must step over %08" TARGET_PRIxADDR, bp->address);
arm11_step(target, true, 0, false);
break;
}
@@ -802,7 +802,7 @@ static int arm11_read_memory_inner(struct target *target,
return ERROR_TARGET_NOT_HALTED;
}
- LOG_DEBUG("ADDR %08" PRIx32 " SIZE %08" PRIx32 " COUNT %08" PRIx32 "",
+ LOG_DEBUG("ADDR %08" PRIx32 " SIZE %08" PRIx32 " COUNT %08" PRIx32,
address,
size,
count);
@@ -819,46 +819,44 @@ static int arm11_read_memory_inner(struct target *target,
return retval;
switch (size) {
- case 1:
- arm11->arm.core_cache->reg_list[1].dirty = true;
-
- for (size_t i = 0; i < count; i++) {
- /* ldrb r1, [r0], #1 */
- /* ldrb r1, [r0] */
- CHECK_RETVAL(arm11_run_instr_no_data1(arm11,
- !arm11_config_memrw_no_increment ? 0xe4d01001 : 0xe5d01000));
+ case 1:
+ arm11->arm.core_cache->reg_list[1].dirty = true;
- uint32_t res;
- /* MCR p14,0,R1,c0,c5,0 */
- CHECK_RETVAL(arm11_run_instr_data_from_core(arm11, 0xEE001E15, &res, 1));
+ for (size_t i = 0; i < count; i++) {
+ /* ldrb r1, [r0], #1 */
+ /* ldrb r1, [r0] */
+ CHECK_RETVAL(arm11_run_instr_no_data1(arm11,
+ !arm11_config_memrw_no_increment ? 0xe4d01001 : 0xe5d01000));
- *buffer++ = res;
- }
+ uint32_t res;
+ /* MCR p14,0,R1,c0,c5,0 */
+ CHECK_RETVAL(arm11_run_instr_data_from_core(arm11, 0xEE001E15, &res, 1));
- break;
+ *buffer++ = res;
+ }
- case 2:
- {
- arm11->arm.core_cache->reg_list[1].dirty = true;
+ break;
- for (size_t i = 0; i < count; i++) {
- /* ldrh r1, [r0], #2 */
- CHECK_RETVAL(arm11_run_instr_no_data1(arm11,
- !arm11_config_memrw_no_increment ? 0xe0d010b2 : 0xe1d010b0));
+ case 2:
+ arm11->arm.core_cache->reg_list[1].dirty = true;
- uint32_t res;
+ for (size_t i = 0; i < count; i++) {
+ /* ldrh r1, [r0], #2 */
+ CHECK_RETVAL(arm11_run_instr_no_data1(arm11,
+ !arm11_config_memrw_no_increment ? 0xe0d010b2 : 0xe1d010b0));
- /* MCR p14,0,R1,c0,c5,0 */
- CHECK_RETVAL(arm11_run_instr_data_from_core(arm11, 0xEE001E15, &res, 1));
+ uint32_t res;
- uint16_t svalue = res;
- memcpy(buffer + i * sizeof(uint16_t), &svalue, sizeof(uint16_t));
- }
+ /* MCR p14,0,R1,c0,c5,0 */
+ CHECK_RETVAL(arm11_run_instr_data_from_core(arm11, 0xEE001E15, &res, 1));
- break;
+ uint16_t svalue = res;
+ memcpy(buffer + i * sizeof(uint16_t), &svalue, sizeof(uint16_t));
}
- case 4:
+ break;
+
+ case 4:
{
uint32_t instr = !arm11_config_memrw_no_increment ? 0xecb05e01 : 0xed905e00;
/** \todo TODO: buffer cast to uint32_t* causes alignment warnings */
@@ -900,7 +898,7 @@ static int arm11_write_memory_inner(struct target *target,
return ERROR_TARGET_NOT_HALTED;
}
- LOG_DEBUG("ADDR %08" PRIx32 " SIZE %08" PRIx32 " COUNT %08" PRIx32 "",
+ LOG_DEBUG("ADDR %08" PRIx32 " SIZE %08" PRIx32 " COUNT %08" PRIx32,
address,
size,
count);
@@ -927,56 +925,53 @@ static int arm11_write_memory_inner(struct target *target,
bool burst = arm11->memwrite_burst && (count > 1);
switch (size) {
- case 1:
- {
- arm11->arm.core_cache->reg_list[1].dirty = true;
-
- for (size_t i = 0; i < count; i++) {
- /* load r1 from DCC with byte data */
- /* MRC p14,0,r1,c0,c5,0 */
- retval = arm11_run_instr_data_to_core1(arm11, 0xee101e15, *buffer++);
- if (retval != ERROR_OK)
- return retval;
-
- /* write r1 to memory */
- /* strb r1, [r0], #1 */
- /* strb r1, [r0] */
- retval = arm11_run_instr_no_data1(arm11,
- !no_increment ? 0xe4c01001 : 0xe5c01000);
- if (retval != ERROR_OK)
- return retval;
- }
+ case 1:
+ arm11->arm.core_cache->reg_list[1].dirty = true;
- break;
+ for (size_t i = 0; i < count; i++) {
+ /* load r1 from DCC with byte data */
+ /* MRC p14,0,r1,c0,c5,0 */
+ retval = arm11_run_instr_data_to_core1(arm11, 0xee101e15, *buffer++);
+ if (retval != ERROR_OK)
+ return retval;
+
+ /* write r1 to memory */
+ /* strb r1, [r0], #1 */
+ /* strb r1, [r0] */
+ retval = arm11_run_instr_no_data1(arm11,
+ !no_increment ? 0xe4c01001 : 0xe5c01000);
+ if (retval != ERROR_OK)
+ return retval;
}
- case 2:
- {
- arm11->arm.core_cache->reg_list[1].dirty = true;
-
- for (size_t i = 0; i < count; i++) {
- uint16_t value;
- memcpy(&value, buffer + i * sizeof(uint16_t), sizeof(uint16_t));
-
- /* load r1 from DCC with halfword data */
- /* MRC p14,0,r1,c0,c5,0 */
- retval = arm11_run_instr_data_to_core1(arm11, 0xee101e15, value);
- if (retval != ERROR_OK)
- return retval;
-
- /* write r1 to memory */
- /* strh r1, [r0], #2 */
- /* strh r1, [r0] */
- retval = arm11_run_instr_no_data1(arm11,
- !no_increment ? 0xe0c010b2 : 0xe1c010b0);
- if (retval != ERROR_OK)
- return retval;
- }
+ break;
- break;
+ case 2:
+ arm11->arm.core_cache->reg_list[1].dirty = true;
+
+ for (size_t i = 0; i < count; i++) {
+ uint16_t value;
+ memcpy(&value, buffer + i * sizeof(uint16_t), sizeof(uint16_t));
+
+ /* load r1 from DCC with halfword data */
+ /* MRC p14,0,r1,c0,c5,0 */
+ retval = arm11_run_instr_data_to_core1(arm11, 0xee101e15, value);
+ if (retval != ERROR_OK)
+ return retval;
+
+ /* write r1 to memory */
+ /* strh r1, [r0], #2 */
+ /* strh r1, [r0] */
+ retval = arm11_run_instr_no_data1(arm11,
+ !no_increment ? 0xe0c010b2 : 0xe1c010b0);
+ if (retval != ERROR_OK)
+ return retval;
}
- case 4: {
+ break;
+
+ case 4:
+ {
/* stream word data through DCC directly to memory */
/* increment: STC p14,c5,[R0],#4 */
/* no increment: STC p14,c5,[R0]*/
@@ -1164,34 +1159,34 @@ static int arm11_examine(struct target *target)
/* assume the manufacturer id is ok; check the part # */
switch ((device_id >> 12) & 0xFFFF) {
- case 0x7B36:
- type = "ARM1136";
- break;
- case 0x7B37:
- type = "ARM11 MPCore";
- break;
- case 0x7B56:
- type = "ARM1156";
- break;
- case 0x7B76:
- arm11->arm.core_type = ARM_CORE_TYPE_SEC_EXT;
- /* NOTE: could default arm11->hardware_step to true */
- type = "ARM1176";
- break;
- default:
- LOG_ERROR("unexpected ARM11 ID code");
- return ERROR_FAIL;
+ case 0x7B36:
+ type = "ARM1136";
+ break;
+ case 0x7B37:
+ type = "ARM11 MPCore";
+ break;
+ case 0x7B56:
+ type = "ARM1156";
+ break;
+ case 0x7B76:
+ arm11->arm.core_type = ARM_CORE_TYPE_SEC_EXT;
+ /* NOTE: could default arm11->hardware_step to true */
+ type = "ARM1176";
+ break;
+ default:
+ LOG_ERROR("unexpected ARM11 ID code");
+ return ERROR_FAIL;
}
LOG_INFO("found %s", type);
/* unlikely this could ever fail, but ... */
switch ((didr >> 16) & 0x0F) {
- case ARM11_DEBUG_V6:
- case ARM11_DEBUG_V61: /* supports security extensions */
- break;
- default:
- LOG_ERROR("Only ARM v6 and v6.1 debug supported.");
- return ERROR_FAIL;
+ case ARM11_DEBUG_V6:
+ case ARM11_DEBUG_V61: /* supports security extensions */
+ break;
+ default:
+ LOG_ERROR("Only ARM v6 and v6.1 debug supported.");
+ return ERROR_FAIL;
}
arm11->brp = ((didr >> 24) & 0x0F) + 1;
@@ -1255,16 +1250,16 @@ COMMAND_HANDLER(arm11_handle_vcr)
struct arm11_common *arm11 = target_to_arm11(target);
switch (CMD_ARGC) {
- case 0:
- break;
- case 1:
- COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], arm11->vcr);
- break;
- default:
- return ERROR_COMMAND_SYNTAX_ERROR;
+ case 0:
+ break;
+ case 1:
+ COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], arm11->vcr);
+ break;
+ default:
+ return ERROR_COMMAND_SYNTAX_ERROR;
}
- LOG_INFO("VCR 0x%08" PRIx32 "", arm11->vcr);
+ LOG_INFO("VCR 0x%08" PRIx32, arm11->vcr);
return ERROR_OK;
}
diff --git a/src/target/arm11_dbgtap.c b/src/target/arm11_dbgtap.c
index 4c7211365b..4c2fedaeb2 100644
--- a/src/target/arm11_dbgtap.c
+++ b/src/target/arm11_dbgtap.c
@@ -85,30 +85,30 @@ static const char *arm11_ir_to_string(uint8_t ir)
const char *s = "unknown";
switch (ir) {
- case ARM11_EXTEST:
- s = "EXTEST";
- break;
- case ARM11_SCAN_N:
- s = "SCAN_N";
- break;
- case ARM11_RESTART:
- s = "RESTART";
- break;
- case ARM11_HALT:
- s = "HALT";
- break;
- case ARM11_INTEST:
- s = "INTEST";
- break;
- case ARM11_ITRSEL:
- s = "ITRSEL";
- break;
- case ARM11_IDCODE:
- s = "IDCODE";
- break;
- case ARM11_BYPASS:
- s = "BYPASS";
- break;
+ case ARM11_EXTEST:
+ s = "EXTEST";
+ break;
+ case ARM11_SCAN_N:
+ s = "SCAN_N";
+ break;
+ case ARM11_RESTART:
+ s = "RESTART";
+ break;
+ case ARM11_HALT:
+ s = "HALT";
+ break;
+ case ARM11_INTEST:
+ s = "INTEST";
+ break;
+ case ARM11_ITRSEL:
+ s = "ITRSEL";
+ break;
+ case ARM11_IDCODE:
+ s = "IDCODE";
+ break;
+ case ARM11_BYPASS:
+ s = "BYPASS";
+ break;
}
return s;
}
@@ -1061,17 +1061,17 @@ static int arm11_bpwp_enable(struct arm_dpm *dpm, unsigned int index_t,
action[1].value = control;
switch (index_t) {
- case 0 ... 15:
- action[0].address = ARM11_SC7_BVR0 + index_t;
- action[1].address = ARM11_SC7_BCR0 + index_t;
- break;
- case 16 ... 32:
- index_t -= 16;
- action[0].address = ARM11_SC7_WVR0 + index_t;
- action[1].address = ARM11_SC7_WCR0 + index_t;
- break;
- default:
- return ERROR_FAIL;
+ case 0 ... 15:
+ action[0].address = ARM11_SC7_BVR0 + index_t;
+ action[1].address = ARM11_SC7_BCR0 + index_t;
+ break;
+ case 16 ... 32:
+ index_t -= 16;
+ action[0].address = ARM11_SC7_WVR0 + index_t;
+ action[1].address = ARM11_SC7_WCR0 + index_t;
+ break;
+ default:
+ return ERROR_FAIL;
}
arm11->bpwp_n += 2;
@@ -1090,15 +1090,15 @@ static int arm11_bpwp_disable(struct arm_dpm *dpm, unsigned int index_t)
action[0].value = 0;
switch (index_t) {
- case 0 ... 15:
- action[0].address = ARM11_SC7_BCR0 + index_t;
- break;
- case 16 ... 32:
- index_t -= 16;
- action[0].address = ARM11_SC7_WCR0 + index_t;
- break;
- default:
- return ERROR_FAIL;
+ case 0 ... 15:
+ action[0].address = ARM11_SC7_BCR0 + index_t;
+ break;
+ case 16 ... 32:
+ index_t -= 16;
+ action[0].address = ARM11_SC7_WCR0 + index_t;
+ break;
+ default:
+ return ERROR_FAIL;
}
arm11->bpwp_n += 1;
diff --git a/src/target/arm720t.c b/src/target/arm720t.c
index d1433dde72..3f7686fb74 100644
--- a/src/target/arm720t.c
+++ b/src/target/arm720t.c
@@ -14,6 +14,7 @@
#include "arm720t.h"
#include
+#include
#include "target_type.h"
#include "register.h"
#include "arm_opcodes.h"
@@ -196,11 +197,12 @@ static int arm720t_post_debug_entry(struct target *target)
retval = jtag_execute_queue();
if (retval != ERROR_OK)
return retval;
- LOG_DEBUG("cp15_control_reg: %8.8" PRIx32 "", arm720t->cp15_control_reg);
+ LOG_DEBUG("cp15_control_reg: %8.8" PRIx32, arm720t->cp15_control_reg);
- arm720t->armv4_5_mmu.mmu_enabled = (arm720t->cp15_control_reg & 0x1U) ? 1 : 0;
- arm720t->armv4_5_mmu.armv4_5_cache.d_u_cache_enabled = (arm720t->cp15_control_reg & 0x4U) ? 1 : 0;
- arm720t->armv4_5_mmu.armv4_5_cache.i_cache_enabled = 0;
+ arm720t->armv4_5_mmu.mmu_enabled = arm720t->cp15_control_reg & 0x1U;
+ arm720t->armv4_5_mmu.armv4_5_cache.d_u_cache_enabled =
+ arm720t->cp15_control_reg & 0x4U;
+ arm720t->armv4_5_mmu.armv4_5_cache.i_cache_enabled = false;
/* save i/d fault status and address register */
retval = arm720t_read_cp15(target, 0xee150f10, &arm720t->fsr_reg);
@@ -226,19 +228,15 @@ static int arm720t_arch_state(struct target *target)
{
struct arm720t_common *arm720t = target_to_arm720(target);
- static const char *state[] = {
- "disabled", "enabled"
- };
-
arm_arch_state(target);
LOG_USER("MMU: %s, Cache: %s",
- state[arm720t->armv4_5_mmu.mmu_enabled],
- state[arm720t->armv4_5_mmu.armv4_5_cache.d_u_cache_enabled]);
+ str_enabled_disabled(arm720t->armv4_5_mmu.mmu_enabled),
+ str_enabled_disabled(arm720t->armv4_5_mmu.armv4_5_cache.d_u_cache_enabled));
return ERROR_OK;
}
-static int arm720_mmu(struct target *target, int *enabled)
+static int arm720_mmu(struct target *target, bool *enabled)
{
if (target->state != TARGET_HALTED) {
LOG_TARGET_ERROR(target, "not halted");
@@ -325,7 +323,7 @@ static int arm720t_soft_reset_halt(struct target *target)
return retval;
} else
break;
- if (debug_level >= 3)
+ if (LOG_LEVEL_IS(LOG_LVL_DEBUG))
alive_sleep(100);
else
keep_alive();
@@ -354,9 +352,9 @@ static int arm720t_soft_reset_halt(struct target *target)
retval = arm720t_disable_mmu_caches(target, 1, 1, 1);
if (retval != ERROR_OK)
return retval;
- arm720t->armv4_5_mmu.mmu_enabled = 0;
- arm720t->armv4_5_mmu.armv4_5_cache.d_u_cache_enabled = 0;
- arm720t->armv4_5_mmu.armv4_5_cache.i_cache_enabled = 0;
+ arm720t->armv4_5_mmu.mmu_enabled = false;
+ arm720t->armv4_5_mmu.armv4_5_cache.d_u_cache_enabled = false;
+ arm720t->armv4_5_mmu.armv4_5_cache.i_cache_enabled = false;
retval = target_call_event_callbacks(target, TARGET_EVENT_HALTED);
if (retval != ERROR_OK)
@@ -407,7 +405,7 @@ static int arm720t_init_arch_info(struct target *target,
arm720t->armv4_5_mmu.disable_mmu_caches = arm720t_disable_mmu_caches;
arm720t->armv4_5_mmu.enable_mmu_caches = arm720t_enable_mmu_caches;
arm720t->armv4_5_mmu.has_tiny_pages = 0;
- arm720t->armv4_5_mmu.mmu_enabled = 0;
+ arm720t->armv4_5_mmu.mmu_enabled = false;
return ERROR_OK;
}
diff --git a/src/target/arm7_9_common.c b/src/target/arm7_9_common.c
index 5550fb1e24..06e76ac0d2 100644
--- a/src/target/arm7_9_common.c
+++ b/src/target/arm7_9_common.c
@@ -637,13 +637,13 @@ int arm7_9_execute_sys_speed(struct target *target)
if ((buf_get_u32(dbg_stat->value, EICE_DBG_STATUS_DBGACK, 1))
&& (buf_get_u32(dbg_stat->value, EICE_DBG_STATUS_SYSCOMP, 1)))
break;
- if (debug_level >= 3)
+ if (LOG_LEVEL_IS(LOG_LVL_DEBUG))
alive_sleep(100);
else
keep_alive();
}
if (timeout) {
- LOG_ERROR("timeout waiting for SYSCOMP & DBGACK, last DBG_STATUS: %" PRIx32 "",
+ LOG_ERROR("timeout waiting for SYSCOMP & DBGACK, last DBG_STATUS: %" PRIx32,
buf_get_u32(dbg_stat->value, 0, dbg_stat->size));
return ERROR_TARGET_TIMEOUT;
}
@@ -1088,7 +1088,7 @@ int arm7_9_soft_reset_halt(struct target *target)
retval = jtag_execute_queue();
if (retval != ERROR_OK)
return retval;
- if (debug_level >= 3)
+ if (LOG_LEVEL_IS(LOG_LVL_DEBUG))
alive_sleep(100);
else
keep_alive();
@@ -1332,7 +1332,7 @@ static int arm7_9_debug_entry(struct target *target)
for (i = 0; i <= 15; i++) {
struct reg *r = arm_reg_current(arm, i);
- LOG_DEBUG("r%i: 0x%8.8" PRIx32 "", i, context[i]);
+ LOG_DEBUG("r%i: 0x%8.8" PRIx32, i, context[i]);
buf_set_u32(r->value, 0, 32, context[i]);
/* r0 and r15 (pc) have to be restored later */
@@ -1340,7 +1340,7 @@ static int arm7_9_debug_entry(struct target *target)
r->valid = true;
}
- LOG_DEBUG("entered debug state at PC 0x%" PRIx32 "", context[15]);
+ LOG_DEBUG("entered debug state at PC 0x%" PRIx32, context[15]);
/* exceptions other than USR & SYS have a saved program status register */
if (arm->spsr) {
@@ -1594,7 +1594,7 @@ static int arm7_9_restore_context(struct target *target)
struct arm_reg *reg_arch_info;
reg_arch_info = reg->arch_info;
if ((reg->dirty) && (reg_arch_info->mode != ARM_MODE_ANY)) {
- LOG_DEBUG("writing SPSR of mode %i with value 0x%8.8" PRIx32 "",
+ LOG_DEBUG("writing SPSR of mode %i with value 0x%8.8" PRIx32,
i,
buf_get_u32(reg->value, 0, 32));
arm7_9->write_xpsr(target, buf_get_u32(reg->value, 0, 32), 1);
@@ -1744,7 +1744,7 @@ int arm7_9_resume(struct target *target,
uint32_t current_opcode;
target_read_u32(target, current_pc, ¤t_opcode);
LOG_ERROR(
- "Couldn't calculate PC of next instruction, current opcode was 0x%8.8" PRIx32 "",
+ "Couldn't calculate PC of next instruction, current opcode was 0x%8.8" PRIx32,
current_opcode);
return retval;
}
@@ -1789,7 +1789,7 @@ int arm7_9_resume(struct target *target,
LOG_DEBUG("new PC after step: 0x%8.8" PRIx32,
buf_get_u32(arm->pc->value, 0, 32));
- LOG_DEBUG("set breakpoint at 0x%8.8" TARGET_PRIxADDR "", breakpoint->address);
+ LOG_DEBUG("set breakpoint at 0x%8.8" TARGET_PRIxADDR, breakpoint->address);
retval = arm7_9_set_breakpoint(target, breakpoint);
if (retval != ERROR_OK)
return retval;
@@ -1937,7 +1937,7 @@ int arm7_9_step(struct target *target, bool current, target_addr_t address,
uint32_t current_opcode;
target_read_u32(target, current_pc, ¤t_opcode);
LOG_ERROR(
- "Couldn't calculate PC of next instruction, current opcode was 0x%8.8" PRIx32 "",
+ "Couldn't calculate PC of next instruction, current opcode was 0x%8.8" PRIx32,
current_opcode);
return retval;
}
@@ -2116,7 +2116,7 @@ int arm7_9_read_memory(struct target *target,
int retval;
int last_reg = 0;
- LOG_DEBUG("address: 0x%8.8" TARGET_PRIxADDR ", size: 0x%8.8" PRIx32 ", count: 0x%8.8" PRIx32 "",
+ LOG_DEBUG("address: 0x%8.8" TARGET_PRIxADDR ", size: 0x%8.8" PRIx32 ", count: 0x%8.8" PRIx32,
address, size, count);
if (target->state != TARGET_HALTED) {
@@ -2135,21 +2135,49 @@ int arm7_9_read_memory(struct target *target,
reg[0] = address;
arm7_9->write_core_regs(target, 0x1, reg);
- int j = 0;
-
switch (size) {
- case 4:
- while (num_accesses < count) {
- uint32_t reg_list;
- thisrun_accesses =
- ((count - num_accesses) >= 14) ? 14 : (count - num_accesses);
- reg_list = (0xffff >> (15 - thisrun_accesses)) & 0xfffe;
+ case 4:
+ while (num_accesses < count) {
+ uint32_t reg_list;
+ thisrun_accesses =
+ ((count - num_accesses) >= 14) ? 14 : (count - num_accesses);
+ reg_list = (0xffff >> (15 - thisrun_accesses)) & 0xfffe;
+
+ if (last_reg <= thisrun_accesses)
+ last_reg = thisrun_accesses;
+
+ arm7_9->load_word_regs(target, reg_list);
+
+ /* fast memory reads are only safe when the target is running
+ * from a sufficiently high clock (32 kHz is usually too slow)
+ */
+ if (arm7_9->fast_memory_access)
+ retval = arm7_9_execute_fast_sys_speed(target);
+ else
+ retval = arm7_9_execute_sys_speed(target);
+ if (retval != ERROR_OK)
+ return retval;
- if (last_reg <= thisrun_accesses)
- last_reg = thisrun_accesses;
+ arm7_9->read_core_regs_target_buffer(target, reg_list, buffer, 4);
- arm7_9->load_word_regs(target, reg_list);
+ /* advance buffer, count number of accesses */
+ buffer += thisrun_accesses * 4;
+ num_accesses += thisrun_accesses;
+ keep_alive();
+ }
+ break;
+ case 2:
+ while (num_accesses < count) {
+ uint32_t reg_list;
+ thisrun_accesses =
+ ((count - num_accesses) >= 14) ? 14 : (count - num_accesses);
+ reg_list = (0xffff >> (15 - thisrun_accesses)) & 0xfffe;
+
+ for (i = 1; i <= thisrun_accesses; i++) {
+ if (i > last_reg)
+ last_reg = i;
+ arm7_9->load_hword_reg(target, i);
/* fast memory reads are only safe when the target is running
* from a sufficiently high clock (32 kHz is usually too slow)
*/
@@ -2160,81 +2188,48 @@ int arm7_9_read_memory(struct target *target,
if (retval != ERROR_OK)
return retval;
- arm7_9->read_core_regs_target_buffer(target, reg_list, buffer, 4);
-
- /* advance buffer, count number of accesses */
- buffer += thisrun_accesses * 4;
- num_accesses += thisrun_accesses;
-
- if ((j++%1024) == 0)
- keep_alive();
}
- break;
- case 2:
- while (num_accesses < count) {
- uint32_t reg_list;
- thisrun_accesses =
- ((count - num_accesses) >= 14) ? 14 : (count - num_accesses);
- reg_list = (0xffff >> (15 - thisrun_accesses)) & 0xfffe;
-
- for (i = 1; i <= thisrun_accesses; i++) {
- if (i > last_reg)
- last_reg = i;
- arm7_9->load_hword_reg(target, i);
- /* fast memory reads are only safe when the target is running
- * from a sufficiently high clock (32 kHz is usually too slow)
- */
- if (arm7_9->fast_memory_access)
- retval = arm7_9_execute_fast_sys_speed(target);
- else
- retval = arm7_9_execute_sys_speed(target);
- if (retval != ERROR_OK)
- return retval;
-
- }
- arm7_9->read_core_regs_target_buffer(target, reg_list, buffer, 2);
+ arm7_9->read_core_regs_target_buffer(target, reg_list, buffer, 2);
- /* advance buffer, count number of accesses */
- buffer += thisrun_accesses * 2;
- num_accesses += thisrun_accesses;
+ /* advance buffer, count number of accesses */
+ buffer += thisrun_accesses * 2;
+ num_accesses += thisrun_accesses;
- if ((j++%1024) == 0)
- keep_alive();
+ keep_alive();
+ }
+ break;
+ case 1:
+ while (num_accesses < count) {
+ uint32_t reg_list;
+ thisrun_accesses =
+ ((count - num_accesses) >= 14) ? 14 : (count - num_accesses);
+ reg_list = (0xffff >> (15 - thisrun_accesses)) & 0xfffe;
+
+ for (i = 1; i <= thisrun_accesses; i++) {
+ if (i > last_reg)
+ last_reg = i;
+ arm7_9->load_byte_reg(target, i);
+ /* fast memory reads are only safe when the target is running
+ * from a sufficiently high clock (32 kHz is usually too slow)
+ */
+ if (arm7_9->fast_memory_access)
+ retval = arm7_9_execute_fast_sys_speed(target);
+ else
+ retval = arm7_9_execute_sys_speed(target);
+ if (retval != ERROR_OK)
+ return retval;
}
- break;
- case 1:
- while (num_accesses < count) {
- uint32_t reg_list;
- thisrun_accesses =
- ((count - num_accesses) >= 14) ? 14 : (count - num_accesses);
- reg_list = (0xffff >> (15 - thisrun_accesses)) & 0xfffe;
-
- for (i = 1; i <= thisrun_accesses; i++) {
- if (i > last_reg)
- last_reg = i;
- arm7_9->load_byte_reg(target, i);
- /* fast memory reads are only safe when the target is running
- * from a sufficiently high clock (32 kHz is usually too slow)
- */
- if (arm7_9->fast_memory_access)
- retval = arm7_9_execute_fast_sys_speed(target);
- else
- retval = arm7_9_execute_sys_speed(target);
- if (retval != ERROR_OK)
- return retval;
- }
- arm7_9->read_core_regs_target_buffer(target, reg_list, buffer, 1);
+ arm7_9->read_core_regs_target_buffer(target, reg_list, buffer, 1);
- /* advance buffer, count number of accesses */
- buffer += thisrun_accesses * 1;
- num_accesses += thisrun_accesses;
+ /* advance buffer, count number of accesses */
+ buffer += thisrun_accesses * 1;
+ num_accesses += thisrun_accesses;
- if ((j++%1024) == 0)
- keep_alive();
- }
- break;
+ keep_alive();
+ }
+ break;
}
if (!is_arm_mode(arm->core_mode))
@@ -2313,30 +2308,74 @@ int arm7_9_write_memory(struct target *target,
embeddedice_store_reg(dbg_ctrl);
switch (size) {
- case 4:
- while (num_accesses < count) {
- uint32_t reg_list;
- thisrun_accesses =
- ((count - num_accesses) >= 14) ? 14 : (count - num_accesses);
- reg_list = (0xffff >> (15 - thisrun_accesses)) & 0xfffe;
-
- for (i = 1; i <= thisrun_accesses; i++) {
- if (i > last_reg)
- last_reg = i;
- reg[i] = target_buffer_get_u32(target, buffer);
- buffer += 4;
- }
+ case 4:
+ while (num_accesses < count) {
+ uint32_t reg_list;
+ thisrun_accesses =
+ ((count - num_accesses) >= 14) ? 14 : (count - num_accesses);
+ reg_list = (0xffff >> (15 - thisrun_accesses)) & 0xfffe;
+
+ for (i = 1; i <= thisrun_accesses; i++) {
+ if (i > last_reg)
+ last_reg = i;
+ reg[i] = target_buffer_get_u32(target, buffer);
+ buffer += 4;
+ }
+
+ arm7_9->write_core_regs(target, reg_list, reg);
+
+ arm7_9->store_word_regs(target, reg_list);
+
+ /* fast memory writes are only safe when the target is running
+ * from a sufficiently high clock (32 kHz is usually too slow)
+ */
+ if (arm7_9->fast_memory_access) {
+ retval = arm7_9_execute_fast_sys_speed(target);
+ } else {
+ retval = arm7_9_execute_sys_speed(target);
+
+ /*
+ * if memory writes are made when the clock is running slow
+ * (i.e. 32 kHz) which is necessary in some scripts to reconfigure
+ * processor operations after a "reset halt" or "reset init",
+ * need to immediately stroke the keep alive or will end up with
+ * gdb "keep alive not sent error message" problem.
+ */
+
+ keep_alive();
+ }
+
+ if (retval != ERROR_OK)
+ return retval;
+
+ num_accesses += thisrun_accesses;
+ }
+ break;
+ case 2:
+ while (num_accesses < count) {
+ uint32_t reg_list;
+ thisrun_accesses =
+ ((count - num_accesses) >= 14) ? 14 : (count - num_accesses);
+ reg_list = (0xffff >> (15 - thisrun_accesses)) & 0xfffe;
+
+ for (i = 1; i <= thisrun_accesses; i++) {
+ if (i > last_reg)
+ last_reg = i;
+ reg[i] = target_buffer_get_u16(target, buffer) & 0xffff;
+ buffer += 2;
+ }
- arm7_9->write_core_regs(target, reg_list, reg);
+ arm7_9->write_core_regs(target, reg_list, reg);
- arm7_9->store_word_regs(target, reg_list);
+ for (i = 1; i <= thisrun_accesses; i++) {
+ arm7_9->store_hword_reg(target, i);
/* fast memory writes are only safe when the target is running
* from a sufficiently high clock (32 kHz is usually too slow)
*/
- if (arm7_9->fast_memory_access)
+ if (arm7_9->fast_memory_access) {
retval = arm7_9_execute_fast_sys_speed(target);
- else {
+ } else {
retval = arm7_9_execute_sys_speed(target);
/*
@@ -2352,99 +2391,55 @@ int arm7_9_write_memory(struct target *target,
if (retval != ERROR_OK)
return retval;
+ }
- num_accesses += thisrun_accesses;
+ num_accesses += thisrun_accesses;
+ }
+ break;
+ case 1:
+ while (num_accesses < count) {
+ uint32_t reg_list;
+ thisrun_accesses =
+ ((count - num_accesses) >= 14) ? 14 : (count - num_accesses);
+ reg_list = (0xffff >> (15 - thisrun_accesses)) & 0xfffe;
+
+ for (i = 1; i <= thisrun_accesses; i++) {
+ if (i > last_reg)
+ last_reg = i;
+ reg[i] = *buffer++ & 0xff;
}
- break;
- case 2:
- while (num_accesses < count) {
- uint32_t reg_list;
- thisrun_accesses =
- ((count - num_accesses) >= 14) ? 14 : (count - num_accesses);
- reg_list = (0xffff >> (15 - thisrun_accesses)) & 0xfffe;
-
- for (i = 1; i <= thisrun_accesses; i++) {
- if (i > last_reg)
- last_reg = i;
- reg[i] = target_buffer_get_u16(target, buffer) & 0xffff;
- buffer += 2;
- }
- arm7_9->write_core_regs(target, reg_list, reg);
+ arm7_9->write_core_regs(target, reg_list, reg);
- for (i = 1; i <= thisrun_accesses; i++) {
- arm7_9->store_hword_reg(target, i);
+ for (i = 1; i <= thisrun_accesses; i++) {
+ arm7_9->store_byte_reg(target, i);
+ /* fast memory writes are only safe when the target is running
+ * from a sufficiently high clock (32 kHz is usually too slow)
+ */
+ if (arm7_9->fast_memory_access) {
+ retval = arm7_9_execute_fast_sys_speed(target);
+ } else {
+ retval = arm7_9_execute_sys_speed(target);
- /* fast memory writes are only safe when the target is running
- * from a sufficiently high clock (32 kHz is usually too slow)
+ /*
+ * if memory writes are made when the clock is running slow
+ * (i.e. 32 kHz) which is necessary in some scripts to reconfigure
+ * processor operations after a "reset halt" or "reset init",
+ * need to immediately stroke the keep alive or will end up with
+ * gdb "keep alive not sent error message" problem.
*/
- if (arm7_9->fast_memory_access)
- retval = arm7_9_execute_fast_sys_speed(target);
- else {
- retval = arm7_9_execute_sys_speed(target);
-
- /*
- * if memory writes are made when the clock is running slow
- * (i.e. 32 kHz) which is necessary in some scripts to reconfigure
- * processor operations after a "reset halt" or "reset init",
- * need to immediately stroke the keep alive or will end up with
- * gdb "keep alive not sent error message" problem.
- */
-
- keep_alive();
- }
-
- if (retval != ERROR_OK)
- return retval;
- }
- num_accesses += thisrun_accesses;
- }
- break;
- case 1:
- while (num_accesses < count) {
- uint32_t reg_list;
- thisrun_accesses =
- ((count - num_accesses) >= 14) ? 14 : (count - num_accesses);
- reg_list = (0xffff >> (15 - thisrun_accesses)) & 0xfffe;
-
- for (i = 1; i <= thisrun_accesses; i++) {
- if (i > last_reg)
- last_reg = i;
- reg[i] = *buffer++ & 0xff;
+ keep_alive();
}
- arm7_9->write_core_regs(target, reg_list, reg);
-
- for (i = 1; i <= thisrun_accesses; i++) {
- arm7_9->store_byte_reg(target, i);
- /* fast memory writes are only safe when the target is running
- * from a sufficiently high clock (32 kHz is usually too slow)
- */
- if (arm7_9->fast_memory_access)
- retval = arm7_9_execute_fast_sys_speed(target);
- else {
- retval = arm7_9_execute_sys_speed(target);
-
- /*
- * if memory writes are made when the clock is running slow
- * (i.e. 32 kHz) which is necessary in some scripts to reconfigure
- * processor operations after a "reset halt" or "reset init",
- * need to immediately stroke the keep alive or will end up with
- * gdb "keep alive not sent error message" problem.
- */
-
- keep_alive();
- }
-
- if (retval != ERROR_OK)
- return retval;
-
- }
+ if (retval != ERROR_OK)
+ return retval;
- num_accesses += thisrun_accesses;
}
- break;
+
+ num_accesses += thisrun_accesses;
+ }
+ break;
}
/* Re-Set DBGACK */
@@ -2641,7 +2636,7 @@ int arm7_9_bulk_write_memory(struct target *target,
uint32_t endaddress = buf_get_u32(reg_params[0].value, 0, 32);
if (endaddress != (address + count*4)) {
LOG_ERROR(
- "DCC write failed, expected end address 0x%08" TARGET_PRIxADDR " got 0x%0" PRIx32 "",
+ "DCC write failed, expected end address 0x%08" TARGET_PRIxADDR " got 0x%0" PRIx32,
(address + count*4),
endaddress);
retval = ERROR_FAIL;
diff --git a/src/target/arm7tdmi.c b/src/target/arm7tdmi.c
index 2f59254afd..fea6a3ff2a 100644
--- a/src/target/arm7tdmi.c
+++ b/src/target/arm7tdmi.c
@@ -327,15 +327,15 @@ static void arm7tdmi_read_core_regs_target_buffer(struct target *target,
/* nothing fetched, STM still in EXECUTE (1 + i cycle), read databus */
if (mask & (1 << i)) {
switch (size) {
- case 4:
- arm7tdmi_clock_data_in_endianness(jtag_info, buf_u32++, 4, be);
- break;
- case 2:
- arm7tdmi_clock_data_in_endianness(jtag_info, buf_u16++, 2, be);
- break;
- case 1:
- arm7tdmi_clock_data_in_endianness(jtag_info, buf_u8++, 1, be);
- break;
+ case 4:
+ arm7tdmi_clock_data_in_endianness(jtag_info, buf_u32++, 4, be);
+ break;
+ case 2:
+ arm7tdmi_clock_data_in_endianness(jtag_info, buf_u16++, 2, be);
+ break;
+ case 1:
+ arm7tdmi_clock_data_in_endianness(jtag_info, buf_u8++, 1, be);
+ break;
}
}
}
diff --git a/src/target/arm920t.c b/src/target/arm920t.c
index 95cfd7ceb2..441e423054 100644
--- a/src/target/arm920t.c
+++ b/src/target/arm920t.c
@@ -12,6 +12,7 @@
#include "arm920t.h"
#include
+#include
#include "target_type.h"
#include "register.h"
#include "arm_opcodes.h"
@@ -425,12 +426,11 @@ int arm920t_post_debug_entry(struct target *target)
&arm920t->armv4_5_mmu.armv4_5_cache);
}
- arm920t->armv4_5_mmu.mmu_enabled =
- (arm920t->cp15_control_reg & 0x1U) ? 1 : 0;
+ arm920t->armv4_5_mmu.mmu_enabled = arm920t->cp15_control_reg & 0x1U;
arm920t->armv4_5_mmu.armv4_5_cache.d_u_cache_enabled =
- (arm920t->cp15_control_reg & 0x4U) ? 1 : 0;
+ arm920t->cp15_control_reg & 0x4U;
arm920t->armv4_5_mmu.armv4_5_cache.i_cache_enabled =
- (arm920t->cp15_control_reg & 0x1000U) ? 1 : 0;
+ arm920t->cp15_control_reg & 0x1000U;
/* save i/d fault status and address register
* FIXME use opcode macros */
@@ -510,10 +510,6 @@ static int arm920t_verify_pointer(struct command_invocation *cmd,
/** Logs summary of ARM920 state for a halted target. */
int arm920t_arch_state(struct target *target)
{
- static const char *state[] = {
- "disabled", "enabled"
- };
-
struct arm920t_common *arm920t = target_to_arm920(target);
if (arm920t->common_magic != ARM920T_COMMON_MAGIC) {
@@ -523,14 +519,14 @@ int arm920t_arch_state(struct target *target)
arm_arch_state(target);
LOG_USER("MMU: %s, D-Cache: %s, I-Cache: %s",
- state[arm920t->armv4_5_mmu.mmu_enabled],
- state[arm920t->armv4_5_mmu.armv4_5_cache.d_u_cache_enabled],
- state[arm920t->armv4_5_mmu.armv4_5_cache.i_cache_enabled]);
+ str_enabled_disabled(arm920t->armv4_5_mmu.mmu_enabled),
+ str_enabled_disabled(arm920t->armv4_5_mmu.armv4_5_cache.d_u_cache_enabled),
+ str_enabled_disabled(arm920t->armv4_5_mmu.armv4_5_cache.i_cache_enabled));
return ERROR_OK;
}
-static int arm920_mmu(struct target *target, int *enabled)
+static int arm920_mmu(struct target *target, bool *enabled)
{
if (target->state != TARGET_HALTED) {
LOG_TARGET_ERROR(target, "not halted");
@@ -750,7 +746,7 @@ int arm920t_soft_reset_halt(struct target *target)
return retval;
} else
break;
- if (debug_level >= 3) {
+ if (LOG_LEVEL_IS(LOG_LVL_DEBUG)) {
/* do not eat all CPU, time out after 1 se*/
alive_sleep(100);
} else
@@ -778,9 +774,9 @@ int arm920t_soft_reset_halt(struct target *target)
arm->pc->valid = true;
arm920t_disable_mmu_caches(target, 1, 1, 1);
- arm920t->armv4_5_mmu.mmu_enabled = 0;
- arm920t->armv4_5_mmu.armv4_5_cache.d_u_cache_enabled = 0;
- arm920t->armv4_5_mmu.armv4_5_cache.i_cache_enabled = 0;
+ arm920t->armv4_5_mmu.mmu_enabled = false;
+ arm920t->armv4_5_mmu.armv4_5_cache.d_u_cache_enabled = false;
+ arm920t->armv4_5_mmu.armv4_5_cache.i_cache_enabled = false;
return target_call_event_callbacks(target, TARGET_EVENT_HALTED);
}
@@ -819,7 +815,7 @@ static int arm920t_init_arch_info(struct target *target,
arm920t->armv4_5_mmu.disable_mmu_caches = arm920t_disable_mmu_caches;
arm920t->armv4_5_mmu.enable_mmu_caches = arm920t_enable_mmu_caches;
arm920t->armv4_5_mmu.has_tiny_pages = 1;
- arm920t->armv4_5_mmu.mmu_enabled = 0;
+ arm920t->armv4_5_mmu.mmu_enabled = false;
/* disabling linefills leads to lockups, so keep them enabled for now
* this doesn't affect correctness, but might affect timing issues, if
diff --git a/src/target/arm926ejs.c b/src/target/arm926ejs.c
index 0531106562..98fe6bf68d 100644
--- a/src/target/arm926ejs.c
+++ b/src/target/arm926ejs.c
@@ -14,6 +14,7 @@
#include "arm926ejs.h"
#include
+#include
#include "target_type.h"
#include "register.h"
#include "arm_opcodes.h"
@@ -220,88 +221,88 @@ static int arm926ejs_examine_debug_reason(struct target *target)
debug_reason = buf_get_u32(dbg_stat->value, 6, 4);
switch (debug_reason) {
- case 0:
- LOG_DEBUG("no *NEW* debug entry (?missed one?)");
- /* ... since last restart or debug reset ... */
- target->debug_reason = DBG_REASON_DBGRQ;
- break;
- case 1:
- LOG_DEBUG("breakpoint from EICE unit 0");
- target->debug_reason = DBG_REASON_BREAKPOINT;
- break;
- case 2:
- LOG_DEBUG("breakpoint from EICE unit 1");
- target->debug_reason = DBG_REASON_BREAKPOINT;
- break;
- case 3:
- LOG_DEBUG("soft breakpoint (BKPT instruction)");
- target->debug_reason = DBG_REASON_BREAKPOINT;
- break;
- case 4:
- LOG_DEBUG("vector catch breakpoint");
- target->debug_reason = DBG_REASON_BREAKPOINT;
- break;
- case 5:
- LOG_DEBUG("external breakpoint");
- target->debug_reason = DBG_REASON_BREAKPOINT;
- break;
- case 6:
- LOG_DEBUG("watchpoint from EICE unit 0");
- target->debug_reason = DBG_REASON_WATCHPOINT;
- break;
- case 7:
- LOG_DEBUG("watchpoint from EICE unit 1");
- target->debug_reason = DBG_REASON_WATCHPOINT;
- break;
- case 8:
- LOG_DEBUG("external watchpoint");
- target->debug_reason = DBG_REASON_WATCHPOINT;
- break;
- case 9:
- LOG_DEBUG("internal debug request");
- target->debug_reason = DBG_REASON_DBGRQ;
- break;
- case 10:
- LOG_DEBUG("external debug request");
- target->debug_reason = DBG_REASON_DBGRQ;
- break;
- case 11:
- LOG_DEBUG("debug re-entry from system speed access");
- /* This is normal when connecting to something that's
- * already halted, or in some related code paths, but
- * otherwise is surprising (and presumably wrong).
- */
- switch (target->debug_reason) {
- case DBG_REASON_DBGRQ:
- break;
- default:
- LOG_ERROR("unexpected -- debug re-entry");
- /* FALLTHROUGH */
- case DBG_REASON_UNDEFINED:
- target->debug_reason = DBG_REASON_DBGRQ;
- break;
- }
- break;
- case 12:
- /* FIX!!!! here be dragons!!! We need to fail here so
- * the target will interpreted as halted but we won't
- * try to talk to it right now... a resume + halt seems
- * to sync things up again. Please send an email to
- * openocd development mailing list if you have hardware
- * to donate to look into this problem....
- */
- LOG_WARNING("WARNING: mystery debug reason MOE = 0xc. Try issuing a resume + halt.");
- target->debug_reason = DBG_REASON_DBGRQ;
+ case 0:
+ LOG_DEBUG("no *NEW* debug entry (?missed one?)");
+ /* ... since last restart or debug reset ... */
+ target->debug_reason = DBG_REASON_DBGRQ;
+ break;
+ case 1:
+ LOG_DEBUG("breakpoint from EICE unit 0");
+ target->debug_reason = DBG_REASON_BREAKPOINT;
+ break;
+ case 2:
+ LOG_DEBUG("breakpoint from EICE unit 1");
+ target->debug_reason = DBG_REASON_BREAKPOINT;
+ break;
+ case 3:
+ LOG_DEBUG("soft breakpoint (BKPT instruction)");
+ target->debug_reason = DBG_REASON_BREAKPOINT;
+ break;
+ case 4:
+ LOG_DEBUG("vector catch breakpoint");
+ target->debug_reason = DBG_REASON_BREAKPOINT;
+ break;
+ case 5:
+ LOG_DEBUG("external breakpoint");
+ target->debug_reason = DBG_REASON_BREAKPOINT;
+ break;
+ case 6:
+ LOG_DEBUG("watchpoint from EICE unit 0");
+ target->debug_reason = DBG_REASON_WATCHPOINT;
+ break;
+ case 7:
+ LOG_DEBUG("watchpoint from EICE unit 1");
+ target->debug_reason = DBG_REASON_WATCHPOINT;
+ break;
+ case 8:
+ LOG_DEBUG("external watchpoint");
+ target->debug_reason = DBG_REASON_WATCHPOINT;
+ break;
+ case 9:
+ LOG_DEBUG("internal debug request");
+ target->debug_reason = DBG_REASON_DBGRQ;
+ break;
+ case 10:
+ LOG_DEBUG("external debug request");
+ target->debug_reason = DBG_REASON_DBGRQ;
+ break;
+ case 11:
+ LOG_DEBUG("debug re-entry from system speed access");
+ /* This is normal when connecting to something that's
+ * already halted, or in some related code paths, but
+ * otherwise is surprising (and presumably wrong).
+ */
+ switch (target->debug_reason) {
+ case DBG_REASON_DBGRQ:
break;
default:
- LOG_WARNING("WARNING: unknown debug reason: 0x%x", debug_reason);
- /* Oh agony! should we interpret this as a halt request or
- * that the target stopped on it's own accord?
- */
+ LOG_ERROR("unexpected -- debug re-entry");
+ /* FALLTHROUGH */
+ case DBG_REASON_UNDEFINED:
target->debug_reason = DBG_REASON_DBGRQ;
- /* if we fail here, we won't talk to the target and it will
- * be reported to be in the halted state */
break;
+ }
+ break;
+ case 12:
+ /* FIX!!!! here be dragons!!! We need to fail here so
+ * the target will interpreted as halted but we won't
+ * try to talk to it right now... a resume + halt seems
+ * to sync things up again. Please send an email to
+ * openocd development mailing list if you have hardware
+ * to donate to look into this problem....
+ */
+ LOG_WARNING("WARNING: mystery debug reason MOE = 0xc. Try issuing a resume + halt.");
+ target->debug_reason = DBG_REASON_DBGRQ;
+ break;
+ default:
+ LOG_WARNING("WARNING: unknown debug reason: 0x%x", debug_reason);
+ /* Oh agony! should we interpret this as a halt request or
+ * that the target stopped on it's own accord?
+ */
+ target->debug_reason = DBG_REASON_DBGRQ;
+ /* if we fail here, we won't talk to the target and it will
+ * be reported to be in the halted state */
+ break;
}
return ERROR_OK;
@@ -426,7 +427,7 @@ static int arm926ejs_post_debug_entry(struct target *target)
retval = jtag_execute_queue();
if (retval != ERROR_OK)
return retval;
- LOG_DEBUG("cp15_control_reg: %8.8" PRIx32 "", arm926ejs->cp15_control_reg);
+ LOG_DEBUG("cp15_control_reg: %8.8" PRIx32, arm926ejs->cp15_control_reg);
if (arm926ejs->armv4_5_mmu.armv4_5_cache.ctype == -1) {
uint32_t cache_type_reg;
@@ -440,9 +441,11 @@ static int arm926ejs_post_debug_entry(struct target *target)
armv4_5_identify_cache(cache_type_reg, &arm926ejs->armv4_5_mmu.armv4_5_cache);
}
- arm926ejs->armv4_5_mmu.mmu_enabled = (arm926ejs->cp15_control_reg & 0x1U) ? 1 : 0;
- arm926ejs->armv4_5_mmu.armv4_5_cache.d_u_cache_enabled = (arm926ejs->cp15_control_reg & 0x4U) ? 1 : 0;
- arm926ejs->armv4_5_mmu.armv4_5_cache.i_cache_enabled = (arm926ejs->cp15_control_reg & 0x1000U) ? 1 : 0;
+ arm926ejs->armv4_5_mmu.mmu_enabled = arm926ejs->cp15_control_reg & 0x1U;
+ arm926ejs->armv4_5_mmu.armv4_5_cache.d_u_cache_enabled =
+ arm926ejs->cp15_control_reg & 0x4U;
+ arm926ejs->armv4_5_mmu.armv4_5_cache.i_cache_enabled =
+ arm926ejs->cp15_control_reg & 0x1000U;
/* save i/d fault status and address register */
retval = arm926ejs->read_cp15(target, 0, 0, 5, 0, &arm926ejs->d_fsr);
@@ -455,7 +458,7 @@ static int arm926ejs_post_debug_entry(struct target *target)
if (retval != ERROR_OK)
return retval;
- LOG_DEBUG("D FSR: 0x%8.8" PRIx32 ", D FAR: 0x%8.8" PRIx32 ", I FSR: 0x%8.8" PRIx32 "",
+ LOG_DEBUG("D FSR: 0x%8.8" PRIx32 ", D FAR: 0x%8.8" PRIx32 ", I FSR: 0x%8.8" PRIx32,
arm926ejs->d_fsr, arm926ejs->d_far, arm926ejs->i_fsr);
uint32_t cache_dbg_ctrl;
@@ -503,10 +506,6 @@ static int arm926ejs_verify_pointer(struct command_invocation *cmd,
/** Logs summary of ARM926 state for a halted target. */
int arm926ejs_arch_state(struct target *target)
{
- static const char *state[] = {
- "disabled", "enabled"
- };
-
struct arm926ejs_common *arm926ejs = target_to_arm926(target);
if (arm926ejs->common_magic != ARM926EJS_COMMON_MAGIC) {
@@ -516,9 +515,9 @@ int arm926ejs_arch_state(struct target *target)
arm_arch_state(target);
LOG_USER("MMU: %s, D-Cache: %s, I-Cache: %s",
- state[arm926ejs->armv4_5_mmu.mmu_enabled],
- state[arm926ejs->armv4_5_mmu.armv4_5_cache.d_u_cache_enabled],
- state[arm926ejs->armv4_5_mmu.armv4_5_cache.i_cache_enabled]);
+ str_enabled_disabled(arm926ejs->armv4_5_mmu.mmu_enabled),
+ str_enabled_disabled(arm926ejs->armv4_5_mmu.armv4_5_cache.d_u_cache_enabled),
+ str_enabled_disabled(arm926ejs->armv4_5_mmu.armv4_5_cache.i_cache_enabled));
return ERROR_OK;
}
@@ -545,7 +544,7 @@ int arm926ejs_soft_reset_halt(struct target *target)
return retval;
} else
break;
- if (debug_level >= 1) {
+ if (LOG_LEVEL_IS(LOG_LVL_WARNING)) {
/* do not eat all CPU, time out after 1 se*/
alive_sleep(100);
} else
@@ -575,9 +574,9 @@ int arm926ejs_soft_reset_halt(struct target *target)
retval = arm926ejs_disable_mmu_caches(target, 1, 1, 1);
if (retval != ERROR_OK)
return retval;
- arm926ejs->armv4_5_mmu.mmu_enabled = 0;
- arm926ejs->armv4_5_mmu.armv4_5_cache.d_u_cache_enabled = 0;
- arm926ejs->armv4_5_mmu.armv4_5_cache.i_cache_enabled = 0;
+ arm926ejs->armv4_5_mmu.mmu_enabled = false;
+ arm926ejs->armv4_5_mmu.armv4_5_cache.d_u_cache_enabled = false;
+ arm926ejs->armv4_5_mmu.armv4_5_cache.i_cache_enabled = false;
return target_call_event_callbacks(target, TARGET_EVENT_HALTED);
}
@@ -689,7 +688,7 @@ int arm926ejs_init_arch_info(struct target *target, struct arm926ejs_common *arm
arm926ejs->armv4_5_mmu.disable_mmu_caches = arm926ejs_disable_mmu_caches;
arm926ejs->armv4_5_mmu.enable_mmu_caches = arm926ejs_enable_mmu_caches;
arm926ejs->armv4_5_mmu.has_tiny_pages = 1;
- arm926ejs->armv4_5_mmu.mmu_enabled = 0;
+ arm926ejs->armv4_5_mmu.mmu_enabled = false;
arm7_9->examine_debug_reason = arm926ejs_examine_debug_reason;
@@ -749,7 +748,7 @@ static int arm926ejs_virt2phys(struct target *target, target_addr_t virtual, tar
return ERROR_OK;
}
-static int arm926ejs_mmu(struct target *target, int *enabled)
+static int arm926ejs_mmu(struct target *target, bool *enabled)
{
struct arm926ejs_common *arm926ejs = target_to_arm926(target);
diff --git a/src/target/arm9tdmi.c b/src/target/arm9tdmi.c
index 8ab12de320..34b4ba2cea 100644
--- a/src/target/arm9tdmi.c
+++ b/src/target/arm9tdmi.c
@@ -398,15 +398,15 @@ static void arm9tdmi_read_core_regs_target_buffer(struct target *target,
if (mask & (1 << i))
/* nothing fetched, STM in MEMORY (i'th cycle) */
switch (size) {
- case 4:
- arm9tdmi_clock_data_in_endianness(jtag_info, buf_u32++, 4, be);
- break;
- case 2:
- arm9tdmi_clock_data_in_endianness(jtag_info, buf_u16++, 2, be);
- break;
- case 1:
- arm9tdmi_clock_data_in_endianness(jtag_info, buf_u8++, 1, be);
- break;
+ case 4:
+ arm9tdmi_clock_data_in_endianness(jtag_info, buf_u32++, 4, be);
+ break;
+ case 2:
+ arm9tdmi_clock_data_in_endianness(jtag_info, buf_u16++, 2, be);
+ break;
+ case 1:
+ arm9tdmi_clock_data_in_endianness(jtag_info, buf_u8++, 1, be);
+ break;
}
}
}
diff --git a/src/target/arm_adi_v5.c b/src/target/arm_adi_v5.c
index df897b80ed..67a3fcc577 100644
--- a/src/target/arm_adi_v5.c
+++ b/src/target/arm_adi_v5.c
@@ -50,8 +50,16 @@
/*
* Relevant specifications from ARM include:
*
- * ARM(tm) Debug Interface v5 Architecture Specification ARM IHI 0031F
+ * ARM(tm) Debug Interface v5 Architecture Specification ARM IHI 0031G
+ * https://developer.arm.com/documentation/ihi0031/latest/
+ *
* ARM(tm) Debug Interface v6 Architecture Specification ARM IHI 0074C
+ * https://developer.arm.com/documentation/ihi0074/latest/
+ *
+ * Note that diagrams B4-1 to B4-7 in both ADI specifications show
+ * SWCLK signal mostly in wrong polarity. See detailed SWD timing
+ * https://developer.arm.com/documentation/dui0499/b/arm-dstream-target-interface-connections/swd-timing-requirements
+ *
* CoreSight(tm) v1.0 Architecture Specification ARM IHI 0029B
*
* CoreSight(tm) DAP-Lite TRM, ARM DDI 0316D
diff --git a/src/target/arm_cti.c b/src/target/arm_cti.c
index b2f78eef78..032e5ac379 100644
--- a/src/target/arm_cti.c
+++ b/src/target/arm_cti.c
@@ -232,13 +232,13 @@ COMMAND_HANDLER(handle_cti_dump)
retval = dap_run(ap->dap);
if (retval != ERROR_OK)
- return JIM_ERR;
+ return retval;
for (size_t i = 0; i < ARRAY_SIZE(cti_names); i++)
command_print(CMD, "%8.8s (0x%04"PRIx32") 0x%08"PRIx32,
cti_names[i].label, cti_names[i].offset, values[i]);
- return JIM_OK;
+ return ERROR_OK;
}
COMMAND_HANDLER(handle_cti_enable)
@@ -434,49 +434,47 @@ static int cti_configure(struct jim_getopt_info *goi, struct arm_cti *cti)
return JIM_OK;
}
-static int cti_create(struct jim_getopt_info *goi)
+COMMAND_HANDLER(handle_cti_create)
{
- struct command_context *cmd_ctx;
- static struct arm_cti *cti;
- Jim_Obj *new_cmd;
- Jim_Cmd *cmd;
- const char *cp;
- int e;
-
- cmd_ctx = current_command_context(goi->interp);
- assert(cmd_ctx);
-
- if (goi->argc < 3) {
- Jim_WrongNumArgs(goi->interp, 1, goi->argv, "?name? ..options...");
- return JIM_ERR;
- }
- /* COMMAND */
- jim_getopt_obj(goi, &new_cmd);
- /* does this command exist? */
- cmd = Jim_GetCommand(goi->interp, new_cmd, JIM_NONE);
- if (cmd) {
- cp = Jim_GetString(new_cmd, NULL);
- Jim_SetResultFormatted(goi->interp, "Command: %s Exists", cp);
- return JIM_ERR;
+ if (CMD_ARGC < 3)
+ return ERROR_COMMAND_SYNTAX_ERROR;
+
+ /* check if the cti name clashes with an existing command name */
+ Jim_Cmd *jimcmd = Jim_GetCommand(CMD_CTX->interp, CMD_JIMTCL_ARGV[0], JIM_NONE);
+ if (jimcmd) {
+ command_print(CMD, "Command/cti: %s Exists", CMD_ARGV[0]);
+ return ERROR_FAIL;
}
/* Create it */
- cti = calloc(1, sizeof(*cti));
- if (!cti)
- return JIM_ERR;
+ struct arm_cti *cti = calloc(1, sizeof(*cti));
+ if (!cti) {
+ LOG_ERROR("Out of memory");
+ return ERROR_FAIL;
+ }
adiv5_mem_ap_spot_init(&cti->spot);
/* Do the rest as "configure" options */
- goi->is_configure = true;
- e = cti_configure(goi, cti);
+ struct jim_getopt_info goi;
+ jim_getopt_setup(&goi, CMD_CTX->interp, CMD_ARGC - 1, CMD_JIMTCL_ARGV + 1);
+ goi.is_configure = 1;
+ int e = cti_configure(&goi, cti);
if (e != JIM_OK) {
+ int reslen;
+ const char *result = Jim_GetString(Jim_GetResult(CMD_CTX->interp), &reslen);
+ if (reslen > 0)
+ command_print(CMD, "%s", result);
free(cti);
- return e;
+ return ERROR_COMMAND_ARGUMENT_INVALID;
}
- cp = Jim_GetString(new_cmd, NULL);
- cti->name = strdup(cp);
+ cti->name = strdup(CMD_ARGV[0]);
+ if (!cti->name) {
+ LOG_ERROR("Out of memory");
+ free(cti);
+ return ERROR_FAIL;
+ }
/* now - create the new cti name command */
const struct command_registration cti_subcommands[] = {
@@ -487,7 +485,7 @@ static int cti_create(struct jim_getopt_info *goi)
};
const struct command_registration cti_commands[] = {
{
- .name = cp,
+ .name = CMD_ARGV[0],
.mode = COMMAND_ANY,
.help = "cti instance command group",
.usage = "",
@@ -495,31 +493,24 @@ static int cti_create(struct jim_getopt_info *goi)
},
COMMAND_REGISTRATION_DONE
};
- e = register_commands_with_data(cmd_ctx, NULL, cti_commands, cti);
- if (e != ERROR_OK)
- return JIM_ERR;
+ int retval = register_commands_with_data(CMD_CTX, NULL, cti_commands, cti);
+ if (retval != ERROR_OK) {
+ free(cti->name);
+ free(cti);
+ return retval;
+ }
list_add_tail(&cti->lh, &all_cti);
cti->ap = dap_get_ap(cti->spot.dap, cti->spot.ap_num);
if (!cti->ap) {
- Jim_SetResultString(goi->interp, "Cannot get AP", -1);
- return JIM_ERR;
+ command_print(CMD, "Cannot get AP");
+ free(cti->name);
+ free(cti);
+ return ERROR_FAIL;
}
- return JIM_OK;
-}
-
-static int jim_cti_create(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
-{
- struct jim_getopt_info goi;
- jim_getopt_setup(&goi, interp, argc - 1, argv + 1);
- if (goi.argc < 2) {
- Jim_WrongNumArgs(goi.interp, goi.argc, goi.argv,
- "